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