From fac395b062366059d0452afd4a2d139f08699006 Mon Sep 17 00:00:00 2001 From: Alexandre Trevizoli Date: Fri, 1 Nov 2019 18:47:41 -0300 Subject: [PATCH 1/3] 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'); --- cores/esp32/Stream.cpp | 110 ++++++++++++++++++++++++++++++++++++++++- cores/esp32/Stream.h | 31 +++++++++++- 2 files changed, 139 insertions(+), 2 deletions(-) diff --git a/cores/esp32/Stream.cpp b/cores/esp32/Stream.cpp index 5c090791968..5727ff6f896 100644 --- a/cores/esp32/Stream.cpp +++ b/cores/esp32/Stream.cpp @@ -85,7 +85,7 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi unsigned long Stream::getTimeout(void) { return _timeout; } - +/* // find returns true if the target string is found bool Stream::find(const char *target) { @@ -141,6 +141,114 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina return false; } +*/ + +// ******************** ALEXANDRE + + // find returns true if the target string is found +bool Stream::find(char *target) +{ + return findUntil(target, strlen(target), NULL, 0); +} + +// reads data from the stream until the target string of given length is found +// returns true if target string is found, false if timed out +bool Stream::find(char *target, size_t length) +{ + return findUntil(target, length, NULL, 0); +} + +// as find but search ends if the terminator string is found +bool Stream::findUntil(char *target, char *terminator) +{ + return findUntil(target, strlen(target), terminator, strlen(terminator)); +} + +// reads data from the stream until the target string of the given length is found +// search terminated if the terminator string is found +// 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) +{ + 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; + } +} + +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; + size_t 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; +} + + + +// ********************************** + + + // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // function is terminated by the first character that is not a digit. diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index 4ce31955acd..e9d3b525ebf 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -60,6 +60,24 @@ class Stream: public Print void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second unsigned long getTimeout(void); + + bool find(char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) { return find ((char *)target); } + // returns true if target string is found, false if timed out (see setTimeout) + + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + // returns true if target string is found, false if timed out + + bool find(char target) { return find (&target, 1); } + + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } + +/* bool find(const char *target); // reads data from the stream until the target string is found bool find(uint8_t *target) { @@ -90,7 +108,7 @@ class Stream: public Print { return findUntil((char *) target, targetLen, terminate, termLen); } - +*/ long parseInt(); // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // integer is terminated by the first character that is not a digit. @@ -123,6 +141,17 @@ 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 + + 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 From 07364a04a4122c230321d77a3add874d92b0111b Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 14 Oct 2020 14:47:19 +0300 Subject: [PATCH 2/3] Update Stream.h --- cores/esp32/Stream.h | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index e9d3b525ebf..2debee7e4f9 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -60,24 +60,7 @@ class Stream: public Print void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second unsigned long getTimeout(void); - - bool find(char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) { return find ((char *)target); } - // returns true if target string is found, false if timed out (see setTimeout) - - bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } - // returns true if target string is found, false if timed out - - bool find(char target) { return find (&target, 1); } - - bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found - bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } - - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } - -/* + bool find(const char *target); // reads data from the stream until the target string is found bool find(uint8_t *target) { @@ -108,7 +91,7 @@ class Stream: public Print { return findUntil((char *) target, targetLen, terminate, termLen); } -*/ + long parseInt(); // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // integer is terminated by the first character that is not a digit. From f13518f0a1f4ee7ac5eb7c962f05c3aae3592115 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 14 Oct 2020 14:49:36 +0300 Subject: [PATCH 3/3] Update Stream.cpp --- cores/esp32/Stream.cpp | 75 +++--------------------------------------- 1 file changed, 5 insertions(+), 70 deletions(-) diff --git a/cores/esp32/Stream.cpp b/cores/esp32/Stream.cpp index 5727ff6f896..7d1649a6fb5 100644 --- a/cores/esp32/Stream.cpp +++ b/cores/esp32/Stream.cpp @@ -85,81 +85,22 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi unsigned long Stream::getTimeout(void) { return _timeout; } -/* -// find returns true if the target string is found -bool Stream::find(const char *target) -{ - return findUntil(target, (char*) ""); -} - -// reads data from the stream until the target string of given length is found -// returns true if target string is found, false if timed out -bool Stream::find(const char *target, size_t length) -{ - return findUntil(target, length, NULL, 0); -} - -// as find but search ends if the terminator string is found -bool Stream::findUntil(const char *target, const char *terminator) -{ - return findUntil(target, strlen(target), terminator, strlen(terminator)); -} -// reads data from the stream until the target string of the given length is found -// search terminated if the terminator string is found -// returns true if target string is found, false if terminated or timed out -bool Stream::findUntil(const char *target, size_t targetLen, const 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; - } - } - return false; -} - -*/ - -// ******************** ALEXANDRE - - // find returns true if the target string is found -bool Stream::find(char *target) +// find returns true if the target string is found +bool Stream::find(const char *target) { return findUntil(target, strlen(target), NULL, 0); } // reads data from the stream until the target string of given length is found // returns true if target string is found, false if timed out -bool Stream::find(char *target, size_t length) +bool Stream::find(const char *target, size_t length) { return findUntil(target, length, NULL, 0); } // as find but search ends if the terminator string is found -bool Stream::findUntil(char *target, char *terminator) +bool Stream::findUntil(const char *target, const char *terminator) { return findUntil(target, strlen(target), terminator, strlen(terminator)); } @@ -167,7 +108,7 @@ bool Stream::findUntil(char *target, char *terminator) // reads data from the stream until the target string of the given length is found // search terminated if the terminator string is found // 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(const char *target, size_t targetLen, const char *terminator, size_t termLen) { if (terminator == NULL) { MultiTarget t[1] = {{target, targetLen, 0}}; @@ -243,12 +184,6 @@ int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { return -1; } - - -// ********************************** - - - // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // function is terminated by the first character that is not a digit.