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
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.