<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-cn">
		<id>http://wiki.ywrobot.net/index.php?action=history&amp;feed=atom&amp;title=Stream.cpp</id>
		<title>Stream.cpp - 版本历史</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.ywrobot.net/index.php?action=history&amp;feed=atom&amp;title=Stream.cpp"/>
		<link rel="alternate" type="text/html" href="http://wiki.ywrobot.net/index.php?title=Stream.cpp&amp;action=history"/>
		<updated>2026-05-14T11:39:44Z</updated>
		<subtitle>本wiki的该页面的版本历史</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://wiki.ywrobot.net/index.php?title=Stream.cpp&amp;diff=88&amp;oldid=prev</id>
		<title>YWrobot CYB：创建页面，内容为“&lt;pre style=&quot;color:blue&quot;&gt; /*  Stream.cpp - adds parsing methods to Stream class  Copyright (c) 2008 David A. Mellis.  All right reserved.   This library is free softw...”</title>
		<link rel="alternate" type="text/html" href="http://wiki.ywrobot.net/index.php?title=Stream.cpp&amp;diff=88&amp;oldid=prev"/>
				<updated>2016-04-25T02:19:45Z</updated>
		
		<summary type="html">&lt;p&gt;创建页面，内容为“&amp;lt;pre style=&amp;quot;color:blue&amp;quot;&amp;gt; /*  Stream.cpp - adds parsing methods to Stream class  Copyright (c) 2008 David A. Mellis.  All right reserved.   This library is free softw...”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre style=&amp;quot;color:blue&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 Stream.cpp - adds parsing methods to Stream class&lt;br /&gt;
 Copyright (c) 2008 David A. Mellis.  All right reserved.&lt;br /&gt;
&lt;br /&gt;
 This library is free software; you can redistribute it and/or&lt;br /&gt;
 modify it under the terms of the GNU Lesser General Public&lt;br /&gt;
 License as published by the Free Software Foundation; either&lt;br /&gt;
 version 2.1 of the License, or (at your option) any later version.&lt;br /&gt;
&lt;br /&gt;
 This library is distributed in the hope that it will be useful,&lt;br /&gt;
 but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt;
 Lesser General Public License for more details.&lt;br /&gt;
&lt;br /&gt;
 You should have received a copy of the GNU Lesser General Public&lt;br /&gt;
 License along with this library; if not, write to the Free Software&lt;br /&gt;
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA&lt;br /&gt;
&lt;br /&gt;
 Created July 2011&lt;br /&gt;
 parsing functions based on TextFinder library by Michael Margolis&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Arduino.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Stream.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define PARSE_TIMEOUT 1000  // default number of milli-seconds to wait&lt;br /&gt;
#define NO_SKIP_CHAR  1  // a magic char not found in a valid ASCII numeric field&lt;br /&gt;
&lt;br /&gt;
// private method to read stream with timeout&lt;br /&gt;
int Stream::timedRead()&lt;br /&gt;
{&lt;br /&gt;
  int c;&lt;br /&gt;
  _startMillis = millis();&lt;br /&gt;
  do {&lt;br /&gt;
    c = read();&lt;br /&gt;
    if (c &amp;gt;= 0) return c;&lt;br /&gt;
  } while(millis() - _startMillis &amp;lt; _timeout);&lt;br /&gt;
  return -1;     // -1 indicates timeout&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// private method to peek stream with timeout&lt;br /&gt;
int Stream::timedPeek()&lt;br /&gt;
{&lt;br /&gt;
  int c;&lt;br /&gt;
  _startMillis = millis();&lt;br /&gt;
  do {&lt;br /&gt;
    c = peek();&lt;br /&gt;
    if (c &amp;gt;= 0) return c;&lt;br /&gt;
  } while(millis() - _startMillis &amp;lt; _timeout);&lt;br /&gt;
  return -1;     // -1 indicates timeout&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returns peek of the next digit in the stream or -1 if timeout&lt;br /&gt;
// discards non-numeric characters&lt;br /&gt;
int Stream::peekNextDigit()&lt;br /&gt;
{&lt;br /&gt;
  int c;&lt;br /&gt;
  while (1) {&lt;br /&gt;
    c = timedPeek();&lt;br /&gt;
    if (c &amp;lt; 0) return c;  // timeout&lt;br /&gt;
    if (c == '-') return c;&lt;br /&gt;
    if (c &amp;gt;= '0' &amp;amp;&amp;amp; c &amp;lt;= '9') return c;&lt;br /&gt;
    read();  // discard non-numeric&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Public Methods&lt;br /&gt;
//////////////////////////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait&lt;br /&gt;
{&lt;br /&gt;
  _timeout = timeout;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
 // find returns true if the target string is found&lt;br /&gt;
bool  Stream::find(char *target)&lt;br /&gt;
{&lt;br /&gt;
  return findUntil(target, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// reads data from the stream until the target string of given length is found&lt;br /&gt;
// returns true if target string is found, false if timed out&lt;br /&gt;
bool Stream::find(char *target, size_t length)&lt;br /&gt;
{&lt;br /&gt;
  return findUntil(target, length, NULL, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// as find but search ends if the terminator string is found&lt;br /&gt;
bool  Stream::findUntil(char *target, char *terminator)&lt;br /&gt;
{&lt;br /&gt;
  return findUntil(target, strlen(target), terminator, strlen(terminator));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// reads data from the stream until the target string of the given length is found&lt;br /&gt;
// search terminated if the terminator string is found&lt;br /&gt;
// returns true if target string is found, false if terminated or timed out&lt;br /&gt;
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)&lt;br /&gt;
{&lt;br /&gt;
  size_t index = 0;  // maximum target string length is 64k bytes!&lt;br /&gt;
  size_t termIndex = 0;&lt;br /&gt;
  int c;&lt;br /&gt;
  &lt;br /&gt;
  if( *target == 0)&lt;br /&gt;
    return true;   // return true if target is a null string&lt;br /&gt;
  while( (c = timedRead()) &amp;gt; 0){&lt;br /&gt;
    &lt;br /&gt;
    if(c != target[index])&lt;br /&gt;
      index = 0; // reset index if any char does not match&lt;br /&gt;
    &lt;br /&gt;
    if( c == target[index]){&lt;br /&gt;
      //////Serial.print(&amp;quot;found &amp;quot;); Serial.write(c); Serial.print(&amp;quot;index now&amp;quot;); Serial.println(index+1);&lt;br /&gt;
      if(++index &amp;gt;= targetLen){ // return true if all chars in the target match&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if(termLen &amp;gt; 0 &amp;amp;&amp;amp; c == terminator[termIndex]){&lt;br /&gt;
      if(++termIndex &amp;gt;= termLen)&lt;br /&gt;
        return false;       // return false if terminate string found before target string&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
      termIndex = 0;&lt;br /&gt;
  }&lt;br /&gt;
  return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// returns the first valid (long) integer value from the current position.&lt;br /&gt;
// initial characters that are not digits (or the minus sign) are skipped&lt;br /&gt;
// function is terminated by the first character that is not a digit.&lt;br /&gt;
long Stream::parseInt()&lt;br /&gt;
{&lt;br /&gt;
  return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// as above but a given skipChar is ignored&lt;br /&gt;
// this allows format characters (typically commas) in values to be ignored&lt;br /&gt;
long Stream::parseInt(char skipChar)&lt;br /&gt;
{&lt;br /&gt;
  boolean isNegative = false;&lt;br /&gt;
  long value = 0;&lt;br /&gt;
  int c;&lt;br /&gt;
&lt;br /&gt;
  c = peekNextDigit();&lt;br /&gt;
  // ignore non numeric leading characters&lt;br /&gt;
  if(c &amp;lt; 0)&lt;br /&gt;
    return 0; // zero returned if timeout&lt;br /&gt;
&lt;br /&gt;
  do{&lt;br /&gt;
    if(c == skipChar)&lt;br /&gt;
      ; // ignore this charactor&lt;br /&gt;
    else if(c == '-')&lt;br /&gt;
      isNegative = true;&lt;br /&gt;
    else if(c &amp;gt;= '0' &amp;amp;&amp;amp; c &amp;lt;= '9')        // is c a digit?&lt;br /&gt;
      value = value * 10 + c - '0';&lt;br /&gt;
    read();  // consume the character we got with peek&lt;br /&gt;
    c = timedPeek();&lt;br /&gt;
  }&lt;br /&gt;
  while( (c &amp;gt;= '0' &amp;amp;&amp;amp; c &amp;lt;= '9') || c == skipChar );&lt;br /&gt;
&lt;br /&gt;
  if(isNegative)&lt;br /&gt;
    value = -value;&lt;br /&gt;
  return value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// as parseInt but returns a floating point value&lt;br /&gt;
float Stream::parseFloat()&lt;br /&gt;
{&lt;br /&gt;
  return parseFloat(NO_SKIP_CHAR);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// as above but the given skipChar is ignored&lt;br /&gt;
// this allows format characters (typically commas) in values to be ignored&lt;br /&gt;
float Stream::parseFloat(char skipChar){&lt;br /&gt;
  boolean isNegative = false;&lt;br /&gt;
  boolean isFraction = false;&lt;br /&gt;
  long value = 0;&lt;br /&gt;
  char c;&lt;br /&gt;
  float fraction = 1.0;&lt;br /&gt;
&lt;br /&gt;
  c = peekNextDigit();&lt;br /&gt;
    // ignore non numeric leading characters&lt;br /&gt;
  if(c &amp;lt; 0)&lt;br /&gt;
    return 0; // zero returned if timeout&lt;br /&gt;
&lt;br /&gt;
  do{&lt;br /&gt;
    if(c == skipChar)&lt;br /&gt;
      ; // ignore&lt;br /&gt;
    else if(c == '-')&lt;br /&gt;
      isNegative = true;&lt;br /&gt;
    else if (c == '.')&lt;br /&gt;
      isFraction = true;&lt;br /&gt;
    else if(c &amp;gt;= '0' &amp;amp;&amp;amp; c &amp;lt;= '9')  {      // is c a digit?&lt;br /&gt;
      value = value * 10 + c - '0';&lt;br /&gt;
      if(isFraction)&lt;br /&gt;
         fraction *= 0.1;&lt;br /&gt;
    }&lt;br /&gt;
    read();  // consume the character we got with peek&lt;br /&gt;
    c = timedPeek();&lt;br /&gt;
  }&lt;br /&gt;
  while( (c &amp;gt;= '0' &amp;amp;&amp;amp; c &amp;lt;= '9')  || c == '.' || c == skipChar );&lt;br /&gt;
&lt;br /&gt;
  if(isNegative)&lt;br /&gt;
    value = -value;&lt;br /&gt;
  if(isFraction)&lt;br /&gt;
    return value * fraction;&lt;br /&gt;
  else&lt;br /&gt;
    return value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// read characters from stream into buffer&lt;br /&gt;
// terminates if length characters have been read, or timeout (see setTimeout)&lt;br /&gt;
// returns the number of characters placed in the buffer&lt;br /&gt;
// the buffer is NOT null terminated.&lt;br /&gt;
//&lt;br /&gt;
size_t Stream::readBytes(char *buffer, size_t length)&lt;br /&gt;
{&lt;br /&gt;
  size_t count = 0;&lt;br /&gt;
  while (count &amp;lt; length) {&lt;br /&gt;
    int c = timedRead();&lt;br /&gt;
    if (c &amp;lt; 0) break;&lt;br /&gt;
    *buffer++ = (char)c;&lt;br /&gt;
    count++;&lt;br /&gt;
  }&lt;br /&gt;
  return count;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// as readBytes with terminator character&lt;br /&gt;
// terminates if length characters have been read, timeout, or if the terminator character  detected&lt;br /&gt;
// returns the number of characters placed in the buffer (0 means no valid data found)&lt;br /&gt;
&lt;br /&gt;
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)&lt;br /&gt;
{&lt;br /&gt;
  if (length &amp;lt; 1) return 0;&lt;br /&gt;
  size_t index = 0;&lt;br /&gt;
  while (index &amp;lt; length) {&lt;br /&gt;
    int c = timedRead();&lt;br /&gt;
    if (c &amp;lt; 0 || c == terminator) break;&lt;br /&gt;
    *buffer++ = (char)c;&lt;br /&gt;
    index++;&lt;br /&gt;
  }&lt;br /&gt;
  return index; // return number of characters, not including null terminator&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
String Stream::readString()&lt;br /&gt;
{&lt;br /&gt;
  String ret;&lt;br /&gt;
  int c = timedRead();&lt;br /&gt;
  while (c &amp;gt;= 0)&lt;br /&gt;
  {&lt;br /&gt;
    ret += (char)c;&lt;br /&gt;
    c = timedRead();&lt;br /&gt;
  }&lt;br /&gt;
  return ret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
String Stream::readStringUntil(char terminator)&lt;br /&gt;
{&lt;br /&gt;
  String ret;&lt;br /&gt;
  int c = timedRead();&lt;br /&gt;
  while (c &amp;gt;= 0 &amp;amp;&amp;amp; c != terminator)&lt;br /&gt;
  {&lt;br /&gt;
    ret += (char)c;&lt;br /&gt;
    c = timedRead();&lt;br /&gt;
  }&lt;br /&gt;
  return ret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>YWrobot CYB</name></author>	</entry>

	</feed>