![]() |
|
|
Generated: 8 Jan 2009 |
00001 // $Header: /tmp/svngaudi/tmp.jEpFh25751/Gaudi/GaudiKernel/GaudiKernel/StreamBuffer.h,v 1.9 2008/10/27 16:41:33 marcocle 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 <cstring> 00011 #include <cstdlib> 00012 00013 #include "GaudiKernel/Kernel.h" 00014 #include "GaudiKernel/swab.h" 00015 00016 // forward declarations 00017 class StreamBuffer; 00018 class DataObject; 00019 class ContainedObject; 00020 00039 class StreamBuffer /* : public std::string */ { 00040 public: 00042 class DataIO { 00043 public: 00045 DataIO() { 00046 } 00048 virtual ~DataIO() { 00049 } 00051 void badStreamMode() { 00052 throw("Not acceptable stream mode!"); 00053 } 00055 virtual void serialize(StreamBuffer& stream) { 00056 if (stream.isReading()) 00057 load(stream); 00058 else if (stream.isWriting()) 00059 dump(stream); 00060 else 00061 badStreamMode(); 00062 } 00064 virtual void load(StreamBuffer&) { 00065 badStreamMode(); 00066 } 00068 virtual void dump(StreamBuffer&) { 00069 badStreamMode(); 00070 } 00071 }; 00072 00074 class Istream : public DataIO { 00076 std::istream* m_stream; 00077 public: 00079 Istream(std::istream& str) : m_stream(&str) { 00080 } 00082 virtual ~Istream() { 00083 } 00085 virtual void load(StreamBuffer& stream) { 00086 // Generic implementation for istreams: 00087 int len; 00088 (*m_stream) >> len; 00089 stream.erase(); 00090 stream.reserve(len); 00091 m_stream->read(stream.data(),len); 00092 } 00093 }; 00095 class Ostream : public DataIO { 00096 std::ostream* m_stream; 00097 public: 00099 Ostream(std::ostream& str) : m_stream(&str) { 00100 } 00102 virtual ~Ostream() { 00103 } 00105 virtual void dump(StreamBuffer& stream) { 00106 // Generic implementation for ostreams: 00107 (*m_stream) << stream.buffPointer(); 00108 m_stream->write(stream.data(), stream.buffPointer()); 00109 } 00110 }; 00111 public: 00113 enum Mode {UNINITIALIZED, READING, WRITING}; 00115 enum SwapAction {SINGLE_BYTE, SWAP, NOSWAP}; 00117 enum State {INVALID=-1, VALID }; 00119 class ContainedLink { 00120 public: 00121 ContainedObject* first; 00122 long second; 00123 long third; 00124 ContainedLink() : first(0), second(INVALID), third(INVALID) { 00125 } 00126 ContainedLink(const ContainedLink& copy) 00127 : first(copy.first), second(copy.second), third(copy.third) { 00128 } 00129 ContainedLink(ContainedObject* pObj, long hint, long link) 00130 : first(pObj), second(hint), third(link) { 00131 } 00132 }; 00134 class IdentifiedLink { 00135 public: 00136 DataObject* first; 00137 long second; 00138 IdentifiedLink() : first(0), second(INVALID) { 00139 } 00140 IdentifiedLink(const IdentifiedLink& copy) 00141 : first(copy.first), second(copy.second) { 00142 } 00143 IdentifiedLink(DataObject* pObj, long hint) 00144 : first(pObj), second(hint) { 00145 } 00146 }; 00147 00148 typedef std::vector<ContainedLink> ContainedLinks; 00150 typedef std::vector<IdentifiedLink> IdentifiedLinks; 00152 typedef void (*AnalyzeFunction)(const void* data, int siz, const std::type_info& type); 00154 friend class DataObject; 00155 00156 protected: 00158 Mode m_mode; 00159 00161 long m_pointer; 00162 00164 long m_length; 00165 00167 char* m_buffer; 00168 00170 bool m_swapEnabled; 00171 00173 ContainedLinks m_containedLinks; 00174 00176 IdentifiedLinks m_identifiedLinks; 00177 00179 AnalyzeFunction m_analyzer; 00180 00182 SwapAction swapBuffer(int siz) const; 00183 00187 template <class TYPE> StreamBuffer& getObjectPointer(const DataObject* pObject, TYPE*& refpObject) { 00188 IdentifiedLink& link = m_identifiedLinks.back(); 00189 DataObject* pObj = link.first; 00190 m_identifiedLinks.pop_back(); 00191 refpObject = dynamic_cast<TYPE*>(pObj); 00192 return *this; 00193 } 00197 template <class TYPE> StreamBuffer& getObjectPointer(const ContainedObject* pObject, TYPE*& refpObject) { 00198 ContainedLink& link = m_containedLinks.back(); 00199 ContainedObject* pObj = link.first; 00200 m_containedLinks.pop_back(); 00201 refpObject = dynamic_cast<TYPE*>(pObj); 00202 return *this; 00203 } 00204 public: 00206 StreamBuffer(bool do_swap=true) : 00207 m_mode(UNINITIALIZED), 00208 m_pointer(0), 00209 m_length(0), 00210 m_buffer(0), 00211 m_swapEnabled(do_swap) 00212 { 00213 m_analyzer = 0; 00214 } 00216 virtual ~StreamBuffer() { 00217 ::free( m_buffer ); 00218 } 00220 const char* data() const { 00221 return m_buffer; 00222 } 00224 char* data() { 00225 return m_buffer; 00226 } 00228 void erase() { 00229 m_pointer = 0; 00230 } 00232 void reserve(long len) { 00233 if ( len > m_length ) { 00234 m_length = (len < 16384) ? 16384 : len; 00235 m_buffer = (char*)::realloc (m_buffer,m_length); 00236 } 00237 } 00239 void extend(long len) { 00240 if ( len + m_pointer > m_length ) { 00241 // We have to be a bit generous here in order not to run too often 00242 // into ::realloc(). 00243 long new_len = (m_length < 16384) ? 16384 : 2*m_length; 00244 if ( m_length < len ) new_len += len; 00245 reserve(new_len); 00246 } 00247 } 00249 long size () const { 00250 return m_length; 00251 } 00253 ContainedLinks& containedLinks() { 00254 return m_containedLinks; 00255 } 00257 const ContainedLinks& containedLinks() const { 00258 return m_containedLinks; 00259 } 00260 00262 IdentifiedLinks& identifiedLinks() { 00263 return m_identifiedLinks; 00264 } 00266 const IdentifiedLinks& identifiedLinks() const { 00267 return m_identifiedLinks; 00268 } 00269 00271 void setMode(Mode m) { 00272 m_mode = m; 00273 m_pointer = 0; 00274 m_containedLinks.erase (m_containedLinks.begin(), m_containedLinks.end()); 00275 m_identifiedLinks.erase(m_identifiedLinks.begin(),m_identifiedLinks.end()); 00276 } 00277 00279 bool isReading() const { 00280 return m_mode == READING; 00281 } 00282 00284 bool isWriting() const { 00285 return m_mode == WRITING; 00286 } 00288 long buffPointer() const { 00289 return m_pointer; 00290 } 00292 void setBuffPointer(long ptr) { 00293 m_pointer = ptr; 00294 } 00296 void setAnalyzer(AnalyzeFunction fun=0) { 00297 m_analyzer = fun; 00298 } 00300 void swapToBuffer(const void* source, int siz); 00301 00303 void swapFromBuffer(void* target, int siz); 00304 00306 StreamBuffer& writeBytes (const char* str, long len) { 00307 extend( m_pointer+len+4 ); 00308 *this << len; 00309 memcpy(data()+buffPointer(), str, len); 00310 m_pointer += len; 00311 return *this; 00312 } 00313 00314 void getIdentifiedLink (DataObject*& pObject, long& hint) { 00315 IdentifiedLink& l = m_identifiedLinks.back(); 00316 pObject = l.first; 00317 hint = l.second; 00318 m_identifiedLinks.pop_back(); 00319 } 00320 void addIdentifiedLink (const DataObject* pObject, long hint) { 00321 m_identifiedLinks.push_back( IdentifiedLink((DataObject*)pObject, hint) ); 00322 } 00323 00324 void getContainedLink (ContainedObject*& pObject, long& hint, long& link) { 00325 ContainedLink& l = m_containedLinks.back(); 00326 pObject = l.first; 00327 hint = l.second; 00328 link = l.third; 00329 m_containedLinks.pop_back(); 00330 } 00331 void addContainedLink (const ContainedObject* pObject, long hint, long link) { 00332 m_containedLinks.push_back( ContainedLink((ContainedObject*)pObject, hint, link) ); 00333 } 00334 00335 #ifdef USE_STREAM_ANALYSER 00336 #define STREAM_ANALYSE(data, len) if ( 0 != m_analyzer ) m_analyzer(&data, len, typeid(data)) 00337 #else 00338 #define STREAM_ANALYSE(data, len) 00339 #endif 00340 00341 // Implement streamer macros for primivive data types. 00342 #define IMPLEMENT_STREAMER(TYPE) \ 00343 /* Output Streamer */ \ 00344 StreamBuffer& operator<<(TYPE data) { \ 00345 swapToBuffer(&data, sizeof(data)); \ 00346 STREAM_ANALYSE(data, sizeof(data)); \ 00347 return *this; \ 00348 } \ 00349 /* Input Streamer */ \ 00350 StreamBuffer& operator>>(TYPE & data) { \ 00351 swapFromBuffer(&data, sizeof(data)); \ 00352 return *this; \ 00353 } 00354 // RootCint does not understand this macro.... 00355 // But we can easily live without it! 00356 #undef IMPLEMENT_STREAMER 00357 00359 StreamBuffer& operator<<(longlong data) { 00360 swapToBuffer(&data, sizeof(data)); 00361 STREAM_ANALYSE(data, sizeof(data)); 00362 return *this; 00363 } 00365 StreamBuffer& operator>>(longlong & data) { 00366 swapFromBuffer(&data, sizeof(data)); 00367 return *this; 00368 } 00370 StreamBuffer& operator<<(int data) { 00371 swapToBuffer(&data, sizeof(data)); 00372 STREAM_ANALYSE(data, sizeof(data)); 00373 return *this; 00374 } 00376 StreamBuffer& operator>>(int & data) { 00377 swapFromBuffer(&data, sizeof(data)); 00378 return *this; 00379 } 00381 StreamBuffer& operator<<(unsigned int data) { 00382 swapToBuffer(&data, sizeof(data)); 00383 STREAM_ANALYSE(data, sizeof(data)); 00384 return *this; 00385 } 00387 StreamBuffer& operator>>(unsigned int & data) { 00388 swapFromBuffer(&data, sizeof(data)); 00389 return *this; 00390 } 00392 StreamBuffer& operator<<(long data) { 00393 swapToBuffer(&data, sizeof(data)); 00394 STREAM_ANALYSE(data, sizeof(data)); 00395 return *this; 00396 } 00398 StreamBuffer& operator>>(long & data) { 00399 swapFromBuffer(&data, sizeof(data)); 00400 return *this; 00401 } 00403 StreamBuffer& operator<<(unsigned long data) { 00404 swapToBuffer(&data, sizeof(data)); 00405 STREAM_ANALYSE(data, sizeof(data)); 00406 return *this; 00407 } 00409 StreamBuffer& operator>>(unsigned long & data) { 00410 swapFromBuffer(&data, sizeof(data)); 00411 return *this; 00412 } 00414 StreamBuffer& operator<<(short data) { 00415 swapToBuffer(&data, sizeof(data)); 00416 STREAM_ANALYSE(data, sizeof(data)); 00417 return *this; 00418 } 00420 StreamBuffer& operator>>(short & data) { 00421 swapFromBuffer(&data, sizeof(data)); 00422 return *this; 00423 } 00425 StreamBuffer& operator<<(unsigned short data) { 00426 swapToBuffer(&data, sizeof(data)); 00427 STREAM_ANALYSE(data, sizeof(data)); 00428 return *this; 00429 } 00431 StreamBuffer& operator>>(unsigned short & data) { 00432 swapFromBuffer(&data, sizeof(data)); 00433 return *this; 00434 } 00436 StreamBuffer& operator<<(char data) { 00437 swapToBuffer(&data, sizeof(data)); 00438 STREAM_ANALYSE(data, sizeof(data)); 00439 return *this; 00440 } 00442 StreamBuffer& operator>>(char & data) { 00443 swapFromBuffer(&data, sizeof(data)); 00444 return *this; 00445 } 00447 StreamBuffer& operator<<(unsigned char data) { 00448 swapToBuffer(&data, sizeof(data)); 00449 STREAM_ANALYSE(data, sizeof(data)); 00450 return *this; 00451 } 00453 StreamBuffer& operator>>(unsigned char & data) { 00454 swapFromBuffer(&data, sizeof(data)); 00455 return *this; 00456 } 00458 StreamBuffer& operator<<(float data) { 00459 swapToBuffer(&data, sizeof(data)); 00460 STREAM_ANALYSE(data, sizeof(data)); 00461 return *this; 00462 } 00464 StreamBuffer& operator>>(float & data) { 00465 swapFromBuffer(&data, sizeof(data)); 00466 return *this; 00467 } 00469 StreamBuffer& operator<<(double data) { 00470 swapToBuffer(&data, sizeof(data)); 00471 STREAM_ANALYSE(data, sizeof(data)); 00472 return *this; 00473 } 00475 StreamBuffer& operator>>(double & data) { 00476 swapFromBuffer(&data, sizeof(data)); 00477 return *this; 00478 } 00480 StreamBuffer& operator>>(char* data) { 00481 long i, len; 00482 *this >> len; 00483 for ( i = 0, data[0]=0; i < len; i++ ) { 00484 data[i] = m_buffer[m_pointer++]; 00485 } 00486 return *this; 00487 } 00489 StreamBuffer& operator<<(const char *data) { 00490 const char* ptr = 0 == data ? "" : data; 00491 int len = strlen(ptr)+1; 00492 if ( 0 == m_analyzer ) 00493 writeBytes(ptr, len); 00494 else { 00495 STREAM_ANALYSE(data, len); 00496 } 00497 return *this; 00498 } 00500 StreamBuffer& operator>>(std::string& data) { 00501 long i, len; 00502 *this >> len; 00503 for ( i = 0, data = ""; i < len; i++ ) { 00504 data.append( 1, m_buffer[m_pointer++] ); 00505 } 00506 return *this; 00507 } 00509 StreamBuffer& operator<<(const std::string& data) { 00510 if ( 0 == m_analyzer) { 00511 const char* ptr = data.c_str(); 00512 long len = data.length(); 00513 writeBytes(ptr, len); 00514 } 00515 else { 00516 STREAM_ANALYSE(data, sizeof(data)); 00517 } 00518 return *this; 00519 } 00526 template<class TYPE> StreamBuffer& operator>>(TYPE*& refpObject) { 00527 return getObjectPointer(refpObject, refpObject); 00528 } 00529 00536 StreamBuffer& operator<<(const ContainedObject* pObject) { 00537 STREAM_ANALYSE(pObject, sizeof(pObject)); 00538 addContainedLink(pObject, INVALID, INVALID); 00539 return *this; 00540 } 00541 00548 StreamBuffer& operator<<(const DataObject* pObject) { 00549 STREAM_ANALYSE(pObject, sizeof(pObject)); 00550 addIdentifiedLink(pObject, INVALID); 00551 return *this; 00552 } 00553 00560 void serialize(DataIO& ioObject) { 00561 ioObject.serialize ( *this ); 00562 m_pointer = 0; 00563 } 00564 }; 00565 00566 #undef STREAM_ANALYSE 00567 00569 inline StreamBuffer::SwapAction StreamBuffer::swapBuffer(int siz) const { 00570 switch(siz) { 00571 case 1: 00572 return SINGLE_BYTE; 00573 default: 00574 #if defined(__alpha) && !defined(__VMS) 00575 // return m_swapEnabled ? SWAP : NOSWAP; 00576 return NOSWAP; 00577 #elif defined(__sun) && defined(__SVR4) && defined(__i386) 00578 // return m_swapEnabled ? SWAP : NOSWAP; 00579 return NOSWAP; 00580 #elif defined(__APPLE__) 00581 // return m_swapEnabled ? SWAP : NOSWAP; 00582 return SWAP; 00583 #elif defined(__linux) && !defined(__powerpc) 00584 // return m_swapEnabled ? SWAP : NOSWAP; 00585 return NOSWAP; 00586 #elif defined(BORLAND) || defined(_WIN32) || defined(WIN32) 00587 // return m_swapEnabled ? SWAP : NOSWAP; 00588 return NOSWAP; 00589 #else 00590 return m_swapEnabled ? SWAP : NOSWAP; 00591 // return NOSWAP; 00592 #endif 00593 } 00594 } 00595 00597 inline void StreamBuffer::swapToBuffer(const void* source, int siz) { 00598 char buff[8], *tar, *src = (char*)source; 00599 extend (m_pointer+siz); 00600 tar = (char*)m_buffer+m_pointer; 00601 switch ( swapBuffer(siz) ) { 00602 case SINGLE_BYTE: 00603 *tar = *src; 00604 break; 00605 case SWAP: 00606 #ifdef __APPLE__ 00607 for(int i = 0,j = siz-1;i<siz;i++,j--) tar[j] = src[i]; 00608 #else 00609 ::_swab (src, buff, siz); 00610 #endif 00611 src = buff; 00612 case NOSWAP: 00613 memcpy(tar, src, siz); 00614 break; 00615 } 00616 m_pointer += siz; 00617 } 00618 00620 inline void StreamBuffer::swapFromBuffer(void* target, int siz) { 00621 char* tar = (char*)target; 00622 char* src = (char*)m_buffer+m_pointer; 00623 switch ( swapBuffer(siz) ) { 00624 case SINGLE_BYTE: 00625 *tar = *src; 00626 break; 00627 case SWAP: 00628 #ifdef __APPLE__ 00629 for(int i = 0,j = siz-1;i<siz;i++,j--) tar[j] = src[i]; 00630 #else 00631 ::_swab (src, tar, siz); 00632 #endif 00633 break; 00634 case NOSWAP: 00635 ::memcpy(tar, src, siz); 00636 break; 00637 } 00638 m_pointer += siz; 00639 } 00640 00641 // Output serialize a vector of items 00642 template <class T> inline 00643 StreamBuffer& operator << (StreamBuffer& s, const std::vector<T>& v) { 00644 s << v.size(); 00645 for ( typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++ ) { 00646 s << (*i); 00647 } 00648 return s; 00649 } 00650 00651 // Input serialize a vector of items 00652 template <class T> inline 00653 StreamBuffer& operator >> (StreamBuffer& s, std::vector<T>& v) { 00654 long i, len; 00655 s >> len; 00656 v.clear(); 00657 for ( i = 0; i < len; i++ ) { 00658 T temp; 00659 s >> temp; 00660 v.push_back(temp); 00661 } 00662 return s; 00663 } 00664 00665 // Output serialize a list of items 00666 template <class T> inline 00667 StreamBuffer& operator << (StreamBuffer& s, const std::list<T>& l) { 00668 s << l.size(); 00669 for ( typename std::list<T>::const_iterator i = l.begin(); i != l.end(); i++ ) { 00670 s << (*i); 00671 } 00672 return s; 00673 } 00674 00675 // Input serialize a list of items 00676 template <class T> inline 00677 StreamBuffer& operator >> (StreamBuffer& s, std::list<T>& l) { 00678 long i, len; 00679 s >> len; 00680 l.clear(); 00681 for ( i = 0; i < len; i++ ) { 00682 T temp; 00683 s >> temp; 00684 l.push_back(temp); 00685 } 00686 return s; 00687 } 00688 #endif // GAUDIKERNEL_STREAMBUFFER_H