00001
00002 #ifndef GAUDIKERNEL_STREAMBUFFER_H
00003 #define GAUDIKERNEL_STREAMBUFFER_H 1
00004
00005
00006 #include <vector>
00007 #include <string>
00008 #include <iostream>
00009 #include "GaudiKernel/swab.h"
00010
00011
00012 class IDataDirectory;
00013 class StreamBuffer;
00014 class DataObject;
00015 class ContainedObject;
00016
00035 class StreamBuffer {
00036 public:
00038 class DataIO {
00039 public:
00041 DataIO() {
00042 }
00044 virtual ~DataIO() {
00045 }
00047 void badStreamMode() {
00048 throw("Not acceptable stream mode!");
00049 }
00051 virtual void serialize(StreamBuffer& stream) {
00052 if (stream.isReading())
00053 load(stream);
00054 else if (stream.isWriting())
00055 dump(stream);
00056 else
00057 badStreamMode();
00058 }
00060 virtual void load(StreamBuffer&) {
00061 badStreamMode();
00062 }
00064 virtual void dump(StreamBuffer&) {
00065 badStreamMode();
00066 }
00067 };
00068
00070 class Istream : public DataIO {
00072 std::istream* m_stream;
00073 public:
00075 Istream(std::istream& str) : m_stream(&str) {
00076 }
00078 virtual ~Istream() {
00079 }
00081 virtual void load(StreamBuffer& stream) {
00082
00083 int len;
00084 (*m_stream) >> len;
00085 stream.erase();
00086 stream.reserve(len);
00087 m_stream->read(stream.data(),len);
00088 }
00089 };
00091 class Ostream : public DataIO {
00092 std::ostream* m_stream;
00093 public:
00095 Ostream(std::ostream& str) : m_stream(&str) {
00096 }
00098 virtual ~Ostream() {
00099 }
00101 virtual void dump(StreamBuffer& stream) {
00102
00103 (*m_stream) << stream.buffPointer();
00104 m_stream->write(stream.data(), stream.buffPointer());
00105 }
00106 };
00107 public:
00109 enum Mode {UNINITIALIZED, READING, WRITING};
00111 enum SwapAction {SINGLE_BYTE, SWAP, NOSWAP};
00113 enum State {INVALID=-1, VALID };
00115 class ContainedLink {
00116 public:
00117 ContainedObject* first;
00118 long second;
00119 long third;
00120 ContainedLink() : first(0), second(INVALID), third(INVALID) {
00121 }
00122 ContainedLink(const ContainedLink& copy)
00123 : first(copy.first), second(copy.second), third(copy.third) {
00124 }
00125 ContainedLink(ContainedObject* pObj, long hint, long link)
00126 : first(pObj), second(hint), third(link) {
00127 }
00128 };
00130 class IdentifiedLink {
00131 public:
00132 DataObject* first;
00133 long second;
00134 IdentifiedLink() : first(0), second(INVALID) {
00135 }
00136 IdentifiedLink(const IdentifiedLink& copy)
00137 : first(copy.first), second(copy.second) {
00138 }
00139 IdentifiedLink(DataObject* pObj, long hint)
00140 : first(pObj), second(hint) {
00141 }
00142 };
00143
00144 typedef std::vector<ContainedLink> ContainedLinks;
00146 typedef std::vector<IdentifiedLink> IdentifiedLinks;
00148 typedef void (*AnalyzeFunction)(const void* data, int siz, const std::type_info& type);
00150 friend class DataObject;
00151
00152 protected:
00154 Mode m_mode;
00155
00157 long m_pointer;
00158
00160 long m_length;
00161
00163 char* m_buffer;
00164
00166 bool m_swapEnabled;
00167
00169 ContainedLinks m_containedLinks;
00170
00172 IdentifiedLinks m_identifiedLinks;
00173
00175 AnalyzeFunction m_analyzer;
00176
00178 SwapAction swapBuffer(int siz) const;
00179
00183 template <class TYPE> StreamBuffer& getObjectPointer(const DataObject* pObject, TYPE*& refpObject) {
00184 IdenfifiedLink& link = m_identifiedLinks.back();
00185 DataObject* pObj = link.first;
00186 m_identifiedLinks.pop_back();
00187 refpObject = dynamic_cast<TYPE*>(pObj);
00188 return *this;
00189 }
00193 template <class TYPE> StreamBuffer& getObjectPointer(const ContainedObject* pObject, TYPE*& refpObject) {
00194 ContainedLink& link = m_containedLinks.back();
00195 ContainedObject* pObj = link.first;
00196 m_containedLinks.pop_back();
00197 refpObject = dynamic_cast<TYPE*>(pObj);
00198 return *this;
00199 }
00200 public:
00202 StreamBuffer(bool do_swap=true) :
00203 m_mode(UNINITIALIZED),
00204 m_pointer(0),
00205 m_length(0),
00206 m_buffer(0),
00207 m_swapEnabled(do_swap)
00208 {
00209 m_analyzer = 0;
00210 }
00212 virtual ~StreamBuffer() {
00213 ::free( m_buffer );
00214 }
00216 const char* data() const {
00217 return m_buffer;
00218 }
00220 char* data() {
00221 return m_buffer;
00222 }
00224 void erase() {
00225 m_pointer = 0;
00226 }
00228 void reserve(long len) {
00229 if ( len > m_length ) {
00230 m_length = (len < 16384) ? 16384 : len;
00231 m_buffer = (char*)::realloc (m_buffer,m_length);
00232 }
00233 }
00235 void extend(long len) {
00236 if ( len + m_pointer > m_length ) {
00237
00238
00239 long new_len = (m_length < 16384) ? 16384 : 2*m_length;
00240 if ( m_length < len ) new_len += len;
00241 reserve(new_len);
00242 }
00243 }
00245 long size () const {
00246 return m_length;
00247 }
00249 ContainedLinks& containedLinks() {
00250 return m_containedLinks;
00251 }
00253 const ContainedLinks& containedLinks() const {
00254 return m_containedLinks;
00255 }
00256
00258 IdentifiedLinks& identifiedLinks() {
00259 return m_identifiedLinks;
00260 }
00262 const IdentifiedLinks& identifiedLinks() const {
00263 return m_identifiedLinks;
00264 }
00265
00267 void setMode(Mode m) {
00268 m_mode = m;
00269 m_pointer = 0;
00270 m_containedLinks.erase (m_containedLinks.begin(), m_containedLinks.end());
00271 m_identifiedLinks.erase(m_identifiedLinks.begin(),m_identifiedLinks.end());
00272 }
00273
00275 bool isReading() const {
00276 return m_mode == READING;
00277 }
00278
00280 bool isWriting() const {
00281 return m_mode == WRITING;
00282 }
00284 long buffPointer() const {
00285 return m_pointer;
00286 }
00288 void setBuffPointer(long ptr) {
00289 m_pointer = ptr;
00290 }
00292 void setAnalyzer(AnalyzeFunction fun=0) {
00293 m_analyzer = fun;
00294 }
00296 void swapToBuffer(const void* source, int siz);
00297
00299 void swapFromBuffer(void* target, int siz);
00300
00302 StreamBuffer& writeBytes (const char* str, long len) {
00303 extend( m_pointer+len+4 );
00304 *this << len;
00305 memcpy(data()+buffPointer(), str, len);
00306 m_pointer += len;
00307 return *this;
00308 }
00309
00310 void getIdentifiedLink (DataObject*& pObject, long& hint) {
00311 IdentifiedLink& l = m_identifiedLinks.back();
00312 pObject = l.first;
00313 hint = l.second;
00314 m_identifiedLinks.pop_back();
00315 }
00316 void addIdentifiedLink (const DataObject* pObject, long hint) {
00317 m_identifiedLinks.push_back( IdentifiedLink((DataObject*)pObject, hint) );
00318 }
00319
00320 void getContainedLink (ContainedObject*& pObject, long& hint, long& link) {
00321 ContainedLink& l = m_containedLinks.back();
00322 pObject = l.first;
00323 hint = l.second;
00324 link = l.third;
00325 m_containedLinks.pop_back();
00326 }
00327 void addContainedLink (const ContainedObject* pObject, long hint, long link) {
00328 m_containedLinks.push_back( ContainedLink((ContainedObject*)pObject, hint, link) );
00329 }
00330
00331 #ifdef USE_STREAM_ANALYSER
00332 #define STREAM_ANALYSE(data, len) if ( 0 != m_analyzer ) m_analyzer(&data, len, typeid(data))
00333 #else
00334 #define STREAM_ANALYSE(data, len)
00335 #endif
00336
00337
00338 #define IMPLEMENT_STREAMER(TYPE) \
00339 \
00340 StreamBuffer& operator<<(TYPE data) { \
00341 swapToBuffer(&data, sizeof(data)); \
00342 STREAM_ANALYSE(data, sizeof(data)); \
00343 return *this; \
00344 } \
00345 \
00346 StreamBuffer& operator>>(TYPE & data) { \
00347 swapFromBuffer(&data, sizeof(data)); \
00348 return *this; \
00349 }
00350
00351
00352 #undef IMPLEMENT_STREAMER
00353
00355 StreamBuffer& operator<<(int data) {
00356 swapToBuffer(&data, sizeof(data));
00357 STREAM_ANALYSE(data, sizeof(data));
00358 return *this;
00359 }
00361 StreamBuffer& operator>>(int & data) {
00362 swapFromBuffer(&data, sizeof(data));
00363 return *this;
00364 }
00366 StreamBuffer& operator<<(unsigned int data) {
00367 swapToBuffer(&data, sizeof(data));
00368 STREAM_ANALYSE(data, sizeof(data));
00369 return *this;
00370 }
00372 StreamBuffer& operator>>(unsigned int & data) {
00373 swapFromBuffer(&data, sizeof(data));
00374 return *this;
00375 }
00377 StreamBuffer& operator<<(long data) {
00378 swapToBuffer(&data, sizeof(data));
00379 STREAM_ANALYSE(data, sizeof(data));
00380 return *this;
00381 }
00383 StreamBuffer& operator>>(long & data) {
00384 swapFromBuffer(&data, sizeof(data));
00385 return *this;
00386 }
00388 StreamBuffer& operator<<(unsigned long data) {
00389 swapToBuffer(&data, sizeof(data));
00390 STREAM_ANALYSE(data, sizeof(data));
00391 return *this;
00392 }
00394 StreamBuffer& operator>>(unsigned long & data) {
00395 swapFromBuffer(&data, sizeof(data));
00396 return *this;
00397 }
00399 StreamBuffer& operator<<(short data) {
00400 swapToBuffer(&data, sizeof(data));
00401 STREAM_ANALYSE(data, sizeof(data));
00402 return *this;
00403 }
00405 StreamBuffer& operator>>(short & data) {
00406 swapFromBuffer(&data, sizeof(data));
00407 return *this;
00408 }
00410 StreamBuffer& operator<<(unsigned short data) {
00411 swapToBuffer(&data, sizeof(data));
00412 STREAM_ANALYSE(data, sizeof(data));
00413 return *this;
00414 }
00416 StreamBuffer& operator>>(unsigned short & data) {
00417 swapFromBuffer(&data, sizeof(data));
00418 return *this;
00419 }
00421 StreamBuffer& operator<<(char data) {
00422 swapToBuffer(&data, sizeof(data));
00423 STREAM_ANALYSE(data, sizeof(data));
00424 return *this;
00425 }
00427 StreamBuffer& operator>>(char & data) {
00428 swapFromBuffer(&data, sizeof(data));
00429 return *this;
00430 }
00432 StreamBuffer& operator<<(unsigned char data) {
00433 swapToBuffer(&data, sizeof(data));
00434 STREAM_ANALYSE(data, sizeof(data));
00435 return *this;
00436 }
00438 StreamBuffer& operator>>(unsigned char & data) {
00439 swapFromBuffer(&data, sizeof(data));
00440 return *this;
00441 }
00443 StreamBuffer& operator<<(float data) {
00444 swapToBuffer(&data, sizeof(data));
00445 STREAM_ANALYSE(data, sizeof(data));
00446 return *this;
00447 }
00449 StreamBuffer& operator>>(float & data) {
00450 swapFromBuffer(&data, sizeof(data));
00451 return *this;
00452 }
00454 StreamBuffer& operator<<(double data) {
00455 swapToBuffer(&data, sizeof(data));
00456 STREAM_ANALYSE(data, sizeof(data));
00457 return *this;
00458 }
00460 StreamBuffer& operator>>(double & data) {
00461 swapFromBuffer(&data, sizeof(data));
00462 return *this;
00463 }
00465 StreamBuffer& operator>>(char* data) {
00466 long i, len;
00467 *this >> len;
00468 for ( i = 0, data[0]=0; i < len; i++ ) {
00469 *data = m_buffer[m_pointer++];
00470 }
00471 return *this;
00472 }
00474 StreamBuffer& operator<<(const char *data) {
00475 const char* ptr = 0 == data ? "" : data;
00476 int len = strlen(ptr)+1;
00477 if ( 0 == m_analyzer )
00478 writeBytes(ptr, len);
00479 else {
00480 STREAM_ANALYSE(data, len);
00481 }
00482 return *this;
00483 }
00485 StreamBuffer& operator>>(std::string& data) {
00486 long i, len;
00487 *this >> len;
00488 for ( i = 0, data = ""; i < len; i++ ) {
00489 data.append( 1, m_buffer[m_pointer++] );
00490 }
00491 return *this;
00492 }
00494 StreamBuffer& operator<<(const std::string& data) {
00495 if ( 0 == m_analyzer) {
00496 const char* ptr = data.c_str();
00497 long len = data.length();
00498 writeBytes(ptr, len);
00499 }
00500 else {
00501 STREAM_ANALYSE(&data, sizeof(data));
00502 }
00503 return *this;
00504 }
00511 template<class TYPE> StreamBuffer& operator>>(TYPE*& refpObject) {
00512 return getObjectPointer(refpObject, refpObject);
00513 }
00514
00521 StreamBuffer& operator<<(const ContainedObject* pObject) {
00522 STREAM_ANALYSE(pObjecta, sizeof(pObject));
00523 addContainedLink(pObject, INVALID, INVALID);
00524 return *this;
00525 }
00526
00533 StreamBuffer& operator<<(const DataObject* pObject) {
00534 STREAM_ANALYSE(pObjecta, sizeof(pObject));
00535 addIdentifiedLink(pObject, INVALID);
00536 return *this;
00537 }
00538
00545 void serialize(DataIO& ioObject) {
00546 ioObject.serialize ( *this );
00547 m_pointer = 0;
00548 }
00549 };
00550
00551 #undef STREAM_ANALYSE
00552
00554 inline StreamBuffer::SwapAction StreamBuffer::swapBuffer(int siz) const {
00555 switch(siz) {
00556 case 1:
00557 return SINGLE_BYTE;
00558 default:
00559 #if defined(__alpha) && !defined(__VMS)
00560
00561 return NOSWAP;
00562 #elif defined(__sun) && defined(__SVR4) && defined(__i386)
00563
00564 return NOSWAP;
00565 #elif defined(__linux) && !defined(__powerpc)
00566
00567 return NOSWAP;
00568 #elif defined(BORLAND) || defined(_WIN32) || defined(WIN32)
00569
00570 return NOSWAP;
00571 #else
00572 return m_swapEnabled ? SWAP : NOSWAP;
00573
00574 #endif
00575 }
00576 }
00577
00579 inline void StreamBuffer::swapToBuffer(const void* source, int siz) {
00580 char buff[8], *tar, *src = (char*)source;
00581 extend (m_pointer+siz);
00582 tar = (char*)m_buffer+m_pointer;
00583 switch ( swapBuffer(siz) ) {
00584 case SINGLE_BYTE:
00585 *tar = *src;
00586 break;
00587 case SWAP:
00588 ::_swab (src, buff, siz);
00589 src = buff;
00590 case NOSWAP:
00591 memcpy(tar, src, siz);
00592 break;
00593 }
00594 m_pointer += siz;
00595 }
00596
00598 inline void StreamBuffer::swapFromBuffer(void* target, int siz) {
00599 char* tar = (char*)target;
00600 char* src = (char*)m_buffer+m_pointer;
00601 switch ( swapBuffer(siz) ) {
00602 case SINGLE_BYTE:
00603 *tar = *src;
00604 break;
00605 case SWAP:
00606 ::_swab (src, tar, siz);
00607 break;
00608 case NOSWAP:
00609 ::memcpy(tar, src, siz);
00610 break;
00611 }
00612 m_pointer += siz;
00613 }
00614 #endif // GAUDIKERNEL_STREAMBUFFER_H