Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members

property_store.h

00001 // Author: stephan beal <stephan@s11n.net> 00002 // License: Public Domain 00003 #ifndef s11n_PROPERTIESPROVIDER_H 00004 #define s11n_PROPERTIESPROVIDER_H 00005 00006 #include <iostream> 00007 #include <map> 00008 #include <sstream> 00009 #include "to_string.h" 00010 namespace s11n 00011 { 00012 /** 00013 property_store is a class for storing arbitrary key/value 00014 pairs. 00015 00016 i often find myself needing classes which contain an 00017 arbitrary number of arbitrary properties, and this 00018 interface has worked very well for me. 00019 00020 It must be strongly stressed that this class is designed 00021 solely with utility, ease-of-use and code maintenance costs 00022 in mind. Not one iota of concern has been given to 00023 optimization! It is not a lightweight object, nor is it 00024 efficient. Do not use this class when speed is of the 00025 essence! That said, it should fast enough for almost all 00026 standard property-list uses. (i often use thousands of them 00027 as property containers for game pieces.) 00028 00029 It's get() and set() template functions support 00030 any types which are both instreamable and outstreamable 00031 (implements both operator<<(std::ostream) and 00032 operator>>(std::istream)). It uses s11n::to/from_string to 00033 convert types to and from strings, so your own types will 00034 be supported as value types if they can be streamed from/to 00035 an i/ostream. 00036 00037 It follows STL container conventions, so it can be used in 00038 many container contexts and with many generic algorithms. 00039 00040 Years later... 00041 00042 This class is in need of optimization. One thought is to 00043 internally use a reference-counted string class instead of 00044 std::string, but i need to do some timings. 00045 */ 00046 class property_store 00047 { 00048 public: 00049 00050 /** 00051 The map type this object uses to store items 00052 internally. 00053 */ 00054 typedef std::map < std::string, std::string > map_type; 00055 typedef map_type::value_type value_type; 00056 00057 /** For compatibility with std::map */ 00058 typedef std::string key_type; 00059 /** For compatibility with std::map */ 00060 typedef std::string mapped_type; 00061 00062 /** 00063 For iterating over properties using STL 00064 conventions. 00065 */ 00066 typedef map_type::iterator iterator; 00067 00068 /** 00069 For iterating over properties using STL 00070 conventions. 00071 */ 00072 typedef map_type::const_iterator const_iterator; 00073 00074 /** 00075 std::string propval = props["bar"] is functionally 00076 identical to get_string("bar"). Unlike std::map and 00077 the like, calling this operator with a key which is 00078 not in the object does not create a new entry - it 00079 simply returns an empty string in that case. 00080 */ 00081 const std::string operator[] ( const std::string & key ) const; 00082 00083 /** 00084 For compatibility with std::map. Inserts a 00085 value_type (i.e., pair<string,string>) into this 00086 object. It calls set_string(), so it is compatible 00087 with subclasses which do custom handling in that 00088 method. 00089 */ 00090 void insert( const value_type & ); 00091 00092 property_store(); 00093 virtual ~ property_store(); 00094 00095 /** 00096 Returns the number of items in this object. This is 00097 a constant-time operation. 00098 */ 00099 unsigned long count_properties() const; 00100 00101 /** 00102 * Returns the value for key, or defaultVal if the key 00103 * is not set. 00104 * 00105 * Note to subclassers: This is the 00106 * "master" getter, so subclasses which want to 00107 * generically alter getXXX() behaviour need only 00108 * override this function. Almost all other getXXX() 00109 * functions call this one, so do not call them from 00110 * inside this function. 00111 */ 00112 virtual std::string get_string( const std::string & key, const std::string & defaultVal = std::string() )const; 00113 00114 /** 00115 Sets the given key to the given value. 00116 See get_string(): same notes apply here. 00117 00118 If key.empty() then this function does nothing. 00119 */ 00120 virtual void set_string( const std::string & key, const std::string & val ); 00121 00122 /** 00123 See set_string(). This function is identical except 00124 that it converts val to string before saving it. If 00125 this type conversion is not possible it will fail 00126 at compile time. A value-conversion failure, on the 00127 other hand, is not caught at compile time. 00128 */ 00129 template < typename T > void set( const std::string & key, const T & val ) 00130 { 00131 this->set_string( key, s11n::to_string( val ) ); 00132 } 00133 00134 /** 00135 The <const char *> variants of get() and set() are 00136 to help the developer avoid having to cast so much 00137 and to help out compilers which have mediocre 00138 template support. :/ 00139 */ 00140 inline void set( const char *key, const char *val ) 00141 { 00142 this->set_string( std::string( key ), std::string( val ) ); 00143 } 00144 /** 00145 Overloaded for strings-via-streams reaons. 00146 */ 00147 inline void set( const std::string & key, const char *val ) 00148 { 00149 this->set_string( key, std::string( val ) ); 00150 } 00151 /** 00152 Overloaded for strings-via-streams reaons. 00153 */ 00154 inline void set( const char *key, const std::string & val ) 00155 { 00156 this->set_string( key, std::string( val ) ); 00157 } 00158 00159 /** 00160 See get_string(). This function is identical except 00161 that the returned string is converted to type T. If 00162 this type is not possible it will fail at compile 00163 time. A value-conversion failure, on the other 00164 hand, is not caught at compile time. 00165 */ 00166 template < typename T > T get( const std::string & key, const T & val ) const 00167 { 00168 std::string foo = this->get_string( key, s11n::to_string( val ) ); 00169 return s11n::from_string( foo, val ); 00170 } 00171 00172 /** 00173 get(): see set(). Same notes apply. 00174 */ 00175 inline std::string get( const char *key, const char *val ) const 00176 { 00177 return this->get_string( std::string( key ), std::string( val ) ); 00178 } 00179 /** 00180 Overloaded for strings-via-streams reasons. 00181 */ 00182 inline std::string get( const std::string & key, const char *val ) const 00183 { 00184 return this->get_string( key, std::string( val ) ); 00185 } 00186 /** 00187 Overloaded for strings-via-streams reasons. 00188 */ 00189 inline std::string get( const char *key, const std::string & val ) const 00190 { 00191 return this->get_string( std::string( key ), val ); 00192 } 00193 00194 00195 /** 00196 Returns true if this object contains the given property. 00197 */ 00198 virtual bool is_set( const std::string & key ) const; 00199 00200 /** 00201 Removes the given property from this object. 00202 */ 00203 virtual bool unset( const std::string & key ); 00204 00205 /** 00206 Removes all entries from this object. 00207 */ 00208 bool clear_properties(); 00209 00210 00211 /** 00212 Note that the set/getTYPE() variants are mostly to 00213 keep old code working. Please use set() and get() 00214 when possible. Sometimes it is more convenient to 00215 use these instead of get()/set(), especially with 00216 something like: 00217 00218 <pre> 00219 props.set( "foo", false ); // ambiguous: may be bool, const char *, or bool or even int zero :/ 00220 </pre> 00221 00222 */ 00223 inline void set_bool( const std::string & key, bool val ) 00224 { 00225 return this->set( key, val ); 00226 } 00227 00228 /** 00229 get_bool(key) is an exception to the set/getXXX() 00230 rule: it returns true if key's value is true, as 00231 evaluated by the static function bool_val(). 00232 */ 00233 bool get_bool( const std::string & key, bool defaultVal ) const; 00234 00235 00236 00237 /** 00238 * Returns the bool value of the passed string. 00239 * The following string values are considered equal to true: 00240 * true, TRUE, True 00241 * yes, YES, Yes, y, Y 00242 * 1 00243 * Anything else evaluates to false. 00244 * CASE IS IMPORTANT! (Sorry, when i learn how to easily lowercase a c++ string 00245 * i'll fix all that.) 00246 */ 00247 static bool bool_val( const std::string & key ); 00248 00249 00250 /** 00251 * Returns the first item in the data map. 00252 * You can use this to iterate, STL-style: 00253 * <pre> 00254 * map_type::iterator it = props.begin(); 00255 * while( it != props.end() ) { ... ++it; } 00256 * </pre> 00257 * 00258 * Note that the iterator represents a 00259 * std::pair<string,string>, so use (*it).first to get 00260 * the key and (*it).second to get the value. 00261 */ 00262 iterator begin(); 00263 00264 /** 00265 Returns a const_iterator pointing at this object's first property. 00266 */ 00267 const_iterator begin() const; 00268 00269 /** 00270 * The after-the-end iterator for the data map. 00271 */ 00272 iterator end(); 00273 /** 00274 * The after-the-end iterator for the data map. 00275 */ 00276 const_iterator end() const; 00277 00278 /** 00279 * Returns end() if the key is not in our map, otherise it returns 00280 * that iterator. Use the iterator's .first member to get the key, 00281 * and .second to get the value. However, you SHOULD call get_string( (*iter).first ) 00282 * to get the value, so subclasses can do some funniness with the key, 00283 * like argv_parser does. Thus: 00284 * <pre> 00285 * std::string val = "not found"; 00286 * iter = foo.find( "key" ); 00287 * if( iter == foo.end() ) { return val; } 00288 * val = foo.get_string( (*iter).first ); 00289 * </pre> 00290 * 00291 * Such usage helps guaranty polymorphic behaviour. 00292 * 00293 * todo?: make this the master getter, instead of 00294 * get_string(), for purposes of overriding getXXX() 00295 * behaviour? 00296 */ 00297 virtual map_type::iterator find( const std::string & key ); 00298 00299 /** 00300 merge() copies all properties from src to dest. It returns the 00301 number of properties copied. 00302 00303 This is potentially a very expensive operation. 00304 */ 00305 static unsigned int merge( const property_store & src, property_store & dest ); 00306 /** 00307 Merges all properties from src into this object. Returns the number 00308 of properties merged. 00309 */ 00310 unsigned int merge( const property_store & src ); 00311 00312 00313 /** 00314 Returns the number of properties in this object. 00315 */ 00316 map_type::size_type size() const; 00317 00318 /** 00319 * Returns the internally-used map_type (see the typedefs, above). 00320 */ 00321 map_type & get_map(); 00322 /** 00323 * Returns the internally-used map_type (see the typedefs, above). 00324 */ 00325 const map_type & get_map() const; 00326 00327 00328 private: 00329 map_type m_map; 00330 }; // class property_store 00331 00332 00333 }; // namespace s11n 00334 #endif // s11n_PROPERTIESPROVIDER_H

Generated on Tue Jul 20 10:46:48 2004 for s11n by doxygen 1.3.7