summaryrefslogtreecommitdiff
path: root/src/mongo/util/str_escape.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/str_escape.cpp')
-rw-r--r--src/mongo/util/str_escape.cpp120
1 files changed, 29 insertions, 91 deletions
diff --git a/src/mongo/util/str_escape.cpp b/src/mongo/util/str_escape.cpp
index c42a916bab0..d191fb92252 100644
--- a/src/mongo/util/str_escape.cpp
+++ b/src/mongo/util/str_escape.cpp
@@ -37,82 +37,45 @@ namespace mongo::str {
namespace {
constexpr char kHexChar[] = "0123456789abcdef";
-// Appends the bytes in the range [begin, end) to the output buffer,
-// which can either be a fmt::memory_buffer, or a std::string.
-template <typename Buffer, typename Iterator>
-void appendBuffer(Buffer& buffer, Iterator begin, Iterator end) {
- buffer.append(begin, end);
-}
-
// 'singleHandler' Function to write a valid single byte UTF-8 sequence with desired escaping.
// 'invalidByteHandler' Function to write a byte of invalid UTF-8 encoding
// 'twoEscaper' Function to write a valid two byte UTF-8 sequence with desired escaping, for C1
// control codes.
-// 'maxLength' Max length to write into output buffer; A value of std::string::npos means unbounded.
-// An escape sequence will not be written if appending the entire sequence will exceed this limit.
-// 'wouldWrite' Output to contain the total bytes that would have been written to the buffer if no
-// size limit is in place.
-//
// All these functions take a function object as their first parameter to perform the
// writing of any escaped data. This function expects the number of handled bytes as its first
// parameter and the corresponding escaped string as the second. They are templates to they can be
// inlined.
-template <typename Buffer,
- typename SingleByteHandler,
- typename InvalidByteHandler,
- typename TwoByteEscaper>
-void escape(Buffer& buffer,
+template <typename SingleByteHandler, typename InvalidByteHandler, typename TwoByteEscaper>
+void escape(fmt::memory_buffer& buffer,
StringData str,
SingleByteHandler singleHandler,
InvalidByteHandler invalidByteHandler,
- TwoByteEscaper twoEscaper,
- size_t maxLength,
- size_t* wouldWrite) {
- // The range [inFirst, it) contains input that does not need to be escaped and that has not been
+ TwoByteEscaper twoEscaper) {
+ // The range [begin, it) contains input that does not need to be escaped and that has not been
// written to output yet.
- // The range [it, inLast) contains remaining input to scan. 'inFirst' is pointing to the
- // beginning of the input that has not yet been written to 'escaped'. 'it' is pointing to the
- // beginning of the unicode code point we're currently processing in the while-loop below.
- // 'inLast' is the end of the input sequence.
- auto inFirst = str.begin();
- auto inLast = str.end();
- auto it = inFirst;
- size_t cap = maxLength;
- size_t total = 0;
+ // The range [it end) contains remaining input to scan 'begin' is pointing to the beginning of
+ // the input that has not yet been written to 'escaped'.
+ // 'it' is pointing to the beginning of the unicode code point we're currently processing in the
+ // while-loop below. 'end' is the end of the input sequence.
+ auto begin = str.begin();
+ auto it = str.begin();
+ auto end = str.end();
// Writes an escaped sequence to output after flushing pending input that does not need to be
// escaped. 'it' is assumed to be at the beginning of the input sequence represented by the
// escaped data.
// 'numHandled' the number of bytes of unescaped data being written escaped in 'escapeSequence'
auto flushAndWrite = [&](size_t numHandled, StringData escapeSequence) {
- // Appends the range [wFirst, wLast) to the output if the result is within the max length.
- // 'canTruncate' controls the behavior if appending the entire range would exceed the limit.
- // If true, this appends input up to the length limit. Otherwise, none is appended.
- auto boundedWrite = [&](auto wFirst, auto wLast, bool canTruncate) {
- size_t len = std::distance(wFirst, wLast);
- total += len;
- if (maxLength != std::string::npos) {
- if (len > cap) {
- if (!canTruncate) {
- cap = 0;
- }
- len = cap;
- }
- cap -= len;
- }
- appendBuffer(buffer, wFirst, wFirst + len);
- };
-
// Flush range of unmodified input
- boundedWrite(inFirst, it, true);
- inFirst = it + numHandled;
+ buffer.append(begin, it);
+ begin = it + numHandled;
// Write escaped data
- boundedWrite(escapeSequence.begin(), escapeSequence.end(), false);
+ buffer.append(escapeSequence.rawData(), escapeSequence.rawData() + escapeSequence.size());
};
auto isValidCodePoint = [&](auto pos, int len) {
- return std::distance(pos, inLast) >= len &&
+ return std::distance(pos, end) >= len &&
std::all_of(pos + 1, pos + len, [](uint8_t c) { return (c >> 6) == 0b10; });
};
@@ -135,7 +98,7 @@ void escape(Buffer& buffer,
auto writeInvalid = [&](uint8_t c) { invalidByteHandler(flushAndWrite, c); };
- while (it != inLast) {
+ while (it != end) {
uint8_t c = *it;
bool bit7 = (c >> 7) & 1;
if (MONGO_likely(!bit7)) {
@@ -193,15 +156,10 @@ void escape(Buffer& buffer,
}
}
// Write last block
- flushAndWrite(0, {});
- if (wouldWrite) {
- *wouldWrite = total;
- }
+ buffer.append(begin, it);
}
} // namespace
-
-template <typename Buffer>
-void escapeForTextCommon(Buffer& buffer, StringData str, size_t maxLength, size_t* wouldWrite) {
+void escapeForText(fmt::memory_buffer& buffer, StringData str) {
auto singleByteHandler = [](const auto& writer, uint8_t unescaped) {
switch (unescaped) {
case '\0':
@@ -329,26 +287,16 @@ void escapeForTextCommon(Buffer& buffer, StringData str, size_t maxLength, size_
str,
std::move(singleByteHandler),
std::move(invalidByteHandler),
- std::move(twoByteEscaper),
- maxLength,
- wouldWrite);
+ std::move(twoByteEscaper));
}
-void escapeForText(fmt::memory_buffer& buffer,
- StringData str,
- size_t maxLength,
- size_t* wouldWrite) {
- escapeForTextCommon(buffer, str, maxLength, wouldWrite);
+std::string escapeForText(StringData str) {
+ fmt::memory_buffer buffer;
+ escapeForText(buffer, str);
+ return fmt::to_string(buffer);
}
-std::string escapeForText(StringData str, size_t maxLength, size_t* wouldWrite) {
- std::string buffer;
- escapeForTextCommon(buffer, str, maxLength, wouldWrite);
- return buffer;
-}
-
-template <typename Buffer>
-void escapeForJSONCommon(Buffer& buffer, StringData str, size_t maxLength, size_t* wouldWrite) {
+void escapeForJSON(fmt::memory_buffer& buffer, StringData str) {
auto singleByteHandler = [](const auto& writer, uint8_t unescaped) {
switch (unescaped) {
case '\0':
@@ -479,21 +427,11 @@ void escapeForJSONCommon(Buffer& buffer, StringData str, size_t maxLength, size_
str,
std::move(singleByteHandler),
std::move(invalidByteHandler),
- std::move(twoByteEscaper),
- maxLength,
- wouldWrite);
+ std::move(twoByteEscaper));
}
-
-void escapeForJSON(fmt::memory_buffer& buffer,
- StringData str,
- size_t maxLength,
- size_t* wouldWrite) {
- escapeForJSONCommon(buffer, str, maxLength, wouldWrite);
-}
-
-std::string escapeForJSON(StringData str, size_t maxLength, size_t* wouldWrite) {
- std::string buffer;
- escapeForJSONCommon(buffer, str, maxLength, wouldWrite);
- return buffer;
+std::string escapeForJSON(StringData str) {
+ fmt::memory_buffer buffer;
+ escapeForJSON(buffer, str);
+ return fmt::to_string(buffer);
}
} // namespace mongo::str