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

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