Add Encoding.encode() and Encoding.decode().
This commit is contained in:
parent
575589e5a3
commit
926ad3ec0d
@ -18,6 +18,162 @@ struct Encoding
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
uint decode(const(ubyte) * data, size_t * encoded_size)
|
||||
{
|
||||
uint result;
|
||||
size_t size;
|
||||
ubyte following_bytes;
|
||||
ubyte c;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case UTF8:
|
||||
c = *data;
|
||||
if ((c & 0x80u) == 0u)
|
||||
{
|
||||
result = c;
|
||||
size = 1u;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((c & 0xE0u) == 0xC0u)
|
||||
{
|
||||
result = c & 0x1Fu;
|
||||
following_bytes = 1u;
|
||||
}
|
||||
else if ((c & 0xF0u) == 0xE0u)
|
||||
{
|
||||
result = c & 0x0Fu;
|
||||
following_bytes = 2u;
|
||||
}
|
||||
else if ((c & 0xF8u) == 0xF0u)
|
||||
{
|
||||
result = c & 0x07u;
|
||||
following_bytes = 3u;
|
||||
}
|
||||
else if ((c & 0xFCu) == 0xF8u)
|
||||
{
|
||||
result = c & 0x03u;
|
||||
following_bytes = 4u;
|
||||
}
|
||||
else if ((c & 0xFEu) == 0xFCu)
|
||||
{
|
||||
result = c & 0x01u;
|
||||
following_bytes = 5u;
|
||||
}
|
||||
size = following_bytes + 1u;
|
||||
while (following_bytes-- > 0u)
|
||||
{
|
||||
data++;
|
||||
result <<= 6u;
|
||||
result |= *data & 0x3Fu;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CP1252:
|
||||
/* TODO */
|
||||
break;
|
||||
case UTF16_LE:
|
||||
result = data[0] | (data[1] << 8u);
|
||||
size = 2u;
|
||||
break;
|
||||
case UTF16_BE:
|
||||
result = (data[0] << 8u) | data[1];
|
||||
size = 2u;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (encoded_size != null)
|
||||
{
|
||||
*encoded_size = size;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ubyte num_bytes_to_encode_code_point(uint code_point)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case UTF8:
|
||||
if (code_point <= 0x7Fu)
|
||||
{
|
||||
return 1u;
|
||||
}
|
||||
else if (code_point <= 0x7FFu)
|
||||
{
|
||||
return 2u;
|
||||
}
|
||||
else if (code_point <= 0xFFFFu)
|
||||
{
|
||||
return 3u;
|
||||
}
|
||||
else if (code_point <= 0x1FFFFFu)
|
||||
{
|
||||
return 4u;
|
||||
}
|
||||
else if (code_point <= 0x3FFFFFFu)
|
||||
{
|
||||
return 5u;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 6u;
|
||||
}
|
||||
case CP1252:
|
||||
/* TODO */
|
||||
break;
|
||||
case UTF16_LE:
|
||||
case UTF16_BE:
|
||||
return 2u;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
ubyte encode(uint code_point, ubyte * buffer)
|
||||
{
|
||||
ubyte size;
|
||||
switch (type)
|
||||
{
|
||||
case UTF8:
|
||||
size = num_bytes_to_encode_code_point(code_point);
|
||||
if (size == 1u)
|
||||
{
|
||||
*buffer = cast(ubyte)code_point;
|
||||
}
|
||||
else if (size > 1u)
|
||||
{
|
||||
*buffer = cast(ubyte)((0xFFu << (8u - size)) | (code_point >> (6u * (size - 1u))));
|
||||
const ubyte end = cast(ubyte)(size - 1u);
|
||||
for (ubyte i = 0u; i < end; i++)
|
||||
{
|
||||
buffer[end - i] = 0x80u | (code_point >> (6u * i) & 0x3Fu);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
case CP1252:
|
||||
/* TODO */
|
||||
break;
|
||||
case UTF16_LE:
|
||||
buffer[0] = cast(ubyte)code_point;
|
||||
buffer[1] = cast(ubyte)(code_point >> 8u);
|
||||
return 2u;
|
||||
case UTF16_BE:
|
||||
buffer[0] = cast(ubyte)(code_point >> 8u);
|
||||
buffer[1] = cast(ubyte)code_point;
|
||||
return 2u;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
static Encoding detect_encoding(const ubyte * data, size_t n, size_t * bom_size)
|
||||
{
|
||||
*bom_size = 0u;
|
||||
|
Loading…
x
Reference in New Issue
Block a user