trunk/branch integration: TextEncoding update

This commit is contained in:
Marian Krivos
2011-08-22 18:22:56 +00:00
parent d35ecf85a2
commit e066d033a2
8 changed files with 391 additions and 80 deletions

View File

@@ -103,37 +103,6 @@ const TextEncoding::CharacterMap& UTF8Encoding::characterMap() const
}
bool UTF8Encoding::isLegal(const unsigned char *bytes, int length)
{
if (0 == bytes || 0 == length) return false;
unsigned char a;
const unsigned char* srcptr = bytes + length;
switch (length)
{
default: return false;
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
switch (*bytes)
{
case 0xE0: if (a < 0xA0) return false; break;
case 0xED: if (a > 0x9F) return false; break;
case 0xF0: if (a < 0x90) return false; break;
case 0xF4: if (a > 0x8F) return false; break;
default: if (a < 0x80) return false;
}
case 1: if (*bytes >= 0x80 && *bytes < 0xC2) return false;
}
if (*bytes > 0xF4) return false;
return true;
}
int UTF8Encoding::convert(const unsigned char* bytes) const
{
int n = _charMap[*bytes];
@@ -141,13 +110,18 @@ int UTF8Encoding::convert(const unsigned char* bytes) const
switch (n)
{
case -6: case -5: case -1: return -1;
case -4: case -3: case -2:
if (!isLegal(bytes, -n)) return -1;
uc = *bytes & ((0x07 << (n + 4)) | 0x03); break;
default: return n;
case -6:
case -5:
case -1:
return -1;
case -4:
case -3:
case -2:
if (!isLegal(bytes, -n)) return -1;
uc = *bytes & ((0x07 << (n + 4)) | 0x03);
break;
default:
return n;
}
while (n++ < -1)
@@ -161,10 +135,6 @@ int UTF8Encoding::convert(const unsigned char* bytes) const
int UTF8Encoding::convert(int ch, unsigned char* bytes, int length) const
{
#ifdef _DEBUG
unsigned char* lb = bytes;
#endif
if (ch <= 0x7F)
{
if (bytes && length >= 1)
@@ -175,37 +145,128 @@ int UTF8Encoding::convert(int ch, unsigned char* bytes, int length) const
{
if (bytes && length >= 2)
{
*bytes++ = (unsigned char) ((ch >> 6) & 0x1F | 0xC0);
*bytes++ = (unsigned char) (((ch >> 6) & 0x1F) | 0xC0);
*bytes = (unsigned char) ((ch & 0x3F) | 0x80);
}
poco_assert_dbg (isLegal(lb, 2));
return 2;
}
else if (ch <= 0xFFFF)
{
if (bytes && length >= 3)
{
*bytes++ = (unsigned char) ((ch >> 12) & 0x0F | 0xE0);
*bytes++ = (unsigned char) ((ch >> 6) & 0x3F | 0x80);
*bytes++ = (unsigned char) (((ch >> 12) & 0x0F) | 0xE0);
*bytes++ = (unsigned char) (((ch >> 6) & 0x3F) | 0x80);
*bytes = (unsigned char) ((ch & 0x3F) | 0x80);
}
poco_assert_dbg (isLegal(lb, 3));
return 3;
}
else if (ch <= 0x10FFFF)
{
if (bytes && length >= 4)
{
*bytes++ = (unsigned char) ((ch >> 18) & 0x07 | 0xF0);
*bytes++ = (unsigned char) ((ch >> 12) & 0x3F | 0x80);
*bytes++ = (unsigned char) ((ch >> 6) & 0x3F | 0x80);
*bytes++ = (unsigned char) (((ch >> 18) & 0x07) | 0xF0);
*bytes++ = (unsigned char) (((ch >> 12) & 0x3F) | 0x80);
*bytes++ = (unsigned char) (((ch >> 6) & 0x3F) | 0x80);
*bytes = (unsigned char) ((ch & 0x3F) | 0x80);
}
poco_assert_dbg (isLegal(lb, 4));
return 4;
}
else return 0;
}
int UTF8Encoding::queryConvert(const unsigned char* bytes, int length) const
{
int n = _charMap[*bytes];
int uc;
if (-n > length)
{
return n;
}
else
{
switch (n)
{
case -6:
case -5:
case -1:
return -1;
case -4:
case -3:
case -2:
if (!isLegal(bytes, -n)) return -1;
uc = *bytes & ((0x07 << (n + 4)) | 0x03);
break;
default:
return n;
}
while (n++ < -1)
{
uc <<= 6;
uc |= (*++bytes & 0x3F);
}
return uc;
}
}
int UTF8Encoding::sequenceLength(const unsigned char* bytes, int length) const
{
if (1 <= length)
{
int cc = _charMap[*bytes];
if (cc >= 0)
return 1;
else
return -cc;
}
else return -1;
}
bool UTF8Encoding::isLegal(const unsigned char *bytes, int length)
{
// Note: The following is loosely based on the isLegalUTF8 function
// from ftp://ftp.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
// Excuse the ugliness...
if (0 == bytes || 0 == length) return false;
unsigned char a;
const unsigned char* srcptr = bytes + length;
switch (length)
{
default:
return false;
// Everything else falls through when true.
case 4:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2:
if ((a = (*--srcptr)) > 0xBF) return false;
switch (*bytes)
{
case 0xE0:
if (a < 0xA0) return false;
break;
case 0xED:
if (a > 0x9F) return false;
break;
case 0xF0:
if (a < 0x90) return false;
break;
case 0xF4:
if (a > 0x8F) return false;
break;
default:
if (a < 0x80) return false;
}
case 1:
if (*bytes >= 0x80 && *bytes < 0xC2) return false;
}
return *bytes <= 0xF4;
}
} // namespace Poco