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 Oct 26 18:25:59 2004 for s11n by  doxygen 1.3.9.1