diff options
Diffstat (limited to 'library/cpp/string_utils/quote/quote.cpp')
| -rw-r--r-- | library/cpp/string_utils/quote/quote.cpp | 65 |
1 files changed, 52 insertions, 13 deletions
diff --git a/library/cpp/string_utils/quote/quote.cpp b/library/cpp/string_utils/quote/quote.cpp index 9559132ae6f..91e31da1102 100644 --- a/library/cpp/string_utils/quote/quote.cpp +++ b/library/cpp/string_utils/quote/quote.cpp @@ -62,10 +62,6 @@ namespace { }; } -static inline char d2x(unsigned x) { - return (char)((x < 10) ? ('0' + x) : ('A' + x - 10)); -} - static inline const char* FixZero(const char* s) noexcept { return s ? s : ""; } @@ -101,22 +97,65 @@ static const bool chars_to_url_escape[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //F }; +static const char d2x[16] = { + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' +}; + +template <class It1> +static inline void EscapeHelper(It1& to, unsigned char c, const bool* escape_map) { + if (!escape_map[c]) { + *to++ = (c == ' ') ? '+' : c; + } else { + *to++ = '%'; + *to++ = d2x[c >> 4]; + *to++ = d2x[c & 0xF]; + } +} + template <class It1, class It2, class It3> static inline It1 Escape(It1 to, It2 from, It3 end, const bool* escape_map = chars_to_url_escape) { while (from != end) { - if (escape_map[(unsigned char)*from]) { - *to++ = '%'; - *to++ = d2x((unsigned char)*from >> 4); - *to++ = d2x((unsigned char)*from & 0xF); + EscapeHelper(to, *from++, escape_map); + } + + *to = 0; + + return to; +} + +static inline char* Escape(char* to, const char* from, const char* end, const bool* escape_map = chars_to_url_escape) { + constexpr size_t BLOCK = 16; + + while (from + BLOCK <= end) { + uint32_t escape_count = 0; + for (size_t i = 0; i < BLOCK; ++i) { + escape_count |= escape_map[(unsigned char)from[i]]; + } + + if (escape_count == 0) { + unsigned char src[BLOCK]; + for (size_t i = 0; i < BLOCK; ++i) { + src[i] = from[i]; + } + for (size_t i = 0; i < BLOCK; ++i) { + unsigned char c = src[i]; + to[i] = (c == ' ') ? '+' : c; + } + to += BLOCK; } else { - *to++ = (*from == ' ' ? '+' : *from); + for (size_t i = 0; i < BLOCK; ++i) { + unsigned char c = from[i]; + EscapeHelper(to, c, escape_map); + } } + from += BLOCK; + } - ++from; + while (from != end) { + EscapeHelper(to, *from++, escape_map); } *to = 0; - return to; } @@ -282,8 +321,8 @@ char* UrlEscape(char* to, TStringBuf src, bool forceEscape) { if (escapePercent || (unsigned char)*from <= ' ' || (unsigned char)*from > '~') { *to++ = '%'; - *to++ = d2x((unsigned char)*from >> 4); - *to++ = d2x((unsigned char)*from & 0xF); + *to++ = d2x[(unsigned char)*from >> 4]; + *to++ = d2x[(unsigned char)*from & 0xF]; } else *to++ = *from; } |
