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 |