1 // Copyright 2006-2008 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/json/string_escape.h"
13 #include "base/check_op.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversion_utils.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/third_party/icu/icu_utf.h"
24 // Format string for printing a \uXXXX escape sequence.
25 const char kU16EscapeFormat[] = "\\u%04X";
27 // The code point to output for an invalid input code unit.
28 const base_icu::UChar32 kReplacementCodePoint = 0xFFFD;
30 // Used below in EscapeSpecialCodePoint().
31 static_assert('<' == 0x3C, "less than sign must be 0x3c");
33 // Try to escape the |code_point| if it is a known special character. If
34 // successful, returns true and appends the escape sequence to |dest|. This
35 // isn't required by the spec, but it's more readable by humans.
36 bool EscapeSpecialCodePoint(base_icu::UChar32 code_point, std::string* dest) {
37 // WARNING: if you add a new case here, you need to update the reader as well.
38 // Note: \v is in the reader, but not here since the JSON spec doesn't
62 // Escape < to prevent script execution; escaping > is not necessary and
63 // not doing so save a few bytes.
65 dest->append("\\u003C");
67 // Escape the "Line Separator" and "Paragraph Separator" characters, since
68 // they should be treated like a new line \r or \n.
70 dest->append("\\u2028");
73 dest->append("\\u2029");
82 bool EscapeJSONStringImpl(const S& str, bool put_in_quotes, std::string* dest) {
83 bool did_replacement = false;
88 const size_t length = str.length();
89 for (size_t i = 0; i < length; ++i) {
90 base_icu::UChar32 code_point;
91 if (!ReadUnicodeCharacter(str.data(), length, &i, &code_point) ||
92 code_point == CBU_SENTINEL) {
93 code_point = kReplacementCodePoint;
94 did_replacement = true;
97 if (EscapeSpecialCodePoint(code_point, dest))
100 // Escape non-printing characters.
102 base::StringAppendF(dest, kU16EscapeFormat, code_point);
104 WriteUnicodeCharacter(code_point, dest);
108 dest->push_back('"');
110 return !did_replacement;
115 bool EscapeJSONString(StringPiece str, bool put_in_quotes, std::string* dest) {
116 return EscapeJSONStringImpl(str, put_in_quotes, dest);
119 bool EscapeJSONString(StringPiece16 str,
122 return EscapeJSONStringImpl(str, put_in_quotes, dest);
125 std::string GetQuotedJSONString(StringPiece str) {
127 EscapeJSONStringImpl(str, true, &dest);
131 std::string GetQuotedJSONString(StringPiece16 str) {
133 EscapeJSONStringImpl(str, true, &dest);
137 std::string EscapeBytesAsInvalidJSONString(StringPiece str,
138 bool put_in_quotes) {
145 if (EscapeSpecialCodePoint(c, &dest))
148 if (c < 32 || c > 126) {
149 base::StringAppendF(&dest, kU16EscapeFormat,
150 static_cast<unsigned char>(c));