18
18
19
19
Created July 2011
20
20
parsing functions based on TextFinder library by Michael Margolis
21
+
22
+ findMulti/findUntil routines written by Jim Leonard/Xuth
21
23
*/
22
24
23
25
#include " Arduino.h"
@@ -75,7 +77,7 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
75
77
// find returns true if the target string is found
76
78
bool Stream::find (char *target)
77
79
{
78
- return findUntil (target, ( char *) " " );
80
+ return findUntil (target, strlen (target), NULL , 0 );
79
81
}
80
82
81
83
// reads data from the stream until the target string of given length is found
@@ -96,32 +98,13 @@ bool Stream::findUntil(char *target, char *terminator)
96
98
// returns true if target string is found, false if terminated or timed out
97
99
bool Stream::findUntil (char *target, size_t targetLen, char *terminator, size_t termLen)
98
100
{
99
- size_t index = 0 ; // maximum target string length is 64k bytes!
100
- size_t termIndex = 0 ;
101
- int c;
102
-
103
- if ( *target == 0 )
104
- return true ; // return true if target is a null string
105
- while ( (c = timedRead ()) > 0 ){
106
-
107
- if (c != target[index])
108
- index = 0 ; // reset index if any char does not match
109
-
110
- if ( c == target[index]){
111
- // ////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
112
- if (++index >= targetLen){ // return true if all chars in the target match
113
- return true ;
114
- }
115
- }
116
-
117
- if (termLen > 0 && c == terminator[termIndex]){
118
- if (++termIndex >= termLen)
119
- return false ; // return false if terminate string found before target string
120
- }
121
- else
122
- termIndex = 0 ;
101
+ if (terminator == NULL ) {
102
+ MultiTarget t[1 ] = {{target, targetLen, 0 }};
103
+ return findMulti (t, 1 ) == 0 ? true : false ;
104
+ } else {
105
+ MultiTarget t[2 ] = {{target, targetLen, 0 }, {terminator, termLen, 0 }};
106
+ return findMulti (t, 2 ) == 0 ? true : false ;
123
107
}
124
- return false ;
125
108
}
126
109
127
110
@@ -137,7 +120,7 @@ long Stream::parseInt()
137
120
// this allows format characters (typically commas) in values to be ignored
138
121
long Stream::parseInt (char skipChar)
139
122
{
140
- boolean isNegative = false ;
123
+ bool isNegative = false ;
141
124
long value = 0 ;
142
125
int c;
143
126
@@ -173,10 +156,10 @@ float Stream::parseFloat()
173
156
// as above but the given skipChar is ignored
174
157
// this allows format characters (typically commas) in values to be ignored
175
158
float Stream::parseFloat (char skipChar){
176
- boolean isNegative = false ;
177
- boolean isFraction = false ;
159
+ bool isNegative = false ;
160
+ bool isFraction = false ;
178
161
long value = 0 ;
179
- int c;
162
+ char c;
180
163
float fraction = 1.0 ;
181
164
182
165
c = peekNextDigit ();
@@ -268,3 +251,62 @@ String Stream::readStringUntil(char terminator)
268
251
return ret;
269
252
}
270
253
254
+ int Stream::findMulti ( struct Stream ::MultiTarget *targets, int tCount) {
255
+ // any zero length target string automatically matches and would make
256
+ // a mess of the rest of the algorithm.
257
+ for (struct MultiTarget *t = targets; t < targets+tCount; ++t)
258
+ if (t->len <= 0 )
259
+ return t - targets;
260
+
261
+ while (1 ) {
262
+ int c = timedRead ();
263
+ if (c < 0 )
264
+ return -1 ;
265
+
266
+ for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
267
+ // the simple case is if we match, deal with that first.
268
+ if (c == t->str [t->index ])
269
+ if (++t->index == t->len )
270
+ return t - targets;
271
+ else
272
+ continue ;
273
+
274
+ // if not we need to walk back and see if we could have matched further
275
+ // down the stream (ie '1112' doesn't match the first position in '11112'
276
+ // but it will match the second position so we can't just reset the current
277
+ // index to 0 when we find a mismatch.
278
+ if (t->index == 0 )
279
+ continue ;
280
+
281
+ int origIndex = t->index ;
282
+ do {
283
+ --t->index ;
284
+ // first check if current char works against the new current index
285
+ if (c != t->str [t->index ])
286
+ continue ;
287
+
288
+ // if it's the only char then we're good, nothing more to check
289
+ if (t->index == 0 ) {
290
+ t->index ++;
291
+ break ;
292
+ }
293
+
294
+ // otherwise we need to check the rest of the found string
295
+ int diff = origIndex - t->index ;
296
+ int i;
297
+ for (i = 0 ; i < t->index ; ++i)
298
+ if (t->str [i] != t->str [i + diff])
299
+ break ;
300
+ // if we successfully got through the previous loop then our current
301
+ // index is good.
302
+ if (i == t->index ) {
303
+ t->index ++;
304
+ break ;
305
+ }
306
+ // otherwise we just try the next index
307
+ } while (t->index );
308
+ }
309
+ }
310
+ // unreachable
311
+ return -1 ;
312
+ }
0 commit comments