pion-net  4.0.9
PionBlob.hpp
1 // -----------------------------------------------------------------------
2 // pion-common: a collection of common libraries used by the Pion Platform
3 // -----------------------------------------------------------------------
4 // Copyright (C) 2007-2009 Atomic Labs, Inc. (http://www.atomiclabs.com)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #ifndef __PION_PIONBLOB_HEADER__
11 #define __PION_PIONBLOB_HEADER__
12 
13 #include <string>
14 #include <boost/detail/atomic_count.hpp>
15 #include <boost/functional/hash.hpp>
16 #include <pion/PionConfig.hpp>
17 
18 
19 namespace pion { // begin namespace pion
20 
21 
26 template <typename CharType, typename AllocType>
27 class PionBlob {
28 protected:
29 
31  struct BlobData {
33  BlobData(AllocType& blob_alloc, const std::size_t len) :
34  m_alloc_ptr(&blob_alloc), m_len(len), m_copies(0)
35  {
36  *((CharType*)(this) + sizeof(struct BlobData) + len) = '\0';
37  }
38 
40  inline const CharType *get(void) const {
41  return ((CharType*)(this) + sizeof(struct BlobData));
42  }
43 
45  inline CharType *get(void) {
46  return ((CharType*)(this) + sizeof(struct BlobData));
47  }
48 
50  AllocType * const m_alloc_ptr;
51 
53  const std::size_t m_len;
54 
56  boost::detail::atomic_count m_copies;
57  };
58 
61 
62 
70  static inline BlobData *create(AllocType& blob_alloc, const std::size_t len) {
71  BlobData *blob_ptr = new (blob_alloc.malloc(len+sizeof(struct BlobData)+1))
72  BlobData(blob_alloc, len);
73  return blob_ptr;
74  }
75 
79  inline void release(void) {
80  if (m_blob_ptr) {
81  if (m_blob_ptr->m_copies == 0) {
82  m_blob_ptr->m_alloc_ptr->free(m_blob_ptr, m_blob_ptr->m_len+sizeof(struct BlobData)+1);
83  } else {
85  }
86  m_blob_ptr = NULL;
87  }
88  }
89 
93  inline BlobData *grab(void) const {
94  if (m_blob_ptr) {
96  return m_blob_ptr;
97  } else {
98  return NULL;
99  }
100  }
101 
102 
103 public:
104 
106  struct BlobParams {
108  BlobParams(AllocType& blob_alloc, const CharType *ptr, const std::size_t len)
109  : m_alloc(blob_alloc), m_ptr(ptr), m_len(len)
110  {}
111  // data parameters for constructing a PionBlob
112  AllocType& m_alloc;
113  const CharType * m_ptr;
114  std::size_t m_len;
115  };
116 
118  virtual ~PionBlob() {
119  release();
120  }
121 
123  PionBlob(void) :
124  m_blob_ptr(NULL)
125  {}
126 
132  PionBlob(const PionBlob& blob) :
133  m_blob_ptr(blob.grab())
134  {}
135 
141  PionBlob(const BlobParams& p) :
142  m_blob_ptr(NULL)
143  {
144  m_blob_ptr = create(p.m_alloc, p.m_len);
145  memcpy(m_blob_ptr->get(), p.m_ptr, p.m_len);
146  }
147 
155  PionBlob(AllocType& blob_alloc, const CharType* ptr, const std::size_t len) :
156  m_blob_ptr(NULL)
157  {
158  m_blob_ptr = create(blob_alloc, len);
159  memcpy(m_blob_ptr->get(), ptr, len);
160  }
161 
168  PionBlob(AllocType& blob_alloc, const std::string& str) :
169  m_blob_ptr(NULL)
170  {
171  m_blob_ptr = create(blob_alloc, str.size());
172  memcpy(m_blob_ptr->get(), str.c_str(), str.size());
173  }
174 
182  inline PionBlob& operator=(const PionBlob& blob) {
183  release();
184  m_blob_ptr = blob.grab();
185  return *this;
186  }
187 
193  inline void set(const BlobParams& p) {
194  release();
195  m_blob_ptr = create(p.m_alloc, p.m_len);
196  memcpy(m_blob_ptr->get(), p.m_ptr, p.m_len);
197  }
198 
206  inline void set(AllocType& blob_alloc, const CharType* ptr, const std::size_t len) {
207  release();
208  m_blob_ptr = create(blob_alloc, len);
209  memcpy(m_blob_ptr->get(), ptr, len);
210  }
211 
218  inline void set(AllocType& blob_alloc, const std::string& str) {
219  release();
220  m_blob_ptr = create(blob_alloc, str.size());
221  memcpy(m_blob_ptr->get(), str.c_str(), str.size());
222  }
223 
232  inline CharType *reserve(AllocType& blob_alloc, const std::size_t len) {
233  release();
234  m_blob_ptr = create(blob_alloc, len);
235  return m_blob_ptr->get();
236  }
237 
239  inline const CharType *get(void) const {
240  return (m_blob_ptr ? m_blob_ptr->get() : "");
241  }
242 
244  inline std::size_t size(void) const {
245  return (m_blob_ptr ? (m_blob_ptr->m_len) : 0);
246  }
247 
249  inline std::size_t length(void) const {
250  return size();
251  }
252 
254  inline bool empty(void) const {
255  return (m_blob_ptr == NULL || m_blob_ptr->m_len == 0);
256  }
257 
259  inline long use_count(void) const {
260  return (m_blob_ptr == NULL ? 0 : m_blob_ptr->m_copies + 1);
261  }
262 
264  inline bool unique(void) const {
265  return (m_blob_ptr == NULL || m_blob_ptr->m_copies == 0);
266  }
267 
269  inline void clear(void) { release(); }
270 
272  inline void reset(void) { release(); }
273 
275  inline bool operator==(const PionBlob& blob) const {
276  if (size() != blob.size())
277  return false;
278  return (empty() || m_blob_ptr==blob.m_blob_ptr || memcmp(get(), blob.get(), m_blob_ptr->m_len)==0);
279  }
280 
282  inline bool operator==(const std::string& str) const {
283  if (size() != str.size())
284  return false;
285  return (empty() || memcmp(get(), str.c_str(), m_blob_ptr->m_len)==0);
286  }
287 
289  inline bool operator!=(const PionBlob& blob) const {
290  return ! (this->operator==(blob));
291  }
292 
294  inline bool operator!=(const std::string& str) const {
295  return ! (this->operator==(str));
296  }
297 
299  inline bool operator<(const PionBlob& blob) const {
300  const std::size_t len = (size() < blob.size() ? size() : blob.size());
301  if (len > 0) {
302  const int val = memcmp(get(), blob.get(), len);
303  if (val < 0)
304  return true;
305  if (val > 0)
306  return false;
307  }
308  return (size() < blob.size());
309  }
310 
312  inline bool operator>(const PionBlob& blob) const {
313  const std::size_t len = (size() < blob.size() ? size() : blob.size());
314  if (len > 0) {
315  const int val = memcmp(get(), blob.get(), len);
316  if (val > 0)
317  return true;
318  if (val < 0)
319  return false;
320  }
321  return (size() > blob.size());
322  }
323 
325  inline bool operator<(const std::string& str) const {
326  const std::size_t len = (size() < str.size() ? size() : str.size());
327  if (len > 0) {
328  const int val = memcmp(get(), str.c_str(), len);
329  if (val < 0)
330  return true;
331  if (val > 0)
332  return false;
333  }
334  return (size() < str.size());
335  }
336 
338  inline bool operator>(const std::string& str) const {
339  const std::size_t len = (size() < str.size() ? size() : str.size());
340  if (len > 0) {
341  const int val = memcmp(get(), str.c_str(), len);
342  if (val > 0)
343  return true;
344  if (val < 0)
345  return false;
346  }
347  return (size() > str.size());
348  }
349 };
350 
351 
353 template <typename CharType, typename AllocType>
354 static inline std::size_t hash_value(const PionBlob<CharType,AllocType>& blob) {
355  return (blob.empty() ? 0 : boost::hash_range(blob.get(), blob.get() + blob.size()));
356 }
357 
358 
362  inline unsigned long getValue(unsigned char c) const {
363  unsigned long result;
364  switch(c) {
365  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
366  result = (c - 48);
367  break;
368  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
369  result = (c - 87);
370  break;
371  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
372  result = (c - 55);
373  break;
374  default:
375  result = 0;
376  break;
377  }
378  return result;
379  }
380 
382  template <typename CharType, typename AllocType>
383  inline std::size_t operator()(const PionBlob<CharType,AllocType>& blob) const {
384  if (blob.size() != 36) // sanity check
385  return hash_value(blob);
386 
387  const char * const data = blob.get();
388  unsigned long n;
389  std::size_t seed = 0;
390 
391  // calculate first ulong value
392  n = (getValue(data[0]) << 28);
393  n |= (getValue(data[1]) << 24);
394  n |= (getValue(data[2]) << 20);
395  n |= (getValue(data[3]) << 16);
396  n |= (getValue(data[4]) << 12);
397  n |= (getValue(data[5]) << 8);
398  n |= (getValue(data[6]) << 4);
399  n |= getValue(data[7]);
400  boost::hash_combine(seed, n);
401 
402  // calculate second ulong value
403  n = (getValue(data[9]) << 28);
404  n |= (getValue(data[10]) << 24);
405  n |= (getValue(data[11]) << 20);
406  n |= (getValue(data[12]) << 16);
407  n |= (getValue(data[14]) << 12);
408  n |= (getValue(data[15]) << 8);
409  n |= (getValue(data[16]) << 4);
410  n |= getValue(data[17]);
411  boost::hash_combine(seed, n);
412 
413  // calculate third ulong value
414  n = (getValue(data[19]) << 28);
415  n |= (getValue(data[20]) << 24);
416  n |= (getValue(data[21]) << 20);
417  n |= (getValue(data[22]) << 16);
418  n |= (getValue(data[24]) << 12);
419  n |= (getValue(data[25]) << 8);
420  n |= (getValue(data[26]) << 4);
421  n |= getValue(data[27]);
422  boost::hash_combine(seed, n);
423 
424  // calculate third ulong value
425  n = (getValue(data[28]) << 28);
426  n |= (getValue(data[29]) << 24);
427  n |= (getValue(data[30]) << 20);
428  n |= (getValue(data[31]) << 16);
429  n |= (getValue(data[32]) << 12);
430  n |= (getValue(data[33]) << 8);
431  n |= (getValue(data[34]) << 4);
432  n |= getValue(data[35]);
433  boost::hash_combine(seed, n);
434 
435  return seed;
436  }
437 
438 #ifdef _MSC_VER
439  //This code is needed for stdext::hash_map
440 
441  enum {
442  bucket_size = 4, // 0 < bucket_size
443  min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N
444  };
445 
446  template <typename CharType, typename AllocType>
447  bool operator()(const PionBlob<CharType, AllocType>& _Keyval1, const PionBlob<CharType, AllocType>& _Keyval2) const {
448  return _Keyval1 < _Keyval2;
449  }
450 #endif
451 };
452 
453 
454 } // end namespace pion
455 
456 #endif
data type used to initialize blobs in variants without copy construction
Definition: PionBlob.hpp:106
bool unique(void) const
returns true if this is a unique instance or if this is null
Definition: PionBlob.hpp:264
unsigned long getValue(unsigned char c) const
helper for hex-&gt;int conversion
Definition: PionBlob.hpp:362
void clear(void)
alias for release() -&gt; switch to empty state
Definition: PionBlob.hpp:269
bool operator>(const PionBlob &blob) const
returns true if this is greater than blob
Definition: PionBlob.hpp:312
PionBlob(AllocType &blob_alloc, const std::string &str)
Definition: PionBlob.hpp:168
std::size_t length(void) const
returns length of the BLOB in octets (alias for size())
Definition: PionBlob.hpp:249
bool operator>(const std::string &str) const
returns true if this is greater than str
Definition: PionBlob.hpp:338
BlobData * grab(void) const
Definition: PionBlob.hpp:93
bool operator==(const PionBlob &blob) const
returns true if str is equal to this (BLOB matches string)
Definition: PionBlob.hpp:275
PionBlob(const PionBlob &blob)
Definition: PionBlob.hpp:132
PionBlob & operator=(const PionBlob &blob)
Definition: PionBlob.hpp:182
optimized hash function object for PionBlob objects which contain PionId string representations (bb49...
Definition: PionBlob.hpp:360
std::size_t size(void) const
returns size of the BLOB in octets
Definition: PionBlob.hpp:244
const CharType * get(void) const
returns (const) reference to the BLOB payload
Definition: PionBlob.hpp:40
bool operator!=(const std::string &str) const
returns true if str is not equal to this (BLOB does not match string)
Definition: PionBlob.hpp:294
bool empty(void) const
returns true if the BLOB is empty (undefined or size == 0)
Definition: PionBlob.hpp:254
void set(AllocType &blob_alloc, const CharType *ptr, const std::size_t len)
Definition: PionBlob.hpp:206
void release(void)
Definition: PionBlob.hpp:79
bool operator<(const PionBlob &blob) const
returns true if this is less than blob
Definition: PionBlob.hpp:299
structure used to store BLOB metadata; payload starts immediately following this
Definition: PionBlob.hpp:31
void reset(void)
alias for release() -&gt; switch to empty state
Definition: PionBlob.hpp:272
bool operator==(const std::string &str) const
returns true if str is equal to this (BLOB matches string)
Definition: PionBlob.hpp:282
std::size_t operator()(const PionBlob< CharType, AllocType > &blob) const
returns hash value for the blob provided
Definition: PionBlob.hpp:383
AllocType *const m_alloc_ptr
pointer to the allocator used by the BLOB
Definition: PionBlob.hpp:50
const CharType * get(void) const
returns (const) reference to the BLOB payload
Definition: PionBlob.hpp:239
BlobData(AllocType &blob_alloc, const std::size_t len)
constructor takes allocator and size (in octets) of BLOB
Definition: PionBlob.hpp:33
CharType * reserve(AllocType &blob_alloc, const std::size_t len)
Definition: PionBlob.hpp:232
long use_count(void) const
returns the number of reference to this BLOB (or 0 if this is null)
Definition: PionBlob.hpp:259
bool operator!=(const PionBlob &blob) const
returns true if blob is not equal to this (two BLOBs do not match)
Definition: PionBlob.hpp:289
PionBlob(const BlobParams &p)
Definition: PionBlob.hpp:141
void set(AllocType &blob_alloc, const std::string &str)
Definition: PionBlob.hpp:218
void set(const BlobParams &p)
Definition: PionBlob.hpp:193
boost::detail::atomic_count m_copies
number of copies referencing this BLOB
Definition: PionBlob.hpp:56
const std::size_t m_len
size of the BLOB, in octets
Definition: PionBlob.hpp:53
static BlobData * create(AllocType &blob_alloc, const std::size_t len)
Definition: PionBlob.hpp:70
PionBlob(AllocType &blob_alloc, const CharType *ptr, const std::size_t len)
Definition: PionBlob.hpp:155
BlobData * m_blob_ptr
pointer to the BLOB metadata structure (payload follows the structure)
Definition: PionBlob.hpp:60
BlobParams(AllocType &blob_alloc, const CharType *ptr, const std::size_t len)
constructor requires all parameters
Definition: PionBlob.hpp:108
virtual ~PionBlob()
virtual destructor
Definition: PionBlob.hpp:118
bool operator<(const std::string &str) const
returns true if this is less than str
Definition: PionBlob.hpp:325
PionBlob(void)
default constructor
Definition: PionBlob.hpp:123