mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-21 15:54:39 +01:00
Merge pull request #2814 from facchinm/test_pr2696
Fix findUntil in Stream library
This commit is contained in:
commit
c25dc61bd6
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
Created July 2011
|
Created July 2011
|
||||||
parsing functions based on TextFinder library by Michael Margolis
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
|
||||||
|
findMulti/findUntil routines written by Jim Leonard/Xuth
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
@ -75,7 +77,7 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
|
|||||||
// find returns true if the target string is found
|
// find returns true if the target string is found
|
||||||
bool Stream::find(char *target)
|
bool Stream::find(char *target)
|
||||||
{
|
{
|
||||||
return findUntil(target, (char*)"");
|
return findUntil(target, strlen(target), NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads data from the stream until the target string of given length is found
|
// 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)
|
|||||||
// returns true if target string is found, false if terminated or timed out
|
// returns true if target string is found, false if terminated or timed out
|
||||||
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||||
{
|
{
|
||||||
size_t index = 0; // maximum target string length is 64k bytes!
|
if (terminator == NULL) {
|
||||||
size_t termIndex = 0;
|
MultiTarget t[1] = {{target, targetLen, 0}};
|
||||||
int c;
|
return findMulti(t, 1) == 0 ? true : false;
|
||||||
|
} else {
|
||||||
if( *target == 0)
|
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||||
return true; // return true if target is a null string
|
return findMulti(t, 2) == 0 ? true : false;
|
||||||
while( (c = timedRead()) > 0){
|
|
||||||
|
|
||||||
if(c != target[index])
|
|
||||||
index = 0; // reset index if any char does not match
|
|
||||||
|
|
||||||
if( c == target[index]){
|
|
||||||
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
|
||||||
if(++index >= targetLen){ // return true if all chars in the target match
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(termLen > 0 && c == terminator[termIndex]){
|
|
||||||
if(++termIndex >= termLen)
|
|
||||||
return false; // return false if terminate string found before target string
|
|
||||||
}
|
|
||||||
else
|
|
||||||
termIndex = 0;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -137,7 +120,7 @@ long Stream::parseInt()
|
|||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
long Stream::parseInt(char skipChar)
|
long Stream::parseInt(char skipChar)
|
||||||
{
|
{
|
||||||
boolean isNegative = false;
|
bool isNegative = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@ -173,10 +156,10 @@ float Stream::parseFloat()
|
|||||||
// as above but the given skipChar is ignored
|
// as above but the given skipChar is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
float Stream::parseFloat(char skipChar){
|
float Stream::parseFloat(char skipChar){
|
||||||
boolean isNegative = false;
|
bool isNegative = false;
|
||||||
boolean isFraction = false;
|
bool isFraction = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int c;
|
char c;
|
||||||
float fraction = 1.0;
|
float fraction = 1.0;
|
||||||
|
|
||||||
c = peekNextDigit();
|
c = peekNextDigit();
|
||||||
@ -268,3 +251,62 @@ String Stream::readStringUntil(char terminator)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||||
|
// any zero length target string automatically matches and would make
|
||||||
|
// a mess of the rest of the algorithm.
|
||||||
|
for (struct MultiTarget *t = targets; t < targets+tCount; ++t)
|
||||||
|
if (t->len <= 0)
|
||||||
|
return t - targets;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
int c = timedRead();
|
||||||
|
if (c < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||||
|
// the simple case is if we match, deal with that first.
|
||||||
|
if (c == t->str[t->index])
|
||||||
|
if (++t->index == t->len)
|
||||||
|
return t - targets;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if not we need to walk back and see if we could have matched further
|
||||||
|
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||||
|
// but it will match the second position so we can't just reset the current
|
||||||
|
// index to 0 when we find a mismatch.
|
||||||
|
if (t->index == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int origIndex = t->index;
|
||||||
|
do {
|
||||||
|
--t->index;
|
||||||
|
// first check if current char works against the new current index
|
||||||
|
if (c != t->str[t->index])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if it's the only char then we're good, nothing more to check
|
||||||
|
if (t->index == 0) {
|
||||||
|
t->index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise we need to check the rest of the found string
|
||||||
|
int diff = origIndex - t->index;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < t->index; ++i)
|
||||||
|
if (t->str[i] != t->str[i + diff])
|
||||||
|
break;
|
||||||
|
// if we successfully got through the previous loop then our current
|
||||||
|
// index is good.
|
||||||
|
if (i == t->index) {
|
||||||
|
t->index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// otherwise we just try the next index
|
||||||
|
} while (t->index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// unreachable
|
||||||
|
return -1;
|
||||||
|
}
|
@ -97,6 +97,20 @@ class Stream : public Print
|
|||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
|
||||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct MultiTarget {
|
||||||
|
const char *str; // string you're searching for
|
||||||
|
size_t len; // length of string you're searching for
|
||||||
|
size_t index; // index used by the search routine.
|
||||||
|
};
|
||||||
|
|
||||||
|
// This allows you to search for an arbitrary number of strings.
|
||||||
|
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||||
|
int findMulti(struct MultiTarget *targets, int tCount);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
Created July 2011
|
Created July 2011
|
||||||
parsing functions based on TextFinder library by Michael Margolis
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
|
||||||
|
findMulti/findUntil routines written by Jim Leonard/Xuth
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
@ -75,7 +77,7 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
|
|||||||
// find returns true if the target string is found
|
// find returns true if the target string is found
|
||||||
bool Stream::find(char *target)
|
bool Stream::find(char *target)
|
||||||
{
|
{
|
||||||
return findUntil(target, (char*)"");
|
return findUntil(target, strlen(target), NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads data from the stream until the target string of given length is found
|
// 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)
|
|||||||
// returns true if target string is found, false if terminated or timed out
|
// returns true if target string is found, false if terminated or timed out
|
||||||
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||||
{
|
{
|
||||||
size_t index = 0; // maximum target string length is 64k bytes!
|
if (terminator == NULL) {
|
||||||
size_t termIndex = 0;
|
MultiTarget t[1] = {{target, targetLen, 0}};
|
||||||
int c;
|
return findMulti(t, 1) == 0 ? true : false;
|
||||||
|
} else {
|
||||||
if( *target == 0)
|
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||||
return true; // return true if target is a null string
|
return findMulti(t, 2) == 0 ? true : false;
|
||||||
while( (c = timedRead()) > 0){
|
|
||||||
|
|
||||||
if(c != target[index])
|
|
||||||
index = 0; // reset index if any char does not match
|
|
||||||
|
|
||||||
if( c == target[index]){
|
|
||||||
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
|
||||||
if(++index >= targetLen){ // return true if all chars in the target match
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(termLen > 0 && c == terminator[termIndex]){
|
|
||||||
if(++termIndex >= termLen)
|
|
||||||
return false; // return false if terminate string found before target string
|
|
||||||
}
|
|
||||||
else
|
|
||||||
termIndex = 0;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -137,7 +120,7 @@ long Stream::parseInt()
|
|||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
long Stream::parseInt(char skipChar)
|
long Stream::parseInt(char skipChar)
|
||||||
{
|
{
|
||||||
boolean isNegative = false;
|
bool isNegative = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@ -173,10 +156,10 @@ float Stream::parseFloat()
|
|||||||
// as above but the given skipChar is ignored
|
// as above but the given skipChar is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
float Stream::parseFloat(char skipChar){
|
float Stream::parseFloat(char skipChar){
|
||||||
boolean isNegative = false;
|
bool isNegative = false;
|
||||||
boolean isFraction = false;
|
bool isFraction = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int c;
|
char c;
|
||||||
float fraction = 1.0;
|
float fraction = 1.0;
|
||||||
|
|
||||||
c = peekNextDigit();
|
c = peekNextDigit();
|
||||||
@ -268,3 +251,62 @@ String Stream::readStringUntil(char terminator)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||||
|
// any zero length target string automatically matches and would make
|
||||||
|
// a mess of the rest of the algorithm.
|
||||||
|
for (struct MultiTarget *t = targets; t < targets+tCount; ++t)
|
||||||
|
if (t->len <= 0)
|
||||||
|
return t - targets;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
int c = timedRead();
|
||||||
|
if (c < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||||
|
// the simple case is if we match, deal with that first.
|
||||||
|
if (c == t->str[t->index])
|
||||||
|
if (++t->index == t->len)
|
||||||
|
return t - targets;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if not we need to walk back and see if we could have matched further
|
||||||
|
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||||
|
// but it will match the second position so we can't just reset the current
|
||||||
|
// index to 0 when we find a mismatch.
|
||||||
|
if (t->index == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int origIndex = t->index;
|
||||||
|
do {
|
||||||
|
--t->index;
|
||||||
|
// first check if current char works against the new current index
|
||||||
|
if (c != t->str[t->index])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if it's the only char then we're good, nothing more to check
|
||||||
|
if (t->index == 0) {
|
||||||
|
t->index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise we need to check the rest of the found string
|
||||||
|
int diff = origIndex - t->index;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < t->index; ++i)
|
||||||
|
if (t->str[i] != t->str[i + diff])
|
||||||
|
break;
|
||||||
|
// if we successfully got through the previous loop then our current
|
||||||
|
// index is good.
|
||||||
|
if (i == t->index) {
|
||||||
|
t->index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// otherwise we just try the next index
|
||||||
|
} while (t->index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// unreachable
|
||||||
|
return -1;
|
||||||
|
}
|
@ -97,6 +97,19 @@ class Stream : public Print
|
|||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
|
||||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct MultiTarget {
|
||||||
|
const char *str; // string you're searching for
|
||||||
|
size_t len; // length of string you're searching for
|
||||||
|
size_t index; // index used by the search routine.
|
||||||
|
};
|
||||||
|
|
||||||
|
// This allows you to search for an arbitrary number of strings.
|
||||||
|
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||||
|
int findMulti(struct MultiTarget *targets, int tCount);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user