mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-26 18:42:41 +01:00
trunk/branch integration: TextEncoding update
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user