141 lines
2.6 KiB
C++
141 lines
2.6 KiB
C++
|
|
||
|
#include "ParsedStream.h"
|
||
|
|
||
|
|
||
|
void ParsedStream::storeByte(unsigned char c) {
|
||
|
int i = (_rx_buffer.head + 1) % RX_BUFFER_SIZE;
|
||
|
|
||
|
// if we should be storing the received character into the location
|
||
|
// just before the tail (meaning that the head would advance to the
|
||
|
// current location of the tail), we're about to overflow the buffer
|
||
|
// and so we don't write the character or advance the head.
|
||
|
if (i != _rx_buffer.tail) {
|
||
|
_rx_buffer.buffer[_rx_buffer.head] = c;
|
||
|
_rx_buffer.head = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ParsedStream::ParsedStream()
|
||
|
{
|
||
|
/*
|
||
|
*/
|
||
|
reset();
|
||
|
}
|
||
|
|
||
|
void ParsedStream::begin(Stream* theUart)
|
||
|
{
|
||
|
_uart = theUart;
|
||
|
}
|
||
|
|
||
|
void ParsedStream::reset() {
|
||
|
/*
|
||
|
*/
|
||
|
ring_buffer _rx_buffer = { { 0 }, 0, 0};
|
||
|
_closed = false;
|
||
|
bytes_matched = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
uint8_t ParsedStream::available(bool raw) {
|
||
|
uint8_t available_bytes;
|
||
|
|
||
|
available_bytes = (RX_BUFFER_SIZE + _rx_buffer.head - _rx_buffer.tail) % RX_BUFFER_SIZE;
|
||
|
|
||
|
if (!raw) {
|
||
|
if (available_bytes > bytes_matched) {
|
||
|
available_bytes -= bytes_matched;
|
||
|
} else {
|
||
|
available_bytes = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return available_bytes;
|
||
|
}
|
||
|
|
||
|
uint8_t ParsedStream::available() {
|
||
|
|
||
|
// NOTE: This causes a read/buffer fill which isn't entirely
|
||
|
// consistent with how `available()` is normally
|
||
|
// handled.
|
||
|
// TODO: Put this buffer fill in the read section instead?
|
||
|
|
||
|
// TODO: Don't refill if we're almost full and don't have a partial
|
||
|
// match?
|
||
|
|
||
|
while (!_closed && freeSpace() && _uart->available()) {
|
||
|
getByte();
|
||
|
}
|
||
|
return available(false);
|
||
|
}
|
||
|
|
||
|
bool ParsedStream::closed() {
|
||
|
return _closed && !available();
|
||
|
}
|
||
|
|
||
|
int ParsedStream::read(void) {
|
||
|
|
||
|
if (!available()) {
|
||
|
getByte();
|
||
|
}
|
||
|
|
||
|
if (!available()) {
|
||
|
return -1;
|
||
|
} else {
|
||
|
unsigned char c = _rx_buffer.buffer[_rx_buffer.tail];
|
||
|
_rx_buffer.tail = (_rx_buffer.tail + 1) % RX_BUFFER_SIZE;
|
||
|
return c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ParsedStream::peek(void) {
|
||
|
|
||
|
if (!available()) {
|
||
|
getByte();
|
||
|
}
|
||
|
|
||
|
if (!available()) {
|
||
|
return -1;
|
||
|
} else {
|
||
|
unsigned char c = _rx_buffer.buffer[_rx_buffer.tail];
|
||
|
return c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
int ParsedStream::freeSpace() {
|
||
|
return RX_BUFFER_SIZE - available(true) - 1 /* The -1 fudge due to storeByte calculation*/;
|
||
|
}
|
||
|
|
||
|
void ParsedStream::getByte() {
|
||
|
int c;
|
||
|
if (_closed) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (freeSpace() == 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// TODO: Tidy this...
|
||
|
c = _uart->read();
|
||
|
if (c == -1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (c == MATCH_TOKEN[bytes_matched]) {
|
||
|
bytes_matched++;
|
||
|
if (bytes_matched == strlen(MATCH_TOKEN)) {
|
||
|
_closed = true;
|
||
|
}
|
||
|
} else if (c == MATCH_TOKEN[0]) {
|
||
|
// Handle e.g. case "**CLOS*"
|
||
|
bytes_matched = 1;
|
||
|
} else {
|
||
|
bytes_matched = 0;
|
||
|
}
|
||
|
|
||
|
storeByte(c);
|
||
|
|
||
|
}
|