Merge pull request #8598 from VeijoPesonen/fix_atcmdparser_oob_handling

ATCmdParser: Fix OOB handling performance-wise
pull/8614/head
Cruz Monrreal 2018-10-31 18:52:21 -05:00 committed by GitHub
commit 3d09f3bd98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 50 deletions

View File

@ -215,7 +215,8 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
restart:
_aborted = false;
// Iterate through each line in the expected response
while (response[0]) {
// response being NULL means we just want to check for OOBs
while (!response || response[0]) {
// Since response is const, we need to copy it into our buffer to
// add the line's null terminator and clobber value-matches with asterisks.
//
@ -224,7 +225,7 @@ restart:
int offset = 0;
bool whole_line_wanted = false;
while (response[i]) {
while (response && response[i]) {
if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') {
_buffer[offset++] = '%';
_buffer[offset++] = '*';
@ -257,6 +258,11 @@ restart:
int j = 0;
while (true) {
// If just peeking for OOBs, and at start of line, check
// readability
if (!response && j == 0 && !_fh->readable()) {
return false;
}
// Receive next character
int c = getc();
if (c < 0) {
@ -284,6 +290,7 @@ restart:
if ((unsigned)j == oob->len && memcmp(
oob->prefix, _buffer + offset, oob->len) == 0) {
debug_if(_dbg_on, "AT! %s\n", oob->prefix);
_oob_cb_count++;
oob->cb();
if (_aborted) {
@ -302,7 +309,7 @@ restart:
// Don't attempt scanning until we get delimiter if they included it in format
// This allows recv("Foo: %s\n") to work, and not match with just the first character of a string
// (scanf does not itself match whitespace in its format string, so \n is not significant to it)
} else {
} else if (response) {
sscanf(_buffer + offset, _buffer, &count);
}
@ -388,52 +395,9 @@ void ATCmdParser::abort()
bool ATCmdParser::process_oob()
{
if (!_fh->readable()) {
return false;
}
int i = 0;
while (true) {
// Receive next character
int c = getc();
if (c < 0) {
return false;
}
// Simplify newlines (borrowed from retarget.cpp)
if ((c == CR && _in_prev != LF) ||
(c == LF && _in_prev != CR)) {
_in_prev = c;
c = '\n';
} else if ((c == CR && _in_prev == LF) ||
(c == LF && _in_prev == CR)) {
_in_prev = c;
// onto next character
continue;
} else {
_in_prev = c;
}
_buffer[i++] = c;
_buffer[i] = 0;
// Check for oob data
struct oob *oob = _oobs;
while (oob) {
if (i == (int)oob->len && memcmp(
oob->prefix, _buffer, oob->len) == 0) {
debug_if(_dbg_on, "AT! %s\r\n", oob->prefix);
oob->cb();
return true;
}
oob = oob->next;
}
// Clear the buffer when we hit a newline or ran out of space
// running out of space usually means we ran into binary data
if (((i + 1) >= _buffer_size) || (c == '\n')) {
debug_if(_dbg_on, "AT< %s", _buffer);
i = 0;
}
}
int pre_count = _oob_cb_count;
recv(NULL);
return _oob_cb_count != pre_count;
}
}

View File

@ -66,6 +66,7 @@ private:
// Parsing information
const char *_output_delimiter;
int _output_delim_size;
int _oob_cb_count;
char _in_prev;
bool _dbg_on;
bool _aborted;
@ -91,7 +92,7 @@ public:
*/
ATCmdParser(FileHandle *fh, const char *output_delimiter = "\r",
int buffer_size = 256, int timeout = 8000, bool debug = false)
: _fh(fh), _buffer_size(buffer_size), _in_prev(0), _oobs(NULL)
: _fh(fh), _buffer_size(buffer_size), _oob_cb_count(0), _in_prev(0), _oobs(NULL)
{
_buffer = new char[buffer_size];
set_timeout(timeout);