Avro C++
NodeConcepts.hh
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * https://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef avro_NodeConcepts_hh__
20 #define avro_NodeConcepts_hh__
21 
22 #include "Config.hh"
23 
24 #include "Exception.hh"
25 #include <map>
26 #include <vector>
27 
28 namespace avro {
29 
46 
47 namespace concepts {
48 
49 template<typename Attribute>
50 struct NoAttribute {
51  static const bool hasAttribute = false;
52 
53  size_t size() const {
54  return 0;
55  }
56 
57  void add(const Attribute & /* attr */) {
58  // There must be an add function for the generic NodeImpl, but the
59  // Node APIs ensure that it is never called, the throw here is
60  // just in case
61  throw Exception("This type does not have attribute");
62  }
63 
64  const Attribute &get(size_t /* index */ = 0) const {
65  // There must be an get function for the generic NodeImpl, but the
66  // Node APIs ensure that it is never called, the throw here is
67  // just in case
68  throw Exception("This type does not have attribute");
69  }
70 
71  Attribute &get(size_t /* index */ = 0) {
72  // There must be an get function for the generic NodeImpl, but the
73  // Node APIs ensure that it is never called, the throw here is
74  // just in case
75  throw Exception("This type does not have attribute");
76  }
77 };
78 
79 template<typename Attribute>
81  static const bool hasAttribute = true;
82 
83  SingleAttribute() : attr_() {}
84 
85  explicit SingleAttribute(const Attribute &a) : attr_(a) {}
86  // copy constructing from another single attribute is allowed
87  SingleAttribute(const SingleAttribute<Attribute> &rhs) : attr_(rhs.attr_) {}
88 
89  // copy constructing from a no attribute is allowed
90  explicit SingleAttribute(const NoAttribute<Attribute> &rhs) : attr_() {}
91 
92  size_t size() const {
93  return 1;
94  }
95 
96  void add(const Attribute &attr) {
97  attr_ = attr;
98  }
99 
100  const Attribute &get(size_t index = 0) const {
101  if (index != 0) {
102  throw Exception("SingleAttribute has only 1 value");
103  }
104  return attr_;
105  }
106 
107  Attribute &get(size_t index = 0) {
108  if (index != 0) {
109  throw Exception("SingleAttribute has only 1 value");
110  }
111  return attr_;
112  }
113 
114 private:
115  template<typename T>
116  friend struct MultiAttribute;
117  Attribute attr_;
118 };
119 
120 template<typename Attribute>
122  static const bool hasAttribute = true;
123 
124  MultiAttribute() = default;
125 
126  // copy constructing from another single attribute is allowed, it
127  // pushes the attribute
128  explicit MultiAttribute(const SingleAttribute<Attribute> &rhs) {
129  // since map is the only type that does this we know it's
130  // final size will be two, so reserve
131  attrs_.reserve(2);
132  attrs_.push_back(rhs.attr_);
133  }
134 
135  MultiAttribute(const MultiAttribute<Attribute> &rhs) : attrs_(rhs.attrs_) {}
136 
137  explicit MultiAttribute(const NoAttribute<Attribute> &rhs) {}
138 
139  size_t size() const {
140  return attrs_.size();
141  }
142 
143  void add(const Attribute &attr) {
144  attrs_.push_back(attr);
145  }
146 
147  const Attribute &get(size_t index = 0) const {
148  return attrs_.at(index);
149  }
150 
151  Attribute &get(size_t index) {
152  return attrs_.at(index);
153  }
154 
155 private:
156  std::vector<Attribute> attrs_;
157 };
158 
159 template<typename T>
161 
162  bool lookup(const std::string &name, size_t &index) const {
163  throw Exception("Name index does not exist");
164  }
165 
166  bool add(const ::std::string &name, size_t) {
167  throw Exception("Name index does not exist");
168  }
169 };
170 
171 template<>
172 struct NameIndexConcept<MultiAttribute<std::string>> {
173  using IndexMap = std::map<std::string, size_t>;
174 
175  bool lookup(const std::string &name, size_t &index) const {
176  auto iter = map_.find(name);
177  if (iter == map_.end()) {
178  return false;
179  }
180  index = iter->second;
181  return true;
182  }
183 
184  bool add(const ::std::string &name, size_t index) {
185  bool added = false;
186  auto lb = map_.lower_bound(name);
187  if (lb == map_.end() || map_.key_comp()(name, lb->first)) {
188  map_.insert(lb, IndexMap::value_type(name, index));
189  added = true;
190  }
191  return added;
192  }
193 
194 private:
195  IndexMap map_;
196 };
197 
198 } // namespace concepts
199 } // namespace avro
200 
201 #endif
avro::concepts::MultiAttribute
Definition: NodeConcepts.hh:121
avro::concepts::NoAttribute
Definition: NodeConcepts.hh:50
avro
A bunch of templates and specializations for encoding and decoding specific types.
Definition: AvroParse.hh:30
avro::concepts::SingleAttribute
Definition: NodeConcepts.hh:80
avro::concepts::NameIndexConcept
Definition: NodeConcepts.hh:160
avro::Exception
Wrapper for std::runtime_error that provides convenience constructor for boost::format objects.
Definition: Exception.hh:31