source: source/ariba/utility/serialization/Data.hpp@ 7521

Last change on this file since 7521 was 7521, checked in by mies, 14 years ago
File size: 11.2 KB
Line 
1// [License]
2// The Ariba-Underlay Copyright
3//
4// Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
5//
6// Institute of Telematics
7// UniversitÀt Karlsruhe (TH)
8// Zirkel 2, 76128 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// The views and conclusions contained in the software and documentation
34// are those of the authors and should not be interpreted as representing
35// official policies, either expressed or implied, of the Institute of
36// Telematics.
37// [License]
38
39#ifndef DATA_HPP_
40#define DATA_HPP_
41
42//== library includes ==
43#include <stdlib.h>
44#include <iostream>
45#include <boost/cstdint.hpp>
46#include <boost/type_traits/make_unsigned.hpp>
47
48// forward declaration
49template<typename T> class DefaultDataModel;
50template<typename T = uint8_t, typename DataModel = DefaultDataModel<uint8_t> > class DataTpl;
51typedef DataTpl<> Data;
52template<typename T, typename DataModel> std::ostream& operator<<(std::ostream& stream, const DataTpl<T, DataModel>& data);
53
54//== internal includes ==
55#include "../internal/Utilities.hpp"
56
57//== local includes ==
58#include "DataUtilities.hpp"
59#include "Serialization.hpp"
60
61/**
62 * This class implements a wrapper for binary data. And this time, when the
63 * word binary is used -- it really means binary! Length and manipulation
64 * are specified and operate in bit precision. Most of the operations are
65 * highly effective using inline functions and compiler optimizations.
66 *
67 * Two versions of binaries are supported: static, non-resizeable binaries
68 * and dynamic, resizeable ones. Please note, this class does not manage
69 * memory, reference counting etc. you have to take care about memory
70 * management yourself! However you can use the <code>release()</code>
71 * to delete the underlaying array.
72 *
73 * @author Sebastian Mies
74 */
75template<typename T, typename DataModel>
76class DataTpl: public Serializeable { SERIALIZEABLE
77protected:
78 typedef DataTpl<T,DataModel> _Data;
79 DataModel model;
80
81public:
82 static const size_t word_width = sizeof(T) * 8;
83
84 class DataManipulator {
85 private:
86 DataModel bits;
87 size_t index;
88
89 public:
90 finline DataManipulator( DataModel& _bits, size_t _index) :
91 bits(_bits), index(_index) {
92 }
93
94 template<typename X>
95 finline operator X() const {
96 return bitget<X>(bits.buffer(), index);
97 }
98
99 template<typename X>
100 finline DataManipulator& operator=(X value) {
101 bitset(value, bits.buffer(), index );
102 return *this;
103 }
104
105 template<typename X>
106 finline void set(X value, size_t length = sizeof(X) * 8, if_uint(X)) {
107 bitcpy(value, 0, bits.buffer(), index, length);
108 }
109
110 template<typename X>
111 finline void set(X value, size_t length = sizeof(X) * 8, if_int(X)) {
112 set(_unsigned(value),length);
113 }
114
115 template<typename X>
116 finline void get(X& value, size_t length = sizeof(X) * 8, if_uint(X)) const {
117 value = bitget<X> (bits.buffer(), index, length);
118 }
119
120 template<typename X>
121 finline void get(X& value, size_t length = sizeof(X) * 8, if_int(X)) const {
122 typedef typename boost::make_unsigned<X>::type unsigned_type;
123 _unsigned(value) = bitget<unsigned_type> (bits.buffer(), index, length);
124 }
125
126 finline void get(bool& value) const {
127 value = bitget( bits.buffer(), index );
128 }
129 };
130
131public:
132 static const Data UNSPECIFIED;
133
134 /**
135 * Constructs a dynamic bit-data object of variable size.
136 */
137 DataTpl() : model() {
138 }
139
140 /**
141 * Contructs a copy of an existing data buffer
142 */
143 finline DataTpl(const DataTpl<T, DataModel>& copy) {
144 this->model = copy.model;
145 }
146
147 finline DataTpl( const DataModel& _model ) : model( _model ) {
148 }
149
150 /**
151 * Constructs a static bit-data object with the given buffer.
152 */
153 finline DataTpl(const T* buffer, size_t length) {
154 model.buffer() = buffer;
155 model.length() = length;
156 }
157
158 /**
159 * Constructs a dynamic bit-data object with the given buffer.
160 */
161 finline DataTpl( T* buffer, size_t length ) {
162 model.buffer() = buffer;
163 model.length() = length;
164 }
165
166 /**
167 * Constructs a dynamic bit-data object of variable size with the given
168 * initial size.
169 */
170 finline DataTpl(size_t length) : model() {
171 model.resize(length);
172 }
173
174
175 /**
176 * Returns the internal buffer of the data.
177 */
178 finline T* getBuffer() const {
179 return model.buffer();
180 }
181
182 /**
183 * Returns the length of the data in bits
184 */
185 finline size_t getLength() const {
186 return model.length();
187 }
188 /**
189 * Sets the length of the data in bits
190 */
191 void setLength(size_t new_length) {
192 model.resize(new_length);
193 }
194
195 /**
196 * Ensures that the buffer pointer has the given
197 * number of bits of memory reserved.
198 *
199 * @param neededLength The minimum data length required.
200 */
201 finline void ensureLength( size_t neededLength ) {
202 if ((int) neededLength > model.length() ) model.resize(neededLength);
203 }
204
205 /**
206 * Returns a manipulator object for a certain bit position.
207 *
208 * @param index The index in bits quantitites.
209 * @return A data manipulation object
210 */
211 finline DataManipulator operator[](size_t index) {
212 return DataManipulator(model, index);
213 }
214
215 /**
216 * Returns a constant manipulator object for a certain bit position.
217 *
218 * @param index The index in bits quantitites.
219 * @return A constant data manipulation object
220 */
221 finline const DataManipulator operator[](size_t index) const {
222 return DataManipulator(model, index);
223 }
224
225 _Data sub( size_t index, size_t length = ~0 ) {
226 if (length == ~0) length = model.length()-index;
227 return _Data(model.sub(index,length));
228 }
229
230 /**
231 * Returns a copy of the specified bit range.
232 *
233 * @param index The first bit to copy
234 * @param length The length of the bit range
235 * @return The cloned data object
236 */
237 _Data clone( size_t index, size_t length ) const {
238 DataModel new_model = model.clone(index,length);
239 return _Data(new_model);
240 }
241
242 /**
243 * Returns a copy of the data.
244 *
245 * @return A cloned data object
246 */
247 _Data clone() const {
248 DataModel new_model = model.clone( 0, model.length() );
249 return _Data(new_model);
250 }
251
252 /**
253 * Returns true, if the data is empty (zero length)
254 *
255 * @return True, if the data is empty (zero length)
256 */
257 finline bool isEmpty() const {
258 return (model.length() == 0);
259 }
260
261 /**
262 * Returns true, if the data buffer is unspecified.
263 * In this case no memory is associated with this data object.
264 *
265 * @return True, if the data buffer is unspecified.
266 */
267 finline bool isUnspecified() const {
268 return model.isUnspecified();
269 }
270
271 /**
272 * This method frees the memory associated with
273 * this data object and sets this object into an unspecified
274 * state.
275 */
276 finline void release() {
277 model.release();
278 }
279
280 // operators
281
282 /**
283 * Assigns another buffer
284 */
285 template<typename X>
286 _Data& operator= (const DataTpl<X>& source) {
287 this->model = source.model;
288 return *this;
289 }
290
291 /**
292 * Returns true, if the datas buffer's pointer and length
293 * are the same.
294 */
295 template<typename X>
296 finline bool operator==( DataTpl<X>& data) {
297 return (data.model.buffer() == model.buffer() &&
298 data.model.length() == model.length() );
299 }
300
301 finline _Data& operator&=(_Data& data) {
302 return *this;
303 }
304
305 finline _Data& operator|=(_Data& data) {
306 return *this;
307 }
308
309 finline _Data& operator^=(_Data& data) {
310 return *this;
311 }
312
313 /* implied operators */
314
315 finline _Data operator&(_Data& data) {
316 return (this->clone() &= data);
317 }
318
319 finline _Data operator|(_Data& data) {
320 return (this->clone() |= data);
321 }
322
323 finline _Data operator^(_Data& data) {
324 return (this->clone() ^= data);
325 }
326};
327
328/* unspecified type */
329template<typename T, typename DataModel>
330const Data DataTpl<T, DataModel>::UNSPECIFIED;
331
332/**
333 * This class implements the default data model
334 *
335 * @author Sebastian Mies
336 */
337template<typename _T>
338class DefaultDataModel {
339public:
340 typedef _T T;
341 typedef DefaultDataModel<T> _Model;
342
343private:
344
345 int32_t bufferLen;
346 T* bufferPtr;
347
348 static finline int calcLength(int length) {
349 if (length<0) return 0;
350 return ((length/8)/sizeof(T)+1);
351 }
352public:
353 finline DefaultDataModel() {
354 bufferPtr = NULL;
355 bufferLen = -1;
356 }
357
358 finline DefaultDataModel( void* buffer, size_t length ) {
359 bufferPtr = (T*)buffer;
360 bufferLen = length;
361 }
362
363 finline DefaultDataModel( const _Model& source ) {
364 this->bufferPtr = source.bufferPtr;
365 this->bufferLen = source.bufferLen;
366 }
367
368 finline _Model& operator=( const _Model& source ) {
369 this->bufferPtr = source.bufferPtr;
370 this->bufferLen = source.bufferLen;
371 return *this;
372 }
373
374 finline T*& buffer() {
375 return bufferPtr;
376 }
377
378 finline T* buffer() const {
379 return bufferPtr;
380 }
381
382 finline int32_t& length() {
383 return bufferLen;
384 }
385
386 finline int32_t length() const {
387 return (bufferLen == -1) ? 0 : bufferLen;
388 }
389
390 finline bool isUnspecified() const {
391 return bufferLen < 0;
392 }
393
394 finline void resize( size_t new_length ) {
395 size_t old_length = calcLength(bufferLen);
396 size_t res_length = calcLength(new_length);
397 if (old_length != res_length) {
398 T* new_buffer = new T[res_length];
399 if (bufferPtr != NULL) {
400 size_t clength = res_length < old_length ? res_length : old_length;
401 memcpy( new_buffer, bufferPtr, clength*sizeof(T) );
402 delete [] bufferPtr;
403 }
404 bufferPtr = new_buffer;
405 bufferLen = new_length;
406 }
407 }
408
409 finline void release() {
410 if (bufferPtr!=NULL && bufferLen>=0) delete [] bufferPtr;
411 bufferPtr = NULL;
412 bufferLen = -1;
413 }
414
415 finline _Model sub( size_t index, size_t length ) {
416 return _Model( bufferPtr + index/sizeof(T), length );
417 }
418
419 finline _Model clone( size_t index, size_t length ) const {
420 _Model new_model;
421 new_model.resize( length );
422 bitcpy( this->buffer(), index, new_model.buffer(), 0, length );
423 return new_model;
424 }
425};
426
427/* serialization */
428sznBeginDefault( Data, X ){
429 for (size_t i = 0; i< getLength() / word_width; i++) X && getBuffer()[i];
430}sznEnd();
431
432/* default human readable text output */
433template<typename T, typename DataModel>
434std::ostream& operator<<(std::ostream& stream, const DataTpl<T, DataModel>& data) {
435 stream << "[" << bitstr(data.getBuffer(), data.getLength(), 4)
436 << "|'";
437 const char* buffer = (const char*) data.getBuffer();
438 for (size_t i = 0; i < data.getLength() / 8; i++) {
439 char c = buffer[i] < 32 ? '.' : buffer[i];
440 stream << c;
441 }
442 stream << "']";
443 return stream;
444}
445#endif /* DATA_HPP_ */
Note: See TracBrowser for help on using the repository browser.