Diff: ATParser.cpp
- Revision:
- 9:9bcb87c27208
- Parent:
- 8:91515b168c70
- Child:
- 10:553f9ffaf657
diff -r 91515b168c70 -r 9bcb87c27208 ATParser.cpp
--- a/ATParser.cpp Mon Jul 20 20:56:30 2015 +0000
+++ b/ATParser.cpp Mon Jul 20 21:28:39 2015 +0000
@@ -60,10 +60,9 @@
// read/write handling with timeouts
int ATParser::write(const char *data, int size) {
int i;
-
for (i = 0; i < size; i++) {
if (putc(data[i]) < 0)
- return i;
+ return -1;
}
return i;
@@ -71,12 +70,10 @@
int ATParser::read(char *data, int size) {
int i;
-
for (i = 0; i < size; i++) {
int c = getc();
-
if (c < 0)
- return i;
+ return -1;
data[i] = c;
}
@@ -85,10 +82,85 @@
}
+// printf/scanf handling
+int ATParser::vprintf(const char *format, va_list args) {
+ if (vsprintf(_buffer, format, args) < 0)
+ return false;
+
+ int i;
+ for (i = 0; _buffer[i]; i++) {
+ if (putc(_buffer[i]) < 0)
+ return -1;
+ }
+
+ return i;
+}
+
+int ATParser::vscanf(const char *format, va_list args) {
+ // Since format is const, we need to copy it into our buffer to
+ // add the line's null terminator and clobber value-matches with asterisks.
+ //
+ // We just use the beginning of the buffer to avoid unnecessary allocations.
+ int i = 0;
+ int offset = 0;
+
+ while (format[i]) {
+ if (format[i] == '%' &&
+ format[i+1] != '%' &&
+ format[i+1] != '*') {
+ _buffer[offset++] = '%';
+ _buffer[offset++] = '*';
+ i++;
+ } else {
+ _buffer[offset++] = format[i++];
+ }
+ }
+
+ // Scanf has very poor support for catching errors
+ // fortunately, we can abuse the %n specifier to determine
+ // if the entire string was matched.
+ _buffer[offset++] = '%';
+ _buffer[offset++] = 'n';
+ _buffer[offset++] = 0;
+
+ // To workaround scanf's lack of error reporting, we actually
+ // make two passes. One checks the validity with the modified
+ // format string that only stores the matched characters (%n).
+ // The other reads in the actual matched values.
+ //
+ // We keep trying the match until we succeed or some other error
+ // derails us.
+ int j = 0;
+
+ while (true) {
+ // Ran out of space
+ if (j+1 >= _buffer_size - offset)
+ return false;
+
+ // Recieve next character
+ int c = getc();
+ if (c < 0)
+ return -1;
+
+ _buffer[offset + j++] = c;
+ _buffer[offset + j] = 0;
+
+ // Check for match
+ int count = -1;
+ sscanf(_buffer+offset, _buffer, &count);
+
+ // We only succeed if all characters in the response are matched
+ if (count == j) {
+ // Store the found results
+ vsscanf(_buffer+offset, format, args);
+ return j;
+ }
+ }
+}
+
+
// Command parsing with line handling
bool ATParser::vsend(const char *command, va_list args) {
- flush();
-
// Create and send command
if (vsprintf(_buffer, command, args) < 0)
return false;
@@ -105,7 +177,7 @@
}
#ifdef AT_ECHO
- printf("AT> %s\r\n", _buffer);
+ ::printf("AT> %s\r\n", _buffer);
#endif
return true;
@@ -152,7 +224,11 @@
// derails us.
int j = 0;
- while (j+1 < _buffer_size - offset) {
+ while (true) {
+ // Ran out of space
+ if (j+1 >= _buffer_size - offset)
+ return false;
+
// Recieve next character
int c = getc();
if (c < 0)
@@ -168,7 +244,7 @@
// We only succeed if all characters in the response are matched
if (count == j) {
#ifdef AT_ECHO
- printf("AT= %s\r\n", _buffer+offset);
+ ::printf("AT= %s\r\n", _buffer+offset);
#endif
// Reuse the front end of the buffer
memcpy(_buffer, response, i);
@@ -185,7 +261,7 @@
// Clear the buffer when we hit a newline
if (strcmp(&_buffer[offset + j-_delim_size], _delimiter) == 0) {
#ifdef AT_ECHO
- printf("AT< %s", _buffer+offset);
+ ::printf("AT< %s", _buffer+offset);
#endif
j = 0;
}
@@ -197,6 +273,22 @@
// Mapping to vararg functions
+int ATParser::printf(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ int res = vprintf(format, args);
+ va_end(args);
+ return res;
+}
+
+int ATParser::scanf(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ int res = vscanf(format, args);
+ va_end(args);
+ return res;
+}
+
bool ATParser::send(const char *command, ...) {
va_list args;
va_start(args, command);