00001
00002 #ifndef GAUDIKERNEL_STREAMBUFFER_H
00003 #define GAUDIKERNEL_STREAMBUFFER_H 1
00004
00005
00006 #include <list>
00007 #include <vector>
00008 #include <string>
00009 #include <iostream>
00010 #include <cstring>
00011 #include <cstdlib>
00012 #include <typeinfo>
00013
00014 #include "GaudiKernel/Kernel.h"
00015 #include "GaudiKernel/swab.h"
00016
00017
00018 class StreamBuffer;
00019 class DataObject;
00020 class ContainedObject;
00021
00040 class StreamBuffer {
00041 public:
00043 class DataIO {
00044 public:
00046 DataIO() {
00047 }
00049 virtual ~DataIO() {
00050 }
00052 void badStreamMode() {
00053 throw("Not acceptable stream mode!");
00054 }
00056 virtual void serialize(StreamBuffer& stream) {
00057 if (stream.isReading())
00058 load(stream);
00059 else if (stream.isWriting())
00060 dump(stream);
00061 else
00062 badStreamMode();
00063 }
00065 virtual void load(StreamBuffer&) {
00066 badStreamMode();
00067 }
00069 virtual void dump(StreamBuffer&) {
00070 badStreamMode();
00071 }
00072 };
00073
00075 class Istream : public DataIO {
00077 std::istream* m_stream;
00078 public:
00080 Istream(std::istream& str) : m_stream(&str) {
00081 }
00083 virtual ~Istream() {
00084 }
00086 virtual void load(StreamBuffer& stream) {
00087
00088 int len;
00089 (*m_stream) >> len;
00090 stream.erase();
00091 stream.reserve(len);
00092 m_stream->read(stream.data(),len);
00093 }
00094 };
00096 class Ostream : public DataIO {
00097 std::ostream* m_stream;
00098 public:
00100 Ostream(std::ostream& str) : m_stream(&str) {
00101 }
00103 virtual ~Ostream() {
00104 }
00106 virtual void dump(StreamBuffer& stream) {
00107
00108 (*m_stream) << stream.buffPointer();
00109 m_stream->write(stream.data(), stream.buffPointer());
00110 }
00111 };
00112 public:
00114 enum Mode {UNINITIALIZED, READING, WRITING};
00116 enum SwapAction {SINGLE_BYTE, SWAP, NOSWAP};
00118 enum State {INVALID=-1, VALID };
00120 class ContainedLink {
00121 public:
00122 ContainedObject* first;
00123 long second;
00124 long third;
00125 ContainedLink() : first(0), second(INVALID), third(INVALID) {
00126 }
00127 ContainedLink(const ContainedLink& copy)
00128 : first(copy.first), second(copy.second), third(copy.third) {
00129 }
00130 ContainedLink(ContainedObject* pObj, long hint, long link)
00131 : first(pObj), second(hint), third(link) {
00132 }
00133 };
00135 class IdentifiedLink {
00136 public:
00137 DataObject* first;
00138 long second;
00139 IdentifiedLink() : first(0), second(INVALID) {
00140 }
00141 IdentifiedLink(const IdentifiedLink& copy)
00142 : first(copy.first), second(copy.second) {
00143 }
00144 IdentifiedLink(DataObject* pObj, long hint)
00145 : first(pObj), second(hint) {
00146 }
00147 };
00148
00149 typedef std::vector<ContainedLink> ContainedLinks;
00151 typedef std::vector<IdentifiedLink> IdentifiedLinks;
00153 typedef void (*AnalyzeFunction)(const void* data, int siz, const std::type_info& type);
00155 friend class DataObject;
00156
00157 protected:
00159 Mode m_mode;
00160
00162 long m_pointer;
00163
00165 long m_length;
00166
00168 char* m_buffer;
00169
00171 bool m_swapEnabled;
00172
00174 ContainedLinks m_containedLinks;
00175
00177 IdentifiedLinks m_identifiedLinks;
00178
00180 AnalyzeFunction m_analyzer;
00181
00183 SwapAction swapBuffer(int siz) const;
00184
00188 template <class TYPE> StreamBuffer& getObjectPointer(const DataObject* pObject, TYPE*& refpObject) {
00189 IdentifiedLink& link = m_identifiedLinks.back();
00190 DataObject* pObj = link.first;
00191 m_identifiedLinks.pop_back();
00192 refpObject = dynamic_cast<TYPE*>(pObj);
00193 return *this;
00194 }
00198 template <class TYPE> StreamBuffer& getObjectPointer(const ContainedObject* pObject, TYPE*& refpObject) {
00199 ContainedLink& link = m_containedLinks.back();
00200 ContainedObject* pObj = link.first;
00201 m_containedLinks.pop_back();
00202 refpObject = dynamic_cast<TYPE*>(pObj);
00203 return *this;
00204 }
00205 public:
00207 StreamBuffer(bool do_swap=true) :
00208 m_mode(UNINITIALIZED),
00209 m_pointer(0),
00210 m_length(0),
00211 m_buffer(0),
00212 m_swapEnabled(do_swap)
00213 {
00214 m_analyzer = 0;
00215 }
00217 virtual ~StreamBuffer() {
00218 ::free( m_buffer );
00219 }
00221 const char* data() const {
00222 return m_buffer;
00223 }
00225 char* data() {
00226 return m_buffer;
00227 }
00229 void erase() {
00230 m_pointer = 0;
00231 }
00233 void reserve(long len) {
00234 if ( len > m_length ) {
00235 m_length = (len < 16384) ? 16384 : len;
00236 m_buffer = (char*)::realloc (m_buffer,m_length);
00237 }
00238 }
00240 void extend(long len) {
00241 if ( len + m_pointer > m_length ) {
00242
00243
00244 long new_len = (m_length < 16384) ? 16384 : 2*m_length;
00245 if ( m_length < len ) new_len += len;
00246 reserve(new_len);
00247 }
00248 }
00250 long size () const {
00251 return m_length;
00252 }
00254 ContainedLinks& containedLinks() {
00255 return m_containedLinks;
00256 }
00258 const ContainedLinks& containedLinks() const {
00259 return m_containedLinks;
00260 }
00261
00263 IdentifiedLinks& identifiedLinks() {
00264 return m_identifiedLinks;
00265 }
00267 const IdentifiedLinks& identifiedLinks() const {
00268 return m_identifiedLinks;
00269 }
00270
00272 void setMode(Mode m) {
00273 m_mode = m;
00274 m_pointer = 0;
00275 m_containedLinks.erase (m_containedLinks.begin(), m_containedLinks.end());
00276 m_identifiedLinks.erase(m_identifiedLinks.begin(),m_identifiedLinks.end());
00277 }
00278
00280 bool isReading() const {
00281 return m_mode == READING;
00282 }
00283
00285 bool isWriting() const {
00286 return m_mode == WRITING;
00287 }
00289 long buffPointer() const {
00290 return m_pointer;
00291 }
00293 void setBuffPointer(long ptr) {
00294 m_pointer = ptr;
00295 }
00297 void setAnalyzer(AnalyzeFunction fun=0) {
00298 m_analyzer = fun;
00299 }
00301 void swapToBuffer(const void* source, int siz);
00302
00304 void swapFromBuffer(void* target, int siz);
00305
00307 StreamBuffer& writeBytes (const char* str, long len) {
00308 extend( m_pointer+len+4 );
00309 *this << len;
00310 memcpy(data()+buffPointer(), str, len);
00311 m_pointer += len;
00312 return *this;
00313 }
00314
00315 void getIdentifiedLink (DataObject*& pObject, long& hint) {
00316 IdentifiedLink& l = m_identifiedLinks.back();
00317 pObject = l.first;
00318 hint = l.second;
00319 m_identifiedLinks.pop_back();
00320 }
00321 void addIdentifiedLink (const DataObject* pObject, long hint) {
00322 m_identifiedLinks.push_back( IdentifiedLink((DataObject*)pObject, hint) );
00323 }
00324
00325 void getContainedLink (ContainedObject*& pObject, long& hint, long& link) {
00326 ContainedLink& l = m_containedLinks.back();
00327 pObject = l.first;
00328 hint = l.second;
00329 link = l.third;
00330 m_containedLinks.pop_back();
00331 }
00332 void addContainedLink (const ContainedObject* pObject, long hint, long link) {
00333 m_containedLinks.push_back( ContainedLink((ContainedObject*)pObject, hint, link) );
00334 }
00335
00336 #ifdef USE_STREAM_ANALYSER
00337 #define STREAM_ANALYSE(data, len) if ( 0 != m_analyzer ) m_analyzer(&data, len, typeid(data))
00338 #else
00339 #define STREAM_ANALYSE(data, len)
00340 #endif
00341
00342
00343 #define IMPLEMENT_STREAMER(TYPE) \
00344 \
00345 StreamBuffer& operator<<(TYPE data) { \
00346 swapToBuffer(&data, sizeof(data)); \
00347 STREAM_ANALYSE(data, sizeof(data)); \
00348 return *this; \
00349 } \
00350 \
00351 StreamBuffer& operator>>(TYPE & data) { \
00352 swapFromBuffer(&data, sizeof(data)); \
00353 return *this; \
00354 }
00355
00356
00357 #undef IMPLEMENT_STREAMER
00358
00360 StreamBuffer& operator<<(longlong data) {
00361 swapToBuffer(&data, sizeof(data));
00362 STREAM_ANALYSE(data, sizeof(data));
00363 return *this;
00364 }
00366 StreamBuffer& operator>>(longlong & data) {
00367 swapFromBuffer(&data, sizeof(data));
00368 return *this;
00369 }
00371 StreamBuffer& operator<<(int data) {
00372 swapToBuffer(&data, sizeof(data));
00373 STREAM_ANALYSE(data, sizeof(data));
00374 return *this;
00375 }
00377 StreamBuffer& operator>>(int & data) {
00378 swapFromBuffer(&data, sizeof(data));
00379 return *this;
00380 }
00382 StreamBuffer& operator<<(unsigned int data) {
00383 swapToBuffer(&data, sizeof(data));
00384 STREAM_ANALYSE(data, sizeof(data));
00385 return *this;
00386 }
00388 StreamBuffer& operator>>(unsigned int & data) {
00389 swapFromBuffer(&data, sizeof(data));
00390 return *this;
00391 }
00393 StreamBuffer& operator<<(long data) {
00394 swapToBuffer(&data, sizeof(data));
00395 STREAM_ANALYSE(data, sizeof(data));
00396 return *this;
00397 }
00399 StreamBuffer& operator>>(long & data) {
00400 swapFromBuffer(&data, sizeof(data));
00401 return *this;
00402 }
00404 StreamBuffer& operator<<(unsigned long data) {
00405 swapToBuffer(&data, sizeof(data));
00406 STREAM_ANALYSE(data, sizeof(data));
00407 return *this;
00408 }
00410 StreamBuffer& operator>>(unsigned long & data) {
00411 swapFromBuffer(&data, sizeof(data));
00412 return *this;
00413 }
00415 StreamBuffer& operator<<(short data) {
00416 swapToBuffer(&data, sizeof(data));
00417 STREAM_ANALYSE(data, sizeof(data));
00418 return *this;
00419 }
00421 StreamBuffer& operator>>(short & data) {
00422 swapFromBuffer(&data, sizeof(data));
00423 return *this;
00424 }
00426 StreamBuffer& operator<<(unsigned short data) {
00427 swapToBuffer(&data, sizeof(data));
00428 STREAM_ANALYSE(data, sizeof(data));
00429 return *this;
00430 }
00432 StreamBuffer& operator>>(unsigned short & data) {
00433 swapFromBuffer(&data, sizeof(data));
00434 return *this;
00435 }
00437 StreamBuffer& operator<<(char data) {
00438 swapToBuffer(&data, sizeof(data));
00439 STREAM_ANALYSE(data, sizeof(data));
00440 return *this;
00441 }
00443 StreamBuffer& operator>>(char & data) {
00444 swapFromBuffer(&data, sizeof(data));
00445 return *this;
00446 }
00448 StreamBuffer& operator<<(unsigned char data) {
00449 swapToBuffer(&data, sizeof(data));
00450 STREAM_ANALYSE(data, sizeof(data));
00451 return *this;
00452 }
00454 StreamBuffer& operator>>(unsigned char & data) {
00455 swapFromBuffer(&data, sizeof(data));
00456 return *this;
00457 }
00459 StreamBuffer& operator<<(float data) {
00460 swapToBuffer(&data, sizeof(data));
00461 STREAM_ANALYSE(data, sizeof(data));
00462 return *this;
00463 }
00465 StreamBuffer& operator>>(float & data) {
00466 swapFromBuffer(&data, sizeof(data));
00467 return *this;
00468 }
00470 StreamBuffer& operator<<(double data) {
00471 swapToBuffer(&data, sizeof(data));
00472 STREAM_ANALYSE(data, sizeof(data));
00473 return *this;
00474 }
00476 StreamBuffer& operator>>(double & data) {
00477 swapFromBuffer(&data, sizeof(data));
00478 return *this;
00479 }
00481 StreamBuffer& operator>>(char* data) {
00482 long i, len;
00483 *this >> len;
00484 for ( i = 0, data[0]=0; i < len; i++ ) {
00485 data[i] = m_buffer[m_pointer++];
00486 }
00487 return *this;
00488 }
00490 StreamBuffer& operator<<(const char *data) {
00491 const char* ptr = 0 == data ? "" : data;
00492 int len = strlen(ptr)+1;
00493 if ( 0 == m_analyzer )
00494 writeBytes(ptr, len);
00495 else {
00496 STREAM_ANALYSE(data, len);
00497 }
00498 return *this;
00499 }
00501 StreamBuffer& operator>>(std::string& data) {
00502 long i, len;
00503 *this >> len;
00504 for ( i = 0, data = ""; i < len; i++ ) {
00505 data.append( 1, m_buffer[m_pointer++] );
00506 }
00507 return *this;
00508 }
00510 StreamBuffer& operator<<(const std::string& data) {
00511 if ( 0 == m_analyzer) {
00512 const char* ptr = data.c_str();
00513 long len = data.length();
00514 writeBytes(ptr, len);
00515 }
00516 else {
00517 STREAM_ANALYSE(data, sizeof(data));
00518 }
00519 return *this;
00520 }
00527 template<class TYPE> StreamBuffer& operator>>(TYPE*& refpObject) {
00528 return getObjectPointer(refpObject, refpObject);
00529 }
00530
00537 StreamBuffer& operator<<(const ContainedObject* pObject) {
00538 STREAM_ANALYSE(pObject, sizeof(pObject));
00539 addContainedLink(pObject, INVALID, INVALID);
00540 return *this;
00541 }
00542
00549 StreamBuffer& operator<<(const DataObject* pObject) {
00550 STREAM_ANALYSE(pObject, sizeof(pObject));
00551 addIdentifiedLink(pObject, INVALID);
00552 return *this;
00553 }
00554
00561 void serialize(DataIO& ioObject) {
00562 ioObject.serialize ( *this );
00563 m_pointer = 0;
00564 }
00565 };
00566
00567 #undef STREAM_ANALYSE
00568
00570 inline StreamBuffer::SwapAction StreamBuffer::swapBuffer(int siz) const {
00571 switch(siz) {
00572 case 1:
00573 return SINGLE_BYTE;
00574 default:
00575 #if defined(__alpha) && !defined(__VMS)
00576
00577 return NOSWAP;
00578 #elif defined(__sun) && defined(__SVR4) && defined(__i386)
00579
00580 return NOSWAP;
00581 #elif defined(__APPLE__)
00582
00583 return SWAP;
00584 #elif defined(__linux) && !defined(__powerpc)
00585
00586 return NOSWAP;
00587 #elif defined(BORLAND) || defined(_WIN32) || defined(WIN32)
00588
00589 return NOSWAP;
00590 #else
00591 return m_swapEnabled ? SWAP : NOSWAP;
00592
00593 #endif
00594 }
00595 }
00596
00598 inline void StreamBuffer::swapToBuffer(const void* source, int siz) {
00599 char buff[8], *tar, *src = (char*)source;
00600 extend (m_pointer+siz);
00601 tar = (char*)m_buffer+m_pointer;
00602 switch ( swapBuffer(siz) ) {
00603 case SINGLE_BYTE:
00604 *tar = *src;
00605 break;
00606 case SWAP:
00607 #ifdef __APPLE__
00608 for(int i = 0,j = siz-1;i<siz;i++,j--) tar[j] = src[i];
00609 #else
00610 ::_swab (src, buff, siz);
00611 #endif
00612 src = buff;
00613 case NOSWAP:
00614 memcpy(tar, src, siz);
00615 break;
00616 }
00617 m_pointer += siz;
00618 }
00619
00621 inline void StreamBuffer::swapFromBuffer(void* target, int siz) {
00622 char* tar = (char*)target;
00623 char* src = (char*)m_buffer+m_pointer;
00624 switch ( swapBuffer(siz) ) {
00625 case SINGLE_BYTE:
00626 *tar = *src;
00627 break;
00628 case SWAP:
00629 #ifdef __APPLE__
00630 for(int i = 0,j = siz-1;i<siz;i++,j--) tar[j] = src[i];
00631 #else
00632 ::_swab (src, tar, siz);
00633 #endif
00634 break;
00635 case NOSWAP:
00636 ::memcpy(tar, src, siz);
00637 break;
00638 }
00639 m_pointer += siz;
00640 }
00641
00642
00643 template <class T> inline
00644 StreamBuffer& operator << (StreamBuffer& s, const std::vector<T>& v) {
00645 s << v.size();
00646 for ( typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++ ) {
00647 s << (*i);
00648 }
00649 return s;
00650 }
00651
00652
00653 template <class T> inline
00654 StreamBuffer& operator >> (StreamBuffer& s, std::vector<T>& v) {
00655 long i, len;
00656 s >> len;
00657 v.clear();
00658 for ( i = 0; i < len; i++ ) {
00659 T temp;
00660 s >> temp;
00661 v.push_back(temp);
00662 }
00663 return s;
00664 }
00665
00666
00667 template <class T> inline
00668 StreamBuffer& operator << (StreamBuffer& s, const std::list<T>& l) {
00669 s << l.size();
00670 for ( typename std::list<T>::const_iterator i = l.begin(); i != l.end(); i++ ) {
00671 s << (*i);
00672 }
00673 return s;
00674 }
00675
00676
00677 template <class T> inline
00678 StreamBuffer& operator >> (StreamBuffer& s, std::list<T>& l) {
00679 long i, len;
00680 s >> len;
00681 l.clear();
00682 for ( i = 0; i < len; i++ ) {
00683 T temp;
00684 s >> temp;
00685 l.push_back(temp);
00686 }
00687 return s;
00688 }
00689 #endif // GAUDIKERNEL_STREAMBUFFER_H