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
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;
|
|
}
|