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

Last change on this file since 6841 was 6786, checked in by mies, 14 years ago

Changed Data to Message conversion constructor in Message to explicit
Fixed some general bugs in Data: operator<<
Fixed bug in DHTMessage: allow unspecified key/values
Added local DHT message delivery
Adapted sources to work with gcc 4.4.1

File size: 11.1 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
47// forward declaration
48template<typename T> class DefaultDataModel;
49template<typename T = uint8_t, typename DataModel = DefaultDataModel<uint8_t> > class DataTpl;
50typedef DataTpl<> Data;
51template<typename T, typename DataModel> std::ostream& operator<<(std::ostream& stream, const DataTpl<T, DataModel>& data);
52
53//== internal includes ==
54#include "../internal/Utilities.hpp"
55
56//== local includes ==
57#include "DataUtilities.hpp"
58#include "Serialization.hpp"
59
60/**
61 * This class implements a wrapper for binary data. And this time, when the
62 * word binary is used -- it really means binary! Length and manipulation
63 * are specified and operate in bit precision. Most of the operations are
64 * highly effective using inline functions and compiler optimizations.
65 *
66 * Two versions of binaries are supported: static, non-resizeable binaries
67 * and dynamic, resizeable ones. Please note, this class does not manage
68 * memory, reference counting etc. you have to take care about memory
69 * management yourself! However you can use the <code>release()</code>
70 * to delete the underlaying array.
71 *
72 * @author Sebastian Mies
73 */
74template<typename T, typename DataModel>
75class DataTpl: public Serializeable { SERIALIZEABLE
76protected:
77 typedef DataTpl<T,DataModel> _Data;
78 DataModel model;
79
80public:
81 static const size_t word_width = sizeof(T) * 8;
82
83 class DataManipulator {
84 private:
85 DataModel bits;
86 size_t index;
87
88 public:
89 finline DataManipulator( DataModel& _bits, size_t _index) :
90 bits(_bits), index(_index) {
91 }
92
93 template<typename X>
94 finline operator X() const {
95 return bitget<X>(bits.buffer(), index);
96 }
97
98 template<typename X>
99 finline DataManipulator& operator=(X value) {
100 bitset(value, bits.buffer(), index );
101 return *this;
102 }
103
104 template<typename X>
105 finline void set(X value, size_t length = sizeof(X) * 8, if_uint(X)) {
106 bitcpy(value, 0, bits.buffer(), index, length);
107 }
108
109 template<typename X>
110 finline void set(X value, size_t length = sizeof(X) * 8, if_int(X)) {
111 set(_unsigned(value),length);
112 }
113
114 template<typename X>
115 finline void get(X& value, size_t length = sizeof(X) * 8, if_uint(X)) const {
116 value = bitget<X> (bits.buffer(), index, length);
117 }
118
119 template<typename X>
120 finline void get(X& value, size_t length = sizeof(X) * 8, if_int(X)) const {
121 _unsigned(value) = bitget<X> (bits.buffer(), index, length);
122 }
123
124 finline void get(bool& value) const {
125 value = bitget( bits.buffer(), index );
126 }
127 };
128
129public:
130 static const Data UNSPECIFIED;
131
132 /**
133 * Constructs a dynamic bit-data object of variable size.
134 */
135 finline DataTpl() : model() {
136 }
137
138 /**
139 * Contructs a copy of an existing data buffer
140 */
141 finline DataTpl(const DataTpl<T, DataModel>& copy) {
142 this->model = copy.model;
143 }
144
145 finline DataTpl( const DataModel& _model ) : model( _model ) {
146 }
147
148 /**
149 * Constructs a static bit-data object with the given buffer.
150 */
151 finline DataTpl(const T* buffer, size_t length) {
152 model.buffer() = buffer;
153 model.length() = length;
154 }
155
156 /**
157 * Constructs a dynamic bit-data object with the given buffer.
158 */
159 finline DataTpl( T* buffer, size_t length ) {
160 model.buffer() = buffer;
161 model.length() = length;
162 }
163
164 /**
165 * Constructs a dynamic bit-data object of variable size with the given
166 * initial size.
167 */
168 finline DataTpl(size_t length) : model() {
169 model.resize(length);
170 }
171
172
173 /**
174 * Returns the internal buffer of the data.
175 */
176 finline T* getBuffer() const {
177 return model.buffer();
178 }
179
180 /**
181 * Returns the length of the data in bits
182 */
183 finline size_t getLength() const {
184 return model.length();
185 }
186 /**
187 * Sets the length of the data in bits
188 */
189 void setLength(size_t new_length) {
190 model.resize(new_length);
191 }
192
193 /**
194 * Ensures that the buffer pointer has the given
195 * number of bits of memory reserved.
196 *
197 * @param neededLength The minimum data length required.
198 */
199 finline void ensureLength( size_t neededLength ) {
200 if ((int) neededLength > model.length() ) model.resize(neededLength);
201 }
202
203 /**
204 * Returns a manipulator object for a certain bit position.
205 *
206 * @param index The index in bits quantitites.
207 * @return A data manipulation object
208 */
209 finline DataManipulator operator[](size_t index) {
210 return DataManipulator(model, index);
211 }
212
213 /**
214 * Returns a constant manipulator object for a certain bit position.
215 *
216 * @param index The index in bits quantitites.
217 * @return A constant data manipulation object
218 */
219 finline const DataManipulator operator[](size_t index) const {
220 return DataManipulator(model, index);
221 }
222
223 _Data sub( size_t index, size_t length = ~0 ) {
224 if (length == ~0) length = model.length()-index;
225 return _Data(model.sub(index,length));
226 }
227
228 /**
229 * Returns a copy of the specified bit range.
230 *
231 * @param index The first bit to copy
232 * @param length The length of the bit range
233 * @return The cloned data object
234 */
235 _Data clone( size_t index, size_t length ) const {
236 DataModel new_model = model.clone(index,length);
237 return _Data(new_model);
238 }
239
240 /**
241 * Returns a copy of the data.
242 *
243 * @return A cloned data object
244 */
245 _Data clone() const {
246 DataModel new_model = model.clone( 0, model.length() );
247 return _Data(new_model);
248 }
249
250 /**
251 * Returns true, if the data is empty (zero length)
252 *
253 * @return True, if the data is empty (zero length)
254 */
255 finline bool isEmpty() const {
256 return (model.length() == 0);
257 }
258
259 /**
260 * Returns true, if the data buffer is unspecified.
261 * In this case no memory is associated with this data object.
262 *
263 * @return True, if the data buffer is unspecified.
264 */
265 finline bool isUnspecified() const {
266 return model.isUnspecified();
267 }
268
269 /**
270 * This method frees the memory associated with
271 * this data object and sets this object into an unspecified
272 * state.
273 */
274 finline void release() {
275 model.release();
276 }
277
278 // operators
279
280 /**
281 * Assigns another buffer
282 */
283 template<typename X>
284 _Data& operator= (const DataTpl<X>& source) {
285 this->model = source.model;
286 return *this;
287 }
288
289 /**
290 * Returns true, if the datas buffer's pointer and length
291 * are the same.
292 */
293 template<typename X>
294 finline bool operator==( DataTpl<X>& data) {
295 return (data.model.buffer() == model.buffer() &&
296 data.model.length() == model.length() );
297 }
298
299 finline _Data& operator&=(_Data& data) {
300 return *this;
301 }
302
303 finline _Data& operator|=(_Data& data) {
304 return *this;
305 }
306
307 finline _Data& operator^=(_Data& data) {
308 return *this;
309 }
310
311 /* implied operators */
312
313 finline _Data operator&(_Data& data) {
314 return (this->clone() &= data);
315 }
316
317 finline _Data operator|(_Data& data) {
318 return (this->clone() |= data);
319 }
320
321 finline _Data operator^(_Data& data) {
322 return (this->clone() ^= data);
323 }
324};
325
326/* unspecified type */
327template<typename T, typename DataModel>
328const Data DataTpl<T, DataModel>::UNSPECIFIED;
329
330/**
331 * This class implements the default data model
332 *
333 * @author Sebastian Mies
334 */
335template<typename _T>
336class DefaultDataModel {
337public:
338 typedef _T T;
339 typedef DefaultDataModel<T> _Model;
340
341private:
342
343 int32_t bufferLen;
344 T* bufferPtr;
345
346 static finline int calcLength(int length) {
347 if (length<0) return 0;
348 return ((length/8)/sizeof(T)+1);
349 }
350public:
351 finline DefaultDataModel() {
352 bufferPtr = NULL;
353 bufferLen = -1;
354 }
355
356 finline DefaultDataModel( void* buffer, size_t length ) {
357 bufferPtr = (T*)buffer;
358 bufferLen = length;
359 }
360
361 finline DefaultDataModel( const _Model& source ) {
362 this->bufferPtr = source.bufferPtr;
363 this->bufferLen = source.bufferLen;
364 }
365
366 finline _Model& operator=( const _Model& source ) {
367 this->bufferPtr = source.bufferPtr;
368 this->bufferLen = source.bufferLen;
369 return *this;
370 }
371
372 finline T*& buffer() {
373 return bufferPtr;
374 }
375
376 finline T* buffer() const {
377 return bufferPtr;
378 }
379
380 finline int32_t& length() {
381 return bufferLen;
382 }
383
384 finline int32_t length() const {
385 return (bufferLen == -1) ? 0 : bufferLen;
386 }
387
388 finline bool isUnspecified() const {
389 return bufferLen < 0;
390 }
391
392 finline void resize( size_t new_length ) {
393 size_t old_length = calcLength(bufferLen);
394 size_t res_length = calcLength(new_length);
395 if (old_length != res_length) {
396 T* new_buffer = new T[res_length];
397 if (bufferPtr != NULL) {
398 size_t clength = res_length < old_length ? res_length : old_length;
399 memcpy( new_buffer, bufferPtr, clength*sizeof(T) );
400 delete [] bufferPtr;
401 }
402 bufferPtr = new_buffer;
403 bufferLen = new_length;
404 }
405 }
406
407 finline void release() {
408 if (bufferPtr!=NULL && bufferLen>=0) delete [] bufferPtr;
409 bufferPtr = NULL;
410 bufferLen = -1;
411 }
412
413 finline _Model sub( size_t index, size_t length ) {
414 return _Model( bufferPtr + index/sizeof(T), length );
415 }
416
417 finline _Model clone( size_t index, size_t length ) const {
418 _Model new_model;
419 new_model.resize( length );
420 bitcpy( this->buffer(), index, new_model.buffer(), 0, length );
421 return new_model;
422 }
423};
424
425/* serialization */
426sznBeginDefault( Data, X ){
427 for (size_t i = 0; i< getLength() / word_width; i++) X && getBuffer()[i];
428}sznEnd();
429
430/* default human readable text output */
431template<typename T, typename DataModel>
432std::ostream& operator<<(std::ostream& stream, const DataTpl<T, DataModel>& data) {
433 stream << "[" << bitstr(data.getBuffer(), data.getLength(), 4)
434 << "|'";
435 const char* buffer = (const char*) data.getBuffer();
436 for (size_t i = 0; i < data.getLength() / 8; i++) {
437 char c = buffer[i] < 32 ? '.' : buffer[i];
438 stream << c;
439 }
440 stream << "']";
441 return stream;
442}
443#endif /* DATA_HPP_ */
Note: See TracBrowser for help on using the repository browser.