From e25c4af1a5340d3d9228abee40f7e5e5775eb6a2 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 2 Dec 2023 00:29:23 +0100 Subject: [PATCH 1/6] String2Stream: +helpers to stream (temporary) streamed strings CS2Stream(sourceStringNotConsumed).sendAll(S2Stream(destString)); --- cores/esp8266/Stream.h | 4 ++++ cores/esp8266/StreamString.h | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cores/esp8266/Stream.h b/cores/esp8266/Stream.h index 21f319ee6b..0706bec001 100644 --- a/cores/esp8266/Stream.h +++ b/cores/esp8266/Stream.h @@ -196,21 +196,25 @@ class Stream: public Print { // returns number of transferred bytes size_t sendAvailable (Stream* to) { return sendGeneric(to, -1, -1, oneShotMs::alwaysExpired); } size_t sendAvailable (Stream& to) { return sendAvailable(&to); } + size_t sendAvailable (Stream&& to) { return sendAvailable(&to); } // transfers data until timeout // returns number of transferred bytes size_t sendAll (Stream* to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, -1, timeoutMs); } size_t sendAll (Stream& to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendAll(&to, timeoutMs); } + size_t sendAll (Stream&& to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendAll(&to, timeoutMs); } // transfers data until a char is encountered (the char is swallowed but not transferred) with timeout // returns number of transferred bytes size_t sendUntil (Stream* to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, readUntilChar, timeoutMs); } size_t sendUntil (Stream& to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendUntil(&to, readUntilChar, timeoutMs); } + size_t sendUntil (Stream&& to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendUntil(&to, readUntilChar, timeoutMs); } // transfers data until requested size or timeout // returns number of transferred bytes size_t sendSize (Stream* to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, maxLen, -1, timeoutMs); } size_t sendSize (Stream& to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendSize(&to, maxLen, timeoutMs); } + size_t sendSize (Stream&& to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendSize(&to, maxLen, timeoutMs); } // remaining size (-1 by default = unknown) virtual ssize_t streamRemaining () { return -1; } diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h index 2331a3c51a..b466c89e97 100644 --- a/cores/esp8266/StreamString.h +++ b/cores/esp8266/StreamString.h @@ -30,6 +30,7 @@ /////////////////////////////////////////////////////////////// // S2Stream points to a String and makes it a Stream +// ("String to Stream") // (it is also the helper for StreamString) class S2Stream: public Stream @@ -192,7 +193,7 @@ class S2Stream: public Stream } // Reading this stream will mark the string as read without consuming - // (not enabled by default) + // (not enabled by default, see CS2Stream) // Calling resetPointer() resets the read state and allows rereading. void resetPointer(int pointer = 0) { @@ -204,6 +205,21 @@ class S2Stream: public Stream int peekPointer; // -1:String is consumed / >=0:resettable pointer }; +/////////////////////////////////////////////////////////////// +// CS2Stream is a S2Stream using an unmodifiable string by default +// ("Constant String to Stream") +// for equivalent with char* see StreamConstPtr(StreamDev.h) + +class CS2Stream: public S2Stream +{ +public: + + CS2Stream(String& string) : S2Stream(string, 0) { } + CS2Stream(String* string) : S2Stream(string, 0) { } + void setConsume() = delete; // prevent from modifying the string +}; + +/////////////////////////////////////////////////////////////// // StreamString is a S2Stream holding the String class StreamString: public String, public S2Stream From 27687f667277e2eb807cb064fcc6f41cc37b7753 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 2 Dec 2023 01:18:38 +0100 Subject: [PATCH 2/6] style --- cores/esp8266/StreamString.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h index b466c89e97..407ee622c6 100644 --- a/cores/esp8266/StreamString.h +++ b/cores/esp8266/StreamString.h @@ -213,10 +213,9 @@ class S2Stream: public Stream class CS2Stream: public S2Stream { public: - CS2Stream(String& string) : S2Stream(string, 0) { } CS2Stream(String* string) : S2Stream(string, 0) { } - void setConsume() = delete; // prevent from modifying the string + void setConsume() = delete; // prevent from modifying the string }; /////////////////////////////////////////////////////////////// From d01664c866ab75121d284557c1f45608e4ea03d7 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sun, 3 Dec 2023 22:38:23 +0100 Subject: [PATCH 3/6] more comments, checks and tests --- cores/esp8266/StreamString.h | 22 +++++++++---------- .../examples/StreamString/StreamString.ino | 18 +++++++++++---- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h index 407ee622c6..3ab0264154 100644 --- a/cores/esp8266/StreamString.h +++ b/cores/esp8266/StreamString.h @@ -29,8 +29,7 @@ #include "WString.h" /////////////////////////////////////////////////////////////// -// S2Stream points to a String and makes it a Stream -// ("String to Stream") +// S2Stream ("String to Stream") points to a String and makes it a Stream // (it is also the helper for StreamString) class S2Stream: public Stream @@ -185,19 +184,19 @@ class S2Stream: public Stream return peekPointer < 0 ? string->length() : string->length() - peekPointer; } - // calling setConsume() will consume bytes as the stream is read - // (enabled by default) + // calling setConsume() will make the string consumed as the stream is read. + // (default behaviour) void setConsume() { peekPointer = -1; } - // Reading this stream will mark the string as read without consuming - // (not enabled by default, see CS2Stream) - // Calling resetPointer() resets the read state and allows rereading. - void resetPointer(int pointer = 0) + // Calling resetPointer() resets the read cursor and allows rereading. + // (this is the opposite of default mode set by setConsume()) + // (check also CS2Stream::) + void resetPointer(size_t pointer = 0) { - peekPointer = pointer; + peekPointer = std::min(std::max(0U, pointer), string->length()); } protected: @@ -206,9 +205,8 @@ class S2Stream: public Stream }; /////////////////////////////////////////////////////////////// -// CS2Stream is a S2Stream using an unmodifiable string by default -// ("Constant String to Stream") -// for equivalent with char* see StreamConstPtr(StreamDev.h) +// CS2Stream ("Constant String to Stream") is a S2Stream using an unmodifiable String +// (for an equivalent with char* see StreamConstPtr:: in StreamDev.h) class CS2Stream: public S2Stream { diff --git a/libraries/esp8266/examples/StreamString/StreamString.ino b/libraries/esp8266/examples/StreamString/StreamString.ino index f177b53edc..9334dd054c 100644 --- a/libraries/esp8266/examples/StreamString/StreamString.ino +++ b/libraries/esp8266/examples/StreamString/StreamString.ino @@ -54,7 +54,7 @@ void testStreamString() { { // We use a a lighter StreamConstPtr(input) to make a read-only Stream out of // a String that obviously should not be modified during the time the - // StreamConstPtr instance is used. It is used as a source to be sent to + // StreamConstPtr instance is used. It is used as a read-only source to be sent to // 'result'. result.clear(); @@ -77,7 +77,7 @@ void testStreamString() { // Now inputString is made into a Stream using S2Stream, // and set in non-consume mode (using ::resetPointer()). - // Then, after that input is read once, it won't be anymore readable + // Then, after input is read once, it won't be anymore readable // until the pointer is reset. S2Stream input(inputString); @@ -87,7 +87,7 @@ void testStreamString() { input.sendAll(result); input.sendAll(result); check("S2Stream.sendAll(StreamString)", result.c_str(), "hello"); - check("unmodified String given to S2Stream", inputString.c_str(), "hello"); + check("String given to S2Stream is unmodified", inputString.c_str(), "hello"); } { @@ -103,6 +103,15 @@ void testStreamString() { check("S2Stream.resetPointer(2):", result.c_str(), "llo"); } + { + // This can also be done with CS2Stream without intermediate variable + + result.clear(); + CS2Stream(inputString).sendAll(result); + CS2Stream(inputString).sendAll(result); + check("CS2Stream(String).sendAll(StreamString)", result.c_str(), "hellohello"); + } + { // inputString made into a Stream // reading the Stream consumes the String @@ -181,7 +190,8 @@ void setup() { testStreamString(); - Serial.printf("sizeof: String:%d Stream:%d StreamString:%d SStream:%d\n", (int)sizeof(String), (int)sizeof(Stream), (int)sizeof(StreamString), (int)sizeof(S2Stream)); + Serial.printf("sizeof: String:%zu Stream:%zu StreamString:%zu S2Stream:%zu CS2Stream:%zu\n", + sizeof(String), sizeof(Stream), sizeof(StreamString), sizeof(S2Stream), sizeof(CS2Stream)); } #endif From 44b3d3902b38165ab9a176f8e49c6d5f3b5fde8e Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 6 Dec 2023 00:02:55 +0100 Subject: [PATCH 4/6] remove CS2Stream --- cores/esp8266/StreamString.h | 15 +-------------- .../examples/StreamString/StreamString.ino | 16 +++++++++------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h index 3ab0264154..385fd31996 100644 --- a/cores/esp8266/StreamString.h +++ b/cores/esp8266/StreamString.h @@ -193,10 +193,9 @@ class S2Stream: public Stream // Calling resetPointer() resets the read cursor and allows rereading. // (this is the opposite of default mode set by setConsume()) - // (check also CS2Stream::) void resetPointer(size_t pointer = 0) { - peekPointer = std::min(std::max(0U, pointer), string->length()); + peekPointer = std::min(std::max(0U, (unsigned int)pointer), string->length()); } protected: @@ -204,18 +203,6 @@ class S2Stream: public Stream int peekPointer; // -1:String is consumed / >=0:resettable pointer }; -/////////////////////////////////////////////////////////////// -// CS2Stream ("Constant String to Stream") is a S2Stream using an unmodifiable String -// (for an equivalent with char* see StreamConstPtr:: in StreamDev.h) - -class CS2Stream: public S2Stream -{ -public: - CS2Stream(String& string) : S2Stream(string, 0) { } - CS2Stream(String* string) : S2Stream(string, 0) { } - void setConsume() = delete; // prevent from modifying the string -}; - /////////////////////////////////////////////////////////////// // StreamString is a S2Stream holding the String diff --git a/libraries/esp8266/examples/StreamString/StreamString.ino b/libraries/esp8266/examples/StreamString/StreamString.ino index 9334dd054c..a4e47a1da2 100644 --- a/libraries/esp8266/examples/StreamString/StreamString.ino +++ b/libraries/esp8266/examples/StreamString/StreamString.ino @@ -104,12 +104,14 @@ void testStreamString() { } { - // This can also be done with CS2Stream without intermediate variable + // This can also be done with StreamConstPtr as source without intermediate variable + // and S2Stream as destination without intermediate variable - result.clear(); - CS2Stream(inputString).sendAll(result); - CS2Stream(inputString).sendAll(result); - check("CS2Stream(String).sendAll(StreamString)", result.c_str(), "hellohello"); + String someRegularString { F("hello") }; + + StreamConstPtr(someRegularString).sendAll(S2Stream(someRegularString)); + StreamConstPtr(someRegularString).sendAll(S2Stream(someRegularString)); + check("StreamConstPtr(aString).sendAll(S2Stream(someString))", someRegularString.c_str(), "hellohello"); } { @@ -190,8 +192,8 @@ void setup() { testStreamString(); - Serial.printf("sizeof: String:%zu Stream:%zu StreamString:%zu S2Stream:%zu CS2Stream:%zu\n", - sizeof(String), sizeof(Stream), sizeof(StreamString), sizeof(S2Stream), sizeof(CS2Stream)); + Serial.printf("sizeof: String:%zu Stream:%zu StreamString:%zu S2Stream:%zu StreamConstPtr:%zu\n", + sizeof(String), sizeof(Stream), sizeof(StreamString), sizeof(S2Stream), sizeof(StreamConstPtr)); } #endif From 0e5edc36087db93106919939ccd4514af69b0a5b Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 6 Dec 2023 09:05:57 +0100 Subject: [PATCH 5/6] fix example update --- .../esp8266/examples/StreamString/StreamString.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/esp8266/examples/StreamString/StreamString.ino b/libraries/esp8266/examples/StreamString/StreamString.ino index a4e47a1da2..73512cf2af 100644 --- a/libraries/esp8266/examples/StreamString/StreamString.ino +++ b/libraries/esp8266/examples/StreamString/StreamString.ino @@ -104,14 +104,14 @@ void testStreamString() { } { - // This can also be done with StreamConstPtr as source without intermediate variable - // and S2Stream as destination without intermediate variable + // Streaming to a regular String - String someRegularString { F("hello") }; + String someSource{ F("hello") }; + String someDestString; - StreamConstPtr(someRegularString).sendAll(S2Stream(someRegularString)); - StreamConstPtr(someRegularString).sendAll(S2Stream(someRegularString)); - check("StreamConstPtr(aString).sendAll(S2Stream(someString))", someRegularString.c_str(), "hellohello"); + StreamConstPtr(someSource).sendAll(S2Stream(someDestString)); + StreamConstPtr(someSource).sendAll(S2Stream(someDestString)); + check("StreamConstPtr(someSource).sendAll(S2Stream(someDestString))", someDestString.c_str(), "hellohello"); } { @@ -193,7 +193,7 @@ void setup() { testStreamString(); Serial.printf("sizeof: String:%zu Stream:%zu StreamString:%zu S2Stream:%zu StreamConstPtr:%zu\n", - sizeof(String), sizeof(Stream), sizeof(StreamString), sizeof(S2Stream), sizeof(StreamConstPtr)); + sizeof(String), sizeof(Stream), sizeof(StreamString), sizeof(S2Stream), sizeof(StreamConstPtr)); } #endif From ce128a6a862c61da723d6f19d9f9e36c8936dc94 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 8 Dec 2023 10:34:13 +0100 Subject: [PATCH 6/6] size_t is already unsigned --- cores/esp8266/StreamString.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h index 385fd31996..dced5aee80 100644 --- a/cores/esp8266/StreamString.h +++ b/cores/esp8266/StreamString.h @@ -195,7 +195,7 @@ class S2Stream: public Stream // (this is the opposite of default mode set by setConsume()) void resetPointer(size_t pointer = 0) { - peekPointer = std::min(std::max(0U, (unsigned int)pointer), string->length()); + peekPointer = std::min(pointer, (size_t)string->length()); } protected: