Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/wifiscanclass_scanDone
Browse files Browse the repository at this point in the history
  • Loading branch information
TD-er authored Sep 13, 2024
2 parents ed52765 + 9e60bbe commit b063e8f
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 211 deletions.
243 changes: 117 additions & 126 deletions cores/esp32/Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/

#include "Arduino.h"
#include "Stream.h"
#include "esp32-hal.h"

#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field

// private method to read stream with timeout
int Stream::timedRead() {
Expand Down Expand Up @@ -55,18 +55,26 @@ int Stream::timedPeek() {

// returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters
int Stream::peekNextDigit() {
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) {
int c;
while (1) {
c = timedPeek();
if (c < 0) {
return c; // timeout
}
if (c == '-') {

if (c < 0 || c == '-' || (c >= '0' && c <= '9') || (detectDecimal && c == '.')) {
return c;
}
if (c >= '0' && c <= '9') {
return c;

switch (lookahead) {
case SKIP_NONE: return -1; // Fail code.
case SKIP_WHITESPACE:
switch (c) {
case ' ':
case '\t':
case '\r':
case '\n': break;
default: return -1; // Fail code.
}
case SKIP_ALL: break;
}
read(); // discard non-numeric
}
Expand All @@ -79,9 +87,6 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
{
_timeout = timeout;
}
unsigned long Stream::getTimeout(void) {
return _timeout;
}

// find returns true if the target string is found
bool Stream::find(const char *target) {
Expand All @@ -105,115 +110,40 @@ bool Stream::findUntil(const char *target, const char *terminator) {
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) {
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0 ? true : false;
return findMulti(t, 1) == 0;
} else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0 ? true : false;
return findMulti(t, 2) == 0;
}
}

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.
long Stream::parseInt() {
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
}

// as above but a given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar) {
boolean isNegative = false;
// lookahead determines how parseInt looks ahead in the stream.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
long Stream::parseInt(LookaheadMode lookahead, char ignore) {
bool isNegative = false;
long value = 0;
int c;

c = peekNextDigit();
c = peekNextDigit(lookahead, false);
// ignore non numeric leading characters
if (c < 0) {
return 0; // zero returned if timeout
}

do {
if (c == skipChar) {
} // ignore this character
if ((char)c == ignore)
; // ignore this character
else if (c == '-') {
isNegative = true;
} else if (c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
}
read(); // consume the character we got with peek
c = timedPeek();
} while ((c >= '0' && c <= '9') || c == skipChar);
} while ((c >= '0' && c <= '9') || (char)c == ignore);

if (isNegative) {
value = -value;
Expand All @@ -222,50 +152,43 @@ long Stream::parseInt(char skipChar) {
}

// as parseInt but returns a floating point value
float Stream::parseFloat() {
return parseFloat(NO_SKIP_CHAR);
}

// 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;
long value = 0;
float Stream::parseFloat(LookaheadMode lookahead, char ignore) {
bool isNegative = false;
bool isFraction = false;
double value = 0.0;
int c;
float fraction = 1.0;
double fraction = 1.0;

c = peekNextDigit();
c = peekNextDigit(lookahead, true);
// ignore non numeric leading characters
if (c < 0) {
return 0; // zero returned if timeout
}

do {
if (c == skipChar) {
} // ignore
if ((char)c == ignore)
; // ignore
else if (c == '-') {
isNegative = true;
} else if (c == '.') {
isFraction = true;
} else if (c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
if (isFraction) {
fraction *= 0.1f;
fraction *= 0.1;
value = value + fraction * (c - '0');
} else {
value = value * 10 + c - '0';
}
}
read(); // consume the character we got with peek
c = timedPeek();
} while ((c >= '0' && c <= '9') || c == '.' || c == skipChar);
} while ((c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore);

if (isNegative) {
value = -value;
}
if (isFraction) {
return value * fraction;
} else {
return value;
}

return value;
}

// read characters from stream into buffer
Expand All @@ -291,13 +214,10 @@ size_t Stream::readBytes(char *buffer, size_t length) {
// returns the number of characters placed in the buffer (0 means no valid data found)

size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
if (length < 1) {
return 0;
}
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 || c == terminator) {
if (c < 0 || (char)c == terminator) {
break;
}
*buffer++ = (char)c;
Expand All @@ -319,9 +239,80 @@ String Stream::readString() {
String Stream::readStringUntil(char terminator) {
String ret;
int c = timedRead();
while (c >= 0 && c != terminator) {
while (c >= 0 && (char)c != terminator) {
ret += (char)c;
c = timedRead();
}
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 ((char)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 ((char)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;
}
Loading

0 comments on commit b063e8f

Please sign in to comment.