Savarese Software Research Corporation
utility/Properties.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WSPR_UTILITY_PROPERTIES_H
00023 #define __SSRC_WSPR_UTILITY_PROPERTIES_H
00024 
00025 #include <boost/variant.hpp>
00026 #include <boost/serialization/variant.hpp>
00027 #include <boost/serialization/vector.hpp>
00028 #include <boost/serialization/split_member.hpp>
00029 #include <boost/ptr_container/serialize_ptr_map.hpp>
00030 #include <boost/ptr_container/serialize_ptr_vector.hpp>
00031 #include <cstdint>
00032 #include <climits>
00033 #include <string>
00034 #include <vector>
00035 #include <utility>
00036 #include <cstdarg>
00037 
00038 #include <ssrc/wispers/utility/properties_ptr.h>
00039 // <boost/serialization/shared_ptr.hpp> leaks memmory (as of boost 1.41.0)
00040 // and implements features unrequired by Wispers.
00041 #include <ssrc/wispers/utility/serialize_shared_ptr.h>
00042 
00043 __BEGIN_NS_SSRC_WSPR_UTILITY
00044 
00045 template<typename T>
00046 struct PropTreeValueOps {
00047   typedef T value_type;
00048   typedef T storage_type;
00049 
00050   storage_type copy(const value_type & t) const {
00051     return t;
00052   }
00053 
00054   void assign(storage_type & s, const value_type & t) const {
00055     s = t;
00056   }
00057 
00058   bool equal(const storage_type & a, const storage_type & b) const {
00059     return (a == b);
00060   }
00061 
00062   void free(const storage_type & t) const { }
00063 
00064   const storage_type & initial_value() const {
00065     return DefaultValue;
00066   }
00067 
00068 private:
00069   static const value_type DefaultValue;
00070 };
00071 
00072 template<typename T> typename PropTreeValueOps<T>::value_type const
00073 PropTreeValueOps<T>::DefaultValue = typename PropTreeValueOps<T>::value_type();
00074 
00075 template<typename T>
00076 struct PropTreePointerOps {
00077   typedef T value_type;
00078   typedef T* storage_type;
00079 
00080   storage_type copy(const value_type & t) const {
00081     return new value_type(t);
00082   }
00083 
00084   storage_type copy(const storage_type & t) const {
00085     if(t == 0)
00086       return 0;
00087     return copy(*t);
00088   }
00089 
00090   void assign(storage_type & s, const value_type & v) const {
00091     if(s != 0) {
00092       *s = v;
00093     } else {
00094       s = copy(v);
00095     }
00096   }
00097 
00098   bool equal(const storage_type a, const storage_type b) const {
00099     if(a != 0 && b != 0)
00100       return (*a == *b);
00101     return (a == b);
00102   }
00103 
00104   void free(storage_type t) const {
00105     delete t;
00106   }
00107 
00108   void assign(storage_type & s, const storage_type & v) const {
00109     if(s != 0) {
00110       if(v != 0) {
00111         *s = *v;
00112       } else {
00113         free(s);
00114         s = 0;
00115       }
00116     } else {
00117       s = copy(v);
00118     }
00119   }
00120 
00121   storage_type initial_value() const {
00122     return 0;
00123   }
00124 };
00125 
00126 template<typename Key, typename Ops, typename TreeType>
00127 class PropTree {
00128 public:
00129   typedef Key key_type;
00130   typedef TreeType tree_type;
00131   typedef Ops operations;
00132   typedef typename operations::value_type value_type;
00133   typedef typename operations::storage_type storage_type;
00134 
00135   typedef boost::ptr_map<key_type, tree_type> child_container;
00136   typedef typename child_container::iterator child_container_iterator;
00137   typedef typename child_container::const_iterator child_container_const_iterator;
00138   typedef typename child_container::size_type size_type;
00139   typedef std::pair<child_container_iterator, bool> insert_result_type;
00140 
00141 protected:
00142 
00143   static const operations Value;
00144 
00145   storage_type _value;
00146   child_container _children;
00147 
00148 public:
00149 
00150   PropTree() : _value(Value.initial_value()) { }
00151 
00152   explicit PropTree(const value_type & v) : _value(Value.copy(v)) { }
00153 
00154   // PropTree should not be used as a polymorphic base class.
00155   /*virtual*/ ~PropTree() {
00156     Value.free(_value);
00157   }
00158 
00159   void clear() {
00160     _children.clear();
00161   }
00162 
00163   bool is_leaf() const {
00164     return _children.empty();
00165   }
00166 
00167   const storage_type & value() const {
00168     return _value;
00169   }
00170 
00171   storage_type & value() {
00172     return _value;
00173   }
00174 
00175   void set_value(const value_type & v) {
00176     Value.assign(_value, v);
00177   }
00178 
00179   child_container_const_iterator child_begin() const {
00180     return _children.begin();
00181   }
00182 
00183   child_container_const_iterator child_end() const {
00184     return _children.end();
00185   }
00186 
00187   tree_type * find(const key_type & key) {
00188     child_container_iterator && it = _children.find(key);
00189     if(it == _children.end())
00190       return 0;
00191     return it->second;
00192   }
00193 
00194   template<typename... P>
00195   tree_type * find(const key_type & key, const P & ...p) {
00196     child_container_iterator && it = _children.find(key);
00197     if(it == _children.end()) {
00198       return 0;
00199     }
00200     return it->second->find(p...);
00201   }
00202 
00203   const tree_type * find(const key_type & key) const {
00204     child_container_const_iterator && it = _children.find(key);
00205     if(it == _children.end())
00206       return 0;
00207     return it->second;
00208   }
00209 
00210   template<typename... P>
00211   const tree_type * find(const key_type & key, const P & ...p) const {
00212     child_container_const_iterator && it = _children.find(key);
00213     if(it == _children.end()) {
00214       return 0;
00215     }
00216     return it->second->find(p...);
00217   }
00218 
00219   tree_type * set(const value_type & val, const key_type & key) {
00220     tree_type *tree = find(key);
00221 
00222     if(tree != 0) {
00223       tree->set_value(val);
00224     } else {
00225       // const_cast works around ptr_map design without using std::auto_ptr
00226       //_children.insert(key, std::auto_ptr<tree_type>(new tree_type(val)));
00227       _children.insert(const_cast<key_type &>(key), (tree = new tree_type(val)));
00228     }
00229 
00230     return tree;
00231   }
00232 
00233   template<typename... P>
00234   tree_type *
00235   set(const value_type & val, const key_type & key, const P & ...p) {
00236     tree_type *tree = find(key);
00237 
00238     if(tree == 0) {
00239       // const_cast works around ptr_map design without using std::auto_ptr
00240       //_children.insert(key, std::auto_ptr<tree_type>(tree = new tree_type));
00241       _children.insert(const_cast<key_type &>(key), (tree = new tree_type));
00242     }
00243 
00244     return tree->set(val, p...);
00245   }
00246 
00247   tree_type * create_node(const key_type & key) {
00248     tree_type *tree = find(key);
00249 
00250     if(tree == 0) {
00251       // const_cast works around ptr_map design without using std::auto_ptr
00252       //_children.insert(key, std::auto_ptr<tree_type>(new tree_type));
00253       _children.insert(const_cast<key_type &>(key), (tree = new tree_type));
00254     }
00255 
00256     return tree;
00257   }
00258 
00259   template<typename... P>
00260   tree_type *
00261   create_node(const key_type & key, const P & ...p) {
00262     tree_type *tree = find(key);
00263 
00264     if(tree == 0) {
00265       // const_cast works around ptr_map design without using std::auto_ptr
00266       //_children.insert(key, std::auto_ptr<tree_type>(tree = new tree_type));
00267       _children.insert(const_cast<key_type &>(key), (tree = new tree_type));
00268     }
00269 
00270     return tree->create_node(p...);
00271   }
00272 
00273   size_type erase(const key_type & key) {
00274     return _children.erase(key);
00275   }
00276 
00277   template<typename... P>
00278   size_type erase(const key_type & key, const P & ...p) {
00279     tree_type *tree = find(key);
00280 
00281     if(tree != 0) {
00282       return tree->erase(p...);
00283     }
00284 
00285     return 0;
00286   }
00287 
00288   // Visitor must define enter and leave functions.
00289   template<typename Visitor>
00290   void visit(const Visitor & v) {
00291     for(child_container_iterator && it = _children.begin(),
00292           && end = _children.end(); it != end;)
00293     {
00294       child_container_iterator child = it++;
00295       tree_type *tree = child->second;
00296       v.enter(child->first, tree, (it == end));
00297       if(!tree->is_leaf()) {
00298         tree->visit(v);
00299       }
00300       v.leave(child->first, tree, (it == end));
00301     }
00302   }
00303 
00304   template<typename Visitor>
00305   void visit(const Visitor & v) const {
00306     for(child_container_const_iterator && it = _children.begin(),
00307           && end = _children.end(); it != end;)
00308     {
00309       child_container_const_iterator child = it++;
00310       const tree_type *tree = child->second;
00311       v.enter(child->first, tree, (it == end));
00312       if(!tree->is_leaf()) {
00313         tree->visit(v);
00314       }
00315       v.leave(child->first, tree, (it == end));
00316     }
00317   }
00318 
00319   bool operator==(const tree_type & p) const {
00320     if(!Value.equal(_value, p._value))
00321       return false;
00322 
00323     if(_children.size() != p._children.size())
00324       return false;
00325 
00326     child_container_const_iterator && it1 = _children.begin(),
00327       && it2 = p._children.begin(), && end1 = _children.end();
00328 
00329     while(it1 != end1) {
00330       if(it1->first != it2->first || !(*(it1->second) == *(it2->second)))
00331         return false;
00332       ++it1;
00333       ++it2;
00334     }
00335 
00336     return true;
00337   }
00338 
00339   // WARNING!  This is a destructive merge with move semantics!
00340   void merge(tree_type && p) {
00341     if(!Value.equal(_value, p._value)) {
00342       Value.free(_value);
00343       _value = p._value;
00344       p._value = Value.initial_value();
00345     }
00346 
00347     child_container_iterator && it1 = _children.begin(),
00348       && it2 = p._children.begin(), && end1 = _children.end(),
00349       && end2 = p._children.end();
00350 
00351     while(it2 != end2) {
00352       if(it1 == end1) {
00353         _children.transfer(it2, end2, p._children);
00354         break;
00355       } else if(it1->first == it2->first) {
00356         it1->second->merge(std::move(*it2->second));
00357         ++it1;
00358         ++it2;
00359       } else if(it1->first > it2->first) {
00360         _children.transfer(it2, p._children);
00361         ++it2;
00362       } else {
00363         ++it1;
00364       }
00365     }
00366   }
00367 
00368   // Non-destructive merge.
00369   void merge(const tree_type & p) {
00370     if(!Value.equal(_value, p._value)) {
00371       Value.assign(_value, p._value);
00372     }
00373 
00374     child_container_iterator && it1 = _children.begin(),
00375       && end1 = _children.end();
00376     child_container_const_iterator && it2 = p._children.begin(),
00377       && end2 = p._children.end();
00378 
00379     while(it2 != end2) {
00380       if(it1 == end1) {
00381         _children.insert(it2, end2);
00382         break;
00383       } else if(it1->first == it2->first) {
00384         it1->second->merge(*it2->second);
00385         ++it1;
00386         ++it2;
00387       } else if(it1->first > it2->first) {
00388         child_container_const_iterator pos = it2;
00389         _children.insert(pos, ++it2);
00390       } else {
00391         ++it1;
00392       }
00393     }
00394   }
00395 
00396   // These functions exist for the benefit of SWIG wrappers.  Do not
00397   // call from C++ code.  Use variadic templates instead.
00398   tree_type * va_set(const value_type & val, const std::va_list & ap) {
00399     key_type *key;
00400     tree_type *tree = static_cast<tree_type*>(this);
00401 
00402     while((key = va_arg(ap, key_type *)) != 0) {
00403       child_container & children = tree->_children;
00404       tree = tree->find(*key);
00405 
00406       if(tree == 0) {
00407         children.insert(*key, (tree = new tree_type));
00408         //children.insert(*key, std::auto_ptr<tree_type>(new tree_type));
00409       }
00410     }
00411 
00412     tree->set_value(val);
00413 
00414     return tree;
00415   }
00416 
00417   tree_type * va_list_find(const key_type *key, const std::va_list & ap) {
00418     tree_type *tree = static_cast<tree_type*>(this);
00419 
00420     do {
00421       if((tree = tree->find(*key)) == 0) {
00422         return 0;
00423       }
00424     } while((key = va_arg(ap, const key_type *)) != 0);
00425 
00426     return tree;
00427   }
00428 
00429   tree_type * va_find(const key_type *key, ...) {
00430     std::va_list ap;
00431 
00432     va_start(ap, key);
00433 
00434     tree_type *result = va_list_find(key, ap);
00435 
00436     va_end(ap);
00437 
00438     return result;
00439   }
00440 
00441   // These functions exist for supporting keys serialized as a sequence
00442   // of tokens, making it impossible to call a multi-argument function.
00443   template<typename Iterator>
00444   tree_type * iterator_set(const value_type & val,
00445                            const Iterator & begin,
00446                            const Iterator & end)
00447   {
00448     tree_type *tree = static_cast<tree_type*>(this);
00449 
00450     for(Iterator key = begin; key != end; ++key) {
00451       child_container & children = tree->_children;
00452       tree = tree->find(*key);
00453 
00454       if(tree == 0) {
00455         children.insert(const_cast<key_type &>(*key), (tree = new tree_type));
00456         //children.insert(*key, std::auto_ptr<tree_type>(new tree_type));
00457       }
00458     }
00459 
00460     tree->set_value(val);
00461 
00462     return tree;
00463   }
00464   template<typename Iterator>
00465   size_type iterator_erase(const Iterator & begin,
00466                            const Iterator & end)
00467   {
00468     tree_type *tree = static_cast<tree_type*>(this);
00469     tree_type *parent = 0;
00470     Iterator last_key;
00471 
00472     for(Iterator key = begin; key != end; ++key) {
00473       parent = tree;
00474       if((tree = tree->find(*key)) == 0) {
00475         return 0;
00476       }
00477       last_key = key;
00478     }
00479 
00480     if(parent) {
00481       return parent->erase(*last_key);
00482     }
00483 
00484     return 0;
00485   }
00486 
00487   template<typename Iterator>
00488   tree_type * iterator_find(const Iterator & begin, const Iterator & end) {
00489     tree_type *tree = static_cast<tree_type*>(this);
00490 
00491     for(Iterator key = begin; key != end; ++key) {
00492       if((tree = tree->find(*key)) == 0) {
00493         return 0;
00494       }
00495     }
00496 
00497     return tree;
00498   }
00499 
00500   template<typename Iterator>
00501   const tree_type * 
00502   iterator_find(const Iterator & begin, const Iterator & end) const {
00503     const tree_type *tree = static_cast<const tree_type*>(this);
00504 
00505     for(Iterator key = begin; key != end; ++key) {
00506       if((tree = tree->find(*key)) == 0) {
00507         return 0;
00508       }
00509     }
00510 
00511     return tree;
00512   }
00513 
00514   // Serialization support.
00515   template<class Archive>
00516   void save(Archive & ar, const unsigned int) const {
00517     ar << _value << _children;
00518   }
00519 
00520   template<class Archive>
00521   void load(Archive & ar, const unsigned int) {
00522     Value.free(_value);
00523     _value = Value.initial_value();
00524     ar >> _value >> _children;
00525   }
00526 
00527   BOOST_SERIALIZATION_SPLIT_MEMBER()
00528 };
00529 
00530 template<typename K, typename T, typename Tr>
00531 typename PropTree<K, T, Tr>::operations
00532 const PropTree<K, T, Tr>::Value = typename PropTree<K, T, Tr>::operations();
00533 
00534 enum PropertyType {
00535   PropertyBool,
00536   PropertyInt,
00537   PropertyUInt,
00538   PropertyInt64,
00539   PropertyUInt64,
00540   PropertyDouble,
00541   PropertyString,
00542   PropertyPrimitiveArray,
00543   PropertyArray
00544 };
00545 
00546 typedef
00547 boost::variant<bool, std::int32_t, std::uint32_t,
00548                std::int64_t, std::uint64_t, double,
00549                std::string>
00550 primitive_property_type;
00551 
00552 class Properties;
00553 
00554 typedef std::vector<primitive_property_type> primitive_property_vector;
00555 typedef boost::ptr_vector<Properties> property_vector;
00556 
00557 typedef
00558 boost::variant<bool, std::int32_t, std::uint32_t,
00559                std::int64_t, std::uint64_t, double,
00560                std::string, primitive_property_vector, property_vector>
00561 property_type;
00562 
00563 template<typename T>
00564 class property_type_value_extractor : public boost::static_visitor<void> {
00565   T* & value;
00566 
00567 public:
00568 
00569   property_type_value_extractor(T* & value) : value(value) { }
00570 
00571   void operator()(T & v) const { value = &v; }
00572 
00573   template<typename V>
00574   void operator()(V & v) const { value = 0; }
00575 };
00576 
00577 
00578 class Properties : public PropTree<std::string,
00579                                     PropTreePointerOps<property_type>,
00580                                     Properties>
00581 {
00582 public:
00583   typedef
00584   PropTree<std::string, PropTreePointerOps<property_type>, Properties> super;
00585 
00586   Properties() { }
00587 
00588   explicit Properties(const value_type & v) : super(v) { }
00589 
00590   Properties(const Properties & p) {
00591 #ifdef WSPR_DEBUG
00592     std::cerr << "Properties non-move const copy constructor called\n";
00593 #endif
00594     if(p._value != 0) {
00595       set_value(*p._value);
00596     } else {
00597       Value.free(_value);
00598       _value = 0;
00599     }
00600     _children = p._children.clone();
00601   }
00602 
00603   Properties & operator=(const Properties & p) {
00604 #ifdef WSPR_DEBUG
00605     std::cerr << "Properties non-move assignment operator called\n";
00606 #endif
00607     if(p._value != 0) {
00608       set_value(*p._value);
00609     } else {
00610       Value.free(_value);
00611       _value = 0;
00612     }
00613     _children = p._children.clone();
00614     return *this;
00615   }
00616 
00617   // Begin move semantics.
00618   explicit Properties(Properties && p) {
00619     _value = p._value;
00620     p._value = 0;
00621     _children = p._children.release();
00622   }
00623 
00624   Properties & operator=(Properties && p) {
00625     Value.free(_value);
00626     _value = p._value;
00627     p._value = 0;
00628     _children = p._children.release();
00629     return *this;
00630   }
00631   // End move semantics.
00632 
00633   bool is_null() const {
00634     return (_value == 0);
00635   }
00636 
00637   // Work around conversion of string literal values to bool by automatic
00638   // type coercion in choosing variant constructor.
00639   template<typename... P>
00640   Properties * set(const char * const val, const P & ...p) {
00641     return super::set(std::string(val), p...);
00642   }
00643 
00644   // Disambiguate type conversions.
00645 #if (LONG_MAX == INT_MAX)
00646   template<typename... P>
00647   Properties * set(const long val, const P & ...p) {
00648     return super::set(static_cast<std::int32_t>(val), p...);
00649   }
00650 
00651   template<typename... P>
00652   Properties * set(const unsigned long val, const P & ...p) {
00653     return super::set(static_cast<std::uint32_t>(val), p...);
00654   }
00655 #endif
00656 
00657   template<typename... P>
00658   Properties * set(const char val, const P & ...p) {
00659     return super::set(static_cast<std::int32_t>(val), p...);
00660   }
00661 
00662   template<typename... P>
00663   Properties * set(const signed char val, const P & ...p) {
00664     return super::set(static_cast<std::int32_t>(val), p...);
00665   }
00666 
00667   template<typename... P>
00668   Properties * set(const unsigned char val, const P & ...p) {
00669     return super::set(static_cast<std::uint32_t>(val), p...);
00670   }
00671 
00672   template<typename... P>
00673   Properties * set(const bool val, const P & ...p) {
00674     return super::set(val, p...);
00675   }
00676 
00677   template<typename... P>
00678   Properties * set(const std::int32_t val, const P & ...p) {
00679     return super::set(val, p...);
00680   }
00681 
00682   template<typename... P>
00683   Properties * set(const std::uint32_t val, const P & ...p) {
00684     return super::set(val, p...);
00685   }
00686 
00687   template<typename... P>
00688   Properties * set(const std::int16_t val, const P & ...p) {
00689     return super::set(static_cast<std::int32_t>(val), p...);
00690   }
00691 
00692   template<typename... P>
00693   Properties * set(const std::uint16_t val, const P & ...p) {
00694     return super::set(static_cast<std::int32_t>(val), p...);
00695   }
00696 
00697   template<typename... P>
00698   Properties * set(const std::int64_t val, const P & ...p) {
00699     return super::set(val, p...);
00700   }
00701 
00702   template<typename... P>
00703   Properties * set(const std::uint64_t val, const P & ...p) {
00704     return super::set(val, p...);
00705   }
00706 
00707   template<typename... P>
00708   Properties * set(const float val, const P & ...p) {
00709     return super::set(static_cast<double>(val), p...);
00710   }
00711 
00712   template<typename... P>
00713   Properties * set(const double val, const P & ...p) {
00714     return super::set(val, p...);
00715   }
00716 
00717   template<typename... P>
00718   Properties * set(const value_type & val, const P & ...p) {
00719     return super::set(val, p...);
00720   }
00721 
00722   // Do same for iterator_set.
00723   template<typename Iterator>
00724   Properties * iterator_set(const char * const val,
00725                             const Iterator & begin,
00726                             const Iterator & end)
00727  {
00728     return super::iterator_set(std::string(val), begin, end);
00729   }
00730 
00731 #if (LONG_MAX == INT_MAX)
00732   template<typename Iterator>
00733   Properties * iterator_set(const long val,
00734                             const Iterator & begin,
00735                             const Iterator & end)
00736  {
00737     return super::iterator_set(static_cast<std::int32_t>(val), begin, end);
00738   }
00739 
00740   template<typename Iterator>
00741   Properties * iterator_set(const unsigned long val,
00742                             const Iterator & begin,
00743                             const Iterator & end)
00744  {
00745     return super::iterator_set(static_cast<std::uint32_t>(val), begin, end);
00746   }
00747 #endif
00748 
00749   template<typename Iterator>
00750   Properties * iterator_set(const char val,
00751                             const Iterator & begin,
00752                             const Iterator & end)
00753   {
00754     return super::iterator_set(static_cast<std::int32_t>(val), begin, end);
00755   }
00756 
00757   template<typename Iterator>
00758   Properties * iterator_set(const signed char val,
00759                             const Iterator & begin,
00760                             const Iterator & end)
00761   {
00762     return super::iterator_set(static_cast<std::int32_t>(val), begin, end);
00763   }
00764 
00765   template<typename Iterator>
00766   Properties * iterator_set(const unsigned char val,
00767                             const Iterator & begin,
00768                             const Iterator & end)
00769   {
00770     return super::iterator_set(static_cast<std::uint32_t>(val), begin, end);
00771   }
00772 
00773   template<typename Iterator>
00774   Properties * iterator_set(const bool val,
00775                             const Iterator & begin,
00776                             const Iterator & end)
00777   {
00778     return super::iterator_set(val, begin, end);
00779   }
00780 
00781   template<typename Iterator>
00782   Properties * iterator_set(const std::int32_t val,
00783                             const Iterator & begin,
00784                             const Iterator & end)
00785   {
00786     return super::iterator_set(val, begin, end);
00787   }
00788 
00789   template<typename Iterator>
00790   Properties * iterator_set(const std::uint32_t val,
00791                             const Iterator & begin,
00792                             const Iterator & end)
00793   {
00794     return super::iterator_set(val, begin, end);
00795   }
00796 
00797   template<typename Iterator>
00798   Properties * iterator_set(const std::int64_t val,
00799                             const Iterator & begin,
00800                             const Iterator & end)
00801   {
00802     return super::iterator_set(val, begin, end);
00803   }
00804 
00805   template<typename Iterator>
00806   Properties * iterator_set(const std::uint64_t val,
00807                             const Iterator & begin,
00808                             const Iterator & end)
00809   {
00810     return super::iterator_set(val, begin, end);
00811   }
00812 
00813   template<typename Iterator>
00814   Properties * iterator_set(const float val,
00815                             const Iterator & begin,
00816                             const Iterator & end)
00817   {
00818     return super::iterator_set(static_cast<double>(val), begin, end);
00819   }
00820 
00821   template<typename Iterator>
00822   Properties * iterator_set(const double val,
00823                             const Iterator & begin,
00824                             const Iterator & end)
00825   {
00826     return super::iterator_set(val, begin, end);
00827   }
00828 
00829   template<typename Iterator>
00830   Properties * iterator_set(const value_type & val,
00831                             const Iterator & begin,
00832                             const Iterator & end)
00833   {
00834     return super::iterator_set(val, begin, end);
00835   }
00836 
00837   template<typename T>
00838   T* get_ptr() const {
00839     T* result = 0;
00840 
00841     if(_value != 0) {
00842       boost::apply_visitor(property_type_value_extractor<T>(result), *_value);
00843     }
00844 
00845     return result;
00846   }
00847 
00848   template<typename T, typename... P>
00849   T* get_ptr(const P & ...p) const {
00850     const Properties *result = find(p...);
00851 
00852     if(result != 0)
00853       return result->get_ptr<T>();
00854 
00855     return 0;
00856   }
00857 
00858   property_vector & create_property_vector() {
00859     set_value(property_vector());
00860     return *get_ptr<property_vector>();
00861   }
00862 
00863   template<typename... P>
00864   property_vector & create_property_vector(const P & ...p) {
00865     return *(set(property_vector(), p...)->get_ptr<property_vector>());
00866   }
00867 
00868   primitive_property_vector & create_primitive_property_vector() {
00869     set_value(primitive_property_vector());
00870     return *get_ptr<primitive_property_vector>();
00871   }
00872 
00873   template<typename... P>
00874   primitive_property_vector & create_primitive_property_vector(const P & ...p) {
00875     return *(set(primitive_property_vector(), p...)->get_ptr<primitive_property_vector>());
00876   }
00877 
00878   template<typename T>
00879   const T & get(const T & default_value = T()) const {
00880     T* result = get_ptr<T>();
00881 
00882     if(result != 0) {
00883       return (*result);
00884     }
00885 
00886     return default_value;
00887   }
00888 
00889   template<typename T, typename... P>
00890   const T & get(const T & default_value, const P & ...p) const {
00891     T* result = get_ptr<T>(p...);
00892 
00893     if(result != 0)
00894       return (*result);
00895 
00896     return default_value;
00897   }
00898 
00899   // These functions exist for the benefit of SWIG wrappers.  Do not
00900   // call from C++ code.  Use variadic templates instead.
00901 
00902   template<typename T>
00903   void va_set(const T & val, ...) {
00904     std::va_list ap;
00905 
00906     va_start(ap, val);
00907 
00908     super::va_set(val, ap);
00909 
00910     va_end(ap);
00911   }
00912 
00913   template<class Archive>
00914   void serialize(Archive & ar, const unsigned int) {
00915     ar & boost::serialization::base_object<super>(*this);
00916   }
00917 };
00918 
00919 
00920 template<typename T, typename Archive>
00921 T load_property(Archive & ar) {
00922   T value;
00923   ar >> value;
00924   return value;
00925 }
00926 
00927 template<typename V, typename Archive>
00928 void load_property_vector(Archive & ar, property_type & p)
00929   SSRC_DECL_THROW(boost::bad_get)
00930 {
00931   p = V();
00932   ar >> boost::get<V>(p);
00933 }
00934 
00935 __END_NS_SSRC_WSPR_UTILITY
00936 
00937 // We need to specialize variant load to avoid copy of ptr_vector.
00938 // We use boost variant save unchanged.
00939 namespace boost {
00940   namespace serialization {
00941     template<class Archive>
00942     void load(Archive & ar, NS_SSRC_WSPR_UTILITY::property_type & p,
00943               const unsigned int)
00944     {
00945       using namespace NS_SSRC_WSPR_UTILITY;
00946 
00947       int which;
00948       ar >> which;
00949       switch(which) {
00950       case PropertyBool:   p = load_property<bool>(ar); break;
00951       case PropertyInt:    p = load_property<std::int32_t>(ar); break;
00952       case PropertyUInt:   p = load_property<std::uint32_t>(ar); break;
00953       case PropertyInt64:  p = load_property<std::int64_t>(ar); break;
00954       case PropertyUInt64: p = load_property<std::uint64_t>(ar); break;
00955       case PropertyDouble: p = load_property<double>(ar); break;
00956       case PropertyString: p = load_property<std::string>(ar); break;
00957       case PropertyPrimitiveArray:
00958         load_property_vector<primitive_property_vector>(ar, p);
00959         break;
00960       case PropertyArray:
00961         load_property_vector<property_vector>(ar, p);
00962         break;
00963       default:
00964         throw boost::archive::archive_exception(boost::archive::archive_exception::unsupported_version);
00965         break;
00966       };
00967     }
00968   }
00969 }
00970 
00971 BOOST_CLASS_TRACKING(NS_SSRC_WSPR_UTILITY::primitive_property_type, boost::serialization::track_never)
00972 BOOST_CLASS_TRACKING(NS_SSRC_WSPR_UTILITY::property_type, boost::serialization::track_never)
00973 BOOST_CLASS_TRACKING(NS_SSRC_WSPR_UTILITY::primitive_property_vector, boost::serialization::track_never)
00974 BOOST_CLASS_TRACKING(NS_SSRC_WSPR_UTILITY::property_vector, boost::serialization::track_never)
00975 BOOST_CLASS_TRACKING(NS_SSRC_WSPR_UTILITY::Properties, boost::serialization::track_never)
00976 
00977 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.