![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Header: /local/reps/Gaudi/GaudiKernel/GaudiKernel/StreamBuffer.h,v 1.8 2003/11/26 08:33:59 mato Exp $ 00002 #ifndef GAUDIKERNEL_STREAMBUFFER_H 00003 #define GAUDIKERNEL_STREAMBUFFER_H 1 00004 00005 // STL include files 00006 #include <list> 00007 #include <vector> 00008 #include <string> 00009 #include <iostream> 00010 #include "GaudiKernel/Kernel.h" 00011 #include "GaudiKernel/swab.h" 00012 00013 // forward declarations 00014 class StreamBuffer; 00015 class DataObject; 00016 class ContainedObject; 00017 00036 class StreamBuffer /* : public std::string */ { 00037 public: 00039 class DataIO { 00040 public: 00042 DataIO() { 00043 } 00045 virtual ~DataIO() { 00046 } 00048 void badStreamMode() { 00049 throw("Not acceptable stream mode!"); 00050 } 00052 virtual void serialize(StreamBuffer& stream) { 00053 if (stream.isReading()) 00054 load(stream); 00055 else if (stream.isWriting()) 00056 dump(stream); 00057 else 00058 badStreamMode(); 00059 } 00061 virtual void load(StreamBuffer&) { 00062 badStreamMode(); 00063 } 00065 virtual void dump(StreamBuffer&) { 00066 badStreamMode(); 00067 } 00068 }; 00069 00071 class Istream : public DataIO { 00073 std::istream* m_stream; 00074 public: 00076 Istream(std::istream& str) : m_stream(&str) { 00077 } 00079 virtual ~Istream() { 00080 } 00082 virtual void load(StreamBuffer& stream) { 00083 // Generic implementation for istreams: 00084 int len; 00085 (*m_stream) >> len; 00086 stream.erase(); 00087 stream.reserve(len); 00088 m_stream->read(stream.data(),len); 00089 } 00090 }; 00092 class Ostream : public DataIO { 00093 std::ostream* m_stream; 00094 public: 00096 Ostream(std::ostream& str) : m_stream(&str) { 00097 } 00099 virtual ~Ostream() { 00100 } 00102 virtual void dump(StreamBuffer& stream) { 00103 // Generic implementation for ostreams: 00104 (*m_stream) << stream.buffPointer(); 00105 m_stream->write(stream.data(), stream.buffPointer()); 00106 } 00107 }; 00108 public: 00110 enum Mode {UNINITIALIZED, READING, WRITING}; 00112 enum SwapAction {SINGLE_BYTE, SWAP, NOSWAP}; 00114 enum State {INVALID=-1, VALID }; 00116 class ContainedLink { 00117 public: 00118 ContainedObject* first; 00119 long second; 00120 long third; 00121 ContainedLink() : first(0), second(INVALID), third(INVALID) { 00122 } 00123 ContainedLink(const ContainedLink& copy) 00124 : first(copy.first), second(copy.second), third(copy.third) { 00125 } 00126 ContainedLink(ContainedObject* pObj, long hint, long link) 00127 : first(pObj), second(hint), third(link) { 00128 } 00129 }; 00131 class IdentifiedLink { 00132 public: 00133 DataObject* first; 00134 long second; 00135 IdentifiedLink() : first(0), second(INVALID) { 00136 } 00137 IdentifiedLink(const IdentifiedLink& copy) 00138 : first(copy.first), second(copy.second) { 00139 } 00140 IdentifiedLink(DataObject* pObj, long hint) 00141 : first(pObj), second(hint) { 00142 } 00143 }; 00144 00145 typedef std::vector<ContainedLink> ContainedLinks; 00147 typedef std::vector<IdentifiedLink> IdentifiedLinks; 00149 typedef void (*AnalyzeFunction)(const void* data, int siz, const std::type_info& type); 00151 friend class DataObject; 00152 00153 protected: 00155 Mode m_mode; 00156 00158 long m_pointer; 00159 00161 long m_length; 00162 00164 char* m_buffer; 00165 00167 bool m_swapEnabled; 00168 00170 ContainedLinks m_containedLinks; 00171 00173 IdentifiedLinks m_identifiedLinks; 00174 00176 AnalyzeFunction m_analyzer; 00177 00179 SwapAction swapBuffer(int siz) const; 00180 00184 template <class TYPE> StreamBuffer& getObjectPointer(const DataObject* pObject, TYPE*& refpObject) { 00185 IdentifiedLink& link = m_identifiedLinks.back(); 00186 DataObject* pObj = link.first; 00187 m_identifiedLinks.pop_back(); 00188 refpObject = dynamic_cast<TYPE*>(pObj); 00189 return *this; 00190 } 00194 template <class TYPE> StreamBuffer& getObjectPointer(const ContainedObject* pObject, TYPE*& refpObject) { 00195 ContainedLink& link = m_containedLinks.back(); 00196 ContainedObject* pObj = link.first; 00197 m_containedLinks.pop_back(); 00198 refpObject = dynamic_cast<TYPE*>(pObj); 00199 return *this; 00200 } 00201 public: 00203 StreamBuffer(bool do_swap=true) : 00204 m_mode(UNINITIALIZED), 00205 m_pointer(0), 00206 m_length(0), 00207 m_buffer(0), 00208 m_swapEnabled(do_swap) 00209 { 00210 m_analyzer = 0; 00211 } 00213 virtual ~StreamBuffer() { 00214 ::free( m_buffer ); 00215 } 00217 const char* data() const { 00218 return m_buffer; 00219 } 00221 char* data() { 00222 return m_buffer; 00223 } 00225 void erase() { 00226 m_pointer = 0; 00227 } 00229 void reserve(long len) { 00230 if ( len > m_length ) { 00231 m_length = (len < 16384) ? 16384 : len; 00232 m_buffer = (char*)::realloc (m_buffer,m_length); 00233 } 00234 } 00236 void extend(long len) { 00237 if ( len + m_pointer > m_length ) { 00238 // We have to be a bit generous here in order not to run too often 00239 // into ::realloc(). 00240 long new_len = (m_length < 16384) ? 16384 : 2*m_length; 00241 if ( m_length < len ) new_len += len; 00242 reserve(new_len); 00243 } 00244 } 00246 long size () const { 00247 return m_length; 00248 } 00250 ContainedLinks& containedLinks() { 00251 return m_containedLinks; 00252 } 00254 const ContainedLinks& containedLinks() const { 00255 return m_containedLinks; 00256 } 00257 00259 IdentifiedLinks& identifiedLinks() { 00260 return m_identifiedLinks; 00261 } 00263 const IdentifiedLinks& identifiedLinks() const { 00264 return m_identifiedLinks; 00265 } 00266 00268 void setMode(Mode m) { 00269 m_mode = m; 00270 m_pointer = 0; 00271 m_containedLinks.erase (m_containedLinks.begin(), m_containedLinks.end()); 00272 m_identifiedLinks.erase(m_identifiedLinks.begin(),m_identifiedLinks.end()); 00273 } 00274 00276 bool isReading() const { 00277 return m_mode == READING; 00278 } 00279 00281 bool isWriting() const { 00282 return m_mode == WRITING; 00283 } 00285 long buffPointer() const { 00286 return m_pointer; 00287 } 00289 void setBuffPointer(long ptr) { 00290 m_pointer = ptr; 00291 } 00293 void setAnalyzer(AnalyzeFunction fun=0) { 00294 m_analyzer = fun; 00295 } 00297 void swapToBuffer(const void* source, int siz); 00298 00300 void swapFromBuffer(void* target, int siz); 00301 00303 StreamBuffer& writeBytes (const char* str, long len) { 00304 extend( m_pointer+len+4 ); 00305 *this << len; 00306 memcpy(data()+buffPointer(), str, len); 00307 m_pointer += len; 00308 return *this; 00309 } 00310 00311 void getIdentifiedLink (DataObject*& pObject, long& hint) { 00312 IdentifiedLink& l = m_identifiedLinks.back(); 00313 pObject = l.first; 00314 hint = l.second; 00315 m_identifiedLinks.pop_back(); 00316 } 00317 void addIdentifiedLink (const DataObject* pObject, long hint) { 00318 m_identifiedLinks.push_back( IdentifiedLink((DataObject*)pObject, hint) ); 00319 } 00320 00321 void getContainedLink (ContainedObject*& pObject, long& hint, long& link) { 00322 ContainedLink& l = m_containedLinks.back(); 00323 pObject = l.first; 00324 hint = l.second; 00325 link = l.third; 00326 m_containedLinks.pop_back(); 00327 } 00328 void addContainedLink (const ContainedObject* pObject, long hint, long link) { 00329 m_containedLinks.push_back( ContainedLink((ContainedObject*)pObject, hint, link) ); 00330 } 00331 00332 #ifdef USE_STREAM_ANALYSER 00333 #define STREAM_ANALYSE(data, len) if ( 0 != m_analyzer ) m_analyzer(&data, len, typeid(data)) 00334 #else 00335 #define STREAM_ANALYSE(data, len) 00336 #endif 00337 00338 // Implement streamer macros for primivive data types. 00339 #define IMPLEMENT_STREAMER(TYPE) \ 00340 /* Output Streamer */ \ 00341 StreamBuffer& operator<<(TYPE data) { \ 00342 swapToBuffer(&data, sizeof(data)); \ 00343 STREAM_ANALYSE(data, sizeof(data)); \ 00344 return *this; \ 00345 } \ 00346 /* Input Streamer */ \ 00347 StreamBuffer& operator>>(TYPE & data) { \ 00348 swapFromBuffer(&data, sizeof(data)); \ 00349 return *this; \ 00350 } 00351 // RootCint does not understand this macro.... 00352 // But we can easily live without it! 00353 #undef IMPLEMENT_STREAMER 00354 00356 StreamBuffer& operator<<(longlong data) { 00357 swapToBuffer(&data, sizeof(data)); 00358 STREAM_ANALYSE(data, sizeof(data)); 00359 return *this; 00360 } 00362 StreamBuffer& operator>>(longlong & data) { 00363 swapFromBuffer(&data, sizeof(data)); 00364 return *this; 00365 } 00367 StreamBuffer& operator<<(int data) { 00368 swapToBuffer(&data, sizeof(data)); 00369 STREAM_ANALYSE(data, sizeof(data)); 00370 return *this; 00371 } 00373 StreamBuffer& operator>>(int & data) { 00374 swapFromBuffer(&data, sizeof(data)); 00375 return *this; 00376 } 00378 StreamBuffer& operator<<(unsigned int data) { 00379 swapToBuffer(&data, sizeof(data)); 00380 STREAM_ANALYSE(data, sizeof(data)); 00381 return *this; 00382 } 00384 StreamBuffer& operator>>(unsigned int & data) { 00385 swapFromBuffer(&data, sizeof(data)); 00386 return *this; 00387 } 00389 StreamBuffer& operator<<(long data) { 00390 swapToBuffer(&data, sizeof(data)); 00391 STREAM_ANALYSE(data, sizeof(data)); 00392 return *this; 00393 } 00395 StreamBuffer& operator>>(long & data) { 00396 swapFromBuffer(&data, sizeof(data)); 00397 return *this; 00398 } 00400 StreamBuffer& operator<<(unsigned long data) { 00401 swapToBuffer(&data, sizeof(data)); 00402 STREAM_ANALYSE(data, sizeof(data)); 00403 return *this; 00404 } 00406 StreamBuffer& operator>>(unsigned long & data) { 00407 swapFromBuffer(&data, sizeof(data)); 00408 return *this; 00409 } 00411 StreamBuffer& operator<<(short data) { 00412 swapToBuffer(&data, sizeof(data)); 00413 STREAM_ANALYSE(data, sizeof(data)); 00414 return *this; 00415 } 00417 StreamBuffer& operator>>(short & data) { 00418 swapFromBuffer(&data, sizeof(data)); 00419 return *this; 00420 } 00422 StreamBuffer& operator<<(unsigned short data) { 00423 swapToBuffer(&data, sizeof(data)); 00424 STREAM_ANALYSE(data, sizeof(data)); 00425 return *this; 00426 } 00428 StreamBuffer& operator>>(unsigned short & data) { 00429 swapFromBuffer(&data, sizeof(data)); 00430 return *this; 00431 } 00433 StreamBuffer& operator<<(char data) { 00434 swapToBuffer(&data, sizeof(data)); 00435 STREAM_ANALYSE(data, sizeof(data)); 00436 return *this; 00437 } 00439 StreamBuffer& operator>>(char & data) { 00440 swapFromBuffer(&data, sizeof(data)); 00441 return *this; 00442 } 00444 StreamBuffer& operator<<(unsigned char data) { 00445 swapToBuffer(&data, sizeof(data)); 00446 STREAM_ANALYSE(data, sizeof(data)); 00447 return *this; 00448 } 00450 StreamBuffer& operator>>(unsigned char & data) { 00451 swapFromBuffer(&data, sizeof(data)); 00452 return *this; 00453 } 00455 StreamBuffer& operator<<(float data) { 00456 swapToBuffer(&data, sizeof(data)); 00457 STREAM_ANALYSE(data, sizeof(data)); 00458 return *this; 00459 } 00461 StreamBuffer& operator>>(float & data) { 00462 swapFromBuffer(&data, sizeof(data)); 00463 return *this; 00464 } 00466 StreamBuffer& operator<<(double data) { 00467 swapToBuffer(&data, sizeof(data)); 00468 STREAM_ANALYSE(data, sizeof(data)); 00469 return *this; 00470 } 00472 StreamBuffer& operator>>(double & data) { 00473 swapFromBuffer(&data, sizeof(data)); 00474 return *this; 00475 } 00477 StreamBuffer& operator>>(char* data) { 00478 long i, len; 00479 *this >> len; 00480 for ( i = 0, data[0]=0; i < len; i++ ) { 00481 data[i] = m_buffer[m_pointer++]; 00482 } 00483 return *this; 00484 } 00486 StreamBuffer& operator<<(const char *data) { 00487 const char* ptr = 0 == data ? "" : data; 00488 int len = strlen(ptr)+1; 00489 if ( 0 == m_analyzer ) 00490 writeBytes(ptr, len); 00491 else { 00492 STREAM_ANALYSE(data, len); 00493 } 00494 return *this; 00495 } 00497 StreamBuffer& operator>>(std::string& data) { 00498 long i, len; 00499 *this >> len; 00500 for ( i = 0, data = ""; i < len; i++ ) { 00501 data.append( 1, m_buffer[m_pointer++] ); 00502 } 00503 return *this; 00504 } 00506 StreamBuffer& operator<<(const std::string& data) { 00507 if ( 0 == m_analyzer) { 00508 const char* ptr = data.c_str(); 00509 long len = data.length(); 00510 writeBytes(ptr, len); 00511 } 00512 else { 00513 STREAM_ANALYSE(data, sizeof(data)); 00514 } 00515 return *this; 00516 } 00523 template<class TYPE> StreamBuffer& operator>>(TYPE*& refpObject) { 00524 return getObjectPointer(refpObject, refpObject); 00525 } 00526 00533 StreamBuffer& operator<<(const ContainedObject* pObject) { 00534 STREAM_ANALYSE(pObject, sizeof(pObject)); 00535 addContainedLink(pObject, INVALID, INVALID); 00536 return *this; 00537 } 00538 00545 StreamBuffer& operator<<(const DataObject* pObject) { 00546 STREAM_ANALYSE(pObject, sizeof(pObject)); 00547 addIdentifiedLink(pObject, INVALID); 00548 return *this; 00549 } 00550 00557 void serialize(DataIO& ioObject) { 00558 ioObject.serialize ( *this ); 00559 m_pointer = 0; 00560 } 00561 }; 00562 00563 #undef STREAM_ANALYSE 00564 00566 inline StreamBuffer::SwapAction StreamBuffer::swapBuffer(int siz) const { 00567 switch(siz) { 00568 case 1: 00569 return SINGLE_BYTE; 00570 default: 00571 #if defined(__alpha) && !defined(__VMS) 00572 // return m_swapEnabled ? SWAP : NOSWAP; 00573 return NOSWAP; 00574 #elif defined(__sun) && defined(__SVR4) && defined(__i386) 00575 // return m_swapEnabled ? SWAP : NOSWAP; 00576 return NOSWAP; 00577 #elif defined(__APPLE__) 00578 // return m_swapEnabled ? SWAP : NOSWAP; 00579 return SWAP; 00580 #elif defined(__linux) && !defined(__powerpc) 00581 // return m_swapEnabled ? SWAP : NOSWAP; 00582 return NOSWAP; 00583 #elif defined(BORLAND) || defined(_WIN32) || defined(WIN32) 00584 // return m_swapEnabled ? SWAP : NOSWAP; 00585 return NOSWAP; 00586 #else 00587 return m_swapEnabled ? SWAP : NOSWAP; 00588 // return NOSWAP; 00589 #endif 00590 } 00591 } 00592 00594 inline void StreamBuffer::swapToBuffer(const void* source, int siz) { 00595 char buff[8], *tar, *src = (char*)source; 00596 extend (m_pointer+siz); 00597 tar = (char*)m_buffer+m_pointer; 00598 switch ( swapBuffer(siz) ) { 00599 case SINGLE_BYTE: 00600 *tar = *src; 00601 break; 00602 case SWAP: 00603 #ifdef __APPLE__ 00604 for(int i = 0,j = siz-1;i<siz;i++,j--) tar[j] = src[i]; 00605 #else 00606 ::_swab (src, buff, siz); 00607 #endif 00608 src = buff; 00609 case NOSWAP: 00610 memcpy(tar, src, siz); 00611 break; 00612 } 00613 m_pointer += siz; 00614 } 00615 00617 inline void StreamBuffer::swapFromBuffer(void* target, int siz) { 00618 char* tar = (char*)target; 00619 char* src = (char*)m_buffer+m_pointer; 00620 switch ( swapBuffer(siz) ) { 00621 case SINGLE_BYTE: 00622 *tar = *src; 00623 break; 00624 case SWAP: 00625 #ifdef __APPLE__ 00626 for(int i = 0,j = siz-1;i<siz;i++,j--) tar[j] = src[i]; 00627 #else 00628 ::_swab (src, tar, siz); 00629 #endif 00630 break; 00631 case NOSWAP: 00632 ::memcpy(tar, src, siz); 00633 break; 00634 } 00635 m_pointer += siz; 00636 } 00637 00638 // Output serialize a vector of items 00639 template <class T> inline 00640 StreamBuffer& operator << (StreamBuffer& s, const std::vector<T>& v) { 00641 s << v.size(); 00642 for ( typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++ ) { 00643 s << (*i); 00644 } 00645 return s; 00646 } 00647 00648 // Input serialize a vector of items 00649 template <class T> inline 00650 StreamBuffer& operator >> (StreamBuffer& s, std::vector<T>& v) { 00651 long i, len; 00652 s >> len; 00653 v.clear(); 00654 for ( i = 0; i < len; i++ ) { 00655 T temp; 00656 s >> temp; 00657 v.push_back(temp); 00658 } 00659 return s; 00660 } 00661 00662 // Output serialize a list of items 00663 template <class T> inline 00664 StreamBuffer& operator << (StreamBuffer& s, const std::list<T>& l) { 00665 s << l.size(); 00666 for ( typename std::list<T>::const_iterator i = l.begin(); i != l.end(); i++ ) { 00667 s << (*i); 00668 } 00669 return s; 00670 } 00671 00672 // Input serialize a list of items 00673 template <class T> inline 00674 StreamBuffer& operator >> (StreamBuffer& s, std::list<T>& l) { 00675 long i, len; 00676 s >> len; 00677 l.clear(); 00678 for ( i = 0; i < len; i++ ) { 00679 T temp; 00680 s >> temp; 00681 l.push_back(temp); 00682 } 00683 return s; 00684 } 00685 #endif // GAUDIKERNEL_STREAMBUFFER_H