Skip to content

Commit 004838a

Browse files
committed
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`.
1 parent 9ecc150 commit 004838a

File tree

4 files changed

+93
-49
lines changed

4 files changed

+93
-49
lines changed

hardware/arduino/avr/cores/arduino/Stream.cpp

+26-15
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int Stream::timedPeek()
5454

5555
// returns peek of the next digit in the stream or -1 if timeout
5656
// discards non-numeric characters
57-
int Stream::peekNextDigit( bool detectDecimal )
57+
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
5858
{
5959
int c;
6060
while (1) {
@@ -65,6 +65,17 @@ int Stream::peekNextDigit( bool detectDecimal )
6565
c >= '0' && c <= '9' ||
6666
detectDecimal && c == '.') return c;
6767

68+
switch( lookahead ){
69+
case SKIP_NONE: return -1; // Fail code.
70+
case SKIP_WHITESPACE:
71+
switch( c ){
72+
case ' ':
73+
case '\t':
74+
case '\r':
75+
case '\n': break;
76+
default: return -1; // Fail code.
77+
}
78+
}
6879
read(); // discard non-numeric
6980
}
7081
}
@@ -114,26 +125,26 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t
114125
// returns the first valid (long) integer value from the current position.
115126
// initial characters that are not digits (or the minus sign) are skipped
116127
// function is terminated by the first character that is not a digit.
117-
long Stream::parseInt()
128+
long Stream::parseInt(LookaheadMode lookahead)
118129
{
119-
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
130+
return parseInt(lookahead, NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
120131
}
121132

122-
// as above but a given skipChar is ignored
133+
// as above but 'ignore' is ignored
123134
// this allows format characters (typically commas) in values to be ignored
124-
long Stream::parseInt(char skipChar)
135+
long Stream::parseInt(LookaheadMode lookahead, char ignore)
125136
{
126137
bool isNegative = false;
127138
long value = 0;
128139
int c;
129140

130-
c = peekNextDigit(false);
141+
c = peekNextDigit(lookahead, false);
131142
// ignore non numeric leading characters
132143
if(c < 0)
133144
return 0; // zero returned if timeout
134145

135146
do{
136-
if(c == skipChar)
147+
if(c == ignore)
137148
; // ignore this charactor
138149
else if(c == '-')
139150
isNegative = true;
@@ -142,7 +153,7 @@ long Stream::parseInt(char skipChar)
142153
read(); // consume the character we got with peek
143154
c = timedPeek();
144155
}
145-
while( (c >= '0' && c <= '9') || c == skipChar );
156+
while( (c >= '0' && c <= '9') || c == ignore );
146157

147158
if(isNegative)
148159
value = -value;
@@ -151,27 +162,27 @@ long Stream::parseInt(char skipChar)
151162

152163

153164
// as parseInt but returns a floating point value
154-
float Stream::parseFloat()
165+
float Stream::parseFloat(LookaheadMode lookahead)
155166
{
156-
return parseFloat(NO_SKIP_CHAR);
167+
return parseFloat(lookahead, NO_SKIP_CHAR);
157168
}
158169

159-
// as above but the given skipChar is ignored
170+
// as above but the given ignore is ignored
160171
// this allows format characters (typically commas) in values to be ignored
161-
float Stream::parseFloat(char skipChar){
172+
float Stream::parseFloat(LookaheadMode lookahead, char ignore){
162173
bool isNegative = false;
163174
bool isFraction = false;
164175
long value = 0;
165176
char c;
166177
float fraction = 1.0;
167178

168-
c = peekNextDigit(true);
179+
c = peekNextDigit(lookahead, true);
169180
// ignore non numeric leading characters
170181
if(c < 0)
171182
return 0; // zero returned if timeout
172183

173184
do{
174-
if(c == skipChar)
185+
if(c == ignore)
175186
; // ignore
176187
else if(c == '-')
177188
isNegative = true;
@@ -185,7 +196,7 @@ float Stream::parseFloat(char skipChar){
185196
read(); // consume the character we got with peek
186197
c = timedPeek();
187198
}
188-
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == skipChar );
199+
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == ignore );
189200

190201
if(isNegative)
191202
value = -value;

hardware/arduino/avr/cores/arduino/Stream.h

+20-9
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,30 @@
2828
// compatability macros for testing
2929
/*
3030
#define getInt() parseInt()
31-
#define getInt(skipChar) parseInt(skipchar)
31+
#define getInt(ignore) parseInt(ignore)
3232
#define getFloat() parseFloat()
33-
#define getFloat(skipChar) parseFloat(skipChar)
33+
#define getFloat(ignore) parseFloat(ignore)
3434
#define getString( pre_string, post_string, buffer, length)
3535
readBytesBetween( pre_string, terminator, buffer, length)
3636
*/
3737

38+
// This enumeration provides the lookahead options for parseInt(), parseFloat()
39+
// The rules set out here are used until either the first valid character is found
40+
// or a time out occurs due to lack of input.
41+
enum LookaheadMode{
42+
SKIP_ALL, // All invalid characters are ignored.
43+
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
44+
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
45+
};
46+
3847
class Stream : public Print
3948
{
4049
protected:
4150
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
4251
unsigned long _startMillis; // used for timeout measurement
4352
int timedRead(); // private method to read stream with timeout
4453
int timedPeek(); // private method to peek stream with timeout
45-
int peekNextDigit( bool detectDecimal ); // returns the next numeric digit in the stream or -1 if timeout
54+
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
4655

4756
public:
4857
virtual int available() = 0;
@@ -73,11 +82,11 @@ class Stream : public Print
7382
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
7483

7584

76-
long parseInt(); // returns the first valid (long) integer value from the current position.
85+
long parseInt(LookaheadMode lookahead = SKIP_ALL); // returns the first valid (long) integer value from the current position.
7786
// initial characters that are not digits (or the minus sign) are skipped
7887
// integer is terminated by the first character that is not a digit.
7988

80-
float parseFloat(); // float version of parseInt
89+
float parseFloat(LookaheadMode lookahead = SKIP_ALL); // float version of parseInt
8190

8291
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
8392
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
@@ -94,11 +103,13 @@ class Stream : public Print
94103
String readStringUntil(char terminator);
95104

96105
protected:
97-
long parseInt(char skipChar); // as above but the given skipChar is ignored
98-
// as above but the given skipChar is ignored
106+
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
107+
long parseInt(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
108+
// as above but 'ignore' is ignored
99109
// this allows format characters (typically commas) in values to be ignored
100-
101-
float parseFloat(char skipChar); // as above but the given skipChar is ignored
110+
111+
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
112+
float parseFloat(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
102113

103114
struct MultiTarget {
104115
const char *str; // string you're searching for

hardware/arduino/sam/cores/arduino/Stream.cpp

+27-16
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int Stream::timedPeek()
5454

5555
// returns peek of the next digit in the stream or -1 if timeout
5656
// discards non-numeric characters
57-
int Stream::peekNextDigit( bool detectDecimal )
57+
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal )
5858
{
5959
int c;
6060
while (1) {
@@ -65,6 +65,17 @@ int Stream::peekNextDigit( bool detectDecimal )
6565
c >= '0' && c <= '9' ||
6666
detectDecimal && c == '.') return c;
6767

68+
switch( lookahead ){
69+
case SKIP_NONE: return -1; // Fail code.
70+
case SKIP_WHITESPACE:
71+
switch( c ){
72+
case ' ':
73+
case '\t':
74+
case '\r':
75+
case '\n': break;
76+
default: return -1; // Fail code.
77+
}
78+
}
6879
read(); // discard non-numeric
6980
}
7081
}
@@ -114,35 +125,35 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t
114125
// returns the first valid (long) integer value from the current position.
115126
// initial characters that are not digits (or the minus sign) are skipped
116127
// function is terminated by the first character that is not a digit.
117-
long Stream::parseInt()
128+
long Stream::parseInt(LookaheadMode lookahead)
118129
{
119-
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
130+
return parseInt(lookahead, NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
120131
}
121132

122-
// as above but a given skipChar is ignored
133+
// as above but 'ignore' is ignored
123134
// this allows format characters (typically commas) in values to be ignored
124-
long Stream::parseInt(char skipChar)
135+
long Stream::parseInt(LookaheadMode lookahead, char ignore)
125136
{
126137
bool isNegative = false;
127138
long value = 0;
128139
int c;
129140

130-
c = peekNextDigit(false);
141+
c = peekNextDigit(lookahead, false);
131142
// ignore non numeric leading characters
132143
if(c < 0)
133144
return 0; // zero returned if timeout
134145

135146
do{
136-
if(c == skipChar)
137-
; // ignore this charactor
147+
if(c == ignore)
148+
; // ignore this character
138149
else if(c == '-')
139150
isNegative = true;
140151
else if(c >= '0' && c <= '9') // is c a digit?
141152
value = value * 10 + c - '0';
142153
read(); // consume the character we got with peek
143154
c = timedPeek();
144155
}
145-
while( (c >= '0' && c <= '9') || c == skipChar );
156+
while( (c >= '0' && c <= '9') || c == ignore );
146157

147158
if(isNegative)
148159
value = -value;
@@ -151,27 +162,27 @@ long Stream::parseInt(char skipChar)
151162

152163

153164
// as parseInt but returns a floating point value
154-
float Stream::parseFloat()
165+
float Stream::parseFloat(LookaheadMode lookahead)
155166
{
156-
return parseFloat(NO_SKIP_CHAR);
167+
return parseFloat(lookahead, NO_SKIP_CHAR);
157168
}
158169

159-
// as above but the given skipChar is ignored
170+
// as above but the given ignore is ignored
160171
// this allows format characters (typically commas) in values to be ignored
161-
float Stream::parseFloat(char skipChar){
172+
float Stream::parseFloat(LookaheadMode lookahead, char ignore){
162173
bool isNegative = false;
163174
bool isFraction = false;
164175
long value = 0;
165176
char c;
166177
float fraction = 1.0;
167178

168-
c = peekNextDigit(true);
179+
c = peekNextDigit(lookahead, true);
169180
// ignore non numeric leading characters
170181
if(c < 0)
171182
return 0; // zero returned if timeout
172183

173184
do{
174-
if(c == skipChar)
185+
if(c == ignore)
175186
; // ignore
176187
else if(c == '-')
177188
isNegative = true;
@@ -185,7 +196,7 @@ float Stream::parseFloat(char skipChar){
185196
read(); // consume the character we got with peek
186197
c = timedPeek();
187198
}
188-
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == skipChar );
199+
while( (c >= '0' && c <= '9') || c == '.' && !isFraction || c == ignore );
189200

190201
if(isNegative)
191202
value = -value;

hardware/arduino/sam/cores/arduino/Stream.h

+20-9
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,30 @@
2828
// compatability macros for testing
2929
/*
3030
#define getInt() parseInt()
31-
#define getInt(skipChar) parseInt(skipchar)
31+
#define getInt(ignore) parseInt(ignore)
3232
#define getFloat() parseFloat()
33-
#define getFloat(skipChar) parseFloat(skipChar)
33+
#define getFloat(ignore) parseFloat(ignore)
3434
#define getString( pre_string, post_string, buffer, length)
3535
readBytesBetween( pre_string, terminator, buffer, length)
3636
*/
3737

38+
// This enumeration provides the lookahead options for parseInt(), parseFloat()
39+
// The rules set out here are used until either the first valid character is found
40+
// or a time out occurs due to lack of input.
41+
enum LookaheadMode{
42+
SKIP_ALL, // All invalid characters are ignored.
43+
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
44+
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
45+
};
46+
3847
class Stream : public Print
3948
{
4049
protected:
4150
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
4251
unsigned long _startMillis; // used for timeout measurement
4352
int timedRead(); // private method to read stream with timeout
4453
int timedPeek(); // private method to peek stream with timeout
45-
int peekNextDigit( bool detectDecimal ); // returns the next numeric digit in the stream or -1 if timeout
54+
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
4655

4756
public:
4857
virtual int available() = 0;
@@ -71,11 +80,11 @@ class Stream : public Print
7180
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
7281

7382

74-
long parseInt(); // returns the first valid (long) integer value from the current position.
83+
long parseInt(LookaheadMode lookahead = SKIP_ALL); // returns the first valid (long) integer value from the current position.
7584
// initial characters that are not digits (or the minus sign) are skipped
7685
// integer is terminated by the first character that is not a digit.
7786

78-
float parseFloat(); // float version of parseInt
87+
float parseFloat(LookaheadMode lookahead = SKIP_ALL); // float version of parseInt
7988

8089
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
8190
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
@@ -92,11 +101,13 @@ class Stream : public Print
92101
String readStringUntil(char terminator);
93102

94103
protected:
95-
long parseInt(char skipChar); // as above but the given skipChar is ignored
96-
// as above but the given skipChar is ignored
104+
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
105+
long parseInt(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
106+
// as above but 'ignore' is ignored
97107
// this allows format characters (typically commas) in values to be ignored
98-
99-
float parseFloat(char skipChar); // as above but the given skipChar is ignored
108+
109+
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
110+
float parseFloat(LookaheadMode lookahead, char ignore); // as above but the given ignore is ignored
100111

101112
struct MultiTarget {
102113
const char *str; // string you're searching for

0 commit comments

Comments
 (0)