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

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