22
22
#ifndef Stream_h
23
23
#define Stream_h
24
24
25
+ #include < debug.h>
25
26
#include < inttypes.h>
26
- #include " Print.h"
27
+ #include < Print.h>
28
+ #include < PolledTimeout.h>
29
+ #include < sys/types.h> // ssize_t
27
30
28
- // compatability macros for testing
31
+ // compatibility macros for testing
29
32
/*
30
33
#define getInt() parseInt()
31
34
#define getInt(skipChar) parseInt(skipchar)
35
38
readBytesBetween( pre_string, terminator, buffer, length)
36
39
*/
37
40
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
+
38
50
class Stream : public Print {
39
51
protected:
40
52
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 {
53
65
// parsing methods
54
66
55
67
void setTimeout (unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
68
+ unsigned long getTimeout () const { return _timeout; }
56
69
57
70
bool find (const char *target); // reads data from the stream until the target string is found
58
71
bool find (uint8_t *target) {
@@ -102,12 +115,114 @@ class Stream: public Print {
102
115
virtual String readString ();
103
116
String readStringUntil (char terminator);
104
117
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
+
105
221
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
108
223
// this allows format characters (typically commas) in values to be ignored
109
224
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
111
226
};
112
227
113
228
#endif
0 commit comments