From fe40b607fcf3b418d61365ce0b1b9e5b4dcd6fdf Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 10 Oct 2017 20:49:55 -0700 Subject: [PATCH] Extract Stream methods into an IStream This allows streams to exist that are input-only, such as a keyboard. --- .../cores/arduino/{Stream.cpp => IStream.cpp} | 34 ++--- hardware/arduino/avr/cores/arduino/IStream.h | 128 ++++++++++++++++++ hardware/arduino/avr/cores/arduino/Stream.h | 108 +-------------- 3 files changed, 148 insertions(+), 122 deletions(-) rename hardware/arduino/avr/cores/arduino/{Stream.cpp => IStream.cpp} (89%) create mode 100644 hardware/arduino/avr/cores/arduino/IStream.h diff --git a/hardware/arduino/avr/cores/arduino/Stream.cpp b/hardware/arduino/avr/cores/arduino/IStream.cpp similarity index 89% rename from hardware/arduino/avr/cores/arduino/Stream.cpp rename to hardware/arduino/avr/cores/arduino/IStream.cpp index d2846316d34..bec5f7d6b26 100644 --- a/hardware/arduino/avr/cores/arduino/Stream.cpp +++ b/hardware/arduino/avr/cores/arduino/IStream.cpp @@ -1,5 +1,5 @@ /* - Stream.cpp - adds parsing methods to Stream class + IStream.cpp - adds parsing methods to IStream class Copyright (c) 2008 David A. Mellis. All right reserved. This library is free software; you can redistribute it and/or @@ -23,12 +23,12 @@ */ #include "Arduino.h" -#include "Stream.h" +#include "IStream.h" #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait // protected method to read stream with timeout -int Stream::timedRead() +int IStream::timedRead() { int c; _startMillis = millis(); @@ -40,7 +40,7 @@ int Stream::timedRead() } // protected method to peek stream with timeout -int Stream::timedPeek() +int IStream::timedPeek() { int c; _startMillis = millis(); @@ -53,7 +53,7 @@ int Stream::timedPeek() // 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 IStream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) { int c; while (1) { @@ -84,26 +84,26 @@ int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) // Public Methods ////////////////////////////////////////////////////////////// -void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait +void IStream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait { _timeout = timeout; } // find returns true if the target string is found -bool Stream::find(char *target) +bool IStream::find(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(char *target, size_t length) +bool IStream::find(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(char *target, char *terminator) +bool IStream::findUntil(char *target, char *terminator) { return findUntil(target, strlen(target), terminator, strlen(terminator)); } @@ -111,7 +111,7 @@ bool Stream::findUntil(char *target, char *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(char *target, size_t targetLen, char *terminator, size_t termLen) +bool IStream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) { if (terminator == NULL) { MultiTarget t[1] = {{target, targetLen, 0}}; @@ -127,7 +127,7 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t // 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 IStream::parseInt(LookaheadMode lookahead, char ignore) { bool isNegative = false; long value = 0; @@ -156,7 +156,7 @@ long Stream::parseInt(LookaheadMode lookahead, char ignore) } // as parseInt but returns a floating point value -float Stream::parseFloat(LookaheadMode lookahead, char ignore) +float IStream::parseFloat(LookaheadMode lookahead, char ignore) { bool isNegative = false; bool isFraction = false; @@ -199,7 +199,7 @@ 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 IStream::readBytes(char *buffer, size_t length) { size_t count = 0; while (count < length) { @@ -216,7 +216,7 @@ size_t Stream::readBytes(char *buffer, size_t 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) -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) +size_t IStream::readBytesUntil(char terminator, char *buffer, size_t length) { if (length < 1) return 0; size_t index = 0; @@ -229,7 +229,7 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) return index; // return number of characters, not including null terminator } -String Stream::readString() +String IStream::readString() { String ret; int c = timedRead(); @@ -241,7 +241,7 @@ String Stream::readString() return ret; } -String Stream::readStringUntil(char terminator) +String IStream::readStringUntil(char terminator) { String ret; int c = timedRead(); @@ -253,7 +253,7 @@ String Stream::readStringUntil(char terminator) return ret; } -int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { +int IStream::findMulti( struct IStream::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) { diff --git a/hardware/arduino/avr/cores/arduino/IStream.h b/hardware/arduino/avr/cores/arduino/IStream.h new file mode 100644 index 00000000000..a4d74ab4ad9 --- /dev/null +++ b/hardware/arduino/avr/cores/arduino/IStream.h @@ -0,0 +1,128 @@ +/* + IStream.h - base class for character-based input 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 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 + + parsing functions based on TextFinder library by Michael Margolis +*/ + +#ifndef IStream_h +#define IStream_h + +#include + +// compatability macros for testing +/* +#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. +}; + +#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field + +class IStream +{ + 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(); // read stream with timeout + int timedPeek(); // 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; + + IStream() {_timeout=1000;} + +// 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(char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) { return find ((char *)target); } + // returns true if target string is found, false if timed out (see setTimeout) + + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + // returns true if target string is found, false if timed out + + bool find(char target) { return find (&target, 1); } + + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((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. + // 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(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); } + // 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); } + // 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 + 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); } + // These overload exists for compatibility with any class that has derived + // IStream 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 + size_t len; // length of string you're searching for + size_t index; // index used by the search routine. + }; + + // This allows you to search for an arbitrary number of strings. + // Returns index of the target that is found first or -1 if timeout occurs. + int findMulti(struct MultiTarget *targets, int tCount); +}; + +#undef NO_IGNORE_CHAR +#endif diff --git a/hardware/arduino/avr/cores/arduino/Stream.h b/hardware/arduino/avr/cores/arduino/Stream.h index 8e950c73137..b9d4a167caf 100644 --- a/hardware/arduino/avr/cores/arduino/Stream.h +++ b/hardware/arduino/avr/cores/arduino/Stream.h @@ -1,6 +1,5 @@ /* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. + Stream.h - base class for character-based input/output streams. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,115 +14,14 @@ 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 */ #ifndef Stream_h #define Stream_h -#include #include "Print.h" +#include "IStream.h" -// compatability macros for testing -/* -#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. -}; - -#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(); // read stream with timeout - int timedPeek(); // 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;} - -// 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(char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) { return find ((char *)target); } - // returns true if target string is found, false if timed out (see setTimeout) - - bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } - // returns true if target string is found, false if timed out - - bool find(char target) { return find (&target, 1); } - - bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found - bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } - - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((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. - // 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(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); } - // 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); } - // 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 - 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); } - // 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 - size_t len; // length of string you're searching for - size_t index; // index used by the search routine. - }; - - // This allows you to search for an arbitrary number of strings. - // Returns index of the target that is found first or -1 if timeout occurs. - int findMulti(struct MultiTarget *targets, int tCount); -}; +class Stream : public Print, public IStream { }; -#undef NO_IGNORE_CHAR #endif