AGirs
StreamParser.cpp
Go to the documentation of this file.
1 #include "StreamParser.h"
2 #include "Pronto.h"
3 #include <string.h>
4 
5 StreamParser::StreamParser(Stream &stream_) : stream(stream_) {
6 }
7 
9  frequency_t frequency = static_cast<frequency_t> (parseAbsInt());
10  size_t introLength = parseAbsInt();
11  size_t repeatLength = parseAbsInt();
12  size_t endingLength = parseAbsInt();
13 
14  microseconds_t *introData = parseData(introLength);
15  microseconds_t *repeatData = parseData(repeatLength);
16  microseconds_t *endingData = parseData(endingLength);
17 
18  return new IrSignal(introData, introLength, repeatData, repeatLength, endingData, endingLength, frequency);
19 }
20 
21 IrSignal* StreamParser::parse(Stream &stream) {
22  StreamParser parser(stream);
23  return parser.parseIrSignal();
24 }
25 
26 const char* StreamParser::parseWord(char* buf, size_t buflen) {
27  while (stream.available() == 0)
28  yield();
29 
30  unsigned i = 0U;
31  while (true) {
32  yield();
33  int c = stream.read(); // non-blocking, returns immediately
34  if (c == invalid)
35  continue;
36  if (isspace(c)) {
37  if (i == 0 && isblank(c))
38  continue; // ignore leading spaces/tabs, but not CR/LF
39  else
40  break;
41  }
42 
43  if (i == buflen - 1) {
44  disposeUntilWhitespace();
45  break;
46  }
47  buf[i] = static_cast<char>(c);
48  i++;
49  }
50  buf[i] = '\0';
51 
52  return buf;
53 }
54 
55 const char* StreamParser::getLine(char* buf, size_t buflen) {
56  while (stream.available() == 0)
57  yield();
58 
59  unsigned i = 0U;
60  while (true) {
61  yield();
62  int c = stream.read(); // non-blocking, returns immediately
63  if (c == invalid)
64  continue;
65  if (isspace(c)) {
66  if (isblank(c)) {
67  if (i == 0)
68  continue; // ignore leading spaces/tabs, but not CR/LF
69  } else
70  break;
71  }
72 
73  if (i == buflen - 1) {
74  disposeUntilWhitespace();
75  break;
76  }
77  buf[i] = static_cast<char>(c);
78  i++;
79  }
80  buf[i] = '\0';
81  return buf;
82 }
83 
84 int32_t StreamParser::parseAbsIntDefault(int32_t fallback) {
85  char c;
86  do {
87  c = customReadChar();
88  } while (c == ' ' || c == '\t' || c == '-' || c == '+');
89 
90  if (c == '\r' || c == '\n')
91  return fallback;
92 
93  return parseAbsInt(c);
94 }
95 
97  char c;
98  do {
99  c = customReadChar();
100  } while (isspace(c) || c == '-' || c == '+');
101 
102  return parseAbsInt(c);
103 }
104 
105 int32_t StreamParser::parseAbsInt(char initial) {
106  char c = initial;
107  int32_t value = invalid;
108  while (true) {
109  if (isspace(c))
110  return value;
111  int32_t n = static_cast<int> (c) - static_cast<int> ('0');
112  if (n < 0 || n > 9) {
113  disposeUntilWhitespace();
114  return value;
115  }
116  if (value == invalid)
117  value = 0;
118  value = value * 10 + n;
119  c = customReadChar();
120  }
121 }
122 
123 uint16_t StreamParser::parseProntoNumber() {
124  char c;
125  do {
126  c = customReadChar();
127  } while (isspace(c));
128 
129  int32_t value = 0;
130  for (unsigned i = 0; i < Pronto::digitsInProntoNumber; i++) {
131  int n = parseHex(c);
132  value = value * 16 + n;
133  c = customReadChar();
134  }
135  return value;
136 }
137 
139  uint16_t type = parseProntoNumber();
140  uint16_t frequencyCode = parseProntoNumber();
141  uint16_t introPairs = parseProntoNumber();
142  uint16_t repeatPairs = parseProntoNumber();
143  size_t size = Pronto::numbersInPreamble + 2 * (introPairs + repeatPairs);
144  uint16_t* data = new microseconds_t[size];
145  data[0] = type;
146  data[1] = frequencyCode;
147  data[2] = introPairs;
148  data[3] = repeatPairs;
149  for (unsigned i = Pronto::numbersInPreamble; i < size; i++)
150  data[i] = parseProntoNumber();
151  return Pronto::parse(data, size);
152 }
153 
154 unsigned int StreamParser::parseHex(char c) {
155  return
156  c < '0' ? invalid
157  : c <= '9' ? static_cast<unsigned>(c - '0')
158  : c < 'A' ? invalid
159  : c <= 'F' ? static_cast<unsigned>(c - 'A') + 10U
160  : c < 'a' ? invalid
161  : c <= 'f' ? static_cast<unsigned>(c - 'a') + 10U
162  : invalid;
163 }
164 
165 char StreamParser::customReadChar() {
166  int c;
167  do {
168  yield();
169  c = stream.peek(); // does not block
170  } while (c == invalid);
171  if (c == '\r' || c == '\n')
172  return static_cast<char>(c);
173 
174  stream.read();
175  return static_cast<char>(c);
176 }
177 
179  while (true) {
180  int c = stream.peek();
181  if (isspace(c))
182  stream.read();
183  else
184  return;
185  }
186 }
187 
188 void StreamParser::disposeUntilWhitespace() {
189  int c;
190  do {
191  c = stream.read();
192  } while (isspace(c));
193 }
194 
195 microseconds_t* StreamParser::parseData(size_t length) {
196  microseconds_t* data = new microseconds_t[length];
197  return parseData(data, length);
198 }
199 
200 microseconds_t* StreamParser::parseData(microseconds_t* data, size_t length) {
201  for (unsigned int i = 0; i < length; i++)
202  data[i] = parseAbsInt();
203 
204  return data;
205 }
Simple class for parsing stuff from an (input) Stream.
Definition: StreamParser.h:13
int32_t parseAbsInt()
Reads a number and returns it as 16 bit unsigned.
static IrSignal * parse(Stream &stream)
Convenience function: combines the constructor and parseIrSignal.
const char * getLine(char *buf, size_t buflen)
int32_t parseAbsIntDefault(int32_t fallback)
Reads a number and returns it as 16 bit unsigned.
const char * parseWord(char *buf, size_t buflen)
Returns a word (separated by whitespace).
IrSignal * parseIrSignal()
Reads the stream and parses it into an IrSignal.
Definition: StreamParser.cpp:8
StreamParser(Stream &stream)
Constructor.
Definition: StreamParser.cpp:5
microseconds_t * parseData(microseconds_t *buffer, size_t length)
IrSignal * parsePronto()
Reads a Pronto Hex format IR signal.
static constexpr int invalid
Definition: StreamParser.h:85