An Overlay-based
Virtual Network Substrate
SpoVNet

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

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

Merged 20090512-mies-connectors changes r3472:r3689 into trunk.

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