An Overlay-based
Virtual Network Substrate
SpoVNet

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.