00001
00002
00003
00004
00005
00006
00007
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 {
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
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)
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
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
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
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
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
00440
00441 enum {
00442 bucket_size = 4,
00443 min_buckets = 8
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 }
00455
00456 #endif