Avro C++
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the 00007 * "License"); you may not use this file except in compliance 00008 * with the License. You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 #ifndef avro_NodeConcepts_hh__ 00020 #define avro_NodeConcepts_hh__ 00021 00022 #include "Config.hh" 00023 00024 #include <vector> 00025 #include <map> 00026 #include "Exception.hh" 00027 00028 namespace avro { 00029 00030 00047 00048 namespace concepts { 00049 00050 template <typename Attribute> 00051 struct NoAttribute 00052 { 00053 static const bool hasAttribute = false; 00054 00055 size_t size() const { 00056 return 0; 00057 } 00058 00059 void add( const Attribute &attr) { 00060 // There must be an add function for the generic NodeImpl, but the 00061 // Node APIs ensure that it is never called, the throw here is 00062 // just in case 00063 throw Exception("This type does not have attribute"); 00064 } 00065 00066 const Attribute &get(size_t index = 0) const { 00067 // There must be an get function for the generic NodeImpl, but the 00068 // Node APIs ensure that it is never called, the throw here is 00069 // just in case 00070 throw Exception("This type does not have attribute"); 00071 // even though this code is unreachable the compiler requires it 00072 static const Attribute empty = Attribute(); 00073 return empty; 00074 } 00075 00076 Attribute &get(size_t index = 0) { 00077 // There must be an get function for the generic NodeImpl, but the 00078 // Node APIs ensure that it is never called, the throw here is 00079 // just in case 00080 throw Exception("This type does not have attribute"); 00081 } 00082 00083 }; 00084 00085 template<typename Attribute> 00086 struct SingleAttribute 00087 { 00088 static const bool hasAttribute = true; 00089 00090 SingleAttribute() : attr_() 00091 { } 00092 00093 SingleAttribute(const Attribute& a) : attr_(a) { } 00094 // copy constructing from another single attribute is allowed 00095 SingleAttribute(const SingleAttribute<Attribute> &rhs) : 00096 attr_(rhs.attr_) 00097 { } 00098 00099 // copy constructing from a no attribute is allowed 00100 SingleAttribute(const NoAttribute<Attribute> &rhs) : 00101 attr_() 00102 { } 00103 00104 size_t size() const { 00105 return 1; 00106 } 00107 00108 void add(const Attribute &attr) { 00109 attr_ = attr; 00110 } 00111 00112 const Attribute &get(size_t index = 0) const { 00113 if (index != 0) { 00114 throw Exception("SingleAttribute has only 1 value"); 00115 } 00116 return attr_; 00117 } 00118 00119 Attribute &get(size_t index = 0) { 00120 if (index != 0) { 00121 throw Exception("SingleAttribute has only 1 value"); 00122 } 00123 return attr_; 00124 } 00125 00126 private: 00127 template<typename T> friend struct MultiAttribute; 00128 Attribute attr_; 00129 }; 00130 00131 template<typename Attribute> 00132 struct MultiAttribute 00133 { 00134 static const bool hasAttribute = true; 00135 00136 MultiAttribute() 00137 { } 00138 00139 // copy constructing from another single attribute is allowed, it 00140 // pushes the attribute 00141 MultiAttribute(const SingleAttribute<Attribute> &rhs) 00142 { 00143 // since map is the only type that does this we know it's 00144 // final size will be two, so reserve 00145 attrs_.reserve(2); 00146 attrs_.push_back(rhs.attr_); 00147 } 00148 00149 MultiAttribute(const MultiAttribute<Attribute> &rhs) : 00150 attrs_(rhs.attrs_) 00151 { } 00152 00153 MultiAttribute(const NoAttribute<Attribute> &rhs) 00154 {} 00155 00156 size_t size() const { 00157 return attrs_.size(); 00158 } 00159 00160 void add(const Attribute &attr) { 00161 attrs_.push_back(attr); 00162 } 00163 00164 const Attribute &get(size_t index = 0) const { 00165 return attrs_.at(index); 00166 } 00167 00168 Attribute &get(size_t index) { 00169 return attrs_.at(index); 00170 } 00171 00172 private: 00173 00174 std::vector<Attribute> attrs_; 00175 }; 00176 00177 00178 template<typename T> 00179 struct NameIndexConcept { 00180 00181 bool lookup(const std::string &name, size_t &index) const { 00182 throw Exception("Name index does not exist"); 00183 return 0; 00184 } 00185 00186 bool add(const::std::string &name, size_t index) { 00187 throw Exception("Name index does not exist"); 00188 return false; 00189 } 00190 }; 00191 00192 template<> 00193 struct NameIndexConcept < MultiAttribute<std::string> > 00194 { 00195 typedef std::map<std::string, size_t> IndexMap; 00196 00197 bool lookup(const std::string &name, size_t &index) const { 00198 IndexMap::const_iterator iter = map_.find(name); 00199 if(iter == map_.end()) { 00200 return false; 00201 } 00202 index = iter->second; 00203 return true; 00204 } 00205 00206 bool add(const::std::string &name, size_t index) { 00207 bool added = false; 00208 IndexMap::iterator lb = map_.lower_bound(name); 00209 if(lb == map_.end() || map_.key_comp()(name, lb->first)) { 00210 map_.insert(lb, IndexMap::value_type(name, index)); 00211 added = true; 00212 } 00213 return added; 00214 } 00215 00216 private: 00217 00218 IndexMap map_; 00219 }; 00220 00221 } // namespace concepts 00222 } // namespace avro 00223 00224 #endif