Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: components/json_schema/json_schema_validator.cc

Issue 2539363004: Make base::Value::TYPE a scoped enum. (Closed)
Patch Set: Rebase Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/json_schema/json_schema_validator.h" 5 #include "components/json_schema/json_schema_validator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cfloat> 10 #include <cfloat>
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 return value; 72 return value;
73 } 73 }
74 74
75 bool IsValidSchema(const base::DictionaryValue* dict, 75 bool IsValidSchema(const base::DictionaryValue* dict,
76 int options, 76 int options,
77 std::string* error) { 77 std::string* error) {
78 // This array must be sorted, so that std::lower_bound can perform a 78 // This array must be sorted, so that std::lower_bound can perform a
79 // binary search. 79 // binary search.
80 static const ExpectedType kExpectedTypes[] = { 80 static const ExpectedType kExpectedTypes[] = {
81 // Note: kRef == "$ref", kSchema == "$schema" 81 // Note: kRef == "$ref", kSchema == "$schema"
82 { schema::kRef, base::Value::TYPE_STRING }, 82 { schema::kRef, base::Value::Type::STRING },
83 { schema::kSchema, base::Value::TYPE_STRING }, 83 { schema::kSchema, base::Value::Type::STRING },
84 84
85 { schema::kAdditionalProperties, base::Value::TYPE_DICTIONARY }, 85 { schema::kAdditionalProperties, base::Value::Type::DICTIONARY },
86 { schema::kChoices, base::Value::TYPE_LIST }, 86 { schema::kChoices, base::Value::Type::LIST },
87 { schema::kDescription, base::Value::TYPE_STRING }, 87 { schema::kDescription, base::Value::Type::STRING },
88 { schema::kEnum, base::Value::TYPE_LIST }, 88 { schema::kEnum, base::Value::Type::LIST },
89 { schema::kId, base::Value::TYPE_STRING }, 89 { schema::kId, base::Value::Type::STRING },
90 { schema::kMaxItems, base::Value::TYPE_INTEGER }, 90 { schema::kMaxItems, base::Value::Type::INTEGER },
91 { schema::kMaxLength, base::Value::TYPE_INTEGER }, 91 { schema::kMaxLength, base::Value::Type::INTEGER },
92 { schema::kMaximum, base::Value::TYPE_DOUBLE }, 92 { schema::kMaximum, base::Value::Type::DOUBLE },
93 { schema::kMinItems, base::Value::TYPE_INTEGER }, 93 { schema::kMinItems, base::Value::Type::INTEGER },
94 { schema::kMinLength, base::Value::TYPE_INTEGER }, 94 { schema::kMinLength, base::Value::Type::INTEGER },
95 { schema::kMinimum, base::Value::TYPE_DOUBLE }, 95 { schema::kMinimum, base::Value::Type::DOUBLE },
96 { schema::kOptional, base::Value::TYPE_BOOLEAN }, 96 { schema::kOptional, base::Value::Type::BOOLEAN },
97 { schema::kPattern, base::Value::TYPE_STRING }, 97 { schema::kPattern, base::Value::Type::STRING },
98 { schema::kPatternProperties, base::Value::TYPE_DICTIONARY }, 98 { schema::kPatternProperties, base::Value::Type::DICTIONARY },
99 { schema::kProperties, base::Value::TYPE_DICTIONARY }, 99 { schema::kProperties, base::Value::Type::DICTIONARY },
100 { schema::kTitle, base::Value::TYPE_STRING }, 100 { schema::kTitle, base::Value::Type::STRING },
101 }; 101 };
102 102
103 bool has_type_or_ref = false; 103 bool has_type_or_ref = false;
104 const base::ListValue* list_value = NULL; 104 const base::ListValue* list_value = NULL;
105 const base::DictionaryValue* dictionary_value = NULL; 105 const base::DictionaryValue* dictionary_value = NULL;
106 std::string string_value; 106 std::string string_value;
107 107
108 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { 108 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
109 // Validate the "type" attribute, which may be a string or a list. 109 // Validate the "type" attribute, which may be a string or a list.
110 if (it.key() == schema::kType) { 110 if (it.key() == schema::kType) {
111 switch (it.value().GetType()) { 111 switch (it.value().GetType()) {
112 case base::Value::TYPE_STRING: 112 case base::Value::Type::STRING:
113 it.value().GetAsString(&string_value); 113 it.value().GetAsString(&string_value);
114 if (!IsValidType(string_value)) { 114 if (!IsValidType(string_value)) {
115 *error = "Invalid value for type attribute"; 115 *error = "Invalid value for type attribute";
116 return false; 116 return false;
117 } 117 }
118 break; 118 break;
119 case base::Value::TYPE_LIST: 119 case base::Value::Type::LIST:
120 it.value().GetAsList(&list_value); 120 it.value().GetAsList(&list_value);
121 for (size_t i = 0; i < list_value->GetSize(); ++i) { 121 for (size_t i = 0; i < list_value->GetSize(); ++i) {
122 if (!list_value->GetString(i, &string_value) || 122 if (!list_value->GetString(i, &string_value) ||
123 !IsValidType(string_value)) { 123 !IsValidType(string_value)) {
124 *error = "Invalid value for type attribute"; 124 *error = "Invalid value for type attribute";
125 return false; 125 return false;
126 } 126 }
127 } 127 }
128 break; 128 break;
129 default: 129 default:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 kExpectedTypes, end, it.key(), CompareToString); 167 kExpectedTypes, end, it.key(), CompareToString);
168 if (entry == end || entry->key != it.key()) { 168 if (entry == end || entry->key != it.key()) {
169 if (options & JSONSchemaValidator::OPTIONS_IGNORE_UNKNOWN_ATTRIBUTES) 169 if (options & JSONSchemaValidator::OPTIONS_IGNORE_UNKNOWN_ATTRIBUTES)
170 continue; 170 continue;
171 *error = base::StringPrintf("Invalid attribute %s", it.key().c_str()); 171 *error = base::StringPrintf("Invalid attribute %s", it.key().c_str());
172 return false; 172 return false;
173 } 173 }
174 174
175 // Integer can be converted to double. 175 // Integer can be converted to double.
176 if (!(it.value().IsType(entry->type) || 176 if (!(it.value().IsType(entry->type) ||
177 (it.value().IsType(base::Value::TYPE_INTEGER) && 177 (it.value().IsType(base::Value::Type::INTEGER) &&
178 entry->type == base::Value::TYPE_DOUBLE))) { 178 entry->type == base::Value::Type::DOUBLE))) {
179 *error = base::StringPrintf("Invalid value for %s attribute", 179 *error = base::StringPrintf("Invalid value for %s attribute",
180 it.key().c_str()); 180 it.key().c_str());
181 return false; 181 return false;
182 } 182 }
183 183
184 // base::Value::TYPE_INTEGER attributes must be >= 0. 184 // base::Value::Type::INTEGER attributes must be >= 0.
185 // This applies to "minItems", "maxItems", "minLength" and "maxLength". 185 // This applies to "minItems", "maxItems", "minLength" and "maxLength".
186 if (it.value().IsType(base::Value::TYPE_INTEGER)) { 186 if (it.value().IsType(base::Value::Type::INTEGER)) {
187 int integer_value; 187 int integer_value;
188 it.value().GetAsInteger(&integer_value); 188 it.value().GetAsInteger(&integer_value);
189 if (integer_value < 0) { 189 if (integer_value < 0) {
190 *error = base::StringPrintf("Value of %s must be >= 0, got %d", 190 *error = base::StringPrintf("Value of %s must be >= 0, got %d",
191 it.key().c_str(), integer_value); 191 it.key().c_str(), integer_value);
192 return false; 192 return false;
193 } 193 }
194 } 194 }
195 195
196 // Validate the "properties" attribute. Each entry maps a key to a schema. 196 // Validate the "properties" attribute. Each entry maps a key to a schema.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 const base::Value* value = NULL; 244 const base::Value* value = NULL;
245 list_value->Get(i, &value); 245 list_value->Get(i, &value);
246 // Sometimes the enum declaration is a dictionary with the enum value 246 // Sometimes the enum declaration is a dictionary with the enum value
247 // under "name". 247 // under "name".
248 value = ExtractNameFromDictionary(value); 248 value = ExtractNameFromDictionary(value);
249 if (!value) { 249 if (!value) {
250 *error = "Invalid value in enum attribute"; 250 *error = "Invalid value in enum attribute";
251 return false; 251 return false;
252 } 252 }
253 switch (value->GetType()) { 253 switch (value->GetType()) {
254 case base::Value::TYPE_NULL: 254 case base::Value::Type::NONE:
255 case base::Value::TYPE_BOOLEAN: 255 case base::Value::Type::BOOLEAN:
256 case base::Value::TYPE_INTEGER: 256 case base::Value::Type::INTEGER:
257 case base::Value::TYPE_DOUBLE: 257 case base::Value::Type::DOUBLE:
258 case base::Value::TYPE_STRING: 258 case base::Value::Type::STRING:
259 break; 259 break;
260 default: 260 default:
261 *error = "Invalid value in enum attribute"; 261 *error = "Invalid value in enum attribute";
262 return false; 262 return false;
263 } 263 }
264 } 264 }
265 } 265 }
266 266
267 // Validate the schemas contained in a "choices" attribute. 267 // Validate the schemas contained in a "choices" attribute.
268 if (it.key() == schema::kChoices) { 268 if (it.key() == schema::kChoices) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 "Expected '*' but got '*'."; 337 "Expected '*' but got '*'.";
338 const char JSONSchemaValidator::kInvalidTypeIntegerNumber[] = 338 const char JSONSchemaValidator::kInvalidTypeIntegerNumber[] =
339 "Expected 'integer' but got 'number', consider using Math.round()."; 339 "Expected 'integer' but got 'number', consider using Math.round().";
340 const char JSONSchemaValidator::kInvalidRegex[] = 340 const char JSONSchemaValidator::kInvalidRegex[] =
341 "Regular expression /*/ is invalid: *"; 341 "Regular expression /*/ is invalid: *";
342 342
343 343
344 // static 344 // static
345 std::string JSONSchemaValidator::GetJSONSchemaType(const base::Value* value) { 345 std::string JSONSchemaValidator::GetJSONSchemaType(const base::Value* value) {
346 switch (value->GetType()) { 346 switch (value->GetType()) {
347 case base::Value::TYPE_NULL: 347 case base::Value::Type::NONE:
348 return schema::kNull; 348 return schema::kNull;
349 case base::Value::TYPE_BOOLEAN: 349 case base::Value::Type::BOOLEAN:
350 return schema::kBoolean; 350 return schema::kBoolean;
351 case base::Value::TYPE_INTEGER: 351 case base::Value::Type::INTEGER:
352 return schema::kInteger; 352 return schema::kInteger;
353 case base::Value::TYPE_DOUBLE: { 353 case base::Value::Type::DOUBLE: {
354 double double_value = 0; 354 double double_value = 0;
355 value->GetAsDouble(&double_value); 355 value->GetAsDouble(&double_value);
356 if (std::abs(double_value) <= std::pow(2.0, DBL_MANT_DIG) && 356 if (std::abs(double_value) <= std::pow(2.0, DBL_MANT_DIG) &&
357 double_value == floor(double_value)) { 357 double_value == floor(double_value)) {
358 return schema::kInteger; 358 return schema::kInteger;
359 } else { 359 } else {
360 return schema::kNumber; 360 return schema::kNumber;
361 } 361 }
362 } 362 }
363 case base::Value::TYPE_STRING: 363 case base::Value::Type::STRING:
364 return schema::kString; 364 return schema::kString;
365 case base::Value::TYPE_DICTIONARY: 365 case base::Value::Type::DICTIONARY:
366 return schema::kObject; 366 return schema::kObject;
367 case base::Value::TYPE_LIST: 367 case base::Value::Type::LIST:
368 return schema::kArray; 368 return schema::kArray;
369 default: 369 default:
370 NOTREACHED() << "Unexpected value type: " << value->GetType(); 370 NOTREACHED() << "Unexpected value type: " << value->GetType();
371 return std::string(); 371 return std::string();
372 } 372 }
373 } 373 }
374 374
375 // static 375 // static
376 std::string JSONSchemaValidator::FormatErrorMessage(const std::string& format, 376 std::string JSONSchemaValidator::FormatErrorMessage(const std::string& format,
377 const std::string& s1) { 377 const std::string& s1) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 500
501 // These casts are safe because of checks in ValidateType(). 501 // These casts are safe because of checks in ValidateType().
502 if (type == schema::kObject) { 502 if (type == schema::kObject) {
503 ValidateObject(static_cast<const base::DictionaryValue*>(instance), 503 ValidateObject(static_cast<const base::DictionaryValue*>(instance),
504 schema, 504 schema,
505 path); 505 path);
506 } else if (type == schema::kArray) { 506 } else if (type == schema::kArray) {
507 ValidateArray(static_cast<const base::ListValue*>(instance), 507 ValidateArray(static_cast<const base::ListValue*>(instance),
508 schema, path); 508 schema, path);
509 } else if (type == schema::kString) { 509 } else if (type == schema::kString) {
510 // Intentionally NOT downcasting to StringValue*. TYPE_STRING only implies 510 // Intentionally NOT downcasting to StringValue*. Type::STRING only
511 // GetAsString() can safely be carried out, not that it's a StringValue. 511 // implies GetAsString() can safely be carried out, not that it's a
512 // StringValue.
512 ValidateString(instance, schema, path); 513 ValidateString(instance, schema, path);
513 } else if (type == schema::kNumber || type == schema::kInteger) { 514 } else if (type == schema::kNumber || type == schema::kInteger) {
514 ValidateNumber(instance, schema, path); 515 ValidateNumber(instance, schema, path);
515 } else if (type != schema::kBoolean && type != schema::kNull) { 516 } else if (type != schema::kBoolean && type != schema::kNull) {
516 NOTREACHED() << "Unexpected type: " << type; 517 NOTREACHED() << "Unexpected type: " << type;
517 } 518 }
518 } 519 }
519 } 520 }
520 521
521 void JSONSchemaValidator::ValidateChoices(const base::Value* instance, 522 void JSONSchemaValidator::ValidateChoices(const base::Value* instance,
(...skipping 25 matching lines...) Expand all
547 for (size_t i = 0; i < choices->GetSize(); ++i) { 548 for (size_t i = 0; i < choices->GetSize(); ++i) {
548 const base::Value* choice = NULL; 549 const base::Value* choice = NULL;
549 CHECK(choices->Get(i, &choice)); 550 CHECK(choices->Get(i, &choice));
550 // Sometimes the enum declaration is a dictionary with the enum value under 551 // Sometimes the enum declaration is a dictionary with the enum value under
551 // "name". 552 // "name".
552 choice = ExtractNameFromDictionary(choice); 553 choice = ExtractNameFromDictionary(choice);
553 if (!choice) { 554 if (!choice) {
554 NOTREACHED(); 555 NOTREACHED();
555 } 556 }
556 switch (choice->GetType()) { 557 switch (choice->GetType()) {
557 case base::Value::TYPE_NULL: 558 case base::Value::Type::NONE:
558 case base::Value::TYPE_BOOLEAN: 559 case base::Value::Type::BOOLEAN:
559 case base::Value::TYPE_STRING: 560 case base::Value::Type::STRING:
560 if (instance->Equals(choice)) 561 if (instance->Equals(choice))
561 return; 562 return;
562 break; 563 break;
563 564
564 case base::Value::TYPE_INTEGER: 565 case base::Value::Type::INTEGER:
565 case base::Value::TYPE_DOUBLE: 566 case base::Value::Type::DOUBLE:
566 if (instance->IsType(base::Value::TYPE_INTEGER) || 567 if (instance->IsType(base::Value::Type::INTEGER) ||
567 instance->IsType(base::Value::TYPE_DOUBLE)) { 568 instance->IsType(base::Value::Type::DOUBLE)) {
568 if (GetNumberValue(choice) == GetNumberValue(instance)) 569 if (GetNumberValue(choice) == GetNumberValue(instance))
569 return; 570 return;
570 } 571 }
571 break; 572 break;
572 573
573 default: 574 default:
574 NOTREACHED() << "Unexpected type in enum: " << choice->GetType(); 575 NOTREACHED() << "Unexpected type in enum: " << choice->GetType();
575 } 576 }
576 } 577 }
577 578
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 schema->GetList(schema::kItems, &tuple_type); 709 schema->GetList(schema::kItems, &tuple_type);
709 size_t tuple_size = tuple_type ? tuple_type->GetSize() : 0; 710 size_t tuple_size = tuple_type ? tuple_type->GetSize() : 0;
710 if (tuple_type) { 711 if (tuple_type) {
711 for (size_t i = 0; i < tuple_size; ++i) { 712 for (size_t i = 0; i < tuple_size; ++i) {
712 std::string i_str = base::Uint64ToString(i); 713 std::string i_str = base::Uint64ToString(i);
713 std::string item_path = path.empty() ? i_str : (path + "." + i_str); 714 std::string item_path = path.empty() ? i_str : (path + "." + i_str);
714 const base::DictionaryValue* item_schema = NULL; 715 const base::DictionaryValue* item_schema = NULL;
715 CHECK(tuple_type->GetDictionary(i, &item_schema)); 716 CHECK(tuple_type->GetDictionary(i, &item_schema));
716 const base::Value* item_value = NULL; 717 const base::Value* item_value = NULL;
717 instance->Get(i, &item_value); 718 instance->Get(i, &item_value);
718 if (item_value && item_value->GetType() != base::Value::TYPE_NULL) { 719 if (item_value && item_value->GetType() != base::Value::Type::NONE) {
719 Validate(item_value, item_schema, item_path); 720 Validate(item_value, item_schema, item_path);
720 } else { 721 } else {
721 bool is_optional = false; 722 bool is_optional = false;
722 item_schema->GetBoolean(schema::kOptional, &is_optional); 723 item_schema->GetBoolean(schema::kOptional, &is_optional);
723 if (!is_optional) { 724 if (!is_optional) {
724 errors_.push_back(Error(item_path, kArrayItemRequired)); 725 errors_.push_back(Error(item_path, kArrayItemRequired));
725 return; 726 return;
726 } 727 }
727 } 728 }
728 } 729 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 841
841 if (*additional_properties_schema) { 842 if (*additional_properties_schema) {
842 std::string additional_properties_type(schema::kAny); 843 std::string additional_properties_type(schema::kAny);
843 CHECK((*additional_properties_schema)->GetString( 844 CHECK((*additional_properties_schema)->GetString(
844 schema::kType, &additional_properties_type)); 845 schema::kType, &additional_properties_type));
845 return additional_properties_type == schema::kAny; 846 return additional_properties_type == schema::kAny;
846 } else { 847 } else {
847 return default_allow_additional_properties_; 848 return default_allow_additional_properties_;
848 } 849 }
849 } 850 }
OLDNEW
« no previous file with comments | « components/history/core/browser/web_history_service.cc ('k') | components/json_schema/json_schema_validator_unittest_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698