if (!doesAnyCharRequireEscaping(value, length)) returnString("\"") + value + "\""; // We have to walk value and escape any special characters. // Appending to String is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL String result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; charconst* end = value + length; for (constchar* c = value; c != end; ++c) { switch (*c) { case'\"': result += "\\\""; break; case'\\': result += "\\\\"; break; case'\b': result += "\\b"; break; case'\f': result += "\\f"; break; case'\n': result += "\\n"; break; case'\r': result += "\\r"; break; case'\t': result += "\\t"; break; // case '/': // Even though \/ is considered a legal escape in JSON, a bare // slash is also legal, so I see no reason to escape it. // (I hope I am not misunderstanding something.) // blep notes: actually escaping \/ may be useful in javascript to avoid </ // sequence. // Should add a flag to allow this compatibility mode and prevent this // sequence from occurring. default: { if (emitUTF8) { unsigned codepoint = static_cast<unsignedchar>(*c); if (codepoint < 0x20) { appendHex(result, codepoint); } else { appendRaw(result, codepoint); } } else { unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c` if (codepoint < 0x20) { appendHex(result, codepoint); } elseif (codepoint < 0x80) { appendRaw(result, codepoint); } elseif (codepoint < 0x10000) { // Basic Multilingual Plane appendHex(result, codepoint); } else { // Extended Unicode. Encode 20 bits as a surrogate pair. codepoint -= 0x10000; appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff)); appendHex(result, 0xdc00 + (codepoint & 0x3ff)); } } } break; } } result += "\""; return result; }