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

Unified Diff: components/policy/core/common/schema.cc

Issue 31273002: Generate the Chrome policy schema at compile time. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/policy/core/common/schema.h ('k') | components/policy/core/common/schema_internal.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/policy/core/common/schema.cc
diff --git a/components/policy/core/common/schema.cc b/components/policy/core/common/schema.cc
index b3e63d7f3b263e4e645baaeea9e1cb0ec58e5823..3830bc149bcf1cfbe95363db00a3e8f460e30606 100644
--- a/components/policy/core/common/schema.cc
+++ b/components/policy/core/common/schema.cc
@@ -5,17 +5,26 @@
#include "components/policy/core/common/schema.h"
#include <algorithm>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/memory/scoped_vector.h"
#include "components/json_schema/json_schema_constants.h"
#include "components/json_schema/json_schema_validator.h"
#include "components/policy/core/common/schema_internal.h"
namespace policy {
+using internal::PropertiesNode;
+using internal::PropertyNode;
+using internal::SchemaData;
+using internal::SchemaNode;
+
namespace {
+const int kInvalid = -1;
+
bool SchemaTypeToValueType(const std::string& type_string,
base::Value::Type* type) {
// Note: "any" is not an accepted type.
@@ -42,17 +51,60 @@ bool SchemaTypeToValueType(const std::string& type_string,
} // namespace
-Schema::Iterator::Iterator(const internal::PropertiesNode* properties)
- : it_(properties->begin),
- end_(properties->end) {}
+// A SchemaOwner can either Wrap() a SchemaData owned elsewhere (currently used
+// to wrap the Chrome schema, which is generated at compile time), or it can
+// own its own SchemaData. In that case, the InternalStorage class holds the
+// data referenced by the SchemaData substructures.
+class SchemaOwner::InternalStorage {
+ public:
+ ~InternalStorage() {}
+
+ static scoped_ptr<InternalStorage> ParseSchema(
+ const base::DictionaryValue& schema,
+ std::string* error);
+
+ const SchemaData* schema_data() const { return &schema_data_; }
+
+ private:
+ InternalStorage() {}
+
+ // Parses the JSON schema in |schema| and returns the index of the
+ // corresponding SchemaNode in |schema_nodes_|, which gets populated with any
+ // necessary intermediate nodes. If |schema| is invalid then -1 is returned
+ // and |error| is set to the error cause.
+ int Parse(const base::DictionaryValue& schema, std::string* error);
+
+ // Helper for Parse().
+ int ParseDictionary(const base::DictionaryValue& schema, std::string* error);
+
+ // Helper for Parse().
+ int ParseList(const base::DictionaryValue& schema, std::string* error);
+
+ SchemaData schema_data_;
+ // TODO: compute the sizes of these arrays before filling them up to avoid
+ // having to resize them.
+ ScopedVector<std::string> strings_;
+ std::vector<SchemaNode> schema_nodes_;
+ std::vector<PropertyNode> property_nodes_;
+ std::vector<PropertiesNode> properties_nodes_;
+
+ DISALLOW_COPY_AND_ASSIGN(InternalStorage);
+};
+
+Schema::Iterator::Iterator(const SchemaData* data, const PropertiesNode* node)
+ : data_(data),
+ it_(data->property_nodes + node->begin),
+ end_(data->property_nodes + node->end) {}
Schema::Iterator::Iterator(const Iterator& iterator)
- : it_(iterator.it_),
+ : data_(iterator.data_),
+ it_(iterator.it_),
end_(iterator.end_) {}
Schema::Iterator::~Iterator() {}
Schema::Iterator& Schema::Iterator::operator=(const Iterator& iterator) {
+ data_ = iterator.data_;
it_ = iterator.it_;
end_ = iterator.end_;
return *this;
@@ -71,35 +123,37 @@ const char* Schema::Iterator::key() const {
}
Schema Schema::Iterator::schema() const {
- return Schema(it_->schema);
+ return Schema(data_, data_->schema_nodes + it_->schema);
}
-Schema::Schema() : schema_(NULL) {}
+Schema::Schema() : data_(NULL), node_(NULL) {}
-Schema::Schema(const internal::SchemaNode* schema) : schema_(schema) {}
+Schema::Schema(const SchemaData* data, const SchemaNode* node)
+ : data_(data), node_(node) {}
-Schema::Schema(const Schema& schema) : schema_(schema.schema_) {}
+Schema::Schema(const Schema& schema)
+ : data_(schema.data_), node_(schema.node_) {}
Schema& Schema::operator=(const Schema& schema) {
- schema_ = schema.schema_;
+ data_ = schema.data_;
+ node_ = schema.node_;
return *this;
}
base::Value::Type Schema::type() const {
CHECK(valid());
- return schema_->type;
+ return node_->type;
}
Schema::Iterator Schema::GetPropertiesIterator() const {
CHECK(valid());
CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
- return Iterator(
- static_cast<const internal::PropertiesNode*>(schema_->extra));
+ return Iterator(data_, data_->properties_nodes + node_->extra);
}
namespace {
-bool CompareKeys(const internal::PropertyNode& node, const std::string& key) {
+bool CompareKeys(const PropertyNode& node, const std::string& key) {
return node.key < key;
}
@@ -108,20 +162,22 @@ bool CompareKeys(const internal::PropertyNode& node, const std::string& key) {
Schema Schema::GetKnownProperty(const std::string& key) const {
CHECK(valid());
CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
- const internal::PropertiesNode* properties_node =
- static_cast<const internal::PropertiesNode*>(schema_->extra);
- const internal::PropertyNode* it = std::lower_bound(
- properties_node->begin, properties_node->end, key, CompareKeys);
- if (it != properties_node->end && it->key == key)
- return Schema(it->schema);
+ const PropertiesNode* node = data_->properties_nodes + node_->extra;
+ const PropertyNode* begin = data_->property_nodes + node->begin;
+ const PropertyNode* end = data_->property_nodes + node->end;
+ const PropertyNode* it = std::lower_bound(begin, end, key, CompareKeys);
+ if (it != end && it->key == key)
+ return Schema(data_, data_->schema_nodes + it->schema);
return Schema();
}
Schema Schema::GetAdditionalProperties() const {
CHECK(valid());
CHECK_EQ(base::Value::TYPE_DICTIONARY, type());
- return Schema(
- static_cast<const internal::PropertiesNode*>(schema_->extra)->additional);
+ const PropertiesNode* node = data_->properties_nodes + node_->extra;
+ if (node->additional == kInvalid)
+ return Schema();
+ return Schema(data_, data_->schema_nodes + node->additional);
}
Schema Schema::GetProperty(const std::string& key) const {
@@ -132,19 +188,25 @@ Schema Schema::GetProperty(const std::string& key) const {
Schema Schema::GetItems() const {
CHECK(valid());
CHECK_EQ(base::Value::TYPE_LIST, type());
- return Schema(static_cast<const internal::SchemaNode*>(schema_->extra));
+ if (node_->extra == kInvalid)
+ return Schema();
+ return Schema(data_, data_->schema_nodes + node_->extra);
}
-SchemaOwner::SchemaOwner(const internal::SchemaNode* root) : root_(root) {}
+SchemaOwner::SchemaOwner(const SchemaData* data,
+ scoped_ptr<InternalStorage> storage)
+ : storage_(storage.Pass()), data_(data) {}
+
+SchemaOwner::~SchemaOwner() {}
-SchemaOwner::~SchemaOwner() {
- for (size_t i = 0; i < property_nodes_.size(); ++i)
- delete[] property_nodes_[i];
+Schema SchemaOwner::schema() const {
+ // data_->schema_nodes[0] is the root node.
+ return Schema(data_, data_->schema_nodes);
}
// static
-scoped_ptr<SchemaOwner> SchemaOwner::Wrap(const internal::SchemaNode* schema) {
- return scoped_ptr<SchemaOwner>(new SchemaOwner(schema));
+scoped_ptr<SchemaOwner> SchemaOwner::Wrap(const SchemaData* data) {
+ return make_scoped_ptr(new SchemaOwner(data, scoped_ptr<InternalStorage>()));
}
// static
@@ -173,26 +235,40 @@ scoped_ptr<SchemaOwner> SchemaOwner::Parse(const std::string& content,
return scoped_ptr<SchemaOwner>();
}
- scoped_ptr<SchemaOwner> impl(new SchemaOwner(NULL));
- impl->root_ = impl->Parse(*dict, error);
- if (!impl->root_)
- impl.reset();
- return impl.PassAs<SchemaOwner>();
+ scoped_ptr<InternalStorage> storage =
+ InternalStorage::ParseSchema(*dict, error);
+ if (!storage)
+ return scoped_ptr<SchemaOwner>();
+ const SchemaData* data = storage->schema_data();
+ return make_scoped_ptr(new SchemaOwner(data, storage.Pass()));
}
-const internal::SchemaNode* SchemaOwner::Parse(
- const base::DictionaryValue& schema,
- std::string* error) {
+// static
+scoped_ptr<SchemaOwner::InternalStorage>
+SchemaOwner::InternalStorage::ParseSchema(const base::DictionaryValue& schema,
+ std::string* error) {
+ scoped_ptr<InternalStorage> storage(new InternalStorage);
+ if (storage->Parse(schema, error) == kInvalid)
+ return scoped_ptr<InternalStorage>();
+ SchemaData* data = &storage->schema_data_;
+ data->schema_nodes = vector_as_array(&storage->schema_nodes_);
+ data->property_nodes = vector_as_array(&storage->property_nodes_);
+ data->properties_nodes = vector_as_array(&storage->properties_nodes_);
+ return storage.Pass();
+}
+
+int SchemaOwner::InternalStorage::Parse(const base::DictionaryValue& schema,
+ std::string* error) {
std::string type_string;
if (!schema.GetString(json_schema_constants::kType, &type_string)) {
*error = "The schema type must be declared.";
- return NULL;
+ return kInvalid;
}
base::Value::Type type = base::Value::TYPE_NULL;
if (!SchemaTypeToValueType(type_string, &type)) {
*error = "Type not supported: " + type_string;
- return NULL;
+ return kInvalid;
}
if (type == base::Value::TYPE_DICTIONARY)
@@ -200,79 +276,87 @@ const internal::SchemaNode* SchemaOwner::Parse(
if (type == base::Value::TYPE_LIST)
return ParseList(schema, error);
- internal::SchemaNode* node = new internal::SchemaNode;
- node->type = type;
- node->extra = NULL;
- schema_nodes_.push_back(node);
- return node;
+ int index = static_cast<int>(schema_nodes_.size());
+ schema_nodes_.push_back(SchemaNode());
+ SchemaNode& node = schema_nodes_.back();
+ node.type = type;
+ node.extra = kInvalid;
+ return index;
}
-const internal::SchemaNode* SchemaOwner::ParseDictionary(
+// static
+int SchemaOwner::InternalStorage::ParseDictionary(
const base::DictionaryValue& schema,
std::string* error) {
- internal::PropertiesNode* properties_node = new internal::PropertiesNode;
- properties_node->begin = NULL;
- properties_node->end = NULL;
- properties_node->additional = NULL;
- properties_nodes_.push_back(properties_node);
+ // Note: recursive calls to Parse() invalidate iterators and references into
+ // the vectors.
+
+ // Reserve an index for this dictionary at the front, so that the root node
+ // is at index 0.
+ int schema_index = static_cast<int>(schema_nodes_.size());
+ schema_nodes_.push_back(SchemaNode());
+
+ int extra = static_cast<int>(properties_nodes_.size());
+ properties_nodes_.push_back(PropertiesNode());
+ properties_nodes_[extra].begin = kInvalid;
+ properties_nodes_[extra].end = kInvalid;
+ properties_nodes_[extra].additional = kInvalid;
const base::DictionaryValue* dict = NULL;
+ if (schema.GetDictionary(json_schema_constants::kAdditionalProperties,
+ &dict)) {
+ int additional = Parse(*dict, error);
+ if (additional == kInvalid)
+ return kInvalid;
+ properties_nodes_[extra].additional = additional;
+ }
+
const base::DictionaryValue* properties = NULL;
if (schema.GetDictionary(json_schema_constants::kProperties, &properties)) {
- internal::PropertyNode* property_nodes =
- new internal::PropertyNode[properties->size()];
- property_nodes_.push_back(property_nodes);
+ int base_index = static_cast<int>(property_nodes_.size());
+ // This reserves nodes for all of the |properties|, and makes sure they
+ // are contiguous. Recursive calls to Parse() will append after these
+ // elements.
+ property_nodes_.resize(base_index + properties->size());
- size_t index = 0;
+ int index = base_index;
for (base::DictionaryValue::Iterator it(*properties);
!it.IsAtEnd(); it.Advance(), ++index) {
// This should have been verified by the JSONSchemaValidator.
CHECK(it.value().GetAsDictionary(&dict));
- const internal::SchemaNode* sub_schema = Parse(*dict, error);
- if (!sub_schema)
- return NULL;
- std::string* key = new std::string(it.key());
- keys_.push_back(key);
- property_nodes[index].key = key->c_str();
- property_nodes[index].schema = sub_schema;
+ int extra = Parse(*dict, error);
+ if (extra == kInvalid)
+ return kInvalid;
+ strings_.push_back(new std::string(it.key()));
+ property_nodes_[index].key = strings_.back()->c_str();
+ property_nodes_[index].schema = extra;
}
- CHECK_EQ(properties->size(), index);
- properties_node->begin = property_nodes;
- properties_node->end = property_nodes + index;
- }
-
- if (schema.GetDictionary(json_schema_constants::kAdditionalProperties,
- &dict)) {
- const internal::SchemaNode* sub_schema = Parse(*dict, error);
- if (!sub_schema)
- return NULL;
- properties_node->additional = sub_schema;
+ CHECK_EQ(static_cast<int>(properties->size()), index - base_index);
+ properties_nodes_[extra].begin = base_index;
+ properties_nodes_[extra].end = index;
}
- internal::SchemaNode* schema_node = new internal::SchemaNode;
- schema_node->type = base::Value::TYPE_DICTIONARY;
- schema_node->extra = properties_node;
- schema_nodes_.push_back(schema_node);
- return schema_node;
+ schema_nodes_[schema_index].type = base::Value::TYPE_DICTIONARY;
+ schema_nodes_[schema_index].extra = extra;
+ return schema_index;
}
-const internal::SchemaNode* SchemaOwner::ParseList(
- const base::DictionaryValue& schema,
- std::string* error) {
+// static
+int SchemaOwner::InternalStorage::ParseList(const base::DictionaryValue& schema,
+ std::string* error) {
const base::DictionaryValue* dict = NULL;
if (!schema.GetDictionary(json_schema_constants::kItems, &dict)) {
*error = "Arrays must declare a single schema for their items.";
- return NULL;
+ return kInvalid;
}
- const internal::SchemaNode* items_schema_node = Parse(*dict, error);
- if (!items_schema_node)
- return NULL;
-
- internal::SchemaNode* schema_node = new internal::SchemaNode;
- schema_node->type = base::Value::TYPE_LIST;
- schema_node->extra = items_schema_node;
- schema_nodes_.push_back(schema_node);
- return schema_node;
+ int extra = Parse(*dict, error);
+ if (extra == kInvalid)
+ return kInvalid;
+ int index = static_cast<int>(schema_nodes_.size());
+ schema_nodes_.push_back(SchemaNode());
+ schema_nodes_[index].type = base::Value::TYPE_LIST;
+ schema_nodes_[index].extra = extra;
+ return index;
}
} // namespace policy
« no previous file with comments | « components/policy/core/common/schema.h ('k') | components/policy/core/common/schema_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698