mirror of
https://github.com/arduino/Arduino.git
synced 2024-11-29 10:24:12 +01:00
This adds control of Stream::parseInt/float lookahead.
Its default is SKIP_ALL which reflects previous versions. However SKIP_NONE, and SKIP_WHITESPACE can refine this behaviour. A parameter used in the protected overloads of parseInt/Float has been changed from `skipChar` to `ignore`.
This commit is contained in:
parent
12d0487258
commit
7857216e69
@ -54,7 +54,7 @@ int Stream::timedPeek()
|
|||||||
|
|
||||||
// returns peek of the next digit in the stream or -1 if timeout
|
// returns peek of the next digit in the stream or -1 if timeout
|
||||||
// discards non-numeric characters
|
// discards non-numeric characters
|
||||||
int Stream::peekNextDigit( bool detectDecimal )
|
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -65,6 +65,17 @@ int Stream::peekNextDigit( bool detectDecimal )
|
|||||||
c >= '0' && c <= '9' ||
|
c >= '0' && c <= '9' ||
|
||||||
detectDecimal && c == '.') return c;
|
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.
|
||||||
|
}
|
||||||
|
}
|
||||||
read(); // discard non-numeric
|
read(); // discard non-numeric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,26 +125,26 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t
|
|||||||
// returns the first valid (long) integer value from the current position.
|
// returns the first valid (long) integer value from the current position.
|
||||||
// initial characters that are not digits (or the minus sign) are skipped
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
// function is terminated by the first character that is not a digit.
|
// function is terminated by the first character that is not a digit.
|
||||||
long Stream::parseInt()
|
long Stream::parseInt(LookaheadMode lookahead)
|
||||||
{
|
{
|
||||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
return parseInt(lookahead, NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// as above but a given skipChar is ignored
|
// as above but 'ignore' is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
long Stream::parseInt(char skipChar)
|
long Stream::parseInt(LookaheadMode lookahead, char ignore)
|
||||||
{
|
{
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
c = peekNextDigit(false);
|
c = peekNextDigit(lookahead, false);
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0)
|
if(c < 0)
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
do{
|
do{
|
||||||
if(c == skipChar)
|
if(c == ignore)
|
||||||
; // ignore this charactor
|
; // ignore this charactor
|
||||||
else if(c == '-')
|
else if(c == '-')
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
@ -142,7 +153,7 @@ long Stream::parseInt(char skipChar)
|
|||||||
read(); // consume the character we got with peek
|
read(); // consume the character we got with peek
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
}
|
}
|
||||||
while( (c >= '0' && c <= '9') || c == skipChar );
|
while( (c >= '0' && c <= '9') || c == ignore );
|
||||||
|
|
||||||
if(isNegative)
|
if(isNegative)
|
||||||
value = -value;
|
value = -value;
|
||||||
@ -151,27 +162,27 @@ long Stream::parseInt(char skipChar)
|
|||||||
|
|
||||||
|
|
||||||
// as parseInt but returns a floating point value
|
// as parseInt but returns a floating point value
|
||||||
float Stream::parseFloat()
|
float Stream::parseFloat(LookaheadMode lookahead)
|
||||||
{
|
{
|
||||||
return parseFloat(NO_SKIP_CHAR);
|
return parseFloat(lookahead, NO_SKIP_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// as above but the given skipChar is ignored
|
// as above but the given ignore is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
float Stream::parseFloat(char skipChar){
|
float Stream::parseFloat(LookaheadMode lookahead, char ignore){
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
bool isFraction = false;
|
bool isFraction = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
char c;
|
char c;
|
||||||
float fraction = 1.0;
|
float fraction = 1.0;
|
||||||
|
|
||||||
c = peekNextDigit(true);
|
c = peekNextDigit(lookahead, true);
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0)
|
if(c < 0)
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
do{
|
do{
|
||||||
if(c == skipChar)
|
if(c == ignore)
|
||||||
; // ignore
|
; // ignore
|
||||||
else if(c == '-')
|
else if(c == '-')
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
@ -185,7 +196,7 @@ float Stream::parseFloat(char skipChar){
|
|||||||
read(); // consume the character we got with peek
|
read(); // consume the character we got with peek
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
}
|
}
|
||||||
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == skipChar );
|
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == ignore );
|
||||||
|
|
||||||
if(isNegative)
|
if(isNegative)
|
||||||
value = -value;
|
value = -value;
|
||||||
|
@ -28,13 +28,22 @@
|
|||||||
// compatability macros for testing
|
// compatability macros for testing
|
||||||
/*
|
/*
|
||||||
#define getInt() parseInt()
|
#define getInt() parseInt()
|
||||||
#define getInt(skipChar) parseInt(skipchar)
|
#define getInt(ignore) parseInt(ignore)
|
||||||
#define getFloat() parseFloat()
|
#define getFloat() parseFloat()
|
||||||
#define getFloat(skipChar) parseFloat(skipChar)
|
#define getFloat(ignore) parseFloat(ignore)
|
||||||
#define getString( pre_string, post_string, buffer, length)
|
#define getString( pre_string, post_string, buffer, length)
|
||||||
readBytesBetween( pre_string, terminator, 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.
|
||||||
|
};
|
||||||
|
|
||||||
class Stream : public Print
|
class Stream : public Print
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -42,7 +51,7 @@ class Stream : public Print
|
|||||||
unsigned long _startMillis; // used for timeout measurement
|
unsigned long _startMillis; // used for timeout measurement
|
||||||
int timedRead(); // private method to read stream with timeout
|
int timedRead(); // private method to read stream with timeout
|
||||||
int timedPeek(); // private method to peek stream with timeout
|
int timedPeek(); // private method to peek stream with timeout
|
||||||
int peekNextDigit( bool detectDecimal ); // returns the next numeric digit in the stream or -1 if timeout
|
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int available() = 0;
|
virtual int available() = 0;
|
||||||
@ -73,11 +82,11 @@ class Stream : public Print
|
|||||||
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
||||||
|
|
||||||
|
|
||||||
long parseInt(); // returns the first valid (long) integer value from the current position.
|
long parseInt(LookaheadMode lookahead = SKIP_ALL); // returns the first valid (long) integer value from the current position.
|
||||||
// initial characters that are not digits (or the minus sign) are skipped
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
// integer is terminated by the first character that is not a digit.
|
// integer is terminated by the first character that is not a digit.
|
||||||
|
|
||||||
float parseFloat(); // float version of parseInt
|
float parseFloat(LookaheadMode lookahead = SKIP_ALL); // float version of parseInt
|
||||||
|
|
||||||
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
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( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
|
||||||
@ -94,11 +103,13 @@ class Stream : public Print
|
|||||||
String readStringUntil(char terminator);
|
String readStringUntil(char terminator);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
|
||||||
// as above but the given skipChar is ignored
|
long parseInt(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
|
||||||
|
// as above but 'ignore' is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
|
||||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
|
||||||
|
float parseFloat(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
|
||||||
|
|
||||||
struct MultiTarget {
|
struct MultiTarget {
|
||||||
const char *str; // string you're searching for
|
const char *str; // string you're searching for
|
||||||
|
@ -54,7 +54,7 @@ int Stream::timedPeek()
|
|||||||
|
|
||||||
// returns peek of the next digit in the stream or -1 if timeout
|
// returns peek of the next digit in the stream or -1 if timeout
|
||||||
// discards non-numeric characters
|
// discards non-numeric characters
|
||||||
int Stream::peekNextDigit( bool detectDecimal )
|
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal )
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -65,6 +65,17 @@ int Stream::peekNextDigit( bool detectDecimal )
|
|||||||
c >= '0' && c <= '9' ||
|
c >= '0' && c <= '9' ||
|
||||||
detectDecimal && c == '.') return c;
|
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.
|
||||||
|
}
|
||||||
|
}
|
||||||
read(); // discard non-numeric
|
read(); // discard non-numeric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,27 +125,27 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t
|
|||||||
// returns the first valid (long) integer value from the current position.
|
// returns the first valid (long) integer value from the current position.
|
||||||
// initial characters that are not digits (or the minus sign) are skipped
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
// function is terminated by the first character that is not a digit.
|
// function is terminated by the first character that is not a digit.
|
||||||
long Stream::parseInt()
|
long Stream::parseInt(LookaheadMode lookahead)
|
||||||
{
|
{
|
||||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
return parseInt(lookahead, NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// as above but a given skipChar is ignored
|
// as above but 'ignore' is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
long Stream::parseInt(char skipChar)
|
long Stream::parseInt(LookaheadMode lookahead, char ignore)
|
||||||
{
|
{
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
c = peekNextDigit(false);
|
c = peekNextDigit(lookahead, false);
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0)
|
if(c < 0)
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
do{
|
do{
|
||||||
if(c == skipChar)
|
if(c == ignore)
|
||||||
; // ignore this charactor
|
; // ignore this character
|
||||||
else if(c == '-')
|
else if(c == '-')
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
else if(c >= '0' && c <= '9') // is c a digit?
|
else if(c >= '0' && c <= '9') // is c a digit?
|
||||||
@ -142,7 +153,7 @@ long Stream::parseInt(char skipChar)
|
|||||||
read(); // consume the character we got with peek
|
read(); // consume the character we got with peek
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
}
|
}
|
||||||
while( (c >= '0' && c <= '9') || c == skipChar );
|
while( (c >= '0' && c <= '9') || c == ignore );
|
||||||
|
|
||||||
if(isNegative)
|
if(isNegative)
|
||||||
value = -value;
|
value = -value;
|
||||||
@ -151,27 +162,27 @@ long Stream::parseInt(char skipChar)
|
|||||||
|
|
||||||
|
|
||||||
// as parseInt but returns a floating point value
|
// as parseInt but returns a floating point value
|
||||||
float Stream::parseFloat()
|
float Stream::parseFloat(LookaheadMode lookahead)
|
||||||
{
|
{
|
||||||
return parseFloat(NO_SKIP_CHAR);
|
return parseFloat(lookahead, NO_SKIP_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// as above but the given skipChar is ignored
|
// as above but the given ignore is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
float Stream::parseFloat(char skipChar){
|
float Stream::parseFloat(LookaheadMode lookahead, char ignore){
|
||||||
bool isNegative = false;
|
bool isNegative = false;
|
||||||
bool isFraction = false;
|
bool isFraction = false;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
char c;
|
char c;
|
||||||
float fraction = 1.0;
|
float fraction = 1.0;
|
||||||
|
|
||||||
c = peekNextDigit(true);
|
c = peekNextDigit(lookahead, true);
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0)
|
if(c < 0)
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
do{
|
do{
|
||||||
if(c == skipChar)
|
if(c == ignore)
|
||||||
; // ignore
|
; // ignore
|
||||||
else if(c == '-')
|
else if(c == '-')
|
||||||
isNegative = true;
|
isNegative = true;
|
||||||
@ -185,7 +196,7 @@ float Stream::parseFloat(char skipChar){
|
|||||||
read(); // consume the character we got with peek
|
read(); // consume the character we got with peek
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
}
|
}
|
||||||
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == skipChar );
|
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == ignore );
|
||||||
|
|
||||||
if(isNegative)
|
if(isNegative)
|
||||||
value = -value;
|
value = -value;
|
||||||
|
@ -28,13 +28,22 @@
|
|||||||
// compatability macros for testing
|
// compatability macros for testing
|
||||||
/*
|
/*
|
||||||
#define getInt() parseInt()
|
#define getInt() parseInt()
|
||||||
#define getInt(skipChar) parseInt(skipchar)
|
#define getInt(ignore) parseInt(ignore)
|
||||||
#define getFloat() parseFloat()
|
#define getFloat() parseFloat()
|
||||||
#define getFloat(skipChar) parseFloat(skipChar)
|
#define getFloat(ignore) parseFloat(ignore)
|
||||||
#define getString( pre_string, post_string, buffer, length)
|
#define getString( pre_string, post_string, buffer, length)
|
||||||
readBytesBetween( pre_string, terminator, 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.
|
||||||
|
};
|
||||||
|
|
||||||
class Stream : public Print
|
class Stream : public Print
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -42,7 +51,7 @@ class Stream : public Print
|
|||||||
unsigned long _startMillis; // used for timeout measurement
|
unsigned long _startMillis; // used for timeout measurement
|
||||||
int timedRead(); // private method to read stream with timeout
|
int timedRead(); // private method to read stream with timeout
|
||||||
int timedPeek(); // private method to peek stream with timeout
|
int timedPeek(); // private method to peek stream with timeout
|
||||||
int peekNextDigit( bool detectDecimal ); // returns the next numeric digit in the stream or -1 if timeout
|
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int available() = 0;
|
virtual int available() = 0;
|
||||||
@ -71,11 +80,11 @@ class Stream : public Print
|
|||||||
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
||||||
|
|
||||||
|
|
||||||
long parseInt(); // returns the first valid (long) integer value from the current position.
|
long parseInt(LookaheadMode lookahead = SKIP_ALL); // returns the first valid (long) integer value from the current position.
|
||||||
// initial characters that are not digits (or the minus sign) are skipped
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
// integer is terminated by the first character that is not a digit.
|
// integer is terminated by the first character that is not a digit.
|
||||||
|
|
||||||
float parseFloat(); // float version of parseInt
|
float parseFloat(LookaheadMode lookahead = SKIP_ALL); // float version of parseInt
|
||||||
|
|
||||||
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
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( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
|
||||||
@ -92,11 +101,13 @@ class Stream : public Print
|
|||||||
String readStringUntil(char terminator);
|
String readStringUntil(char terminator);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
|
||||||
// as above but the given skipChar is ignored
|
long parseInt(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
|
||||||
|
// as above but 'ignore' is ignored
|
||||||
// this allows format characters (typically commas) in values to be ignored
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
|
||||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
|
||||||
|
float parseFloat(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
|
||||||
|
|
||||||
struct MultiTarget {
|
struct MultiTarget {
|
||||||
const char *str; // string you're searching for
|
const char *str; // string you're searching for
|
||||||
|
Loading…
Reference in New Issue
Block a user