Commit 415e67951ba678139bb352ff33375c23eab28ca7

Authored by m-holger
Committed by Jay Berkenbilt
1 parent 1787d850

Refactor JSON::encode_string

Showing 1 changed file with 52 additions and 32 deletions
libqpdf/JSON.cc
... ... @@ -220,41 +220,61 @@ JSON::unparse() const
220 220 std::string
221 221 JSON::encode_string(std::string const& str)
222 222 {
223   - std::string result;
224   - size_t len = str.length();
225   - for (size_t i = 0; i < len; ++i) {
226   - unsigned char ch = static_cast<unsigned char>(str.at(i));
227   - switch (ch) {
228   - case '\\':
229   - result += "\\\\";
230   - break;
231   - case '\"':
232   - result += "\\\"";
233   - break;
234   - case '\b':
235   - result += "\\b";
236   - break;
237   - case '\f':
238   - result += "\\f";
239   - break;
240   - case '\n':
241   - result += "\\n";
242   - break;
243   - case '\r':
244   - result += "\\r";
245   - break;
246   - case '\t':
247   - result += "\\t";
248   - break;
249   - default:
250   - if (ch < 32) {
251   - result += "\\u" + QUtil::int_to_string_base(ch, 16, 4);
252   - } else {
253   - result.append(1, static_cast<char>(ch));
  223 + static auto constexpr hexchars = "0123456789abcdef";
  224 +
  225 + auto begin = str.cbegin();
  226 + auto end = str.cend();
  227 + auto iter = begin;
  228 + while (iter != end) {
  229 + auto c = static_cast<unsigned char>(*iter);
  230 + if ((c > 34 && c != '\\') || c == ' ' || c == 33) {
  231 + // Optimistically check that no char in str requires escaping.
  232 + // Hopefully we can just return the input str.
  233 + ++iter;
  234 + } else {
  235 + // We found a char that requires escaping. Initialize result to the
  236 + // chars scanned so far, append/replace the rest of str one char at
  237 + // a time, and return the result.
  238 + std::string result{begin, iter};
  239 +
  240 + for (; iter != end; ++iter) {
  241 + auto ch = static_cast<unsigned char>(*iter);
  242 + if ((ch > 34 && ch != '\\') || ch == ' ' || ch == 33) {
  243 + // Check for most common case first.
  244 + result += *iter;
  245 + } else {
  246 + switch (ch) {
  247 + case '\\':
  248 + result += "\\\\";
  249 + break;
  250 + case '\"':
  251 + result += "\\\"";
  252 + break;
  253 + case '\b':
  254 + result += "\\b";
  255 + break;
  256 + case '\f':
  257 + result += "\\f";
  258 + break;
  259 + case '\n':
  260 + result += "\\n";
  261 + break;
  262 + case '\r':
  263 + result += "\\r";
  264 + break;
  265 + case '\t':
  266 + result += "\\t";
  267 + break;
  268 + default:
  269 + result += ch < 16 ? "\\u000" : "\\u001";
  270 + result += hexchars[ch % 16];
  271 + }
  272 + }
254 273 }
  274 + return result;
255 275 }
256 276 }
257   - return result;
  277 + return str;
258 278 }
259 279  
260 280 JSON
... ...