Stream.cpp
Go to the documentation of this file.
1 /*
2  Stream.cpp - adds parsing methods to Stream class
3  Copyright (c) 2008 David A. Mellis. All right reserved.
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 
19  Created July 2011
20  parsing functions based on TextFinder library by Michael Margolis
21 
22  findMulti/findUntil routines written by Jim Leonard/Xuth
23  */
24 
25 #include "Arduino.h"
26 #include "Stream.h"
27 
28 #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
29 
30 // private method to read stream with timeout
32 {
33  int c;
34  _startMillis = millis();
35  do {
36  c = read();
37  if (c >= 0) return c;
38  } while(millis() - _startMillis < _timeout);
39  return -1; // -1 indicates timeout
40 }
41 
42 // private method to peek stream with timeout
44 {
45  int c;
46  _startMillis = millis();
47  do {
48  c = peek();
49  if (c >= 0) return c;
50  } while(millis() - _startMillis < _timeout);
51  return -1; // -1 indicates timeout
52 }
53 
54 // returns peek of the next digit in the stream or -1 if timeout
55 // discards non-numeric characters
56 int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
57 {
58  int c;
59  while (1) {
60  c = timedPeek();
61 
62  if( c < 0 ||
63  c == '-' ||
64  (c >= '0' && c <= '9') ||
65  (detectDecimal && c == '.')) return c;
66 
67  switch( lookahead ){
68  case SKIP_NONE: return -1; // Fail code.
69  case SKIP_WHITESPACE:
70  switch( c ){
71  case ' ':
72  case '\t':
73  case '\r':
74  case '\n': break;
75  default: return -1; // Fail code.
76  }
77  case SKIP_ALL:
78  break;
79  }
80  read(); // discard non-numeric
81  }
82 }
83 
84 // Public Methods
86 
87 void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
88 {
89  _timeout = timeout;
90 }
91 
92  // find returns true if the target string is found
93 bool Stream::find(char *target)
94 {
95  return findUntil(target, strlen(target), NULL, 0);
96 }
97 
98 // reads data from the stream until the target string of given length is found
99 // returns true if target string is found, false if timed out
100 bool Stream::find(char *target, size_t length)
101 {
102  return findUntil(target, length, NULL, 0);
103 }
104 
105 // as find but search ends if the terminator string is found
106 bool Stream::findUntil(char *target, char *terminator)
107 {
108  return findUntil(target, strlen(target), terminator, strlen(terminator));
109 }
110 
111 // reads data from the stream until the target string of the given length is found
112 // search terminated if the terminator string is found
113 // returns true if target string is found, false if terminated or timed out
114 bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
115 {
116  if (terminator == NULL) {
117  MultiTarget t[1] = {{target, targetLen, 0}};
118  return findMulti(t, 1) == 0 ? true : false;
119  } else {
120  MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
121  return findMulti(t, 2) == 0 ? true : false;
122  }
123 }
124 
125 // returns the first valid (long) integer value from the current position.
126 // lookahead determines how parseInt looks ahead in the stream.
127 // See LookaheadMode enumeration at the top of the file.
128 // Lookahead is terminated by the first character that is not a valid part of an integer.
129 // Once parsing commences, 'ignore' will be skipped in the stream.
130 long Stream::parseInt(LookaheadMode lookahead, char ignore)
131 {
132  bool isNegative = false;
133  long value = 0;
134  int c;
135 
136  c = peekNextDigit(lookahead, false);
137  // ignore non numeric leading characters
138  if(c < 0)
139  return 0; // zero returned if timeout
140 
141  do{
142  if(c == ignore)
143  ; // ignore this character
144  else if(c == '-')
145  isNegative = true;
146  else if(c >= '0' && c <= '9') // is c a digit?
147  value = value * 10 + c - '0';
148  read(); // consume the character we got with peek
149  c = timedPeek();
150  }
151  while( (c >= '0' && c <= '9') || c == ignore );
152 
153  if(isNegative)
154  value = -value;
155  return value;
156 }
157 
158 // as parseInt but returns a floating point value
159 float Stream::parseFloat(LookaheadMode lookahead, char ignore)
160 {
161  bool isNegative = false;
162  bool isFraction = false;
163  long value = 0;
164  int c;
165  float fraction = 1.0;
166 
167  c = peekNextDigit(lookahead, true);
168  // ignore non numeric leading characters
169  if(c < 0)
170  return 0; // zero returned if timeout
171 
172  do{
173  if(c == ignore)
174  ; // ignore
175  else if(c == '-')
176  isNegative = true;
177  else if (c == '.')
178  isFraction = true;
179  else if(c >= '0' && c <= '9') { // is c a digit?
180  value = value * 10 + c - '0';
181  if(isFraction)
182  fraction *= 0.1;
183  }
184  read(); // consume the character we got with peek
185  c = timedPeek();
186  }
187  while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore );
188 
189  if(isNegative)
190  value = -value;
191  if(isFraction)
192  return value * fraction;
193  else
194  return value;
195 }
196 
197 // read characters from stream into buffer
198 // terminates if length characters have been read, or timeout (see setTimeout)
199 // returns the number of characters placed in the buffer
200 // the buffer is NOT null terminated.
201 //
202 size_t Stream::readBytes(char *buffer, size_t length)
203 {
204  size_t count = 0;
205  while (count < length) {
206  int c = timedRead();
207  if (c < 0) break;
208  *buffer++ = (char)c;
209  count++;
210  }
211  return count;
212 }
213 
214 
215 // as readBytes with terminator character
216 // terminates if length characters have been read, timeout, or if the terminator character detected
217 // returns the number of characters placed in the buffer (0 means no valid data found)
218 
219 size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
220 {
221  if (length < 1) return 0;
222  size_t index = 0;
223  while (index < length) {
224  int c = timedRead();
225  if (c < 0 || c == terminator) break;
226  *buffer++ = (char)c;
227  index++;
228  }
229  return index; // return number of characters, not including null terminator
230 }
231 
233 {
234  String ret;
235  int c = timedRead();
236  while (c >= 0)
237  {
238  ret += (char)c;
239  c = timedRead();
240  }
241  return ret;
242 }
243 
244 String Stream::readStringUntil(char terminator)
245 {
246  String ret;
247  int c = timedRead();
248  while (c >= 0 && c != terminator)
249  {
250  ret += (char)c;
251  c = timedRead();
252  }
253  return ret;
254 }
255 
256 int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
257  // any zero length target string automatically matches and would make
258  // a mess of the rest of the algorithm.
259  for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
260  if (t->len <= 0)
261  return t - targets;
262  }
263 
264  while (1) {
265  int c = timedRead();
266  if (c < 0)
267  return -1;
268 
269  for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
270  // the simple case is if we match, deal with that first.
271  if (c == t->str[t->index]) {
272  if (++t->index == t->len)
273  return t - targets;
274  else
275  continue;
276  }
277 
278  // if not we need to walk back and see if we could have matched further
279  // down the stream (ie '1112' doesn't match the first position in '11112'
280  // but it will match the second position so we can't just reset the current
281  // index to 0 when we find a mismatch.
282  if (t->index == 0)
283  continue;
284 
285  int origIndex = t->index;
286  do {
287  --t->index;
288  // first check if current char works against the new current index
289  if (c != t->str[t->index])
290  continue;
291 
292  // if it's the only char then we're good, nothing more to check
293  if (t->index == 0) {
294  t->index++;
295  break;
296  }
297 
298  // otherwise we need to check the rest of the found string
299  int diff = origIndex - t->index;
300  size_t i;
301  for (i = 0; i < t->index; ++i) {
302  if (t->str[i] != t->str[i + diff])
303  break;
304  }
305 
306  // if we successfully got through the previous loop then our current
307  // index is good.
308  if (i == t->index) {
309  t->index++;
310  break;
311  }
312 
313  // otherwise we just try the next index
314  } while (t->index);
315  }
316  }
317  // unreachable
318  return -1;
319 }
GLuint GLsizei GLsizei * length
size_t readBytesUntil(char terminator, char *buffer, size_t length)
Definition: Stream.cpp:219
long parseInt(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR)
Definition: Stream.cpp:130
const GLfloat * c
GLdouble GLdouble t
int timedRead()
Definition: Stream.cpp:31
unsigned long _timeout
Definition: Stream.h:52
bool findUntil(char *target, char *terminator)
Definition: Stream.cpp:106
GLsizei const GLfloat * value
unsigned long _startMillis
Definition: Stream.h:53
bool find(char *target)
Definition: Stream.cpp:93
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
Definition: Stream.cpp:56
GLuint buffer
float parseFloat(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR)
Definition: Stream.cpp:159
unsigned long millis(void)
Definition: wiring.c:65
String readString()
Definition: Stream.cpp:232
virtual int read()=0
GLenum target
int findMulti(struct MultiTarget *targets, int tCount)
Definition: Stream.cpp:256
LookaheadMode
Definition: Stream.h:41
GLuint index
void setTimeout(unsigned long timeout)
Definition: Stream.cpp:87
size_t readBytes(char *buffer, size_t length)
Definition: Stream.cpp:202
String readStringUntil(char terminator)
Definition: Stream.cpp:244
int timedPeek()
Definition: Stream.cpp:43
GLuint GLuint GLsizei count
virtual int peek()=0


arduino_daq
Author(s):
autogenerated on Mon Jun 10 2019 12:46:03