pion-net  4.0.9
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