#if HFS
#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) >= (u_int8_t) '0' && (c) <= (u_int8_t) '9') || \
((c) >= (u_int8_t) 'A' && (c) <= (u_int8_t) 'F'))
static void GetFilenameExtension( ItemCount length, ConstUniCharArrayPtr unicodeStr, char* extStr );
static u_int32_t HexStringToInteger( u_int32_t length, const u_int8_t *hexStr );
static void
GetFilenameExtension(ItemCount length, ConstUniCharArrayPtr unicodeStr, char * extStr)
{
u_int32_t i;
UniChar c;
u_int16_t extChars;
u_int16_t 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 ) {
u_int8_t *extStrPtr = (u_int8_t *)extStr;
const UniChar *unicodeStrPtr = &unicodeStr[i];
for ( i = 0; i <= extChars; ++i )
*(extStrPtr++) = (u_int8_t) *(unicodeStrPtr++);
extStr[extChars + 1] = '\0';
}
}
__private_extern__ u_int32_t
CountFilenameExtensionChars( const unsigned char * filename, u_int32_t length )
{
u_int32_t i;
UniChar c;
u_int32_t extChars;
u_int16_t maxExtChars;
Boolean foundExtension;
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 == (u_int8_t) '.' ) {
if ( extChars > 0 )
return (extChars);
break;
}
if ( EXTENSIONCHAR(c) )
++extChars;
else
break;
}
return 0;
}
HFSCatalogNodeID
GetEmbeddedFileID(const unsigned char * filename, u_int32_t length, u_int32_t *prefixLength)
{
short extChars;
short i;
u_int8_t c;
*prefixLength = 0;
if ( filename == NULL )
return 0;
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 u_int32_t
HexStringToInteger(u_int32_t length, const u_int8_t *hexStr)
{
u_int32_t value;
u_int32_t i;
u_int8_t c;
const u_int8_t *p;
value = 0;
p = hexStr;
for ( i = 0; i < length; ++i ) {
c = *p++;
if (c >= '0' && c <= '9') {
value = value << 4;
value += (u_int32_t) c - (u_int32_t) '0';
} else if (c >= 'A' && c <= 'F') {
value = value << 4;
value += 10 + ((unsigned int) c - (unsigned int) 'A');
} else {
return 0;
}
}
return value;
}
int32_t FastRelString( ConstStr255Param str1, ConstStr255Param str2 )
{
u_int16_t* compareTable;
int32_t bestGuess;
u_int8_t length, length2;
u_int8_t 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 = (u_int16_t*) gCompareTable;
while (length--)
{
u_int8_t aChar, bChar;
aChar = *(str1++);
bChar = *(str2++);
if (aChar != bChar) {
u_int16_t aSortWord, bSortWord;
aSortWord = compareTable[aChar];
bSortWord = compareTable[bChar];
if (aSortWord > bSortWord)
return 1;
if (aSortWord < bSortWord)
return -1;
}
}
return bestGuess;
}
int32_t FastUnicodeCompare ( register ConstUniCharArrayPtr str1, register ItemCount length1,
register ConstUniCharArrayPtr str2, register ItemCount length2)
{
register u_int16_t c1,c2;
register u_int16_t temp;
register u_int16_t* lowerCaseTable;
lowerCaseTable = (u_int16_t*) 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];
snprintf(fileIDStr, sizeof(fileIDStr), "#%X", cnid);
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);
strlcat((char *)dstStr, fileIDStr, maxDstLen);
strlcat((char *)dstStr, extStr, maxDstLen);
*actualDstLen = utf8len + (strlen(extStr) + strlen(fileIDStr));
return noErr;
}
#else
#include <sys/types.h>
int32_t FastUnicodeCompare( void * str1, u_int32_t length1, void * str2, u_int32_t length2 );
int32_t FastUnicodeCompare( __unused void * str1,
__unused u_int32_t length1,
__unused void * str2,
__unused u_int32_t length2 )
{
return( 0 );
}
#endif