1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-29 05:21:37 +03:00

Stream::send() (#6979)

This commit is contained in:
david gauchard
2021-03-15 01:36:20 +01:00
committed by GitHub
parent 4cc1472821
commit c720c0d9e8
48 changed files with 2136 additions and 650 deletions

View File

@ -0,0 +1,188 @@
// this example sketch in the public domain is also a host and device test
#include <StreamDev.h>
#include <StreamString.h>
void loop() {
delay(1000);
}
void checksketch(const char* what, const char* res1, const char* res2) {
if (strcmp(res1, res2) == 0) {
Serial << "PASSED: Test " << what << " (result: '" << res1 << "')\n";
} else {
Serial << "FAILED: Test " << what << ": '" << res1 << "' <> '" << res2 << "' !\n";
}
}
#ifndef check
#define check(what, res1, res2) checksketch(what, res1, res2)
#endif
void testStringPtrProgmem() {
static const char inProgmem [] PROGMEM = "I am in progmem";
auto inProgmem2 = F("I am too in progmem");
int heap = (int)ESP.getFreeHeap();
auto stream1 = StreamConstPtr(inProgmem, sizeof(inProgmem) - 1);
auto stream2 = StreamConstPtr(inProgmem2);
Serial << stream1 << " - " << stream2 << "\n";
heap -= (int)ESP.getFreeHeap();
check("NO heap occupation while streaming progmem strings", String(heap).c_str(), "0");
}
void testStreamString() {
String inputString = "hello";
StreamString result;
// By default, reading a S2Stream(String) or a StreamString will consume the String.
// It can be disabled by calling ::resetPointer(), (not default)
// and reenabled by calling ::setConsume(). (default)
//
// In default consume mode, reading a byte or a block will remove it from
// the String. Operations are O(n²).
//
// In non-default non-consume mode, it will just move a pointer. That one
// can be ::resetPointer(pos) anytime. See the example below.
// The String included in 'result' will not be modified by read:
// (this is not the default)
result.resetPointer();
{
// 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
// 'result'.
result.clear();
StreamConstPtr(inputString).sendAll(result);
StreamConstPtr(inputString).sendAll(result);
StreamConstPtr(inputString).sendAll(result);
check("StreamConstPtr.sendAll(StreamString)", result.c_str(), "hellohellohello");
}
{
// equivalent of the above
result.clear();
result << inputString;
result << inputString << inputString;
check("StreamString<<String", result.c_str(), "hellohellohello");
}
{
// 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
// until the pointer is reset.
S2Stream input(inputString);
input.resetPointer();
result.clear();
input.sendAll(result);
input.sendAll(result);
check("S2Stream.sendAll(StreamString)", result.c_str(), "hello");
check("unmodified String given to S2Stream", inputString.c_str(), "hello");
}
{
// Same as above, with an offset
result.clear();
S2Stream input(inputString);
// stream position set to offset 2 (0 by default)
input.resetPointer(2);
input.sendAll(result);
input.sendAll(result);
check("S2Stream.resetPointer(2):", result.c_str(), "llo");
}
{
// inputString made into a Stream
// reading the Stream consumes the String
result.clear();
S2Stream input(inputString);
// reading stream will consume the string
input.setConsume(); // can be ommitted, this is the default
input.sendSize(result, 1);
input.sendSize(result, 2);
check("setConsume(): S2Stream().sendSize(StreamString,3)", result.c_str(), "hel");
check("setConsume(): String given from S2Stream is swallowed", inputString.c_str(), "lo");
}
// Streaming with common String constructors
{
StreamString cons(inputString);
check("StreamString(String)", cons.c_str(), inputString.c_str());
}
{
StreamString cons(result);
check("StreamString(char*)", cons.c_str(), result.c_str());
}
{
StreamString cons("abc");
check("StreamString(char*)", cons.c_str(), "abc");
}
{
StreamString cons(F("abc"));
check("StreamString(F())", cons.c_str(), "abc");
}
{
StreamString cons(23);
check("StreamString(int)", cons.c_str(), "23");
}
{
StreamString cons('a');
check("StreamString(char)", cons.c_str(), "a");
}
{
StreamString cons(23.2);
check("StreamString(float)", cons.c_str(), "23.20");
}
#if !CORE_MOCK
// A progmem won't use Heap when StringPtr is used
testStringPtrProgmem();
// .. but it does when S2Stream or StreamString is used
{
int heap = (int)ESP.getFreeHeap();
auto stream = StreamString(F("I am in progmem"));
Serial << stream << "\n";
heap -= (int)ESP.getFreeHeap();
String heapStr(heap);
if (heap != 0) {
check("heap is occupied by String/StreamString(progmem)", heapStr.c_str(), heapStr.c_str());
} else {
check("ERROR: heap should be occupied by String/StreamString(progmem)", heapStr.c_str(), "-1");
}
}
// (check again to be sure)
testStringPtrProgmem();
#endif
}
#ifndef TEST_CASE
void setup() {
Serial.begin(115200);
delay(1000);
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));
}
#endif