Turi Create  4.0
blob.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_BLOB_HPP
7 #define TURI_BLOB_HPP
8 
9 #include <cstring>
10 #include <cstdlib>
11 #include <cassert>
12 
13 #include <core/storage/serialization/iarchive.hpp>
14 #include <core/storage/serialization/oarchive.hpp>
15 #include <core/storage/serialization/vector.hpp>
16 #include <core/storage/serialization/map.hpp>
17 
18 namespace turi {
19  /**
20  * blob is the general representation of a "block" of information.
21  *. 'data' must be exactly 'length' bytes and must be entirely
22  * self contained. It must not hold references to other memory
23  * regions. That is to say, I should be able read off exactly
24  * 'length' bytes from 'data', and send it across a network/write it
25  * to a disk/etc, and the information should still be consistent
26  * The blob is self-managed and will free and delete the underlying memory
27  * when it goes out of scope.
28  */
29  class blob {
30  size_t size_; /// number of bytes of the 'data' field
31  void* data_; /// user information
32  public:
33 
34  /** Create an empty blob */
35  blob() : size_(0), data_(NULL) { }
36 
37  /** Create simple blob of a certain size (with allocation)*/
38  blob(size_t new_size) :
39  size_(0), data_(NULL) {
40  resize(new_size);
41  } // end of basic blob constructor
42 
43  /** Makes a copy of the ptr provided */
44  blob(size_t osize, void* odata) : size_(0), data_(NULL) {
45  if (osize > 0) { copy(osize, odata); }
46  } // end of basic blob constructor
47 
48  /** Copy constructor */
49  blob(const blob &b) : size_(0), data_(NULL) {
50  if (b.size_ != 0 && b.data_ != NULL) {
51  copy(b);
52  }
53  }
54 
55  ~blob() { clear(); }
56 
57  /** Smart Casting */
58  template<typename T>
59  T& as() {
60  assert(data_ != NULL);
61  assert(sizeof(T) <= size_);
62  return *reinterpret_cast<T*>(data_);
63  }
64 
65  /** Smart Casting */
66  template<typename T>
67  const T& as() const {
68  assert(data_ != NULL);
69  assert(sizeof(T) <= size_);
70  return *reinterpret_cast<T*>(data_);
71  }
72 
73  /** Smart Casting */
74  template<typename T>
75  T* as_ptr() {
76  assert(data_ != NULL);
77  assert(sizeof(T) <= size_);
78  return reinterpret_cast<T*>(data_);
79  }
80 
81  /** Smart Casting */
82  template<typename T>
83  const T* as_ptr() const {
84  assert(data_ != NULL);
85  assert(sizeof(T) <= size_);
86  return reinterpret_cast<const T*>(data_);
87  }
88 
89  /** Get the size of the blob */
90  size_t size() const { return size_; }
91 
92  /** Get the size of the blob */
93  void* data() { return data_; }
94 
95  /** Get the size of the blob */
96  const void* data() const { return data_; }
97 
98 
99 
100  blob& operator=(const blob& b){
101  copy(b);
102  return *this;
103  }
104 
105 
106 
107  /** make a copy of the data passed in as arguments. */
108  void copy(size_t osize, void* odata) {
109  resize(osize);
110  // Copy the contents over
111  memcpy(data_, odata, osize);
112  }
113 
114  /** Make "deep" copy of the blob by replicate its binary data */
115  void copy(const blob& other) {
116  assert(other.size_ == 0 || other.data_ != NULL);
117  // Do an allocation (which is only done if necessary)
118  resize(other.size_);
119  // Copy the contents over
120  memcpy(data_, other.data_, size_);
121  }
122 
123  /** deprecated. Just use operator= */
124  blob copy() const{
125  return *this;
126  }
127  /** Resize the blob to any size including 0 */
128  void resize(size_t new_size) {
129  if(new_size == 0) {
130  // if resize to zero then just clear
131  clear();
132  } else if(size_ == new_size ) {
133  // if resize to current size then nop
134  assert(data_ != NULL);
135  } else {
136  clear();
137  assert(data_ == NULL && size_ == 0);
138  size_ = new_size;
139  data_ = malloc(new_size);
140  assert(data_ != NULL);
141  }
142  } // end of malloc
143 
144 
145  /** free the memory associated with this blob */
146  void clear() {
147  if(data_ != NULL) {
148  assert(size_ > 0);
149  free(data_);
150  data_ = NULL;
151  }
152  size_ = 0;
153  } // end of free
154 
155 
156  /** Swaps the contents of two blobs. A "safe" version of a shallow copy */
157  void swap(blob &b) {
158  void* tmp = b.data_;
159  size_t tmpsize = b.size_;
160 
161  b.data_ = data_;
162  b.size_ = size_;
163 
164  data_ = tmp;
165  size_ = tmpsize;
166  }
167 
168  void load(iarchive& arc) {
169  clear();
170  arc >> size_;
171  if (size_ == 0) {
172  data_ = NULL;
173  } else {
174  data_ = malloc(size_);
175  deserialize(arc, data_, size_);
176  }
177  }
178 
179  void save(oarchive& arc) const {
180  arc << size_;
181  if (size_ != 0) {
182  serialize(arc, data_, size_);
183  }
184  }
185  }; // end of blob
186 
187 
188 } // end of namespace
189 #endif
blob(size_t osize, void *odata)
Definition: blob.hpp:44
T * as_ptr()
Definition: blob.hpp:75
void resize(size_t new_size)
Definition: blob.hpp:128
The serialization input archive object which, provided with a reference to an istream, will read from the istream, providing deserialization capabilities.
Definition: iarchive.hpp:60
void clear()
Definition: blob.hpp:146
blob(size_t new_size)
Definition: blob.hpp:38
const T & as() const
Definition: blob.hpp:67
blob(const blob &b)
Definition: blob.hpp:49
void copy(const blob &other)
Definition: blob.hpp:115
blob()
user information
Definition: blob.hpp:35
size_t size() const
Definition: blob.hpp:90
const void * data() const
Definition: blob.hpp:96
void * data()
Definition: blob.hpp:93
void copy(size_t osize, void *odata)
Definition: blob.hpp:108
blob copy() const
Definition: blob.hpp:124
void swap(blob &b)
Definition: blob.hpp:157
T & as()
Definition: blob.hpp:59
The serialization output archive object which, provided with a reference to an ostream, will write to the ostream, providing serialization capabilities.
Definition: oarchive.hpp:80
const T * as_ptr() const
Definition: blob.hpp:83