close Warning: Can't use blame annotator:
No changeset 2259 in the repository

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

Last change on this file since 12459 was 6922, checked in by mies, 15 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
RevLine 
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.