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