File indexing completed on 2025-01-18 09:57:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef GAUDIKERNEL_STREAMBUFFER_H
0012 #define GAUDIKERNEL_STREAMBUFFER_H 1
0013
0014
0015 #include <algorithm>
0016 #include <cstdlib>
0017 #include <cstring>
0018 #include <iostream>
0019 #include <list>
0020 #include <string>
0021 #include <typeinfo>
0022 #include <vector>
0023
0024 #include "GaudiKernel/Kernel.h"
0025 #include "GaudiKernel/swab.h"
0026
0027
0028 class StreamBuffer;
0029 class DataObject;
0030 class ContainedObject;
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 class StreamBuffer
0052 {
0053 public:
0054
0055 class DataIO {
0056 public:
0057
0058 DataIO() = default;
0059
0060 virtual ~DataIO() = default;
0061
0062 void badStreamMode() { throw( "Not acceptable stream mode!" ); }
0063
0064 virtual void serialize( StreamBuffer& stream ) {
0065 if ( stream.isReading() )
0066 load( stream );
0067 else if ( stream.isWriting() )
0068 dump( stream );
0069 else
0070 badStreamMode();
0071 }
0072
0073 virtual void load( StreamBuffer& ) { badStreamMode(); }
0074
0075 virtual void dump( StreamBuffer& ) { badStreamMode(); }
0076 };
0077
0078
0079 class Istream : public DataIO {
0080
0081 std::istream* m_stream;
0082
0083 public:
0084
0085 Istream( std::istream& str ) : m_stream( &str ) {}
0086
0087
0088 void load( StreamBuffer& stream ) override {
0089
0090 int len;
0091 ( *m_stream ) >> len;
0092 stream.erase();
0093 stream.reserve( len );
0094 m_stream->read( stream.data(), len );
0095 }
0096 };
0097
0098 class Ostream : public DataIO {
0099 std::ostream* m_stream;
0100
0101 public:
0102
0103 Ostream( std::ostream& str ) : m_stream( &str ) {}
0104
0105 virtual ~Ostream() = default;
0106
0107
0108 void dump( StreamBuffer& stream ) override {
0109
0110 ( *m_stream ) << stream.buffPointer();
0111 m_stream->write( stream.data(), stream.buffPointer() );
0112 }
0113 };
0114
0115 public:
0116
0117 enum Mode { UNINITIALIZED, READING, WRITING };
0118
0119 enum SwapAction { SINGLE_BYTE, SWAP, NOSWAP };
0120
0121 enum State { INVALID = -1, VALID };
0122
0123 class ContainedLink {
0124 public:
0125 ContainedObject* first = nullptr;
0126 long second = INVALID;
0127 long third = INVALID;
0128 ContainedLink() = default;
0129 ContainedLink( ContainedObject* pObj, long hint, long link ) : first( pObj ), second( hint ), third( link ) {}
0130 ContainedLink( const ContainedLink& copy ) = default;
0131 ContainedLink& operator=( const ContainedLink& copy ) = default;
0132 };
0133
0134 class IdentifiedLink {
0135 public:
0136 DataObject* first = nullptr;
0137 long second = INVALID;
0138 IdentifiedLink() = default;
0139 IdentifiedLink( DataObject* pObj, long hint ) : first( pObj ), second( hint ) {}
0140 IdentifiedLink( const IdentifiedLink& copy ) = default;
0141 IdentifiedLink& operator=( const IdentifiedLink& copy ) = default;
0142 };
0143
0144 typedef std::vector<ContainedLink> ContainedLinks;
0145
0146 typedef std::vector<IdentifiedLink> IdentifiedLinks;
0147
0148 typedef void ( *AnalyzeFunction )( const void* data, int siz, const std::type_info& type );
0149
0150 friend class DataObject;
0151
0152 protected:
0153
0154 Mode m_mode = UNINITIALIZED;
0155
0156
0157 mutable long m_pointer = 0;
0158
0159
0160 mutable long m_length = 0;
0161
0162
0163 mutable char* m_buffer = nullptr;
0164
0165
0166 bool m_swapEnabled = true;
0167
0168
0169 mutable ContainedLinks m_containedLinks;
0170
0171
0172 mutable IdentifiedLinks m_identifiedLinks;
0173
0174
0175 AnalyzeFunction m_analyzer = nullptr;
0176
0177
0178 SwapAction swapBuffer( int siz ) const;
0179
0180
0181
0182
0183 template <class TYPE>
0184 StreamBuffer& getObjectPointer( const DataObject* , TYPE*& refpObject ) {
0185 IdentifiedLink& link = m_identifiedLinks.back();
0186 DataObject* pObj = link.first;
0187 m_identifiedLinks.pop_back();
0188 refpObject = dynamic_cast<TYPE*>( pObj );
0189 return *this;
0190 }
0191
0192
0193
0194 template <class TYPE>
0195 StreamBuffer& getObjectPointer( const ContainedObject* , TYPE*& refpObject ) {
0196 ContainedLink& link = m_containedLinks.back();
0197 ContainedObject* pObj = link.first;
0198 m_containedLinks.pop_back();
0199 refpObject = dynamic_cast<TYPE*>( pObj );
0200 return *this;
0201 }
0202
0203 public:
0204
0205 StreamBuffer( bool do_swap = true ) : m_swapEnabled( do_swap ) {}
0206
0207 virtual ~StreamBuffer() { ::free( m_buffer ); }
0208
0209 const char* data() const { return m_buffer; }
0210
0211 char* data() { return m_buffer; }
0212
0213 void erase() { m_pointer = 0; }
0214
0215 char* adopt() const {
0216 char* ptr = m_buffer;
0217 m_containedLinks.erase( m_containedLinks.begin(), m_containedLinks.end() );
0218 m_identifiedLinks.erase( m_identifiedLinks.begin(), m_identifiedLinks.end() );
0219 m_buffer = NULL;
0220 m_pointer = 0;
0221 m_length = 0;
0222 return ptr;
0223 }
0224
0225 void reserve( long len ) {
0226 if ( len > m_length ) {
0227 m_length = ( len < 16384 ) ? 16384 : len;
0228 m_buffer = (char*)::realloc( m_buffer, m_length );
0229 }
0230 }
0231
0232 void extend( long len ) {
0233 if ( len + m_pointer > m_length ) {
0234
0235
0236 long new_len = ( m_length < 16384 ) ? 16384 : 2 * m_length;
0237 if ( m_length < len ) new_len += len;
0238 reserve( new_len );
0239 }
0240 }
0241
0242 long size() const { return m_length; }
0243
0244 ContainedLinks& containedLinks() { return m_containedLinks; }
0245
0246 const ContainedLinks& containedLinks() const { return m_containedLinks; }
0247
0248
0249 IdentifiedLinks& identifiedLinks() { return m_identifiedLinks; }
0250
0251 const IdentifiedLinks& identifiedLinks() const { return m_identifiedLinks; }
0252
0253
0254 void setMode( Mode m ) {
0255 m_mode = m;
0256 m_pointer = 0;
0257 m_containedLinks.erase( m_containedLinks.begin(), m_containedLinks.end() );
0258 m_identifiedLinks.erase( m_identifiedLinks.begin(), m_identifiedLinks.end() );
0259 }
0260
0261
0262 bool isReading() const { return m_mode == READING; }
0263
0264
0265 bool isWriting() const { return m_mode == WRITING; }
0266
0267 long buffPointer() const { return m_pointer; }
0268
0269 void setBuffPointer( long ptr ) { m_pointer = ptr; }
0270
0271 void setAnalyzer( AnalyzeFunction fun = nullptr ) { m_analyzer = fun; }
0272
0273 void swapToBuffer( const void* source, int siz );
0274
0275
0276 void swapFromBuffer( void* target, int siz );
0277
0278
0279 StreamBuffer& writeBytes( const char* str, long len ) {
0280 extend( m_pointer + len + 4 );
0281 *this << len;
0282 std::copy_n( str, len, data() + buffPointer() );
0283 m_pointer += len;
0284 return *this;
0285 }
0286
0287 void getIdentifiedLink( DataObject*& pObject, long& hint ) {
0288 IdentifiedLink& l = m_identifiedLinks.back();
0289 pObject = l.first;
0290 hint = l.second;
0291 m_identifiedLinks.pop_back();
0292 }
0293 void addIdentifiedLink( const DataObject* pObject, long hint ) {
0294 m_identifiedLinks.push_back( IdentifiedLink( (DataObject*)pObject, hint ) );
0295 }
0296
0297 void getContainedLink( ContainedObject*& pObject, long& hint, long& link ) {
0298 ContainedLink& l = m_containedLinks.back();
0299 pObject = l.first;
0300 hint = l.second;
0301 link = l.third;
0302 m_containedLinks.pop_back();
0303 }
0304 void addContainedLink( const ContainedObject* pObject, long hint, long link ) {
0305 m_containedLinks.push_back( ContainedLink( (ContainedObject*)pObject, hint, link ) );
0306 }
0307
0308 #ifdef USE_STREAM_ANALYSER
0309 # define STREAM_ANALYSE( data, len ) \
0310 if ( 0 != m_analyzer ) m_analyzer( &data, len, typeid( data ) )
0311 #else
0312 # define STREAM_ANALYSE( data, len )
0313 #endif
0314
0315
0316 #define IMPLEMENT_STREAMER( TYPE ) \
0317 \
0318 StreamBuffer& operator<<( TYPE data ) { \
0319 swapToBuffer( &data, sizeof( data ) ); \
0320 STREAM_ANALYSE( data, sizeof( data ) ); \
0321 return *this; \
0322 } \
0323 \
0324 StreamBuffer& operator>>( TYPE& data ) { \
0325 swapFromBuffer( &data, sizeof( data ) ); \
0326 return *this; \
0327 }
0328
0329
0330 #undef IMPLEMENT_STREAMER
0331
0332
0333 StreamBuffer& operator<<( long long data ) {
0334 swapToBuffer( &data, sizeof( data ) );
0335 STREAM_ANALYSE( data, sizeof( data ) );
0336 return *this;
0337 }
0338
0339 StreamBuffer& operator>>( long long& data ) {
0340 swapFromBuffer( &data, sizeof( data ) );
0341 return *this;
0342 }
0343
0344 StreamBuffer& operator<<( int data ) {
0345 swapToBuffer( &data, sizeof( data ) );
0346 STREAM_ANALYSE( data, sizeof( data ) );
0347 return *this;
0348 }
0349
0350 StreamBuffer& operator>>( int& data ) {
0351 swapFromBuffer( &data, sizeof( data ) );
0352 return *this;
0353 }
0354
0355 StreamBuffer& operator<<( unsigned int data ) {
0356 swapToBuffer( &data, sizeof( data ) );
0357 STREAM_ANALYSE( data, sizeof( data ) );
0358 return *this;
0359 }
0360
0361 StreamBuffer& operator>>( unsigned int& data ) {
0362 swapFromBuffer( &data, sizeof( data ) );
0363 return *this;
0364 }
0365
0366 StreamBuffer& operator<<( long data ) {
0367 swapToBuffer( &data, sizeof( data ) );
0368 STREAM_ANALYSE( data, sizeof( data ) );
0369 return *this;
0370 }
0371
0372 StreamBuffer& operator>>( long& data ) {
0373 swapFromBuffer( &data, sizeof( data ) );
0374 return *this;
0375 }
0376
0377 StreamBuffer& operator<<( unsigned long data ) {
0378 swapToBuffer( &data, sizeof( data ) );
0379 STREAM_ANALYSE( data, sizeof( data ) );
0380 return *this;
0381 }
0382
0383 StreamBuffer& operator>>( unsigned long& data ) {
0384 swapFromBuffer( &data, sizeof( data ) );
0385 return *this;
0386 }
0387
0388 StreamBuffer& operator<<( short data ) {
0389 swapToBuffer( &data, sizeof( data ) );
0390 STREAM_ANALYSE( data, sizeof( data ) );
0391 return *this;
0392 }
0393
0394 StreamBuffer& operator>>( short& data ) {
0395 swapFromBuffer( &data, sizeof( data ) );
0396 return *this;
0397 }
0398
0399 StreamBuffer& operator<<( unsigned short data ) {
0400 swapToBuffer( &data, sizeof( data ) );
0401 STREAM_ANALYSE( data, sizeof( data ) );
0402 return *this;
0403 }
0404
0405 StreamBuffer& operator>>( unsigned short& data ) {
0406 swapFromBuffer( &data, sizeof( data ) );
0407 return *this;
0408 }
0409
0410 StreamBuffer& operator<<( char data ) {
0411 swapToBuffer( &data, sizeof( data ) );
0412 STREAM_ANALYSE( data, sizeof( data ) );
0413 return *this;
0414 }
0415
0416 StreamBuffer& operator>>( char& data ) {
0417 swapFromBuffer( &data, sizeof( data ) );
0418 return *this;
0419 }
0420
0421 StreamBuffer& operator<<( unsigned char data ) {
0422 swapToBuffer( &data, sizeof( data ) );
0423 STREAM_ANALYSE( data, sizeof( data ) );
0424 return *this;
0425 }
0426
0427 StreamBuffer& operator>>( unsigned char& data ) {
0428 swapFromBuffer( &data, sizeof( data ) );
0429 return *this;
0430 }
0431
0432 StreamBuffer& operator<<( float data ) {
0433 swapToBuffer( &data, sizeof( data ) );
0434 STREAM_ANALYSE( data, sizeof( data ) );
0435 return *this;
0436 }
0437
0438 StreamBuffer& operator>>( float& data ) {
0439 swapFromBuffer( &data, sizeof( data ) );
0440 return *this;
0441 }
0442
0443 StreamBuffer& operator<<( double data ) {
0444 swapToBuffer( &data, sizeof( data ) );
0445 STREAM_ANALYSE( data, sizeof( data ) );
0446 return *this;
0447 }
0448
0449 StreamBuffer& operator>>( double& data ) {
0450 swapFromBuffer( &data, sizeof( data ) );
0451 return *this;
0452 }
0453
0454 StreamBuffer& operator>>( char* data ) {
0455 long i, len;
0456 *this >> len;
0457 for ( i = 0, data[0] = 0; i < len; i++ ) { data[i] = m_buffer[m_pointer++]; }
0458 return *this;
0459 }
0460
0461 StreamBuffer& operator<<( const char* data ) {
0462 const char* ptr = 0 == data ? "" : data;
0463 size_t len = strlen( ptr ) + 1;
0464 if ( 0 == m_analyzer )
0465 writeBytes( ptr, len );
0466 else { STREAM_ANALYSE( data, len ); }
0467 return *this;
0468 }
0469
0470 StreamBuffer& operator>>( std::string& data ) {
0471 long i, len;
0472 *this >> len;
0473 for ( i = 0, data = ""; i < len; i++ ) { data.append( 1, m_buffer[m_pointer++] ); }
0474 return *this;
0475 }
0476
0477 StreamBuffer& operator<<( const std::string& data ) {
0478 if ( 0 == m_analyzer ) {
0479 const char* ptr = data.c_str();
0480 long len = data.length();
0481 writeBytes( ptr, len );
0482 } else {
0483 STREAM_ANALYSE( data, sizeof( data ) );
0484 }
0485 return *this;
0486 }
0487
0488
0489
0490
0491
0492
0493 template <class TYPE>
0494 StreamBuffer& operator>>( TYPE*& refpObject ) {
0495 return getObjectPointer( refpObject, refpObject );
0496 }
0497
0498
0499
0500
0501
0502
0503
0504 StreamBuffer& operator<<( const ContainedObject* pObject ) {
0505 STREAM_ANALYSE( pObject, sizeof( pObject ) );
0506 addContainedLink( pObject, INVALID, INVALID );
0507 return *this;
0508 }
0509
0510
0511
0512
0513
0514
0515
0516 StreamBuffer& operator<<( const DataObject* pObject ) {
0517 STREAM_ANALYSE( pObject, sizeof( pObject ) );
0518 addIdentifiedLink( pObject, INVALID );
0519 return *this;
0520 }
0521
0522
0523
0524
0525
0526
0527
0528 void serialize( DataIO& ioObject ) {
0529 ioObject.serialize( *this );
0530 m_pointer = 0;
0531 }
0532 };
0533
0534 #undef STREAM_ANALYSE
0535
0536
0537 inline StreamBuffer::SwapAction StreamBuffer::swapBuffer( int siz ) const {
0538 switch ( siz ) {
0539 case 1:
0540 return SINGLE_BYTE;
0541 default:
0542 #if defined( __alpha ) && !defined( __VMS )
0543
0544 return NOSWAP;
0545 #elif defined( __sun ) && defined( __SVR4 ) && defined( __i386 )
0546
0547 return NOSWAP;
0548 #elif defined( __APPLE__ )
0549
0550 return SWAP;
0551 #elif defined( __linux ) && !defined( __powerpc )
0552
0553 return NOSWAP;
0554 #elif defined( BORLAND ) || defined( _WIN32 ) || defined( WIN32 )
0555
0556 return NOSWAP;
0557 #else
0558 return m_swapEnabled ? SWAP : NOSWAP;
0559
0560 #endif
0561 }
0562 }
0563
0564
0565 inline void StreamBuffer::swapToBuffer( const void* source, int siz ) {
0566 char buff[8], *tar, *src = (char*)source;
0567 extend( m_pointer + siz );
0568 tar = m_buffer + m_pointer;
0569 switch ( swapBuffer( siz ) ) {
0570 case SINGLE_BYTE:
0571 *tar = *src;
0572 break;
0573 case SWAP:
0574 #ifdef __APPLE__
0575 for ( int i = 0, j = siz - 1; i < siz; i++, j-- ) tar[j] = src[i];
0576 #else
0577 ::_swab( src, buff, siz );
0578 #endif
0579 src = buff;
0580 [[fallthrough]];
0581 case NOSWAP:
0582 std::copy_n( src, siz, tar );
0583 break;
0584 default:
0585 break;
0586 }
0587 m_pointer += siz;
0588 }
0589
0590
0591 inline void StreamBuffer::swapFromBuffer( void* target, int siz ) {
0592 char* tar = (char*)target;
0593 char* src = m_buffer + m_pointer;
0594 switch ( swapBuffer( siz ) ) {
0595 case SINGLE_BYTE:
0596 *tar = *src;
0597 break;
0598 case SWAP:
0599 #ifdef __APPLE__
0600 for ( int i = 0, j = siz - 1; i < siz; i++, j-- ) tar[j] = src[i];
0601 #else
0602 ::_swab( src, tar, siz );
0603 #endif
0604 break;
0605 case NOSWAP:
0606 std::copy_n( src, siz, tar );
0607 break;
0608 default:
0609 break;
0610 }
0611 m_pointer += siz;
0612 }
0613
0614
0615 template <class T>
0616 inline StreamBuffer& operator<<( StreamBuffer& s, const std::vector<T>& v ) {
0617 s << v.size();
0618 for ( const auto& i : v ) s << i;
0619 return s;
0620 }
0621
0622
0623 template <class T>
0624 inline StreamBuffer& operator>>( StreamBuffer& s, std::vector<T>& v ) {
0625 long i, len;
0626 s >> len;
0627 v.clear();
0628 for ( i = 0; i < len; i++ ) {
0629 T temp;
0630 s >> temp;
0631 v.push_back( temp );
0632 }
0633 return s;
0634 }
0635
0636
0637 template <class T>
0638 inline StreamBuffer& operator<<( StreamBuffer& s, const std::list<T>& l ) {
0639 s << l.size();
0640 for ( const auto& i : l ) s << i;
0641 return s;
0642 }
0643
0644
0645 template <class T>
0646 inline StreamBuffer& operator>>( StreamBuffer& s, std::list<T>& l ) {
0647 long len;
0648 s >> len;
0649 l.clear();
0650 for ( long i = 0; i < len; i++ ) {
0651 T temp;
0652 s >> temp;
0653 l.push_back( temp );
0654 }
0655 return s;
0656 }
0657 #endif