diff --git a/api/Stream.h b/api/Stream.h index e81c71ba..4b9d2860 100644 --- a/api/Stream.h +++ b/api/Stream.h @@ -128,6 +128,34 @@ class Stream : public Print #undef NO_IGNORE_CHAR +template +struct Format { // Structure to store a value and a modifier. + T data; + int modifier; +}; + +template +Format format(T const data, int const modifier) { + Format fmt {data, modifier}; + return fmt; +} + + +template +Stream& operator <<(Stream& stream, T const data) { // Stream insertion operator for plain data types. + stream.print(data); + return stream; +} + +template +Stream& operator <<(Stream& stream, Format const& parameters) { // Stream insertion operator with modifiers (e.g., BIN, HEX, number of digits, etc.). + stream.print(parameters.data, parameters.modifier); + return stream; +} + } -using arduino::Stream; \ No newline at end of file +using arduino::Stream; +using arduino::Format; +using arduino::format; +using arduino::operator <<; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0f6200b2..1431a427 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -55,6 +55,7 @@ set(TEST_SRCS src/Stream/test_find.cpp src/Stream/test_findUntil.cpp src/Stream/test_getTimeout.cpp + src/Stream/test_insertion_operator.cpp src/Stream/test_parseFloat.cpp src/Stream/test_parseInt.cpp src/Stream/test_readBytes.cpp diff --git a/test/src/Stream/test_insertion_operator.cpp b/test/src/Stream/test_insertion_operator.cpp new file mode 100644 index 00000000..e0be4263 --- /dev/null +++ b/test/src/Stream/test_insertion_operator.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Arduino. All rights reserved. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include + +#include +#include + +/************************************************************************************** + * TEST CODE + **************************************************************************************/ + +TEST_CASE ("Testing 'Format' initialisation", "[Stream-insertion-operator-01]") { + Format fmt {'a', 2}; + REQUIRE(fmt.data == 'a'); + REQUIRE(fmt.modifier == 2); +} + +TEST_CASE ("Testing 'format' helper function", "[Stream-insertion-operator-02]") { + Format fmt {format('a', 2)}; + REQUIRE(fmt.data == 'a'); + REQUIRE(fmt.modifier == 2); +} + +TEST_CASE ("Testing basic insertion operator", "[Stream-insertion-operator-03]") { + StreamMock mock; + mock << 'a' << 12 << 'b' << 34; // Note we cannot test C strings as `StreamMock` has its own << operator. + REQUIRE(mock.available() == 6); +} + +TEST_CASE ("Testing insertion operator with modifiers", "[Stream-insertion-operator-03]") { + StreamMock mock; + mock << format(1.2, 4); // Expands to `1.2000`. + REQUIRE(mock.available() == 6); + mock << format(12, BIN); // Expands to `1100`. + REQUIRE(mock.available() == 10); +}