From b5876f17fef690e93b1730f25e2aa6ccb77981c4 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 11 Sep 2024 11:20:02 +0300 Subject: [PATCH 1/3] fix(api): Update Arduino Stream class Upstream code contains some fixes --- cores/esp32/Stream.cpp | 344 ++++++++++++++++++++--------------------- cores/esp32/Stream.h | 170 ++++++++++---------- 2 files changed, 253 insertions(+), 261 deletions(-) diff --git a/cores/esp32/Stream.cpp b/cores/esp32/Stream.cpp index 1eb8e512a32..95b2ca3aadf 100644 --- a/cores/esp32/Stream.cpp +++ b/cores/esp32/Stream.cpp @@ -18,55 +18,64 @@ 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() { +int Stream::timedRead() +{ int c; _startMillis = millis(); do { c = read(); - if (c >= 0) { - return c; - } - } while (millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // private method to peek stream with timeout -int Stream::timedPeek() { +int Stream::timedPeek() +{ int c; _startMillis = millis(); do { c = peek(); - if (c >= 0) { - return c; - } - } while (millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // 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 == '-') { - return c; - } - if (c >= '0' && c <= '9') { - return c; + + if( c < 0 || + c == '-' || + (c >= '0' && c <= '9') || + (detectDecimal && c == '.')) 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 } @@ -79,193 +88,111 @@ 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) { + // 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(const 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(const char *target, const char *terminator) { +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) { +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 - } + if(c < 0) + return 0; // zero returned if timeout - do { - if (c == skipChar) { - } // ignore this character - else if (c == '-') { + do{ + if((char)c == ignore) + ; // ignore this character + else if(c == '-') isNegative = true; - } else if (c >= '0' && c <= '9') { // is c a digit? + 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) { + if(isNegative) value = -value; - } return value; } // 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(); - // ignore non numeric leading characters - if (c < 0) { - return 0; // zero returned if timeout - } + c = peekNextDigit(lookahead, true); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout - do { - if (c == skipChar) { - } // ignore - else if (c == '-') { + do{ + if((char)c == ignore) + ; // ignore + else if(c == '-') isNegative = true; - } else if (c == '.') { + 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; + else if(c >= '0' && c <= '9') { // is c a digit? + if(isFraction) { + 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) { + if(isNegative) value = -value; - } - if (isFraction) { - return value * fraction; - } else { - return value; - } + + return value; } // read characters from stream into buffer @@ -273,55 +200,120 @@ float Stream::parseFloat(char skipChar) { // returns the number of characters placed in the buffer // the buffer is NOT null terminated. // -size_t Stream::readBytes(char *buffer, size_t length) { +size_t Stream::readBytes(char *buffer, size_t length) +{ size_t count = 0; while (count < length) { int c = timedRead(); - if (c < 0) { - break; - } + if (c < 0) break; *buffer++ = (char)c; count++; } return count; } + // as readBytes with terminator character // terminates if length characters have been read, timeout, or if the terminator character detected // 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 Stream::readBytesUntil(char terminator, char *buffer, size_t length) +{ size_t index = 0; while (index < length) { int c = timedRead(); - if (c < 0 || c == terminator) { - break; - } + if (c < 0 || (char)c == terminator) break; *buffer++ = (char)c; index++; } - return index; // return number of characters, not including null terminator + return index; // return number of characters, not including null terminator } -String Stream::readString() { +String Stream::readString() +{ String ret; int c = timedRead(); - while (c >= 0) { + while (c >= 0) + { ret += (char)c; c = timedRead(); } return ret; } -String Stream::readStringUntil(char terminator) { +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; +} diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index 5a83747a55f..0e5bef70624 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -1,119 +1,117 @@ /* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. + Stream.h - base class for character-based streams. + Copyright (c) 2010 David A. Mellis. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - parsing functions based on TextFinder library by Michael Margolis - */ + parsing functions based on TextFinder library by Michael Margolis +*/ -#ifndef Stream_h -#define Stream_h +#pragma once #include #include "Print.h" // compatibility macros for testing /* - #define getInt() parseInt() - #define getInt(skipChar) parseInt(skipchar) - #define getFloat() parseFloat() - #define getFloat(skipChar) parseFloat(skipChar) - #define getString( pre_string, post_string, buffer, length) - readBytesBetween( pre_string, terminator, buffer, length) - */ - -class Stream : public Print { -protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout - -public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - - Stream() : _startMillis(0) { - _timeout = 1000; - } - virtual ~Stream() {} - - // parsing methods +#define getInt() parseInt() +#define getInt(ignore) parseInt(ignore) +#define getFloat() parseFloat() +#define getFloat(ignore) parseFloat(ignore) +#define getString( pre_string, post_string, buffer, length) +readBytesBetween( pre_string, terminator, buffer, length) +*/ + +// This enumeration provides the lookahead options for parseInt(), parseFloat() +// The rules set out here are used until either the first valid character is found +// or a time out occurs due to lack of input. +enum LookaheadMode{ + SKIP_ALL, // All invalid characters are ignored. + SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. + SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. +}; - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - unsigned long getTimeout(void); +#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field + +class Stream : public Print +{ + protected: + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout + + public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; + + Stream() {_timeout=1000;} - bool find(const char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) { - return find((char *)target); - } +// parsing methods + + void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + unsigned long getTimeout(void) { return _timeout; } + + bool find(const char *target); // reads data from the stream until the target string is found + bool find(const uint8_t *target) { return find ((const char *)target); } // returns true if target string is found, false if timed out (see setTimeout) - bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(const uint8_t *target, size_t length) { - return find((char *)target, length); - } + bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); } // returns true if target string is found, false if timed out - bool find(char target) { - return find(&target, 1); - } + bool find(char target) { return find (&target, 1); } - bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found - bool findUntil(const uint8_t *target, const char *terminator) { - return findUntil((char *)target, terminator); - } + bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found + bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); } - bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { - return findUntil((char *)target, targetLen, terminate, termLen); - } + bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const 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. + long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); + // returns the first valid (long) integer value from the current position. + // 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. - float parseFloat(); // float version of parseInt + float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); + // float version of parseInt - virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer - virtual size_t readBytes(uint8_t *buffer, size_t length) { - return readBytes((char *)buffer, length); - } + size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer + size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } // terminates if length characters have been read or timeout (see setTimeout) // returns the number of characters placed in the buffer (0 means no valid data found) - size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character - size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { - return readBytesUntil(terminator, (char *)buffer, length); - } + size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character + size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) // Arduino String functions to be added here - virtual String readString(); + String readString(); String readStringUntil(char terminator); -protected: - long parseInt(char skipChar); // 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 - - float parseFloat(char skipChar); // as above but the given skipChar is ignored + protected: + long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } + float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } + // These overload exists for compatibility with any class that has derived + // Stream and used parseFloat/Int with a custom ignore character. To keep + // the public API simple, these overload remains protected. struct MultiTarget { const char *str; // string you're searching for @@ -126,4 +124,6 @@ class Stream : public Print { int findMulti(struct MultiTarget *targets, int tCount); }; -#endif +#undef NO_IGNORE_CHAR + +using arduino::Stream; \ No newline at end of file From 3ff0b25ae9489e51eca975167a8f50e9b098e8e4 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 11 Sep 2024 11:23:03 +0300 Subject: [PATCH 2/3] Update Stream.h --- cores/esp32/Stream.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index 0e5bef70624..4c0e0dee886 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -125,5 +125,3 @@ class Stream : public Print }; #undef NO_IGNORE_CHAR - -using arduino::Stream; \ No newline at end of file From c53e63c9eb9bd7bfbd13ed5a9eec37443966ec7e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:04:33 +0000 Subject: [PATCH 3/3] ci(pre-commit): Apply automatic fixes --- cores/esp32/Stream.cpp | 183 ++++++++++++++++++++--------------------- cores/esp32/Stream.h | 95 ++++++++++++--------- 2 files changed, 149 insertions(+), 129 deletions(-) diff --git a/cores/esp32/Stream.cpp b/cores/esp32/Stream.cpp index 95b2ca3aadf..5c2060eaa35 100644 --- a/cores/esp32/Stream.cpp +++ b/cores/esp32/Stream.cpp @@ -28,54 +28,53 @@ #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait // private method to read stream with timeout -int Stream::timedRead() -{ +int Stream::timedRead() { int c; _startMillis = millis(); do { c = read(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout + if (c >= 0) { + return c; + } + } while (millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // private method to peek stream with timeout -int Stream::timedPeek() -{ +int Stream::timedPeek() { int c; _startMillis = millis(); do { c = peek(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout + if (c >= 0) { + return c; + } + } while (millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // returns peek of the next digit in the stream or -1 if timeout // discards non-numeric characters -int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) -{ +int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) { int c; while (1) { c = timedPeek(); - if( c < 0 || - c == '-' || - (c >= '0' && c <= '9') || - (detectDecimal && c == '.')) 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; + if (c < 0 || c == '-' || (c >= '0' && c <= '9') || (detectDecimal && c == '.')) { + 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 } @@ -89,30 +88,26 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi _timeout = timeout; } - // find returns true if the target string is found -bool Stream::find(const 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(const 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(const char *target, const char *terminator) -{ +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) -{ +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; @@ -127,37 +122,37 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina // 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) -{ +long Stream::parseInt(LookaheadMode lookahead, char ignore) { bool isNegative = false; long value = 0; int c; c = peekNextDigit(lookahead, false); // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout + if (c < 0) { + return 0; // zero returned if timeout + } - do{ - if((char)c == ignore) - ; // ignore this character - else if(c == '-') + do { + if ((char)c == ignore) + ; // ignore this character + else if (c == '-') { isNegative = true; - else if(c >= '0' && c <= '9') // is c a digit? + } 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') || (char)c == ignore ); + } while ((c >= '0' && c <= '9') || (char)c == ignore); - if(isNegative) + if (isNegative) { value = -value; + } return value; } // as parseInt but returns a floating point value -float Stream::parseFloat(LookaheadMode lookahead, char ignore) -{ +float Stream::parseFloat(LookaheadMode lookahead, char ignore) { bool isNegative = false; bool isFraction = false; double value = 0.0; @@ -165,19 +160,20 @@ float Stream::parseFloat(LookaheadMode lookahead, char ignore) double fraction = 1.0; c = peekNextDigit(lookahead, true); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if((char)c == ignore) - ; // ignore - else if(c == '-') + // ignore non numeric leading characters + if (c < 0) { + return 0; // zero returned if timeout + } + + do { + if ((char)c == ignore) + ; // ignore + else if (c == '-') { isNegative = true; - else if (c == '.') + } else if (c == '.') { isFraction = true; - else if(c >= '0' && c <= '9') { // is c a digit? - if(isFraction) { + } else if (c >= '0' && c <= '9') { // is c a digit? + if (isFraction) { fraction *= 0.1; value = value + fraction * (c - '0'); } else { @@ -186,11 +182,11 @@ float Stream::parseFloat(LookaheadMode lookahead, char ignore) } read(); // consume the character we got with peek c = timedPeek(); - } - while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore ); + } while ((c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore); - if(isNegative) + if (isNegative) { value = -value; + } return value; } @@ -200,94 +196,96 @@ float Stream::parseFloat(LookaheadMode lookahead, char ignore) // returns the number of characters placed in the buffer // the buffer is NOT null terminated. // -size_t Stream::readBytes(char *buffer, size_t length) -{ +size_t Stream::readBytes(char *buffer, size_t length) { size_t count = 0; while (count < length) { int c = timedRead(); - if (c < 0) break; + if (c < 0) { + break; + } *buffer++ = (char)c; count++; } return count; } - // as readBytes with terminator character // terminates if length characters have been read, timeout, or if the terminator character detected // 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) -{ +size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { size_t index = 0; while (index < length) { int c = timedRead(); - if (c < 0 || (char)c == terminator) break; + if (c < 0 || (char)c == terminator) { + break; + } *buffer++ = (char)c; index++; } - return index; // return number of characters, not including null terminator + return index; // return number of characters, not including null terminator } -String Stream::readString() -{ +String Stream::readString() { String ret; int c = timedRead(); - while (c >= 0) - { + while (c >= 0) { ret += (char)c; c = timedRead(); } return ret; } -String Stream::readStringUntil(char terminator) -{ +String Stream::readStringUntil(char terminator) { String ret; int c = timedRead(); - while (c >= 0 && (char)c != terminator) - { + while (c >= 0 && (char)c != terminator) { ret += (char)c; c = timedRead(); } return ret; } -int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { +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) + for (struct MultiTarget *t = targets; t < targets + tCount; ++t) { + if (t->len <= 0) { return t - targets; + } } while (1) { int c = timedRead(); - if (c < 0) + if (c < 0) { return -1; + } - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + 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) + if (++t->index == t->len) { return t - targets; - else + } 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) + 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]) + 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) { @@ -299,8 +297,9 @@ int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { int diff = origIndex - t->index; size_t i; for (i = 0; i < t->index; ++i) { - if (t->str[i] != t->str[i + diff]) + if (t->str[i] != t->str[i + diff]) { break; + } } // if we successfully got through the previous loop then our current diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index 4c0e0dee886..123694f6fc6 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -37,50 +37,63 @@ readBytesBetween( pre_string, terminator, buffer, length) // This enumeration provides the lookahead options for parseInt(), parseFloat() // The rules set out here are used until either the first valid character is found // or a time out occurs due to lack of input. -enum LookaheadMode{ - SKIP_ALL, // All invalid characters are ignored. - SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. - SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. +enum LookaheadMode { + SKIP_ALL, // All invalid characters are ignored. + SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. + SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. }; -#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field +#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field -class Stream : public Print -{ - protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout +class Stream : public Print { +protected: + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout - public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; +public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; - Stream() {_timeout=1000;} + Stream() { + _timeout = 1000; + } -// parsing methods + // parsing methods void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - unsigned long getTimeout(void) { return _timeout; } - - bool find(const char *target); // reads data from the stream until the target string is found - bool find(const uint8_t *target) { return find ((const char *)target); } + unsigned long getTimeout(void) { + return _timeout; + } + + bool find(const char *target); // reads data from the stream until the target string is found + bool find(const uint8_t *target) { + return find((const char *)target); + } // returns true if target string is found, false if timed out (see setTimeout) - bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); } + bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(const uint8_t *target, size_t length) { + return find((const char *)target, length); + } // returns true if target string is found, false if timed out - bool find(char target) { return find (&target, 1); } + bool find(char target) { + return find(&target, 1); + } - bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found - bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); } + bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found + bool findUntil(const uint8_t *target, const char *terminator) { + return findUntil((const char *)target, terminator); + } - bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); } + bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { + return findUntil((const char *)target, targetLen, terminate, termLen); + } long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); // returns the first valid (long) integer value from the current position. @@ -92,13 +105,17 @@ class Stream : public Print float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); // float version of parseInt - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } + size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer + size_t readBytes(uint8_t *buffer, size_t length) { + return readBytes((char *)buffer, length); + } // terminates if length characters have been read or timeout (see setTimeout) // returns the number of characters placed in the buffer (0 means no valid data found) - size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character - size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } + size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character + size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { + return readBytesUntil(terminator, (char *)buffer, length); + } // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) @@ -106,9 +123,13 @@ class Stream : public Print String readString(); String readStringUntil(char terminator); - protected: - long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } - float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } +protected: + long parseInt(char ignore) { + return parseInt(SKIP_ALL, ignore); + } + float parseFloat(char ignore) { + return parseFloat(SKIP_ALL, ignore); + } // These overload exists for compatibility with any class that has derived // Stream and used parseFloat/Int with a custom ignore character. To keep // the public API simple, these overload remains protected.