# 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
    00232     inline CharType *reserve(AllocType& blob_alloc, const std::size_t len) {
    00233         release();
    00234         m_blob_ptr = create(blob_alloc, len);
    00235         return m_blob_ptr->get();
    00236     }
    00237
    00239     inline const CharType *get(void) const {
    00240         return (m_blob_ptr ? m_blob_ptr->get() : "");
    00241     }
    00242
    00244     inline std::size_t size(void) const {
    00245         return (m_blob_ptr ? (m_blob_ptr->m_len) : 0);
    00246     }
    00247
    00249     inline std::size_t length(void) const {
    00250         return size();
    00251     }
    00252
    00254     inline bool empty(void) const {
    00255         return (m_blob_ptr == NULL || m_blob_ptr->m_len == 0);
    00256     }
    00257
    00259     inline long use_count(void) const {
    00260         return (m_blob_ptr == NULL ? 0 : m_blob_ptr->m_copies + 1);
    00261     }
    00262
    00264     inline bool unique(void) const {
    00265         return (m_blob_ptr == NULL || m_blob_ptr->m_copies == 0);
    00266     }
    00267
    00269     inline void clear(void) { release(); }
    00270
    00272     inline void reset(void) { release(); }
    00273
    00275     inline bool operator==(const PionBlob& blob) const {
    00276         if (size() != blob.size())
    00277             return false;
    00278         return (empty() || m_blob_ptr==blob.m_blob_ptr || memcmp(get(), blob.get(), m_blob_ptr->m_len)==0);
    00279     }
    00280
    00282     inline bool operator==(const std::string& str) const {
    00283         if (size() != str.size())
    00284             return false;
    00285         return (empty() || memcmp(get(), str.c_str(), m_blob_ptr->m_len)==0);
    00286     }
    00287
    00289     inline bool operator!=(const PionBlob& blob) const {
    00290         return ! (this->operator==(blob));
    00291     }
    00292
    00294     inline bool operator!=(const std::string& str) const {
    00295         return ! (this->operator==(str));
    00296     }
    00297
    00299     inline bool operator<(const PionBlob& blob) const {
    00300         const std::size_t len = (size() < blob.size() ? size() : blob.size());
    00301         if (len > 0) {
    00302             const int val = memcmp(get(), blob.get(), len);
    00303             if (val < 0)
    00304                 return true;
    00305             if (val > 0)
    00306                 return false;
    00307         }
    00308         return (size() < blob.size());
    00309     }
    00310
    00312     inline bool operator>(const PionBlob& blob) const {
    00313         const std::size_t len = (size() < blob.size() ? size() : blob.size());
    00314         if (len > 0) {
    00315             const int val = memcmp(get(), blob.get(), len);
    00316             if (val > 0)
    00317                 return true;
    00318             if (val < 0)
    00319                 return false;
    00320         }
    00321         return (size() > blob.size());
    00322     }
    00323
    00325     inline bool operator<(const std::string& str) const {
    00326         const std::size_t len = (size() < str.size() ? size() : str.size());
    00327         if (len > 0) {
    00328             const int val = memcmp(get(), str.c_str(), len);
    00329             if (val < 0)
    00330                 return true;
    00331             if (val > 0)
    00332                 return false;
    00333         }
    00334         return (size() < str.size());
    00335     }
    00336
    00338     inline bool operator>(const std::string& str) const {
    00339         const std::size_t len = (size() < str.size() ? size() : str.size());
    00340         if (len > 0) {
    00341             const int val = memcmp(get(), str.c_str(), len);
    00342             if (val > 0)
    00343                 return true;
    00344             if (val < 0)
    00345                 return false;
    00346         }
    00347         return (size() > str.size());
    00348     }
    00349 };
    00350
    00351
    00353 template <typename CharType, typename AllocType>
    00354 static inline std::size_t hash_value(const PionBlob<CharType,AllocType>& blob) {
    00355     return (blob.empty() ? 0 : boost::hash_range(blob.get(), blob.get() + blob.size()));
    00356 }
    00357
    00358
    00360 struct HashPionIdBlob {
    00362     inline unsigned long getValue(unsigned char c) const {
    00363         unsigned long result;
    00364         switch(c) {
    00365         case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
    00366             result = (c - 48);
    00367             break;
    00368         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    00369             result = (c - 87);
    00370             break;
    00371         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    00372             result = (c - 55);
    00373             break;
    00374         default:
    00375             result = 0;
    00376             break;
    00377         }
    00378         return result;
    00379     }
    00380
    00382     template <typename CharType, typename AllocType>
    00383     inline std::size_t operator()(const PionBlob<CharType,AllocType>& blob) const {
    00384         if (blob.size() != 36)  // sanity check
    00385             return hash_value(blob);
    00386
    00387         const char * const data = blob.get();
    00388         unsigned long n;
    00389         std::size_t seed = 0;
    00390
    00391         // calculate first ulong value
    00392         n = (getValue(data[0]) << 28);
    00393         n |= (getValue(data[1]) << 24);
    00394         n |= (getValue(data[2]) << 20);
    00395         n |= (getValue(data[3]) << 16);
    00396         n |= (getValue(data[4]) << 12);
    00397         n |= (getValue(data[5]) << 8);
    00398         n |= (getValue(data[6]) << 4);
    00399         n |= getValue(data[7]);
    00400         boost::hash_combine(seed, n);
    00401
    00402         // calculate second ulong value
    00403         n = (getValue(data[9]) << 28);
    00404         n |= (getValue(data[10]) << 24);
    00405         n |= (getValue(data[11]) << 20);
    00406         n |= (getValue(data[12]) << 16);
    00407         n |= (getValue(data[14]) << 12);
    00408         n |= (getValue(data[15]) << 8);
    00409         n |= (getValue(data[16]) << 4);
    00410         n |= getValue(data[17]);
    00411         boost::hash_combine(seed, n);
    00412
    00413         // calculate third ulong value
    00414         n = (getValue(data[19]) << 28);
    00415         n |= (getValue(data[20]) << 24);
    00416         n |= (getValue(data[21]) << 20);
    00417         n |= (getValue(data[22]) << 16);
    00418         n |= (getValue(data[24]) << 12);
    00419         n |= (getValue(data[25]) << 8);
    00420         n |= (getValue(data[26]) << 4);
    00421         n |= getValue(data[27]);
    00422         boost::hash_combine(seed, n);
    00423
    00424         // calculate third ulong value
    00425         n = (getValue(data[28]) << 28);
    00426         n |= (getValue(data[29]) << 24);
    00427         n |= (getValue(data[30]) << 20);
    00428         n |= (getValue(data[31]) << 16);
    00429         n |= (getValue(data[32]) << 12);
    00430         n |= (getValue(data[33]) << 8);
    00431         n |= (getValue(data[34]) << 4);
    00432         n |= getValue(data[35]);
    00433         boost::hash_combine(seed, n);
    00434
    00435         return seed;
    00436     }
    00437
    00438 #ifdef _MSC_VER
    00439     //This code is needed for stdext::hash_map
    00440
    00441     enum {
    00442         bucket_size = 4,    // 0 < bucket_size
    00443         min_buckets = 8     // min_buckets = 2 ^^ N, 0 < N
    00444     };
    00445
    00446     template <typename CharType, typename AllocType>
    00447     bool operator()(const PionBlob<CharType, AllocType>& _Keyval1, const PionBlob<CharType, AllocType>& _Keyval2) const {
    00448         return _Keyval1 < _Keyval2;
    00449     }
    00450 #endif
    00451 };
    00452
    00453
    00454 }   // end namespace pion
    00455
    00456 #endif