fix decodeUrl; decode all values; add more tests

This commit is contained in:
artpaul 2016-12-15 22:12:41 +05:00
parent fea00eb595
commit d3657d311b
3 changed files with 31 additions and 22 deletions

View File

@ -5,12 +5,13 @@
namespace DB namespace DB
{ {
template <typename T> /// We assume that size of the buf isn't less than url.size().
static void decodeUrl(const StringView & url, T & dest, size_t & offset) static size_t decodeUrl(const StringView & url, char* dst)
{ {
const char* p = url.data(); const char* p = url.data();
const char* st = url.data(); const char* st = url.data();
const char* end = url.data() + url.size(); const char* const end = url.data() + url.size();
char* buf = dst;
for (; p < end; ++p) for (; p < end; ++p)
{ {
@ -24,15 +25,11 @@ static void decodeUrl(const StringView & url, T & dest, size_t & offset)
{ {
unsigned char digit = (h << 4) + l; unsigned char digit = (h << 4) + l;
if (digit < 127) { memcpy(buf, st, p - st);
dest.resize(dest.size() + p - st + 1); buf += p - st;
memcpy(&dest[offset], st, p - st); *buf = digit;
offset += p - st; ++buf;
dest[offset] = digit; st = p + 3;
offset++;
st = p + 3;
}
} }
p += 2; p += 2;
@ -40,17 +37,16 @@ static void decodeUrl(const StringView & url, T & dest, size_t & offset)
if (st == url.data()) if (st == url.data())
{ {
dest.resize(dest.size() + url.size() + 1); memcpy(buf, url.data(), url.size());
memcpy(&dest[offset], url.data(), url.size()); return url.size();
offset += url.size() + 1;
dest[offset - 1] = 0;
} }
else if (st < p) else if (st < p)
{ {
dest.resize(dest.size() + p - st); memcpy(buf, st, p - st);
memcpy(&dest[offset], st, p - st); buf += p - st;
offset += p - st;
} }
return buf - dst;
} }
@ -90,8 +86,14 @@ void DecodeURLComponentImpl::vector(const ColumnString::Chars_t & data, const Co
{ {
const char * current = reinterpret_cast<const char *>(&data[prev_offset]); const char * current = reinterpret_cast<const char *>(&data[prev_offset]);
const StringView url(current, offsets[i] - prev_offset - 1); const StringView url(current, offsets[i] - prev_offset - 1);
size_t prev_size = res_data.size();
decodeUrl(url, res_data, res_offset); res_data.resize(prev_size + url.size() + 1);
size_t len = decodeUrl(url, reinterpret_cast<char *>(res_data.data() + res_offset));
res_data.resize(prev_size + len);
res_offset += len;
res_data[res_offset] = 0;
res_offset++;
res_offsets[i] = res_offset; res_offsets[i] = res_offset;
prev_offset = offsets[i]; prev_offset = offsets[i];
@ -102,8 +104,9 @@ void DecodeURLComponentImpl::vector(const ColumnString::Chars_t & data, const Co
void DecodeURLComponentImpl::constant(const std::string & data, void DecodeURLComponentImpl::constant(const std::string & data,
std::string & res_data) std::string & res_data)
{ {
size_t offset = 0; res_data.resize(data.size());
decodeUrl(data, res_data, offset); size_t len = decodeUrl(data, &res_data[0]);
res_data.resize(len);
} }

View File

@ -12,4 +12,7 @@ com
ru ru
ru ru
П
%D%9
/?query=hello world+foo+bar
/?query=hello world+foo+bar /?query=hello world+foo+bar

View File

@ -15,4 +15,7 @@ SELECT topLevelDomain('http://127.0.0.1:443/') AS Domain;
SELECT topLevelDomain('svn+ssh://example.ru?q=hello%20world') AS Domain; SELECT topLevelDomain('svn+ssh://example.ru?q=hello%20world') AS Domain;
SELECT topLevelDomain('svn+ssh://example.ru.?q=hello%20world') AS Domain; SELECT topLevelDomain('svn+ssh://example.ru.?q=hello%20world') AS Domain;
SELECT decodeURLComponent('%D0%9F');
SELECT decodeURLComponent('%D%9');
SELECT decodeURLComponent(pathFull('http://127.0.0.1/?query=hello%20world+foo%2Bbar')) AS Path; SELECT decodeURLComponent(pathFull('http://127.0.0.1/?query=hello%20world+foo%2Bbar')) AS Path;
SELECT decodeURLComponent(materialize(pathFull('http://127.0.0.1/?query=hello%20world+foo%2Bbar'))) AS Path;