| # Gaudi Framework, version v21r11 |

Home |  | Generated: 30 Sep 2010

# StreamBuffer.h

Go to the documentation of this file.

    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 #include <typeinfo>
    00013
    00014 #include "GaudiKernel/Kernel.h"
    00015 #include "GaudiKernel/swab.h"
    00016
    00017 // forward declarations
    00018 class StreamBuffer;
    00019 class DataObject;
    00020 class ContainedObject;
    00021
    00040 class StreamBuffer /* : public std::string  */  {
    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       // Generic implementation for istreams:
    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       // Generic implementation for ostreams:
    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       // We have to be a bit generous here in order not to run too often
    00243       // into ::realloc().
    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   // Implement streamer macros for primivive data types.
    00343 #define IMPLEMENT_STREAMER(TYPE)                                    \
    00344   /*  Output Streamer                                   */          \
    00345   StreamBuffer& operator<<(TYPE   data)     {                       \
    00346     swapToBuffer(&data, sizeof(data));                              \
    00347     STREAM_ANALYSE(data, sizeof(data));                             \
    00348     return *this;                                                   \
    00349   }                                                                 \
    00350   /*  Input Streamer                                    */          \
    00351   StreamBuffer& operator>>(TYPE & data)     {                       \
    00352     swapFromBuffer(&data, sizeof(data));                            \
    00353     return *this;                                                   \
    00354   }
    00355 // RootCint does not understand this macro....
    00356 // But we can easily live without it!
    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 //    return m_swapEnabled ? SWAP : NOSWAP;
    00577     return NOSWAP;
    00578 #elif defined(__sun) && defined(__SVR4) && defined(__i386)
    00579 //    return m_swapEnabled ? SWAP : NOSWAP;
    00580     return NOSWAP;
    00581 #elif defined(__APPLE__)
    00582 //    return m_swapEnabled ? SWAP : NOSWAP;
    00583     return SWAP;
    00584 #elif defined(__linux) && !defined(__powerpc)
    00585 //    return m_swapEnabled ? SWAP : NOSWAP;
    00586     return NOSWAP;
    00587 #elif defined(BORLAND) || defined(_WIN32) || defined(WIN32)
    00588 //    return m_swapEnabled ? SWAP : NOSWAP;
    00589     return NOSWAP;
    00590 #else
    00591     return m_swapEnabled ? SWAP : NOSWAP;
    00592 //    return NOSWAP;
    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 // Output serialize a vector of items
    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 // Input serialize a vector of items
    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 // Output serialize a list of items
    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 // Input serialize a list of items
    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