| # Gaudi Framework, version v21r10p1 |

Home |  | Generated: 29 Jul 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
    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