Skip to content

Commit

Permalink
Support OCT and BIN radix for read and print
Browse files Browse the repository at this point in the history
  • Loading branch information
tgtakaoka committed Jan 5, 2025
1 parent 4df3302 commit 71b5814
Show file tree
Hide file tree
Showing 10 changed files with 319 additions and 66 deletions.
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ course we can use `Serial.available()` in `loop()` and carefully use
So `libcli` library comes for help. This library offers a Cli instance
as a command line interface which can

- read a letter, a word string, a line of string, decimal and
hexadecimal number from serial console asynchronously.
- read a letter, a word string, a line of string, decimal,
hexadecimal, octal, and binary number from serial console
asynchronously.

- act as `Stream` and do any form of `print()` and `println()`.

- print decimal number with left or right aligned in a specified width
format, such as `"%-6d"` or `"%6d"` in `printf()`.

- print hexadecimal number in specified fixed-width format, such as
`"%08X"` in `printf()`.
- print hexadecimal, octal, and binary number in specified
fixed-width format, such as `"%08X"` `"%04O"` in `printf()`.

- print string with left or right aligned in a specified width, such
as `"%-8s"` or `"%8s"` in `printf()`.
Expand Down Expand Up @@ -87,16 +88,20 @@ void readHex(NumberCallback callback, uintptr_t context, uint32_t limit = UINT32
void readHex(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defVal);
void readDec(NumberCallback callback, uintptr_t context, uint23_t limit = UINt32_MAX);
void readDec(NumberCallback callback, uintptr_t context, uint23_t limit, uint32_t defVal);
void readNum(NumberCallback callback, uintptr_t context, uint8_t radix = 10, uint23_t limit = UINt32_MAX);
void readNum(NumberCallback callback, uintptr_t context, uint8_t radix = 10, uint23_t limit, uint32_t defVal);
void printStr(const char *text, int8_t width = 0);
void printStr(const __FlashStringHelper *text, int8_t width = 0);
void printStr_P(const /*PROGMEM*/ char *text_P, int8_t width = 0);
void printHex(uint32_t number, int8_t width = 0);
void printDec(uint32_t number, int8_t width = 0);
void printNum(uint32_t number, uint8_t radix = 10, int8_t width = 0);
void printlnStr(const __FlashStringHelper *text, int8_t width = 0);
void printlnStr_P(const /*PROGMEM*/ char *text_P, int8_t width = 0);
void printlnHex(uint32_t number, int8_t width = 0);
void printlnDec(uint32_t number, int8_t width = 0);
void printlnNum(uint32_t number, uint8_t radix = 10, int8_t width = 0);
void backspace(int8_t n = 1);
```

Expand Down
15 changes: 10 additions & 5 deletions README_.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ course we can use `Serial.available()` in `loop()` and carefully use
So `libcli` library comes for help. This library offers a Cli instance
as a command line interface which can

* read a letter, a word string, a line of string, decimal and
hexadecimal number from serial console asynchronously.
* read a letter, a word string, a line of string, decimal,
hexadecimal, octal and binary number from serial console
asynchronously.
* act as `Stream` and do any form of `print()` and `println()`.
* print decimal number with left or right aligned in a specified width
format, such as `"%-6d"` or `"%6d"` in `printf()`.
* print hexadecimal number in specified fixed-width format, such as
`"%08X"` in `printf()`.
* print hexadecimal, octal, and binary number in specified fixed-width
format, such as `"%08X", "%04O"` in `printf()`.
* print string with left or right aligned in a specified width, such
as `"%-8s"` or `"%8s"` in `printf()`.

Expand Down Expand Up @@ -66,7 +67,7 @@ void loop() {
}
----

The version 1.3 API has the following functions.
The version 1.4 API has the following functions.

[source,C++]
----
Expand All @@ -85,16 +86,20 @@ void readHex(NumberCallback callback, uintptr_t context, uint32_t limit = UINT32
void readHex(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defVal);
void readDec(NumberCallback callback, uintptr_t context, uint23_t limit = UINt32_MAX);
void readDec(NumberCallback callback, uintptr_t context, uint23_t limit, uint32_t defVal);
void readNum(NumberCallback callback, uintptr_t context, uint8_t radix = 10, uint23_t limit = UINt32_MAX);
void readNum(NumberCallback callback, uintptr_t context, uint8_t radix, uint23_t limit, uint32_t defVal);
void printStr(const char *text, int8_t width = 0);
void printStr(const __FlashStringHelper *text, int8_t width = 0);
void printStr_P(const /*PROGMEM*/ char *text_P, int8_t width = 0);
void printHex(uint32_t number, int8_t width = 0);
void printDec(uint32_t number, int8_t width = 0);
void printNum(uint32_t number, uint8_t radix = 10, int8_t width = 0);
void printlnStr(const __FlashStringHelper *text, int8_t width = 0);
void printlnStr_P(const /*PROGMEM*/ char *text_P, int8_t width = 0);
void printlnHex(uint32_t number, int8_t width = 0);
void printlnDec(uint32_t number, int8_t width = 0);
void printlnNum(uint32_t number, uint8_t radix = 10, int8_t width = 0);
void backspace(int8_t n = 1);
----

Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "libcli",
"version": "1.3.0",
"version": "1.4.0",
"description": "Command Line Interface Library",
"keywords": "command line",
"repository":
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=libcli
version=1.3.0
version=1.4.0
author=Tadashi G. Takaoka
maintainer=Tadashi G. Takaoka <[email protected]>
sentence=Command Line Interface library
Expand Down
28 changes: 25 additions & 3 deletions src/libcli.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
#include <Arduino.h>

#define LIBCLI_VERSION_MAJOR 1
#define LIBCLI_VERSION_MINOR 3
#define LIBCLI_VERSION_MINOR 4
#define LIBCLI_VERSION_PATCH 0
#define LIBCLI_VERSION_STRING "1.3.0"
#define LIBCLI_VERSION_STRING "1.4.0"

#include "libcli_types.h"

Expand All @@ -35,7 +35,6 @@ namespace libcli {
/** Library interface of libcli. */
class Cli final : public Stream {
public:

Cli() : _impl() {}

/** Initialize with |console| as command line interface. */
Expand Down Expand Up @@ -110,6 +109,18 @@ class Cli final : public Stream {
*/
void readDec(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defval);

/**
* Read |radix| number less or equal to |limit|.
*/
void readNum(NumberCallback callback, uintptr_t context, uint8_t radix = 10,
uint32_t limit = UINT32_MAX);

/**
* Read |radix| number less or equal to |limit| with |defval| as default.
*/
void readNum(NumberCallback callback, uintptr_t context, uint8_t radix, uint32_t limit,
uint32_t defval);

/**
* Print |number| in 0-prefixed hexadecimal format of |width| chars. Negative |width| means left
* aligned.
Expand All @@ -122,6 +133,12 @@ class Cli final : public Stream {
*/
size_t printDec(uint32_t number, int8_t width = 0);

/**
* Print |number| in right-aligned |radix| format of |width| chars. Negative |width| means left
* aligned.
*/
size_t printNum(uint32_t number, uint8_t radix = 10, int8_t width = 0);

/**
* Print |number| in 0-prefixed hexadecimal format of |width| chars and newline.
*/
Expand All @@ -132,6 +149,11 @@ class Cli final : public Stream {
*/
size_t printlnDec(uint32_t number, int8_t width = 0);

/**
* Print |number| in right-aligned |radix|format of |width| chars and newline.
*/
size_t printlnNum(uint32_t number, uint8_t radix = 10, int8_t width = 0);

/*
* Print |text| in right-aligned of |width| chars. Negative |width| means left-aligned.
*/
Expand Down
33 changes: 25 additions & 8 deletions src/libcli/libcli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ Cli &Cli::instance() {
}

size_t Cli::printHex(uint32_t number, int8_t width) {
return _impl.printHex(number, width, false);
return _impl.printNum(number, width, 16, false);
}

size_t Cli::printDec(uint32_t number, int8_t width) {
return _impl.printDec(number, width, false);
return _impl.printNum(number, width, 10, false);
}

size_t Cli::printNum(uint32_t number, uint8_t radix, int8_t width) {
return _impl.printNum(number, width, radix, false);
}

size_t Cli::printStr(const __FlashStringHelper *text, int8_t width) {
Expand All @@ -48,11 +52,15 @@ size_t Cli::printStr_P(const /*PROGMEM*/ char *text_P, int8_t width) {
}

size_t Cli::printlnHex(uint32_t number, int8_t width) {
return _impl.printHex(number, width, true);
return _impl.printNum(number, width, 16, true);
}

size_t Cli::printlnDec(uint32_t number, int8_t width) {
return _impl.printDec(number, width, true);
return _impl.printNum(number, width, 10, true);
}

size_t Cli::printlnNum(uint32_t number, uint8_t radix, int8_t width) {
return _impl.printNum(number, width, radix, true);
}

size_t Cli::printlnStr(const __FlashStringHelper *text, int8_t width) {
Expand Down Expand Up @@ -86,19 +94,28 @@ void Cli::readLine(
}

void Cli::readHex(NumberCallback callback, uintptr_t context, uint32_t limit) {
_impl.setCallback(callback, context, limit, true);
_impl.setCallback(callback, context, limit, 16);
}

void Cli::readHex(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defval) {
_impl.setCallback(callback, context, limit, defval, true);
_impl.setCallback(callback, context, limit, defval, 16);
}

void Cli::readDec(NumberCallback callback, uintptr_t context, uint32_t limit) {
_impl.setCallback(callback, context, limit, false);
_impl.setCallback(callback, context, limit, 10);
}

void Cli::readDec(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defval) {
_impl.setCallback(callback, context, limit, defval, false);
_impl.setCallback(callback, context, limit, defval, 10);
}

void Cli::readNum(NumberCallback callback, uintptr_t context, uint8_t radix, uint32_t limit) {
_impl.setCallback(callback, context, limit, radix);
}

void Cli::readNum(NumberCallback callback, uintptr_t context, uint8_t radix, uint32_t limit,
uint32_t defval) {
_impl.setCallback(callback, context, limit, defval, radix);
}

} // namespace libcli
Expand Down
56 changes: 18 additions & 38 deletions src/libcli/libcli_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ bool isNewline(char c) {
}

/** Returns number of digits of |number| in |radix|. */
int8_t getDigits(uint32_t number, bool hex) {
const uint8_t radix = hex ? 16 : 10;
int8_t getDigits(uint32_t number, uint8_t radix) {
int8_t n = 0;
do {
n++;
Expand All @@ -62,20 +61,10 @@ size_t Impl::pad_right(int8_t len, int8_t width, char pad) {
return size;
}

size_t Impl::printHex(uint32_t number, int8_t width, bool newline) {
const auto len = getDigits(number, true);
size_t size = pad_left(len, width, '0');
size += console->print(number, HEX);
size += pad_right(len, width, ' ');
if (newline)
size += console->println();
return size;
}

size_t Impl::printDec(uint32_t number, int8_t width, bool newline) {
const auto len = getDigits(number, false);
size_t size = pad_left(len, width, ' ');
size += console->print(number, DEC);
size_t Impl::printNum(uint32_t number, int8_t width, uint8_t radix, bool newline) {
const auto len = getDigits(number, radix);
size_t size = pad_left(len, width, radix == 10 ? ' ' : '0');
size += console->print(number, radix);
size += pad_right(len, width, ' ');
if (newline)
size += console->println();
Expand Down Expand Up @@ -160,37 +149,33 @@ void Impl::processString(char c) {
}
}

void Impl::setCallback(NumberCallback callback, uintptr_t context, uint32_t limit, bool hex) {
void Impl::setCallback(NumberCallback callback, uintptr_t context, uint32_t limit, uint8_t radix) {
this->callback.number = callback;
num_width = getDigits(num_limit = limit, num_hex = hex);
num_width = getDigits(num_limit = limit, num_radix = radix);
num_value = 0;
num_len = 0;
setProcessor(&Impl::processNumber, context);
}

void Impl::setCallback(
NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defval, bool hex) {
setCallback(callback, context, limit, hex);
void Impl::setCallback(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defval,
uint8_t radix) {
setCallback(callback, context, limit, radix);
backspace(num_width);
num_value = defval;
num_len = num_width;
if (hex) {
printHex(num_value, num_len, false);
} else {
printDec(num_value, num_len, false);
}
printNum(num_value, num_len, radix, false);
}

bool Impl::checkLimit(char c, uint8_t &n) const {
if (num_len >= num_width)
return false;
c = toUpperCase(c);
if (!num_hex && isDigit(c)) {
if (num_radix <= 10 && isDigit(c) && c < num_radix + '0') {
n = c - '0';
const uint32_t limit = num_limit / 10;
return num_value < limit || (num_value == limit && n <= (num_limit % 10));
const uint32_t limit = num_limit / num_radix;
return num_value < limit || (num_value == limit && n <= (num_limit % num_radix));
}
if (num_hex && isHexadecimalDigit(c)) {
if (num_radix == 16 && isHexadecimalDigit(c)) {
n = isDigit(c) ? c - '0' : c - 'A' + 10;
const uint32_t limit = num_limit / 16;
return num_value < limit || (num_value == limit && n <= (num_limit % 16));
Expand All @@ -199,10 +184,9 @@ bool Impl::checkLimit(char c, uint8_t &n) const {
}

void Impl::processNumber(char c) {
const uint8_t radix = num_hex ? 16 : 10;
uint8_t n;
if (checkLimit(c, n)) {
num_value *= radix;
num_value *= num_radix;
num_value += n;
num_len++;
console->print(c);
Expand All @@ -212,7 +196,7 @@ void Impl::processNumber(char c) {
State state;
if (isBackspace(c)) {
if (num_len) {
num_value /= radix;
num_value /= num_radix;
num_len--;
backspace(1);
return;
Expand All @@ -221,11 +205,7 @@ void Impl::processNumber(char c) {
} else if (isSpace(c) && num_len) {
backspace(num_len);
num_len = num_width;
if (num_hex) {
printHex(num_value, num_len, false);
} else {
printDec(num_value, num_len, false);
}
printNum(num_value, num_len, num_radix, false);
if (isNewline(c)) {
console->print(' ');
state = CLI_NEWLINE;
Expand Down
11 changes: 5 additions & 6 deletions src/libcli/libcli_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,12 @@ struct Impl final {
void setCallback(LetterCallback callback, uintptr_t context);
void setCallback(StringCallback callback, uintptr_t context, char *buffer, size_t size,
bool hasDefval, bool word);
void setCallback(NumberCallback callback, uintptr_t context, uint32_t limit, bool hex);
void setCallback(NumberCallback callback, uintptr_t context, uint32_t limit,
uint32_t defval, bool hex);
void setCallback(NumberCallback callback, uintptr_t context, uint32_t limit, uint8_t radix);
void setCallback(NumberCallback callback, uintptr_t context, uint32_t limit, uint32_t defval,
uint8_t radix);

size_t backspace(int8_t n);
size_t printHex(uint32_t number, int8_t width, bool newline);
size_t printDec(uint32_t number, int8_t width, bool newline);
size_t printNum(uint32_t number, int8_t width, uint8_t radix, bool newline);
size_t printStr(const __FlashStringHelper *str, int8_t width, bool newline);
size_t printStr(const char *str, int8_t width, bool newline);

Expand Down Expand Up @@ -82,7 +81,7 @@ struct Impl final {

uint32_t num_value;
uint32_t num_limit;
bool num_hex;
uint8_t num_radix;
uint8_t num_len;
uint8_t num_width;

Expand Down
Loading

0 comments on commit 71b5814

Please sign in to comment.