Developers Archive

List Statistics

  • Total Threads: 675
  • Total Posts: 2049

Phrases Used to Find This Thread

  #1  
05-06-2011 10:58 PM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #2  
07-06-2011 03:15 PM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #3  
07-06-2011 04:34 PM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I don't agree about the prefix change. Before Michael's explanation of getString() I might have agreed, but having tried it, I think it makes a lot of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I don't think it's necessary. I think Michael's argument about get() in this case is valid, but if there's consensus on read() and write() I won't object.

I'd recommend keeping the int return type on readString() or getString(). It's valuable to know how big long actual returned array is, vs. what you allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do think
>> that users would prefer having the get functions as a stream method rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>>> through Dave's proposal, I tried to think through how to explain the code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>>> And as Michael points out getInt() does more than just the casting, it also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like names
>>>>>> that are evocative of their functionality and 'get' naming was chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for this API
>>>>>> (it is for me, and most of my web parsing applications seem to use the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find() to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #4  
07-06-2011 08:54 PM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I don't agree about the prefix change. Before Michael's explanation of getString() I might have agreed, but having tried it, I think it makes a lot of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I don't think it's necessary. I think Michael's argument about get() in this case is valid, but if there's consensus on read() and write() I won't object.

I'd recommend keeping the int return type on readString() or getString(). It's valuable to know how big long actual returned array is, vs. what you allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do think
>> that users would prefer having the get functions as a stream method rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>>> through Dave's proposal, I tried to think through how to explain the code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>>> And as Michael points out getInt() does more than just the casting, it also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like names
>>>>>> that are evocative of their functionality and 'get' naming was chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for this API
>>>>>> (it is for me, and most of my web parsing applications seem to use the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find() to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Seems like there are three outstanding issues:

1. Orthogonal method naming: for example, should the method be called
readInt or getInt
2. Should readString/getString have a prestring argument.
3. Should readString/getString return a String or the number of bytes
stored


On the first point, I don’t think the functionality of getInt/getFloat
methods etc is orthogonal with the current stream method to read a
character. read returns the next char in the stream, getInt reads as many
characters as required until it finds one or more ASCII digits and converts
these to an integer. I would expect an orthogonal implementation of readInt
to return the integer value of the next two bytes in the stream. Such a
method could be useful for reading data packed into a binary structure. I am
not suggesting we include this (although it would be easy to implement if
you wanted it) but I do feel that the rather different functionality of the
proposed getInt deserves a name that differentiates from a simple read of a
data type.

Regarding point 2, we could support both version of read/getString – one
without the prestring and one with:
getString( endchar, buffer, length) // all characters up to but excluding
endchar will be copied to the buffer (if the buffer is smaller than length,
the string will be truncated .)
and:
getString(prestring, endchar, buffer, length) // as above but seeks to the
first character following prestring.

There is no performance or resource overhead in the latter getString, it
uses the find method internally - I think this is just a question of which
is easier for the user to type and understand.

Regarding the return type of readString/getString, I would be uncomfortable
if a method was not available that returned the number of bytes collected.
Perhaps that’s just me. Feel free to add method that returned a String if
you feel this was also needed but I don’t feel qualified to implement that
for the Arduino runtime environment.

Michael

-----Original Message-----
From: Tom Igoe
Sent: Tuesday, June 07, 2011 4:34 PM
To: David A. Mellis
Cc: Michael Margolis ;
Subject: Re: [Developers] Adding parsing to Stream

I don't agree about the prefix change. Before Michael's explanation of
getString() I might have agreed, but having tried it, I think it makes a lot
of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I
don't think it's necessary. I think Michael's argument about get() in this
case is valid, but if there's consensus on read() and write() I won't
object.

I'd recommend keeping the int return type on readString() or getString().
It's valuable to know how big long actual returned array is, vs. what you
allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do
>> think
>> that users would prefer having the get functions as a stream method
>> rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the
>> Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the
>> Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in
>>> the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading
>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>> code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>> getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings.
>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>> also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names
>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>> chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting
>>>>>> string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for
>>>>>> this API
>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>> the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>> of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>> we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>> int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>> is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>> a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>> and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>> to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>> the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>> only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>> API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>> is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>> to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>> the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>> not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>> (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #5  
09-06-2011 03:53 AM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I don't agree about the prefix change. Before Michael's explanation of getString() I might have agreed, but having tried it, I think it makes a lot of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I don't think it's necessary. I think Michael's argument about get() in this case is valid, but if there's consensus on read() and write() I won't object.

I'd recommend keeping the int return type on readString() or getString(). It's valuable to know how big long actual returned array is, vs. what you allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do think
>> that users would prefer having the get functions as a stream method rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>>> through Dave's proposal, I tried to think through how to explain the code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>>> And as Michael points out getInt() does more than just the casting, it also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like names
>>>>>> that are evocative of their functionality and 'get' naming was chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for this API
>>>>>> (it is for me, and most of my web parsing applications seem to use the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find() to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Seems like there are three outstanding issues:

1. Orthogonal method naming: for example, should the method be called
readInt or getInt
2. Should readString/getString have a prestring argument.
3. Should readString/getString return a String or the number of bytes
stored


On the first point, I don’t think the functionality of getInt/getFloat
methods etc is orthogonal with the current stream method to read a
character. read returns the next char in the stream, getInt reads as many
characters as required until it finds one or more ASCII digits and converts
these to an integer. I would expect an orthogonal implementation of readInt
to return the integer value of the next two bytes in the stream. Such a
method could be useful for reading data packed into a binary structure. I am
not suggesting we include this (although it would be easy to implement if
you wanted it) but I do feel that the rather different functionality of the
proposed getInt deserves a name that differentiates from a simple read of a
data type.

Regarding point 2, we could support both version of read/getString – one
without the prestring and one with:
getString( endchar, buffer, length) // all characters up to but excluding
endchar will be copied to the buffer (if the buffer is smaller than length,
the string will be truncated .)
and:
getString(prestring, endchar, buffer, length) // as above but seeks to the
first character following prestring.

There is no performance or resource overhead in the latter getString, it
uses the find method internally - I think this is just a question of which
is easier for the user to type and understand.

Regarding the return type of readString/getString, I would be uncomfortable
if a method was not available that returned the number of bytes collected.
Perhaps that’s just me. Feel free to add method that returned a String if
you feel this was also needed but I don’t feel qualified to implement that
for the Arduino runtime environment.

Michael

-----Original Message-----
From: Tom Igoe
Sent: Tuesday, June 07, 2011 4:34 PM
To: David A. Mellis
Cc: Michael Margolis ;
Subject: Re: [Developers] Adding parsing to Stream

I don't agree about the prefix change. Before Michael's explanation of
getString() I might have agreed, but having tried it, I think it makes a lot
of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I
don't think it's necessary. I think Michael's argument about get() in this
case is valid, but if there's consensus on read() and write() I won't
object.

I'd recommend keeping the int return type on readString() or getString().
It's valuable to know how big long actual returned array is, vs. what you
allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do
>> think
>> that users would prefer having the get functions as a stream method
>> rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the
>> Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the
>> Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in
>>> the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading
>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>> code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>> getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings.
>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>> also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names
>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>> chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting
>>>>>> string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for
>>>>>> this API
>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>> the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>> of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>> we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>> int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>> is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>> a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>> and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>> to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>> the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>> only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>> API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>> is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>> to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>> the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>> not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>> (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
To take your issues in turn:

1. getInt() / getFloat() sound like simple accessors, i.e. methods
that return existing values rather than actually doing work.
Therefore, the confusion added by using different names for different
types (i.e. read() for chars, getInt() for ints) isn't offset by a
corresponding increase in clarity. If we want a different name, we
should use something suggestive of the work being done, e.g.
parseInt() and parseFloat(). Otherwise, I think we should just stick
with read for consistency.

2. readString() with a prefix isn't orthogonal to find() plus
readString() without a prefix. In general, if we offer a function for
A and another function for B, we should avoid functions that do both A
and B. By offering more than one way to do the same thing, you force
people to figure out whether the two options are the same, to decide
which one to use, and to recognize both approaches when reading code.
I'd rather reduce confusion at the cost of an extra line of code.

In this case, it's even more confusing because we're offering multiple
ways to search for the prefix (with or without a terminator) and more
than one way to retrieve the string (also with and without a
terminator). But a readString() method that accepts a prefix and a
suffix covers only one of those four cases, forcing people to fall
back on separate statements for the other three. This just increases
the difficulty of distinguishing and deciding between using two
separate calls or one combined one. I'd rather avoid the confusion
and just offer one way to do it.

3. I'd like to offer methods that store data into an existing buffer
and methods that return a newly-formed String. For consistency with
the naming in Processing (although with slightly different syntax),
let's use readBytes() and readBytesUntil() to store the data into an
existing buffer (returning the number of bytes read) and readString()
and readStringUntil() to return a newly-formed String (whose length
can be queried).

What do you think?

On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
> Seems like there are three outstanding issues:
>
> 1.    Orthogonal method naming: for example, should the method be called
> readInt or getInt
> 2.    Should readString/getString have a prestring argument.
> 3.    Should readString/getString return a String or the number of bytes
> stored
>
>
> On the first point, I don’t think the functionality of getInt/getFloat
> methods etc is orthogonal with the current stream method to read a
> character. read returns the next char in the stream, getInt reads as many
> characters as required until it finds one or more ASCII digits and converts
> these to an integer. I would expect an orthogonal implementation of readInt
> to return the integer value of the next two bytes in the stream. Such a
> method could be useful for reading data packed into a binary structure. I am
> not suggesting we include this (although it would be easy to implement if
> you wanted it) but I do feel that the rather different functionality of the
> proposed getInt deserves a name that differentiates from a simple read of a
> data type.
>
> Regarding point 2, we could support both version of read/getString – one
> without the prestring and one with:
> getString( endchar, buffer, length) // all characters up to but excluding
> endchar will be copied to the buffer (if the buffer is smaller than length,
> the string will be truncated .)
> and:
> getString(prestring, endchar, buffer, length) // as above but seeks to the
> first character following prestring.
>
> There is no performance or resource overhead in the latter getString, it
> uses the find method internally - I think this is just a question of which
> is easier for the user to type and understand.
>
> Regarding the return type of readString/getString, I would be uncomfortable
> if a method was not available that returned the number of bytes collected.
> Perhaps that’s just me. Feel free to add method that returned a String if
> you feel this was also needed but I don’t feel qualified to implement that
> for the Arduino runtime environment.
>
> Michael
>
> -----Original Message----- From: Tom Igoe
> Sent: Tuesday, June 07, 2011 4:34 PM
> To: David A. Mellis
> Cc: Michael Margolis ;
> Subject: Re: [Developers] Adding parsing to Stream
>
> I don't agree about the prefix change.  Before Michael's explanation of
> getString() I might have agreed, but having tried it, I think it makes a lot
> of sense. There's a lot of value in having the prefix. For example,
>
>     result = response.getString("", "", tweetBuffer, 140);
>
> returns something very different than
>
>     result = response.getString(", tweetBuffer, 150);
>
> and I don't think the following makes anything clearer:
>
>      response.find("");
>      response.getString("
", tweetBuffer, 150);
>
> Is there something I'm misunderstanding about your argument?
>
>
> The main thing that would make things clearer to me  would be:
>
>  tweetBuffer = response.getString("", "", 140);
>
> But I understand why that's a bad idea.
>
>
> I understand your desire to use read() and write()  where possible, though I
> don't think it's necessary. I think Michael's argument about get() in this
> case is valid, but if there's consensus on read() and write() I won't
> object.
>
> I'd recommend keeping the int return type on readString() or getString().
> It's valuable to know how big long actual returned array is, vs. what you
> allocated.
>
>
>
> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>
>> Yeah, you're right...  the memory constraints on Arduino make it
>> unreasonable to first read strings and then parse them (like in
>> Processing) and it seems silly for such functionality not to be in the
>> core somewhere.
>>
>> Can we go with the names readInt() and readFloat()?
>>
>> Can we omit the prefix parameters from readString() and
>> readStringUntil() - i.e. require a preceding call to find()?  I know
>> this makes string extraction a bit more verbose, but I think it also
>> makes it more clear.  In general, I've been trying to keep the API's
>> orthogonal and simple, even if it means sometimes using more than one
>> function call instead of one call to a more complex function.
>>
>> And the setTimeout() argument should probably be in milliseconds, not
>> seconds, both for consistency with the pulseIn() functions and to
>> allow finer control.
>>
>> I'd suggest, then:
>>
>> setTimeout(ms)
>> find(target) // String or char *
>> findUntil(target, terminator) // String or char *
>> readInt() / readInt(skipchar)
>> readFloat() / readFloat(skipchar)
>> readString()
>> readStringUntil(endchar)
>> readBytes(buf, buflen)
>> readBytesUntil(endchar, buf, buflen)
>>
>> Is that okay?
>>
>> I'm still curious if people have any other requirements in terms of
>> numeric formats that they'd like readInt() or readFloat() to support.
>> For example, do you need to be able to specify the character that
>> separates the whole from the decimal part of the float?
>>
>> David
>>
>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>> wrote:
>>>
>>> I think the methods to get numeric values (getInt and getFloat) would
>>> probably be more used with Serial than find() an findUntil().
>>>
>>> I have no objection to TextFinder being included as a library but do
>>> think
>>> that users would prefer having the get functions as a stream method
>>> rather
>>> than having to explicitly instantiate the TextFinder class, as would be
>>> required if a separate library.
>>>
>>> The need to do the following in a sketch (if implemented as a library) is
>>> not onerous
>>>
>>> #include
>>> TextFinder  finder(Serial);
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = finder.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>>
>>> }
>>>
>>>
>>> but this seems simpler and clearer
>>>
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = Serial.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>> }
>>>
>>> void loop();
>>>
>>> Michael
>>>
>>> --------------------------------------------------
>>> From: "Tom Igoe" <>
>>> Sent: Sunday, June 05, 2011 8:48 PM
>>> To: "David A. Mellis" <>
>>> Cc: "Michael Margolis" <>; <>
>>> Subject: Re: [Developers] Adding parsing to Stream
>>>
>>>> I think textFinder is good for things other than web pages, but I am in
>>>> favor of a small core.  How would you feel about including TextFinder in
>>>> the
>>>> standard distribution, assuming Michael agreed? That might offer a
>>>> reasonable compromise of small core, but easy access to the functions.
>>>>
>>>> t.
>>>>
>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>
>>>>> The more I think about this, the more I feel like maybe we should only
>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>> setting the timeout).  The other functionality feels fairly specific
>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>> be supported by the Stream class itself.  That is, maybe we should
>>>>> plan to continue to have a separate TextFinder library for more
>>>>> complex parsing tasks, and only integrate the functionality that
>>>>> applicable to wide range of stream types to the Stream interface
>>>>> itself.
>>>>>
>>>>> In general, I'm trying to keep the core API small - with the
>>>>> understanding that lots of useful, real-world examples will still
>>>>> require third-party libraries.  Including extra parsing functions
>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>> that it will be inconsistent with other portions of the API.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>
>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>
>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>> reading
>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>> code
>>>>>> and realized it'd take me longer to explain with find() then
>>>>>> readStringUntil() than it would with getString().  So I prefer
>>>>>> getString().
>>>>>>
>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>> strings.
>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>> also
>>>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>>>> getInt() and int() are different things, no?
>>>>>>
>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>
>>>>>> t.
>>>>>>
>>>>>>
>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>
>>>>>>> I am open to whatever method names are most suitable but  I like
>>>>>>> names
>>>>>>> that are evocative of their functionality and 'get' naming  was
>>>>>>> chosen over
>>>>>>> read because these methods do more than just read .  I also think the
>>>>>>>  string parsing method as proposed is easier to use for getting
>>>>>>> string
>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>
>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>>>> getting a string between two tokens is  an important capability for
>>>>>>> this API
>>>>>>>  (it is for me, and most of my web parsing applications seem to use
>>>>>>> the
>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>
>>>>>>> Tom, what do you think?
>>>>>>>
>>>>>>> Michael
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>> To: Michael Margolis
>>>>>>> Cc: Tom Igoe ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>> readString()
>>>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>
>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>> string before converting it to a number.
>>>>>>>
>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>> of
>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>> buffer
>>>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>> instead.
>>>>>>>
>>>>>>> How does that sound?
>>>>>>>
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>> <> wrote:
>>>>>>>>
>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>> we
>>>>>>>> rename  the getString method as follows:
>>>>>>>>
>>>>>>>> int readString( char *pre_string, char  post_string, char *buffer,
>>>>>>>> int
>>>>>>>> length); // read into a static character buffer
>>>>>>>>
>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>
>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>> like
>>>>>>>> this:
>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>> limited
>>>>>>>> String len may cause unexpected results
>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>> ncountered  -
>>>>>>>> Warning as above
>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>> find(pre_string) and
>>>>>>>> readStringUntil(post_char)
>>>>>>>>
>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>> is
>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>> whichever
>>>>>>>> brave soul volunteers to implement the dynamic String methods.  I am
>>>>>>>> a
>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>> dynamic
>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>
>>>>>>>> Michael Margolis
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>> To: Tom Igoe
>>>>>>>> Cc: Michael Margolis ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>> like:
>>>>>>>>
>>>>>>>> if (Serial.find(""))
>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>
>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>> result if you run out of room in the buffer.  (Do you throw out
>>>>>>>> older
>>>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>> and
>>>>>>>>> it's
>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>> and
>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>> on a
>>>>>>>>> stream.  I've had some cases where I needed to switch from find()
>>>>>>>>> to
>>>>>>>>> a
>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>
>>>>>>>>> This is what I want
>>>>>>>>>
>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>> I'm
>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>> between
>>>>>>>>>
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>> t.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>
>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>
>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>> character?
>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>> value of
>>>>>>>>>>> 0?
>>>>>>>>>>
>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>> will
>>>>>>>>>> be most useful.
>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>> the
>>>>>>>>>> API
>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>> user
>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>> Arduino
>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>> defines
>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>> setDecimalPointChar() could  be added if this functionality was
>>>>>>>>>> only
>>>>>>>>>> needed
>>>>>>>>>> in this API.
>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>
>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>
>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>> else
>>>>>>>>>> regarding this API.
>>>>>>>>>>
>>>>>>>>>> Michael
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>> To: Michael Margolis
>>>>>>>>>> Cc:
>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>
>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>
>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>> we
>>>>>>>>>> should keep in mind?
>>>>>>>>>>
>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>>>> than
>>>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>> doubles.
>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>> <> wrote:
>>>>>>>>>>>
>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>> finding and
>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>> by
>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>> for
>>>>>>>>>>> the
>>>>>>>>>>> incoming data.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>>>> (with
>>>>>>>>>>> help
>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>> implements
>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>> Ethernet
>>>>>>>>>>> are
>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>> API,
>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> setTimeout()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>>>> character
>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>> value
>>>>>>>>>>> is
>>>>>>>>>>> used
>>>>>>>>>>> by all of the other parsing  methods and could be useful for
>>>>>>>>>>> other
>>>>>>>>>>> stream
>>>>>>>>>>> functions.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>
>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> find()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Reads data from the stream until the target string
>>>>>>>>>>> is
>>>>>>>>>>> found
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>> to
>>>>>>>>>>> search
>>>>>>>>>>> for
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>> including
>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>> the
>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>>>
>>>>>>>>>>>  // here if the string "GET /" is found in the stream
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> findUntil()
>>>>>>>>>>>
>>>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>>>> found.
>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>> token.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>> for,
>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>> the
>>>>>>>>>>> search
>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>
>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>
>>>>>>>>>>>  // here if “pin” is found in the current line
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // stream buffer is at the beginning of the next line
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>> implemented
>>>>>>>>>>> if
>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>> pointer
>>>>>>>>>>> to a
>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>> functionally
>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>> target
>>>>>>>>>>> and
>>>>>>>>>>> terminate strings.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Returns the first valid (long) integer value from
>>>>>>>>>>> the
>>>>>>>>>>> current
>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>> minus
>>>>>>>>>>> sign)
>>>>>>>>>>> are
>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>> not
>>>>>>>>>>> a
>>>>>>>>>>> digit
>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>> integer
>>>>>>>>>>> values
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>>>
>>>>>>>>>>> {
>>>>>>>>>>>
>>>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>
>>>>>>>>>>>  Serial.println(value);
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getString()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>>>> stores
>>>>>>>>>>> into
>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>> length.
>>>>>>>>>>> The
>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>> preString
>>>>>>>>>>> that
>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>> string,
>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>> the
>>>>>>>>>>> first
>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>> buffer.
>>>>>>>>>>>
>>>>>>>>>>> Returns:  Returns the number of characters placed in the buffer
>>>>>>>>>>> (0
>>>>>>>>>>> means
>>>>>>>>>>> no
>>>>>>>>>>> valid data found)
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>> terminating null
>>>>>>>>>>>
>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>
>>>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>
>>>>>>>>>>>  {
>>>>>>>>>>>
>>>>>>>>>>>    Serial.print("found ");
>>>>>>>>>>>
>>>>>>>>>>>    Serial.println(buffer);
>>>>>>>>>>>
>>>>>>>>>>>  }
>>>>>>>>>>>
>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>
>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>> from
>>>>>>>>>>> the
>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----
>>>>>>>>>>>
>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>> suggest
>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>
>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>> Stream.cpp
>>>>>>>>>>> to
>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>>
>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #6  
09-06-2011 11:03 AM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I don't agree about the prefix change. Before Michael's explanation of getString() I might have agreed, but having tried it, I think it makes a lot of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I don't think it's necessary. I think Michael's argument about get() in this case is valid, but if there's consensus on read() and write() I won't object.

I'd recommend keeping the int return type on readString() or getString(). It's valuable to know how big long actual returned array is, vs. what you allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do think
>> that users would prefer having the get functions as a stream method rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>>> through Dave's proposal, I tried to think through how to explain the code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>>> And as Michael points out getInt() does more than just the casting, it also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like names
>>>>>> that are evocative of their functionality and 'get' naming was chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for this API
>>>>>> (it is for me, and most of my web parsing applications seem to use the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find() to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Seems like there are three outstanding issues:

1. Orthogonal method naming: for example, should the method be called
readInt or getInt
2. Should readString/getString have a prestring argument.
3. Should readString/getString return a String or the number of bytes
stored


On the first point, I don’t think the functionality of getInt/getFloat
methods etc is orthogonal with the current stream method to read a
character. read returns the next char in the stream, getInt reads as many
characters as required until it finds one or more ASCII digits and converts
these to an integer. I would expect an orthogonal implementation of readInt
to return the integer value of the next two bytes in the stream. Such a
method could be useful for reading data packed into a binary structure. I am
not suggesting we include this (although it would be easy to implement if
you wanted it) but I do feel that the rather different functionality of the
proposed getInt deserves a name that differentiates from a simple read of a
data type.

Regarding point 2, we could support both version of read/getString – one
without the prestring and one with:
getString( endchar, buffer, length) // all characters up to but excluding
endchar will be copied to the buffer (if the buffer is smaller than length,
the string will be truncated .)
and:
getString(prestring, endchar, buffer, length) // as above but seeks to the
first character following prestring.

There is no performance or resource overhead in the latter getString, it
uses the find method internally - I think this is just a question of which
is easier for the user to type and understand.

Regarding the return type of readString/getString, I would be uncomfortable
if a method was not available that returned the number of bytes collected.
Perhaps that’s just me. Feel free to add method that returned a String if
you feel this was also needed but I don’t feel qualified to implement that
for the Arduino runtime environment.

Michael

-----Original Message-----
From: Tom Igoe
Sent: Tuesday, June 07, 2011 4:34 PM
To: David A. Mellis
Cc: Michael Margolis ;
Subject: Re: [Developers] Adding parsing to Stream

I don't agree about the prefix change. Before Michael's explanation of
getString() I might have agreed, but having tried it, I think it makes a lot
of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I
don't think it's necessary. I think Michael's argument about get() in this
case is valid, but if there's consensus on read() and write() I won't
object.

I'd recommend keeping the int return type on readString() or getString().
It's valuable to know how big long actual returned array is, vs. what you
allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do
>> think
>> that users would prefer having the get functions as a stream method
>> rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the
>> Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the
>> Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in
>>> the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading
>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>> code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>> getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings.
>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>> also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names
>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>> chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting
>>>>>> string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for
>>>>>> this API
>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>> the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>> of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>> we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>> int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>> is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>> a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>> and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>> to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>> the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>> only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>> API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>> is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>> to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>> the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>> not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>> (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
To take your issues in turn:

1. getInt() / getFloat() sound like simple accessors, i.e. methods
that return existing values rather than actually doing work.
Therefore, the confusion added by using different names for different
types (i.e. read() for chars, getInt() for ints) isn't offset by a
corresponding increase in clarity. If we want a different name, we
should use something suggestive of the work being done, e.g.
parseInt() and parseFloat(). Otherwise, I think we should just stick
with read for consistency.

2. readString() with a prefix isn't orthogonal to find() plus
readString() without a prefix. In general, if we offer a function for
A and another function for B, we should avoid functions that do both A
and B. By offering more than one way to do the same thing, you force
people to figure out whether the two options are the same, to decide
which one to use, and to recognize both approaches when reading code.
I'd rather reduce confusion at the cost of an extra line of code.

In this case, it's even more confusing because we're offering multiple
ways to search for the prefix (with or without a terminator) and more
than one way to retrieve the string (also with and without a
terminator). But a readString() method that accepts a prefix and a
suffix covers only one of those four cases, forcing people to fall
back on separate statements for the other three. This just increases
the difficulty of distinguishing and deciding between using two
separate calls or one combined one. I'd rather avoid the confusion
and just offer one way to do it.

3. I'd like to offer methods that store data into an existing buffer
and methods that return a newly-formed String. For consistency with
the naming in Processing (although with slightly different syntax),
let's use readBytes() and readBytesUntil() to store the data into an
existing buffer (returning the number of bytes read) and readString()
and readStringUntil() to return a newly-formed String (whose length
can be queried).

What do you think?

On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
> Seems like there are three outstanding issues:
>
> 1.    Orthogonal method naming: for example, should the method be called
> readInt or getInt
> 2.    Should readString/getString have a prestring argument.
> 3.    Should readString/getString return a String or the number of bytes
> stored
>
>
> On the first point, I don’t think the functionality of getInt/getFloat
> methods etc is orthogonal with the current stream method to read a
> character. read returns the next char in the stream, getInt reads as many
> characters as required until it finds one or more ASCII digits and converts
> these to an integer. I would expect an orthogonal implementation of readInt
> to return the integer value of the next two bytes in the stream. Such a
> method could be useful for reading data packed into a binary structure. I am
> not suggesting we include this (although it would be easy to implement if
> you wanted it) but I do feel that the rather different functionality of the
> proposed getInt deserves a name that differentiates from a simple read of a
> data type.
>
> Regarding point 2, we could support both version of read/getString – one
> without the prestring and one with:
> getString( endchar, buffer, length) // all characters up to but excluding
> endchar will be copied to the buffer (if the buffer is smaller than length,
> the string will be truncated .)
> and:
> getString(prestring, endchar, buffer, length) // as above but seeks to the
> first character following prestring.
>
> There is no performance or resource overhead in the latter getString, it
> uses the find method internally - I think this is just a question of which
> is easier for the user to type and understand.
>
> Regarding the return type of readString/getString, I would be uncomfortable
> if a method was not available that returned the number of bytes collected.
> Perhaps that’s just me. Feel free to add method that returned a String if
> you feel this was also needed but I don’t feel qualified to implement that
> for the Arduino runtime environment.
>
> Michael
>
> -----Original Message----- From: Tom Igoe
> Sent: Tuesday, June 07, 2011 4:34 PM
> To: David A. Mellis
> Cc: Michael Margolis ;
> Subject: Re: [Developers] Adding parsing to Stream
>
> I don't agree about the prefix change.  Before Michael's explanation of
> getString() I might have agreed, but having tried it, I think it makes a lot
> of sense. There's a lot of value in having the prefix. For example,
>
>     result = response.getString("", "", tweetBuffer, 140);
>
> returns something very different than
>
>     result = response.getString(", tweetBuffer, 150);
>
> and I don't think the following makes anything clearer:
>
>      response.find("");
>      response.getString("
", tweetBuffer, 150);
>
> Is there something I'm misunderstanding about your argument?
>
>
> The main thing that would make things clearer to me  would be:
>
>  tweetBuffer = response.getString("", "", 140);
>
> But I understand why that's a bad idea.
>
>
> I understand your desire to use read() and write()  where possible, though I
> don't think it's necessary. I think Michael's argument about get() in this
> case is valid, but if there's consensus on read() and write() I won't
> object.
>
> I'd recommend keeping the int return type on readString() or getString().
> It's valuable to know how big long actual returned array is, vs. what you
> allocated.
>
>
>
> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>
>> Yeah, you're right...  the memory constraints on Arduino make it
>> unreasonable to first read strings and then parse them (like in
>> Processing) and it seems silly for such functionality not to be in the
>> core somewhere.
>>
>> Can we go with the names readInt() and readFloat()?
>>
>> Can we omit the prefix parameters from readString() and
>> readStringUntil() - i.e. require a preceding call to find()?  I know
>> this makes string extraction a bit more verbose, but I think it also
>> makes it more clear.  In general, I've been trying to keep the API's
>> orthogonal and simple, even if it means sometimes using more than one
>> function call instead of one call to a more complex function.
>>
>> And the setTimeout() argument should probably be in milliseconds, not
>> seconds, both for consistency with the pulseIn() functions and to
>> allow finer control.
>>
>> I'd suggest, then:
>>
>> setTimeout(ms)
>> find(target) // String or char *
>> findUntil(target, terminator) // String or char *
>> readInt() / readInt(skipchar)
>> readFloat() / readFloat(skipchar)
>> readString()
>> readStringUntil(endchar)
>> readBytes(buf, buflen)
>> readBytesUntil(endchar, buf, buflen)
>>
>> Is that okay?
>>
>> I'm still curious if people have any other requirements in terms of
>> numeric formats that they'd like readInt() or readFloat() to support.
>> For example, do you need to be able to specify the character that
>> separates the whole from the decimal part of the float?
>>
>> David
>>
>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>> wrote:
>>>
>>> I think the methods to get numeric values (getInt and getFloat) would
>>> probably be more used with Serial than find() an findUntil().
>>>
>>> I have no objection to TextFinder being included as a library but do
>>> think
>>> that users would prefer having the get functions as a stream method
>>> rather
>>> than having to explicitly instantiate the TextFinder class, as would be
>>> required if a separate library.
>>>
>>> The need to do the following in a sketch (if implemented as a library) is
>>> not onerous
>>>
>>> #include
>>> TextFinder  finder(Serial);
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = finder.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>>
>>> }
>>>
>>>
>>> but this seems simpler and clearer
>>>
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = Serial.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>> }
>>>
>>> void loop();
>>>
>>> Michael
>>>
>>> --------------------------------------------------
>>> From: "Tom Igoe" <>
>>> Sent: Sunday, June 05, 2011 8:48 PM
>>> To: "David A. Mellis" <>
>>> Cc: "Michael Margolis" <>; <>
>>> Subject: Re: [Developers] Adding parsing to Stream
>>>
>>>> I think textFinder is good for things other than web pages, but I am in
>>>> favor of a small core.  How would you feel about including TextFinder in
>>>> the
>>>> standard distribution, assuming Michael agreed? That might offer a
>>>> reasonable compromise of small core, but easy access to the functions.
>>>>
>>>> t.
>>>>
>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>
>>>>> The more I think about this, the more I feel like maybe we should only
>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>> setting the timeout).  The other functionality feels fairly specific
>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>> be supported by the Stream class itself.  That is, maybe we should
>>>>> plan to continue to have a separate TextFinder library for more
>>>>> complex parsing tasks, and only integrate the functionality that
>>>>> applicable to wide range of stream types to the Stream interface
>>>>> itself.
>>>>>
>>>>> In general, I'm trying to keep the core API small - with the
>>>>> understanding that lots of useful, real-world examples will still
>>>>> require third-party libraries.  Including extra parsing functions
>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>> that it will be inconsistent with other portions of the API.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>
>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>
>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>> reading
>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>> code
>>>>>> and realized it'd take me longer to explain with find() then
>>>>>> readStringUntil() than it would with getString().  So I prefer
>>>>>> getString().
>>>>>>
>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>> strings.
>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>> also
>>>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>>>> getInt() and int() are different things, no?
>>>>>>
>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>
>>>>>> t.
>>>>>>
>>>>>>
>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>
>>>>>>> I am open to whatever method names are most suitable but  I like
>>>>>>> names
>>>>>>> that are evocative of their functionality and 'get' naming  was
>>>>>>> chosen over
>>>>>>> read because these methods do more than just read .  I also think the
>>>>>>>  string parsing method as proposed is easier to use for getting
>>>>>>> string
>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>
>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>>>> getting a string between two tokens is  an important capability for
>>>>>>> this API
>>>>>>>  (it is for me, and most of my web parsing applications seem to use
>>>>>>> the
>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>
>>>>>>> Tom, what do you think?
>>>>>>>
>>>>>>> Michael
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>> To: Michael Margolis
>>>>>>> Cc: Tom Igoe ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>> readString()
>>>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>
>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>> string before converting it to a number.
>>>>>>>
>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>> of
>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>> buffer
>>>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>> instead.
>>>>>>>
>>>>>>> How does that sound?
>>>>>>>
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>> <> wrote:
>>>>>>>>
>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>> we
>>>>>>>> rename  the getString method as follows:
>>>>>>>>
>>>>>>>> int readString( char *pre_string, char  post_string, char *buffer,
>>>>>>>> int
>>>>>>>> length); // read into a static character buffer
>>>>>>>>
>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>
>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>> like
>>>>>>>> this:
>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>> limited
>>>>>>>> String len may cause unexpected results
>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>> ncountered  -
>>>>>>>> Warning as above
>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>> find(pre_string) and
>>>>>>>> readStringUntil(post_char)
>>>>>>>>
>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>> is
>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>> whichever
>>>>>>>> brave soul volunteers to implement the dynamic String methods.  I am
>>>>>>>> a
>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>> dynamic
>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>
>>>>>>>> Michael Margolis
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>> To: Tom Igoe
>>>>>>>> Cc: Michael Margolis ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>> like:
>>>>>>>>
>>>>>>>> if (Serial.find(""))
>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>
>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>> result if you run out of room in the buffer.  (Do you throw out
>>>>>>>> older
>>>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>> and
>>>>>>>>> it's
>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>> and
>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>> on a
>>>>>>>>> stream.  I've had some cases where I needed to switch from find()
>>>>>>>>> to
>>>>>>>>> a
>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>
>>>>>>>>> This is what I want
>>>>>>>>>
>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>> I'm
>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>> between
>>>>>>>>>
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>> t.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>
>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>
>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>> character?
>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>> value of
>>>>>>>>>>> 0?
>>>>>>>>>>
>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>> will
>>>>>>>>>> be most useful.
>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>> the
>>>>>>>>>> API
>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>> user
>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>> Arduino
>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>> defines
>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>> setDecimalPointChar() could  be added if this functionality was
>>>>>>>>>> only
>>>>>>>>>> needed
>>>>>>>>>> in this API.
>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>
>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>
>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>> else
>>>>>>>>>> regarding this API.
>>>>>>>>>>
>>>>>>>>>> Michael
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>> To: Michael Margolis
>>>>>>>>>> Cc:
>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>
>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>
>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>> we
>>>>>>>>>> should keep in mind?
>>>>>>>>>>
>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>>>> than
>>>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>> doubles.
>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>> <> wrote:
>>>>>>>>>>>
>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>> finding and
>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>> by
>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>> for
>>>>>>>>>>> the
>>>>>>>>>>> incoming data.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>>>> (with
>>>>>>>>>>> help
>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>> implements
>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>> Ethernet
>>>>>>>>>>> are
>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>> API,
>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> setTimeout()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>>>> character
>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>> value
>>>>>>>>>>> is
>>>>>>>>>>> used
>>>>>>>>>>> by all of the other parsing  methods and could be useful for
>>>>>>>>>>> other
>>>>>>>>>>> stream
>>>>>>>>>>> functions.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>
>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> find()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Reads data from the stream until the target string
>>>>>>>>>>> is
>>>>>>>>>>> found
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>> to
>>>>>>>>>>> search
>>>>>>>>>>> for
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>> including
>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>> the
>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>>>
>>>>>>>>>>>  // here if the string "GET /" is found in the stream
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> findUntil()
>>>>>>>>>>>
>>>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>>>> found.
>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>> token.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>> for,
>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>> the
>>>>>>>>>>> search
>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>
>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>
>>>>>>>>>>>  // here if “pin” is found in the current line
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // stream buffer is at the beginning of the next line
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>> implemented
>>>>>>>>>>> if
>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>> pointer
>>>>>>>>>>> to a
>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>> functionally
>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>> target
>>>>>>>>>>> and
>>>>>>>>>>> terminate strings.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Returns the first valid (long) integer value from
>>>>>>>>>>> the
>>>>>>>>>>> current
>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>> minus
>>>>>>>>>>> sign)
>>>>>>>>>>> are
>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>> not
>>>>>>>>>>> a
>>>>>>>>>>> digit
>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>> integer
>>>>>>>>>>> values
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>>>
>>>>>>>>>>> {
>>>>>>>>>>>
>>>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>
>>>>>>>>>>>  Serial.println(value);
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getString()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>>>> stores
>>>>>>>>>>> into
>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>> length.
>>>>>>>>>>> The
>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>> preString
>>>>>>>>>>> that
>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>> string,
>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>> the
>>>>>>>>>>> first
>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>> buffer.
>>>>>>>>>>>
>>>>>>>>>>> Returns:  Returns the number of characters placed in the buffer
>>>>>>>>>>> (0
>>>>>>>>>>> means
>>>>>>>>>>> no
>>>>>>>>>>> valid data found)
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>> terminating null
>>>>>>>>>>>
>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>
>>>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>
>>>>>>>>>>>  {
>>>>>>>>>>>
>>>>>>>>>>>    Serial.print("found ");
>>>>>>>>>>>
>>>>>>>>>>>    Serial.println(buffer);
>>>>>>>>>>>
>>>>>>>>>>>  }
>>>>>>>>>>>
>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>
>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>> from
>>>>>>>>>>> the
>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----
>>>>>>>>>>>
>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>> suggest
>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>
>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>> Stream.cpp
>>>>>>>>>>> to
>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>>
>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I agree with 3). I think you are wrong on 1) and 2).

t.

On Jun 8, 2011, at 10:53 PM, David A. Mellis wrote:

> To take your issues in turn:
>
> 1. getInt() / getFloat() sound like simple accessors, i.e. methods
> that return existing values rather than actually doing work.
> Therefore, the confusion added by using different names for different
> types (i.e. read() for chars, getInt() for ints) isn't offset by a
> corresponding increase in clarity. If we want a different name, we
> should use something suggestive of the work being done, e.g.
> parseInt() and parseFloat(). Otherwise, I think we should just stick
> with read for consistency.
>
> 2. readString() with a prefix isn't orthogonal to find() plus
> readString() without a prefix. In general, if we offer a function for
> A and another function for B, we should avoid functions that do both A
> and B. By offering more than one way to do the same thing, you force
> people to figure out whether the two options are the same, to decide
> which one to use, and to recognize both approaches when reading code.
> I'd rather reduce confusion at the cost of an extra line of code.
>
> In this case, it's even more confusing because we're offering multiple
> ways to search for the prefix (with or without a terminator) and more
> than one way to retrieve the string (also with and without a
> terminator). But a readString() method that accepts a prefix and a
> suffix covers only one of those four cases, forcing people to fall
> back on separate statements for the other three. This just increases
> the difficulty of distinguishing and deciding between using two
> separate calls or one combined one. I'd rather avoid the confusion
> and just offer one way to do it.
>
> 3. I'd like to offer methods that store data into an existing buffer
> and methods that return a newly-formed String. For consistency with
> the naming in Processing (although with slightly different syntax),
> let's use readBytes() and readBytesUntil() to store the data into an
> existing buffer (returning the number of bytes read) and readString()
> and readStringUntil() to return a newly-formed String (whose length
> can be queried).
>
> What do you think?
>
> On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
>> Seems like there are three outstanding issues:
>>
>> 1. Orthogonal method naming: for example, should the method be called
>> readInt or getInt
>> 2. Should readString/getString have a prestring argument.
>> 3. Should readString/getString return a String or the number of bytes
>> stored
>>
>>
>> On the first point, I don’t think the functionality of getInt/getFloat
>> methods etc is orthogonal with the current stream method to read a
>> character. read returns the next char in the stream, getInt reads as many
>> characters as required until it finds one or more ASCII digits and converts
>> these to an integer. I would expect an orthogonal implementation of readInt
>> to return the integer value of the next two bytes in the stream. Such a
>> method could be useful for reading data packed into a binary structure. I am
>> not suggesting we include this (although it would be easy to implement if
>> you wanted it) but I do feel that the rather different functionality of the
>> proposed getInt deserves a name that differentiates from a simple read of a
>> data type.
>>
>> Regarding point 2, we could support both version of read/getString – one
>> without the prestring and one with:
>> getString( endchar, buffer, length) // all characters up to but excluding
>> endchar will be copied to the buffer (if the buffer is smaller than length,
>> the string will be truncated .)
>> and:
>> getString(prestring, endchar, buffer, length) // as above but seeks to the
>> first character following prestring.
>>
>> There is no performance or resource overhead in the latter getString, it
>> uses the find method internally - I think this is just a question of which
>> is easier for the user to type and understand.
>>
>> Regarding the return type of readString/getString, I would be uncomfortable
>> if a method was not available that returned the number of bytes collected.
>> Perhaps that’s just me. Feel free to add method that returned a String if
>> you feel this was also needed but I don’t feel qualified to implement that
>> for the Arduino runtime environment.
>>
>> Michael
>>
>> -----Original Message----- From: Tom Igoe
>> Sent: Tuesday, June 07, 2011 4:34 PM
>> To: David A. Mellis
>> Cc: Michael Margolis ;
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>> I don't agree about the prefix change. Before Michael's explanation of
>> getString() I might have agreed, but having tried it, I think it makes a lot
>> of sense. There's a lot of value in having the prefix. For example,
>>
>> result = response.getString("", "", tweetBuffer, 140);
>>
>> returns something very different than
>>
>> result = response.getString(", tweetBuffer, 150);
>>
>> and I don't think the following makes anything clearer:
>>
>> response.find("");
>> response.getString("
", tweetBuffer, 150);
>>
>> Is there something I'm misunderstanding about your argument?
>>
>>
>> The main thing that would make things clearer to me would be:
>>
>> tweetBuffer = response.getString("", "", 140);
>>
>> But I understand why that's a bad idea.
>>
>>
>> I understand your desire to use read() and write() where possible, though I
>> don't think it's necessary. I think Michael's argument about get() in this
>> case is valid, but if there's consensus on read() and write() I won't
>> object.
>>
>> I'd recommend keeping the int return type on readString() or getString().
>> It's valuable to know how big long actual returned array is, vs. what you
>> allocated.
>>
>>
>>
>> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>>
>>> Yeah, you're right... the memory constraints on Arduino make it
>>> unreasonable to first read strings and then parse them (like in
>>> Processing) and it seems silly for such functionality not to be in the
>>> core somewhere.
>>>
>>> Can we go with the names readInt() and readFloat()?
>>>
>>> Can we omit the prefix parameters from readString() and
>>> readStringUntil() - i.e. require a preceding call to find()? I know
>>> this makes string extraction a bit more verbose, but I think it also
>>> makes it more clear. In general, I've been trying to keep the API's
>>> orthogonal and simple, even if it means sometimes using more than one
>>> function call instead of one call to a more complex function.
>>>
>>> And the setTimeout() argument should probably be in milliseconds, not
>>> seconds, both for consistency with the pulseIn() functions and to
>>> allow finer control.
>>>
>>> I'd suggest, then:
>>>
>>> setTimeout(ms)
>>> find(target) // String or char *
>>> findUntil(target, terminator) // String or char *
>>> readInt() / readInt(skipchar)
>>> readFloat() / readFloat(skipchar)
>>> readString()
>>> readStringUntil(endchar)
>>> readBytes(buf, buflen)
>>> readBytesUntil(endchar, buf, buflen)
>>>
>>> Is that okay?
>>>
>>> I'm still curious if people have any other requirements in terms of
>>> numeric formats that they'd like readInt() or readFloat() to support.
>>> For example, do you need to be able to specify the character that
>>> separates the whole from the decimal part of the float?
>>>
>>> David
>>>
>>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>>> wrote:
>>>>
>>>> I think the methods to get numeric values (getInt and getFloat) would
>>>> probably be more used with Serial than find() an findUntil().
>>>>
>>>> I have no objection to TextFinder being included as a library but do
>>>> think
>>>> that users would prefer having the get functions as a stream method
>>>> rather
>>>> than having to explicitly instantiate the TextFinder class, as would be
>>>> required if a separate library.
>>>>
>>>> The need to do the following in a sketch (if implemented as a library) is
>>>> not onerous
>>>>
>>>> #include
>>>> TextFinder finder(Serial);
>>>> void setup()
>>>> {
>>>> Serial.begin(9600);
>>>> int val = finder.getInt(); // return the next integer value on the
>>>> Serial
>>>> stream
>>>>
>>>> }
>>>>
>>>>
>>>> but this seems simpler and clearer
>>>>
>>>> void setup()
>>>> {
>>>> Serial.begin(9600);
>>>> int val = Serial.getInt(); // return the next integer value on the
>>>> Serial
>>>> stream
>>>> }
>>>>
>>>> void loop();
>>>>
>>>> Michael
>>>>
>>>> --------------------------------------------------
>>>> From: "Tom Igoe" <>
>>>> Sent: Sunday, June 05, 2011 8:48 PM
>>>> To: "David A. Mellis" <>
>>>> Cc: "Michael Margolis" <>; <>
>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>
>>>>> I think textFinder is good for things other than web pages, but I am in
>>>>> favor of a small core. How would you feel about including TextFinder in
>>>>> the
>>>>> standard distribution, assuming Michael agreed? That might offer a
>>>>> reasonable compromise of small core, but easy access to the functions.
>>>>>
>>>>> t.
>>>>>
>>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>>
>>>>>> The more I think about this, the more I feel like maybe we should only
>>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>>> setting the timeout). The other functionality feels fairly specific
>>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>>> be supported by the Stream class itself. That is, maybe we should
>>>>>> plan to continue to have a separate TextFinder library for more
>>>>>> complex parsing tasks, and only integrate the functionality that
>>>>>> applicable to wide range of stream types to the Stream interface
>>>>>> itself.
>>>>>>
>>>>>> In general, I'm trying to keep the core API small - with the
>>>>>> understanding that lots of useful, real-world examples will still
>>>>>> require third-party libraries. Including extra parsing functions
>>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>>> that it will be inconsistent with other portions of the API.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>>
>>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>>> reading
>>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>>> code
>>>>>>> and realized it'd take me longer to explain with find() then
>>>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>>>> getString().
>>>>>>>
>>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>>> strings.
>>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>>> also
>>>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>>>> getInt() and int() are different things, no?
>>>>>>>
>>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> I am open to whatever method names are most suitable but I like
>>>>>>>> names
>>>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>>>> chosen over
>>>>>>>> read because these methods do more than just read . I also think the
>>>>>>>> string parsing method as proposed is easier to use for getting
>>>>>>>> string
>>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>>
>>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>>>> getting a string between two tokens is an important capability for
>>>>>>>> this API
>>>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>>>> the
>>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>>
>>>>>>>> Tom, what do you think?
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc: Tom Igoe ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>>> readString()
>>>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>>
>>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>>> string before converting it to a number.
>>>>>>>>
>>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>>> of
>>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>>> buffer
>>>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>>> instead.
>>>>>>>>
>>>>>>>> How does that sound?
>>>>>>>>
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>>> we
>>>>>>>>> rename the getString method as follows:
>>>>>>>>>
>>>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>>>> int
>>>>>>>>> length); // read into a static character buffer
>>>>>>>>>
>>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>>
>>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>>> like
>>>>>>>>> this:
>>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>>> limited
>>>>>>>>> String len may cause unexpected results
>>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>>> ncountered -
>>>>>>>>> Warning as above
>>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>>> find(pre_string) and
>>>>>>>>> readStringUntil(post_char)
>>>>>>>>>
>>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>>> is
>>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>>> whichever
>>>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>>>> a
>>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>>> dynamic
>>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>>> To: Tom Igoe
>>>>>>>>> Cc: Michael Margolis ;
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>>> like:
>>>>>>>>>
>>>>>>>>> if (Serial.find(""))
>>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>>
>>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>>>> older
>>>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>>> and
>>>>>>>>>> it's
>>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>>> and
>>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>>> on a
>>>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>>>> to
>>>>>>>>>> a
>>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>>
>>>>>>>>>> This is what I want
>>>>>>>>>>
>>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>>> I'm
>>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>>> between
>>>>>>>>>>
>>>>>>>>>> and
>>>>>>>>>>
>>>>>>>>>> t.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>>
>>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>>
>>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>>> character?
>>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>>> value of
>>>>>>>>>>>> 0?
>>>>>>>>>>>
>>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>>> will
>>>>>>>>>>> be most useful.
>>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>>> the
>>>>>>>>>>> API
>>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>>
>>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>>> supporting
>>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>>
>>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>>> user
>>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>>> Arduino
>>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>>> defines
>>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>>>> only
>>>>>>>>>>> needed
>>>>>>>>>>> in this API.
>>>>>>>>>>>
>>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>>
>>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>>
>>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>>> else
>>>>>>>>>>> regarding this API.
>>>>>>>>>>>
>>>>>>>>>>> Michael
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>>> To: Michael Margolis
>>>>>>>>>>> Cc:
>>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>>
>>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>>
>>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>>> we
>>>>>>>>>>> should keep in mind?
>>>>>>>>>>>
>>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>>>> than
>>>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>>> doubles.
>>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>>
>>>>>>>>>>> David
>>>>>>>>>>>
>>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>>> <> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>>> finding and
>>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>>> by
>>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>>> for
>>>>>>>>>>>> the
>>>>>>>>>>>> incoming data.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>>>> (with
>>>>>>>>>>>> help
>>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>>> implements
>>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>>> Ethernet
>>>>>>>>>>>> are
>>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>>> API,
>>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> setTimeout()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>>>> character
>>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>>> value
>>>>>>>>>>>> is
>>>>>>>>>>>> used
>>>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>>>> other
>>>>>>>>>>>> stream
>>>>>>>>>>>> functions.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> find()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>>>> is
>>>>>>>>>>>> found
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>>> to
>>>>>>>>>>>> search
>>>>>>>>>>>> for
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>>> including
>>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>>> the
>>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>>>
>>>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>>>
>>>>>>>>>>>> else
>>>>>>>>>>>>
>>>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> findUntil()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>>>> found.
>>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>>> token.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>>> for,
>>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>>> the
>>>>>>>>>>>> search
>>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>>
>>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>>
>>>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>>>
>>>>>>>>>>>> else
>>>>>>>>>>>>
>>>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>>> implemented
>>>>>>>>>>>> if
>>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>>> pointer
>>>>>>>>>>>> to a
>>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>>> functionally
>>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>>> target
>>>>>>>>>>>> and
>>>>>>>>>>>> terminate strings.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getValue()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>>>> the
>>>>>>>>>>>> current
>>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>>> minus
>>>>>>>>>>>> sign)
>>>>>>>>>>>> are
>>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>>> not
>>>>>>>>>>>> a
>>>>>>>>>>>> digit
>>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: none
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>>> integer
>>>>>>>>>>>> values
>>>>>>>>>>>>
>>>>>>>>>>>> int value;
>>>>>>>>>>>>
>>>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>>>
>>>>>>>>>>>> {
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value);
>>>>>>>>>>>>
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>>> allows
>>>>>>>>>>>> format
>>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> int value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getFloat()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: none
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> float value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>>> allows
>>>>>>>>>>>> format
>>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> float value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getString()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>>>> stores
>>>>>>>>>>>> into
>>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>>> length.
>>>>>>>>>>>> The
>>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>>> preString
>>>>>>>>>>>> that
>>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>>> string,
>>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>>> the
>>>>>>>>>>>> first
>>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>>> buffer.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>>>> (0
>>>>>>>>>>>> means
>>>>>>>>>>>> no
>>>>>>>>>>>> valid data found)
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>>> terminating null
>>>>>>>>>>>>
>>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>>
>>>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>>
>>>>>>>>>>>> {
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>>>
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>>
>>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>>> from
>>>>>>>>>>>> the
>>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> -----
>>>>>>>>>>>>
>>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>>> suggest
>>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>>
>>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>>> Stream.cpp
>>>>>>>>>>>> to
>>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>>
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>>
>>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #7  
09-06-2011 11:46 AM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I don't agree about the prefix change. Before Michael's explanation of getString() I might have agreed, but having tried it, I think it makes a lot of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I don't think it's necessary. I think Michael's argument about get() in this case is valid, but if there's consensus on read() and write() I won't object.

I'd recommend keeping the int return type on readString() or getString(). It's valuable to know how big long actual returned array is, vs. what you allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do think
>> that users would prefer having the get functions as a stream method rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>>> through Dave's proposal, I tried to think through how to explain the code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>>> And as Michael points out getInt() does more than just the casting, it also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like names
>>>>>> that are evocative of their functionality and 'get' naming was chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for this API
>>>>>> (it is for me, and most of my web parsing applications seem to use the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find() to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Seems like there are three outstanding issues:

1. Orthogonal method naming: for example, should the method be called
readInt or getInt
2. Should readString/getString have a prestring argument.
3. Should readString/getString return a String or the number of bytes
stored


On the first point, I don’t think the functionality of getInt/getFloat
methods etc is orthogonal with the current stream method to read a
character. read returns the next char in the stream, getInt reads as many
characters as required until it finds one or more ASCII digits and converts
these to an integer. I would expect an orthogonal implementation of readInt
to return the integer value of the next two bytes in the stream. Such a
method could be useful for reading data packed into a binary structure. I am
not suggesting we include this (although it would be easy to implement if
you wanted it) but I do feel that the rather different functionality of the
proposed getInt deserves a name that differentiates from a simple read of a
data type.

Regarding point 2, we could support both version of read/getString – one
without the prestring and one with:
getString( endchar, buffer, length) // all characters up to but excluding
endchar will be copied to the buffer (if the buffer is smaller than length,
the string will be truncated .)
and:
getString(prestring, endchar, buffer, length) // as above but seeks to the
first character following prestring.

There is no performance or resource overhead in the latter getString, it
uses the find method internally - I think this is just a question of which
is easier for the user to type and understand.

Regarding the return type of readString/getString, I would be uncomfortable
if a method was not available that returned the number of bytes collected.
Perhaps that’s just me. Feel free to add method that returned a String if
you feel this was also needed but I don’t feel qualified to implement that
for the Arduino runtime environment.

Michael

-----Original Message-----
From: Tom Igoe
Sent: Tuesday, June 07, 2011 4:34 PM
To: David A. Mellis
Cc: Michael Margolis ;
Subject: Re: [Developers] Adding parsing to Stream

I don't agree about the prefix change. Before Michael's explanation of
getString() I might have agreed, but having tried it, I think it makes a lot
of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I
don't think it's necessary. I think Michael's argument about get() in this
case is valid, but if there's consensus on read() and write() I won't
object.

I'd recommend keeping the int return type on readString() or getString().
It's valuable to know how big long actual returned array is, vs. what you
allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do
>> think
>> that users would prefer having the get functions as a stream method
>> rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the
>> Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the
>> Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in
>>> the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading
>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>> code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>> getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings.
>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>> also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names
>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>> chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting
>>>>>> string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for
>>>>>> this API
>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>> the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>> of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>> we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>> int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>> is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>> a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>> and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>> to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>> the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>> only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>> API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>> is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>> to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>> the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>> not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>> (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
To take your issues in turn:

1. getInt() / getFloat() sound like simple accessors, i.e. methods
that return existing values rather than actually doing work.
Therefore, the confusion added by using different names for different
types (i.e. read() for chars, getInt() for ints) isn't offset by a
corresponding increase in clarity. If we want a different name, we
should use something suggestive of the work being done, e.g.
parseInt() and parseFloat(). Otherwise, I think we should just stick
with read for consistency.

2. readString() with a prefix isn't orthogonal to find() plus
readString() without a prefix. In general, if we offer a function for
A and another function for B, we should avoid functions that do both A
and B. By offering more than one way to do the same thing, you force
people to figure out whether the two options are the same, to decide
which one to use, and to recognize both approaches when reading code.
I'd rather reduce confusion at the cost of an extra line of code.

In this case, it's even more confusing because we're offering multiple
ways to search for the prefix (with or without a terminator) and more
than one way to retrieve the string (also with and without a
terminator). But a readString() method that accepts a prefix and a
suffix covers only one of those four cases, forcing people to fall
back on separate statements for the other three. This just increases
the difficulty of distinguishing and deciding between using two
separate calls or one combined one. I'd rather avoid the confusion
and just offer one way to do it.

3. I'd like to offer methods that store data into an existing buffer
and methods that return a newly-formed String. For consistency with
the naming in Processing (although with slightly different syntax),
let's use readBytes() and readBytesUntil() to store the data into an
existing buffer (returning the number of bytes read) and readString()
and readStringUntil() to return a newly-formed String (whose length
can be queried).

What do you think?

On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
> Seems like there are three outstanding issues:
>
> 1.    Orthogonal method naming: for example, should the method be called
> readInt or getInt
> 2.    Should readString/getString have a prestring argument.
> 3.    Should readString/getString return a String or the number of bytes
> stored
>
>
> On the first point, I don’t think the functionality of getInt/getFloat
> methods etc is orthogonal with the current stream method to read a
> character. read returns the next char in the stream, getInt reads as many
> characters as required until it finds one or more ASCII digits and converts
> these to an integer. I would expect an orthogonal implementation of readInt
> to return the integer value of the next two bytes in the stream. Such a
> method could be useful for reading data packed into a binary structure. I am
> not suggesting we include this (although it would be easy to implement if
> you wanted it) but I do feel that the rather different functionality of the
> proposed getInt deserves a name that differentiates from a simple read of a
> data type.
>
> Regarding point 2, we could support both version of read/getString – one
> without the prestring and one with:
> getString( endchar, buffer, length) // all characters up to but excluding
> endchar will be copied to the buffer (if the buffer is smaller than length,
> the string will be truncated .)
> and:
> getString(prestring, endchar, buffer, length) // as above but seeks to the
> first character following prestring.
>
> There is no performance or resource overhead in the latter getString, it
> uses the find method internally - I think this is just a question of which
> is easier for the user to type and understand.
>
> Regarding the return type of readString/getString, I would be uncomfortable
> if a method was not available that returned the number of bytes collected.
> Perhaps that’s just me. Feel free to add method that returned a String if
> you feel this was also needed but I don’t feel qualified to implement that
> for the Arduino runtime environment.
>
> Michael
>
> -----Original Message----- From: Tom Igoe
> Sent: Tuesday, June 07, 2011 4:34 PM
> To: David A. Mellis
> Cc: Michael Margolis ;
> Subject: Re: [Developers] Adding parsing to Stream
>
> I don't agree about the prefix change.  Before Michael's explanation of
> getString() I might have agreed, but having tried it, I think it makes a lot
> of sense. There's a lot of value in having the prefix. For example,
>
>     result = response.getString("", "", tweetBuffer, 140);
>
> returns something very different than
>
>     result = response.getString(", tweetBuffer, 150);
>
> and I don't think the following makes anything clearer:
>
>      response.find("");
>      response.getString("
", tweetBuffer, 150);
>
> Is there something I'm misunderstanding about your argument?
>
>
> The main thing that would make things clearer to me  would be:
>
>  tweetBuffer = response.getString("", "", 140);
>
> But I understand why that's a bad idea.
>
>
> I understand your desire to use read() and write()  where possible, though I
> don't think it's necessary. I think Michael's argument about get() in this
> case is valid, but if there's consensus on read() and write() I won't
> object.
>
> I'd recommend keeping the int return type on readString() or getString().
> It's valuable to know how big long actual returned array is, vs. what you
> allocated.
>
>
>
> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>
>> Yeah, you're right...  the memory constraints on Arduino make it
>> unreasonable to first read strings and then parse them (like in
>> Processing) and it seems silly for such functionality not to be in the
>> core somewhere.
>>
>> Can we go with the names readInt() and readFloat()?
>>
>> Can we omit the prefix parameters from readString() and
>> readStringUntil() - i.e. require a preceding call to find()?  I know
>> this makes string extraction a bit more verbose, but I think it also
>> makes it more clear.  In general, I've been trying to keep the API's
>> orthogonal and simple, even if it means sometimes using more than one
>> function call instead of one call to a more complex function.
>>
>> And the setTimeout() argument should probably be in milliseconds, not
>> seconds, both for consistency with the pulseIn() functions and to
>> allow finer control.
>>
>> I'd suggest, then:
>>
>> setTimeout(ms)
>> find(target) // String or char *
>> findUntil(target, terminator) // String or char *
>> readInt() / readInt(skipchar)
>> readFloat() / readFloat(skipchar)
>> readString()
>> readStringUntil(endchar)
>> readBytes(buf, buflen)
>> readBytesUntil(endchar, buf, buflen)
>>
>> Is that okay?
>>
>> I'm still curious if people have any other requirements in terms of
>> numeric formats that they'd like readInt() or readFloat() to support.
>> For example, do you need to be able to specify the character that
>> separates the whole from the decimal part of the float?
>>
>> David
>>
>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>> wrote:
>>>
>>> I think the methods to get numeric values (getInt and getFloat) would
>>> probably be more used with Serial than find() an findUntil().
>>>
>>> I have no objection to TextFinder being included as a library but do
>>> think
>>> that users would prefer having the get functions as a stream method
>>> rather
>>> than having to explicitly instantiate the TextFinder class, as would be
>>> required if a separate library.
>>>
>>> The need to do the following in a sketch (if implemented as a library) is
>>> not onerous
>>>
>>> #include
>>> TextFinder  finder(Serial);
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = finder.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>>
>>> }
>>>
>>>
>>> but this seems simpler and clearer
>>>
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = Serial.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>> }
>>>
>>> void loop();
>>>
>>> Michael
>>>
>>> --------------------------------------------------
>>> From: "Tom Igoe" <>
>>> Sent: Sunday, June 05, 2011 8:48 PM
>>> To: "David A. Mellis" <>
>>> Cc: "Michael Margolis" <>; <>
>>> Subject: Re: [Developers] Adding parsing to Stream
>>>
>>>> I think textFinder is good for things other than web pages, but I am in
>>>> favor of a small core.  How would you feel about including TextFinder in
>>>> the
>>>> standard distribution, assuming Michael agreed? That might offer a
>>>> reasonable compromise of small core, but easy access to the functions.
>>>>
>>>> t.
>>>>
>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>
>>>>> The more I think about this, the more I feel like maybe we should only
>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>> setting the timeout).  The other functionality feels fairly specific
>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>> be supported by the Stream class itself.  That is, maybe we should
>>>>> plan to continue to have a separate TextFinder library for more
>>>>> complex parsing tasks, and only integrate the functionality that
>>>>> applicable to wide range of stream types to the Stream interface
>>>>> itself.
>>>>>
>>>>> In general, I'm trying to keep the core API small - with the
>>>>> understanding that lots of useful, real-world examples will still
>>>>> require third-party libraries.  Including extra parsing functions
>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>> that it will be inconsistent with other portions of the API.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>
>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>
>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>> reading
>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>> code
>>>>>> and realized it'd take me longer to explain with find() then
>>>>>> readStringUntil() than it would with getString().  So I prefer
>>>>>> getString().
>>>>>>
>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>> strings.
>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>> also
>>>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>>>> getInt() and int() are different things, no?
>>>>>>
>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>
>>>>>> t.
>>>>>>
>>>>>>
>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>
>>>>>>> I am open to whatever method names are most suitable but  I like
>>>>>>> names
>>>>>>> that are evocative of their functionality and 'get' naming  was
>>>>>>> chosen over
>>>>>>> read because these methods do more than just read .  I also think the
>>>>>>>  string parsing method as proposed is easier to use for getting
>>>>>>> string
>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>
>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>>>> getting a string between two tokens is  an important capability for
>>>>>>> this API
>>>>>>>  (it is for me, and most of my web parsing applications seem to use
>>>>>>> the
>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>
>>>>>>> Tom, what do you think?
>>>>>>>
>>>>>>> Michael
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>> To: Michael Margolis
>>>>>>> Cc: Tom Igoe ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>> readString()
>>>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>
>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>> string before converting it to a number.
>>>>>>>
>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>> of
>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>> buffer
>>>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>> instead.
>>>>>>>
>>>>>>> How does that sound?
>>>>>>>
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>> <> wrote:
>>>>>>>>
>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>> we
>>>>>>>> rename  the getString method as follows:
>>>>>>>>
>>>>>>>> int readString( char *pre_string, char  post_string, char *buffer,
>>>>>>>> int
>>>>>>>> length); // read into a static character buffer
>>>>>>>>
>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>
>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>> like
>>>>>>>> this:
>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>> limited
>>>>>>>> String len may cause unexpected results
>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>> ncountered  -
>>>>>>>> Warning as above
>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>> find(pre_string) and
>>>>>>>> readStringUntil(post_char)
>>>>>>>>
>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>> is
>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>> whichever
>>>>>>>> brave soul volunteers to implement the dynamic String methods.  I am
>>>>>>>> a
>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>> dynamic
>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>
>>>>>>>> Michael Margolis
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>> To: Tom Igoe
>>>>>>>> Cc: Michael Margolis ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>> like:
>>>>>>>>
>>>>>>>> if (Serial.find(""))
>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>
>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>> result if you run out of room in the buffer.  (Do you throw out
>>>>>>>> older
>>>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>> and
>>>>>>>>> it's
>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>> and
>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>> on a
>>>>>>>>> stream.  I've had some cases where I needed to switch from find()
>>>>>>>>> to
>>>>>>>>> a
>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>
>>>>>>>>> This is what I want
>>>>>>>>>
>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>> I'm
>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>> between
>>>>>>>>>
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>> t.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>
>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>
>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>> character?
>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>> value of
>>>>>>>>>>> 0?
>>>>>>>>>>
>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>> will
>>>>>>>>>> be most useful.
>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>> the
>>>>>>>>>> API
>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>> user
>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>> Arduino
>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>> defines
>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>> setDecimalPointChar() could  be added if this functionality was
>>>>>>>>>> only
>>>>>>>>>> needed
>>>>>>>>>> in this API.
>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>
>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>
>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>> else
>>>>>>>>>> regarding this API.
>>>>>>>>>>
>>>>>>>>>> Michael
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>> To: Michael Margolis
>>>>>>>>>> Cc:
>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>
>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>
>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>> we
>>>>>>>>>> should keep in mind?
>>>>>>>>>>
>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>>>> than
>>>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>> doubles.
>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>> <> wrote:
>>>>>>>>>>>
>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>> finding and
>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>> by
>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>> for
>>>>>>>>>>> the
>>>>>>>>>>> incoming data.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>>>> (with
>>>>>>>>>>> help
>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>> implements
>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>> Ethernet
>>>>>>>>>>> are
>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>> API,
>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> setTimeout()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>>>> character
>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>> value
>>>>>>>>>>> is
>>>>>>>>>>> used
>>>>>>>>>>> by all of the other parsing  methods and could be useful for
>>>>>>>>>>> other
>>>>>>>>>>> stream
>>>>>>>>>>> functions.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>
>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> find()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Reads data from the stream until the target string
>>>>>>>>>>> is
>>>>>>>>>>> found
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>> to
>>>>>>>>>>> search
>>>>>>>>>>> for
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>> including
>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>> the
>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>>>
>>>>>>>>>>>  // here if the string "GET /" is found in the stream
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> findUntil()
>>>>>>>>>>>
>>>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>>>> found.
>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>> token.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>> for,
>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>> the
>>>>>>>>>>> search
>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>
>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>
>>>>>>>>>>>  // here if “pin” is found in the current line
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // stream buffer is at the beginning of the next line
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>> implemented
>>>>>>>>>>> if
>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>> pointer
>>>>>>>>>>> to a
>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>> functionally
>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>> target
>>>>>>>>>>> and
>>>>>>>>>>> terminate strings.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Returns the first valid (long) integer value from
>>>>>>>>>>> the
>>>>>>>>>>> current
>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>> minus
>>>>>>>>>>> sign)
>>>>>>>>>>> are
>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>> not
>>>>>>>>>>> a
>>>>>>>>>>> digit
>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>> integer
>>>>>>>>>>> values
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>>>
>>>>>>>>>>> {
>>>>>>>>>>>
>>>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>
>>>>>>>>>>>  Serial.println(value);
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getString()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>>>> stores
>>>>>>>>>>> into
>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>> length.
>>>>>>>>>>> The
>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>> preString
>>>>>>>>>>> that
>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>> string,
>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>> the
>>>>>>>>>>> first
>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>> buffer.
>>>>>>>>>>>
>>>>>>>>>>> Returns:  Returns the number of characters placed in the buffer
>>>>>>>>>>> (0
>>>>>>>>>>> means
>>>>>>>>>>> no
>>>>>>>>>>> valid data found)
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>> terminating null
>>>>>>>>>>>
>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>
>>>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>
>>>>>>>>>>>  {
>>>>>>>>>>>
>>>>>>>>>>>    Serial.print("found ");
>>>>>>>>>>>
>>>>>>>>>>>    Serial.println(buffer);
>>>>>>>>>>>
>>>>>>>>>>>  }
>>>>>>>>>>>
>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>
>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>> from
>>>>>>>>>>> the
>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----
>>>>>>>>>>>
>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>> suggest
>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>
>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>> Stream.cpp
>>>>>>>>>>> to
>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>>
>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I agree with 3). I think you are wrong on 1) and 2).

t.

On Jun 8, 2011, at 10:53 PM, David A. Mellis wrote:

> To take your issues in turn:
>
> 1. getInt() / getFloat() sound like simple accessors, i.e. methods
> that return existing values rather than actually doing work.
> Therefore, the confusion added by using different names for different
> types (i.e. read() for chars, getInt() for ints) isn't offset by a
> corresponding increase in clarity. If we want a different name, we
> should use something suggestive of the work being done, e.g.
> parseInt() and parseFloat(). Otherwise, I think we should just stick
> with read for consistency.
>
> 2. readString() with a prefix isn't orthogonal to find() plus
> readString() without a prefix. In general, if we offer a function for
> A and another function for B, we should avoid functions that do both A
> and B. By offering more than one way to do the same thing, you force
> people to figure out whether the two options are the same, to decide
> which one to use, and to recognize both approaches when reading code.
> I'd rather reduce confusion at the cost of an extra line of code.
>
> In this case, it's even more confusing because we're offering multiple
> ways to search for the prefix (with or without a terminator) and more
> than one way to retrieve the string (also with and without a
> terminator). But a readString() method that accepts a prefix and a
> suffix covers only one of those four cases, forcing people to fall
> back on separate statements for the other three. This just increases
> the difficulty of distinguishing and deciding between using two
> separate calls or one combined one. I'd rather avoid the confusion
> and just offer one way to do it.
>
> 3. I'd like to offer methods that store data into an existing buffer
> and methods that return a newly-formed String. For consistency with
> the naming in Processing (although with slightly different syntax),
> let's use readBytes() and readBytesUntil() to store the data into an
> existing buffer (returning the number of bytes read) and readString()
> and readStringUntil() to return a newly-formed String (whose length
> can be queried).
>
> What do you think?
>
> On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
>> Seems like there are three outstanding issues:
>>
>> 1. Orthogonal method naming: for example, should the method be called
>> readInt or getInt
>> 2. Should readString/getString have a prestring argument.
>> 3. Should readString/getString return a String or the number of bytes
>> stored
>>
>>
>> On the first point, I don’t think the functionality of getInt/getFloat
>> methods etc is orthogonal with the current stream method to read a
>> character. read returns the next char in the stream, getInt reads as many
>> characters as required until it finds one or more ASCII digits and converts
>> these to an integer. I would expect an orthogonal implementation of readInt
>> to return the integer value of the next two bytes in the stream. Such a
>> method could be useful for reading data packed into a binary structure. I am
>> not suggesting we include this (although it would be easy to implement if
>> you wanted it) but I do feel that the rather different functionality of the
>> proposed getInt deserves a name that differentiates from a simple read of a
>> data type.
>>
>> Regarding point 2, we could support both version of read/getString – one
>> without the prestring and one with:
>> getString( endchar, buffer, length) // all characters up to but excluding
>> endchar will be copied to the buffer (if the buffer is smaller than length,
>> the string will be truncated .)
>> and:
>> getString(prestring, endchar, buffer, length) // as above but seeks to the
>> first character following prestring.
>>
>> There is no performance or resource overhead in the latter getString, it
>> uses the find method internally - I think this is just a question of which
>> is easier for the user to type and understand.
>>
>> Regarding the return type of readString/getString, I would be uncomfortable
>> if a method was not available that returned the number of bytes collected.
>> Perhaps that’s just me. Feel free to add method that returned a String if
>> you feel this was also needed but I don’t feel qualified to implement that
>> for the Arduino runtime environment.
>>
>> Michael
>>
>> -----Original Message----- From: Tom Igoe
>> Sent: Tuesday, June 07, 2011 4:34 PM
>> To: David A. Mellis
>> Cc: Michael Margolis ;
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>> I don't agree about the prefix change. Before Michael's explanation of
>> getString() I might have agreed, but having tried it, I think it makes a lot
>> of sense. There's a lot of value in having the prefix. For example,
>>
>> result = response.getString("", "", tweetBuffer, 140);
>>
>> returns something very different than
>>
>> result = response.getString(", tweetBuffer, 150);
>>
>> and I don't think the following makes anything clearer:
>>
>> response.find("");
>> response.getString("
", tweetBuffer, 150);
>>
>> Is there something I'm misunderstanding about your argument?
>>
>>
>> The main thing that would make things clearer to me would be:
>>
>> tweetBuffer = response.getString("", "", 140);
>>
>> But I understand why that's a bad idea.
>>
>>
>> I understand your desire to use read() and write() where possible, though I
>> don't think it's necessary. I think Michael's argument about get() in this
>> case is valid, but if there's consensus on read() and write() I won't
>> object.
>>
>> I'd recommend keeping the int return type on readString() or getString().
>> It's valuable to know how big long actual returned array is, vs. what you
>> allocated.
>>
>>
>>
>> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>>
>>> Yeah, you're right... the memory constraints on Arduino make it
>>> unreasonable to first read strings and then parse them (like in
>>> Processing) and it seems silly for such functionality not to be in the
>>> core somewhere.
>>>
>>> Can we go with the names readInt() and readFloat()?
>>>
>>> Can we omit the prefix parameters from readString() and
>>> readStringUntil() - i.e. require a preceding call to find()? I know
>>> this makes string extraction a bit more verbose, but I think it also
>>> makes it more clear. In general, I've been trying to keep the API's
>>> orthogonal and simple, even if it means sometimes using more than one
>>> function call instead of one call to a more complex function.
>>>
>>> And the setTimeout() argument should probably be in milliseconds, not
>>> seconds, both for consistency with the pulseIn() functions and to
>>> allow finer control.
>>>
>>> I'd suggest, then:
>>>
>>> setTimeout(ms)
>>> find(target) // String or char *
>>> findUntil(target, terminator) // String or char *
>>> readInt() / readInt(skipchar)
>>> readFloat() / readFloat(skipchar)
>>> readString()
>>> readStringUntil(endchar)
>>> readBytes(buf, buflen)
>>> readBytesUntil(endchar, buf, buflen)
>>>
>>> Is that okay?
>>>
>>> I'm still curious if people have any other requirements in terms of
>>> numeric formats that they'd like readInt() or readFloat() to support.
>>> For example, do you need to be able to specify the character that
>>> separates the whole from the decimal part of the float?
>>>
>>> David
>>>
>>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>>> wrote:
>>>>
>>>> I think the methods to get numeric values (getInt and getFloat) would
>>>> probably be more used with Serial than find() an findUntil().
>>>>
>>>> I have no objection to TextFinder being included as a library but do
>>>> think
>>>> that users would prefer having the get functions as a stream method
>>>> rather
>>>> than having to explicitly instantiate the TextFinder class, as would be
>>>> required if a separate library.
>>>>
>>>> The need to do the following in a sketch (if implemented as a library) is
>>>> not onerous
>>>>
>>>> #include
>>>> TextFinder finder(Serial);
>>>> void setup()
>>>> {
>>>> Serial.begin(9600);
>>>> int val = finder.getInt(); // return the next integer value on the
>>>> Serial
>>>> stream
>>>>
>>>> }
>>>>
>>>>
>>>> but this seems simpler and clearer
>>>>
>>>> void setup()
>>>> {
>>>> Serial.begin(9600);
>>>> int val = Serial.getInt(); // return the next integer value on the
>>>> Serial
>>>> stream
>>>> }
>>>>
>>>> void loop();
>>>>
>>>> Michael
>>>>
>>>> --------------------------------------------------
>>>> From: "Tom Igoe" <>
>>>> Sent: Sunday, June 05, 2011 8:48 PM
>>>> To: "David A. Mellis" <>
>>>> Cc: "Michael Margolis" <>; <>
>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>
>>>>> I think textFinder is good for things other than web pages, but I am in
>>>>> favor of a small core. How would you feel about including TextFinder in
>>>>> the
>>>>> standard distribution, assuming Michael agreed? That might offer a
>>>>> reasonable compromise of small core, but easy access to the functions.
>>>>>
>>>>> t.
>>>>>
>>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>>
>>>>>> The more I think about this, the more I feel like maybe we should only
>>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>>> setting the timeout). The other functionality feels fairly specific
>>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>>> be supported by the Stream class itself. That is, maybe we should
>>>>>> plan to continue to have a separate TextFinder library for more
>>>>>> complex parsing tasks, and only integrate the functionality that
>>>>>> applicable to wide range of stream types to the Stream interface
>>>>>> itself.
>>>>>>
>>>>>> In general, I'm trying to keep the core API small - with the
>>>>>> understanding that lots of useful, real-world examples will still
>>>>>> require third-party libraries. Including extra parsing functions
>>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>>> that it will be inconsistent with other portions of the API.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>>
>>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>>> reading
>>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>>> code
>>>>>>> and realized it'd take me longer to explain with find() then
>>>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>>>> getString().
>>>>>>>
>>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>>> strings.
>>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>>> also
>>>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>>>> getInt() and int() are different things, no?
>>>>>>>
>>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> I am open to whatever method names are most suitable but I like
>>>>>>>> names
>>>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>>>> chosen over
>>>>>>>> read because these methods do more than just read . I also think the
>>>>>>>> string parsing method as proposed is easier to use for getting
>>>>>>>> string
>>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>>
>>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>>>> getting a string between two tokens is an important capability for
>>>>>>>> this API
>>>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>>>> the
>>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>>
>>>>>>>> Tom, what do you think?
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc: Tom Igoe ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>>> readString()
>>>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>>
>>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>>> string before converting it to a number.
>>>>>>>>
>>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>>> of
>>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>>> buffer
>>>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>>> instead.
>>>>>>>>
>>>>>>>> How does that sound?
>>>>>>>>
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>>> we
>>>>>>>>> rename the getString method as follows:
>>>>>>>>>
>>>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>>>> int
>>>>>>>>> length); // read into a static character buffer
>>>>>>>>>
>>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>>
>>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>>> like
>>>>>>>>> this:
>>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>>> limited
>>>>>>>>> String len may cause unexpected results
>>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>>> ncountered -
>>>>>>>>> Warning as above
>>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>>> find(pre_string) and
>>>>>>>>> readStringUntil(post_char)
>>>>>>>>>
>>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>>> is
>>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>>> whichever
>>>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>>>> a
>>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>>> dynamic
>>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>>> To: Tom Igoe
>>>>>>>>> Cc: Michael Margolis ;
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>>> like:
>>>>>>>>>
>>>>>>>>> if (Serial.find(""))
>>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>>
>>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>>>> older
>>>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>>> and
>>>>>>>>>> it's
>>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>>> and
>>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>>> on a
>>>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>>>> to
>>>>>>>>>> a
>>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>>
>>>>>>>>>> This is what I want
>>>>>>>>>>
>>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>>> I'm
>>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>>> between
>>>>>>>>>>
>>>>>>>>>> and
>>>>>>>>>>
>>>>>>>>>> t.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>>
>>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>>
>>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>>> character?
>>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>>> value of
>>>>>>>>>>>> 0?
>>>>>>>>>>>
>>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>>> will
>>>>>>>>>>> be most useful.
>>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>>> the
>>>>>>>>>>> API
>>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>>
>>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>>> supporting
>>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>>
>>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>>> user
>>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>>> Arduino
>>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>>> defines
>>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>>>> only
>>>>>>>>>>> needed
>>>>>>>>>>> in this API.
>>>>>>>>>>>
>>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>>
>>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>>
>>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>>> else
>>>>>>>>>>> regarding this API.
>>>>>>>>>>>
>>>>>>>>>>> Michael
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>>> To: Michael Margolis
>>>>>>>>>>> Cc:
>>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>>
>>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>>
>>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>>> we
>>>>>>>>>>> should keep in mind?
>>>>>>>>>>>
>>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>>>> than
>>>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>>> doubles.
>>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>>
>>>>>>>>>>> David
>>>>>>>>>>>
>>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>>> <> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>>> finding and
>>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>>> by
>>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>>> for
>>>>>>>>>>>> the
>>>>>>>>>>>> incoming data.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>>>> (with
>>>>>>>>>>>> help
>>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>>> implements
>>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>>> Ethernet
>>>>>>>>>>>> are
>>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>>> API,
>>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> setTimeout()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>>>> character
>>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>>> value
>>>>>>>>>>>> is
>>>>>>>>>>>> used
>>>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>>>> other
>>>>>>>>>>>> stream
>>>>>>>>>>>> functions.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> find()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>>>> is
>>>>>>>>>>>> found
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>>> to
>>>>>>>>>>>> search
>>>>>>>>>>>> for
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>>> including
>>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>>> the
>>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>>>
>>>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>>>
>>>>>>>>>>>> else
>>>>>>>>>>>>
>>>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> findUntil()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>>>> found.
>>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>>> token.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>>> for,
>>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>>> the
>>>>>>>>>>>> search
>>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>>
>>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>>
>>>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>>>
>>>>>>>>>>>> else
>>>>>>>>>>>>
>>>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>>> implemented
>>>>>>>>>>>> if
>>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>>> pointer
>>>>>>>>>>>> to a
>>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>>> functionally
>>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>>> target
>>>>>>>>>>>> and
>>>>>>>>>>>> terminate strings.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getValue()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>>>> the
>>>>>>>>>>>> current
>>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>>> minus
>>>>>>>>>>>> sign)
>>>>>>>>>>>> are
>>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>>> not
>>>>>>>>>>>> a
>>>>>>>>>>>> digit
>>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: none
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>>> integer
>>>>>>>>>>>> values
>>>>>>>>>>>>
>>>>>>>>>>>> int value;
>>>>>>>>>>>>
>>>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>>>
>>>>>>>>>>>> {
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value);
>>>>>>>>>>>>
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>>> allows
>>>>>>>>>>>> format
>>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> int value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getFloat()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: none
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> float value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>>> allows
>>>>>>>>>>>> format
>>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> float value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getString()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>>>> stores
>>>>>>>>>>>> into
>>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>>> length.
>>>>>>>>>>>> The
>>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>>> preString
>>>>>>>>>>>> that
>>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>>> string,
>>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>>> the
>>>>>>>>>>>> first
>>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>>> buffer.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>>>> (0
>>>>>>>>>>>> means
>>>>>>>>>>>> no
>>>>>>>>>>>> valid data found)
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>>> terminating null
>>>>>>>>>>>>
>>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>>
>>>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>>
>>>>>>>>>>>> {
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>>>
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>>
>>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>>> from
>>>>>>>>>>>> the
>>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> -----
>>>>>>>>>>>>
>>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>>> suggest
>>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>>
>>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>>> Stream.cpp
>>>>>>>>>>>> to
>>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>>
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>>
>>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
> the confusion added by using different names for different
>types (i.e. read() for chars, getInt() for ints) isn't offset by a
>corresponding increase in clarity.
I have suggested different names because the current read method IS
functionally different from the TextFinder methods to parse an int or float.
And as I said previously, I think it makes sense to reserve readInt for a
method that returns the next two bytes in the stream converted to its int
value.
But I am ok going with whatever naming you, Tom and the rest of the Arduino
team agree on.

>In general, if we offer a function for A and another function for B,
> we should avoid functions that do both A and B.

If both A (find) and B (readString within given delimiters) are clear and
provide commonly required functionality I would think this is preferable to
what may be a theoretically more concise solution. Again, I will go with
what you, Tom and the team agree on - but as one that writes lots of
Arduino web code, I would be sad to see the loss of the preString argument.

I do not feel qualified to implement and test the readString methods,
although I will be happy to assist whoever takes that on.
I have previously expressed my concerns about trying to migrate something
similar to the Processing String capability onto the chips that are used on
the current Arduino boards. Part of Processing’s appeal is that it isolates
the novice programmer from the complexity of memory management. A well
behaved Processing program is unlikely to ever run out of memory and coding
errors that result in memory exhaustion are flagged by runtime exception
handling.
Relieving users of explicit memory management would be a huge benefit if the
Processing way of doing things could be transferred to Arduino. But with
the limited memory available on the current processors and lack if runtime
exception handling, I will be interested to see if Processing like String
handling will prove to be robust on an ATmega328.

Michael Margolis

-----Original Message-----
From: David A. Mellis
Sent: Thursday, June 09, 2011 3:53 AM
To: Michael Margolis
Cc: Tom Igoe ;
Subject: Re: [Developers] Adding parsing to Stream

To take your issues in turn:

1. getInt() / getFloat() sound like simple accessors, i.e. methods
that return existing values rather than actually doing work.
Therefore, the confusion added by using different names for different
types (i.e. read() for chars, getInt() for ints) isn't offset by a
corresponding increase in clarity. If we want a different name, we
should use something suggestive of the work being done, e.g.
parseInt() and parseFloat(). Otherwise, I think we should just stick
with read for consistency.

2. readString() with a prefix isn't orthogonal to find() plus
readString() without a prefix. In general, if we offer a function for
A and another function for B, we should avoid functions that do both A
and B. By offering more than one way to do the same thing, you force
people to figure out whether the two options are the same, to decide
which one to use, and to recognize both approaches when reading code.
I'd rather reduce confusion at the cost of an extra line of code.

In this case, it's even more confusing because we're offering multiple
ways to search for the prefix (with or without a terminator) and more
than one way to retrieve the string (also with and without a
terminator). But a readString() method that accepts a prefix and a
suffix covers only one of those four cases, forcing people to fall
back on separate statements for the other three. This just increases
the difficulty of distinguishing and deciding between using two
separate calls or one combined one. I'd rather avoid the confusion
and just offer one way to do it.

3. I'd like to offer methods that store data into an existing buffer
and methods that return a newly-formed String. For consistency with
the naming in Processing (although with slightly different syntax),
let's use readBytes() and readBytesUntil() to store the data into an
existing buffer (returning the number of bytes read) and readString()
and readStringUntil() to return a newly-formed String (whose length
can be queried).

What do you think?

On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <>
wrote:
> Seems like there are three outstanding issues:
>
> 1. Orthogonal method naming: for example, should the method be called
> readInt or getInt
> 2. Should readString/getString have a prestring argument.
> 3. Should readString/getString return a String or the number of bytes
> stored
>
>
> On the first point, I don’t think the functionality of getInt/getFloat
> methods etc is orthogonal with the current stream method to read a
> character. read returns the next char in the stream, getInt reads as many
> characters as required until it finds one or more ASCII digits and
> converts
> these to an integer. I would expect an orthogonal implementation of
> readInt
> to return the integer value of the next two bytes in the stream. Such a
> method could be useful for reading data packed into a binary structure. I
> am
> not suggesting we include this (although it would be easy to implement if
> you wanted it) but I do feel that the rather different functionality of
> the
> proposed getInt deserves a name that differentiates from a simple read of
> a
> data type.
>
> Regarding point 2, we could support both version of read/getString – one
> without the prestring and one with:
> getString( endchar, buffer, length) // all characters up to but excluding
> endchar will be copied to the buffer (if the buffer is smaller than
> length,
> the string will be truncated .)
> and:
> getString(prestring, endchar, buffer, length) // as above but seeks to the
> first character following prestring.
>
> There is no performance or resource overhead in the latter getString, it
> uses the find method internally - I think this is just a question of which
> is easier for the user to type and understand.
>
> Regarding the return type of readString/getString, I would be
> uncomfortable
> if a method was not available that returned the number of bytes collected.
> Perhaps that’s just me. Feel free to add method that returned a String if
> you feel this was also needed but I don’t feel qualified to implement that
> for the Arduino runtime environment.
>
> Michael
>
> -----Original Message----- From: Tom Igoe
> Sent: Tuesday, June 07, 2011 4:34 PM
> To: David A. Mellis
> Cc: Michael Margolis ;
> Subject: Re: [Developers] Adding parsing to Stream
>
> I don't agree about the prefix change. Before Michael's explanation of
> getString() I might have agreed, but having tried it, I think it makes a
> lot
> of sense. There's a lot of value in having the prefix. For example,
>
> result = response.getString("", "", tweetBuffer, 140);
>
> returns something very different than
>
> result = response.getString(", tweetBuffer, 150);
>
> and I don't think the following makes anything clearer:
>
> response.find("");
> response.getString("
", tweetBuffer, 150);
>
> Is there something I'm misunderstanding about your argument?
>
>
> The main thing that would make things clearer to me would be:
>
> tweetBuffer = response.getString("", "", 140);
>
> But I understand why that's a bad idea.
>
>
> I understand your desire to use read() and write() where possible, though
> I
> don't think it's necessary. I think Michael's argument about get() in this
> case is valid, but if there's consensus on read() and write() I won't
> object.
>
> I'd recommend keeping the int return type on readString() or getString().
> It's valuable to know how big long actual returned array is, vs. what you
> allocated.
>
>
>
> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>
>> Yeah, you're right... the memory constraints on Arduino make it
>> unreasonable to first read strings and then parse them (like in
>> Processing) and it seems silly for such functionality not to be in the
>> core somewhere.
>>
>> Can we go with the names readInt() and readFloat()?
>>
>> Can we omit the prefix parameters from readString() and
>> readStringUntil() - i.e. require a preceding call to find()? I know
>> this makes string extraction a bit more verbose, but I think it also
>> makes it more clear. In general, I've been trying to keep the API's
>> orthogonal and simple, even if it means sometimes using more than one
>> function call instead of one call to a more complex function.
>>
>> And the setTimeout() argument should probably be in milliseconds, not
>> seconds, both for consistency with the pulseIn() functions and to
>> allow finer control.
>>
>> I'd suggest, then:
>>
>> setTimeout(ms)
>> find(target) // String or char *
>> findUntil(target, terminator) // String or char *
>> readInt() / readInt(skipchar)
>> readFloat() / readFloat(skipchar)
>> readString()
>> readStringUntil(endchar)
>> readBytes(buf, buflen)
>> readBytesUntil(endchar, buf, buflen)
>>
>> Is that okay?
>>
>> I'm still curious if people have any other requirements in terms of
>> numeric formats that they'd like readInt() or readFloat() to support.
>> For example, do you need to be able to specify the character that
>> separates the whole from the decimal part of the float?
>>
>> David
>>
>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>> wrote:
>>>
>>> I think the methods to get numeric values (getInt and getFloat) would
>>> probably be more used with Serial than find() an findUntil().
>>>
>>> I have no objection to TextFinder being included as a library but do
>>> think
>>> that users would prefer having the get functions as a stream method
>>> rather
>>> than having to explicitly instantiate the TextFinder class, as would be
>>> required if a separate library.
>>>
>>> The need to do the following in a sketch (if implemented as a library)
>>> is
>>> not onerous
>>>
>>> #include
>>> TextFinder finder(Serial);
>>> void setup()
>>> {
>>> Serial.begin(9600);
>>> int val = finder.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>>
>>> }
>>>
>>>
>>> but this seems simpler and clearer
>>>
>>> void setup()
>>> {
>>> Serial.begin(9600);
>>> int val = Serial.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>> }
>>>
>>> void loop();
>>>
>>> Michael
>>>
>>> --------------------------------------------------
>>> From: "Tom Igoe" <>
>>> Sent: Sunday, June 05, 2011 8:48 PM
>>> To: "David A. Mellis" <>
>>> Cc: "Michael Margolis" <>; <>
>>> Subject: Re: [Developers] Adding parsing to Stream
>>>
>>>> I think textFinder is good for things other than web pages, but I am in
>>>> favor of a small core. How would you feel about including TextFinder
>>>> in
>>>> the
>>>> standard distribution, assuming Michael agreed? That might offer a
>>>> reasonable compromise of small core, but easy access to the functions.
>>>>
>>>> t.
>>>>
>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>
>>>>> The more I think about this, the more I feel like maybe we should only
>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>> setting the timeout). The other functionality feels fairly specific
>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>> be supported by the Stream class itself. That is, maybe we should
>>>>> plan to continue to have a separate TextFinder library for more
>>>>> complex parsing tasks, and only integrate the functionality that
>>>>> applicable to wide range of stream types to the Stream interface
>>>>> itself.
>>>>>
>>>>> In general, I'm trying to keep the core API small - with the
>>>>> understanding that lots of useful, real-world examples will still
>>>>> require third-party libraries. Including extra parsing functions
>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>> that it will be inconsistent with other portions of the API.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>
>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>
>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>> reading
>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>> code
>>>>>> and realized it'd take me longer to explain with find() then
>>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>>> getString().
>>>>>>
>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>> strings.
>>>>>> And as Michael points out getInt() does more than just the casting,
>>>>>> it
>>>>>> also
>>>>>> finds the next int in the string, and then casts it. So
>>>>>> conceptually,
>>>>>> getInt() and int() are different things, no?
>>>>>>
>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>
>>>>>> t.
>>>>>>
>>>>>>
>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>
>>>>>>> I am open to whatever method names are most suitable but I like
>>>>>>> names
>>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>>> chosen over
>>>>>>> read because these methods do more than just read . I also think
>>>>>>> the
>>>>>>> string parsing method as proposed is easier to use for getting
>>>>>>> string
>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>
>>>>>>> But I don’t object to changing the names or the functionality as
>>>>>>> long
>>>>>>> as we don’t sacrifice clarity or usability. It seems to me that
>>>>>>> if
>>>>>>> getting a string between two tokens is an important capability for
>>>>>>> this API
>>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>>> the
>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>
>>>>>>> Tom, what do you think?
>>>>>>>
>>>>>>> Michael
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>> To: Michael Margolis
>>>>>>> Cc: Tom Igoe ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>> readString()
>>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>
>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>> string before converting it to a number.
>>>>>>>
>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>> of
>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>> buffer
>>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>>> strings
>>>>>>> instead.
>>>>>>>
>>>>>>> How does that sound?
>>>>>>>
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>> <> wrote:
>>>>>>>>
>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>> we
>>>>>>>> rename the getString method as follows:
>>>>>>>>
>>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>>> int
>>>>>>>> length); // read into a static character buffer
>>>>>>>>
>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>
>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>> like
>>>>>>>> this:
>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>> limited
>>>>>>>> String len may cause unexpected results
>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>> ncountered -
>>>>>>>> Warning as above
>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>> find(pre_string) and
>>>>>>>> readStringUntil(post_char)
>>>>>>>>
>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>> is
>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>> whichever
>>>>>>>> brave soul volunteers to implement the dynamic String methods. I
>>>>>>>> am
>>>>>>>> a
>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>> dynamic
>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>
>>>>>>>> Michael Margolis
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>> To: Tom Igoe
>>>>>>>> Cc: Michael Margolis ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>>> something
>>>>>>>> like:
>>>>>>>>
>>>>>>>> if (Serial.find(""))
>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>
>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>>> older
>>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>> and
>>>>>>>>> it's
>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>> and
>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>>> finds()
>>>>>>>>> on a
>>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>>> to
>>>>>>>>> a
>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>
>>>>>>>>> This is what I want
>>>>>>>>>
>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>> I'm
>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>> between
>>>>>>>>>
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>> t.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>
>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>
>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>> character?
>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>> value of
>>>>>>>>>>> 0?
>>>>>>>>>>
>>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>>> think
>>>>>>>>>> will
>>>>>>>>>> be most useful.
>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>> the
>>>>>>>>>> API
>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> This could be added by specifying the decimal point character to
>>>>>>>>>> a
>>>>>>>>>> user
>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>> Arduino
>>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>>> contains
>>>>>>>>>> defines
>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>>> only
>>>>>>>>>> needed
>>>>>>>>>> in this API.
>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>
>>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>>> consistency.
>>>>>>>>>>
>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>> else
>>>>>>>>>> regarding this API.
>>>>>>>>>>
>>>>>>>>>> Michael
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>> To: Michael Margolis
>>>>>>>>>> Cc:
>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>
>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>
>>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>>> cases
>>>>>>>>>> we
>>>>>>>>>> should keep in mind?
>>>>>>>>>>
>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>>> than
>>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>>> the
>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>> doubles.
>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>> <> wrote:
>>>>>>>>>>>
>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>> finding and
>>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>>> character
>>>>>>>>>>> by
>>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>>> required
>>>>>>>>>>> for
>>>>>>>>>>> the
>>>>>>>>>>> incoming data.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>>> (with
>>>>>>>>>>> help
>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>> implements
>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>> Ethernet
>>>>>>>>>>> are
>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>> API,
>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> setTimeout()
>>>>>>>>>>>
>>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>>> character
>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>> value
>>>>>>>>>>> is
>>>>>>>>>>> used
>>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>>> other
>>>>>>>>>>> stream
>>>>>>>>>>> functions.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>
>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> find()
>>>>>>>>>>>
>>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>>> is
>>>>>>>>>>> found
>>>>>>>>>>>
>>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>> to
>>>>>>>>>>> search
>>>>>>>>>>> for
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>>> and
>>>>>>>>>>> including
>>>>>>>>>>> the last character in targetStr will be flushed. Returns false
>>>>>>>>>>> if
>>>>>>>>>>> the
>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>>
>>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> findUntil()
>>>>>>>>>>>
>>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>>> found.
>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>> token.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>> for,
>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>> the
>>>>>>>>>>> search
>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>
>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>
>>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>> implemented
>>>>>>>>>>> if
>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>> pointer
>>>>>>>>>>> to a
>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>> functionally
>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>> target
>>>>>>>>>>> and
>>>>>>>>>>> terminate strings.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue()
>>>>>>>>>>>
>>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>>> the
>>>>>>>>>>> current
>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>> minus
>>>>>>>>>>> sign)
>>>>>>>>>>> are
>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>> not
>>>>>>>>>>> a
>>>>>>>>>>> digit
>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>> integer
>>>>>>>>>>> values
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>>
>>>>>>>>>>> {
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getString()
>>>>>>>>>>>
>>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>>> stores
>>>>>>>>>>> into
>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>> length.
>>>>>>>>>>> The
>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>> preString
>>>>>>>>>>> that
>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>> string,
>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>> the
>>>>>>>>>>> first
>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>> buffer.
>>>>>>>>>>>
>>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>>> (0
>>>>>>>>>>> means
>>>>>>>>>>> no
>>>>>>>>>>> valid data found)
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>> terminating null
>>>>>>>>>>>
>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>
>>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>
>>>>>>>>>>> {
>>>>>>>>>>>
>>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>
>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>> from
>>>>>>>>>>> the
>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----
>>>>>>>>>>>
>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>> suggest
>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>
>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>> Stream.cpp
>>>>>>>>>>> to
>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>>
>
>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)

  #8  
09-06-2011 01:45 PM
Developers member admin is online now
User
 

Sorry Michael, I wasn't particularly clear in my response earlier.
Reading things into a String and then casting them to int or float was
something David suggested as a possible other solution a few messages back.

I don't mind too much whether TextFinder is a separate library in the
core distribution, or part of Stream, but I would like to see it
included somewhere.

I also think that it shouldn't force people to use String (which it
doesn't at present), although I have no problem with people using it
with String if they want.

Hopefully that clarifies things...

Adrian.

On 05/06/11 22:39, Michael Margolis wrote:
> Adrian,
>
> I was not proposing to have the core getInt and getFloat use String.
> The implementation I attached to my email with the code parses the
> values without allocating any memory. I would agree that parsing
> functions that use String (in my view all String functions) are best
> suited in a library rather than the core.
>
> Michael
>
> --------------------------------------------------
> From: "Adrian McEwen" <>
> Sent: Sunday, June 05, 2011 9:15 PM
> To: <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> That sounds like a good compromise to me. TextFinder is really handy
>> in combination with the Ethernet library, and the suggestion of
>> having to pull data into a String and then cast it to convert to int
>> or float, etc. is just introducing all of the memory issues that I
>> use TextFinder in order to avoid :-)
>>
>> Just my tuppence-worth,
>>
>> Adrian.
>>
>> On 05/06/2011 20:48, Tom Igoe wrote:
>>> I think textFinder is good for things other than web pages, but I am
>>> in favor of a small core. How would you feel about including
>>> TextFinder in the standard distribution, assuming Michael agreed?
>>> That might offer a reasonable compromise of small core, but easy
>>> access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe<> wrote:
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and
>>>>> I found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading through Dave's proposal, I tried to think through how to
>>>>> explain the code and realized it'd take me longer to explain with
>>>>> find() then readStringUntil() than it would with getString(). So
>>>>> I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings. And as Michael points out getInt() does more than just
>>>>> the casting, it also finds the next int in the string, and then
>>>>> casts it. So conceptually, getInt() and int() are different
>>>>> things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names that are evocative of their functionality and 'get' naming
>>>>>> was chosen over read because these methods do more than just read
>>>>>> . I also think the string parsing method as proposed is easier
>>>>>> to use for getting string between tokens, which seemed to be the
>>>>>> primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as
>>>>>> long as we don’t sacrifice clarity or usability. It seems to
>>>>>> me that if getting a string between two tokens is an important
>>>>>> capability for this API (it is for me, and most of my web
>>>>>> parsing applications seem to use the current getString) then it
>>>>>> would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative
>>>>>> versions of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated
>>>>>> strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>> For closer naming with the similar Processing functionality,
>>>>>>> should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char
>>>>>>> *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like this:
>>>>>>> String readStringUntil() //reads up to the first newline –
>>>>>>> Warning, limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when
>>>>>>> there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods.
>>>>>>> I am a
>>>>>>> String sceptic from way back so am not well placed to advise on
>>>>>>> how dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do
>>>>>>> something like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe<>
>>>>>>> wrote:
>>>>>>>> i have been using TextFinder in the rewrite of Making Things
>>>>>>>> talk and it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see
>>>>>>>> find() and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple
>>>>>>>> finds() on a
>>>>>>>> stream. I've had some cases where I needed to switch from
>>>>>>>> find() to a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a<.
>>>>>>>> Maybe I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a
>>>>>>>>>> real value of
>>>>>>>>>> 0?
>>>>>>>>> Good questions, I am interested to hear what the people here
>>>>>>>>> think will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid
>>>>>>>>> bloating the API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>> This could be added by specifying the decimal point character
>>>>>>>>> to a user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that
>>>>>>>>> contains defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality
>>>>>>>>> was only needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>> getValue seemed less techy but I take the point about
>>>>>>>>> consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and
>>>>>>>>> anything else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use
>>>>>>>>> cases we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify
>>>>>>>>> more than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with
>>>>>>>>> the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done
>>>>>>>>>> character by
>>>>>>>>>> character so no intermediate static or dynamic buffer is
>>>>>>>>>> required for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I
>>>>>>>>>> wrote (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to
>>>>>>>>>> the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for
>>>>>>>>>> a character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target
>>>>>>>>>> string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character
>>>>>>>>>> string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to
>>>>>>>>>> and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns
>>>>>>>>>> false if the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string
>>>>>>>>>> is found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to
>>>>>>>>>> search for,
>>>>>>>>>> terminateStr is the null terminated C string that will
>>>>>>>>>> terminate the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be
>>>>>>>>>> a pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in
>>>>>>>>>> the target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value
>>>>>>>>>> from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that
>>>>>>>>>> is not a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index< 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored.
>>>>>>>>>> This allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters
>>>>>>>>>> and stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the
>>>>>>>>>> buffer length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired
>>>>>>>>>> target string,
>>>>>>>>>> following characters this are appended to the given buffer
>>>>>>>>>> until the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the
>>>>>>>>>> buffer (0 means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<",">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character
>>>>>>>>>> read from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free
>>>>>>>>>> to suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores> arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> Developers mailing list
>>>
>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>
>>
>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Yeah, you're right... the memory constraints on Arduino make it
unreasonable to first read strings and then parse them (like in
Processing) and it seems silly for such functionality not to be in the
core somewhere.

Can we go with the names readInt() and readFloat()?

Can we omit the prefix parameters from readString() and
readStringUntil() - i.e. require a preceding call to find()? I know
this makes string extraction a bit more verbose, but I think it also
makes it more clear. In general, I've been trying to keep the API's
orthogonal and simple, even if it means sometimes using more than one
function call instead of one call to a more complex function.

And the setTimeout() argument should probably be in milliseconds, not
seconds, both for consistency with the pulseIn() functions and to
allow finer control.

I'd suggest, then:

setTimeout(ms)
find(target) // String or char *
findUntil(target, terminator) // String or char *
readInt() / readInt(skipchar)
readFloat() / readFloat(skipchar)
readString()
readStringUntil(endchar)
readBytes(buf, buflen)
readBytesUntil(endchar, buf, buflen)

Is that okay?

I'm still curious if people have any other requirements in terms of
numeric formats that they'd like readInt() or readFloat() to support.
For example, do you need to be able to specify the character that
separates the whole from the decimal part of the float?

David

On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
> I think the methods to get numeric values (getInt and getFloat) would
> probably be more used with Serial than find() an findUntil().
>
> I have no objection to TextFinder being included as a library but do think
> that users would prefer having the get functions as a stream method rather
> than having to explicitly instantiate the TextFinder class, as would be
> required if a separate library.
>
> The need to do the following in a sketch (if implemented as a library) is
> not onerous
>
> #include
> TextFinder  finder(Serial);
> void setup()
> {
>  Serial.begin(9600);
>  int  val = finder.getInt(); // return the next integer value on the Serial
> stream
>
> }
>
>
> but this seems simpler and clearer
>
> void setup()
> {
>  Serial.begin(9600);
>  int  val = Serial.getInt(); // return the next integer value on the Serial
> stream
> }
>
> void loop();
>
> Michael
>
> --------------------------------------------------
> From: "Tom Igoe" <>
> Sent: Sunday, June 05, 2011 8:48 PM
> To: "David A. Mellis" <>
> Cc: "Michael Margolis" <>; <>
> Subject: Re: [Developers] Adding parsing to Stream
>
>> I think textFinder is good for things other than web pages, but I am in
>> favor of a small core.  How would you feel about including TextFinder in the
>> standard distribution, assuming Michael agreed? That might offer a
>> reasonable compromise of small core, but easy access to the functions.
>>
>> t.
>>
>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>
>>> The more I think about this, the more I feel like maybe we should only
>>> add the find() and findUntil() methods to stream (with some method for
>>> setting the timeout).  The other functionality feels fairly specific
>>> to parsing webpages, which isn't something that feels like it needs to
>>> be supported by the Stream class itself.  That is, maybe we should
>>> plan to continue to have a separate TextFinder library for more
>>> complex parsing tasks, and only integrate the functionality that
>>> applicable to wide range of stream types to the Stream interface
>>> itself.
>>>
>>> In general, I'm trying to keep the core API small - with the
>>> understanding that lots of useful, real-world examples will still
>>> require third-party libraries.  Including extra parsing functions
>>> starts to feel in conflict with this general philosophy and I worry
>>> that it will be inconsistent with other portions of the API.
>>>
>>> Thoughts?
>>>
>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>
>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>
>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>> through Dave's proposal, I tried to think through how to explain the code
>>>> and realized it'd take me longer to explain with find() then
>>>> readStringUntil() than it would with getString().  So I prefer getString().
>>>>
>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>> And as Michael points out getInt() does more than just the casting, it also
>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>> getInt() and int() are different things, no?
>>>>
>>>> As for read() vs get() naming, I could go either way.
>>>>
>>>> t.
>>>>
>>>>
>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>
>>>>> I am open to whatever method names are most suitable but  I like names
>>>>> that are evocative of their functionality and 'get' naming  was chosen over
>>>>> read because these methods do more than just read .  I also think the
>>>>>  string parsing method as proposed is easier to use for getting string
>>>>> between tokens, which seemed to be the primary use case.
>>>>>
>>>>> But I don’t object to changing the names or the functionality as long
>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>> getting a string between two tokens is  an important capability for this API
>>>>>  (it is for me, and most of my web parsing applications seem to use the
>>>>> current getString) then it would be a shame to lose this.
>>>>>
>>>>> Tom, what do you think?
>>>>>
>>>>> Michael
>>>>>
>>>>> -----Original Message----- From: David A. Mellis
>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>> To: Michael Margolis
>>>>> Cc: Tom Igoe ;
>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>
>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>> allows people to be explicit about how to handle situations in which
>>>>> the prefix isn't found or when to stop looking for it.
>>>>>
>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>> strings - and making people read data from the Serial port into a
>>>>> string before converting it to a number.
>>>>>
>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>> instead.
>>>>>
>>>>> How does that sound?
>>>>>
>>>>>
>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>> <> wrote:
>>>>>>
>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>> rename  the getString method as follows:
>>>>>>
>>>>>> int readString( char *pre_string, char  post_string, char *buffer, int
>>>>>> length); // read into a static character buffer
>>>>>>
>>>>>> note that the post string argument changed from a char* to char
>>>>>>
>>>>>> I would guess that the dynamic String methods could be something like
>>>>>> this:
>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>> limited
>>>>>> String len may cause unexpected results
>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>> ncountered  -
>>>>>> Warning as above
>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>> find(pre_string) and
>>>>>> readStringUntil(post_char)
>>>>>>
>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>> whichever
>>>>>> brave soul volunteers to implement the dynamic String methods.  I am a
>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>> dynamic
>>>>>> String functionality in stream should be implemented.
>>>>>>
>>>>>> Michael Margolis
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>> To: Tom Igoe
>>>>>> Cc: Michael Margolis ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>> like:
>>>>>>
>>>>>> if (Serial.find(""))
>>>>>> head = Serial.readStringUntil('<');
>>>>>>
>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>> result if you run out of room in the buffer.  (Do you throw out older
>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>> it's
>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>> and
>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>> on a
>>>>>>> stream.  I've had some cases where I needed to switch from find() to
>>>>>>> a
>>>>>>> character based search. For example, if I'm looking for
>>>>>>>
>>>>>>> This is what I want
>>>>>>>
>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>> I'm
>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>
>>>>>>> and
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> David, thanks for your comments.
>>>>>>>>
>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>> value of
>>>>>>>>> 0?
>>>>>>>>
>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>> will
>>>>>>>> be most useful.
>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>> API
>>>>>>>> with features that are not likely to be used.
>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>> user
>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>> defines
>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>> setDecimalPointChar() could  be added if this functionality was only
>>>>>>>> needed
>>>>>>>> in this API.
>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>
>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>
>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>> else
>>>>>>>> regarding this API.
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc:
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Thanks for the proposal!
>>>>>>>>
>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>> we
>>>>>>>> should keep in mind?
>>>>>>>>
>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>> than
>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>> timeout and a real value of 0?
>>>>>>>>
>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>> supporting
>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>
>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>> doubles.
>>>>>>>> The word "value" seems very generic.
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>> finding and
>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>> by
>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>> for
>>>>>>>>> the
>>>>>>>>> incoming data.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>> (with
>>>>>>>>> help
>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>> implements
>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>> Ethernet
>>>>>>>>> are
>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>> implementation or examples.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> setTimeout()
>>>>>>>>>
>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>> character
>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>> is
>>>>>>>>> used
>>>>>>>>> by all of the other parsing  methods and could be useful for other
>>>>>>>>> stream
>>>>>>>>> functions.
>>>>>>>>>
>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>
>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>
>>>>>>>>> Returns: nothing
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> find()
>>>>>>>>>
>>>>>>>>> Description:  Reads data from the stream until the target string is
>>>>>>>>> found
>>>>>>>>>
>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>> search
>>>>>>>>> for
>>>>>>>>>
>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>> including
>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>> the
>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>
>>>>>>>>>   // here if the string "GET /" is found in the stream
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // here if find method timed out (stream buffer is empty)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> findUntil()
>>>>>>>>>
>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>> found.
>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>
>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>
>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>> for,
>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>> the
>>>>>>>>> search
>>>>>>>>> if found in the stream.
>>>>>>>>>
>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>> terminateStr is encountered.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>
>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>
>>>>>>>>>   // here if “pin” is found in the current line
>>>>>>>>>
>>>>>>>>> else
>>>>>>>>>
>>>>>>>>>   // stream buffer is at the beginning of the next line
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>> implemented
>>>>>>>>> if
>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>> pointer
>>>>>>>>> to a
>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>> functionally
>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>> target
>>>>>>>>> and
>>>>>>>>> terminate strings.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue()
>>>>>>>>>
>>>>>>>>> Description:  Returns the first valid (long) integer value from the
>>>>>>>>> current
>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>> sign)
>>>>>>>>> are
>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>> a
>>>>>>>>> digit
>>>>>>>>> following one or more valid digits.
>>>>>>>>>
>>>>>>>>> Syntax: getvalue()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>> integer
>>>>>>>>> values
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>
>>>>>>>>>  Serial.println(value);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getValue(skipChar)
>>>>>>>>>
>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>
>>>>>>>>> int value;
>>>>>>>>>
>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat()
>>>>>>>>>
>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>
>>>>>>>>> Syntax: getFloat()
>>>>>>>>>
>>>>>>>>> Parameters: none
>>>>>>>>>
>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>> allows
>>>>>>>>> format
>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>
>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>
>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>
>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>
>>>>>>>>> float value;
>>>>>>>>>
>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>
>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> getString()
>>>>>>>>>
>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>> stores
>>>>>>>>> into
>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>> length.
>>>>>>>>> The
>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>> that
>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>
>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>
>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>> string,
>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>> the
>>>>>>>>> first
>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>
>>>>>>>>> Returns:  Returns the number of characters placed in the buffer (0
>>>>>>>>> means
>>>>>>>>> no
>>>>>>>>> valid data found)
>>>>>>>>>
>>>>>>>>> Example:
>>>>>>>>>
>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>> terminating null
>>>>>>>>>
>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>
>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>
>>>>>>>>>  {
>>>>>>>>>
>>>>>>>>>     Serial.print("found ");
>>>>>>>>>
>>>>>>>>>     Serial.println(buffer);
>>>>>>>>>
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>
>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----
>>>>>>>>>
>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>> suggest
>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>
>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>> Stream.cpp
>>>>>>>>> to
>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Developers mailing list
>>>>>>>>
>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I don't agree about the prefix change. Before Michael's explanation of getString() I might have agreed, but having tried it, I think it makes a lot of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I don't think it's necessary. I think Michael's argument about get() in this case is valid, but if there's consensus on read() and write() I won't object.

I'd recommend keeping the int return type on readString() or getString(). It's valuable to know how big long actual returned array is, vs. what you allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do think
>> that users would prefer having the get functions as a stream method rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter reading
>>>>> through Dave's proposal, I tried to think through how to explain the code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just strings.
>>>>> And as Michael points out getInt() does more than just the casting, it also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like names
>>>>>> that are evocative of their functionality and 'get' naming was chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for this API
>>>>>> (it is for me, and most of my web parsing applications seem to use the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions of
>>>>>> readString() and readStringUntil() that accept an existing byte buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer, int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find() to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
Seems like there are three outstanding issues:

1. Orthogonal method naming: for example, should the method be called
readInt or getInt
2. Should readString/getString have a prestring argument.
3. Should readString/getString return a String or the number of bytes
stored


On the first point, I don’t think the functionality of getInt/getFloat
methods etc is orthogonal with the current stream method to read a
character. read returns the next char in the stream, getInt reads as many
characters as required until it finds one or more ASCII digits and converts
these to an integer. I would expect an orthogonal implementation of readInt
to return the integer value of the next two bytes in the stream. Such a
method could be useful for reading data packed into a binary structure. I am
not suggesting we include this (although it would be easy to implement if
you wanted it) but I do feel that the rather different functionality of the
proposed getInt deserves a name that differentiates from a simple read of a
data type.

Regarding point 2, we could support both version of read/getString – one
without the prestring and one with:
getString( endchar, buffer, length) // all characters up to but excluding
endchar will be copied to the buffer (if the buffer is smaller than length,
the string will be truncated .)
and:
getString(prestring, endchar, buffer, length) // as above but seeks to the
first character following prestring.

There is no performance or resource overhead in the latter getString, it
uses the find method internally - I think this is just a question of which
is easier for the user to type and understand.

Regarding the return type of readString/getString, I would be uncomfortable
if a method was not available that returned the number of bytes collected.
Perhaps that’s just me. Feel free to add method that returned a String if
you feel this was also needed but I don’t feel qualified to implement that
for the Arduino runtime environment.

Michael

-----Original Message-----
From: Tom Igoe
Sent: Tuesday, June 07, 2011 4:34 PM
To: David A. Mellis
Cc: Michael Margolis ;
Subject: Re: [Developers] Adding parsing to Stream

I don't agree about the prefix change. Before Michael's explanation of
getString() I might have agreed, but having tried it, I think it makes a lot
of sense. There's a lot of value in having the prefix. For example,

result = response.getString("", "", tweetBuffer, 140);

returns something very different than

result = response.getString(", tweetBuffer, 150);

and I don't think the following makes anything clearer:

response.find("");
response.getString("
", tweetBuffer, 150);

Is there something I'm misunderstanding about your argument?


The main thing that would make things clearer to me would be:

tweetBuffer = response.getString("", "", 140);

But I understand why that's a bad idea.


I understand your desire to use read() and write() where possible, though I
don't think it's necessary. I think Michael's argument about get() in this
case is valid, but if there's consensus on read() and write() I won't
object.

I'd recommend keeping the int return type on readString() or getString().
It's valuable to know how big long actual returned array is, vs. what you
allocated.



On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:

> Yeah, you're right... the memory constraints on Arduino make it
> unreasonable to first read strings and then parse them (like in
> Processing) and it seems silly for such functionality not to be in the
> core somewhere.
>
> Can we go with the names readInt() and readFloat()?
>
> Can we omit the prefix parameters from readString() and
> readStringUntil() - i.e. require a preceding call to find()? I know
> this makes string extraction a bit more verbose, but I think it also
> makes it more clear. In general, I've been trying to keep the API's
> orthogonal and simple, even if it means sometimes using more than one
> function call instead of one call to a more complex function.
>
> And the setTimeout() argument should probably be in milliseconds, not
> seconds, both for consistency with the pulseIn() functions and to
> allow finer control.
>
> I'd suggest, then:
>
> setTimeout(ms)
> find(target) // String or char *
> findUntil(target, terminator) // String or char *
> readInt() / readInt(skipchar)
> readFloat() / readFloat(skipchar)
> readString()
> readStringUntil(endchar)
> readBytes(buf, buflen)
> readBytesUntil(endchar, buf, buflen)
>
> Is that okay?
>
> I'm still curious if people have any other requirements in terms of
> numeric formats that they'd like readInt() or readFloat() to support.
> For example, do you need to be able to specify the character that
> separates the whole from the decimal part of the float?
>
> David
>
> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
> wrote:
>> I think the methods to get numeric values (getInt and getFloat) would
>> probably be more used with Serial than find() an findUntil().
>>
>> I have no objection to TextFinder being included as a library but do
>> think
>> that users would prefer having the get functions as a stream method
>> rather
>> than having to explicitly instantiate the TextFinder class, as would be
>> required if a separate library.
>>
>> The need to do the following in a sketch (if implemented as a library) is
>> not onerous
>>
>> #include
>> TextFinder finder(Serial);
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = finder.getInt(); // return the next integer value on the
>> Serial
>> stream
>>
>> }
>>
>>
>> but this seems simpler and clearer
>>
>> void setup()
>> {
>> Serial.begin(9600);
>> int val = Serial.getInt(); // return the next integer value on the
>> Serial
>> stream
>> }
>>
>> void loop();
>>
>> Michael
>>
>> --------------------------------------------------
>> From: "Tom Igoe" <>
>> Sent: Sunday, June 05, 2011 8:48 PM
>> To: "David A. Mellis" <>
>> Cc: "Michael Margolis" <>; <>
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>>> I think textFinder is good for things other than web pages, but I am in
>>> favor of a small core. How would you feel about including TextFinder in
>>> the
>>> standard distribution, assuming Michael agreed? That might offer a
>>> reasonable compromise of small core, but easy access to the functions.
>>>
>>> t.
>>>
>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>
>>>> The more I think about this, the more I feel like maybe we should only
>>>> add the find() and findUntil() methods to stream (with some method for
>>>> setting the timeout). The other functionality feels fairly specific
>>>> to parsing webpages, which isn't something that feels like it needs to
>>>> be supported by the Stream class itself. That is, maybe we should
>>>> plan to continue to have a separate TextFinder library for more
>>>> complex parsing tasks, and only integrate the functionality that
>>>> applicable to wide range of stream types to the Stream interface
>>>> itself.
>>>>
>>>> In general, I'm trying to keep the core API small - with the
>>>> understanding that lots of useful, real-world examples will still
>>>> require third-party libraries. Including extra parsing functions
>>>> starts to feel in conflict with this general philosophy and I worry
>>>> that it will be inconsistent with other portions of the API.
>>>>
>>>> Thoughts?
>>>>
>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>
>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>
>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>> reading
>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>> code
>>>>> and realized it'd take me longer to explain with find() then
>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>> getString().
>>>>>
>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>> strings.
>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>> also
>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>> getInt() and int() are different things, no?
>>>>>
>>>>> As for read() vs get() naming, I could go either way.
>>>>>
>>>>> t.
>>>>>
>>>>>
>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>
>>>>>> I am open to whatever method names are most suitable but I like
>>>>>> names
>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>> chosen over
>>>>>> read because these methods do more than just read . I also think the
>>>>>> string parsing method as proposed is easier to use for getting
>>>>>> string
>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>
>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>> getting a string between two tokens is an important capability for
>>>>>> this API
>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>> the
>>>>>> current getString) then it would be a shame to lose this.
>>>>>>
>>>>>> Tom, what do you think?
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> -----Original Message----- From: David A. Mellis
>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>> To: Michael Margolis
>>>>>> Cc: Tom Igoe ;
>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>
>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>> readString()
>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>> allows people to be explicit about how to handle situations in which
>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>
>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>> strings - and making people read data from the Serial port into a
>>>>>> string before converting it to a number.
>>>>>>
>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>> of
>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>> buffer
>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>> instead.
>>>>>>
>>>>>> How does that sound?
>>>>>>
>>>>>>
>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>> <> wrote:
>>>>>>>
>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>> we
>>>>>>> rename the getString method as follows:
>>>>>>>
>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>> int
>>>>>>> length); // read into a static character buffer
>>>>>>>
>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>
>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>> like
>>>>>>> this:
>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>> limited
>>>>>>> String len may cause unexpected results
>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>> ncountered -
>>>>>>> Warning as above
>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>> find(pre_string) and
>>>>>>> readStringUntil(post_char)
>>>>>>>
>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>> is
>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>> whichever
>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>> a
>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>> dynamic
>>>>>>> String functionality in stream should be implemented.
>>>>>>>
>>>>>>> Michael Margolis
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>> To: Tom Igoe
>>>>>>> Cc: Michael Margolis ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>> like:
>>>>>>>
>>>>>>> if (Serial.find(""))
>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>
>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>> older
>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>> and
>>>>>>>> it's
>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>> and
>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>> on a
>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>> to
>>>>>>>> a
>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>
>>>>>>>> This is what I want
>>>>>>>>
>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>> I'm
>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>> between
>>>>>>>>
>>>>>>>> and
>>>>>>>>
>>>>>>>> t.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>
>>>>>>>>> David, thanks for your comments.
>>>>>>>>>
>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>> character?
>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>> value of
>>>>>>>>>> 0?
>>>>>>>>>
>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>> will
>>>>>>>>> be most useful.
>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>> the
>>>>>>>>> API
>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>> user
>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>> Arduino
>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>> defines
>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>> only
>>>>>>>>> needed
>>>>>>>>> in this API.
>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>
>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>
>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>> else
>>>>>>>>> regarding this API.
>>>>>>>>>
>>>>>>>>> Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>> To: Michael Margolis
>>>>>>>>> Cc:
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> Thanks for the proposal!
>>>>>>>>>
>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>> we
>>>>>>>>> should keep in mind?
>>>>>>>>>
>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>> than
>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>
>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>> supporting
>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>
>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>> doubles.
>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>> <> wrote:
>>>>>>>>>>
>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>> finding and
>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>> by
>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>> for
>>>>>>>>>> the
>>>>>>>>>> incoming data.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>> (with
>>>>>>>>>> help
>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>> implements
>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>> Ethernet
>>>>>>>>>> are
>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>> API,
>>>>>>>>>> implementation or examples.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> setTimeout()
>>>>>>>>>>
>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>> character
>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>> value
>>>>>>>>>> is
>>>>>>>>>> used
>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>> other
>>>>>>>>>> stream
>>>>>>>>>> functions.
>>>>>>>>>>
>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>
>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>
>>>>>>>>>> Returns: nothing
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> find()
>>>>>>>>>>
>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>> is
>>>>>>>>>> found
>>>>>>>>>>
>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>> to
>>>>>>>>>> search
>>>>>>>>>> for
>>>>>>>>>>
>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>> including
>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>> the
>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>
>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> findUntil()
>>>>>>>>>>
>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>> found.
>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>> token.
>>>>>>>>>>
>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>
>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>> for,
>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>> the
>>>>>>>>>> search
>>>>>>>>>> if found in the stream.
>>>>>>>>>>
>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>
>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>
>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>
>>>>>>>>>> else
>>>>>>>>>>
>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>> implemented
>>>>>>>>>> if
>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>> pointer
>>>>>>>>>> to a
>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>> functionally
>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>> target
>>>>>>>>>> and
>>>>>>>>>> terminate strings.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue()
>>>>>>>>>>
>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>> the
>>>>>>>>>> current
>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>> minus
>>>>>>>>>> sign)
>>>>>>>>>> are
>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>> not
>>>>>>>>>> a
>>>>>>>>>> digit
>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>> integer
>>>>>>>>>> values
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>
>>>>>>>>>> Serial.println(value);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> int value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat()
>>>>>>>>>>
>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>
>>>>>>>>>> Parameters: none
>>>>>>>>>>
>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>> allows
>>>>>>>>>> format
>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>
>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>
>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>
>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>
>>>>>>>>>> float value;
>>>>>>>>>>
>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>
>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> getString()
>>>>>>>>>>
>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>> stores
>>>>>>>>>> into
>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>> length.
>>>>>>>>>> The
>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>> preString
>>>>>>>>>> that
>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>
>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>
>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>> string,
>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>> the
>>>>>>>>>> first
>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>> buffer.
>>>>>>>>>>
>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>> (0
>>>>>>>>>> means
>>>>>>>>>> no
>>>>>>>>>> valid data found)
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>> terminating null
>>>>>>>>>>
>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>
>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>>
>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>
>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>
>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>> from
>>>>>>>>>> the
>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----
>>>>>>>>>>
>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>> suggest
>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>
>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>> Stream.cpp
>>>>>>>>>> to
>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Michael Margolis
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Developers mailing list
>>>>>>>>>
>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>>


_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
To take your issues in turn:

1. getInt() / getFloat() sound like simple accessors, i.e. methods
that return existing values rather than actually doing work.
Therefore, the confusion added by using different names for different
types (i.e. read() for chars, getInt() for ints) isn't offset by a
corresponding increase in clarity. If we want a different name, we
should use something suggestive of the work being done, e.g.
parseInt() and parseFloat(). Otherwise, I think we should just stick
with read for consistency.

2. readString() with a prefix isn't orthogonal to find() plus
readString() without a prefix. In general, if we offer a function for
A and another function for B, we should avoid functions that do both A
and B. By offering more than one way to do the same thing, you force
people to figure out whether the two options are the same, to decide
which one to use, and to recognize both approaches when reading code.
I'd rather reduce confusion at the cost of an extra line of code.

In this case, it's even more confusing because we're offering multiple
ways to search for the prefix (with or without a terminator) and more
than one way to retrieve the string (also with and without a
terminator). But a readString() method that accepts a prefix and a
suffix covers only one of those four cases, forcing people to fall
back on separate statements for the other three. This just increases
the difficulty of distinguishing and deciding between using two
separate calls or one combined one. I'd rather avoid the confusion
and just offer one way to do it.

3. I'd like to offer methods that store data into an existing buffer
and methods that return a newly-formed String. For consistency with
the naming in Processing (although with slightly different syntax),
let's use readBytes() and readBytesUntil() to store the data into an
existing buffer (returning the number of bytes read) and readString()
and readStringUntil() to return a newly-formed String (whose length
can be queried).

What do you think?

On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
> Seems like there are three outstanding issues:
>
> 1.    Orthogonal method naming: for example, should the method be called
> readInt or getInt
> 2.    Should readString/getString have a prestring argument.
> 3.    Should readString/getString return a String or the number of bytes
> stored
>
>
> On the first point, I don’t think the functionality of getInt/getFloat
> methods etc is orthogonal with the current stream method to read a
> character. read returns the next char in the stream, getInt reads as many
> characters as required until it finds one or more ASCII digits and converts
> these to an integer. I would expect an orthogonal implementation of readInt
> to return the integer value of the next two bytes in the stream. Such a
> method could be useful for reading data packed into a binary structure. I am
> not suggesting we include this (although it would be easy to implement if
> you wanted it) but I do feel that the rather different functionality of the
> proposed getInt deserves a name that differentiates from a simple read of a
> data type.
>
> Regarding point 2, we could support both version of read/getString – one
> without the prestring and one with:
> getString( endchar, buffer, length) // all characters up to but excluding
> endchar will be copied to the buffer (if the buffer is smaller than length,
> the string will be truncated .)
> and:
> getString(prestring, endchar, buffer, length) // as above but seeks to the
> first character following prestring.
>
> There is no performance or resource overhead in the latter getString, it
> uses the find method internally - I think this is just a question of which
> is easier for the user to type and understand.
>
> Regarding the return type of readString/getString, I would be uncomfortable
> if a method was not available that returned the number of bytes collected.
> Perhaps that’s just me. Feel free to add method that returned a String if
> you feel this was also needed but I don’t feel qualified to implement that
> for the Arduino runtime environment.
>
> Michael
>
> -----Original Message----- From: Tom Igoe
> Sent: Tuesday, June 07, 2011 4:34 PM
> To: David A. Mellis
> Cc: Michael Margolis ;
> Subject: Re: [Developers] Adding parsing to Stream
>
> I don't agree about the prefix change.  Before Michael's explanation of
> getString() I might have agreed, but having tried it, I think it makes a lot
> of sense. There's a lot of value in having the prefix. For example,
>
>     result = response.getString("", "", tweetBuffer, 140);
>
> returns something very different than
>
>     result = response.getString(", tweetBuffer, 150);
>
> and I don't think the following makes anything clearer:
>
>      response.find("");
>      response.getString("
", tweetBuffer, 150);
>
> Is there something I'm misunderstanding about your argument?
>
>
> The main thing that would make things clearer to me  would be:
>
>  tweetBuffer = response.getString("", "", 140);
>
> But I understand why that's a bad idea.
>
>
> I understand your desire to use read() and write()  where possible, though I
> don't think it's necessary. I think Michael's argument about get() in this
> case is valid, but if there's consensus on read() and write() I won't
> object.
>
> I'd recommend keeping the int return type on readString() or getString().
> It's valuable to know how big long actual returned array is, vs. what you
> allocated.
>
>
>
> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>
>> Yeah, you're right...  the memory constraints on Arduino make it
>> unreasonable to first read strings and then parse them (like in
>> Processing) and it seems silly for such functionality not to be in the
>> core somewhere.
>>
>> Can we go with the names readInt() and readFloat()?
>>
>> Can we omit the prefix parameters from readString() and
>> readStringUntil() - i.e. require a preceding call to find()?  I know
>> this makes string extraction a bit more verbose, but I think it also
>> makes it more clear.  In general, I've been trying to keep the API's
>> orthogonal and simple, even if it means sometimes using more than one
>> function call instead of one call to a more complex function.
>>
>> And the setTimeout() argument should probably be in milliseconds, not
>> seconds, both for consistency with the pulseIn() functions and to
>> allow finer control.
>>
>> I'd suggest, then:
>>
>> setTimeout(ms)
>> find(target) // String or char *
>> findUntil(target, terminator) // String or char *
>> readInt() / readInt(skipchar)
>> readFloat() / readFloat(skipchar)
>> readString()
>> readStringUntil(endchar)
>> readBytes(buf, buflen)
>> readBytesUntil(endchar, buf, buflen)
>>
>> Is that okay?
>>
>> I'm still curious if people have any other requirements in terms of
>> numeric formats that they'd like readInt() or readFloat() to support.
>> For example, do you need to be able to specify the character that
>> separates the whole from the decimal part of the float?
>>
>> David
>>
>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>> wrote:
>>>
>>> I think the methods to get numeric values (getInt and getFloat) would
>>> probably be more used with Serial than find() an findUntil().
>>>
>>> I have no objection to TextFinder being included as a library but do
>>> think
>>> that users would prefer having the get functions as a stream method
>>> rather
>>> than having to explicitly instantiate the TextFinder class, as would be
>>> required if a separate library.
>>>
>>> The need to do the following in a sketch (if implemented as a library) is
>>> not onerous
>>>
>>> #include
>>> TextFinder  finder(Serial);
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = finder.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>>
>>> }
>>>
>>>
>>> but this seems simpler and clearer
>>>
>>> void setup()
>>> {
>>>  Serial.begin(9600);
>>>  int  val = Serial.getInt(); // return the next integer value on the
>>> Serial
>>> stream
>>> }
>>>
>>> void loop();
>>>
>>> Michael
>>>
>>> --------------------------------------------------
>>> From: "Tom Igoe" <>
>>> Sent: Sunday, June 05, 2011 8:48 PM
>>> To: "David A. Mellis" <>
>>> Cc: "Michael Margolis" <>; <>
>>> Subject: Re: [Developers] Adding parsing to Stream
>>>
>>>> I think textFinder is good for things other than web pages, but I am in
>>>> favor of a small core.  How would you feel about including TextFinder in
>>>> the
>>>> standard distribution, assuming Michael agreed? That might offer a
>>>> reasonable compromise of small core, but easy access to the functions.
>>>>
>>>> t.
>>>>
>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>
>>>>> The more I think about this, the more I feel like maybe we should only
>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>> setting the timeout).  The other functionality feels fairly specific
>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>> be supported by the Stream class itself.  That is, maybe we should
>>>>> plan to continue to have a separate TextFinder library for more
>>>>> complex parsing tasks, and only integrate the functionality that
>>>>> applicable to wide range of stream types to the Stream interface
>>>>> itself.
>>>>>
>>>>> In general, I'm trying to keep the core API small - with the
>>>>> understanding that lots of useful, real-world examples will still
>>>>> require third-party libraries.  Including extra parsing functions
>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>> that it will be inconsistent with other portions of the API.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>
>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>
>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>> reading
>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>> code
>>>>>> and realized it'd take me longer to explain with find() then
>>>>>> readStringUntil() than it would with getString().  So I prefer
>>>>>> getString().
>>>>>>
>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>> strings.
>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>> also
>>>>>> finds the next int in the string, and then casts it.  So conceptually,
>>>>>> getInt() and int() are different things, no?
>>>>>>
>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>
>>>>>> t.
>>>>>>
>>>>>>
>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>
>>>>>>> I am open to whatever method names are most suitable but  I like
>>>>>>> names
>>>>>>> that are evocative of their functionality and 'get' naming  was
>>>>>>> chosen over
>>>>>>> read because these methods do more than just read .  I also think the
>>>>>>>  string parsing method as proposed is easier to use for getting
>>>>>>> string
>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>
>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>> as we don’t sacrifice clarity or usability.    It seems to me that if
>>>>>>> getting a string between two tokens is  an important capability for
>>>>>>> this API
>>>>>>>  (it is for me, and most of my web parsing applications seem to use
>>>>>>> the
>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>
>>>>>>> Tom, what do you think?
>>>>>>>
>>>>>>> Michael
>>>>>>>
>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>> To: Michael Margolis
>>>>>>> Cc: Tom Igoe ;
>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>
>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>> readString()
>>>>>>> or readStringUntil().  That eliminates redundancy from the API and
>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>
>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>> with readString() instead of getInt() and getFloat()?  Although I
>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>> string before converting it to a number.
>>>>>>>
>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>> of
>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>> buffer
>>>>>>> into which to store the bytes (along with the buffer length).  Then,
>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>> instead.
>>>>>>>
>>>>>>> How does that sound?
>>>>>>>
>>>>>>>
>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>> <> wrote:
>>>>>>>>
>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>> we
>>>>>>>> rename  the getString method as follows:
>>>>>>>>
>>>>>>>> int readString( char *pre_string, char  post_string, char *buffer,
>>>>>>>> int
>>>>>>>> length); // read into a static character buffer
>>>>>>>>
>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>
>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>> like
>>>>>>>> this:
>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>> limited
>>>>>>>> String len may cause unexpected results
>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>> ncountered  -
>>>>>>>> Warning as above
>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>> find(pre_string) and
>>>>>>>> readStringUntil(post_char)
>>>>>>>>
>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>> is
>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>> whichever
>>>>>>>> brave soul volunteers to implement the dynamic String methods.  I am
>>>>>>>> a
>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>> dynamic
>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>
>>>>>>>> Michael Margolis
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>> To: Tom Igoe
>>>>>>>> Cc: Michael Margolis ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>> like:
>>>>>>>>
>>>>>>>> if (Serial.find(""))
>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>
>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>> result if you run out of room in the buffer.  (Do you throw out
>>>>>>>> older
>>>>>>>> characters or newer ones?  How do you tell if it's happened?)
>>>>>>>>
>>>>>>>> David
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>> and
>>>>>>>>> it's
>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>> and
>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>> on a
>>>>>>>>> stream.  I've had some cases where I needed to switch from find()
>>>>>>>>> to
>>>>>>>>> a
>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>
>>>>>>>>> This is what I want
>>>>>>>>>
>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>> I'm
>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>> between
>>>>>>>>>
>>>>>>>>> and
>>>>>>>>>
>>>>>>>>> t.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>
>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>
>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>> character?
>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>> value of
>>>>>>>>>>> 0?
>>>>>>>>>>
>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>> will
>>>>>>>>>> be most useful.
>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>> the
>>>>>>>>>> API
>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>> user
>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>> Arduino
>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>> defines
>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>> setDecimalPointChar() could  be added if this functionality was
>>>>>>>>>> only
>>>>>>>>>> needed
>>>>>>>>>> in this API.
>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>
>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>
>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>> else
>>>>>>>>>> regarding this API.
>>>>>>>>>>
>>>>>>>>>> Michael
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>> To: Michael Margolis
>>>>>>>>>> Cc:
>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>
>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>
>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>> we
>>>>>>>>>> should keep in mind?
>>>>>>>>>>
>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>> getValue() functions.  Would you want to be able to specify more
>>>>>>>>>> than
>>>>>>>>>> one skip character?  Do we need some way to distinguish between a
>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>
>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>> supporting
>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>
>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>> doubles.
>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>
>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>> <> wrote:
>>>>>>>>>>>
>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>> finding and
>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>> by
>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>> for
>>>>>>>>>>> the
>>>>>>>>>>> incoming data.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I  wrote
>>>>>>>>>>> (with
>>>>>>>>>>> help
>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>> implements
>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>> Ethernet
>>>>>>>>>>> are
>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>> API,
>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> setTimeout()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Sets the maximum number of seconds to wait for a
>>>>>>>>>>> character
>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>> value
>>>>>>>>>>> is
>>>>>>>>>>> used
>>>>>>>>>>> by all of the other parsing  methods and could be useful for
>>>>>>>>>>> other
>>>>>>>>>>> stream
>>>>>>>>>>> functions.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>
>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> find()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Reads data from the stream until the target string
>>>>>>>>>>> is
>>>>>>>>>>> found
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  find(targetStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>> to
>>>>>>>>>>> search
>>>>>>>>>>> for
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>> including
>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>> the
>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> if( client.find("GET /") ) {  // search for 'GET'
>>>>>>>>>>>
>>>>>>>>>>>  // here if the string "GET /" is found in the stream
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> findUntil()
>>>>>>>>>>>
>>>>>>>>>>> Description:  As find but search ends if the terminate string is
>>>>>>>>>>> found.
>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>> token.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>> for,
>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>> the
>>>>>>>>>>> search
>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>
>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>
>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>
>>>>>>>>>>>  // here if “pin” is found in the current line
>>>>>>>>>>>
>>>>>>>>>>> else
>>>>>>>>>>>
>>>>>>>>>>>  // stream buffer is at the beginning of the next line
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>> implemented
>>>>>>>>>>> if
>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>> pointer
>>>>>>>>>>> to a
>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>> functionally
>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>> target
>>>>>>>>>>> and
>>>>>>>>>>> terminate strings.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Returns the first valid (long) integer value from
>>>>>>>>>>> the
>>>>>>>>>>> current
>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>> minus
>>>>>>>>>>> sign)
>>>>>>>>>>> are
>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>> not
>>>>>>>>>>> a
>>>>>>>>>>> digit
>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>> integer
>>>>>>>>>>> values
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> for(int Index = 0; Index  < 3; Index ++)
>>>>>>>>>>>
>>>>>>>>>>> {
>>>>>>>>>>>
>>>>>>>>>>>  value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>
>>>>>>>>>>>  Serial.println(value);
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> int value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Description:  float version of getValue.
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>
>>>>>>>>>>> Parameters: none
>>>>>>>>>>>
>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12.34
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Description:  As above but the given skipChar is ignored. This
>>>>>>>>>>> allows
>>>>>>>>>>> format
>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>
>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>
>>>>>>>>>>> Parameters:  skipChar: a character to ignore
>>>>>>>>>>>
>>>>>>>>>>> Returns:  floating point value or 0 if timeout.
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>
>>>>>>>>>>> float value;
>>>>>>>>>>>
>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>
>>>>>>>>>>> Serial.println(value);  // prints 12345.67
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> getString()
>>>>>>>>>>>
>>>>>>>>>>> Description:  Finds a string between pre and post delimiters and
>>>>>>>>>>> stores
>>>>>>>>>>> into
>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>> length.
>>>>>>>>>>> The
>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>> preString
>>>>>>>>>>> that
>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>
>>>>>>>>>>> Syntax:  getString(preString, postString, buffer,  length)
>>>>>>>>>>>
>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>> string,
>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>> the
>>>>>>>>>>> first
>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>> buffer.
>>>>>>>>>>>
>>>>>>>>>>> Returns:  Returns the number of characters placed in the buffer
>>>>>>>>>>> (0
>>>>>>>>>>> means
>>>>>>>>>>> no
>>>>>>>>>>> valid data found)
>>>>>>>>>>>
>>>>>>>>>>> Example:
>>>>>>>>>>>
>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>> terminating null
>>>>>>>>>>>
>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>
>>>>>>>>>>>  if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>
>>>>>>>>>>>  {
>>>>>>>>>>>
>>>>>>>>>>>    Serial.print("found ");
>>>>>>>>>>>
>>>>>>>>>>>    Serial.println(buffer);
>>>>>>>>>>>
>>>>>>>>>>>  }
>>>>>>>>>>>
>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>
>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>> from
>>>>>>>>>>> the
>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----
>>>>>>>>>>>
>>>>>>>>>>> This functionality has worked quite well for me but feel free to
>>>>>>>>>>> suggest
>>>>>>>>>>> improvements to the API, implementation or documentation.
>>>>>>>>>>>
>>>>>>>>>>> You can run the examples in the zip by copying Stream.h and
>>>>>>>>>>> Stream.cpp
>>>>>>>>>>> to
>>>>>>>>>>> the cores > arduino directory of the 1.0 beta.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Michael Margolis
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Developers mailing list
>>>>>>>>>>>
>>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Developers mailing list
>>>>>>>>>>
>>>>>>>>>> http://arduino.cc/mailman/listinfo/developers_arduino.cc
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>>
>
>

_______________________________________________
Developers mailing list

http://arduino.cc/mailman/listinfo/developers_arduino.cc
)
I agree with 3). I think you are wrong on 1) and 2).

t.

On Jun 8, 2011, at 10:53 PM, David A. Mellis wrote:

> To take your issues in turn:
>
> 1. getInt() / getFloat() sound like simple accessors, i.e. methods
> that return existing values rather than actually doing work.
> Therefore, the confusion added by using different names for different
> types (i.e. read() for chars, getInt() for ints) isn't offset by a
> corresponding increase in clarity. If we want a different name, we
> should use something suggestive of the work being done, e.g.
> parseInt() and parseFloat(). Otherwise, I think we should just stick
> with read for consistency.
>
> 2. readString() with a prefix isn't orthogonal to find() plus
> readString() without a prefix. In general, if we offer a function for
> A and another function for B, we should avoid functions that do both A
> and B. By offering more than one way to do the same thing, you force
> people to figure out whether the two options are the same, to decide
> which one to use, and to recognize both approaches when reading code.
> I'd rather reduce confusion at the cost of an extra line of code.
>
> In this case, it's even more confusing because we're offering multiple
> ways to search for the prefix (with or without a terminator) and more
> than one way to retrieve the string (also with and without a
> terminator). But a readString() method that accepts a prefix and a
> suffix covers only one of those four cases, forcing people to fall
> back on separate statements for the other three. This just increases
> the difficulty of distinguishing and deciding between using two
> separate calls or one combined one. I'd rather avoid the confusion
> and just offer one way to do it.
>
> 3. I'd like to offer methods that store data into an existing buffer
> and methods that return a newly-formed String. For consistency with
> the naming in Processing (although with slightly different syntax),
> let's use readBytes() and readBytesUntil() to store the data into an
> existing buffer (returning the number of bytes read) and readString()
> and readStringUntil() to return a newly-formed String (whose length
> can be queried).
>
> What do you think?
>
> On Tue, Jun 7, 2011 at 3:54 PM, Michael Margolis <> wrote:
>> Seems like there are three outstanding issues:
>>
>> 1. Orthogonal method naming: for example, should the method be called
>> readInt or getInt
>> 2. Should readString/getString have a prestring argument.
>> 3. Should readString/getString return a String or the number of bytes
>> stored
>>
>>
>> On the first point, I don’t think the functionality of getInt/getFloat
>> methods etc is orthogonal with the current stream method to read a
>> character. read returns the next char in the stream, getInt reads as many
>> characters as required until it finds one or more ASCII digits and converts
>> these to an integer. I would expect an orthogonal implementation of readInt
>> to return the integer value of the next two bytes in the stream. Such a
>> method could be useful for reading data packed into a binary structure. I am
>> not suggesting we include this (although it would be easy to implement if
>> you wanted it) but I do feel that the rather different functionality of the
>> proposed getInt deserves a name that differentiates from a simple read of a
>> data type.
>>
>> Regarding point 2, we could support both version of read/getString – one
>> without the prestring and one with:
>> getString( endchar, buffer, length) // all characters up to but excluding
>> endchar will be copied to the buffer (if the buffer is smaller than length,
>> the string will be truncated .)
>> and:
>> getString(prestring, endchar, buffer, length) // as above but seeks to the
>> first character following prestring.
>>
>> There is no performance or resource overhead in the latter getString, it
>> uses the find method internally - I think this is just a question of which
>> is easier for the user to type and understand.
>>
>> Regarding the return type of readString/getString, I would be uncomfortable
>> if a method was not available that returned the number of bytes collected.
>> Perhaps that’s just me. Feel free to add method that returned a String if
>> you feel this was also needed but I don’t feel qualified to implement that
>> for the Arduino runtime environment.
>>
>> Michael
>>
>> -----Original Message----- From: Tom Igoe
>> Sent: Tuesday, June 07, 2011 4:34 PM
>> To: David A. Mellis
>> Cc: Michael Margolis ;
>> Subject: Re: [Developers] Adding parsing to Stream
>>
>> I don't agree about the prefix change. Before Michael's explanation of
>> getString() I might have agreed, but having tried it, I think it makes a lot
>> of sense. There's a lot of value in having the prefix. For example,
>>
>> result = response.getString("", "", tweetBuffer, 140);
>>
>> returns something very different than
>>
>> result = response.getString(", tweetBuffer, 150);
>>
>> and I don't think the following makes anything clearer:
>>
>> response.find("");
>> response.getString("
", tweetBuffer, 150);
>>
>> Is there something I'm misunderstanding about your argument?
>>
>>
>> The main thing that would make things clearer to me would be:
>>
>> tweetBuffer = response.getString("", "", 140);
>>
>> But I understand why that's a bad idea.
>>
>>
>> I understand your desire to use read() and write() where possible, though I
>> don't think it's necessary. I think Michael's argument about get() in this
>> case is valid, but if there's consensus on read() and write() I won't
>> object.
>>
>> I'd recommend keeping the int return type on readString() or getString().
>> It's valuable to know how big long actual returned array is, vs. what you
>> allocated.
>>
>>
>>
>> On Jun 7, 2011, at 10:15 AM, David A. Mellis wrote:
>>
>>> Yeah, you're right... the memory constraints on Arduino make it
>>> unreasonable to first read strings and then parse them (like in
>>> Processing) and it seems silly for such functionality not to be in the
>>> core somewhere.
>>>
>>> Can we go with the names readInt() and readFloat()?
>>>
>>> Can we omit the prefix parameters from readString() and
>>> readStringUntil() - i.e. require a preceding call to find()? I know
>>> this makes string extraction a bit more verbose, but I think it also
>>> makes it more clear. In general, I've been trying to keep the API's
>>> orthogonal and simple, even if it means sometimes using more than one
>>> function call instead of one call to a more complex function.
>>>
>>> And the setTimeout() argument should probably be in milliseconds, not
>>> seconds, both for consistency with the pulseIn() functions and to
>>> allow finer control.
>>>
>>> I'd suggest, then:
>>>
>>> setTimeout(ms)
>>> find(target) // String or char *
>>> findUntil(target, terminator) // String or char *
>>> readInt() / readInt(skipchar)
>>> readFloat() / readFloat(skipchar)
>>> readString()
>>> readStringUntil(endchar)
>>> readBytes(buf, buflen)
>>> readBytesUntil(endchar, buf, buflen)
>>>
>>> Is that okay?
>>>
>>> I'm still curious if people have any other requirements in terms of
>>> numeric formats that they'd like readInt() or readFloat() to support.
>>> For example, do you need to be able to specify the character that
>>> separates the whole from the decimal part of the float?
>>>
>>> David
>>>
>>> On Sun, Jun 5, 2011 at 5:32 PM, Michael Margolis <>
>>> wrote:
>>>>
>>>> I think the methods to get numeric values (getInt and getFloat) would
>>>> probably be more used with Serial than find() an findUntil().
>>>>
>>>> I have no objection to TextFinder being included as a library but do
>>>> think
>>>> that users would prefer having the get functions as a stream method
>>>> rather
>>>> than having to explicitly instantiate the TextFinder class, as would be
>>>> required if a separate library.
>>>>
>>>> The need to do the following in a sketch (if implemented as a library) is
>>>> not onerous
>>>>
>>>> #include
>>>> TextFinder finder(Serial);
>>>> void setup()
>>>> {
>>>> Serial.begin(9600);
>>>> int val = finder.getInt(); // return the next integer value on the
>>>> Serial
>>>> stream
>>>>
>>>> }
>>>>
>>>>
>>>> but this seems simpler and clearer
>>>>
>>>> void setup()
>>>> {
>>>> Serial.begin(9600);
>>>> int val = Serial.getInt(); // return the next integer value on the
>>>> Serial
>>>> stream
>>>> }
>>>>
>>>> void loop();
>>>>
>>>> Michael
>>>>
>>>> --------------------------------------------------
>>>> From: "Tom Igoe" <>
>>>> Sent: Sunday, June 05, 2011 8:48 PM
>>>> To: "David A. Mellis" <>
>>>> Cc: "Michael Margolis" <>; <>
>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>
>>>>> I think textFinder is good for things other than web pages, but I am in
>>>>> favor of a small core. How would you feel about including TextFinder in
>>>>> the
>>>>> standard distribution, assuming Michael agreed? That might offer a
>>>>> reasonable compromise of small core, but easy access to the functions.
>>>>>
>>>>> t.
>>>>>
>>>>> On Jun 5, 2011, at 3:47 PM, David A. Mellis wrote:
>>>>>
>>>>>> The more I think about this, the more I feel like maybe we should only
>>>>>> add the find() and findUntil() methods to stream (with some method for
>>>>>> setting the timeout). The other functionality feels fairly specific
>>>>>> to parsing webpages, which isn't something that feels like it needs to
>>>>>> be supported by the Stream class itself. That is, maybe we should
>>>>>> plan to continue to have a separate TextFinder library for more
>>>>>> complex parsing tasks, and only integrate the functionality that
>>>>>> applicable to wide range of stream types to the Stream interface
>>>>>> itself.
>>>>>>
>>>>>> In general, I'm trying to keep the core API small - with the
>>>>>> understanding that lots of useful, real-world examples will still
>>>>>> require third-party libraries. Including extra parsing functions
>>>>>> starts to feel in conflict with this general philosophy and I worry
>>>>>> that it will be inconsistent with other portions of the API.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> On Sun, Jun 5, 2011 at 12:47 PM, Tom Igoe <> wrote:
>>>>>>>
>>>>>>> Overall, Dave's proposals seem to add complication for the reader.
>>>>>>>
>>>>>>> I'm in the middle of some examples with TextFinder right now, and I
>>>>>>> found getInt() and getString() to be pretty staightforwardAfter
>>>>>>> reading
>>>>>>> through Dave's proposal, I tried to think through how to explain the
>>>>>>> code
>>>>>>> and realized it'd take me longer to explain with find() then
>>>>>>> readStringUntil() than it would with getString(). So I prefer
>>>>>>> getString().
>>>>>>>
>>>>>>> Combining getInt() and int() seems like a bigger deal than just
>>>>>>> strings.
>>>>>>> And as Michael points out getInt() does more than just the casting, it
>>>>>>> also
>>>>>>> finds the next int in the string, and then casts it. So conceptually,
>>>>>>> getInt() and int() are different things, no?
>>>>>>>
>>>>>>> As for read() vs get() naming, I could go either way.
>>>>>>>
>>>>>>> t.
>>>>>>>
>>>>>>>
>>>>>>> On Jun 4, 2011, at 3:25 PM, Michael Margolis wrote:
>>>>>>>
>>>>>>>> I am open to whatever method names are most suitable but I like
>>>>>>>> names
>>>>>>>> that are evocative of their functionality and 'get' naming was
>>>>>>>> chosen over
>>>>>>>> read because these methods do more than just read . I also think the
>>>>>>>> string parsing method as proposed is easier to use for getting
>>>>>>>> string
>>>>>>>> between tokens, which seemed to be the primary use case.
>>>>>>>>
>>>>>>>> But I don’t object to changing the names or the functionality as long
>>>>>>>> as we don’t sacrifice clarity or usability. It seems to me that if
>>>>>>>> getting a string between two tokens is an important capability for
>>>>>>>> this API
>>>>>>>> (it is for me, and most of my web parsing applications seem to use
>>>>>>>> the
>>>>>>>> current getString) then it would be a shame to lose this.
>>>>>>>>
>>>>>>>> Tom, what do you think?
>>>>>>>>
>>>>>>>> Michael
>>>>>>>>
>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>> Sent: Saturday, June 04, 2011 3:05 PM
>>>>>>>> To: Michael Margolis
>>>>>>>> Cc: Tom Igoe ;
>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>
>>>>>>>> Instead of offering so many versions of readString(), I'd rather
>>>>>>>> separate finding of the prefix from reading of the string: i.e.
>>>>>>>> requiring a call to find() or findUntil(), then a call to
>>>>>>>> readString()
>>>>>>>> or readStringUntil(). That eliminates redundancy from the API and
>>>>>>>> allows people to be explicit about how to handle situations in which
>>>>>>>> the prefix isn't found or when to stop looking for it.
>>>>>>>>
>>>>>>>> Also, maybe we should use readInt() and readFloat() for consistency
>>>>>>>> with readString() instead of getInt() and getFloat()? Although I
>>>>>>>> wonder if we couldn't get away with making int() and float() work on
>>>>>>>> strings - and making people read data from the Serial port into a
>>>>>>>> string before converting it to a number.
>>>>>>>>
>>>>>>>> We can use readBytes() and readBytesUntil() as alternative versions
>>>>>>>> of
>>>>>>>> readString() and readStringUntil() that accept an existing byte
>>>>>>>> buffer
>>>>>>>> into which to store the bytes (along with the buffer length). Then,
>>>>>>>> readString() and readStringUntil() can return newly allocated strings
>>>>>>>> instead.
>>>>>>>>
>>>>>>>> How does that sound?
>>>>>>>>
>>>>>>>>
>>>>>>>> On Tue, May 31, 2011 at 11:18 PM, Michael Margolis
>>>>>>>> <> wrote:
>>>>>>>>>
>>>>>>>>> For closer naming with the similar Processing functionality, should
>>>>>>>>> we
>>>>>>>>> rename the getString method as follows:
>>>>>>>>>
>>>>>>>>> int readString( char *pre_string, char post_string, char *buffer,
>>>>>>>>> int
>>>>>>>>> length); // read into a static character buffer
>>>>>>>>>
>>>>>>>>> note that the post string argument changed from a char* to char
>>>>>>>>>
>>>>>>>>> I would guess that the dynamic String methods could be something
>>>>>>>>> like
>>>>>>>>> this:
>>>>>>>>> String readStringUntil() //reads up to the first newline – Warning,
>>>>>>>>> limited
>>>>>>>>> String len may cause unexpected results
>>>>>>>>> String readStringUntil(post_char) // reads until post char is
>>>>>>>>> ncountered -
>>>>>>>>> Warning as above
>>>>>>>>> String readStringUntil(pre_char, post_char) // combines
>>>>>>>>> find(pre_string) and
>>>>>>>>> readStringUntil(post_char)
>>>>>>>>>
>>>>>>>>> The issue with finding a friendly way to inform the user when there
>>>>>>>>> is
>>>>>>>>> insufficient RAM for the function to operate is challenge for
>>>>>>>>> whichever
>>>>>>>>> brave soul volunteers to implement the dynamic String methods. I am
>>>>>>>>> a
>>>>>>>>> String sceptic from way back so am not well placed to advise on how
>>>>>>>>> dynamic
>>>>>>>>> String functionality in stream should be implemented.
>>>>>>>>>
>>>>>>>>> Michael Margolis
>>>>>>>>>
>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>> Sent: Wednesday, June 01, 2011 2:21 AM
>>>>>>>>> To: Tom Igoe
>>>>>>>>> Cc: Michael Margolis ;
>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>
>>>>>>>>> The plan is also to add readStringUntil(), so you could do something
>>>>>>>>> like:
>>>>>>>>>
>>>>>>>>> if (Serial.find(""))
>>>>>>>>> head = Serial.readStringUntil('<');
>>>>>>>>>
>>>>>>>>> I'm not sure it makes sense to add functions that do a find without
>>>>>>>>> removing characters from the buffer (e.g. a peekUntil()) because of
>>>>>>>>> the limited RAM on the Arduino and the confusion that's likely to
>>>>>>>>> result if you run out of room in the buffer. (Do you throw out
>>>>>>>>> older
>>>>>>>>> characters or newer ones? How do you tell if it's happened?)
>>>>>>>>>
>>>>>>>>> David
>>>>>>>>>
>>>>>>>>> On Tue, May 31, 2011 at 11:53 AM, Tom Igoe <>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> i have been using TextFinder in the rewrite of Making Things talk
>>>>>>>>>> and
>>>>>>>>>> it's
>>>>>>>>>> very handy. I'd love to see it in the core. I'd love to see find()
>>>>>>>>>> and
>>>>>>>>>> findUntil() use peek() perhaps, so that you can do multiple finds()
>>>>>>>>>> on a
>>>>>>>>>> stream. I've had some cases where I needed to switch from find()
>>>>>>>>>> to
>>>>>>>>>> a
>>>>>>>>>> character based search. For example, if I'm looking for
>>>>>>>>>>
>>>>>>>>>> This is what I want
>>>>>>>>>>
>>>>>>>>>> I have to find() for the then read() until I see a <. Maybe
>>>>>>>>>> I'm
>>>>>>>>>> missing something, but it'd be nice to just slurp everything
>>>>>>>>>> between
>>>>>>>>>>
>>>>>>>>>> and
>>>>>>>>>>
>>>>>>>>>> t.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On May 31, 2011, at 10:32 AM, Michael Margolis wrote:
>>>>>>>>>>
>>>>>>>>>>> David, thanks for your comments.
>>>>>>>>>>>
>>>>>>>>>>>> Would you want to be able to specify more than one skip
>>>>>>>>>>>> character?
>>>>>>>>>>>> Do we need some way to distinguish between a timeout and a real
>>>>>>>>>>>> value of
>>>>>>>>>>>> 0?
>>>>>>>>>>>
>>>>>>>>>>> Good questions, I am interested to hear what the people here think
>>>>>>>>>>> will
>>>>>>>>>>> be most useful.
>>>>>>>>>>> These things are easy to add but I would like to avoid bloating
>>>>>>>>>>> the
>>>>>>>>>>> API
>>>>>>>>>>> with features that are not likely to be used.
>>>>>>>>>>>
>>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>>> supporting
>>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>>
>>>>>>>>>>> This could be added by specifying the decimal point character to a
>>>>>>>>>>> user
>>>>>>>>>>> supplied character such as a comma (default is '.')
>>>>>>>>>>> If locale specific configuration was needed in elsewhere in
>>>>>>>>>>> Arduino
>>>>>>>>>>> functionality I would suggest having a locale.h file that contains
>>>>>>>>>>> defines
>>>>>>>>>>> for things like this. But a Stream method, perhaps named
>>>>>>>>>>> setDecimalPointChar() could be added if this functionality was
>>>>>>>>>>> only
>>>>>>>>>>> needed
>>>>>>>>>>> in this API.
>>>>>>>>>>>
>>>>>>>>>>>> I'd suggest using getInt() and getFloat() ...
>>>>>>>>>>>
>>>>>>>>>>> getValue seemed less techy but I take the point about consistency.
>>>>>>>>>>>
>>>>>>>>>>> I would be interested to hear others views on these and anything
>>>>>>>>>>> else
>>>>>>>>>>> regarding this API.
>>>>>>>>>>>
>>>>>>>>>>> Michael
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----Original Message----- From: David A. Mellis
>>>>>>>>>>> Sent: Tuesday, May 31, 2011 2:30 PM
>>>>>>>>>>> To: Michael Margolis
>>>>>>>>>>> Cc:
>>>>>>>>>>> Subject: Re: [Developers] Adding parsing to Stream
>>>>>>>>>>>
>>>>>>>>>>> Thanks for the proposal!
>>>>>>>>>>>
>>>>>>>>>>> Does anyone have any suggestions for the API or specific use cases
>>>>>>>>>>> we
>>>>>>>>>>> should keep in mind?
>>>>>>>>>>>
>>>>>>>>>>> In particular, I'm curious about the precise semantics for the
>>>>>>>>>>> getValue() functions. Would you want to be able to specify more
>>>>>>>>>>> than
>>>>>>>>>>> one skip character? Do we need some way to distinguish between a
>>>>>>>>>>> timeout and a real value of 0?
>>>>>>>>>>>
>>>>>>>>>>> For getFloat(), do we need a way to specify the character that
>>>>>>>>>>> separates the whole and fractional part of the number (e.g.
>>>>>>>>>>> supporting
>>>>>>>>>>> European formatting like 1.234,56)?
>>>>>>>>>>>
>>>>>>>>>>> I'd suggest using getInt() and getFloat() for consistency with the
>>>>>>>>>>> names of the data types, even if we actually return longs and
>>>>>>>>>>> doubles.
>>>>>>>>>>> The word "value" seems very generic.
>>>>>>>>>>>
>>>>>>>>>>> David
>>>>>>>>>>>
>>>>>>>>>>> On Tue, May 31, 2011 at 7:27 AM, Michael Margolis
>>>>>>>>>>> <> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> This is a proposal for enhancements to Stream to support the
>>>>>>>>>>>> finding and
>>>>>>>>>>>> extracting numeric and string data. The parsing is done character
>>>>>>>>>>>> by
>>>>>>>>>>>> character so no intermediate static or dynamic buffer is required
>>>>>>>>>>>> for
>>>>>>>>>>>> the
>>>>>>>>>>>> incoming data.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The code is based on the TextFinder library
>>>>>>>>>>>> (http://www.arduino.cc/playground/Code/TextFinder) that I wrote
>>>>>>>>>>>> (with
>>>>>>>>>>>> help
>>>>>>>>>>>> from Philip Lindsay) for the Arduino Cookbook.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The attached zip file contains 1.0 core Stream source code that
>>>>>>>>>>>> implements
>>>>>>>>>>>> the API described below. Examples showing use with Serial and
>>>>>>>>>>>> Ethernet
>>>>>>>>>>>> are
>>>>>>>>>>>> also included. Please feel free to suggest improvements to the
>>>>>>>>>>>> API,
>>>>>>>>>>>> implementation or examples.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Here are the currently supported methods:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> setTimeout()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Sets the maximum number of seconds to wait for a
>>>>>>>>>>>> character
>>>>>>>>>>>> from the stream. The default value is 5 seconds. The timeout
>>>>>>>>>>>> value
>>>>>>>>>>>> is
>>>>>>>>>>>> used
>>>>>>>>>>>> by all of the other parsing methods and could be useful for
>>>>>>>>>>>> other
>>>>>>>>>>>> stream
>>>>>>>>>>>> functions.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: setTimeout( timeout)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: timout: the maximum number of seconds to wait.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: nothing
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> setTimeout(10); // set timeout to ten seconds
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> find()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Reads data from the stream until the target string
>>>>>>>>>>>> is
>>>>>>>>>>>> found
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: find(targetStr)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: targetStr is the null terminated C character string
>>>>>>>>>>>> to
>>>>>>>>>>>> search
>>>>>>>>>>>> for
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: true if target string is found. All characters up to and
>>>>>>>>>>>> including
>>>>>>>>>>>> the last character in targetStr will be flushed. Returns false if
>>>>>>>>>>>> the
>>>>>>>>>>>> targetStr is not found within the timeout period.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> if( client.find("GET /") ) { // search for 'GET'
>>>>>>>>>>>>
>>>>>>>>>>>> // here if the string "GET /" is found in the stream
>>>>>>>>>>>>
>>>>>>>>>>>> else
>>>>>>>>>>>>
>>>>>>>>>>>> // here if find method timed out (stream buffer is empty)
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> findUntil()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As find but search ends if the terminate string is
>>>>>>>>>>>> found.
>>>>>>>>>>>> Useful to stop searches at the end of a line or at a string
>>>>>>>>>>>> token.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: findUntil(targetStr, terminateStr)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: targetStr is the null terminated C string to search
>>>>>>>>>>>> for,
>>>>>>>>>>>> terminateStr is the null terminated C string that will terminate
>>>>>>>>>>>> the
>>>>>>>>>>>> search
>>>>>>>>>>>> if found in the stream.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: true if targetStr is found, returns false if timeout or
>>>>>>>>>>>> terminateStr is encountered.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // search to the end of line for “pin”
>>>>>>>>>>>>
>>>>>>>>>>>> if(client.findUntil("pin", "\n\r"))
>>>>>>>>>>>>
>>>>>>>>>>>> // here if “pin” is found in the current line
>>>>>>>>>>>>
>>>>>>>>>>>> else
>>>>>>>>>>>>
>>>>>>>>>>>> // stream buffer is at the beginning of the next line
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Note that a binary variants of find and findUntil could be
>>>>>>>>>>>> implemented
>>>>>>>>>>>> if
>>>>>>>>>>>> necessary for searching for binary data. Parameters would be a
>>>>>>>>>>>> pointer
>>>>>>>>>>>> to a
>>>>>>>>>>>> byte array and the length of the target array. This would be
>>>>>>>>>>>> functionally
>>>>>>>>>>>> equivalent to the above but would handle null characters in the
>>>>>>>>>>>> target
>>>>>>>>>>>> and
>>>>>>>>>>>> terminate strings.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getValue()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Returns the first valid (long) integer value from
>>>>>>>>>>>> the
>>>>>>>>>>>> current
>>>>>>>>>>>> position. Initial characters that are not ASCII digits (or a
>>>>>>>>>>>> minus
>>>>>>>>>>>> sign)
>>>>>>>>>>>> are
>>>>>>>>>>>> ignored. The value is terminated by the first character that is
>>>>>>>>>>>> not
>>>>>>>>>>>> a
>>>>>>>>>>>> digit
>>>>>>>>>>>> following one or more valid digits.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getvalue()
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: none
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // this fragment will extract and print three comma separated
>>>>>>>>>>>> integer
>>>>>>>>>>>> values
>>>>>>>>>>>>
>>>>>>>>>>>> int value;
>>>>>>>>>>>>
>>>>>>>>>>>> for(int Index = 0; Index < 3; Index ++)
>>>>>>>>>>>>
>>>>>>>>>>>> {
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getValue(); // get a numeric value
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value);
>>>>>>>>>>>>
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getValue(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>>> allows
>>>>>>>>>>>> format
>>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getvalue(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: long integer value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12,345 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> int value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getValue(','); // ignore commas
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12345
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getFloat()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: float version of getValue.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getFloat()
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: none
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: : floating point value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12.34 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> float value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12.34
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getFloat(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Description: As above but the given skipChar is ignored. This
>>>>>>>>>>>> allows
>>>>>>>>>>>> format
>>>>>>>>>>>> characters (typically commas) in values to be ignored
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getFloat(skipChar)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: skipChar: a character to ignore
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: floating point value or 0 if timeout.
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> // send $12,345.67 terminated with a newline
>>>>>>>>>>>>
>>>>>>>>>>>> float value;
>>>>>>>>>>>>
>>>>>>>>>>>> value = Serial.getFloat();
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(value); // prints 12345.67
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> getString()
>>>>>>>>>>>>
>>>>>>>>>>>> Description: Finds a string between pre and post delimiters and
>>>>>>>>>>>> stores
>>>>>>>>>>>> into
>>>>>>>>>>>> a given buffer. The string will be truncated to fit the buffer
>>>>>>>>>>>> length.
>>>>>>>>>>>> The
>>>>>>>>>>>> string is terminated by the first character following the
>>>>>>>>>>>> preString
>>>>>>>>>>>> that
>>>>>>>>>>>> matches the first character of the terminator.
>>>>>>>>>>>>
>>>>>>>>>>>> Syntax: getString(preString, postString, buffer, length)
>>>>>>>>>>>>
>>>>>>>>>>>> Parameters: preString: a string that precedes the desired target
>>>>>>>>>>>> string,
>>>>>>>>>>>> following characters this are appended to the given buffer until
>>>>>>>>>>>> the
>>>>>>>>>>>> first
>>>>>>>>>>>> character of postString is encountered, length: the size of
>>>>>>>>>>>> buffer.
>>>>>>>>>>>>
>>>>>>>>>>>> Returns: Returns the number of characters placed in the buffer
>>>>>>>>>>>> (0
>>>>>>>>>>>> means
>>>>>>>>>>>> no
>>>>>>>>>>>> valid data found)
>>>>>>>>>>>>
>>>>>>>>>>>> Example:
>>>>>>>>>>>>
>>>>>>>>>>>> char buffer[8]; // must be big enough to hold target string and
>>>>>>>>>>>> terminating null
>>>>>>>>>>>>
>>>>>>>>>>>> // get a string between "<" and ">"
>>>>>>>>>>>>
>>>>>>>>>>>> if(client.getString( "<", ">", buffer, sizeof(buffer) ))
>>>>>>>>>>>>
>>>>>>>>>>>> {
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.print("found ");
>>>>>>>>>>>>
>>>>>>>>>>>> Serial.println(buffer);
>>>>>>>>>>>>
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> This will print ‘target’ if the stream contains “
>>>>>>>>>>>>
>>>>>>>>>>>> Characters before the ‘<’ are discarded. The next character read
>>>>>>>>>>>> from
>>>>>>>>>>>> the
>>>>>>>>>>>> stream will be the character following ‘>’
>>>>>>>>>>>>