You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

213 lines
5.8 KiB

/**
* Utilities for console commands
*
* Created on 2020/03/11.
*/
#ifndef LIBCONSOLE_UTILS_H
#define LIBCONSOLE_UTILS_H
#include <stdio.h>
#include <console/console.h>
#ifndef STR
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#ifndef OBC_FIRMWARE
#define EXPENDABLE_STRING(x) x
#define EXPENDABLE_CODE(x) x
#else
#define EXPENDABLE_STRING(x) ""
#define EXPENDABLE_CODE(x) do {} while(0);
#endif
/**
* Read an argument, or return default if it is empty.
*
* This works for commands arg_int0
*
* Usage:
*
* \code
* static struct {
* struct arg_int *foo;
* } args;
*
* args.foo = arg_int0(...);
*
* int foo = GET_ARG_INT0(args.foo, 1234);
* \endcode
*/
#define GET_ARG_INT0(_arg, _def) ((_arg)->count ? (_arg)->ival[0] : (_def))
/**
* Get CSP node ID from an argument table, using own address as default.
*
* Usage:
*
* \code
* static struct {
* struct arg_int *node;
* } args;
*
* args.node = arg_int0(...);
*
* int node = GET_ARG_CSPADDR0(args.node);
* \endcode
*/
#define GET_ARG_CSPADDR0(_arg) GET_ARG_INT0((_arg), csp_get_address())
/**
* Shortcut to get a timeout argument's value, using CSP_DEF_TIMEOUT_MS as default.
*/
#define GET_ARG_TIMEOUT0(_arg) GET_ARG_INT0((_arg), CONSOLE_CSP_DEF_TIMEOUT_MS)
/**
* Define an optional CSP node argument
*/
#define arg_cspaddr0() arg_int0(NULL, NULL, "<node>", EXPENDABLE_STRING("node ID"))
/**
* Define a mandatory CSP node argument
*/
#define arg_cspaddr1() arg_int1(NULL, NULL, "<node>", EXPENDABLE_STRING("node ID"))
/**
* Define an optional timeout argument, with `CSP_DEF_TIMEOUT_MS`
* shown as default. Use `GET_ARG_TIMEOUT0()` to retrieve its value.
*/
#define arg_timeout0() arg_int0("t", "timeout", "<ms>", EXPENDABLE_STRING("timeout in ms (default "STR(CONSOLE_CSP_DEF_TIMEOUT_MS)")"))
/**
* Define a timeout argument with a custom value shown as default.
* Use `GET_ARG_INT0()` with the matching default to retrieve its value.
*/
#define arg_timeout0_def(_def) arg_int0("t", "timeout", "<ms>", EXPENDABLE_STRING("timeout in ms (default "STR(_def)")"))
#define EMPTY_CMD_SETUP(_helptext) \
(void)ctx; \
static struct { \
struct arg_end *end; \
} args; \
\
if (reg) { \
args.end = arg_end(1); \
\
reg->argtable = &args; \
reg->help = EXPENDABLE_STRING(_helptext); \
return 0; \
}
/**
* Hexdump a buffer
*
* @param outf - output file
* @param data - data to dump
* @param len - data size
*/
void console_hexdump(const void *data, size_t len);
/**
* Decode hexa string to binary
*
* @param hex - hexa string, upper or lower case, must have even length
* @param dest - destination buffer
* @param capacity - buffer size
* @return destination length, or: -1 (bad args), -2 (bad format), -3 (too long)
*/
int console_base16_decode(const char *hex, void *dest, size_t capacity);
#if CONSOLE_USE_MEMSTREAM
/**
* Data struct for the filecap utilities
*/
struct console_filecap {
char *buf;
size_t buf_size;
FILE *file;
};
typedef struct console_filecap console_filecap_t;
/**
* Open a temporary in-memory file that can be used to capture the output
* of functions taking a FILE * argument.
*
* @param cap - pointer to a filecap struct (can be on stack)
* @return success
*/
console_err_t console_filecap_init(console_filecap_t *cap);
/**
* Clean up the capture struct.
*
* If the buffer is to be used elsewhere, place NULL in the struct to avoid freeing it.
*
* If the struct itself was allocated on heap, it is the caller's responsibility to free it manually.
*
* @param cap - pointer to a filecap struct
*/
void console_filecap_end(console_filecap_t *cap);
/**
* Print the captured output to console output stream and clean up the struct (calls `console_filecap_end()`)
*
* @param cap - pointer to a filecap struct
*/
void console_filecap_print_end(console_filecap_t *cap);
#endif // CONSOLE_USE_MEMSTREAM
/**
* Cross-platform malloc that can be used from console commands.
* If CSP is available and the platform is not POSIX, the implementation from there is used (i.e. FreeRTOS alloc)
*/
void * __attribute__((malloc)) console_malloc(size_t size);
/**
* Cross-platform realloc that can be used from console commands.
*
* It is not possible to determine the size of an allocated memory region in a portable way,
* that's why this function takes the old size as an argument. On POSIX, the argument is simply ignored.
*
* If CSP is available and the platform is not POSIX, the implementation from there is used (i.e. FreeRTOS alloc).
* NOTE: CSP does not provide realloc, therefore this function allocates a new buffer, copies data, and frees the old buffer.
*
* Returns the original buffer if the new size is <= old size.
*/
void * console_realloc(void *ptr, size_t oldsize, size_t newsize);
/**
* Cross-platform calloc that can be used from console commands.
* If CSP is available and the platform is not POSIX, the implementation from there is used (i.e. FreeRTOS alloc)
*/
void * __attribute__((malloc,alloc_size(1,2))) console_calloc(size_t nmemb, size_t size);
/**
* `free()` for memory allocated by `console_malloc()` or `console_calloc()`
*/
void console_free(void *ptr);
/**
* `strdup()` using `console_malloc()`. Free with `console_free()`
*/
char * console_strdup(const char *ptr);
/**
* `strndup()` using `console_malloc()`. Free with `console_free()`
*/
char * console_strndup(const char *ptr, size_t maxlen);
#endif //LIBCONSOLE_UTILS_H