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://www.mrpt.org/                                |
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                  * \ingroup mrpt_base_grp
00053                  * \sa CFileStream, CMemoryStream,CSerializable
00054                  */
00055                 class BASE_IMPEXP CStream
00056                 {
00057                 public:
00058                         /** Used in CStream::Seek
00059                           */
00060                         enum TSeekOrigin
00061                         {
00062                                 sFromBeginning = 0,
00063                                 sFromCurrent = 1,
00064                                 sFromEnd = 2
00065                         };
00066 
00067                 protected:
00068                         /** Introduces a pure virtual method responsible for reading from the stream.
00069                          */
00070                         virtual size_t  Read(void *Buffer, size_t Count) = 0;
00071 
00072                         /** Introduces a pure virtual method responsible for writing to the stream.
00073                          *  Write attempts to write up to Count bytes to Buffer, and returns the number of bytes actually written.
00074                          */
00075                         virtual size_t  Write(const void *Buffer, size_t Count) = 0;
00076                 public:
00077                         /* Constructor
00078                          */
00079                         CStream() { }
00080 
00081                         /* Destructor
00082                          */
00083                         virtual ~CStream();
00084 
00085                         /** Reads a block of bytes from the stream into Buffer
00086                          *      \exception std::exception On any error, or if ZERO bytes are read.
00087                          *  \return The amound of bytes actually read.
00088                          * \note This method is endianness-dependent. 
00089                          * \sa ReadBufferImmediate ; Important, see: ReadBufferFixEndianness, 
00090                          */
00091                         size_t  ReadBuffer(void *Buffer, size_t Count);
00092 
00093                         /** 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.
00094                          *  \param ElementCount The number of elements (not bytes) to read.
00095                          *  \param ptr A pointer to the first output element in an array (or std::vector<>, etc...).
00096                          *  \return The amound of *bytes* (not elements) actually read (under error situations, the last element may be invalid if the data stream abruptly ends).
00097                          *  Example of usage:
00098                          *  \code
00099                          *   uint32_t  N;
00100                          *   s >> N;
00101                          *   vector<float>  vec(N);
00102                          *   if (N) 
00103                          *     s.ReadBufferFixEndianness<float>(&vec[0],N);
00104                          *  \endcode
00105                          *      \exception std::exception On any error, or if ZERO bytes are read.
00106                          * \sa ReadBufferFixEndianness, ReadBuffer
00107                          */
00108                         template <typename T>
00109                         size_t  ReadBufferFixEndianness(T *ptr, size_t ElementCount)
00110                         {
00111                         #if !MRPT_IS_BIG_ENDIAN
00112                                 // little endian: no conversion needed.
00113                                 return ReadBuffer(ptr,ElementCount*sizeof(T));
00114                         #else
00115                                 // big endian: convert.
00116                                 const size_t nread = ReadBuffer(ptr,ElementCount*sizeof(T));
00117                                 for (size_t i=0;i<ElementCount;i++) mrpt::utils::reverseBytesInPlace(ptr[i]);
00118                                 return nread;
00119                         #endif
00120                         }
00121 
00122 
00123                         /** 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).
00124                          *  Note that this method will fallback to ReadBuffer() in most CStream classes but in some hardware-related  classes.
00125                          *      \exception std::exception On any error, or if ZERO bytes are read.
00126                          */
00127                         virtual size_t  ReadBufferImmediate(void *Buffer, size_t Count) { return ReadBuffer(Buffer, Count); }
00128 
00129                         /** Writes a block of bytes to the stream from Buffer.
00130                          *      \exception std::exception On any error
00131                          *  \sa Important, see: WriteBufferFixEndianness
00132                          * \note This method is endianness-dependent. 
00133                          */
00134                         void  WriteBuffer (const void *Buffer, size_t Count);
00135 
00136 
00137 
00138                         /** Writes a sequence of elemental datatypes, taking care of reordering their bytes from the running architecture to MRPT stream standard (little endianness).
00139                          *  \param ElementCount The number of elements (not bytes) to write.
00140                          *  \param ptr A pointer to the first input element in an array (or std::vector<>, etc...).
00141                          *  Example of usage:
00142                          *  \code
00143                          *   vector<float>  vec = ...
00144                          *   uint32_t N = vec.size();
00145                          *   s << N
00146                          *   if (N) 
00147                          *     s.WriteBufferFixEndianness<float>(&vec[0],N);
00148                          *  \endcode
00149                          *  \exception std::exception On any error
00150                          *  \sa WriteBuffer
00151                          */
00152                         template <typename T>
00153                         void WriteBufferFixEndianness(const T *ptr, size_t ElementCount)
00154                         {
00155                         #if !MRPT_IS_BIG_ENDIAN
00156                                 // little endian: no conversion needed.
00157                                 return WriteBuffer(ptr,ElementCount*sizeof(T));
00158                         #else
00159                                 // big endian: the individual "<<" functions already convert endiannes
00160                                 for (size_t i=0;i<ElementCount;i++) (*this) << ptr[i];
00161                         #endif
00162                         }
00163 
00164 
00165                         /** Copies a specified number of bytes from one stream to another. */
00166                         size_t  CopyFrom(CStream* Source, size_t Count);
00167 
00168                         /** Introduces a pure virtual method for moving to a specified position in the streamed resource.
00169                          *   he Origin parameter indicates how to interpret the Offset parameter. Origin should be one of the following values:
00170                          *      - sFromBeginning        (Default) Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
00171                          *      - sFromCurrent          Offset is from the current position in the resource. Seek moves to Position + Offset.
00172                          *      - 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.
00173                          * \return Seek returns the new value of the Position property.
00174                          */
00175                         virtual uint64_t Seek(long Offset, CStream::TSeekOrigin Origin = sFromBeginning) = 0;
00176 
00177                         /** Returns the total amount of bytes in the stream.
00178                          */
00179                         virtual uint64_t getTotalBytesCount() = 0;
00180 
00181                         /** Method for getting the current cursor position, where 0 is the first byte and TotalBytesCount-1 the last one.
00182                          */
00183                         virtual uint64_t getPosition() =0;
00184 
00185                         /** Writes an object to the stream.
00186                          */
00187                         void WriteObject( const CSerializable *o );
00188 
00189                         /** Reads an object from stream, its class determined at runtime, and returns a smart pointer to the object.
00190                          * \exception std::exception On I/O error or undefined class.
00191                          * \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.
00192                          */
00193                         CSerializablePtr ReadObject();
00194 
00195                         /** Reads an object from stream, where its class must be the same
00196                          *    as the supplied object, where the loaded object will be stored in.
00197                          * \exception std::exception On I/O error or different class found.
00198                          * \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.
00199                          */
00200                         void ReadObject(CSerializable *existingObj);
00201 
00202                         /** Write an object to a stream in the binary MRPT format. */
00203                         CStream& operator << (const CSerializablePtr & pObj);
00204                         /** Write an object to a stream in the binary MRPT format. */
00205                         CStream& operator << (const CSerializable &obj);
00206 
00207                         CStream& operator >> (CSerializablePtr &pObj);
00208                         CStream& operator >> (CSerializable &obj);
00209 
00210 
00211 
00212                         /** Writes a string to the stream in a textual form.
00213                           * \sa CStdOutStream
00214                           */
00215                         virtual int printf(const char *fmt,...) MRPT_printf_format_check(2,3);  // The first argument (1) is "this" !!!
00216 
00217                         /** Prints a vector in the format [A,B,C,...] using CStream::printf, and the fmt string for <b>each</b> vector element. */
00218                         template <typename T>
00219                         void printf_vector(const char *fmt, const std::vector<T> &V )
00220                         {
00221                                 this->printf("[");
00222                                 size_t N = V.size();
00223                                 for (size_t i=0;i<N;i++)
00224                                 {
00225                                         this->printf(fmt,V[i]);
00226                                         if (i!=(N-1)) this->printf(",");
00227                                 }
00228                                 this->printf("]");
00229                         }
00230 
00231                         /** Send a message to the device.
00232                          *  Note that only the low byte from the "type" field will be used.
00233                          *
00234                          *  For frames of size < 255 the frame format is an array of bytes in this order:
00235                          *  \code
00236                          *  <START_FLAG> <HEADER> <LENGTH> <BODY> <END_FLAG>
00237                          *      <START_FLAG>    = 0x69
00238                          *      <HEADER>                = A header byte
00239                          *      <LENGHT>                = Number of bytes of BODY
00240                          *      <BODY>                  = N x bytes
00241                          *      <END_FLAG>              = 0X96
00242                          *  Total length        =       <LENGTH> + 4
00243                          *  \endcode
00244                          *
00245                          *  For frames of size > 255 the frame format is an array of bytes in this order:
00246                          *  \code
00247                          *  <START_FLAG> <HEADER> <HIBYTE(LENGTH)> <LOBYTE(LENGTH)> <BODY> <END_FLAG>
00248                          *      <START_FLAG>    = 0x79
00249                          *      <HEADER>                = A header byte
00250                          *      <LENGHT>                = Number of bytes of BODY
00251                          *      <BODY>                  = N x bytes
00252                          *      <END_FLAG>              = 0X96
00253                          *  Total length        =       <LENGTH> + 5
00254                          *  \endcode
00255                          *
00256                          * \exception std::exception On communication errors
00257                          */
00258                         void  sendMessage( const utils::CMessage &msg);
00259 
00260                         /** Tries to receive a message from the device.
00261                           * \exception std::exception On communication errors
00262                           * \returns True if successful, false if there is no new data from the device (but communications seem to work fine)
00263                           * \sa The frame format is described in sendMessage()
00264                           */
00265                         bool  receiveMessage( utils::CMessage &msg );
00266 
00267                         /** Reads from the stream until a '\n' character is found ('\r' characters are ignored).
00268                           * \return false on EOF or any other read error.
00269                           */
00270                         bool getline(std::string &out_str);
00271 
00272 
00273                 }; // End of class def.
00274 
00275 
00276         #define DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( T ) \
00277                 CStream BASE_IMPEXP & operator<<(CStream&out, const T &a); \
00278                 CStream BASE_IMPEXP & operator>>(CStream&in, T &a);
00279 
00280                 // Definitions:
00281                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( bool )
00282                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint8_t )
00283                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int8_t )
00284                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint16_t )
00285                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int16_t )
00286                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint32_t )
00287                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int32_t )
00288                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( uint64_t )
00289                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( int64_t )
00290                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( float )
00291                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( double )
00292 #ifdef HAVE_LONG_DOUBLE
00293                 DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( long double )
00294 #endif
00295 
00296                 // Why this shouldn't be templatized?: There's a more modern system
00297                 // in MRPT that serializes any kind of vector<T>, deque<T>, etc... but
00298                 // to keep COMPATIBILITY with old serialized objects we must preserve
00299                 // the ones listed here:
00300 
00301                 // Write --------------------
00302                 CStream BASE_IMPEXP & operator << (CStream&s, const char *a);
00303                 CStream BASE_IMPEXP & operator << (CStream&s, const std::string &str);
00304 
00305                 CStream BASE_IMPEXP & operator << (CStream&s, const vector_float  &a);
00306                 CStream BASE_IMPEXP & operator << (CStream&s, const vector_double &a);
00307 
00308                 CStream BASE_IMPEXP & operator << (CStream&, const vector_int &a);
00309                 CStream BASE_IMPEXP & operator << (CStream&, const vector_uint &a);
00310                 CStream BASE_IMPEXP & operator << (CStream&, const vector_word &a);
00311                 CStream BASE_IMPEXP & operator << (CStream&, const vector_signed_word &a);
00312                 CStream BASE_IMPEXP & operator << (CStream&, const vector_long &a);
00313                 CStream BASE_IMPEXP & operator << (CStream&, const vector_byte &a);
00314                 CStream BASE_IMPEXP & operator << (CStream&, const vector_signed_byte &a);
00315 
00316                 CStream BASE_IMPEXP & operator << (CStream&, const vector_bool &a);
00317                 CStream BASE_IMPEXP & operator << (CStream&, const std::vector<std::string> &);
00318 
00319         #if MRPT_WORD_SIZE!=32  // If it's 32 bit, size_t <=> uint32_t
00320                 CStream BASE_IMPEXP & operator << (CStream&, const std::vector<size_t> &a);
00321         #endif
00322 
00323                 // Read --------------------
00324                 CStream BASE_IMPEXP & operator>>(CStream&in, char *a);
00325                 CStream BASE_IMPEXP & operator>>(CStream&in, std::string &str);
00326 
00327                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_double &a);
00328                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_float &a);
00329 
00330                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_int &a);
00331                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_uint &a);
00332                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_word &a);
00333                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_signed_word &a);
00334                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_long &a);
00335                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_byte &a);
00336                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_signed_byte &a);
00337                 CStream BASE_IMPEXP & operator>>(CStream&in, vector_bool &a);
00338 
00339                 CStream BASE_IMPEXP & operator>>(CStream&in, std::vector<std::string> &a);
00340 
00341                 // For backward compatibility, since in MRPT<0.8.1 vector_XXX and std::vector<XXX> were exactly equivalent, now there're not.
00342                 CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<float>  &a);
00343                 CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<double> &a);
00344                 CStream BASE_IMPEXP & operator << (CStream&s, const std::vector<float>  &a);
00345                 CStream BASE_IMPEXP & operator << (CStream&s, const std::vector<double> &a);
00346 
00347         #if MRPT_WORD_SIZE!=32  // If it's 32 bit, size_t <=> uint32_t
00348                 CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<size_t> &a);
00349         #endif
00350 
00351         } // End of namespace
00352 } // End of namespace
00353 
00354 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011