Main MRPT website > C++ reference
MRPT logo

CStream.h

Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                   http://mrpt.sourceforge.net/                            |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  CSTREAM_H
00029 #define  CSTREAM_H
00030 
00031 #include <mrpt/utils/utils_defs.h>
00032 #include <mrpt/utils/CUncopiable.h>
00033 #include <mrpt/utils/CObject.h>
00034 #include <mrpt/utils/exceptions.h>
00035 
00036 namespace mrpt
00037 {
00038         namespace utils
00039         {
00040                 class BASE_IMPEXP CSerializable;
00041                 struct BASE_IMPEXP  CSerializablePtr;
00042                 class BASE_IMPEXP CMessage;
00043 
00044                 /** This base class is used to provide a unified interface to
00045                  *    files,memory buffers,..Please see the derived classes. This class is
00046                  *    largely inspired by Borland VCL "TStream" class. <br><br>
00047                  *  Apart of the "VCL like" methods, operators ">>" and "<<" have been
00048                  *    defined so that simple types (int,bool,char,float,char *,std::string,...)
00049                  *    can be directly written and read to and from any CStream easily.
00050                  *  Please, it is recomendable to read CSerializable documentation also.
00051                  *
00052                  * \sa CFileStream, CMemoryStream,CSerializable
00053                  */
00054                 class BASE_IMPEXP CStream
00055                 {
00056                 public:
00057                         /** Used in CStream::Seek
00058                           */
00059                         enum TSeekOrigin
00060                         {
00061                                 sFromBeginning = 0,
00062                                 sFromCurrent = 1,
00063                                 sFromEnd = 2
00064                         };
00065 
00066                 protected:
00067                         /** Introduces a pure virtual method responsible for reading from the stream.
00068                          */
00069                         virtual size_t  Read(void *Buffer, size_t Count) = 0;
00070 
00071                         /** Introduces a pure virtual method responsible for writing to the stream.
00072                          *  Write attempts to write up to Count bytes to Buffer, and returns the number of bytes actually written.
00073                          */
00074                         virtual size_t  Write(const void *Buffer, size_t Count) = 0;
00075                 public:
00076                         /* Constructor
00077                          */
00078                         CStream() { }
00079 
00080                         /* Destructor
00081                          */
00082                         virtual ~CStream();
00083 
00084                         /** Reads a block of bytes from the stream into Buffer
00085                          *      \exception std::exception On any error, or if ZERO bytes are read.
00086                          *  \return The amound of bytes actually read.
00087                          * \note This method is endianness-dependent. 
00088                          * \sa ReadBufferImmediate ; Important, see: ReadBufferFixEndianness, 
00089                          */
00090                         size_t  ReadBuffer(void *Buffer, size_t Count);
00091 
00092                         /** Reads a sequence of elemental datatypes, taking care of reordering their bytes from the MRPT stream standard (little endianness) to the format of the running architecture.
00093                          *  \param ElementCount The number of elements (not bytes) to read.
00094                          *  \param ptr A pointer to the first output element in an array (or std::vector<>, etc...).
00095                          *  \return The amound of *bytes* (not elements) actually read (under error situations, the last element may be invalid if the data stream abruptly ends).
00096                          *  Example of usage:
00097                          *  \code
00098                          *   uint32_t  N;
00099                          *   s >> N;
00100                          *   vector<float>  vec(N);
00101                          *   if (N) 
00102                          *     s.ReadBufferFixEndianness<float>(&vec[0],N);
00103                          *  \endcode
00104                          *      \exception std::exception On any error, or if ZERO bytes are read.
00105                          * \sa ReadBufferFixEndianness, ReadBuffer
00106                          */
00107                         template <typename T>
00108                         size_t  ReadBufferFixEndianness(T *ptr, size_t ElementCount)
00109                         {
00110                         #if !MRPT_IS_BIG_ENDIAN
00111                                 // little endian: no conversion needed.
00112                                 return ReadBuffer(ptr,ElementCount*sizeof(T));
00113                         #else
00114                                 // big endian: convert.
00115                                 const size_t nread = ReadBuffer(ptr,ElementCount*sizeof(T));
00116                                 for (size_t i=0;i<ElementCount;i++) mrpt::utils::reverseBytesInPlace(ptr[i]);
00117                                 return nread;
00118                         #endif
00119                         }
00120 
00121 
00122                         /** Reads a block of bytes from the stream into Buffer, and returns the amound of bytes actually read, without waiting for more extra bytes to arrive (just those already enqued in the stream).
00123                          *  Note that this method will fallback to ReadBuffer() in most CStream classes but in some hardware-related  classes.
00124                          *      \exception std::exception On any error, or if ZERO bytes are read.
00125                          */
00126                         virtual size_t  ReadBufferImmediate(void *Buffer, size_t Count) { return ReadBuffer(Buffer, Count); }
00127 
00128                         /** Writes a block of bytes to the stream from Buffer.
00129                          *      \exception std::exception On any error
00130                          *  \sa Important, see: WriteBufferFixEndianness
00131                          * \note This method is endianness-dependent. 
00132                          */
00133                         void  WriteBuffer (const void *Buffer, size_t Count);
00134 
00135 
00136 
00137                         /** Writes a sequence of elemental datatypes, taking care of reordering their bytes from the running architecture to MRPT stream standard (little endianness).
00138                          *  \param ElementCount The number of elements (not bytes) to write.
00139                          *  \param ptr A pointer to the first input element in an array (or std::vector<>, etc...).
00140                          *  Example of usage:
00141                          *  \code
00142                          *   vector<float>  vec = ...
00143                          *   uint32_t N = vec.size();
00144                          *   s << N
00145                          *   if (N) 
00146                          *     s.WriteBufferFixEndianness<float>(&vec[0],N);
00147                          *  \endcode
00148                          *  \exception std::exception On any error
00149                          *  \sa WriteBuffer
00150                          */
00151                         template <typename T>
00152                         void WriteBufferFixEndianness(const T *ptr, size_t ElementCount)
00153                         {
00154                         #if !MRPT_IS_BIG_ENDIAN
00155                                 // little endian: no conversion needed.
00156                                 return WriteBuffer(ptr,ElementCount*sizeof(T));
00157                         #else
00158                                 // big endian: the individual "<<" functions already convert endiannes
00159                                 for (size_t i=0;i<ElementCount;i++) (*this) << ptr[i];
00160                         #endif
00161                         }
00162 
00163 
00164                         /** Copies a specified number of bytes from one stream to another. */
00165                         size_t  CopyFrom(CStream* Source, size_t Count);
00166 
00167                         /** Introduces a pure virtual method for moving to a specified position in the streamed resource.
00168                          *   he Origin parameter indicates how to interpret the Offset parameter. Origin should be one of the following values:
00169                          *      - sFromBeginning        (Default) Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
00170                          *      - sFromCurrent          Offset is from the current position in the resource. Seek moves to Position + Offset.
00171                          *      - sFromEnd                      Offset is from the end of the resource. Offset must be <= 0 to indicate a number of bytes before the end of the file.
00172                          * \return Seek returns the new value of the Position property.
00173                          */
00174                         virtual uint64_t Seek(long Offset, CStream::TSeekOrigin Origin = sFromBeginning) = 0;
00175 
00176                         /** Returns the total amount of bytes in the stream.
00177                          */
00178                         virtual uint64_t getTotalBytesCount() = 0;
00179 
00180                         /** Method for getting the current cursor position, where 0 is the first byte and TotalBytesCount-1 the last one.
00181                          */
00182                         virtual uint64_t getPosition() =0;
00183 
00184                         /** Writes an object to the stream.
00185                          */
00186                         void WriteObject( const CSerializable *o );
00187 
00188                         /** Reads an object from stream, its class determined at runtime, and returns a smart pointer to the object.
00189                          * \exception std::exception On I/O error or undefined class.
00190                          * \exception mrpt::utils::CExceptionEOF On an End-Of-File condition found at a correct place: an EOF that abruptly finishes in the middle of one object raises a plain std::exception instead.
00191                          */
00192                         CSerializablePtr ReadObject();
00193 
00194                         /** Reads an object from stream, where its class must be the same
00195                          *    as the supplied object, where the loaded object will be stored in.
00196                          * \exception std::exception On I/O error or different class found.
00197                          * \exception mrpt::utils::CExceptionEOF On an End-Of-File condition found at a correct place: an EOF that abruptly finishes in the middle of one object raises a plain std::exception instead.
00198                          */
00199                         void ReadObject(CSerializable *existingObj);
00200 
00201                         /** Write an object to a stream in the binary MRPT format. */
00202                         CStream& operator << (const CSerializablePtr & pObj);
00203                         /** Write an object to a stream in the binary MRPT format. */
00204                         CStream& operator << (const CSerializable &obj);
00205 
00206                         CStream& operator >> (CSerializablePtr &pObj);
00207                         CStream& operator >> (CSerializable &obj);
00208 
00209 
00210 
00211                         /** Writes a string to the stream in a textual form.
00212                           * \sa CStdOutStream
00213                           */
00214                         virtual int printf(const char *fmt,...) MRPT_printf_format_check(2,3);  // The first argument (1) is "this" !!!
00215 
00216                         /** Prints a vector in the format [A,B,C,...] using CStream::printf, and the fmt string for <b>each</b> vector element. */
00217                         template <typename T>
00218                         void printf_vector(const char *fmt, const std::vector<T> &V )
00219                         {
00220                                 this->printf("[");
00221                                 size_t N = V.size();
00222                                 for (size_t i=0;i<N;i++)
00223                                 {
00224                                         this->printf(fmt,V[i]);
00225                                         if (i!=(N-1)) this->printf(",");
00226                                 }
00227                                 this->printf("]");
00228                         }
00229 
00230                         /** Send a message to the device.
00231                          *  Note that only the low byte from the "type" field will be used.
00232                          *
00233                          *  For frames of size < 255 the frame format is an array of bytes in this order:
00234                          *  \code
00235                          *  <START_FLAG> <HEADER> <LENGTH> <BODY> <END_FLAG>
00236                          *      <START_FLAG>    = 0x69
00237                          *      <HEADER>                = A header byte
00238                          *      <LENGHT>                = Number of bytes of BODY
00239                          *      <BODY>                  = N x bytes
00240                          *      <END_FLAG>              = 0X96
00241                          *  Total length        =       <LENGTH> + 4
00242                          *  \endcode
00243                          *
00244                          *  For frames of size > 255 the frame format is an array of bytes in this order:
00245                          *  \code
00246                          *  <START_FLAG> <HEADER> <HIBYTE(LENGTH)> <LOBYTE(LENGTH)> <BODY> <END_FLAG>
00247                          *      <START_FLAG>    = 0x79
00248                          *      <HEADER>                = A header byte
00249                          *      <LENGHT>                = Number of bytes of BODY
00250                          *      <BODY>                  = N x bytes
00251                          *      <END_FLAG>              = 0X96
00252                          *  Total length        =       <LENGTH> + 5
00253                          *  \endcode
00254                          *
00255                          * \exception std::exception On communication errors
00256                          */
00257                         void  sendMessage( const utils::CMessage &msg);
00258 
00259                         /** Tries to receive a message from the device.
00260                           * \exception std::exception On communication errors
00261                           * \returns True if successful, false if there is no new data from the device (but communications seem to work fine)
00262                           * \sa The frame format is described in sendMessage()
00263                           */
00264                         bool  receiveMessage( utils::CMessage &msg );
00265 
00266                         /** Reads from the stream until a '\n' character is found ('\r' characters are ignored).
00267                           * \return false on EOF or any other read error.
00268                           */
00269                         bool getline(std::string &out_str);
00270 
00271 
00272                 }; // End of class def.
00273 
00274 
00275         #define DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( T ) \
00276                 CStream BASE_IMPEXP & operator<<(CStream&out, const T &a); \
00277                 CStream BASE_IMPEXP & operator>>(CStream&in, T &a);
00278 
00279                 // Definitions:
00280                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( bool )
00281                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint8_t )
00282                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int8_t )
00283                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint16_t )
00284                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int16_t )
00285                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint32_t )
00286                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int32_t )
00287                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint64_t )
00288                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int64_t )
00289                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( float )
00290                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( double )
00291 #ifdef HAVE_LONG_DOUBLE
00292                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( long double )
00293 #endif
00294 
00295                 // Why this shouldn't be templatized?: There's a more modern system
00296                 // in MRPT that serializes any kind of vector<T>, deque<T>, etc... but
00297                 // to keep COMPATIBILITY with old serialized objects we must preserve
00298                 // the ones listed here:
00299 
00300                 // Write --------------------
00301                 CStream BASE_IMPEXP & operator << (CStream&s, const char *a);
00302                 CStream BASE_IMPEXP & operator << (CStream&s, const std::string &str);
00303 
00304                 CStream BASE_IMPEXP & operator << (CStream&s, const vector_float  &a);
00305                 CStream BASE_IMPEXP & operator << (CStream&s, const vector_double &a);
00306 
00307                 CStream BASE_IMPEXP & operator << (CStream&, const vector_int &a);
00308                 CStream BASE_IMPEXP & operator << (CStream&, const vector_uint &a);
00309                 CStream BASE_IMPEXP & operator << (CStream&, const vector_word &a);
00310                 CStream BASE_IMPEXP & operator << (CStream&, const vector_signed_word &a);
00311                 CStream BASE_IMPEXP & operator << (CStream&, const vector_long &a);
00312                 CStream BASE_IMPEXP & operator << (CStream&, const vector_byte &a);
00313                 CStream BASE_IMPEXP & operator << (CStream&, const vector_signed_byte &a);
00314 
00315                 CStream BASE_IMPEXP & operator << (CStream&, const vector_bool &a);
00316                 CStream BASE_IMPEXP & operator << (CStream&, const std::vector<std::string> &);
00317 
00318         #if MRPT_WORD_SIZE!=32  // If it's 32 bit, size_t <=> uint32_t
00319                 CStream BASE_IMPEXP & operator << (CStream&, const std::vector<size_t> &a);
00320         #endif
00321 
00322                 // Read --------------------
00323                 CStream BASE_IMPEXP & operator>>(CStream&in, char *a);
00324                 CStream BASE_IMPEXP & operator>>(CStream&in, std::string &str);
00325 
00326                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_double &a);
00327                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_float &a);
00328 
00329                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_int &a);
00330                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_uint &a);
00331                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_word &a);
00332                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_signed_word &a);
00333                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_long &a);
00334                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_byte &a);
00335                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_signed_byte &a);
00336                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_bool &a);
00337 
00338                 CStream BASE_IMPEXP & operator>>(CStream&in, std::vector<std::string> &a);
00339 
00340                 // For backward compatibility, since in MRPT<0.8.1 vector_XXX and std::vector<XXX> were exactly equivalent, now there're not.
00341                 CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<float>  &a);
00342                 CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<double> &a);
00343                 CStream BASE_IMPEXP & operator << (CStream&s, const std::vector<float>  &a);
00344                 CStream BASE_IMPEXP & operator << (CStream&s, const std::vector<double> &a);
00345 
00346         #if MRPT_WORD_SIZE!=32  // If it's 32 bit, size_t <=> uint32_t
00347                 CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<size_t> &a);
00348         #endif
00349 
00350         } // End of namespace
00351 } // End of namespace
00352 
00353 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011