OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/json/json_parser.h" | 5 #include "base/json/json_parser.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <memory> | 8 #include <utility> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/memory/ptr_util.h" | |
12 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
15 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
16 #include "base/strings/utf_string_conversion_utils.h" | 17 #include "base/strings/utf_string_conversion_utils.h" |
17 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
18 #include "base/third_party/icu/icu_utf.h" | 19 #include "base/third_party/icu/icu_utf.h" |
19 #include "base/values.h" | 20 #include "base/values.h" |
20 | 21 |
21 namespace base { | 22 namespace base { |
22 namespace internal { | 23 namespace internal { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 const int kStackMaxDepth = 100; | 27 const int kStackMaxDepth = 100; |
27 | 28 |
28 const int32_t kExtendedASCIIStart = 0x80; | 29 const int32_t kExtendedASCIIStart = 0x80; |
29 | 30 |
30 // This and the class below are used to own the JSON input string for when | 31 // This and the class below are used to own the JSON input string for when |
31 // string tokens are stored as StringPiece instead of std::string. This | 32 // string tokens are stored as StringPiece instead of std::string. This |
32 // optimization avoids about 2/3rds of string memory copies. The constructor | 33 // optimization avoids about 2/3rds of string memory copies. The constructor |
33 // takes ownership of the input string. The real root value is Swap()ed into | 34 // takes ownership of the input string. The real root value is Swap()ed into |
34 // the new instance. | 35 // the new instance. |
35 class DictionaryHiddenRootValue : public DictionaryValue { | 36 class DictionaryHiddenRootValue : public DictionaryValue { |
36 public: | 37 public: |
37 DictionaryHiddenRootValue(std::string* json, Value* root) : json_(json) { | 38 DictionaryHiddenRootValue(std::string json, Value* root) |
39 : json_(std::move(json)) { | |
38 DCHECK(root->IsType(Value::TYPE_DICTIONARY)); | 40 DCHECK(root->IsType(Value::TYPE_DICTIONARY)); |
39 DictionaryValue::Swap(static_cast<DictionaryValue*>(root)); | 41 DictionaryValue::Swap(static_cast<DictionaryValue*>(root)); |
40 } | 42 } |
41 | 43 |
42 void Swap(DictionaryValue* other) override { | 44 void Swap(DictionaryValue* other) override { |
43 DVLOG(1) << "Swap()ing a DictionaryValue inefficiently."; | 45 DVLOG(1) << "Swap()ing a DictionaryValue inefficiently."; |
44 | 46 |
45 // First deep copy to convert JSONStringValue to std::string and swap that | 47 // First deep copy to convert JSONStringValue to std::string and swap that |
46 // copy with |other|, which contains the new contents of |this|. | 48 // copy with |other|, which contains the new contents of |this|. |
47 std::unique_ptr<DictionaryValue> copy(DeepCopy()); | 49 std::unique_ptr<DictionaryValue> copy(CreateDeepCopy()); |
48 copy->Swap(other); | 50 copy->Swap(other); |
49 | 51 |
50 // Then erase the contents of the current dictionary and swap in the | 52 // Then erase the contents of the current dictionary and swap in the |
51 // new contents, originally from |other|. | 53 // new contents, originally from |other|. |
52 Clear(); | 54 Clear(); |
53 json_.reset(); | 55 json_.clear(); |
54 DictionaryValue::Swap(copy.get()); | 56 DictionaryValue::Swap(copy.get()); |
55 } | 57 } |
56 | 58 |
57 // Not overriding DictionaryValue::Remove because it just calls through to | 59 // Not overriding DictionaryValue::Remove because it just calls through to |
58 // the method below. | 60 // the method below. |
59 | 61 |
60 bool RemoveWithoutPathExpansion(const std::string& key, | 62 bool RemoveWithoutPathExpansion(const std::string& key, |
61 std::unique_ptr<Value>* out) override { | 63 std::unique_ptr<Value>* out) override { |
62 // If the caller won't take ownership of the removed value, just call up. | 64 // If the caller won't take ownership of the removed value, just call up. |
63 if (!out) | 65 if (!out) |
64 return DictionaryValue::RemoveWithoutPathExpansion(key, out); | 66 return DictionaryValue::RemoveWithoutPathExpansion(key, out); |
65 | 67 |
66 DVLOG(1) << "Remove()ing from a DictionaryValue inefficiently."; | 68 DVLOG(1) << "Remove()ing from a DictionaryValue inefficiently."; |
67 | 69 |
68 // Otherwise, remove the value while its still "owned" by this and copy it | 70 // Otherwise, remove the value while its still "owned" by this and copy it |
69 // to convert any JSONStringValues to std::string. | 71 // to convert any JSONStringValues to std::string. |
70 std::unique_ptr<Value> out_owned; | 72 std::unique_ptr<Value> out_owned; |
71 if (!DictionaryValue::RemoveWithoutPathExpansion(key, &out_owned)) | 73 if (!DictionaryValue::RemoveWithoutPathExpansion(key, &out_owned)) |
72 return false; | 74 return false; |
73 | 75 |
74 out->reset(out_owned->DeepCopy()); | 76 *out = out_owned->CreateDeepCopy(); |
75 | 77 |
76 return true; | 78 return true; |
77 } | 79 } |
78 | 80 |
79 private: | 81 private: |
80 std::unique_ptr<std::string> json_; | 82 std::string json_; |
81 | 83 |
82 DISALLOW_COPY_AND_ASSIGN(DictionaryHiddenRootValue); | 84 DISALLOW_COPY_AND_ASSIGN(DictionaryHiddenRootValue); |
83 }; | 85 }; |
84 | 86 |
85 class ListHiddenRootValue : public ListValue { | 87 class ListHiddenRootValue : public ListValue { |
86 public: | 88 public: |
87 ListHiddenRootValue(std::string* json, Value* root) : json_(json) { | 89 ListHiddenRootValue(std::string json, Value* root) : json_(std::move(json)) { |
dcheng
2016/04/27 22:12:11
How do we feel about this? Or do we prefer std::un
jbroman
2016/04/27 22:19:39
I prefer std::string to std::unique_ptr<std::strin
jbroman
2016/04/27 22:25:24
Having now read more of the surrounding code, I th
dcheng
2016/04/27 22:38:27
I don't think start_pos_ is used after parsing. Ev
| |
88 DCHECK(root->IsType(Value::TYPE_LIST)); | 90 DCHECK(root->IsType(Value::TYPE_LIST)); |
89 ListValue::Swap(static_cast<ListValue*>(root)); | 91 ListValue::Swap(static_cast<ListValue*>(root)); |
90 } | 92 } |
91 | 93 |
92 void Swap(ListValue* other) override { | 94 void Swap(ListValue* other) override { |
93 DVLOG(1) << "Swap()ing a ListValue inefficiently."; | 95 DVLOG(1) << "Swap()ing a ListValue inefficiently."; |
94 | 96 |
95 // First deep copy to convert JSONStringValue to std::string and swap that | 97 // First deep copy to convert JSONStringValue to std::string and swap that |
96 // copy with |other|, which contains the new contents of |this|. | 98 // copy with |other|, which contains the new contents of |this|. |
97 std::unique_ptr<ListValue> copy(DeepCopy()); | 99 std::unique_ptr<ListValue> copy(CreateDeepCopy()); |
98 copy->Swap(other); | 100 copy->Swap(other); |
99 | 101 |
100 // Then erase the contents of the current list and swap in the new contents, | 102 // Then erase the contents of the current list and swap in the new contents, |
101 // originally from |other|. | 103 // originally from |other|. |
102 Clear(); | 104 Clear(); |
103 json_.reset(); | 105 json_.clear(); |
104 ListValue::Swap(copy.get()); | 106 ListValue::Swap(copy.get()); |
105 } | 107 } |
106 | 108 |
107 bool Remove(size_t index, std::unique_ptr<Value>* out) override { | 109 bool Remove(size_t index, std::unique_ptr<Value>* out) override { |
108 // If the caller won't take ownership of the removed value, just call up. | 110 // If the caller won't take ownership of the removed value, just call up. |
109 if (!out) | 111 if (!out) |
110 return ListValue::Remove(index, out); | 112 return ListValue::Remove(index, out); |
111 | 113 |
112 DVLOG(1) << "Remove()ing from a ListValue inefficiently."; | 114 DVLOG(1) << "Remove()ing from a ListValue inefficiently."; |
113 | 115 |
114 // Otherwise, remove the value while its still "owned" by this and copy it | 116 // Otherwise, remove the value while its still "owned" by this and copy it |
115 // to convert any JSONStringValues to std::string. | 117 // to convert any JSONStringValues to std::string. |
116 std::unique_ptr<Value> out_owned; | 118 std::unique_ptr<Value> out_owned; |
117 if (!ListValue::Remove(index, &out_owned)) | 119 if (!ListValue::Remove(index, &out_owned)) |
118 return false; | 120 return false; |
119 | 121 |
120 out->reset(out_owned->DeepCopy()); | 122 *out = out_owned->CreateDeepCopy(); |
121 | 123 |
122 return true; | 124 return true; |
123 } | 125 } |
124 | 126 |
125 private: | 127 private: |
126 std::unique_ptr<std::string> json_; | 128 std::string json_; |
127 | 129 |
128 DISALLOW_COPY_AND_ASSIGN(ListHiddenRootValue); | 130 DISALLOW_COPY_AND_ASSIGN(ListHiddenRootValue); |
129 }; | 131 }; |
130 | 132 |
131 // A variant on StringValue that uses StringPiece instead of copying the string | 133 // A variant on StringValue that uses StringPiece instead of copying the string |
132 // into the Value. This can only be stored in a child of hidden root (above), | 134 // into the Value. This can only be stored in a child of hidden root (above), |
133 // otherwise the referenced string will not be guaranteed to outlive it. | 135 // otherwise the referenced string will not be guaranteed to outlive it. |
134 class JSONStringValue : public Value { | 136 class JSONStringValue : public Value { |
135 public: | 137 public: |
136 explicit JSONStringValue(const StringPiece& piece) | 138 explicit JSONStringValue(const StringPiece& piece) |
137 : Value(TYPE_STRING), | 139 : Value(TYPE_STRING), |
138 string_piece_(piece) { | 140 string_piece_(piece) { |
139 } | 141 } |
140 | 142 |
141 // Overridden from Value: | 143 // Overridden from Value: |
142 bool GetAsString(std::string* out_value) const override { | 144 bool GetAsString(std::string* out_value) const override { |
143 string_piece_.CopyToString(out_value); | 145 string_piece_.CopyToString(out_value); |
144 return true; | 146 return true; |
145 } | 147 } |
146 bool GetAsString(string16* out_value) const override { | 148 bool GetAsString(string16* out_value) const override { |
147 *out_value = UTF8ToUTF16(string_piece_); | 149 *out_value = UTF8ToUTF16(string_piece_); |
148 return true; | 150 return true; |
149 } | 151 } |
152 #if 0 | |
jbroman
2016/04/27 22:19:39
remove before landing?
dcheng
2016/04/27 22:23:05
Should already be gone in the latest PS.
| |
150 Value* DeepCopy() const override { | 153 Value* DeepCopy() const override { |
151 return new StringValue(string_piece_.as_string()); | 154 return new StringValue(string_piece_.as_string()); |
152 } | 155 } |
156 #endif | |
153 bool Equals(const Value* other) const override { | 157 bool Equals(const Value* other) const override { |
154 std::string other_string; | 158 std::string other_string; |
155 return other->IsType(TYPE_STRING) && other->GetAsString(&other_string) && | 159 return other->IsType(TYPE_STRING) && other->GetAsString(&other_string) && |
156 StringPiece(other_string) == string_piece_; | 160 StringPiece(other_string) == string_piece_; |
157 } | 161 } |
158 | 162 |
159 private: | 163 private: |
160 // The location in the original input stream. | 164 // The location in the original input stream. |
161 StringPiece string_piece_; | 165 StringPiece string_piece_; |
162 | 166 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 line_number_(0), | 200 line_number_(0), |
197 index_last_line_(0), | 201 index_last_line_(0), |
198 error_code_(JSONReader::JSON_NO_ERROR), | 202 error_code_(JSONReader::JSON_NO_ERROR), |
199 error_line_(0), | 203 error_line_(0), |
200 error_column_(0) { | 204 error_column_(0) { |
201 } | 205 } |
202 | 206 |
203 JSONParser::~JSONParser() { | 207 JSONParser::~JSONParser() { |
204 } | 208 } |
205 | 209 |
206 Value* JSONParser::Parse(const StringPiece& input) { | 210 std::unique_ptr<Value> JSONParser::Parse(StringPiece input) { |
207 std::unique_ptr<std::string> input_copy; | 211 std::string input_copy; |
208 // If the children of a JSON root can be detached, then hidden roots cannot | 212 // If the children of a JSON root can be detached, then hidden roots cannot |
209 // be used, so do not bother copying the input because StringPiece will not | 213 // be used, so do not bother copying the input because StringPiece will not |
210 // be used anywhere. | 214 // be used anywhere. |
211 if (!(options_ & JSON_DETACHABLE_CHILDREN)) { | 215 if (!(options_ & JSON_DETACHABLE_CHILDREN)) { |
212 input_copy.reset(new std::string(input.as_string())); | 216 input_copy = input.as_string(); |
213 start_pos_ = input_copy->data(); | 217 start_pos_ = input_copy.data(); |
214 } else { | 218 } else { |
215 start_pos_ = input.data(); | 219 start_pos_ = input.data(); |
216 } | 220 } |
217 pos_ = start_pos_; | 221 pos_ = start_pos_; |
218 end_pos_ = start_pos_ + input.length(); | 222 end_pos_ = start_pos_ + input.length(); |
219 index_ = 0; | 223 index_ = 0; |
220 line_number_ = 1; | 224 line_number_ = 1; |
221 index_last_line_ = 0; | 225 index_last_line_ = 0; |
222 | 226 |
223 error_code_ = JSONReader::JSON_NO_ERROR; | 227 error_code_ = JSONReader::JSON_NO_ERROR; |
(...skipping 20 matching lines...) Expand all Loading... | |
244 if (!CanConsume(1) || (NextChar() && GetNextToken() != T_END_OF_INPUT)) { | 248 if (!CanConsume(1) || (NextChar() && GetNextToken() != T_END_OF_INPUT)) { |
245 ReportError(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, 1); | 249 ReportError(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, 1); |
246 return NULL; | 250 return NULL; |
247 } | 251 } |
248 } | 252 } |
249 | 253 |
250 // Dictionaries and lists can contain JSONStringValues, so wrap them in a | 254 // Dictionaries and lists can contain JSONStringValues, so wrap them in a |
251 // hidden root. | 255 // hidden root. |
252 if (!(options_ & JSON_DETACHABLE_CHILDREN)) { | 256 if (!(options_ & JSON_DETACHABLE_CHILDREN)) { |
253 if (root->IsType(Value::TYPE_DICTIONARY)) { | 257 if (root->IsType(Value::TYPE_DICTIONARY)) { |
254 return new DictionaryHiddenRootValue(input_copy.release(), root.get()); | 258 return WrapUnique( |
259 new DictionaryHiddenRootValue(std::move(input_copy), root.get())); | |
255 } else if (root->IsType(Value::TYPE_LIST)) { | 260 } else if (root->IsType(Value::TYPE_LIST)) { |
256 return new ListHiddenRootValue(input_copy.release(), root.get()); | 261 return WrapUnique( |
262 new ListHiddenRootValue(std::move(input_copy), root.get())); | |
257 } else if (root->IsType(Value::TYPE_STRING)) { | 263 } else if (root->IsType(Value::TYPE_STRING)) { |
258 // A string type could be a JSONStringValue, but because there's no | 264 // A string type could be a JSONStringValue, but because there's no |
259 // corresponding HiddenRootValue, the memory will be lost. Deep copy to | 265 // corresponding HiddenRootValue, the memory will be lost. Deep copy to |
260 // preserve it. | 266 // preserve it. |
261 return root->DeepCopy(); | 267 return root->CreateDeepCopy(); |
262 } | 268 } |
263 } | 269 } |
264 | 270 |
265 // All other values can be returned directly. | 271 // All other values can be returned directly. |
266 return root.release(); | 272 return root; |
267 } | 273 } |
268 | 274 |
269 JSONReader::JsonParseError JSONParser::error_code() const { | 275 JSONReader::JsonParseError JSONParser::error_code() const { |
270 return error_code_; | 276 return error_code_; |
271 } | 277 } |
272 | 278 |
273 std::string JSONParser::GetErrorMessage() const { | 279 std::string JSONParser::GetErrorMessage() const { |
274 return FormatErrorMessage(error_line_, error_column_, | 280 return FormatErrorMessage(error_line_, error_column_, |
275 JSONReader::ErrorCodeToString(error_code_)); | 281 JSONReader::ErrorCodeToString(error_code_)); |
276 } | 282 } |
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
974 const std::string& description) { | 980 const std::string& description) { |
975 if (line || column) { | 981 if (line || column) { |
976 return StringPrintf("Line: %i, column: %i, %s", | 982 return StringPrintf("Line: %i, column: %i, %s", |
977 line, column, description.c_str()); | 983 line, column, description.c_str()); |
978 } | 984 } |
979 return description; | 985 return description; |
980 } | 986 } |
981 | 987 |
982 } // namespace internal | 988 } // namespace internal |
983 } // namespace base | 989 } // namespace base |
OLD | NEW |