FastArduino  v1.7
C++ library to build fast but small Arduino/AVR projects
streams.h
Go to the documentation of this file.
1 // Copyright 2016-2021 Jean-Francois Poilpret
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
21 #ifndef STREAMS_HH
22 #define STREAMS_HH
23 
24 #include <ctype.h>
25 #include "queue.h"
26 #include "flash.h"
27 #include "ios.h"
28 #include "streambuf.h"
29 #include "time.h"
30 
55 namespace streams
56 {
60  class ostream : public ios_base
61  {
62  public:
67  explicit ostream(ostreambuf& streambuf) : streambuf_{streambuf} {}
68 
69  ostream& operator=(const ostream&) = delete;
70 
74  ostreambuf& rdbuf() const
75  {
76  return streambuf_;
77  }
78 
86  void flush()
87  {
88  streambuf_.pubsync();
89  }
90 
98  void put(char c)
99  {
100  streambuf_.sputc(c);
101  check_overflow();
102  }
103 
113  void write(const char* content, size_t size)
114  {
115  streambuf_.sputn(content, size);
116  check_overflow();
117  }
118 
127  void write(const char* str)
128  {
129  streambuf_.sputn(str);
130  check_overflow();
131  }
132 
141  void write(const flash::FlashStorage* str)
142  {
143  streambuf_.sputn(str);
144  check_overflow();
145  }
146 
157  ostream& operator<<(const void* ptr)
158  {
159  convert(streambuf_, uint16_t(ptr));
160  after_insertion();
161  return *this;
162  }
163 
172  ostream& operator<<(bool value)
173  {
174  convert(streambuf_, value);
175  after_insertion();
176  return *this;
177  }
178 
187  ostream& operator<<(char ch)
188  {
189  convert(streambuf_, ch);
190  after_insertion();
191  return *this;
192  }
193 
202  ostream& operator<<(const char* str)
203  {
204  justify(streambuf_, str, false, nullptr);
205  after_insertion();
206  return *this;
207  }
208 
217  ostream& operator<<(const flash::FlashStorage* str)
218  {
219  justify(streambuf_, str);
220  after_insertion();
221  return *this;
222  }
223 
234  ostream& operator<<(int value)
235  {
236  convert(streambuf_, value);
237  after_insertion();
238  return *this;
239  }
240 
251  ostream& operator<<(unsigned int value)
252  {
253  convert(streambuf_, value);
254  after_insertion();
255  return *this;
256  }
257 
268  ostream& operator<<(long value)
269  {
270  convert(streambuf_, value);
271  after_insertion();
272  return *this;
273  }
274 
285  ostream& operator<<(unsigned long value)
286  {
287  convert(streambuf_, value);
288  after_insertion();
289  return *this;
290  }
291 
302  ostream& operator<<(double value)
303  {
304  convert(streambuf_, value);
305  after_insertion();
306  return *this;
307  }
308 
312  using MANIPULATOR = void (*)(ostream&);
313 
331  {
332  func(*this);
333  return *this;
334  }
335 
336  private:
337  void after_insertion()
338  {
339  check_overflow();
340  if (flags() & unitbuf) streambuf_.pubsync();
341  width(0);
342  }
343 
344  void check_overflow()
345  {
346  if (streambuf_.overflow()) setstate(badbit);
347  }
348 
349  ostreambuf& streambuf_;
350  };
351 
352  // NOTE: istream API is blocking, while istreambuf is not
356  class istream : public ios_base
357  {
358  public:
363  explicit istream(istreambuf& streambuf) : streambuf_{streambuf} {}
364 
365  istream& operator=(const istream&) = delete;
366 
370  istreambuf& rdbuf() const
371  {
372  return streambuf_;
373  }
374 
381  int peek()
382  {
383  int value;
384  while ((value = streambuf_.sgetc()) == istreambuf::EOF) time::yield();
385  return value;
386  }
387 
394  int get()
395  {
396  int value;
397  while ((value = streambuf_.sbumpc()) == istreambuf::EOF) time::yield();
398  return value;
399  }
400 
408  istream& get(char& ch)
409  {
410  ch = get();
411  return *this;
412  }
413 
422  istream& get(char* str, size_t n, char delim = '\n')
423  {
424  while (--n)
425  {
426  int ch = peek();
427  if (ch == delim) break;
428  *str++ = get();
429  }
430  *str = 0;
431  return *this;
432  }
433 
442  istream& getline(char* str, size_t n, char delim = '\n')
443  {
444  while (--n)
445  {
446  int ch = get();
447  if (ch == delim) break;
448  *str++ = ch;
449  }
450  *str = 0;
451  return *this;
452  }
453 
461  istream& ignore(size_t n = 1, int delim = istreambuf::EOF)
462  {
463  bool forever = (n == 0);
464  while (forever || (n > 0))
465  {
466  --n;
467  if (get() == delim) break;
468  }
469  return *this;
470  }
471 
477  istream& read(char* str, size_t n)
478  {
479  while (n--) *str++ = get();
480  return *this;
481  }
482 
495  istream& operator>>(char* buf)
496  {
497  if (width() > 0)
498  {
499  skipws_if_needed();
500  scan(buf, width());
501  width(0);
502  }
503  return *this;
504  }
505 
520  istream& operator>>(bool& value)
521  {
522  skipws_if_needed();
523  char buffer[10 + 1];
524  convert(scan(buffer, sizeof buffer), value);
525  return *this;
526  }
527 
540  istream& operator>>(char& value)
541  {
542  skipws_if_needed();
543  value = containers::pull(streambuf_.queue());
544  return *this;
545  }
546 
559  istream& operator>>(int& value)
560  {
561  skipws_if_needed();
562  char buffer[sizeof(int) * 8 + 1];
563  convert(scan(buffer, sizeof buffer), value);
564  return *this;
565  }
566 
579  istream& operator>>(unsigned int& value)
580  {
581  skipws_if_needed();
582  char buffer[sizeof(int) * 8 + 1];
583  convert(scan(buffer, sizeof buffer), value);
584  return *this;
585  }
586 
599  istream& operator>>(long& value)
600  {
601  skipws_if_needed();
602  char buffer[sizeof(long) * 8 + 1];
603  convert(scan(buffer, sizeof buffer), value);
604  return *this;
605  }
606 
619  istream& operator>>(unsigned long& value)
620  {
621  skipws_if_needed();
622  char buffer[sizeof(long) * 8 + 1];
623  convert(scan(buffer, sizeof buffer), value);
624  return *this;
625  }
626 
639  istream& operator>>(double& value)
640  {
641  skipws_if_needed();
642  // Allocate sufficient size for fixed/scientific representation with precision max = 16
643  // Need 1 more for sign, 1 for DP, 1 for first digit, 4 for e+00
644  char buffer[DOUBLE_BUFFER_SIZE];
645  convert(scan(buffer, sizeof buffer), value);
646  return *this;
647  }
648 
652  using MANIPULATOR = void (*)(istream&);
653 
672  {
673  func(*this);
674  return *this;
675  }
676 
677  private:
678  void skipws_if_needed()
679  {
680  if (flags() & skipws) skip_whitespace();
681  }
682 
683  void skip_whitespace()
684  {
685  while (isspace(containers::peek(streambuf_.queue()))) containers::pull(streambuf_.queue());
686  }
687 
688  char* scan(char* str, size_t max);
689 
690  istreambuf& streambuf_;
691 
692  template<typename FSTREAM> friend void ws(FSTREAM&);
693  };
694 
705  template<typename FSTREAM> inline void ws(FSTREAM& stream)
706  {
707  stream.skip_whitespace();
708  }
709 
713  template<typename FSTREAM> inline void flush(FSTREAM& stream)
714  {
715  stream.flush();
716  }
717 
722  template<typename FSTREAM> inline void endl(FSTREAM& stream)
723  {
724  stream.put('\n');
725  stream.flush();
726  }
727 }
728 
729 #endif /* STREAMS_HH */
730 
streams::ostream::operator<<
ostream & operator<<(MANIPULATOR func)
Apply a MANIPULATOR to this output stream.
Definition: streams.h:330
streams::istream::getline
istream & getline(char *str, size_t n, char delim='\n')
Extract characters from this input stream and stores them as a C-string, until either (n - 1) charact...
Definition: streams.h:442
streams::ostream::operator<<
ostream & operator<<(bool value)
Output a boolean value.
Definition: streams.h:172
streams::ostream::operator<<
ostream & operator<<(unsigned int value)
Output an unsigned integral number, represented within the current base(), using the current minimum ...
Definition: streams.h:251
streams::ostream
Output stream wrapper to provide formatted output API, a la C++.
Definition: streams.h:61
streams::istream::operator>>
istream & operator>>(unsigned int &value)
Input and interpret next word from buffer as an unsigned integer value.
Definition: streams.h:579
streams::istreambuf
Input API based on a ring buffer.
Definition: streambuf.h:209
streams::istream::operator>>
istream & operator>>(MANIPULATOR func)
Apply a MANIPULATOR to this input stream.
Definition: streams.h:671
streams::istream::operator>>
istream & operator>>(char &value)
Input next character from buffer.
Definition: streams.h:540
streams::ostream::MANIPULATOR
void(*)(ostream &) MANIPULATOR
General type of a manipulator function applicable to this output stream.
Definition: streams.h:312
streams::ostream::put
void put(char c)
Insert character c into this stream.
Definition: streams.h:98
streams::ostream::write
void write(const flash::FlashStorage *str)
Write a flash-stored string (null-terminated) to this stream.
Definition: streams.h:141
streams::istream::operator>>
istream & operator>>(char *buf)
Read characters from buffer into buf until one of these conditions happen:
Definition: streams.h:495
streams::istream::ws
friend void ws(FSTREAM &)
Manipulator for an input stream, which will swallow all white spaces from that stream.
Definition: streams.h:705
streams::ostreambuf
Output API based on a ring buffer.
Definition: streambuf.h:46
time::yield
void yield()
Utility method used by many FastArduino API in order to "yield" some processor time; concretely it ju...
Definition: time.cpp:22
streams::istream::peek
int peek()
Return the next character in this input stream, without extracting it.
Definition: streams.h:381
streams::ostream::ostream
ostream(ostreambuf &streambuf)
Construct a formatted output wrapper of streambuf.
Definition: streams.h:67
streams::ios_base::setstate
void setstate(iostate state)
Set the stream error flags state in addition to currently set flags.
Definition: ios.h:90
streams::ios_base::badbit
static constexpr iostate badbit
This bit is set when an irrecoverable stream error has occurred, e.g.
Definition: ios.h:74
streams::ostreambuf::sputn
void sputn(const char *content, size_t size)
Append several characters to the buffer.
Definition: streambuf.h:92
streams::endl
void endl(FSTREAM &stream)
Manipulator for an output stream, which will insert a new-line character and flush the stream buffer.
Definition: streams.h:722
streams::istream::istream
istream(istreambuf &streambuf)
Construct a formatted input wrapper of streambuf.
Definition: streams.h:363
streams::ostream::operator<<
ostream & operator<<(char ch)
Output a single character.
Definition: streams.h:187
streams::ios_base::flags
fmtflags flags() const
Return the format flags currently selected in this stream.
Definition: ios.h:296
streams::ios_base::width
uint8_t width() const
Get the current minimum width value (default = 0) used for formatted output.
Definition: ios.h:400
streams::istream::rdbuf
istreambuf & rdbuf() const
Return the stream buffer associated with this stream.
Definition: streams.h:370
streams::istream::ignore
istream & ignore(size_t n=1, int delim=istreambuf::EOF)
Extract characters from this input stream and discards them, until either n characters have been extr...
Definition: streams.h:461
streams::istreambuf::sgetc
int sgetc()
Definition: streambuf.h:247
streams::ostream::operator<<
ostream & operator<<(double value)
Output a floating point number, using the current minimum width() and precision().
Definition: streams.h:302
streams::istreambuf::sbumpc
int sbumpc()
Definition: streambuf.h:236
streams::ostream::operator<<
ostream & operator<<(const char *str)
Output a C-string (\0 terminated).
Definition: streams.h:202
streams::ios_base
Base class for formatted streams.
Definition: ios.h:38
streams::istream::read
istream & read(char *str, size_t n)
Read a block of data from this input stream.
Definition: streams.h:477
time.h
Simple time utilities.
streams::ostream::operator<<
ostream & operator<<(int value)
Output a signed integral number, represented within the current base(), using the current minimum wid...
Definition: streams.h:234
streams::istream::operator>>
istream & operator>>(bool &value)
Input and interpret next character from buffer as a boolean value.
Definition: streams.h:520
streams::istream::get
int get()
Extract a single character from this input stream.
Definition: streams.h:394
streams::istream
Input stream wrapper to provide formatted input API, a la C++.
Definition: streams.h:357
containers::peek
T peek(Queue< T, TREF > &queue)
Peek an item from the beginning of queue.
Definition: queue.h:573
streams::ws
void ws(FSTREAM &stream)
Manipulator for an input stream, which will swallow all white spaces from that stream.
Definition: streams.h:705
streams::ios_base::skipws
static constexpr fmtflags skipws
Skip leading spaces on certain extraction (read) operations.
Definition: ios.h:272
streams::ostream::operator<<
ostream & operator<<(unsigned long value)
Output an unsigned long integral number, represented within the current base(), using the current min...
Definition: streams.h:285
queue.h
Utility API to handle ring-buffer queue containers.
streams::istream::get
istream & get(char &ch)
Extract a single character from this input stream.
Definition: streams.h:408
containers::pull
T pull(Queue< T, TREF > &queue)
Pull an item from the beginning of queue.
Definition: queue.h:556
streams::ostream::operator<<
ostream & operator<<(const flash::FlashStorage *str)
Output a C-string (\0 terminated) that is stored in flash memory.
Definition: streams.h:217
streams::ostream::write
void write(const char *str)
Write a string (null-terminated) to this stream.
Definition: streams.h:127
ios.h
C++-like std::iostream facilities.
streams::ios_base::unitbuf
static constexpr fmtflags unitbuf
Flush output after each insertion operation.
Definition: ios.h:274
streams
Defines C++-like streams API, based on circular buffers for input or output.
Definition: empty_streams.h:34
streams::ostream::flush
void flush()
Flush this ostream and blocks until all its buffer has been written to the underlying device.
Definition: streams.h:86
streams::ostream::write
void write(const char *content, size_t size)
Write a block of data to this stream.
Definition: streams.h:113
streams::istream::operator>>
istream & operator>>(unsigned long &value)
Input and interpret next word from buffer as an unsigned long integer value.
Definition: streams.h:619
streams::ostreambuf::pubsync
void pubsync()
Wait until all buffer content has been pulled by a consumer.
Definition: streambuf.h:64
streams::istreambuf::EOF
static const int EOF
Special value returned by sbumpc() when buffer is empty.
Definition: streambuf.h:220
streams::ostreambuf::sputc
void sputc(char c)
Append a character to the buffer.
Definition: streambuf.h:76
streams::istream::operator>>
istream & operator>>(double &value)
Input and interpret next word from buffer as a floating point value.
Definition: streams.h:639
streams::ostream::operator<<
ostream & operator<<(const void *ptr)
Output the address of a pointer.
Definition: streams.h:157
streams::istreambuf::queue
QUEUE & queue()
Return the underlying queue.
Definition: streambuf.h:258
streams::ostream::rdbuf
ostreambuf & rdbuf() const
Return the stream buffer associated with this stream.
Definition: streams.h:74
streams::istream::operator>>
istream & operator>>(int &value)
Input and interpret next word from buffer as a signed integer value.
Definition: streams.h:559
streams::ostreambuf::overflow
bool overflow() const
Indicate if a buffer overflow has occurred since last time pubsync() or reset_overflow() was called.
Definition: streambuf.h:145
streambuf.h
C++-like std::iostream facilities.
streams::istream::operator>>
istream & operator>>(long &value)
Input and interpret next word from buffer as a signed long integer value.
Definition: streams.h:599
streams::istream::get
istream & get(char *str, size_t n, char delim='\n')
Extract characters from this input stream and stores them as a C-string, until either (n - 1) charact...
Definition: streams.h:422
streams::ostream::operator<<
ostream & operator<<(long value)
Output a signed long integral number, represented within the current base(), using the current minimu...
Definition: streams.h:268
streams::flush
void flush(FSTREAM &stream)
Manipulator for an output stream, which will flush the stream buffer.
Definition: streams.h:713
flash.h
Flash memory utilities.
streams::istream::MANIPULATOR
void(*)(istream &) MANIPULATOR
General type of a manipulator function applicable to this input stream.
Definition: streams.h:652