An Overlay-based
Virtual Network Substrate
SpoVNet

source: source/ariba/utility/serialization/DataStream.hpp @ 7468

Last change on this file since 7468 was 6922, checked in by mies, 14 years ago

replaced deprecated hash_map, hash_set classes with boost
added unsigned serialization
fixed more warnings
included -Wall to Makefile.am

File size: 17.9 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 DATASTREAM_HPP_
40#define DATASTREAM_HPP_
41
42//== Library includes ==
43#include <boost/cstdint.hpp>
44#include <boost/type_traits/make_unsigned.hpp>
45
46#include <cassert>
47#include <iostream>
48#include <vector>
49#include <string.h>
50
51#ifndef SERIALIZATION_NS
52#define SERIALIZATION_NS ariba::utility::serialization
53#define SERIALIZATION_NS_INT SERIALIZATION_NS::internal
54
55/* some words on the namespaces */
56#define SERIALIZATION_NS_BEGIN() \
57        namespace ariba { \
58        namespace utility { \
59        namespace serialization {
60
61#define SERIALIZATION_NS_END() \
62        } } }
63#endif
64
65//== forward declarations ==
66SERIALIZATION_NS_BEGIN()
67
68// data stream template forward declaration
69template<Mode __mode, int __variant = DEFAULT_V, typename T = uint8_t>
70class DataStreamTpl;
71
72// internal explicit serialization forward declaration
73namespace internal {
74        template<typename T> class ITpl;
75        template<typename T> ITpl<T> I( T& value, size_t length = sizeof(T)*8 );
76        class cI;
77        class T;
78        class cT;
79}
80
81// virtual serialization forward declaration
82bool data_serialization( Mode mode, VSerializeable* obj, Data& data, int variant = DEFAULT_V );
83Data data_serialize( const VSerializeable* obj, int variant = DEFAULT_V );
84bool data_deserialize( VSerializeable* obj, Data& data, int variant = DEFAULT_V );
85size_t data_length( const VSerializeable* obj, int variant = DEFAULT_V );
86
87SERIALIZATION_NS_END()
88
89//== Internal includes ==
90#include "../internal/Utilities.hpp"
91
92//== Local includes ==
93#include "Serialization.hpp"
94#include "DataUtilities.hpp"
95#include "Data.hpp"
96
97SERIALIZATION_NS_BEGIN()
98
99/**
100 *
101 */
102template<Mode __mode, int __variant, typename T>
103class DataStreamTpl {
104
105        template<typename X>
106        friend class SERIALIZATION_NS_INT::ITpl;
107        friend class SERIALIZATION_NS_INT::cI;
108        friend class SERIALIZATION_NS_INT::T;
109        friend class SERIALIZATION_NS_INT::cT;
110
111        template<Mode _a, int _b, typename _c>
112        friend std::ostream& operator<<( std::ostream&, DataStreamTpl<_a, _b, _c>& );
113
114private:
115        /* index in the buffer */
116        size_t index;
117
118        /* binary buffer */
119        DataTpl<T> bits;
120
121        /* support serializers */
122        template<class X>
123        finline void add(const X& ser, if_is_base_of( ExplicitSerializer, X )) {
124                ser.SERIALIZATION_METHOD_NAME(*this);
125        }
126
127        template<class X>
128        finline void remove(const X& ser, if_is_base_of( ExplicitSerializer, X )) {
129                ser.SERIALIZATION_METHOD_NAME(*this);
130        }
131
132        /* support serializeables */
133        template<class X>
134        finline void add( X& obj, if_is_base_of( Serializeable, X ) ) {
135                get_serializer<__variant>(obj).SERIALIZATION_METHOD_NAME(*this);
136        }
137
138        template<class X>
139        finline void add( const X& obj, if_is_base_of( Serializeable, X ) ) {
140                get_serializer<__variant>((X&)obj).SERIALIZATION_METHOD_NAME(*this);
141        }
142
143        template<class X>
144        finline void remove( X& obj, if_is_base_of( Serializeable, X ) ) {
145                get_serializer<__variant>(obj).SERIALIZATION_METHOD_NAME(*this);
146        }
147
148        /* support uints */
149        template<typename X>
150        finline void add(X& obj, if_uint(X)) {
151                if (!isMeasure())
152//                      bitcpy( obj, 0, bits.getBuffer(), index);
153                        bitcpy( obj, 0, bits.getBuffer(), index, sizeof(X)*8 );
154                index += sizeof(X) * 8;
155        }
156
157        template<typename X>
158        finline void remove(X& obj, if_uint(X)) {
159                //if (!isMeasure()) bits[index].get(obj);
160                if (!isMeasure())
161                        bitcpy( bits.getBuffer(), index, obj, 0, sizeof(X)*8 );
162                index += sizeof(X) * 8;
163        }
164
165        /* support signed ints */
166        template<typename X>
167        finline void add(X& sobj, if_int(X)) {
168                typedef typename boost::make_unsigned<X>::type UX;
169                UX& obj = *((UX*)&sobj);
170                if (!isMeasure())
171                bitcpy( sobj, 0, bits.getBuffer(), index);
172                index += sizeof(X) * 8;
173        }
174
175        template<typename X>
176        finline void remove(X& sobj, if_int(X)) {
177                typedef typename boost::make_unsigned<X>::type UX;
178                UX& obj = *((UX*)&sobj);
179                if (!isMeasure()) bits[index].get(obj);
180                index += sizeof(X) * 8;
181        }
182
183        /* support boolean types */
184        finline void add( bool& obj ) {
185                if (!isMeasure()) bits[index] = obj;
186                index += 1;
187        }
188
189        finline void remove( bool& obj ) {
190                if (!isMeasure()) bits[index].get(obj);
191                index += 1;
192        }
193
194        /* support vserializeables */
195        finline void add( const VSerializeable* obj ) {
196                if (!isMeasure()) {
197                        Data data = data_serialize( (VSerializeable*)obj, __variant );
198                        add(data); data.release();
199                } else {
200                        index += data_length( obj, __variant );
201                }
202        }
203
204        finline void remove( VSerializeable* obj ) {
205                Data data( bits.getBuffer() + index / 8, getRemainingLength() );
206                size_t length = obj->SERIALIZATION_METHOD_NAME( __mode, data, __variant );
207                index += length;
208        }
209
210        finline void remove( const VSerializeable* obj ) {
211                throw "NOT SUPPORTED!";
212        }
213
214        /* data stream typedef */
215        typedef DataStreamTpl<__mode, __variant, T> _DataStream;
216
217public:
218
219        finline DataStreamTpl() : bits() {
220                index = 0;
221        }
222
223        finline DataStreamTpl( Data& binary ) : bits(binary) {
224                index = 0;
225        }
226
227        finline DataStreamTpl( _DataStream& stream ) {
228                throw "Error: DataStreams can not be copied.";
229        }
230
231        /**
232         * Returns the current mode of the data stream
233         *
234         * @return the current mode of the data stream
235         */
236        finline Mode getMode() const {
237                return __mode;
238        }
239
240        /**
241         * Returns true, if this is a measure of data length
242         *
243         * @return true, if this is a measure of data length
244         */
245        finline bool isMeasure() {
246                return __mode == MEASURE;
247        }
248
249        finline bool isSerializer() {
250                return (__mode == SERIALIZE) || isMeasure();
251        }
252
253        finline bool isDeserializer() {
254                return __mode == DESERIALIZE;
255        }
256
257        /**
258         * Returns the variants that are used.
259         *
260         * @return The variants that are used.
261         */
262        finline int getVariant() const {
263                return __variant;
264        }
265
266        /**
267         * Returns the remaining length.
268         * This method is only applicable in deserialize mode.
269         *
270         * @return The remaining length of the stream.
271         */
272        finline size_t getRemainingLength() const {
273                return bits.getLength() - index;
274        }
275
276        /**
277         * Returns the remaining data in the data buffer.
278         * This method is only applicable in deserialize mode.
279         *
280         * @return The remaining data in the data buffer.
281         */
282        finline Data getRemainingData( size_t length ) {
283                Data subData = Data(bits.getBuffer() + index / bits.word_width, length);
284                index += length;
285                return subData;
286        }
287
288        /**
289         * Returns the current length of the stream.
290         * This method is only applicable in serialize mode.
291         *
292         * @return The current length of the stream.
293         */
294        finline size_t getCurrentLength() const {
295                return index;
296        }
297
298        /**
299         * Resets the index of the stream
300         */
301        finline void reset(Mode mode = UNDEFINED) {
302                this->index = 0;
303                this->mode = mode;
304        }
305
306        /**
307         * Returns a mark of the current position in the stream
308         */
309        finline size_t mark() const {
310                return index;
311        }
312
313        /**
314         * Seeks to the given position
315         */
316        finline void seek( size_t idx ) {
317                index = idx;
318        }
319
320        /**
321         * Assures that the given length is available in the
322         * buffer.
323         */
324        finline void ensureLength( size_t size ) {
325                if (!isMeasure()) bits.ensureLength( size + index );
326        }
327
328        /**
329         * Returns a binary object, of the current stream content
330         */
331        finline Data getData() {
332                bits.setLength(index);
333                return bits;
334        }
335
336        finline uint8_t* bytes( size_t length ) {
337                assert((index%bits.word_width)==0);
338                if (!isMeasure()) {
339                        bits.ensureLength( index + length * 8);
340                        uint8_t* buffer = (uint8_t*)bits.getBuffer()+(index/bits.word_width);
341                        index += length*8;
342                        return buffer;
343                } else {
344                        index += length*8;
345                        return NULL;
346                }
347        }
348
349        /**
350         * deserialises or serializes an object depending on the bit-streams mode
351         */
352        template<typename X>
353        finline _DataStream& operator&&( X& obj ) {
354                if (isSerializer()) add(obj); else if (isDeserializer()) remove(obj);
355                return *this;
356        }
357
358        template<typename X>
359        finline _DataStream& operator&&( const X& obj ) {
360                if (isSerializer()) add(obj); else if (isDeserializer()) remove(obj);
361                return *this;
362        }
363
364        template<typename X>
365        finline _DataStream& operator&&( X* obj ) {
366                if (isSerializer()) add(obj); else if (isDeserializer()) remove(obj);
367                return *this;
368        }
369
370        template<typename X>
371        finline _DataStream& operator&&( const X* obj ) {
372                if (isSerializer()) add(obj); else if (isDeserializer()) remove(obj);
373                return *this;
374        }
375};
376
377//--------------------------------------------------------------------------
378
379template<Mode _a, int _b, typename _c>
380std::ostream& operator<<( std::ostream& stream,
381                DataStreamTpl<_a, _b, _c>& binaryStream ) {
382        stream << binaryStream.bits << "";
383        return stream;
384}
385
386//--------------------------------------------------------------------------
387
388namespace internal {
389        using_serialization;
390
391        /* integer support - I( value, length ) */
392        template<typename T>
393        class ITpl : public ExplicitSerializer {
394        private:
395                T& value;
396                size_t length;
397        public:
398                finline ITpl( T& _value, size_t _length = sizeof(T)*8 )
399                : value(_value), length(_length) {}
400
401                sznMethodBegin(X)
402                if (X.isSerializer()) {
403                        if (!X.isMeasure())
404                        X.bits[X.index].set( value, length );
405                        X.index += length;
406                } else {
407                        X.bits[X.index].get(value,length);
408                        X.index += length;
409                }
410                sznMethodEnd()
411        };
412
413        template<typename T>
414        finline ITpl<T> I( T& value, size_t length ) {
415                return ITpl<T>(value, length);
416        }
417
418        /* const int support - cI( uintmax_t ) */
419        class cI : public ExplicitSerializer {
420        private:
421                const uintmax_t value;
422                size_t length;
423        public:
424                finline cI( const uintmax_t _value, size_t _length )
425                : value(_value), length(_length) {}
426
427                sznMethodBegin(X)
428                if (X.isSerializer()) {
429                        if (!X.isMeasure())
430                        X.bits[X.index].set(value,length);
431                        X.index += length;
432                } else {
433                        uintmax_t _value = 0;
434                        X.bits[X.index].get(_value,length);
435                        if (_value != value) break;
436                        X.index += length;
437                }
438                sznMethodEnd()
439        };
440
441        /* const char* support - cT( const char* ) */
442        class cT : public ExplicitSerializer {
443        private:
444                const char* text;
445
446        public:
447                finline cT( const char* _text )
448                : text(_text) {}
449
450                sznMethodBegin(X)
451                if (X.isSerializer()) {
452                        size_t length = strlen(text);
453                        if (!X.isMeasure()) {
454                                for (size_t i=0; i<length; i++)
455                                X.bits[X.index+i*8] = (uint8_t)text[i];
456                        }
457                        X.index += length * 8;
458                } else {
459                        size_t length = strlen(text);
460                        for (size_t i=0; i<length; i++) {
461                                char c = 0;
462                                X.bits[X.index+i*8].get(c);
463                                if (c!=text[i]) break;
464                        }
465                }
466                sznMethodEnd()
467        };
468
469        /* string and char* support, T( char* | std::string ) */
470        class T : public ExplicitSerializer {
471        private:
472                bool isCharP;
473                char** text;
474                std::string* string;
475                int length;
476
477        public:
478                finline T( char*& _text, int length = -1 ) :
479                        text(&_text), string(NULL) {
480                        this->isCharP = true;
481                        this->length = length;
482                }
483
484                finline T( std::string& _string, int length = -1 ) :
485                        text(NULL), string(&_string) {
486                        this->isCharP = false;
487                        this->length = length;
488                }
489
490                sznMethodBegin(X)
491                if (X.isSerializer()) {
492                        char* textp = isCharP ? *text : (char*)string->c_str();
493                        size_t plength = length!= -1 ? length : strlen(textp);
494                        if (!X.isMeasure()) {
495                                size_t i;
496                                for (i=0; i<plength && textp[i]!=0; i++)
497                                X.bits[X.index+i*8] = (uint8_t)textp[i];
498                                if (length==-1) X.bits[X.index+i*8] = (uint8_t)0;
499                        }
500                        X.index += plength * 8 + ((length == -1) ? 8 : 0);
501                } else {
502                        std::string s;
503                        size_t i = 0;
504                        while (length == -1 || i < (size_t)length) {
505                                uint8_t c = 0;
506                                X.bits[X.index].get(c); X.index += 8;
507                                if (c == 0 && length == -1) break;
508                                s += (char)c;
509                                i++;
510                        }
511                        if (isCharP) *text = strdup(s.c_str());
512                        else string->assign(s);
513                }
514                sznMethodEnd()
515        };
516
517        /* array and vector support */
518        template<typename T>
519        class ArrayTpl : public ExplicitSerializer {
520        private:
521                T*& v;
522                size_t l;
523
524        public:
525                finline ArrayTpl( T*& array, size_t length ) :
526                v(array), l(length) {}
527
528                sznMethodBegin(X)
529                if (X.isDeserializer()) v = new T[l];
530                for (size_t i=0; i<l; i++) X && v[i];
531                sznMethodEnd()
532        };
533
534        template<typename T>
535        class StaticArrayTpl : public ExplicitSerializer {
536        private:
537                T* v;
538                size_t l;
539
540        public:
541                finline StaticArrayTpl( T* array, size_t length ) :
542                v(array), l(length) {}
543
544                sznMethodBegin(X)
545                        for (size_t i=0; i<l; i++) X && v[i];
546                sznMethodEnd()
547        };
548
549        template<typename T>
550        class VectorTpl : public ExplicitSerializer {
551        private:
552                std::vector<T>& v;
553                size_t l;
554
555        public:
556                finline VectorTpl( std::vector<T>& vec, size_t length ) :
557                v(vec), l(length) {}
558
559                sznMethodBegin(X)
560                if (X.isDeserializer()) v.resize(l);
561                for (size_t i=0; i<l; i++) X && v[i];
562                sznMethodEnd()
563        };
564
565        template<typename X, typename T>
566        finline X V( T& x ) {
567                throw "ERROR: No vector serializer for this type";
568        }
569
570        template<typename T>
571        finline ArrayTpl<T> A( T*& array, size_t length ) {
572                return ArrayTpl<T>(array,length);
573        }
574
575        template<typename T>
576        finline StaticArrayTpl<T> static_A( T* array, size_t length ) {
577                return StaticArrayTpl<T>(array,length);
578        }
579
580        template<typename T>
581        finline VectorTpl<T> A( std::vector<T>& array, size_t length ) {
582                return VectorTpl<T>(array,length);
583        }
584
585        /* allocated virtual object support */
586        template<typename T>
587        class VOTpl : ExplicitSerializer {
588        private:
589                int variant;
590                T*& obj;
591        public:
592                finline VOTpl( T*& mobj, int variant ) : obj(mobj) {
593                }
594                sznMethodBegin(X)
595                if (X.isSerializer()) {
596                        if (obj!=NULL) X && obj;
597                } else {
598                        obj = new T();
599                        X && obj;
600                }
601                sznMethodEnd()
602        };
603
604        template<typename T>
605        finline VOTpl<T> VO( T*& obj, int variant = DEFAULT_V ) {
606                return VOTpl<T>(obj,variant);
607        }
608
609        /* allocated non-virtual object serialization support */
610        template<typename T>
611        class OTpl : ExplicitSerializer {
612        private:
613                int variant;
614                T*& obj;
615        public:
616                finline OTpl( T*& mobj, int variant ) : obj(mobj) {
617                }
618                sznMethodBegin(X)
619                if (X.isSerializer()) {
620                        if (obj!=NULL) X && *obj;
621                } else {
622                        obj = new T();
623                        X && *obj;
624                }
625                sznMethodEnd()
626        };
627
628        template<typename T>
629        finline OTpl<T> O( T*& obj, int variant = DEFAULT_V ) {
630                return OTpl<T>(obj,variant);
631        }
632
633} // namespace internal
634
635//--------------------------------------------------------------------------
636
637//= static serialization =
638//= get length =
639
640template<int __variant, typename X> finline
641size_t data_length_v( const X& obj ) {
642        DataStreamTpl<MEASURE, __variant> stream;
643        return (stream && (X&)obj).getCurrentLength();
644}
645
646template<typename X> finline
647size_t data_length( const X& obj ) {
648        return data_length_v<DEFAULT_V>(obj);
649}
650
651template<Mode __mode, int __variant, typename X> finline
652size_t data_serialization_v( X& obj, Data& data,
653                if_is_base_of(Serializeable, X) ) {
654        if (__mode == SERIALIZE) {
655                DataStreamTpl<SERIALIZE, __variant> stream;
656                size_t len = data_length_v<__variant>(obj);
657                stream.ensureLength( len );
658                return (data = (stream && obj).getData()).getLength();
659        } else {
660                DataStreamTpl<DESERIALIZE, __variant> stream( data );
661                return (stream && obj).getCurrentLength();
662        }
663}
664
665template<Mode __mode, int __variant, typename X>
666size_t slow_data_serialization_v( X& obj, Data& data,
667                if_is_base_of(Serializeable, X) ) {
668        return slow_data_serialization_v<__mode,__variant>(obj,data);
669}
670
671template<Mode __mode, typename X>
672size_t data_serialization( X& obj, Data& data,
673                if_is_base_of( Serializeable, X ) ) {
674        return slow_data_serialization_v<__mode, DEFAULT_V>( obj, data );
675}
676
677template<int __variant, typename X>
678Data data_serialize_v( const X& obj, if_is_base_of(Serializeable, X) ) {
679        Data data; data_serialization_v<SERIALIZE, __variant>( (X&)obj, data );
680        return data;
681}
682
683template<typename X>
684Data data_serialize( const X& obj, if_is_base_of(Serializeable, X) ) {
685        return data_serialize_v<DEFAULT_V>(obj);
686}
687
688template<int __variant, typename X>
689size_t data_deserialize_v( X& obj, Data data, if_is_base_of(Serializeable, X) ) {
690        return data_serialization_v<DESERIALIZE,__variant>( obj, data );
691}
692
693template<typename X>
694size_t data_deserialize( X& obj, Data data,
695                if_is_base_of(Serializeable, X) ) {
696        return data_deserialize_v<DEFAULT_V>(obj, data);
697}
698
699//= virtual serialization =
700
701finline bool data_serialization( VSerializeable* obj, Data& data,
702                Mode mode, int variant /*= DEFAULT_V*/) {
703        size_t length = obj->SERIALIZATION_METHOD_NAME( mode, data, variant );
704        return length != 0;
705}
706
707finline Data data_serialize( const VSerializeable* obj,
708                int variant /*= DEFAULT_V*/) {
709        Data data;
710        data_serialization( (VSerializeable*)obj, data, SERIALIZE, variant );
711        return data;
712}
713
714finline bool data_deserialize( VSerializeable* obj, Data& data,
715                int variant /*= DEFAULT_V*/) {
716        return data_serialization( obj, data, DESERIALIZE, variant );
717}
718
719finline size_t data_length( const VSerializeable* obj, int variant /*= DEFAULT_V*/) {
720        return ((VSerializeable*)obj)->SERIALIZATION_METHOD_NAME( MEASURE,
721                        (Data&)Data::UNSPECIFIED, variant );
722}
723
724//--------------------------------------------------------------------------
725
726SERIALIZATION_NS_END()
727
728#endif /* DATASTREAM_HPP_ */
Note: See TracBrowser for help on using the repository browser.