Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / cores / arduino / Stream.cpp @ 58d82c77

History | View | Annotate | Download (6.75 KB)

1
/*
2
 Stream.cpp - adds parsing methods to Stream class
3
 Copyright (c) 2008 David A. Mellis.  All right reserved.
4

5
 This library is free software; you can redistribute it and/or
6
 modify it under the terms of the GNU Lesser General Public
7
 License as published by the Free Software Foundation; either
8
 version 2.1 of the License, or (at your option) any later version.
9

10
 This library is distributed in the hope that it will be useful,
11
 but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 Lesser General Public License for more details.
14

15
 You should have received a copy of the GNU Lesser General Public
16
 License along with this library; if not, write to the Free Software
17
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18

19
 Created July 2011
20
 parsing functions based on TextFinder library by Michael Margolis
21
 */
22

    
23
#include "Arduino.h"
24
#include "Stream.h"
25

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

    
29
// private method to read stream with timeout
30
int Stream::timedRead()
31
{
32
  int c;
33
  _startMillis = millis();
34
  do {
35
    c = read();
36
    if (c >= 0) return c;
37
  } while(millis() - _startMillis < _timeout);
38
  return -1;     // -1 indicates timeout
39
}
40

    
41
// private method to peek stream with timeout
42
int Stream::timedPeek()
43
{
44
  int c;
45
  _startMillis = millis();
46
  do {
47
    c = peek();
48
    if (c >= 0) return c;
49
  } while(millis() - _startMillis < _timeout);
50
  return -1;     // -1 indicates timeout
51
}
52

    
53
// returns peek of the next digit in the stream or -1 if timeout
54
// discards non-numeric characters
55
int Stream::peekNextDigit()
56
{
57
  int c;
58
  while (1) {
59
    c = timedPeek();
60
    if (c < 0) return c;  // timeout
61
    if (c == '-') return c;
62
    if (c >= '0' && c <= '9') return c;
63
    read();  // discard non-numeric
64
  }
65
}
66

    
67
// Public Methods
68
//////////////////////////////////////////////////////////////
69

    
70
void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait
71
{
72
  _timeout = timeout;
73
}
74

    
75
 // find returns true if the target string is found
76
bool  Stream::find(char *target)
77
{
78
  return findUntil(target, NULL);
79
}
80

    
81
// reads data from the stream until the target string of given length is found
82
// returns true if target string is found, false if timed out
83
bool Stream::find(char *target, size_t length)
84
{
85
  return findUntil(target, length, NULL, 0);
86
}
87

    
88
// as find but search ends if the terminator string is found
89
bool  Stream::findUntil(char *target, char *terminator)
90
{
91
  return findUntil(target, strlen(target), terminator, strlen(terminator));
92
}
93

    
94
// reads data from the stream until the target string of the given length is found
95
// search terminated if the terminator string is found
96
// returns true if target string is found, false if terminated or timed out
97
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
98
{
99
  size_t index = 0;  // maximum target string length is 64k bytes!
100
  size_t termIndex = 0;
101
  int c;
102

    
103
  if( *target == 0)
104
     return true;   // return true if target is a null string
105
  while( (c = timedRead()) > 0){
106
    if( c == target[index]){
107
    //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
108
      if(++index >= targetLen){ // return true if all chars in the target match
109
        return true;
110
      }
111
    }
112
    else{
113
      index = 0;  // reset index if any char does not match
114
    }
115
    if(termLen > 0 && c == terminator[termIndex]){
116
       if(++termIndex >= termLen)
117
         return false;       // return false if terminate string found before target string
118
    }
119
    else
120
        termIndex = 0;
121
  }
122
  return false;
123
}
124

    
125

    
126
// returns the first valid (long) integer value from the current position.
127
// initial characters that are not digits (or the minus sign) are skipped
128
// function is terminated by the first character that is not a digit.
129
long Stream::parseInt()
130
{
131
  return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
132
}
133

    
134
// as above but a given skipChar is ignored
135
// this allows format characters (typically commas) in values to be ignored
136
long Stream::parseInt(char skipChar)
137
{
138
  boolean isNegative = false;
139
  long value = 0;
140
  int c;
141

    
142
  c = peekNextDigit();
143
  // ignore non numeric leading characters
144
  if(c < 0)
145
    return 0; // zero returned if timeout
146

    
147
  do{
148
    if(c == skipChar)
149
      ; // ignore this charactor
150
    else if(c == '-')
151
      isNegative = true;
152
    else if(c >= '0' && c <= '9')        // is c a digit?
153
      value = value * 10 + c - '0';
154
    read();  // consume the character we got with peek
155
    c = timedPeek();
156
  }
157
  while( (c >= '0' && c <= '9') || c == skipChar );
158

    
159
  if(isNegative)
160
    value = -value;
161
  return value;
162
}
163

    
164

    
165
// as parseInt but returns a floating point value
166
float Stream::parseFloat()
167
{
168
  return parseFloat(NO_SKIP_CHAR);
169
}
170

    
171
// as above but the given skipChar is ignored
172
// this allows format characters (typically commas) in values to be ignored
173
float Stream::parseFloat(char skipChar){
174
  boolean isNegative = false;
175
  boolean isFraction = false;
176
  long value = 0;
177
  char c;
178
  float fraction = 1.0;
179

    
180
  c = peekNextDigit();
181
    // ignore non numeric leading characters
182
  if(c < 0)
183
    return 0; // zero returned if timeout
184

    
185
  do{
186
    if(c == skipChar)
187
      ; // ignore
188
    else if(c == '-')
189
      isNegative = true;
190
    else if (c == '.')
191
      isFraction = true;
192
    else if(c >= '0' && c <= '9')  {      // is c a digit?
193
      value = value * 10 + c - '0';
194
      if(isFraction)
195
         fraction *= 0.1;
196
    }
197
    read();  // consume the character we got with peek
198
    c = timedPeek();
199
  }
200
  while( (c >= '0' && c <= '9')  || c == '.' || c == skipChar );
201

    
202
  if(isNegative)
203
    value = -value;
204
  if(isFraction)
205
    return value * fraction;
206
  else
207
    return value;
208
}
209

    
210
// read characters from stream into buffer
211
// terminates if length characters have been read, or timeout (see setTimeout)
212
// returns the number of characters placed in the buffer
213
// the buffer is NOT null terminated.
214
//
215
size_t Stream::readBytes(char *buffer, size_t length)
216
{
217
  size_t count = 0;
218
  while (count < length) {
219
    int c = timedRead();
220
    if (c < 0) break;
221
    *buffer++ = (char)c;
222
    count++;
223
  }
224
  return count;
225
}
226

    
227

    
228
// as readBytes with terminator character
229
// terminates if length characters have been read, timeout, or if the terminator character  detected
230
// returns the number of characters placed in the buffer (0 means no valid data found)
231

    
232
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
233
{
234
  if (length < 1) return 0;
235
  size_t index = 0;
236
  while (index < length) {
237
    int c = timedRead();
238
    if (c < 0 || c == terminator) break;
239
    *buffer++ = (char)c;
240
    index++;
241
  }
242
  return index; // return number of characters, not including null terminator
243
}
244