lib/datahash/datahash.h

Go to the documentation of this file.
00001 /*
00002  * datahash.h
00003  *
00004  * Copyright (C) 2004-2006,2008,2009,2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * A basic recursive text-based data structure.  Optimized for small-ish
00032  * objects (a few 10's of KB at most)
00033  */
00034 
00035 #ifndef WAVEPACKET_DATAHASH_H__
00036 #define WAVEPACKET_DATAHASH_H__
00037 
00038 
00039 // includes --------------------------------------------------------------------
00040 #include "common/common.h"
00041 #include "threadsafe/smart_ptr.h"
00042 #include "threadsafe/threadsafe_multimap.h"
00043 
00044 
00045 /// \ingroup datahash_top
00046 /*@{*/
00047 
00048 
00049 ////////////////////////////////////////////////////////////////////////////////
00050 ///
00051 ///     \defgroup datahash Datahash API
00052 ///
00053 ///     Datahash object plus supporting serialization/deserialization and
00054 ///     other utilities.
00055 ///
00056 ////////////////////////////////////////////////////////////////////////////////
00057 /*@{*/
00058 
00059 
00060 /// is the given key valid?  there are restrictions on key formats
00061 bool isValidHashKeyName(IN const char * key_name) throw();
00062 
00063 /// throw an exception if the given key is not valid
00064 void validateHashKeyName(IN const char * key_name);
00065 
00066 
00067 enum eHashDataType {
00068         eHashDataType_String    = 1,    ///< simple text string value
00069         eHashDataType_Hash      = 2,    ///< subhash
00070 
00071         // keep this last
00072         eHashDataType_Invalid   = 0
00073 };
00074 
00075 
00076 class Datahash;         // forward declaration
00077 
00078 
00079 struct hash_value_t {
00080         // constructor, manipulators
00081         hash_value_t(IN const char * txt);
00082         hash_value_t(IN const std::string& s);
00083         hash_value_t(IN smart_ptr<Datahash>& h);
00084         hash_value_t(void) throw() { this->clear(); }
00085 
00086         void clear(void) throw();
00087 
00088         // data fields
00089         eHashDataType           type;
00090         std::string             text;
00091         smart_ptr<Datahash>     hash;
00092 };
00093 
00094 
00095 
00096 ////////////////////////////////////////////////////////////////////////////////
00097 ///
00098 ///     Basic datahash object
00099 ///
00100 ///     A recursive hash structure that supports key/value access, where there
00101 ///     are (in general) multiple values for a given key.  Keys are either
00102 ///     simple (a single value is a single string) or complex (a single value
00103 ///     is itself another hash).
00104 ///
00105 ////////////////////////////////////////////////////////////////////////////////
00106 class Datahash : public threadsafe_multimap<std::string, hash_value_t> {
00107 private:
00108         typedef threadsafe_multimap<std::string, hash_value_t> base_map_t;
00109 
00110 public:
00111         // we overload insert so we can validate keys
00112         void insert(IN const char * key, IN const hash_value_t& hv) {
00113                         validateHashKeyName(key);
00114                         base_map_t::insert(key, hv);
00115                 }
00116 
00117         void insert(IN const std::string& key, IN const hash_value_t& hv) {
00118                         validateHashKeyName(key.c_str());
00119                         base_map_t::insert(key, hv);
00120                 }
00121 
00122         // friendly insert routines
00123         void insert(IN const char * key, IN const char * value) {
00124                         hash_value_t hv;
00125                         hv.type = eHashDataType_String;
00126                         hv.text = value;
00127                         this->insert(key, hv);
00128                 }
00129 
00130         void insert(IN const char * key, IN smart_ptr<Datahash>& subHash) {
00131                         hash_value_t hv;
00132                         hv.type = eHashDataType_Hash;
00133                         hv.hash = subHash;
00134                         this->insert(key, hv);
00135                 }
00136 
00137         // const-safe API
00138         int count(IN const char * key) const throw() {
00139                         return nonConst()->count(key);
00140                 }
00141 
00142         void getIterator(OUT iterator_t& i) const throw() {
00143                         nonConst()->getIterator(i);
00144                 }
00145 
00146         void getIterator(IN const char * key, OUT iterator_t& i) const throw() {
00147                         nonConst()->getIterator(key, i);
00148                 }
00149 
00150         const hash_value_t * getNextElementUnsafe(IO iterator_t& i,
00151                                         OUT std::string& key) const throw() {
00152                         return nonConst()->getNextElementUnsafe(i, key);
00153                 }
00154 
00155         const hash_value_t * getNextElementUnsafe(IO iterator_t& i) const throw() {
00156                         std::string key;
00157                         return nonConst()->getNextElementUnsafe(i, key);
00158                 }
00159 
00160         // helper factory method
00161         static smart_ptr<Datahash> create(void) { return new Datahash; }
00162 
00163 private:
00164         // yuck!  Nasty hack to get around const problems.  The threadsafe
00165         //      multimap is technically never const, because accessors need
00166         //      to hold the mutex, which involves changing state.  However,
00167         //      other than temporarily holding the mutex, some operations are
00168         //      const-safe.  Therefore, this method (and the above const
00169         //      wrappers) allow some methods to be called as if the hash was
00170         //      truly const.
00171         threadsafe_multimap<std::string, hash_value_t> * nonConst(void) const throw() {
00172                         return (Datahash *) this;
00173                 }
00174 };
00175 
00176 
00177 /*@}*/  // end of documentation group
00178 
00179 
00180 #endif  // WAVEPACKET_DATAHASH_H__
00181