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 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_ | 5 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_ |
6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_ | 6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/base_export.h" | 12 #include "base/base_export.h" |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/memory/scoped_vector.h" | |
16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
17 #include "base/string16.h" | 18 #include "base/string16.h" |
18 #include "base/values.h" | 19 #include "base/values.h" |
19 | 20 |
20 // JSONValueConverter converts a JSON value into a C++ struct in a | 21 // JSONValueConverter converts a JSON value into a C++ struct in a |
21 // lightweight way. | 22 // lightweight way. |
22 // | 23 // |
23 // Usage: | 24 // Usage: |
24 // For real examples, you may want to refer to _unittest.cc file. | 25 // For real examples, you may want to refer to _unittest.cc file. |
25 // | 26 // |
(...skipping 30 matching lines...) Expand all Loading... | |
56 // method. Then, just use RegisterNestedField() from the containing struct's | 57 // method. Then, just use RegisterNestedField() from the containing struct's |
57 // RegisterJSONConverter method. | 58 // RegisterJSONConverter method. |
58 // struct Nested { | 59 // struct Nested { |
59 // Message foo; | 60 // Message foo; |
60 // static void RegisterJSONConverter(...) { | 61 // static void RegisterJSONConverter(...) { |
61 // ... | 62 // ... |
62 // converter->RegisterNestedField("foo", &Nested::foo); | 63 // converter->RegisterNestedField("foo", &Nested::foo); |
63 // } | 64 // } |
64 // }; | 65 // }; |
65 // | 66 // |
66 // For repeated field, we just assume std::vector for its container | 67 // For repeated field, we just assume ScopedVector for its container |
67 // and you can put RegisterRepeatedInt or some other types. Use | 68 // and you can use RegisterRepeatedMessage (not std::vector to avoid |
68 // RegisterRepeatedMessage for nested repeated fields. | 69 // copy constructors). For repeated fields of basic types such like |
70 // int, we assume std::vector for its container and you can use | |
71 // RegisterRepeatedInt and so on. | |
69 // | 72 // |
70 | 73 |
71 namespace base { | 74 namespace base { |
72 | 75 |
73 template <typename StructType> | 76 template <typename StructType> |
74 class JSONValueConverter; | 77 class JSONValueConverter; |
75 | 78 |
76 namespace internal { | 79 namespace internal { |
77 | 80 |
78 class FieldConverterBase { | 81 class FieldConverterBase { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 JSONValueConverter<NestedType> converter_; | 204 JSONValueConverter<NestedType> converter_; |
202 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter); | 205 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter); |
203 }; | 206 }; |
204 | 207 |
205 template <typename Element> | 208 template <typename Element> |
206 class RepeatedValueConverter : public ValueConverter<std::vector<Element> > { | 209 class RepeatedValueConverter : public ValueConverter<std::vector<Element> > { |
207 public: | 210 public: |
208 RepeatedValueConverter() {} | 211 RepeatedValueConverter() {} |
209 | 212 |
210 virtual bool Convert( | 213 virtual bool Convert( |
211 const base::Value& value, std::vector<Element>* field) const OVERRIDE { | 214 const base::Value& value, std::vector<Element>* field) const OVERRIDE { |
awong
2012/01/13 00:27:55
Why do we still use a std::vector<> here?
Jun Mukai
2012/01/13 01:09:21
Either is fine but I don't have a strong motivatio
Jun Mukai
2012/01/13 02:10:37
Done.
satorux1
2012/01/13 02:13:51
nice. ints and doubles are cheap to copy but strin
| |
212 const base::ListValue* list = NULL; | 215 const base::ListValue* list = NULL; |
213 if (!value.GetAsList(&list)) { | 216 if (!value.GetAsList(&list)) { |
214 // The field is not a list. | 217 // The field is not a list. |
215 return false; | 218 return false; |
216 } | 219 } |
217 | 220 |
218 field->reserve(list->GetSize()); | 221 field->reserve(list->GetSize()); |
219 for (size_t i = 0; i < list->GetSize(); ++i) { | 222 for (size_t i = 0; i < list->GetSize(); ++i) { |
220 base::Value* element = NULL; | 223 base::Value* element = NULL; |
221 if (!list->Get(i, &element)) | 224 if (!list->Get(i, &element)) |
222 continue; | 225 continue; |
223 | 226 |
224 Element e; | 227 Element e; |
225 if (!basic_converter_.Convert(*element, &e)) { | 228 if (basic_converter_.Convert(*element, &e)) { |
229 field->push_back(e); | |
230 } else { | |
226 DVLOG(1) << "failure at " << i << "-th element"; | 231 DVLOG(1) << "failure at " << i << "-th element"; |
227 return false; | 232 return false; |
228 } | 233 } |
229 field->push_back(e); | |
230 } | 234 } |
231 return true; | 235 return true; |
232 } | 236 } |
233 | 237 |
234 private: | 238 private: |
235 BasicValueConverter<Element> basic_converter_; | 239 BasicValueConverter<Element> basic_converter_; |
236 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter); | 240 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter); |
237 }; | 241 }; |
238 | 242 |
239 template <typename NestedType> | 243 template <typename NestedType> |
240 class RepeatedMessageConverter | 244 class RepeatedMessageConverter |
241 : public ValueConverter<std::vector<NestedType> > { | 245 : public ValueConverter<ScopedVector<NestedType> > { |
242 public: | 246 public: |
243 RepeatedMessageConverter() {} | 247 RepeatedMessageConverter() {} |
244 | 248 |
245 virtual bool Convert( | 249 virtual bool Convert(const base::Value& value, |
246 const base::Value& value, std::vector<NestedType>* field) const OVERRIDE { | 250 ScopedVector<NestedType>* field) const OVERRIDE { |
247 const base::ListValue* list = NULL; | 251 const base::ListValue* list = NULL; |
248 if (!value.GetAsList(&list)) | 252 if (!value.GetAsList(&list)) |
249 return false; | 253 return false; |
250 | 254 |
251 field->reserve(list->GetSize()); | 255 field->reserve(list->GetSize()); |
252 for (size_t i = 0; i < list->GetSize(); ++i) { | 256 for (size_t i = 0; i < list->GetSize(); ++i) { |
253 base::Value* element = NULL; | 257 base::Value* element = NULL; |
254 if (!list->Get(i, &element)) | 258 if (!list->Get(i, &element)) |
255 continue; | 259 continue; |
256 | 260 |
257 field->push_back(NestedType()); | 261 NestedType* nested = new NestedType(); |
258 if (!converter_.Convert(*element, &field->back())) { | 262 if (converter_.Convert(*element, nested)) { |
263 field->push_back(nested); | |
264 } else { | |
259 DVLOG(1) << "failure at " << i << "-th element"; | 265 DVLOG(1) << "failure at " << i << "-th element"; |
260 return false; | 266 return false; |
261 } | 267 } |
262 } | 268 } |
263 return true; | 269 return true; |
264 } | 270 } |
265 | 271 |
266 private: | 272 private: |
267 JSONValueConverter<NestedType> converter_; | 273 JSONValueConverter<NestedType> converter_; |
268 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter); | 274 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter); |
269 }; | 275 }; |
270 | 276 |
271 } // namespace internal | 277 } // namespace internal |
272 | 278 |
273 template <class StructType> | 279 template <class StructType> |
274 class JSONValueConverter { | 280 class JSONValueConverter { |
275 public: | 281 public: |
276 JSONValueConverter() { | 282 JSONValueConverter() { |
277 StructType::RegisterJSONConverter(this); | 283 StructType::RegisterJSONConverter(this); |
278 } | 284 } |
279 | 285 |
280 ~JSONValueConverter() { | |
281 STLDeleteContainerPointers(fields_.begin(), fields_.end()); | |
282 } | |
283 | |
284 void RegisterIntField(const std::string& field_name, | 286 void RegisterIntField(const std::string& field_name, |
285 int StructType::* field) { | 287 int StructType::* field) { |
286 fields_.push_back(new internal::FieldConverter<StructType, int>( | 288 fields_.push_back(new internal::FieldConverter<StructType, int>( |
287 field_name, field, new internal::BasicValueConverter<int>)); | 289 field_name, field, new internal::BasicValueConverter<int>)); |
288 } | 290 } |
289 | 291 |
290 void RegisterStringField(const std::string& field_name, | 292 void RegisterStringField(const std::string& field_name, |
291 std::string StructType::* field) { | 293 std::string StructType::* field) { |
292 fields_.push_back(new internal::FieldConverter<StructType, std::string>( | 294 fields_.push_back(new internal::FieldConverter<StructType, std::string>( |
293 field_name, field, new internal::BasicValueConverter<std::string>)); | 295 field_name, field, new internal::BasicValueConverter<std::string>)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 | 356 |
355 void RegisterRepeatedBool(const std::string& field_name, | 357 void RegisterRepeatedBool(const std::string& field_name, |
356 std::vector<bool> StructType::* field) { | 358 std::vector<bool> StructType::* field) { |
357 fields_.push_back( | 359 fields_.push_back( |
358 new internal::FieldConverter<StructType, std::vector<bool> >( | 360 new internal::FieldConverter<StructType, std::vector<bool> >( |
359 field_name, field, new internal::RepeatedValueConverter<bool>)); | 361 field_name, field, new internal::RepeatedValueConverter<bool>)); |
360 } | 362 } |
361 | 363 |
362 template <class NestedType> | 364 template <class NestedType> |
363 void RegisterRepeatedMessage(const std::string& field_name, | 365 void RegisterRepeatedMessage(const std::string& field_name, |
364 std::vector<NestedType> StructType::* field) { | 366 ScopedVector<NestedType> StructType::* field) { |
365 fields_.push_back( | 367 fields_.push_back( |
366 new internal::FieldConverter<StructType, std::vector<NestedType> >( | 368 new internal::FieldConverter<StructType, ScopedVector<NestedType> >( |
367 field_name, | 369 field_name, |
368 field, | 370 field, |
369 new internal::RepeatedMessageConverter<NestedType>)); | 371 new internal::RepeatedMessageConverter<NestedType>)); |
370 } | 372 } |
371 | 373 |
372 bool Convert(const base::Value& value, StructType* output) const { | 374 bool Convert(const base::Value& value, StructType* output) const { |
373 const DictionaryValue* dictionary_value = NULL; | 375 const DictionaryValue* dictionary_value = NULL; |
374 if (!value.GetAsDictionary(&dictionary_value)) | 376 if (!value.GetAsDictionary(&dictionary_value)) |
375 return false; | 377 return false; |
376 | 378 |
377 for(std::vector<internal::FieldConverterBase*>::const_iterator it = | 379 for(size_t i = 0; i < fields_.size(); ++i) { |
378 fields_.begin(); it != fields_.end(); ++it) { | 380 const internal::FieldConverterBase* field_converter = fields_[i]; |
379 base::Value* field = NULL; | 381 base::Value* field = NULL; |
380 if (dictionary_value->Get((*it)->field_path(), &field)) { | 382 if (dictionary_value->Get(field_converter->field_path(), &field)) { |
381 if (!(*it)->ConvertField(*field, output)) { | 383 if (!field_converter->ConvertField(*field, output)) { |
382 DVLOG(1) << "failure at field " << (*it)->field_path(); | 384 DVLOG(1) << "failure at field " << field_converter->field_path(); |
383 return false; | 385 return false; |
384 } | 386 } |
385 } | 387 } |
386 } | 388 } |
387 return true; | 389 return true; |
388 } | 390 } |
389 | 391 |
390 private: | 392 private: |
391 std::vector<internal::FieldConverterBase*> fields_; | 393 ScopedVector<internal::FieldConverterBase> fields_; |
392 | 394 |
393 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter); | 395 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter); |
394 }; | 396 }; |
395 | 397 |
396 } // namespace base | 398 } // namespace base |
397 | 399 |
398 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_ | 400 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_ |
OLD | NEW |