Skip to content

Commit 25bd585

Browse files
Corrections of Stream.Find, FindUntil and added FindMulti - like AVR-Core Libraries (#3442)
* Corrections of Find, FindUntil and FindMulti Find has some bug that is not working with Ethernet.find() so, I copied code from Stream.h and Stream.cpp in AVR-CORE library and now it's working perfectly. I don't know where was the error, but an Ethernet.find compiled to MEGA2560 was working but not working when compiled to esp32, after corrections of code (copy of AVR-Core libraries) it's working perfect. So probably has some error on original ESP32-Core library. Below is part of code that was working with MEGA2560 and not with ESP32 libraries. client.find never return TRUE with ESP32 original library and with AVR it's works. boolean esp32_fw_update(EthernetClient &client, DecodedHeader &header, const String &field_filename, const String &field_crc) { char bound[header.boundary.length()+3]; char term[]="\r\n"; strcpy(bound,header.boundary.c_str()); strcat(bound,term); while (client.find(bound)) { String line=client.readStringUntil('\r'); * Update Stream.h * Update Stream.cpp Co-authored-by: Me No Dev <[email protected]>
1 parent d79a1f3 commit 25bd585

File tree

2 files changed

+81
-26
lines changed

2 files changed

+81
-26
lines changed

Diff for: cores/esp32/Stream.cpp

+69-26
Original file line numberDiff line numberDiff line change
@@ -87,58 +87,101 @@ unsigned long Stream::getTimeout(void) {
8787
}
8888

8989
// find returns true if the target string is found
90-
bool Stream::find(const char *target)
90+
bool Stream::find(const char *target)
9191
{
92-
return findUntil(target, (char*) "");
92+
return findUntil(target, strlen(target), NULL, 0);
9393
}
9494

9595
// reads data from the stream until the target string of given length is found
9696
// returns true if target string is found, false if timed out
9797
bool Stream::find(const char *target, size_t length)
9898
{
99-
return findUntil(target, length, NULL, 0);
99+
return findUntil(target, length, NULL, 0);
100100
}
101101

102102
// as find but search ends if the terminator string is found
103-
bool Stream::findUntil(const char *target, const char *terminator)
103+
bool Stream::findUntil(const char *target, const char *terminator)
104104
{
105-
return findUntil(target, strlen(target), terminator, strlen(terminator));
105+
return findUntil(target, strlen(target), terminator, strlen(terminator));
106106
}
107107

108108
// reads data from the stream until the target string of the given length is found
109109
// search terminated if the terminator string is found
110110
// returns true if target string is found, false if terminated or timed out
111111
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
112112
{
113-
size_t index = 0; // maximum target string length is 64k bytes!
114-
size_t termIndex = 0;
115-
int c;
113+
if (terminator == NULL) {
114+
MultiTarget t[1] = {{target, targetLen, 0}};
115+
return findMulti(t, 1) == 0 ? true : false;
116+
} else {
117+
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
118+
return findMulti(t, 2) == 0 ? true : false;
119+
}
120+
}
116121

117-
if(*target == 0) {
118-
return true; // return true if target is a null string
119-
}
120-
while((c = timedRead()) > 0) {
122+
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
123+
// any zero length target string automatically matches and would make
124+
// a mess of the rest of the algorithm.
125+
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
126+
if (t->len <= 0)
127+
return t - targets;
128+
}
121129

122-
if(c != target[index]) {
123-
index = 0; // reset index if any char does not match
130+
while (1) {
131+
int c = timedRead();
132+
if (c < 0)
133+
return -1;
134+
135+
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
136+
// the simple case is if we match, deal with that first.
137+
if (c == t->str[t->index]) {
138+
if (++t->index == t->len)
139+
return t - targets;
140+
else
141+
continue;
142+
}
143+
144+
// if not we need to walk back and see if we could have matched further
145+
// down the stream (ie '1112' doesn't match the first position in '11112'
146+
// but it will match the second position so we can't just reset the current
147+
// index to 0 when we find a mismatch.
148+
if (t->index == 0)
149+
continue;
150+
151+
int origIndex = t->index;
152+
do {
153+
--t->index;
154+
// first check if current char works against the new current index
155+
if (c != t->str[t->index])
156+
continue;
157+
158+
// if it's the only char then we're good, nothing more to check
159+
if (t->index == 0) {
160+
t->index++;
161+
break;
124162
}
125163

126-
if(c == target[index]) {
127-
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
128-
if(++index >= targetLen) { // return true if all chars in the target match
129-
return true;
130-
}
164+
// otherwise we need to check the rest of the found string
165+
int diff = origIndex - t->index;
166+
size_t i;
167+
for (i = 0; i < t->index; ++i) {
168+
if (t->str[i] != t->str[i + diff])
169+
break;
131170
}
132171

133-
if(termLen > 0 && c == terminator[termIndex]) {
134-
if(++termIndex >= termLen) {
135-
return false; // return false if terminate string found before target string
136-
}
137-
} else {
138-
termIndex = 0;
172+
// if we successfully got through the previous loop then our current
173+
// index is good.
174+
if (i == t->index) {
175+
t->index++;
176+
break;
139177
}
178+
179+
// otherwise we just try the next index
180+
} while (t->index);
140181
}
141-
return false;
182+
}
183+
// unreachable
184+
return -1;
142185
}
143186

144187
// returns the first valid (long) integer value from the current position.

Diff for: cores/esp32/Stream.h

+12
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class Stream: public Print
6060

6161
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
6262
unsigned long getTimeout(void);
63+
6364
bool find(const char *target); // reads data from the stream until the target string is found
6465
bool find(uint8_t *target)
6566
{
@@ -123,6 +124,17 @@ class Stream: public Print
123124
// this allows format characters (typically commas) in values to be ignored
124125

125126
float parseFloat(char skipChar); // as above but the given skipChar is ignored
127+
128+
struct MultiTarget {
129+
const char *str; // string you're searching for
130+
size_t len; // length of string you're searching for
131+
size_t index; // index used by the search routine.
132+
};
133+
134+
// This allows you to search for an arbitrary number of strings.
135+
// Returns index of the target that is found first or -1 if timeout occurs.
136+
int findMulti(struct MultiTarget *targets, int tCount);
137+
126138
};
127139

128140
#endif

0 commit comments

Comments
 (0)