123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifndef avro_NodeConcepts_hh__
- #define avro_NodeConcepts_hh__
- #include "Config.hh"
- #include "Exception.hh"
- #include <map>
- #include <vector>
- namespace avro {
- ///
- /// The concept classes are used to simplify NodeImpl. Since different types
- /// of avro types carry different attributes, such as names, or field names for
- /// record members. Using the concept class of NoAttribute vs Attribute, the
- /// NodeImpl object can enable/disable the attribute, but the code is the same
- /// in either case.
- ///
- /// Furthermore, attributes may have different types, for example, most
- /// attributes are strings, but fixed types have a size attribute, which is
- /// integer.
- ///
- /// Since compound types are composed of other types, the leaf attribute
- /// concepts extend a NodeImpl to include leaf nodes, and attributes for leaf
- /// nodes, which are used to build parse trees.
- ///
- ///
- namespace concepts {
- template<typename Attribute>
- struct NoAttribute {
- static const bool hasAttribute = false;
- size_t size() const {
- return 0;
- }
- void add(const Attribute & /* attr */) {
- // There must be an add function for the generic NodeImpl, but the
- // Node APIs ensure that it is never called, the throw here is
- // just in case
- throw Exception("This type does not have attribute");
- }
- const Attribute &get(size_t /* index */ = 0) const {
- // There must be an get function for the generic NodeImpl, but the
- // Node APIs ensure that it is never called, the throw here is
- // just in case
- throw Exception("This type does not have attribute");
- }
- Attribute &get(size_t /* index */ = 0) {
- // There must be an get function for the generic NodeImpl, but the
- // Node APIs ensure that it is never called, the throw here is
- // just in case
- throw Exception("This type does not have attribute");
- }
- };
- template<typename Attribute>
- struct SingleAttribute {
- static const bool hasAttribute = true;
- SingleAttribute() : attr_() {}
- explicit SingleAttribute(const Attribute &a) : attr_(a) {}
- // copy constructing from another single attribute is allowed
- SingleAttribute(const SingleAttribute<Attribute> &rhs) : attr_(rhs.attr_) {}
- // copy constructing from a no attribute is allowed
- explicit SingleAttribute(const NoAttribute<Attribute> &rhs) : attr_() {}
- size_t size() const {
- return 1;
- }
- void add(const Attribute &attr) {
- attr_ = attr;
- }
- const Attribute &get(size_t index = 0) const {
- if (index != 0) {
- throw Exception("SingleAttribute has only 1 value");
- }
- return attr_;
- }
- Attribute &get(size_t index = 0) {
- if (index != 0) {
- throw Exception("SingleAttribute has only 1 value");
- }
- return attr_;
- }
- private:
- template<typename T>
- friend struct MultiAttribute;
- Attribute attr_;
- };
- template<typename Attribute>
- struct MultiAttribute {
- static const bool hasAttribute = true;
- MultiAttribute() = default;
- // copy constructing from another single attribute is allowed, it
- // pushes the attribute
- explicit MultiAttribute(const SingleAttribute<Attribute> &rhs) {
- // since map is the only type that does this we know it's
- // final size will be two, so reserve
- attrs_.reserve(2);
- attrs_.push_back(rhs.attr_);
- }
- MultiAttribute(const MultiAttribute<Attribute> &rhs) : attrs_(rhs.attrs_) {}
- explicit MultiAttribute(const NoAttribute<Attribute> &rhs) {}
- size_t size() const {
- return attrs_.size();
- }
- void add(const Attribute &attr) {
- attrs_.push_back(attr);
- }
- const Attribute &get(size_t index = 0) const {
- return attrs_.at(index);
- }
- Attribute &get(size_t index) {
- return attrs_.at(index);
- }
- private:
- std::vector<Attribute> attrs_;
- };
- template<typename T>
- struct NameIndexConcept {
- bool lookup(const std::string &name, size_t &index) const {
- throw Exception("Name index does not exist");
- }
- bool add(const ::std::string &name, size_t) {
- throw Exception("Name index does not exist");
- }
- };
- template<>
- struct NameIndexConcept<MultiAttribute<std::string>> {
- using IndexMap = std::map<std::string, size_t>;
- bool lookup(const std::string &name, size_t &index) const {
- auto iter = map_.find(name);
- if (iter == map_.end()) {
- return false;
- }
- index = iter->second;
- return true;
- }
- bool add(const ::std::string &name, size_t index) {
- bool added = false;
- auto lb = map_.lower_bound(name);
- if (lb == map_.end() || map_.key_comp()(name, lb->first)) {
- map_.insert(lb, IndexMap::value_type(name, index));
- added = true;
- }
- return added;
- }
- private:
- IndexMap map_;
- };
- } // namespace concepts
- } // namespace avro
- #endif
|