| 4445 | } |
| 4446 | |
| 4447 | static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { |
| 4448 | if (value == NULL) |
| 4449 | return ""; |
| 4450 | |
| 4451 | if (!isAnyCharRequiredQuoting(value, length)) |
| 4452 | return JSONCPP_STRING("\"") + value + "\""; |
| 4453 | // We have to walk value and escape any special characters. |
| 4454 | // Appending to JSONCPP_STRING is not efficient, but this should be rare. |
| 4455 | // (Note: forward slashes are *not* rare, but I am not escaping them.) |
| 4456 | JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL |
| 4457 | JSONCPP_STRING result; |
| 4458 | result.reserve(maxsize); // to avoid lots of mallocs |
| 4459 | result += "\""; |
| 4460 | char const* end = value + length; |
| 4461 | for (const char* c = value; c != end; ++c) { |
| 4462 | switch (*c) { |
| 4463 | case '\"': |
| 4464 | result += "\\\""; |
| 4465 | break; |
| 4466 | case '\\': |
| 4467 | result += "\\\\"; |
| 4468 | break; |
| 4469 | case '\b': |
| 4470 | result += "\\b"; |
| 4471 | break; |
| 4472 | case '\f': |
| 4473 | result += "\\f"; |
| 4474 | break; |
| 4475 | case '\n': |
| 4476 | result += "\\n"; |
| 4477 | break; |
| 4478 | case '\r': |
| 4479 | result += "\\r"; |
| 4480 | break; |
| 4481 | case '\t': |
| 4482 | result += "\\t"; |
| 4483 | break; |
| 4484 | // case '/': |
| 4485 | // Even though \/ is considered a legal escape in JSON, a bare |
| 4486 | // slash is also legal, so I see no reason to escape it. |
| 4487 | // (I hope I am not misunderstanding something.) |
| 4488 | // blep notes: actually escaping \/ may be useful in javascript to avoid </ |
| 4489 | // sequence. |
| 4490 | // Should add a flag to allow this compatibility mode and prevent this |
| 4491 | // sequence from occurring. |
| 4492 | default: { |
| 4493 | unsigned int cp = utf8ToCodepoint(c, end); |
| 4494 | // don't escape non-control characters |
| 4495 | // (short escape sequence are applied above) |
| 4496 | if (cp < 0x80 && cp >= 0x20) |
| 4497 | result += static_cast<char>(cp); |
| 4498 | else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane |
| 4499 | result += "\\u"; |
| 4500 | result += toHex16Bit(cp); |
| 4501 | } else { // codepoint is not in Basic Multilingual Plane |
| 4502 | // convert to surrogate pair first |
| 4503 | cp -= 0x10000; |
| 4504 | result += "\\u"; |
no test coverage detected