diff --git a/api/Stream.h b/api/Stream.h index e81c71ba..b20fe548 100644 --- a/api/Stream.h +++ b/api/Stream.h @@ -128,6 +128,35 @@ class Stream : public Print #undef NO_IGNORE_CHAR +// Structure to store a value and a modifier. +template +struct Format { + T data; + int modifier; +}; + +// Helper function that creates a `Format` object. +template +Format format(T const data, int const modifier) { + Format fmt {data, modifier}; + return fmt; +} + +// Stream insertion operator for plain data types. +template +Stream& operator <<(Stream& stream, T const data) { + stream.print(data); + return stream; +} + +// Stream insertion operator with modifiers (e.g., BIN, HEX, number of digits, etc.). +template +Stream& operator <<(Stream& stream, Format const& parameters) { + stream.print(parameters.data, parameters.modifier); + return stream; +} + } -using arduino::Stream; \ No newline at end of file +using arduino::Stream; +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..7de74705 --- /dev/null +++ b/test/src/Stream/test_insertion_operator.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Arduino. All rights reserved. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include + +#include + +/************************************************************************************** + * TEST CODE + **************************************************************************************/ + +TEST_CASE ("Testing 'Format' initialisation", "[Stream-insertion-operator-01]") { + arduino::Format fmt {'a', 2}; + REQUIRE(fmt.data == 'a'); + REQUIRE(fmt.modifier == 2); +} + +TEST_CASE ("Testing 'format' helper function", "[Stream-insertion-operator-02]") { + arduino::Format fmt {arduino::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 because `StreamMock` has its own << operator. + REQUIRE(mock.available() == 6); + + char buf[10] {}; + mock.readBytes(buf, 6); + REQUIRE(not strncmp(buf, "a12b34", 6)); +} + +TEST_CASE ("Testing insertion operator with modifiers", "[Stream-insertion-operator-04]") { + StreamMock mock; + mock << arduino::format(1.2, 4); + REQUIRE(mock.available() == 6); + + char buf[10] {}; + mock.readBytes(buf, 6); + REQUIRE(not strncmp(buf, "1.2000", 6)); + + mock << arduino::format(12, BIN); + REQUIRE(mock.available() == 4); + + mock.readBytes(buf, 4); + REQUIRE(not strncmp(buf, "1100", 4)); +}