This is the multi-page printable view of this section. Click here to print...

Return to the regular view of this page

As of 2025-07-24

Input/Output Stream

Base class for handling input/output streams
This is a base class for handling input/output streams.
  • Provides interfaces to several classes (Serial, Wire, SPI, smplbuf) using polymorphism with the CRTP (Curiously Recurring Template Pattern) method.
    • In CRTP, derived classes are defined as template class Derived : public stream<Derived>;, allowing the base class to also refer to methods of the derived class.
  • This class defines common processing such as the print method and the << operator, and calls methods like write() implemented in derived classes, achieving an implementation similar to using virtual functions.

Interface (Implemented in Derived Classes)

Derived classes implement the following functions.

available()

int available()

// example
while(Serial.available()) {
  int c = Serial.read();
  // ... any
}

Returns 1 if input exists, 0 if not.

ParameterDescription
Return int0: No data 1: Data available

flush()

void flush()

// example
Serial.println("long long word .... ");
Serial.flush();

Flushes the output (waits until output is complete).

read()

int read()

// example
int c;
while (-1 != (c = read())) {
    // any
}

Reads one byte of data from the stream. Returns -1 if no data is available.

write()

size_t write(int c)

// example
Serial.write(0x30);

Outputs one byte to the stream.

ParameterDescription
nThe character to output.
Return size_t1 if output succeeded, 0 if failed.

vOutput()

static void vOutput(char out, void* vp)

A static function that outputs one byte. Since it is not a class method, member variables cannot be used. Instead, a pointer to the class instance is passed as the parameter vp.

This static function is used internally and passed as a function pointer for one-byte output to fctprintf(). It is used to implement methods like print.

ParameterDescription
outThe character to output
vpPointer to the class instance
Usually cast back to the original class to call the write() method

Interface

putchar()

void mwx::stream::putchar(char c)

// example
Serial.putchar('A');
// result -> A

Outputs one byte.

size_t print(T val, int base = DEC) // T: integer type
size_t print(double val, int place = 2)
size_t print(const char*str)
size_t print(std::initializer_list<int>)

// example
Serial.print("the value is ");
Serial.print(123, DEC);
Serial.println(".");
// result -> the value is 123.

Serial.print(123.456, 1);
// result -> 123.5

Serial.print({ 0x12, 0x34, 0xab, 0xcd });
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Performs various formatted outputs.

ParameterDescription
valThe numeric type to format and output
baseOutput format BIN binary / OCT octal / DEC decimal / HEX hexadecimal
placeNumber of decimal places
Return size_tNumber of bytes written

printfmt()

size_t printfmt(const char* format, ...);

// example
Serial.printfmt("the value is %d.", 123);
// result -> the value is 123.

Outputs formatted output in printf style.

See TWESDK/TWENET/current/src/printf/README.md

operator <<

// examples
Serial << "this value is" // const char*
       << int(123)
       << '.';
       << mwx::crlf;
// result -> this value is 123.

Serial << fromat("this value is %d.", 123) << twe::crlf;
// result -> this value is 123.

Serial << mwx::flush; // flush here

Serial << bigendian(0x1234abcd);
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Serial << int(0x30) // output 0x30=48, "48"
       << '/'
       << uint8_t(0x31); // output '1', not "48"
// result -> 48/1

smplbuf<char,16> buf = { 0x12, 0x34, 0xab, 0xcd };
Serail << but.to_stream();
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Seiral << make_pair(buf.begin(), buf.end());
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.

Serial << bytelist({ 0x12, 0x34, 0xab, 0xcd });
// will output 4byte of 0x12 0x34 0xab 0xcd in binary.
Argument TypeDescription
charOutputs one byte (does not format as a number)
intOutputs integer (printf “%d”)
doubleOutputs number (printf “%.2f”)
uint8_tOutputs one byte (same as char type)
uint16_tOutputs 2 bytes (big endian order)
uint32_tOutputs 4 bytes (big endian order)
const char*``uint8_t*``const char[S]Outputs up to the terminating character. The terminator is not included in output. (S is fixed array size)
uint8_t[S]Outputs S bytes of the array as is. (S is fixed array size)
format()Outputs in printf format
mwx::crlfOutputs newline CRLF
mwx::flushFlushes output
bigendian()Outputs numeric types in big endian order (rvalue)
std::pair<T*, T*>Pair containing begin(), end() pointers of byte type. Can be generated by make_pair. T is assumed to be uint8_t. (rvalue)
bytelist()Outputs byte sequence using std::initializer_list
smplbuf<uint8_t,AL>&Outputs contents of an array class of type uint8_t. ALC is memory allocation method.
smplbuf<uint8_t, AL>::to_stream()Outputs data of smplbuf<T>
T is uint8_t type, AL is memory allocation method.

set_timeout(), get_error_status(), clear_error_status()

uint8_t get_error_status()
void clear_error_status()
void set_timeout(uint8_t centisec)

// example
Serial.set_timeout(100); // Set timeout to 1000ms
uint8_t c;
Serial >> c;

Manages input timeout and errors using the >> operator.

Specify the timeout duration with set_timeout(), and perform input with the >> operator. If input is not obtained within the specified time, error value can be read with get_error_status(). Clear error status with clear_error_status().

Argument TypeDescription
centisecSets timeout duration in 1/10 second units. Specifying 0xff disables timeout.

Error Values

ValueMeaning
0No error
1Error status

operator >>

inline D& operator >> (uint8_t& v)
inline D& operator >> (char_t& v)
template <int S> inline D& operator >> (uint8_t(&v)[S])
inline D& operator >> (uint16_t& v)
inline D& operator >> (uint32_t& v)
inline D& operator >> (mwx::null_stream&& p)

//// Example
uint8_t c;

the_twelite.stop_watchdog(); // Stop the watchdog
Serial.set_timeout(0xFF); // No timeout

// Read one byte
Serial >> c;
Serial << crlf << "char #1: [" << c << ']';

// Discard bytes
Serial >> null_stream(3); // Discard 3 bytes
Serial << crlf << "char #2-4: skipped";

// Read 4 bytes (fixed-length array of uint8_t only)
uint8_t buff[4];
Serial >> buff;
Serial << crlf << "char #5-8: [" << buff << "]";

Performs input.

Below are the types that can be read and stored.

Argument TypeDescription
uint8_t, char_tReads one byte
uint16_tReads 2 bytes (big endian order)
uint32_tReads 4 bytes (big endian order)
uint8_t[S]Reads S bytes (S is fixed array size)
null_stream(int n)Discards n bytes

1 - mwx::mwx_format

printf format input
This is a helper class that writes format specifiers for the << operator of mwx::stream.

Within the library, it is aliased as Using format=mwx::mwx_format;.

Serial << format("formatted print: %.2f", (double)3123 / 100.) << mwx::crlf;

// formatted print: 31.23[newline]
  • Store the argument list received by the constructor into internal class variables using parameter pack expansion
  • When operator << is called, call fctprintf() and write data to the stream

Constructor

format(const char *fmt, ...)

The constructor saves the format pointer and parameters. The following << operator call interprets the format and performs output processing.

ParameterDescription
fmtFormat string. See TWESDK/TWENET/current/src/printf/README.md
...Parameters corresponding to the format string.
※ The maximum number is 4; using 5 or more parameters will cause a compile error. ※ Consistency with the format is not checked, so unsafe for inconsistent input.

2 - mwx::bigendian

Data output in big-endian order
This is a helper class that outputs numeric types as big-endian byte sequences for the << operator of mwx::stream.
Serial << mwx::bigendian(0x1234abcdUL);

// output binary -> 0x12 0x34 0xab 0xcd

Constructor

template <typename T>
bigendian::bigendian(T v)
ParameterDescription
vA value of type uint16_t or uint32_t

3 - mwx::crlf

Output of newline code
An instance of a helper class to output newline code (CR LF) for the << operator of mwx::stream.
Serial << "hello world!" << mwx::crlf;

4 - mwx::flush

Force output of the output buffer
Flushes the output buffer of mwx::stream.

An instance of a helper class that calls the flush() method.

for (int i = 0; i < 127; ++i) {
    Serial << "hello world! (" << i << ")" << twe::endl << twe::flush;
}
  • In the case of a serial port, polling wait is performed until output is complete
  • In the case of an mwx::simpbuf buffer, 0x00 is output at the end (size does not change)

5 - stream_helper

Helper object
stream_helper is a helper object that provides the mwx::stream interface. It generates a helper object that references a data class, and performs data input/output through the helper object.

Below, a helper object bs is generated from the array b of smplbuf, and data input is performed using the mwx::stream::operator <<() operator.

smplbuf_u8<32> b;
auto&& bs = b.get_stream_helper(); // Helper object

// Generate data sequence
uint8_t FOURCHARS[]={'A', 'B', 'C', 'D'};
bs << FOURCHARS;
bs << ';';
bs << uint32_t(0x30313233); // "0123"
bs << format(";%d", 99);

Serial << b << crlf; // Output to Serial is via smplbuf_u8<32> class

// Result: ABCD;0123;99

Overview

stream_helper behaves as if the data array is a stream.

Internally, it keeps track of the read/write position within the data array. It behaves as follows:

  • When reading or writing, the read/write position moves to the next position.
  • After reading the last data or appending data to the end, the read/write position becomes the end position.
  • When the read/write position is at the end,
    • available() returns false.
    • Reading is not possible.
    • Writing appends data if within writable range.

Creating stream_helper

stream_helper is created from member functions of data classes (smplbuf, EEPROM).

auto&& obj_helper = obj.get_stream_helper()
// obj is an object of a data class, and obj_helper's type is long, so it is received with auto&&.

Methods

rewind()

void rewind()

Moves the read/write position to the beginning.

seek()

int seek(int offset, int whence = MWX_SEEK_SET)

Sets the read/write position.

whencePosition set
MWX_SEEK_SETSets from the beginning. offset of 0 means the same as rewind().
MWX_SEEK_CURMoves by offset from the current position.
MWX_SEEK_ENDSets to the end position. offset of 0 sets to the end. -1 moves to the last character.

tell()

int tell()

Returns the read/write position. Returns -1 if at the end position.

available()

int available()

Returns 0 if the read/write position is at the end. Otherwise, returns a non-zero value.