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