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/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/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. diff --git a/src/CommandParser.h b/src/CommandParser.h index 597f6ca..8a9d1bd 100644 --- a/src/CommandParser.h +++ b/src/CommandParser.h @@ -24,15 +24,18 @@ 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; // 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 ++; } @@ -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;