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
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)
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
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
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
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
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
00426
00427 enum {
00428 bucket_size = 4,
00429 min_buckets = 8
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 }
00441
00442 #endif