lf_hfs_unicode_wrappers.c [plain text]
#include "lf_hfs_unicode_wrappers.h"
#include "lf_hfs_ucs_string_cmp_data.h"
#include "lf_hfs_sbunicode.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_int64_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';
}
}
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;
}
int32_t UnicodeBinaryCompare (register ConstUniCharArrayPtr str1, register ItemCount len1,
register ConstUniCharArrayPtr str2, register ItemCount len2) {
uint16_t c1 =0;
uint16_t c2 =0;
ItemCount string_length;
int32_t result = 0;
if (len1 < len2) {
string_length = len1;
--result;
}
else if (len1 > len2) {
string_length = len2;
++result;
}
else {
string_length = len1;
}
while (string_length--) {
c1 = *(str1++);
c2 = *(str2++);
if (c1 > c2) {
result = 1;
break;
}
if (c1 < c2) {
result = -1;
break;
}
}
return result;
}
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;
}
u_int32_t
CountFilenameExtensionChars( const unsigned char * filename, u_int32_t length )
{
UniChar c;
u_int16_t maxExtChars;
if ( length < 3 )
return 0;
if ( length < (kMaxFileExtensionChars + 2) )
maxExtChars = length - 2;
else
maxExtChars = kMaxFileExtensionChars;
u_int32_t extChars = 0;
u_int32_t i = length - 1;
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;
}
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;
}
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, ':', UTF_ADD_NULL_TERM);
strlcat((char *)dstStr, fileIDStr, maxDstLen);
strlcat((char *)dstStr, extStr, maxDstLen);
*actualDstLen = utf8len + (strlen(extStr) + strlen(fileIDStr));
return noErr;
}