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: at Sat Mar 26 06:40:17 UTC 2011 |