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
00013 #include "GaudiKernel/Kernel.h"
00014 #include "GaudiKernel/swab.h"
00015
00016
00017 class StreamBuffer;
00018 class DataObject;
00019 class ContainedObject;
00020
00039 class StreamBuffer {
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
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
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
00242
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
00342 #define IMPLEMENT_STREAMER(TYPE) \
00343 \
00344 StreamBuffer& operator<<(TYPE data) { \
00345 swapToBuffer(&data, sizeof(data)); \
00346 STREAM_ANALYSE(data, sizeof(data)); \
00347 return *this; \
00348 } \
00349 \
00350 StreamBuffer& operator>>(TYPE & data) { \
00351 swapFromBuffer(&data, sizeof(data)); \
00352 return *this; \
00353 }
00354
00355
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
00576 return NOSWAP;
00577 #elif defined(__sun) && defined(__SVR4) && defined(__i386)
00578
00579 return NOSWAP;
00580 #elif defined(__APPLE__)
00581
00582 return SWAP;
00583 #elif defined(__linux) && !defined(__powerpc)
00584
00585 return NOSWAP;
00586 #elif defined(BORLAND) || defined(_WIN32) || defined(WIN32)
00587
00588 return NOSWAP;
00589 #else
00590 return m_swapEnabled ? SWAP : NOSWAP;
00591
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
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
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
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
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