You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
2.7 KiB

/*
Utility class to process data in a byte-wise manner without
requiring large memory buffers on the microcontroller.
*/
#include "stream_connection.h"
StreamConnection::StreamConnection(NetworkConnection& connection) : _connection (connection) {
/*
Initialise our one character buffer for the last character
read to indicate no character is currently buffered.
*/
_byteSeen = -1;
}
int StreamConnection::peekByte() {
/*
See what the next character will be without consuming it.
*/
if (_byteSeen < 0) {
if (_connection.available()) {
_byteSeen = _connection.read();
}
}
return _byteSeen;
}
int StreamConnection::readByte() {
/*
Read the next character, reffering to the buffer first if available,
consuming it in the process.
*/
int newByte = -1;
if (_byteSeen < 0) {
if (_connection.available()) {
newByte = _connection.read();
}
} else {
newByte = _byteSeen;
_byteSeen = -1;
}
return newByte;
}
int StreamConnection::readSegmentByte(const char * separators) {
/*
Read bytes until we encounter a separator, which we don't consume.
*/
// Blocks
while (peekByte() < 0) { // TODO: Time out?
delay(500);
}
if (!strchr(separators, peekByte())) {
return readByte();
}
return -1;
}
int StreamConnection::skipSegment(const char * separators) {
/*
Skip a segment between separators and the closing separators.
This enables us to skip to the end of a line for example.
*/
do {
if (peekByte() < 0) {
return -1;
}
// Skip everything not a separator
} while (!strchr(separators, peekByte()) && readByte());
do {
/* // We can't return here or we get stuck above.
if (peekByte() < 0) {
return -1;
}*/
while (peekByte() < 0) {
delay(500); // TODO: Time out?
}
// Skip everything that *is* a separator
} while (strchr(separators, peekByte()) && readByte());
return 1;
}
int StreamConnection::gobbleMatch(const char * separators, const char * target) {
/*
See if the next characters match the target string,
consuming characters in the process.
*/
int idx = 0;
int byteRead = -1;
while ((byteRead = readSegmentByte(separators)) >=0) {
if (idx < strlen(target)) {
if (byteRead != target[idx]) {
break;
}
idx++;
} else {
break;
}
}
if ((byteRead == -1) && (idx == strlen(target))) { // Matched
while (skipSegment(separators) < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
return 1;
}
return -1;
}