2222#ifndef Stream_h
2323#define Stream_h
2424
25+ #include < debug.h>
2526#include < inttypes.h>
26- #include " Print.h"
27+ #include < Print.h>
28+ #include < PolledTimeout.h>
29+ #include < sys/types.h> // ssize_t
2730
28- // compatability macros for testing
31+ // compatibility macros for testing
2932/*
3033 #define getInt() parseInt()
3134 #define getInt(skipChar) parseInt(skipchar)
3538 readBytesBetween( pre_string, terminator, buffer, length)
3639 */
3740
41+ // Arduino `Client: public Stream` class defines `virtual int read(uint8_t *buf, size_t size) = 0;`
42+ // This function is now imported into `Stream::` for `Stream::send*()`.
43+ // Other classes inheriting from `Stream::` and implementing `read(uint8_t *buf, size_t size)`
44+ // must consequently use `int` as return type, namely Hardware/SoftwareSerial, FileSystems...
45+ #define STREAM_READ_RETURNS_INT 1
46+
47+ // Stream::send API is present
48+ #define STREAMSEND_API 1
49+
3850class Stream : public Print {
3951 protected:
4052 unsigned long _timeout = 1000 ; // number of milliseconds to wait for the next char before aborting timed read
@@ -53,6 +65,7 @@ class Stream: public Print {
5365// parsing methods
5466
5567 void setTimeout (unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
68+ unsigned long getTimeout () const { return _timeout; }
5669
5770 bool find (const char *target); // reads data from the stream until the target string is found
5871 bool find (uint8_t *target) {
@@ -102,12 +115,114 @@ class Stream: public Print {
102115 virtual String readString ();
103116 String readStringUntil (char terminator);
104117
118+ virtual int read (uint8_t * buffer, size_t len);
119+ int read (char * buffer, size_t len) { return read ((uint8_t *)buffer, len); }
120+
121+ // ////////////////// extension: direct access to input buffer
122+ // to provide when possible a pointer to available data for read
123+
124+ // informs user and ::to*() on effective buffered peek API implementation
125+ // by default: not available
126+ virtual bool hasPeekBufferAPI () const { return false ; }
127+
128+ // returns number of byte accessible by peekBuffer()
129+ virtual size_t peekAvailable () { return 0 ; }
130+
131+ // returns a pointer to available data buffer (size = peekAvailable())
132+ // semantic forbids any kind of ::read()
133+ // - after calling peekBuffer()
134+ // - and before calling peekConsume()
135+ virtual const char * peekBuffer () { return nullptr ; }
136+
137+ // consumes bytes after peekBuffer() use
138+ // (then ::read() is allowed)
139+ virtual void peekConsume (size_t consume) { (void )consume; }
140+
141+ // by default read timeout is possible (incoming data from network,serial..)
142+ // children can override to false (like String::)
143+ virtual bool inputCanTimeout () { return true ; }
144+
145+ // (outputCanTimeout() is defined in Print::)
146+
147+ // //////////////////////
148+ // ////////////////// extensions: Streaming streams to streams
149+ // Stream::send*()
150+ //
151+ // Stream::send*() uses 1-copy transfers when peekBuffer API is
152+ // available, or makes a regular transfer through a temporary buffer.
153+ //
154+ // - for efficiency, Stream classes should implement peekAPI when
155+ // possible
156+ // - for an efficient timeout management, Print/Stream classes
157+ // should implement {output,input}CanTimeout()
158+
159+ using oneShotMs = esp8266::polledTimeout::oneShotFastMs;
160+ static constexpr int temporaryStackBufferSize = 64 ;
161+
162+ // ::send*() methods:
163+ // - always stop before timeout when "no-more-input-possible-data"
164+ // or "no-more-output-possible-data" condition is met
165+ // - always return number of transfered bytes
166+ // When result is 0 or less than requested maxLen, Print::getLastSend()
167+ // contains an error reason.
168+
169+ // transfers already buffered / immediately available data (no timeout)
170+ // returns number of transfered bytes
171+ size_t sendAvailable (Print* to) { return sendGeneric (to, -1 , -1 , oneShotMs::alwaysExpired); }
172+ size_t sendAvailable (Print& to) { return sendAvailable (&to); }
173+
174+ // transfers data until timeout
175+ // returns number of transfered bytes
176+ size_t sendAll (Print* to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric (to, -1 , -1 , timeoutMs); }
177+ size_t sendAll (Print& to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendAll (&to, timeoutMs); }
178+
179+ // transfers data until a char is encountered (the char is swallowed but not transfered) with timeout
180+ // returns number of transfered bytes
181+ size_t sendUntil (Print* to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric (to, -1 , readUntilChar, timeoutMs); }
182+ size_t sendUntil (Print& to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendUntil (&to, readUntilChar, timeoutMs); }
183+
184+ // transfers data until requested size or timeout
185+ // returns number of transfered bytes
186+ size_t sendSize (Print* to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric (to, maxLen, -1 , timeoutMs); }
187+ size_t sendSize (Print& to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendSize (&to, maxLen, timeoutMs); }
188+
189+ // remaining size (-1 by default = unknown)
190+ virtual ssize_t streamRemaining () { return -1 ; }
191+
192+ enum class Report
193+ {
194+ Success = 0 ,
195+ TimedOut,
196+ ReadError,
197+ WriteError,
198+ ShortOperation,
199+ };
200+
201+ Report getLastSendReport () const { return _sendReport; }
202+
203+ protected:
204+ size_t sendGeneric (Print* to,
205+ const ssize_t len = -1 ,
206+ const int readUntilChar = -1 ,
207+ oneShotMs::timeType timeoutMs = oneShotMs::neverExpires /* neverExpires=>getTimeout() */ );
208+
209+ size_t SendGenericPeekBuffer (Print* to, const ssize_t len, const int readUntilChar, const oneShotMs::timeType timeoutMs);
210+ size_t SendGenericRegularUntil (Print* to, const ssize_t len, const int readUntilChar, const oneShotMs::timeType timeoutMs);
211+ size_t SendGenericRegular (Print* to, const ssize_t len, const oneShotMs::timeType timeoutMs);
212+
213+ void setReport (Report report) { _sendReport = report; }
214+
215+ private:
216+
217+ Report _sendReport = Report::Success;
218+
219+ // ////////////////// end of extensions
220+
105221 protected:
106- long parseInt (char skipChar); // as above but the given skipChar is ignored
107- // as above but the given skipChar is ignored
222+ long parseInt (char skipChar); // as parseInt() but the given skipChar is ignored
108223 // this allows format characters (typically commas) in values to be ignored
109224
110- float parseFloat (char skipChar); // as above but the given skipChar is ignored
225+ float parseFloat (char skipChar); // as parseFloat() but the given skipChar is ignored
111226};
112227
113228#endif
0 commit comments