Optimized utf8 decoding
git-svn-id: http://pugixml.googlecode.com/svn/trunk@447 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
1046fe1f7b
commit
6e2521830f
@ -796,9 +796,7 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
const char8_t utf8_byte_mask = 0x3f;
|
const char8_t utf8_byte_mask = 0x3f;
|
||||||
|
|
||||||
const char8_t* end = data + size;
|
while (size)
|
||||||
|
|
||||||
while (data < end)
|
|
||||||
{
|
{
|
||||||
char8_t lead = *data;
|
char8_t lead = *data;
|
||||||
|
|
||||||
@ -807,29 +805,48 @@ namespace pugi
|
|||||||
{
|
{
|
||||||
result = Traits::low(result, lead);
|
result = Traits::low(result, lead);
|
||||||
data += 1;
|
data += 1;
|
||||||
|
size -= 1;
|
||||||
|
|
||||||
|
// process aligned single-byte (ascii) blocks
|
||||||
|
if ((reinterpret_cast<uintptr_t>(data) & 3) == 0)
|
||||||
|
{
|
||||||
|
while (size >= 4 && (*reinterpret_cast<const char32_t*>(data) & 0x80808080) == 0)
|
||||||
|
{
|
||||||
|
result = Traits::low(result, data[0]);
|
||||||
|
result = Traits::low(result, data[1]);
|
||||||
|
result = Traits::low(result, data[2]);
|
||||||
|
result = Traits::low(result, data[3]);
|
||||||
|
data += 4;
|
||||||
|
size -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 110xxxxx -> U+0080..U+07FF
|
// 110xxxxx -> U+0080..U+07FF
|
||||||
else if ((unsigned)(lead - 0xC0) < 0x20 && (end - data) > 1 && (data[1] & 0xc0) == 0x80)
|
else if ((unsigned)(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
|
||||||
{
|
{
|
||||||
result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
|
result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
|
||||||
data += 2;
|
data += 2;
|
||||||
|
size -= 2;
|
||||||
}
|
}
|
||||||
// 1110xxxx -> U+0800-U+FFFF
|
// 1110xxxx -> U+0800-U+FFFF
|
||||||
else if ((unsigned)(lead - 0xE0) < 0x10 && (end - data) > 2 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
|
else if ((unsigned)(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
|
||||||
{
|
{
|
||||||
result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
|
result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
|
||||||
data += 3;
|
data += 3;
|
||||||
|
size -= 3;
|
||||||
}
|
}
|
||||||
// 11110xxx -> U+10000..U+10FFFF
|
// 11110xxx -> U+10000..U+10FFFF
|
||||||
else if ((unsigned)(lead - 0xF0) < 0x08 && (end - data) > 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
|
else if ((unsigned)(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
|
||||||
{
|
{
|
||||||
result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
|
result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
|
||||||
data += 4;
|
data += 4;
|
||||||
|
size -= 4;
|
||||||
}
|
}
|
||||||
// 10xxxxxx or 11111xxx -> invalid
|
// 10xxxxxx or 11111xxx -> invalid
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data += 1;
|
data += 1;
|
||||||
|
size -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user