summaryrefslogtreecommitdiffstats
path: root/library/cpp/string_utils/quote/quote.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/cpp/string_utils/quote/quote.cpp')
-rw-r--r--library/cpp/string_utils/quote/quote.cpp65
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;
}