| 79 | |
| 80 | template <typename S> |
| 81 | bool EscapeJSONStringImpl(const S& str, bool put_in_quotes, std::string* dest) { |
| 82 | bool did_replacement = false; |
| 83 | |
| 84 | if (put_in_quotes) |
| 85 | dest->push_back('"'); |
| 86 | |
| 87 | // Casting is necessary because ICU uses int32_t. Try and do so safely. |
| 88 | CHECK_LE(str.length(), |
| 89 | static_cast<size_t>(std::numeric_limits<int32_t>::max())); |
| 90 | const int32_t length = static_cast<int32_t>(str.length()); |
| 91 | |
| 92 | for (int32_t i = 0; i < length; ++i) { |
| 93 | uint32_t code_point; |
| 94 | if (!ReadUnicodeCharacter(str.data(), length, &i, &code_point)) { |
| 95 | code_point = kReplacementCodePoint; |
| 96 | did_replacement = true; |
| 97 | } |
| 98 | |
| 99 | if (EscapeSpecialCodePoint(code_point, dest)) |
| 100 | continue; |
| 101 | |
| 102 | // Escape non-printing characters. |
| 103 | if (code_point < 32) |
| 104 | base::StringAppendF(dest, kU16EscapeFormat, code_point); |
| 105 | else |
| 106 | WriteUnicodeCharacter(code_point, dest); |
| 107 | } |
| 108 | |
| 109 | if (put_in_quotes) |
| 110 | dest->push_back('"'); |
| 111 | |
| 112 | return !did_replacement; |
| 113 | } |
| 114 | |
| 115 | } // namespace |
| 116 |
no test coverage detected