From f03c47c75516b013de7ac3e7930388b50f350830 Mon Sep 17 00:00:00 2001 From: Anthony Zhang Date: Mon, 13 Jul 2020 02:25:43 -0400 Subject: [PATCH 1/3] Minor parsing bugfix --- README.md | 4 ++-- src/CommandParser.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cafda96..8f4cba6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This library has a higher RAM footprint compared to similar libraries, because i Quickstart ---------- -Search for "CommandParser" in the Arduino Library Manager, and install it. Now you can try a quick example sketch: +Search for "CommandParser" in the Arduino Library Manager, and install it. Now you can try a quick example sketch that accepts commands over serial: ```cpp #include @@ -65,7 +65,7 @@ More examples: Grammar ------- -Commands are null-terminated strings that largely follow this PEG grammar: +Commands are null-terminated strings that largely follow this [PEG grammar](https://en.wikipedia.org/wiki/Parsing_expression_grammar): ``` COMMAND <- COMMAND_NAME (' '+ (ARG_STRING / ARG_DOUBLE / ARG_INT64 / ARG_UINT64))* ' '* diff --git a/src/CommandParser.h b/src/CommandParser.h index 597f6ca..0ed8b04 100644 --- a/src/CommandParser.h +++ b/src/CommandParser.h @@ -32,7 +32,7 @@ template size_t strToInt(const char* buf, T *value, T min_value, T m // parse sign if necessary bool isNegative = false; - if (min_value < 0 && buf[position] == '+' || buf[position] == '-') { + if (min_value < 0 && (buf[position] == '+' || buf[position] == '-')) { isNegative = buf[position] == '-'; position ++; } From 01aa55637f7328cc5a911686459e4549da255894 Mon Sep 17 00:00:00 2001 From: Anthony Zhang Date: Mon, 13 Jul 2020 02:26:17 -0400 Subject: [PATCH 2/3] Bump version --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index b2f9c77..43a26a0 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=CommandParser -version=1.1.0 +version=1.1.1 author=Anthony Zhang (Uberi) maintainer=Anthony Zhang (Uberi) sentence=An Arduino library for parsing commands of the form COMMAND_NAME ARG1 ARG2 ARG3. From 6a3b411f9a2aebfe0e26b32734e29b2f12fe0b10 Mon Sep 17 00:00:00 2001 From: Olaf Hagendorf Date: Thu, 29 Apr 2021 23:16:54 +0200 Subject: [PATCH 3/3] - adding ISO C style for limits defines - bugfixing parsing of negativ int numbers - negativ sign was ignored --- .gitignore | 1 + .mbedignore | 3 +++ src/CommandParser.h | 20 ++++++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .mbedignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..751553b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.bak diff --git a/.mbedignore b/.mbedignore new file mode 100644 index 0000000..2645cfc --- /dev/null +++ b/.mbedignore @@ -0,0 +1,3 @@ +./examples/* +./keywords.txt +./library.properties \ No newline at end of file diff --git a/src/CommandParser.h b/src/CommandParser.h index 0ed8b04..8a9d1bd 100644 --- a/src/CommandParser.h +++ b/src/CommandParser.h @@ -24,8 +24,11 @@ size_t strlcpy(char *dst, const char *src, size_t size) { } */ -// avr-libc lacks strtoll and strtoull (see https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html), so we'll implement our own to be compatible with AVR boards such as the Arduino Uno -// typically you would use this like: `int64_t result; size_t bytesRead = strToInt("-0x123", &result, std::numeric_limits::min(), std::numeric_limits::max())` +// avr-libc lacks strtoll and strtoull (see https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html), +// so we'll implement our own to be compatible with AVR boards such as the Arduino Uno +// typically you would use this like: +// `int64_t result; size_t bytesRead = strToInt("-0x123", &result, std::numeric_limits::min(), +// std::numeric_limits::max())` // if an error occurs during parsing, `bytesRead` will be 0 and `result` will be an arbitrary value template size_t strToInt(const char* buf, T *value, T min_value, T max_value) { size_t position = 0; @@ -68,6 +71,7 @@ template size_t strToInt(const char* buf, T *value, T min_value, T m position ++; } + if(isNegative) *value *= -1; return digit == -1 ? 0 : position; // ensure that there is at least one digit } @@ -212,7 +216,13 @@ class CommandParser { break; } case 'u': { // uint64_t argument +#if defined ULONG_LONG_MAX // GNU style size_t bytesRead = strToInt(command, &commandArgs[i].asUInt64, 0, ULONG_LONG_MAX); +#elif defined ULLONG_MAX // ISO C style + size_t bytesRead = strToInt(command, &commandArgs[i].asUInt64, 0, ULLONG_MAX); +#else + #error "ULONG_LONG_MAX not defined" +#endif if (bytesRead == 0 || (command[bytesRead] != ' ' && command[bytesRead] != '\0')) { snprintf(response, MAX_RESPONSE_SIZE, "parse error: invalid uint64_t for arg %d", i + 1); return false; @@ -221,7 +231,13 @@ class CommandParser { break; } case 'i': { // int64_t argument +#if defined LONG_LONG_MAX // GNU style size_t bytesRead = strToInt(command, &commandArgs[i].asInt64, LONG_LONG_MIN, LONG_LONG_MAX); +#elif defined LLONG_MAX // ISO C style + size_t bytesRead = strToInt(command, &commandArgs[i].asInt64, LLONG_MIN, LLONG_MAX); +#else + #error "LONG_LONG_MAX not defined" +#endif if (bytesRead == 0 || (command[bytesRead] != ' ' && command[bytesRead] != '\0')) { snprintf(response, MAX_RESPONSE_SIZE, "parse error: invalid int64_t for arg %d", i + 1); return false;