Main MRPT website > C++ reference
MRPT logo
CStream.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef CSTREAM_H
29 #define CSTREAM_H
30 
31 #include <mrpt/utils/utils_defs.h>
32 #include <mrpt/utils/CUncopiable.h>
33 #include <mrpt/utils/CObject.h>
34 #include <mrpt/utils/exceptions.h>
35 
36 namespace mrpt
37 {
38  namespace utils
39  {
43 
44  /** This base class is used to provide a unified interface to
45  * files,memory buffers,..Please see the derived classes. This class is
46  * largely inspired by Borland VCL "TStream" class. <br><br>
47  * Apart of the "VCL like" methods, operators ">>" and "<<" have been
48  * defined so that simple types (int,bool,char,float,char *,std::string,...)
49  * can be directly written and read to and from any CStream easily.
50  * Please, it is recomendable to read CSerializable documentation also.
51  *
52  * \ingroup mrpt_base_grp
53  * \sa CFileStream, CMemoryStream,CSerializable
54  */
56  {
57  public:
58  /** Used in CStream::Seek
59  */
61  {
62  sFromBeginning = 0,
63  sFromCurrent = 1,
64  sFromEnd = 2
65  };
66 
67  protected:
68  /** Introduces a pure virtual method responsible for reading from the stream.
69  */
70  virtual size_t Read(void *Buffer, size_t Count) = 0;
71 
72  /** Introduces a pure virtual method responsible for writing to the stream.
73  * Write attempts to write up to Count bytes to Buffer, and returns the number of bytes actually written.
74  */
75  virtual size_t Write(const void *Buffer, size_t Count) = 0;
76  public:
77  /* Constructor
78  */
79  CStream() { }
80 
81  /* Destructor
82  */
83  virtual ~CStream();
84 
85  /** Reads a block of bytes from the stream into Buffer
86  * \exception std::exception On any error, or if ZERO bytes are read.
87  * \return The amound of bytes actually read.
88  * \note This method is endianness-dependent.
89  * \sa ReadBufferImmediate ; Important, see: ReadBufferFixEndianness,
90  */
91  size_t ReadBuffer(void *Buffer, size_t Count);
92 
93  /** 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.
94  * \param ElementCount The number of elements (not bytes) to read.
95  * \param ptr A pointer to the first output element in an array (or std::vector<>, etc...).
96  * \return The amound of *bytes* (not elements) actually read (under error situations, the last element may be invalid if the data stream abruptly ends).
97  * Example of usage:
98  * \code
99  * uint32_t N;
100  * s >> N;
101  * vector<float> vec(N);
102  * if (N)
103  * s.ReadBufferFixEndianness<float>(&vec[0],N);
104  * \endcode
105  * \exception std::exception On any error, or if ZERO bytes are read.
106  * \sa ReadBufferFixEndianness, ReadBuffer
107  */
108  template <typename T>
109  size_t ReadBufferFixEndianness(T *ptr, size_t ElementCount)
110  {
111  #if !MRPT_IS_BIG_ENDIAN
112  // little endian: no conversion needed.
113  return ReadBuffer(ptr,ElementCount*sizeof(T));
114  #else
115  // big endian: convert.
116  const size_t nread = ReadBuffer(ptr,ElementCount*sizeof(T));
117  for (size_t i=0;i<ElementCount;i++) mrpt::utils::reverseBytesInPlace(ptr[i]);
118  return nread;
119  #endif
120  }
121 
122 
123  /** 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).
124  * Note that this method will fallback to ReadBuffer() in most CStream classes but in some hardware-related classes.
125  * \exception std::exception On any error, or if ZERO bytes are read.
126  */
127  virtual size_t ReadBufferImmediate(void *Buffer, size_t Count) { return ReadBuffer(Buffer, Count); }
128 
129  /** Writes a block of bytes to the stream from Buffer.
130  * \exception std::exception On any error
131  * \sa Important, see: WriteBufferFixEndianness
132  * \note This method is endianness-dependent.
133  */
134  void WriteBuffer (const void *Buffer, size_t Count);
135 
136 
137 
138  /** Writes a sequence of elemental datatypes, taking care of reordering their bytes from the running architecture to MRPT stream standard (little endianness).
139  * \param ElementCount The number of elements (not bytes) to write.
140  * \param ptr A pointer to the first input element in an array (or std::vector<>, etc...).
141  * Example of usage:
142  * \code
143  * vector<float> vec = ...
144  * uint32_t N = vec.size();
145  * s << N
146  * if (N)
147  * s.WriteBufferFixEndianness<float>(&vec[0],N);
148  * \endcode
149  * \exception std::exception On any error
150  * \sa WriteBuffer
151  */
152  template <typename T>
153  void WriteBufferFixEndianness(const T *ptr, size_t ElementCount)
154  {
155  #if !MRPT_IS_BIG_ENDIAN
156  // little endian: no conversion needed.
157  return WriteBuffer(ptr,ElementCount*sizeof(T));
158  #else
159  // big endian: the individual "<<" functions already convert endiannes
160  for (size_t i=0;i<ElementCount;i++) (*this) << ptr[i];
161  #endif
162  }
163 
164 
165  /** Copies a specified number of bytes from one stream to another. */
166  size_t CopyFrom(CStream* Source, size_t Count);
167 
168  /** Introduces a pure virtual method for moving to a specified position in the streamed resource.
169  * he Origin parameter indicates how to interpret the Offset parameter. Origin should be one of the following values:
170  * - sFromBeginning (Default) Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
171  * - sFromCurrent Offset is from the current position in the resource. Seek moves to Position + Offset.
172  * - 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.
173  * \return Seek returns the new value of the Position property.
174  */
175  virtual uint64_t Seek(long Offset, CStream::TSeekOrigin Origin = sFromBeginning) = 0;
176 
177  /** Returns the total amount of bytes in the stream.
178  */
179  virtual uint64_t getTotalBytesCount() = 0;
180 
181  /** Method for getting the current cursor position, where 0 is the first byte and TotalBytesCount-1 the last one.
182  */
183  virtual uint64_t getPosition() =0;
184 
185  /** Writes an object to the stream.
186  */
187  void WriteObject( const CSerializable *o );
188 
189  /** Reads an object from stream, its class determined at runtime, and returns a smart pointer to the object.
190  * \exception std::exception On I/O error or undefined class.
191  * \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.
192  */
193  CSerializablePtr ReadObject();
194 
195  /** Reads an object from stream, where its class must be the same
196  * as the supplied object, where the loaded object will be stored in.
197  * \exception std::exception On I/O error or different class found.
198  * \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.
199  */
200  void ReadObject(CSerializable *existingObj);
201 
202  /** Write an object to a stream in the binary MRPT format. */
203  CStream& operator << (const CSerializablePtr & pObj);
204  /** Write an object to a stream in the binary MRPT format. */
205  CStream& operator << (const CSerializable &obj);
206 
209 
210 
211 
212  /** Writes a string to the stream in a textual form.
213  * \sa CStdOutStream
214  */
215  virtual int printf(const char *fmt,...) MRPT_printf_format_check(2,3); // The first argument (1) is "this" !!!
216 
217  /** Prints a vector in the format [A,B,C,...] using CStream::printf, and the fmt string for <b>each</b> vector element. */
218  template <typename T>
219  void printf_vector(const char *fmt, const std::vector<T> &V )
220  {
221  this->printf("[");
222  size_t N = V.size();
223  for (size_t i=0;i<N;i++)
224  {
225  this->printf(fmt,V[i]);
226  if (i!=(N-1)) this->printf(",");
227  }
228  this->printf("]");
229  }
230 
231  /** Send a message to the device.
232  * Note that only the low byte from the "type" field will be used.
233  *
234  * For frames of size < 255 the frame format is an array of bytes in this order:
235  * \code
236  * <START_FLAG> <HEADER> <LENGTH> <BODY> <END_FLAG>
237  * <START_FLAG> = 0x69
238  * <HEADER> = A header byte
239  * <LENGHT> = Number of bytes of BODY
240  * <BODY> = N x bytes
241  * <END_FLAG> = 0X96
242  * Total length = <LENGTH> + 4
243  * \endcode
244  *
245  * For frames of size > 255 the frame format is an array of bytes in this order:
246  * \code
247  * <START_FLAG> <HEADER> <HIBYTE(LENGTH)> <LOBYTE(LENGTH)> <BODY> <END_FLAG>
248  * <START_FLAG> = 0x79
249  * <HEADER> = A header byte
250  * <LENGHT> = Number of bytes of BODY
251  * <BODY> = N x bytes
252  * <END_FLAG> = 0X96
253  * Total length = <LENGTH> + 5
254  * \endcode
255  *
256  * \exception std::exception On communication errors
257  */
258  void sendMessage( const utils::CMessage &msg);
259 
260  /** Tries to receive a message from the device.
261  * \exception std::exception On communication errors
262  * \returns True if successful, false if there is no new data from the device (but communications seem to work fine)
263  * \sa The frame format is described in sendMessage()
264  */
265  bool receiveMessage( utils::CMessage &msg );
266 
267  /** Reads from the stream until a '\n' character is found ('\r' characters are ignored).
268  * \return false on EOF or any other read error.
269  */
270  bool getline(std::string &out_str);
271 
272 
273  }; // End of class def.
274 
275 
276  #define DECLARE_CSTREAM_READ_WRITE_SIMPLE_TYPE( T ) \
277  CStream BASE_IMPEXP & operator<<(CStream&out, const T &a); \
278  CStream BASE_IMPEXP & operator>>(CStream&in, T &a);
279 
280  // Definitions:
292 #ifdef HAVE_LONG_DOUBLE
294 #endif
295 
296  // Why this shouldn't be templatized?: There's a more modern system
297  // in MRPT that serializes any kind of vector<T>, deque<T>, etc... but
298  // to keep COMPATIBILITY with old serialized objects we must preserve
299  // the ones listed here:
300 
301  // Write --------------------
302  CStream BASE_IMPEXP & operator << (CStream&s, const char *a);
303  CStream BASE_IMPEXP & operator << (CStream&s, const std::string &str);
304 
307 
315 
317  CStream BASE_IMPEXP & operator << (CStream&, const std::vector<std::string> &);
318 
319  #if MRPT_WORD_SIZE!=32 // If it's 32 bit, size_t <=> uint32_t
320  CStream BASE_IMPEXP & operator << (CStream&, const std::vector<size_t> &a);
321  #endif
322 
323  // Read --------------------
324  CStream BASE_IMPEXP & operator>>(CStream&in, char *a);
325  CStream BASE_IMPEXP & operator>>(CStream&in, std::string &str);
326 
329 
338 
339  CStream BASE_IMPEXP & operator>>(CStream&in, std::vector<std::string> &a);
340 
341  // For backward compatibility, since in MRPT<0.8.1 vector_XXX and std::vector<XXX> were exactly equivalent, now there're not.
342  CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<float> &a);
343  CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<double> &a);
344  CStream BASE_IMPEXP & operator << (CStream&s, const std::vector<float> &a);
345  CStream BASE_IMPEXP & operator << (CStream&s, const std::vector<double> &a);
346 
347  #if MRPT_WORD_SIZE!=32 // If it's 32 bit, size_t <=> uint32_t
348  CStream BASE_IMPEXP & operator >> (CStream&s, std::vector<size_t> &a);
349  #endif
350 
351  } // End of namespace
352 } // End of namespace
353 
354 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013