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

Last change on this file since 3057 was 3057, checked in by Christoph Mayer, 16 years ago

-fixes #4 (merge tidy interface with current implementation)

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