Skip to content

Commit

Permalink
Merge pull request esp8266#2814 from facchinm/test_pr2696
Browse files Browse the repository at this point in the history
Fix findUntil in Stream library
  • Loading branch information
facchinm committed Mar 24, 2015
2 parents 948bf20 + f43a7a6 commit c25dc61
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 60 deletions.
102 changes: 72 additions & 30 deletions hardware/arduino/avr/cores/arduino/Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/

#include "Arduino.h"
Expand Down Expand Up @@ -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
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
Expand All @@ -96,32 +98,13 @@ bool Stream::findUntil(char *target, char *terminator)
// 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)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
int c;

if( *target == 0)
return true; // return true if target is a null string
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;
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0 ? true : false;
} else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0 ? true : false;
}
return false;
}


Expand All @@ -137,7 +120,7 @@ long Stream::parseInt()
// this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar)
{
boolean isNegative = false;
bool isNegative = false;
long value = 0;
int c;

Expand Down Expand Up @@ -173,10 +156,10 @@ float Stream::parseFloat()
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float Stream::parseFloat(char skipChar){
boolean isNegative = false;
boolean isFraction = false;
bool isNegative = false;
bool isFraction = false;
long value = 0;
int c;
char c;
float fraction = 1.0;

c = peekNextDigit();
Expand Down Expand Up @@ -268,3 +251,62 @@ String Stream::readStringUntil(char terminator)
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;
}
14 changes: 14 additions & 0 deletions hardware/arduino/avr/cores/arduino/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ class Stream : public Print
// this allows format characters (typically commas) in values to be 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
102 changes: 72 additions & 30 deletions hardware/arduino/sam/cores/arduino/Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/

#include "Arduino.h"
Expand Down Expand Up @@ -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
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
Expand All @@ -96,32 +98,13 @@ bool Stream::findUntil(char *target, char *terminator)
// 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)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
int c;

if( *target == 0)
return true; // return true if target is a null string
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;
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0 ? true : false;
} else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0 ? true : false;
}
return false;
}


Expand All @@ -137,7 +120,7 @@ long Stream::parseInt()
// this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar)
{
boolean isNegative = false;
bool isNegative = false;
long value = 0;
int c;

Expand Down Expand Up @@ -173,10 +156,10 @@ float Stream::parseFloat()
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float Stream::parseFloat(char skipChar){
boolean isNegative = false;
boolean isFraction = false;
bool isNegative = false;
bool isFraction = false;
long value = 0;
int c;
char c;
float fraction = 1.0;

c = peekNextDigit();
Expand Down Expand Up @@ -268,3 +251,62 @@ String Stream::readStringUntil(char terminator)
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;
}
13 changes: 13 additions & 0 deletions hardware/arduino/sam/cores/arduino/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ class Stream : public Print
// this allows format characters (typically commas) in values to be 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

0 comments on commit c25dc61

Please sign in to comment.