mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
add unicode decode
This commit is contained in:
parent
6ecf505f48
commit
8359289283
@ -1,9 +1,10 @@
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionStringToString.h>
|
||||
#include <Common/StringUtils/StringUtils.h>
|
||||
#include <common/find_symbols.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
@ -54,8 +55,8 @@ namespace
|
||||
}
|
||||
|
||||
private:
|
||||
static const int min_XML_number = 32;
|
||||
static const int max_XML_number = 126;
|
||||
static const int max_legal_unicode_value = 0x10FFFF;
|
||||
static const int max_legal_unicode_bits = 7;
|
||||
static size_t execute(const char * src, size_t src_size, char * dst)
|
||||
{
|
||||
const char * src_prev_pos = src;
|
||||
@ -80,6 +81,32 @@ namespace
|
||||
src_curr_pos = src_end;
|
||||
break;
|
||||
}
|
||||
else if (isValidNumeric(src_curr_pos, src_next_pos))
|
||||
{
|
||||
std::vector<char> decodeNumericChars;
|
||||
decodeNumericPart(src_curr_pos + 2, src_next_pos, decodeNumericChars);
|
||||
if (decodeNumericChars.empty())
|
||||
{
|
||||
++src_curr_pos;
|
||||
size_t bytes_to_copy = src_curr_pos - src_prev_pos;
|
||||
memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
|
||||
dst_pos += bytes_to_copy;
|
||||
src_prev_pos = src_curr_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_to_copy = src_curr_pos - src_prev_pos;
|
||||
memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
|
||||
dst_pos += bytes_to_copy;
|
||||
for (size_t i = 0; i < decodeNumericChars.size(); i++)
|
||||
{
|
||||
*dst_pos = decodeNumericChars[i];
|
||||
++dst_pos;
|
||||
}
|
||||
src_prev_pos = src_next_pos + 1;
|
||||
}
|
||||
src_curr_pos = src_next_pos + 1;
|
||||
}
|
||||
else if (src_next_pos - src_curr_pos == 3)
|
||||
{
|
||||
if (strncmp(src_curr_pos, "<", 3) == 0)
|
||||
@ -122,26 +149,6 @@ namespace
|
||||
++dst_pos;
|
||||
src_prev_pos = src_curr_pos + 5;
|
||||
}
|
||||
else if (*(src_curr_pos + 1) == '#' && isdigit(*(src_curr_pos + 2)) && isdigit(*(src_curr_pos + 3)))
|
||||
{
|
||||
char numeric_character = decodeNumberPart(src_curr_pos + 2);
|
||||
if (numeric_character == '\0')
|
||||
{
|
||||
size_t bytes_to_copy = src_next_pos - src_prev_pos;
|
||||
memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
|
||||
dst_pos += bytes_to_copy;
|
||||
src_prev_pos = src_curr_pos + 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_to_copy = src_curr_pos - src_prev_pos;
|
||||
memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
|
||||
dst_pos += bytes_to_copy;
|
||||
*dst_pos = '\0' + numeric_character;
|
||||
++dst_pos;
|
||||
src_prev_pos = src_curr_pos + 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++src_curr_pos;
|
||||
@ -173,28 +180,6 @@ namespace
|
||||
++dst_pos;
|
||||
src_prev_pos = src_curr_pos + 6;
|
||||
}
|
||||
else if (
|
||||
*(src_curr_pos + 1) == '#' && isdigit(*(src_curr_pos + 2)) && isdigit(*(src_curr_pos + 3))
|
||||
&& isdigit(*(src_curr_pos + 4)))
|
||||
{
|
||||
char numeric_character = decodeNumberPart(src_curr_pos + 2);
|
||||
if (numeric_character == '\0')
|
||||
{
|
||||
size_t bytes_to_copy = src_next_pos - src_prev_pos;
|
||||
memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
|
||||
dst_pos += bytes_to_copy;
|
||||
src_prev_pos = src_curr_pos + 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_to_copy = src_curr_pos - src_prev_pos;
|
||||
memcpySmallAllowReadWriteOverflow15(dst_pos, src_prev_pos, bytes_to_copy);
|
||||
dst_pos += bytes_to_copy;
|
||||
*dst_pos = '\0' + numeric_character;
|
||||
++dst_pos;
|
||||
src_prev_pos = src_curr_pos + 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++src_curr_pos;
|
||||
@ -227,14 +212,118 @@ namespace
|
||||
return dst_pos - dst;
|
||||
}
|
||||
|
||||
static inline char decodeNumberPart(const char * src)
|
||||
static void decodeNumericPart(const char * src, const char * end, std::vector<char> & decodeNumericChars)
|
||||
{
|
||||
auto numberic_ans = strtol(src, nullptr, 10);
|
||||
if (numberic_ans >= min_XML_number && numberic_ans <= max_XML_number)
|
||||
int numeric_ans;
|
||||
if (*src == 'x' || *src == 'X')
|
||||
{
|
||||
return '\0' + numberic_ans;
|
||||
numeric_ans = hexOrDecStrToInt(src + 1, end, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
numeric_ans = hexOrDecStrToInt(src, end, 10);
|
||||
}
|
||||
const auto num_bits = numBitsCount(numeric_ans);
|
||||
if (num_bits <= 7)
|
||||
{
|
||||
decodeNumericChars.push_back('\0' + (numeric_ans & 0x7F));
|
||||
}
|
||||
else if (num_bits <= 11)
|
||||
{
|
||||
decodeNumericChars.push_back('\0' + ((numeric_ans >> 6) & 0x1F) + 0xC0);
|
||||
decodeNumericChars.push_back('\0' + (numeric_ans & 0x3F) + 0x80);
|
||||
}
|
||||
else if (num_bits <= 16)
|
||||
{
|
||||
decodeNumericChars.push_back('\0' + ((numeric_ans >> 12) & 0x0F) + 0xE0);
|
||||
decodeNumericChars.push_back('\0' + ((numeric_ans >> 6) & 0x3F) + 0x80);
|
||||
decodeNumericChars.push_back('\0' + (numeric_ans & 0x3F) + 0x80);
|
||||
}
|
||||
else if ((num_bits <= 21) && (numeric_ans <= max_legal_unicode_value))
|
||||
{
|
||||
decodeNumericChars.push_back('\0' + ((numeric_ans >> 18) & 0x07) + 0xF0);
|
||||
decodeNumericChars.push_back('\0' + ((numeric_ans >> 12) & 0x3F) + 0x80);
|
||||
decodeNumericChars.push_back('\0' + ((numeric_ans >> 6) & 0x3F) + 0x80);
|
||||
decodeNumericChars.push_back('\0' + (numeric_ans & 0x3F) + 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
static int hexOrDecStrToInt(const char * src, const char * end, int base)
|
||||
{
|
||||
int numeric_ans = 0;
|
||||
int pos = 0;
|
||||
if (base == 16)
|
||||
{
|
||||
while (src + pos != end)
|
||||
{
|
||||
if (isNumericASCII(*(src + pos)))
|
||||
{
|
||||
numeric_ans = numeric_ans * base + (*(src + pos) - '0');
|
||||
}
|
||||
else if (*(src + pos) >= 'a' && *(src + pos) <= 'f')
|
||||
{
|
||||
numeric_ans = numeric_ans * base + (*(src + pos) - 'a' + 10);
|
||||
}
|
||||
else if (*(src + pos) >= 'A' && *(src + pos) <= 'F')
|
||||
{
|
||||
numeric_ans = numeric_ans * base + (*(src + pos) - 'A' + 10);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (src + pos != end)
|
||||
{
|
||||
numeric_ans = numeric_ans * base + (*(src + pos) - '0');
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
return numeric_ans;
|
||||
}
|
||||
static int numBitsCount(int integer)
|
||||
{
|
||||
size_t num_bits = 0;
|
||||
while (integer > 0)
|
||||
{
|
||||
++num_bits;
|
||||
integer >>= 1;
|
||||
}
|
||||
return num_bits;
|
||||
}
|
||||
static bool isValidNumeric(const char * src, const char * end)
|
||||
{
|
||||
int pos;
|
||||
if (*src != '&' || *(src + 1) != '#' || (end - (src + 2) > max_legal_unicode_bits))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*(src + 2) == 'x' || *(src + 2) == 'X')
|
||||
{
|
||||
pos = 3;
|
||||
while (src + pos != end)
|
||||
{
|
||||
if (!isHexDigit(*(src + pos)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = 2;
|
||||
while (src + pos != end)
|
||||
{
|
||||
if (!isNumericASCII(*(src + pos)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8,17 +8,10 @@ Hello, &a;& world
|
||||
Hello, <t;& world
|
||||
Hello, <t& world
|
||||
Hello, &t;& world
|
||||
�	

|
||||

|
||||
 !"#$%&\'()*+,-./012
|
||||
!"#$%&\'()*+,-./012
|
||||
)*+,-./0123456789:;<
|
||||
=>?@ABCDEFGHIJKLMNOP
|
||||
QRSTUVWXYZ[\\]^_`abcd
|
||||
efghijklmnopqrstuvwx
|
||||
yz{|}~€‚ƒ„…†‡ˆ‰Š‹Œ
|
||||
Ž‘’“”•–—˜™š›œžŸ 
|
||||
¡¢£¤¥¦§¨©ª«¬­®¯°±²³´
|
||||
µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈ
|
||||
ÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜ
|
||||
ÝÞßàáâãäåæçèéêëìíîïð
|
||||
ñòóôõö÷øùúûüýþÿĀ
|
||||
为什么
|
||||
为什么
|
||||
�\'123
|
||||
ЦЦЮЮЫㄱ
|
||||
|
@ -10,17 +10,11 @@ SELECT decodeXMLComponent('Hello, <t& world');
|
||||
SELECT decodeXMLComponent('Hello, &t;& world');
|
||||
|
||||
--decode numeric entities
|
||||
SELECT decodeXMLComponent('�	 ');
|
||||
SELECT decodeXMLComponent(' ');
|
||||
SELECT decodeXMLComponent(' !"#$%&'()*+,-./012');
|
||||
|
||||
SELECT decodeXMLComponent(' !"#$%&'()*+,-./012');
|
||||
SELECT decodeXMLComponent(')*+,-./0123456789:;<');
|
||||
SELECT decodeXMLComponent('=>?@ABCDEFGHIJKLMNOP');
|
||||
SELECT decodeXMLComponent('QRSTUVWXYZ[\]^_`abcd');
|
||||
SELECT decodeXMLComponent('efghijklmnopqrstuvwx');
|
||||
SELECT decodeXMLComponent('yz{|}~€‚ƒ„…†‡ˆ‰Š‹Œ');
|
||||
SELECT decodeXMLComponent('Ž‘’“”•–—˜™š›œžŸ ');
|
||||
SELECT decodeXMLComponent('¡¢£¤¥¦§¨©ª«¬­®¯°±²³´');
|
||||
SELECT decodeXMLComponent('µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈ');
|
||||
SELECT decodeXMLComponent('ÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜ');
|
||||
SELECT decodeXMLComponent('ÝÞßàáâãäåæçèéêëìíîïð');
|
||||
SELECT decodeXMLComponent('ñòóôõö÷øùúûüýþÿĀ');
|
||||
SELECT decodeXMLComponent('为');
|
||||
SELECT decodeXMLComponent('为');
|
||||
SELECT decodeXMLComponent('�'123');
|
||||
SELECT decodeXMLComponent('ЦЦЮЮЫㄱ');
|
Loading…
Reference in New Issue
Block a user