Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

CdbAnyTypeDict.hh

Go to the documentation of this file.
00001 #ifndef CDBBASE_ANY_TYPE_DICT_HH
00002 #define CDBBASE_ANY_TYPE_DICT_HH
00003 
00004 // File and Version Information:
00005 //      $Id: CdbAnyTypeDict.hh,v 1.2 2005/11/07 18:14:37 gapon Exp $
00006 
00007 #include "CdbBase/CdbCommon.hh"
00008 
00009 #include <map>
00010 #include <vector>
00011 
00012 /// The internal machinery of the dictionary
00013 
00014 namespace CdbAnyTypeDictImpl {
00015 
00016     struct TypeIdGenerator {
00017         static int next( ) { static int id = 0; return id++; }
00018     };
00019 
00020     template< typename T >
00021     struct Type2Id {
00022         static int id( ) { static int myId = TypeIdGenerator::next( ); return myId; }
00023     };
00024 
00025     struct HolderBase {
00026         HolderBase( int theTypeId ) : typeId(theTypeId) { }
00027         virtual ~HolderBase( ) { }
00028         virtual HolderBase* clone( ) const = 0;
00029         int typeId;
00030     };
00031 
00032     template< typename T >
00033     struct Holder : public HolderBase {
00034         Holder( T* thePtr ) : HolderBase( Type2Id<T>::id( )), ptr(thePtr) { }
00035         Holder( const Holder<T>& other ) : HolderBase( other ), ptr(new T( *other.ptr )) { }
00036         Holder<T>& operator=( const Holder<T>& other )
00037         {
00038             if( this != &other ) {
00039                 HolderBase::operator=( other );
00040                 delete ptr;
00041                 ptr = new T( *other.ptr );
00042             }
00043             return *this;
00044         }
00045         virtual ~Holder( ) { delete ptr; }
00046         virtual HolderBase* clone( ) const { return new Holder( *this ); }
00047         T* ptr;
00048     private:
00049         Holder( );
00050     };
00051 }
00052 
00053 /// A dictionary class for objects of any type
00054 /**
00055   * The class can be used to store heterogenious collections of objects.
00056   * The only template parameter of the class is:
00057   *
00058   *   K - a type of the dictionary's keys
00059   *
00060   * Objects stored in the dictionary can be of any types as long as these types
00061   * support the value semantics (meet the following minimal interface):
00062   *
00063   *   class T {
00064   *   public:
00065   *     T();
00066   *     T(const T&);
00067   *     ~T();
00068   *     T& operator=(const T&);
00069   *   };
00070   *
00071   * All keys in the dictionary are unique. A type of each object is also remembered (in some form)
00072   * by the dictionary, therefore next time, when a user will be making a query to find an object
00073   * for a certain key then the stored object's type will get compared with the one expected by
00074   * the users, and they should match. Otherwise a error code will get returned.
00075   *
00076   * Here is a simple example how to use the dictionary:
00077   *
00078   *   CdbAnyTypeDict<std::string> dict;
00079   *
00080   *   if( !dict.exists( "PI" )) {
00081   *     const double pi = 3.14;
00082   *     if( CdbStatus::Success != dict.insert( "PI", pi )) {
00083   *       cerr << "failed to insert 'PI' into the dictionary\n";
00084   *       ...
00085   *     }
00086   *   }
00087   *   if( CdbStatus::Success != dict.replace( "PI", 3.14195, false )) {
00088   *     cerr << "failed to replice 'PI' in the dictionary with a more precise value\n";
00089   *     ...
00090   *   }
00091   */
00092 template< class K >
00093 class CdbAnyTypeDict {
00094 
00095 private:
00096 
00097   /// The dictionary type for storing kay-value pairs
00098 
00099     typedef std::map<K,CdbAnyTypeDictImpl::HolderBase*> HolderBaseMap;
00100 
00101 public:
00102 
00103   /// The default constructor
00104 
00105     CdbAnyTypeDict( ) { }
00106 
00107   /// The copy constructor
00108 
00109     CdbAnyTypeDict( const CdbAnyTypeDict<K>& other )
00110     {
00111         for( typename HolderBaseMap::const_iterator itr = other._data.begin( );
00112                                                     itr != other._data.end( );
00113                                                     ++itr ) _data[itr->first] = itr->second->clone( );
00114     }
00115 
00116   /// The destructor
00117 
00118     virtual ~CdbAnyTypeDict( )
00119     {
00120         for( typename HolderBaseMap::iterator itr = _data.begin( );
00121                                               itr != _data.end( );
00122                                             ++itr ) delete itr->second;
00123     }
00124 
00125   /// The assignment operator
00126 
00127     CdbAnyTypeDict<K>& operator=( const CdbAnyTypeDict<K>& other )
00128     {
00129         if( this != &other ) {
00130             for( typename HolderBaseMap::iterator itr = _data.begin( );
00131                                                   itr != _data.end( );
00132                                                 ++itr ) delete itr->second;
00133         _data.clear( );
00134         for( typename HolderBaseMap::const_iterator itr = other._data.begin( );
00135                                                     itr != other._data.end( );
00136                                                   ++itr ) _data[itr->first] = itr->second->clone( );
00137         }
00138         return *this;
00139     }
00140 
00141   /// Check if the dictionary is empty (has no keys registered)
00142 
00143     bool empty( ) const
00144     {
00145         return _data.empty( );
00146     }
00147 
00148   /// Check if the specified key exists in the dictionary
00149 
00150     bool exists( const K& theKey ) const
00151     {
00152         typename HolderBaseMap::const_iterator itr = _data.find( theKey );
00153         return itr != _data.end( );
00154     }
00155 
00156   /// Insert the new object into the dictionary
00157   /**
00158     * The method is meant to make a copy of the input object and register it in the dictionary
00159     * with the specified key. A type of the input object will also be remembered, so that next
00160     * time when a user will be making a query for that key then the stored type will get compared
00161     * with the one expected by the user.
00162     *
00163     * The method will return CdbStatus::Error if the specified key is already known to the dictionary.
00164     */
00165     template< typename V >
00166     CdbStatus insert( const K& theKey,
00167                       const V& theValue
00168                     )
00169     {
00170         if( exists( theKey )) return CdbStatus::Error;
00171         _data[theKey] = new CdbAnyTypeDictImpl::Holder<V>( new V( theValue ));
00172         return CdbStatus::Success;
00173     }
00174 
00175   /// Replace an object in the dictionary
00176   /**
00177     * The method will replace an existing object in the dictionary for the specified key.
00178     * Depending on a value of the optional "forceCreateFlag" the key may or may not be allowed
00179     * to be missing in the dictionary prior to calling the method. If the keys is not known
00180     * and the flag is set to "false" then the CdbStatus::NotFound value will be returned. Otherwise
00181     * a new entry will be created.
00182     *
00183     * If the key is already known to the dictionary then the new object's type should match
00184     * the one stored before. Otherwise the CdbStatus::ConflictOfParameters status value will
00185     * be returned.
00186     */
00187     template< typename V >
00188     CdbStatus replace( const K&   theKey,
00189                        const V&   theValue,
00190                        const bool forceCreateFlag = true )
00191     {
00192         typename HolderBaseMap::const_iterator itr = _data.find( theKey );
00193         if( itr !=  _data.end( )) {
00194             if( itr->second->typeId != CdbAnyTypeDictImpl::Type2Id<V>::id( )) return CdbStatus::ConflictOfParameters;
00195             delete itr->second;
00196         } else {
00197             if( !forceCreateFlag) return CdbStatus::NotFound;
00198         }
00199         _data[theKey] = new CdbAnyTypeDictImpl::Holder<V>( new V( theValue ));
00200         return CdbStatus::Success;
00201     }
00202 
00203   /// Find an object in the dictionary
00204   /**
00205     * The method will try to find an existing object in the dictionary for the specified key.
00206     * If the key is not found then the CdbStatus::NotFound value will be returned.
00207     *
00208     * If the key is already known to the dictionary then the expected object's type should match
00209     * the one stored before. Otherwise the CdbStatus::ConflictOfParameters status value will
00210     * be returned.
00211     */
00212     template< typename V >
00213     CdbStatus find( const K& theKey,
00214                     V&       theValue ) const
00215     {
00216         typename HolderBaseMap::const_iterator itr = _data.find( theKey );
00217         if( itr == _data.end( )) return CdbStatus::NotFound;
00218 
00219         const CdbAnyTypeDictImpl::HolderBase* holderBasePtr = itr->second;
00220         if( holderBasePtr->typeId != CdbAnyTypeDictImpl::Type2Id<V>::id( )) return CdbStatus::ConflictOfParameters;
00221 
00222         const CdbAnyTypeDictImpl::Holder<V>* holderPtr = (const CdbAnyTypeDictImpl::Holder<V>*)holderBasePtr;
00223         theValue = V( *holderPtr->ptr );
00224 
00225         return CdbStatus::Success;
00226     }
00227 
00228   /// Get a vector of keys registered in the dictionary
00229   /**
00230     * The method would initialize and fill the specified vector with known keys.
00231     * Note that the keys will not be sorted.
00232     */
00233     void keys( std::vector<K>& theVectorOfKeys ) const
00234     {
00235         theVectorOfKeys.resize( 0 );
00236         for( typename HolderBaseMap::const_iterator itr = _data.begin( );
00237                                                     itr != _data.end( );
00238                                                   ++itr ) theVectorOfKeys.push_back( itr->first );
00239         return;
00240     }
00241 
00242 private:
00243 
00244   // The storage for keys and objects
00245 
00246     HolderBaseMap _data;
00247 };
00248 
00249 #endif  // CDBBASE_ANY_TYPE_DICT_HH

Generated on Mon Dec 5 18:21:59 2005 for CDB by doxygen1.3-rc3