]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp
Change TOP_DIR to TMK_DIR in makefiles
[qmk_firmware.git] / protocol / usb_hid / arduino-1.0.1 / cores / arduino / Stream.cpp
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     
107     if(c != target[index])
108       index = 0; // reset index if any char does not match
109     
110     if( c == target[index]){
111       //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
112       if(++index >= targetLen){ // return true if all chars in the target match
113         return true;
114       }
115     }
116     
117     if(termLen > 0 && c == terminator[termIndex]){
118       if(++termIndex >= termLen)
119         return false;       // return false if terminate string found before target string
120     }
121     else
122       termIndex = 0;
123   }
124   return false;
125 }
126
127
128 // returns the first valid (long) integer value from the current position.
129 // initial characters that are not digits (or the minus sign) are skipped
130 // function is terminated by the first character that is not a digit.
131 long Stream::parseInt()
132 {
133   return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
134 }
135
136 // as above but a given skipChar is ignored
137 // this allows format characters (typically commas) in values to be ignored
138 long Stream::parseInt(char skipChar)
139 {
140   boolean isNegative = false;
141   long value = 0;
142   int c;
143
144   c = peekNextDigit();
145   // ignore non numeric leading characters
146   if(c < 0)
147     return 0; // zero returned if timeout
148
149   do{
150     if(c == skipChar)
151       ; // ignore this charactor
152     else if(c == '-')
153       isNegative = true;
154     else if(c >= '0' && c <= '9')        // is c a digit?
155       value = value * 10 + c - '0';
156     read();  // consume the character we got with peek
157     c = timedPeek();
158   }
159   while( (c >= '0' && c <= '9') || c == skipChar );
160
161   if(isNegative)
162     value = -value;
163   return value;
164 }
165
166
167 // as parseInt but returns a floating point value
168 float Stream::parseFloat()
169 {
170   return parseFloat(NO_SKIP_CHAR);
171 }
172
173 // as above but the given skipChar is ignored
174 // this allows format characters (typically commas) in values to be ignored
175 float Stream::parseFloat(char skipChar){
176   boolean isNegative = false;
177   boolean isFraction = false;
178   long value = 0;
179   char c;
180   float fraction = 1.0;
181
182   c = peekNextDigit();
183     // ignore non numeric leading characters
184   if(c < 0)
185     return 0; // zero returned if timeout
186
187   do{
188     if(c == skipChar)
189       ; // ignore
190     else if(c == '-')
191       isNegative = true;
192     else if (c == '.')
193       isFraction = true;
194     else if(c >= '0' && c <= '9')  {      // is c a digit?
195       value = value * 10 + c - '0';
196       if(isFraction)
197          fraction *= 0.1;
198     }
199     read();  // consume the character we got with peek
200     c = timedPeek();
201   }
202   while( (c >= '0' && c <= '9')  || c == '.' || c == skipChar );
203
204   if(isNegative)
205     value = -value;
206   if(isFraction)
207     return value * fraction;
208   else
209     return value;
210 }
211
212 // read characters from stream into buffer
213 // terminates if length characters have been read, or timeout (see setTimeout)
214 // returns the number of characters placed in the buffer
215 // the buffer is NOT null terminated.
216 //
217 size_t Stream::readBytes(char *buffer, size_t length)
218 {
219   size_t count = 0;
220   while (count < length) {
221     int c = timedRead();
222     if (c < 0) break;
223     *buffer++ = (char)c;
224     count++;
225   }
226   return count;
227 }
228
229
230 // as readBytes with terminator character
231 // terminates if length characters have been read, timeout, or if the terminator character  detected
232 // returns the number of characters placed in the buffer (0 means no valid data found)
233
234 size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
235 {
236   if (length < 1) return 0;
237   size_t index = 0;
238   while (index < length) {
239     int c = timedRead();
240     if (c < 0 || c == terminator) break;
241     *buffer++ = (char)c;
242     index++;
243   }
244   return index; // return number of characters, not including null terminator
245 }
246
247 String Stream::readString()
248 {
249   String ret;
250   int c = timedRead();
251   while (c >= 0)
252   {
253     ret += (char)c;
254     c = timedRead();
255   }
256   return ret;
257 }
258
259 String Stream::readStringUntil(char terminator)
260 {
261   String ret;
262   int c = timedRead();
263   while (c >= 0 && c != terminator)
264   {
265     ret += (char)c;
266     c = timedRead();
267   }
268   return ret;
269 }
270