modm API documentation
iostream.hpp
1 /*
2  * Copyright (c) 2009-2010, Martin Rosekeit
3  * Copyright (c) 2009-2012, Fabian Greif
4  * Copyright (c) 2011, Georgi Grinshpun
5  * Copyright (c) 2011-2017, 2019 Niklas Hauser
6  * Copyright (c) 2012, 2015-2016, Sascha Schade
7  * Copyright (c) 2015-2016, Kevin Läufer
8  * Copyright (c) 2017, Marten Junga
9  *
10  * This file is part of the modm project.
11  *
12  * This Source Code Form is subject to the terms of the Mozilla Public
13  * License, v. 2.0. If a copy of the MPL was not distributed with this
14  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
15  */
16 // ----------------------------------------------------------------------------
17 
18 #ifndef MODM_IOSTREAM_HPP
19 #define MODM_IOSTREAM_HPP
20 
21 #include <cstddef>
22 #include <modm/architecture/utils.hpp>
23 
24 #include <stdarg.h> // va_list
25 #include <inttypes.h>
26 #include <type_traits>
27 
28 #include "iodevice.hpp"
29 #include "iodevice_wrapper.hpp" // convenience
30 
31 namespace modm
32 {
33 
34 /**
35  * @ingroup modm_io
36  * @author Martin Rosekeit <martin.rosekeit@rwth-aachen.de>
37  * @author Niklas Hauser
38  */
39 class IOStream
40 {
41 public:
42  /**
43  * @param device device to write the stream to
44  *
45  * @code
46  * MyIODevice device;
47  * IOStream stream( device );
48  * @endcode
49  */
50  inline IOStream(IODevice& odevice) :
51  device(&odevice)
52  {}
53 
54  // Acccessors -------------------------------------------------------------
55  inline IOStream&
56  write(char c)
57  { device->write(c); return *this; }
58 
59  static constexpr char eof = -1;
60 
61  /// Reads one character and returns it if available. Otherwise, returns IOStream::eof.
62  inline IOStream&
63  get(char& c)
64  {
65  if(!device->read(c)) {
66  c = IOStream::eof;
67  }
68  return *this;
69  }
70 
71  /// reads characters into NULL delimited c string
72  /// in contrast to the standard implementation, this does not care about
73  /// newline characters in the input
74  IOStream&
75  get(char* s, size_t n);
76 
77  template<size_t N>
78  inline IOStream&
79  get(char (&s)[N])
80  { return get(s, N); }
81 
82  // Modes ------------------------------------------------------------------
83  inline IOStream&
84  flush()
85  {
86  device->flush();
87  mode = Mode::Ascii;
88  return *this;
89  }
90 
91  inline IOStream&
92  endl()
93  {
94  mode = Mode::Ascii;
95  device->write('\n');
96  return *this;
97  }
98 
99  /// set the output mode to binary style for integer types
100  inline IOStream&
101  bin()
102  { mode = Mode::Binary; return *this; }
103 
104  /// set the output mode to hexadecimal style for integer types
105  inline IOStream&
106  hex()
107  { mode = Mode::Hexadecimal; return *this; }
108 
109  /// set the output mode to ASCII style for integer types
110  inline IOStream&
112  { mode = Mode::Ascii; return *this; }
113 
114  // Types ------------------------------------------------------------------
115  IOStream&
116  operator << (const bool& v);
117 
118  // char is equal to int8_t!
119  inline IOStream&
120  operator << (const char& v)
121  {
122  if (mode == Mode::Ascii)
123  device->write(v);
124  else if (mode == Mode::Binary)
125  writeBin(static_cast<uint8_t>(v));
126  else
127  writeHex(static_cast<uint8_t>(v));
128  return *this;
129  }
130  inline IOStream&
131  operator << (const uint8_t& v)
132  {
133  if (mode == Mode::Ascii)
134  writeInteger(static_cast<uint16_t>(v));
135  else if (mode == Mode::Binary)
136  writeBin(v);
137  else
138  writeHex(v);
139  return *this;
140  }
141 
142  inline IOStream& operator << (const int16_t& v)
143  { writeIntegerMode(v); return *this; }
144  inline IOStream& operator << (const uint16_t& v)
145  { writeIntegerMode(v); return *this; }
146 
147  inline IOStream& operator << (const int32_t& v)
148  { writeIntegerMode(v); return *this; }
149  inline IOStream& operator << (const uint32_t& v)
150  { writeIntegerMode(v); return *this; }
151 
152  inline IOStream&
153  operator << (const char* s)
154  { device->write(s); return *this; }
155 
156  /// write the hex value of a pointer
157  inline IOStream&
158  operator << (const void* p)
159  { writePointer(p); return *this; }
160 
161  /// Write the hex value of any function pointer
162  template<class Ret, class... Args>
163  IOStream&
164  operator << (Ret(*pointer)(Args...))
165  { writePointer(reinterpret_cast<const void*>(&pointer)); return *this; }
166 
167  inline IOStream&
168  operator << (IOStream& (*format)(IOStream&))
169  { return format(*this); }
170 
171 protected:
172  template< typename T >
173  void
174  writeIntegerMode(const T v)
175  {
176  constexpr size_t t_bits = sizeof(T)*8;
177  if (mode == Mode::Ascii) {
178  writeInteger(v);
179  } else if (mode == Mode::Binary) {
180  for (uint8_t ii=t_bits-8; ii < t_bits; ii -= 8)
181  writeBin(static_cast<std::make_unsigned_t<T>>(v) >> ii);
182  } else {
183  for (uint8_t ii=t_bits-8; ii < t_bits; ii -= 8)
184  writeHex(static_cast<std::make_unsigned_t<T>>(v) >> ii);
185  }
186  }
187 
188  void writeInteger(int16_t value);
189  void writeInteger(uint16_t value);
190  void writeInteger(int32_t value);
191  void writeInteger(uint32_t value);
192  void writePointer(const void* value);
193  void writeHex(uint8_t value);
194  void writeBin(uint8_t value);
195 
196 private:
197  enum class
198  Mode
199  {
200  Ascii,
201  Hexadecimal,
202  Binary
203  };
204 
205  IOStream(const IOStream&) = delete;
206  IOStream& operator =(const IOStream&) = delete;
207 
208 private:
209  IODevice* const device;
210  Mode mode = Mode::Ascii;
211 };
212 
213 /// @ingroup modm_io
214 /// @{
215 
216 /// Flushes the output stream.
217 /// This manipulator simply calls the stream's flush() member function.
218 inline IOStream&
220 { return ios.flush(); }
221 
222 //// Write a newline. **DOES NOT FLUSH THE STREAM!**
223 inline IOStream&
224 endl(IOStream& ios)
225 { return ios.endl(); }
226 
227 /// set the output mode to binary style
228 inline IOStream&
230 { return ios.bin(); }
231 
232 /// set the output mode to hexadecimal style
233 inline IOStream&
235 { return ios.hex(); }
236 
237 /// set the output mode to ASCII style
238 inline IOStream&
240 { return ios.ascii(); }
241 
242 /// Set the foreground colour on ANSI terminals.
243 IOStream&
244 black(IOStream& ios);
245 
246 IOStream&
247 red(IOStream& ios);
248 
249 IOStream&
250 green(IOStream& ios);
251 
252 IOStream&
253 yellow(IOStream& ios);
254 
255 IOStream&
256 blue(IOStream& ios);
257 
258 IOStream&
259 magenta(IOStream& ios);
260 
261 IOStream&
262 cyan(IOStream& ios);
263 
264 IOStream&
265 white(IOStream& ios);
266 /// @}
267 
268 } // namespace modm
269 
270 #endif // MODM_IOSTREAM_HPP
IOStream & black(IOStream &ios)
Set the foreground colour on ANSI terminals.
Definition: iostream.cpp:110
IOStream & ascii(IOStream &ios)
set the output mode to ASCII style
Definition: iostream.hpp:239
IOStream & bin(IOStream &ios)
set the output mode to binary style
Definition: iostream.hpp:229
IOStream & hex(IOStream &ios)
set the output mode to hexadecimal style
Definition: iostream.hpp:234
IOStream & flush(IOStream &ios)
Definition: iostream.hpp:219
IOStream & ascii()
set the output mode to ASCII style for integer types
Definition: iostream.hpp:111
IOStream & hex()
set the output mode to hexadecimal style for integer types
Definition: iostream.hpp:106
IOStream & bin()
set the output mode to binary style for integer types
Definition: iostream.hpp:101
virtual bool read(char &c) = 0
Read a single character.
IOStream & get(char &c)
Reads one character and returns it if available. Otherwise, returns IOStream::eof...
Definition: iostream.hpp:63
virtual void write(char c) = 0
Write a single character.
Definition: modm/src/modm/io/iodevice.hpp:26
IOStream(IODevice &odevice)
Definition: iostream.hpp:50
Definition: iostream.hpp:39