#include <sys/param.h>
#include <sys/utfconv.h>
#include "../../hfs_macos_defs.h"
#include "UCStringCompareData.h"
#include "../headers/FileMgrInternal.h"
#include "../headers/HFSUnicodeWrappers.h"
enum {
kMinFileExtensionChars = 1,
kMaxFileExtensionChars = 5
};
#define EXTENSIONCHAR(c) (((c) >= 0x61 && (c) <= 0x7A) || \
((c) >= 0x41 && (c) <= 0x5A) || \
((c) >= 0x30 && (c) <= 0x39))
#define IsHexDigit(c) (((c) >= (UInt8) '0' && (c) <= (UInt8) '9') || \
((c) >= (UInt8) 'A' && (c) <= (UInt8) 'F'))
static void GetFilenameExtension( ItemCount length, ConstUniCharArrayPtr unicodeStr, char* extStr );
static void GetFileIDString( HFSCatalogNodeID fileID, char* fileIDStr );
static UInt32 HexStringToInteger( UInt32 length, const UInt8 *hexStr );
static void
GetFileIDString( HFSCatalogNodeID fileID, char * fileIDStr )
{
SInt32 i, b;
UInt8 *translate = (UInt8 *) "0123456789ABCDEF";
UInt8 c;
fileIDStr[0] = '#';
for ( i = 0, b = 28; b >= 0; b -= 4 ) {
c = *(translate + ((fileID >> b) & 0x0000000F));
if ( (c != (UInt8) '0') || (i > 1) || (b == 0) )
fileIDStr[++i] = c;
}
fileIDStr[++i] = '\0';
}
static void
GetFilenameExtension(ItemCount length, ConstUniCharArrayPtr unicodeStr, char * extStr)
{
UInt32 i;
UniChar c;
UInt16 extChars;
UInt16 maxExtChars;
Boolean foundExtension;
extStr[0] = '\0';
if ( length < 3 )
return;
if ( length < (kMaxFileExtensionChars + 2) )
maxExtChars = length - 2;
else
maxExtChars = kMaxFileExtensionChars;
i = length;
extChars = 0;
foundExtension = false;
while ( extChars <= maxExtChars ) {
c = unicodeStr[--i];
if ( c == (UniChar) '.' ) {
if ( extChars > 0 )
foundExtension = true;
break;
}
if ( EXTENSIONCHAR(c) )
++extChars;
else
break;
}
if ( foundExtension ) {
UInt8 *extStrPtr = extStr;
const UniChar *unicodeStrPtr = &unicodeStr[i];
for ( i = 0; i <= extChars; ++i )
*(extStrPtr++) = (UInt8) *(unicodeStrPtr++);
extStr[extChars + 1] = '\0';
}
}
static UInt32
CountFilenameExtensionChars( const unsigned char * filename, UInt32 length )
{
UInt32 i;
UniChar c;
UInt32 extChars;
UInt16 maxExtChars;
Boolean foundExtension;
if (length == kUndefinedStrLen)
length = strlen(filename);
if ( length < 3 )
return 0;
if ( length < (kMaxFileExtensionChars + 2) )
maxExtChars = length - 2;
else
maxExtChars = kMaxFileExtensionChars;
extChars = 0;
i = length - 1;
foundExtension = false;
while ( extChars <= maxExtChars ) {
c = filename[i--];
if ( c == (UInt8) '.' ) {
if ( extChars > 0 )
return (extChars);
break;
}
if ( EXTENSIONCHAR(c) )
++extChars;
else
break;
}
return 0;
}
HFSCatalogNodeID
GetEmbeddedFileID(const unsigned char * filename, UInt32 length, UInt32 *prefixLength)
{
short extChars;
short i;
UInt8 c;
*prefixLength = 0;
if ( filename == NULL )
return 0;
if (length == kUndefinedStrLen)
length = strlen(filename);
if ( length < 28 )
return 0;
if ( length > 5 )
extChars = CountFilenameExtensionChars(filename, length);
else
extChars = 0;
if ( extChars > 0 )
length -= (extChars + 1);
for ( i = length - 1; i >= 0; --i) {
c = filename[i];
if ( c == '#' ) {
if ( (length - i) < 3 )
break;
*prefixLength = i;
return HexStringToInteger(length - i - 1, &filename[i+1]);
}
if ( !IsHexDigit(c) )
break;
}
return 0;
}
static UInt32
HexStringToInteger(UInt32 length, const UInt8 *hexStr)
{
UInt32 value;
short i;
UInt8 c;
const UInt8 *p;
value = 0;
p = hexStr;
for ( i = 0; i < length; ++i ) {
c = *p++;
if (c >= '0' && c <= '9') {
value = value << 4;
value += (UInt32) c - (UInt32) '0';
} else if (c >= 'A' && c <= 'F') {
value = value << 4;
value += 10 + ((unsigned int) c - (unsigned int) 'A');
} else {
return 0;
}
}
return value;
}
extern unsigned short gCompareTable[];
SInt32 FastRelString( ConstStr255Param str1, ConstStr255Param str2 )
{
UInt16* compareTable;
SInt32 bestGuess;
UInt8 length, length2;
UInt8 delta;
delta = 0;
length = *(str1++);
length2 = *(str2++);
if (length == length2)
bestGuess = 0;
else if (length < length2)
{
bestGuess = -1;
delta = length2 - length;
}
else
{
bestGuess = 1;
length = length2;
}
compareTable = (UInt16*) gCompareTable;
while (length--)
{
UInt8 aChar, bChar;
aChar = *(str1++);
bChar = *(str2++);
if (aChar != bChar) {
UInt16 aSortWord, bSortWord;
aSortWord = compareTable[aChar];
bSortWord = compareTable[bChar];
if (aSortWord > bSortWord)
return 1;
if (aSortWord < bSortWord)
return -1;
}
}
return bestGuess;
}
extern UInt16 gLowerCaseTable[];
extern UInt16 gLatinCaseFold[];
SInt32 FastUnicodeCompare ( register ConstUniCharArrayPtr str1, register ItemCount length1,
register ConstUniCharArrayPtr str2, register ItemCount length2)
{
register UInt16 c1,c2;
register UInt16 temp;
register UInt16* lowerCaseTable;
lowerCaseTable = (UInt16*) gLowerCaseTable;
while (1) {
c1 = 0;
c2 = 0;
while (length1 && c1 == 0) {
c1 = *(str1++);
--length1;
if (c1 < 0x0100) {
c1 = gLatinCaseFold[c1];
break;
}
if ((temp = lowerCaseTable[c1>>8]) != 0)
c1 = lowerCaseTable[temp + (c1 & 0x00FF)];
}
while (length2 && c2 == 0) {
c2 = *(str2++);
--length2;
if (c2 < 0x0100) {
c2 = gLatinCaseFold[c2];
break;
}
if ((temp = lowerCaseTable[c2>>8]) != 0)
c2 = lowerCaseTable[temp + (c2 & 0x00FF)];
}
if (c1 != c2) break;
if (c1 == 0) return 0; }
if (c1 < c2)
return -1;
else
return 1;
}
OSErr
ConvertUnicodeToUTF8Mangled(ByteCount srcLen, ConstUniCharArrayPtr srcStr, ByteCount maxDstLen,
ByteCount *actualDstLen, unsigned char* dstStr, HFSCatalogNodeID cnid)
{
ByteCount subMaxLen;
size_t utf8len;
char fileIDStr[15];
char extStr[15];
GetFileIDString(cnid, fileIDStr);
GetFilenameExtension(srcLen/sizeof(UniChar), srcStr, extStr);
srcLen -= strlen(extStr) * sizeof(UniChar);
subMaxLen = maxDstLen - (strlen(extStr) + strlen(fileIDStr));
(void) utf8_encodestr(srcStr, srcLen, dstStr, &utf8len, subMaxLen, ':', 0);
strcat(dstStr, fileIDStr);
strcat(dstStr, extStr);
*actualDstLen = utf8len + (strlen(extStr) + strlen(fileIDStr));
return noErr;
}