NodeConcepts.hh

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 <vector>
00023 #include <map>
00024 #include "Exception.hh"
00025 
00026 namespace avro {
00027 
00028 
00045 
00046 namespace concepts {
00047 
00048 template <typename Attribute>
00049 struct NoAttribute
00050 {
00051     static const bool hasAttribute = false;
00052 
00053     size_t size() const {
00054         return 0;
00055     }
00056 
00057     void add( const Attribute &attr) {
00058         // There must be an add function for the generic NodeImpl, but the
00059         // Node APIs ensure that it is never called, the throw here is
00060         // just in case
00061         throw Exception("This type does not have attribute");
00062     }
00063 
00064     const Attribute &get(size_t index = 0) const {
00065         // There must be an get function for the generic NodeImpl, but the
00066         // Node APIs ensure that it is never called, the throw here is
00067         // just in case
00068         throw Exception("This type does not have attribute");
00069         // even though this code is unreachable the compiler requires it
00070         static const Attribute empty = Attribute();
00071         return empty;
00072     }
00073 
00074 };
00075 
00076 template<typename Attribute>
00077 struct SingleAttribute
00078 {
00079     static const bool hasAttribute = true;
00080 
00081     SingleAttribute() : attr_(), size_(0)
00082     { }
00083 
00084     // copy constructing from another single attribute is allowed
00085     SingleAttribute(const SingleAttribute<Attribute> &rhs) : 
00086         attr_(rhs.attr_), size_(rhs.size_)
00087     { }
00088 
00089     // copy constructing from a no attribute is allowed
00090     SingleAttribute(const NoAttribute<Attribute> &rhs) : 
00091         attr_(), size_(0)
00092     { }
00093 
00094     size_t size() const {
00095         return size_;
00096     }
00097 
00098     void add(const Attribute &attr) {
00099         if(size_ == 0) {
00100             size_ = 1;
00101         }
00102         else {
00103             throw Exception("SingleAttribute can only be set once");
00104         }
00105         attr_ = attr;
00106     }
00107 
00108     const Attribute &get(size_t index = 0) const {
00109         if(index != 0) {
00110             throw Exception("SingleAttribute has only 1 value");
00111         }
00112         return attr_;
00113     }
00114 
00115   private:
00116 
00117     template<typename T> friend class MultiAttribute;
00118 
00119     Attribute attr_;
00120     int       size_;
00121 };
00122 
00123 template<typename Attribute>
00124 struct MultiAttribute
00125 {
00126     static const bool hasAttribute = true;
00127 
00128     MultiAttribute() 
00129     { }
00130 
00131     // copy constructing from another single attribute is allowed, it
00132     // pushes the attribute
00133     MultiAttribute(const SingleAttribute<Attribute> &rhs) 
00134     { 
00135         // since map is the only type that does this we know it's
00136         // final size will be two, so reserve 
00137         attrs_.reserve(2);
00138         attrs_.push_back(rhs.attr_);
00139     }
00140 
00141     MultiAttribute(const MultiAttribute<Attribute> &rhs)  :
00142         attrs_(rhs.attrs_)
00143     { }
00144 
00145     MultiAttribute(const NoAttribute<Attribute> &rhs)
00146     {}
00147 
00148     size_t size() const {
00149         return attrs_.size();
00150     }
00151 
00152     void add(const Attribute &attr) {
00153         attrs_.push_back(attr); 
00154     }
00155 
00156     const Attribute &get(size_t index = 0) const {
00157         return attrs_.at(index);
00158     }
00159 
00160     Attribute &get(size_t index) {
00161         return attrs_.at(index);
00162     }
00163 
00164   private:
00165 
00166     std::vector<Attribute> attrs_;
00167 };
00168 
00169 
00170 template<typename T>
00171 struct NameIndexConcept {
00172 
00173     bool lookup(const std::string &name, size_t &index) const {
00174         throw Exception("Name index does not exist");
00175         return 0;
00176     }
00177 
00178     bool add(const::std::string &name, size_t index) {
00179         throw Exception("Name index does not exist");
00180         return false;
00181     }
00182 };
00183 
00184 template<>
00185 struct NameIndexConcept < MultiAttribute<std::string> > 
00186 {
00187     typedef std::map<std::string, size_t> IndexMap;
00188 
00189     bool lookup(const std::string &name, size_t &index) const {
00190         IndexMap::const_iterator iter = map_.find(name); 
00191         if(iter == map_.end()) {
00192             return false;
00193         }
00194         index = iter->second;
00195         return true;
00196     }
00197 
00198     bool add(const::std::string &name, size_t index) {
00199         bool added = false;
00200         IndexMap::iterator lb = map_.lower_bound(name); 
00201         if(lb == map_.end() || map_.key_comp()(name, lb->first)) {
00202             map_.insert(lb, IndexMap::value_type(name, index));
00203             added = true;
00204         }
00205         return added;
00206     }
00207 
00208   private:
00209 
00210     IndexMap map_;
00211 };
00212 
00213 } // namespace concepts
00214 } // namespace avro
00215 
00216 #endif