common/include/pion/PionBlob.hpp

00001 // -----------------------------------------------------------------------
00002 // pion-common: a collection of common libraries used by the Pion Platform
00003 // -----------------------------------------------------------------------
00004 // Copyright (C) 2007-2009 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Distributed under the Boost Software License, Version 1.0.
00007 // See http://www.boost.org/LICENSE_1_0.txt
00008 //
00009 
00010 #ifndef __PION_PIONBLOB_HEADER__
00011 #define __PION_PIONBLOB_HEADER__
00012 
00013 #include <string>
00014 #include <boost/detail/atomic_count.hpp>
00015 #include <boost/functional/hash.hpp>
00016 #include <pion/PionConfig.hpp>
00017 
00018 
00019 namespace pion {    // begin namespace pion
00020 
00021 
00026 template <typename CharType, typename AllocType>
00027 class PionBlob {
00028 protected:
00029 
00031     struct BlobData {
00033         BlobData(AllocType& blob_alloc, const std::size_t len) :
00034             m_alloc_ptr(&blob_alloc), m_len(len), m_copies(0)
00035         {
00036             *((CharType*)(this) + sizeof(struct BlobData) + len) = '\0';
00037         }
00038         
00040         inline const CharType *get(void) const {
00041             return ((CharType*)(this) + sizeof(struct BlobData));
00042         }
00043     
00045         inline CharType *get(void) {
00046             return ((CharType*)(this) + sizeof(struct BlobData));
00047         }
00048     
00050         AllocType * const               m_alloc_ptr;
00051 
00053         const std::size_t               m_len;
00054 
00056         boost::detail::atomic_count     m_copies;
00057     };
00058 
00060     BlobData *          m_blob_ptr;
00061 
00062 
00070     static inline BlobData *create(AllocType& blob_alloc, const std::size_t len) {
00071         BlobData *blob_ptr = new (blob_alloc.malloc(len+sizeof(struct BlobData)+1))
00072             BlobData(blob_alloc, len);
00073         return blob_ptr;
00074     }
00075 
00079     inline void release(void) {
00080         if (m_blob_ptr) {
00081             if (m_blob_ptr->m_copies == 0) {
00082                 m_blob_ptr->m_alloc_ptr->free(m_blob_ptr, m_blob_ptr->m_len+sizeof(struct BlobData)+1);
00083             } else {
00084                 --m_blob_ptr->m_copies;
00085             }
00086             m_blob_ptr = NULL;
00087         }
00088     }
00089 
00093     inline BlobData *grab(void) const {
00094         if (m_blob_ptr) {
00095             ++m_blob_ptr->m_copies;
00096             return m_blob_ptr;
00097         } else {
00098             return NULL;
00099         }
00100     }
00101     
00102     
00103 public:
00104 
00106     struct BlobParams {
00108         BlobParams(AllocType& blob_alloc, const CharType *ptr, const std::size_t len)
00109             : m_alloc(blob_alloc), m_ptr(ptr), m_len(len)
00110         {}
00111         // data parameters for constructing a PionBlob
00112         AllocType&          m_alloc;
00113         const CharType *    m_ptr;
00114         std::size_t         m_len;
00115     };
00116 
00118     virtual ~PionBlob() {
00119         release();
00120     }
00121 
00123     PionBlob(void) :
00124         m_blob_ptr(NULL)
00125     {}
00126 
00132     PionBlob(const PionBlob& blob) :
00133         m_blob_ptr(blob.grab())
00134     {}
00135 
00141     PionBlob(const BlobParams& p) :
00142         m_blob_ptr(NULL)
00143     {
00144         m_blob_ptr = create(p.m_alloc, p.m_len);
00145         memcpy(m_blob_ptr->get(), p.m_ptr, p.m_len);
00146     }
00147 
00155     PionBlob(AllocType& blob_alloc, const CharType* ptr, const std::size_t len) :
00156         m_blob_ptr(NULL)
00157     {
00158         m_blob_ptr = create(blob_alloc, len);
00159         memcpy(m_blob_ptr->get(), ptr, len);
00160     }
00161 
00168     PionBlob(AllocType& blob_alloc, const std::string& str) :
00169         m_blob_ptr(NULL)
00170     {
00171         m_blob_ptr = create(blob_alloc, str.size());
00172         memcpy(m_blob_ptr->get(), str.c_str(), str.size());
00173     }
00174 
00182     inline PionBlob& operator=(const PionBlob& blob) {
00183         release();
00184         m_blob_ptr = blob.grab();
00185         return *this;
00186     }
00187     
00193     inline void set(const BlobParams& p) {
00194         release();
00195         m_blob_ptr = create(p.m_alloc, p.m_len);
00196         memcpy(m_blob_ptr->get(), p.m_ptr, p.m_len);
00197     }
00198 
00206     inline void set(AllocType& blob_alloc, const CharType* ptr, const std::size_t len) {
00207         release();
00208         m_blob_ptr = create(blob_alloc, len);
00209         memcpy(m_blob_ptr->get(), ptr, len);
00210     }
00211 
00218     inline void set(AllocType& blob_alloc, const std::string& str) {
00219         release();
00220         m_blob_ptr = create(blob_alloc, str.size());
00221         memcpy(m_blob_ptr->get(), str.c_str(), str.size());
00222     }
00223 
00225     inline const CharType *get(void) const {
00226         return (m_blob_ptr ? m_blob_ptr->get() : "");
00227     }
00228 
00230     inline std::size_t size(void) const {
00231         return (m_blob_ptr ? (m_blob_ptr->m_len) : 0);
00232     }
00233 
00235     inline std::size_t length(void) const {
00236         return size();
00237     }
00238     
00240     inline bool empty(void) const {
00241         return (m_blob_ptr == NULL || m_blob_ptr->m_len == 0);
00242     }
00243     
00245     inline long use_count(void) const {
00246         return (m_blob_ptr == NULL ? 0 : m_blob_ptr->m_copies + 1);
00247     }
00248 
00250     inline bool unique(void) const {
00251         return (m_blob_ptr == NULL || m_blob_ptr->m_copies == 0);
00252     }
00253     
00255     inline void clear(void) { release(); }
00256 
00258     inline void reset(void) { release(); }
00259 
00261     inline bool operator==(const PionBlob& blob) const {
00262         if (size() != blob.size())
00263             return false;
00264         return (empty() || m_blob_ptr==blob.m_blob_ptr || memcmp(get(), blob.get(), m_blob_ptr->m_len)==0);
00265     }
00266 
00268     inline bool operator==(const std::string& str) const {
00269         if (size() != str.size())
00270             return false;
00271         return (empty() || memcmp(get(), str.c_str(), m_blob_ptr->m_len)==0);
00272     }
00273 
00275     inline bool operator!=(const PionBlob& blob) const {
00276         return ! (this->operator==(blob));
00277     }
00278 
00280     inline bool operator!=(const std::string& str) const {
00281         return ! (this->operator==(str));
00282     }
00283 
00285     inline bool operator<(const PionBlob& blob) const {
00286         const std::size_t len = (size() < blob.size() ? size() : blob.size());
00287         if (len > 0) {
00288             const int val = memcmp(get(), blob.get(), len);
00289             if (val < 0)
00290                 return true;
00291             if (val > 0)
00292                 return false;
00293         }
00294         return (size() < blob.size());
00295     }
00296         
00298     inline bool operator>(const PionBlob& blob) const {
00299         const std::size_t len = (size() < blob.size() ? size() : blob.size());
00300         if (len > 0) {
00301             const int val = memcmp(get(), blob.get(), len);
00302             if (val > 0)
00303                 return true;
00304             if (val < 0)
00305                 return false;
00306         }
00307         return (size() > blob.size());
00308     }
00309 
00311     inline bool operator<(const std::string& str) const {
00312         const std::size_t len = (size() < str.size() ? size() : str.size());
00313         if (len > 0) {
00314             const int val = memcmp(get(), str.c_str(), len);
00315             if (val < 0)
00316                 return true;
00317             if (val > 0)
00318                 return false;
00319         }
00320         return (size() < str.size());
00321     }
00322 
00324     inline bool operator>(const std::string& str) const {
00325         const std::size_t len = (size() < str.size() ? size() : str.size());
00326         if (len > 0) {
00327             const int val = memcmp(get(), str.c_str(), len);
00328             if (val > 0)
00329                 return true;
00330             if (val < 0)
00331                 return false;
00332         }
00333         return (size() > str.size());
00334     }
00335 };
00336 
00337 
00339 template <typename CharType, typename AllocType>
00340 static inline std::size_t hash_value(const PionBlob<CharType,AllocType>& blob) {
00341     return (blob.empty() ? 0 : boost::hash_range(blob.get(), blob.get() + blob.size()));
00342 }
00343 
00344 
00346 struct HashPionIdBlob {
00348     inline unsigned long getValue(unsigned char c) const {
00349         unsigned long result;
00350         switch(c) {
00351         case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
00352             result = (c - 48);
00353             break;
00354         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00355             result = (c - 87);
00356             break;
00357         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00358             result = (c - 55);
00359             break;
00360         default:
00361             result = 0;
00362             break;
00363         }
00364         return result;
00365     }
00366 
00368     template <typename CharType, typename AllocType>
00369     inline std::size_t operator()(const PionBlob<CharType,AllocType>& blob) const {
00370         if (blob.size() != 36)  // sanity check
00371             return hash_value(blob);
00372 
00373         const char * const data = blob.get();
00374         unsigned long n;
00375         std::size_t seed = 0;
00376 
00377         // calculate first ulong value
00378         n = (getValue(data[0]) << 28);
00379         n |= (getValue(data[1]) << 24);
00380         n |= (getValue(data[2]) << 20);
00381         n |= (getValue(data[3]) << 16);
00382         n |= (getValue(data[4]) << 12);
00383         n |= (getValue(data[5]) << 8);
00384         n |= (getValue(data[6]) << 4);
00385         n |= getValue(data[7]);
00386         boost::hash_combine(seed, n);
00387 
00388         // calculate second ulong value
00389         n = (getValue(data[9]) << 28);
00390         n |= (getValue(data[10]) << 24);
00391         n |= (getValue(data[11]) << 20);
00392         n |= (getValue(data[12]) << 16);
00393         n |= (getValue(data[14]) << 12);
00394         n |= (getValue(data[15]) << 8);
00395         n |= (getValue(data[16]) << 4);
00396         n |= getValue(data[17]);
00397         boost::hash_combine(seed, n);
00398         
00399         // calculate third ulong value
00400         n = (getValue(data[19]) << 28);
00401         n |= (getValue(data[20]) << 24);
00402         n |= (getValue(data[21]) << 20);
00403         n |= (getValue(data[22]) << 16);
00404         n |= (getValue(data[24]) << 12);
00405         n |= (getValue(data[25]) << 8);
00406         n |= (getValue(data[26]) << 4);
00407         n |= getValue(data[27]);
00408         boost::hash_combine(seed, n);
00409 
00410         // calculate third ulong value
00411         n = (getValue(data[28]) << 28);
00412         n |= (getValue(data[29]) << 24);
00413         n |= (getValue(data[30]) << 20);
00414         n |= (getValue(data[31]) << 16);
00415         n |= (getValue(data[32]) << 12);
00416         n |= (getValue(data[33]) << 8);
00417         n |= (getValue(data[34]) << 4);
00418         n |= getValue(data[35]);
00419         boost::hash_combine(seed, n);
00420 
00421         return seed;
00422     }
00423 
00424 #ifdef _MSC_VER
00425     //This code is needed for stdext::hash_map
00426 
00427     enum {
00428         bucket_size = 4,    // 0 < bucket_size
00429         min_buckets = 8     // min_buckets = 2 ^^ N, 0 < N
00430     };
00431 
00432     template <typename CharType, typename AllocType>
00433     bool operator()(const PionBlob<CharType, AllocType>& _Keyval1, const PionBlob<CharType, AllocType>& _Keyval2) const {
00434         return _Keyval1 < _Keyval2;
00435     }
00436 #endif
00437 };
00438 
00439 
00440 }   // end namespace pion
00441 
00442 #endif

Generated on Fri Apr 30 14:48:53 2010 for pion-net by  doxygen 1.4.7