Implement serial command parser with floating point support

This commit is contained in:
2024-09-22 03:54:28 +02:00
parent 746f81667e
commit 0103834441
5 changed files with 148 additions and 26 deletions

72
src/common/parser.c Normal file
View File

@@ -0,0 +1,72 @@
#include "common.h"
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#define CMD_MAX_LEN 128
// TODO: Write documentation.
// TODO: Implement start and stop commands.
// TODO: Reset command buffer on timeout?
static char cmdbuf[CMD_MAX_LEN + 1];
static char *tail = cmdbuf + CMD_MAX_LEN - 1;
static char *head = cmdbuf;
static bool ParseLine(cmd_t *out);
bool CMD_Parse(char ch, cmd_t *out)
{
bool is_valid;
if (ch == '\n' || ch == '\r') {
is_valid = ParseLine(out);
tail = cmdbuf + CMD_MAX_LEN - 1;
head = cmdbuf;
return is_valid;
}
if (head < tail) {
*head++ = ch;
*head = '\0';
}
return false;
}
static bool ParseLine(cmd_t *out)
{
head = cmdbuf;
// Command SET <float> <float>
if (tolower(head[0] == 's')) {
if ((tolower(head[1]) != 'e') ||
(tolower(head[2]) != 't')) {
return false;
}
out->type = T_SET;
head += 3;
// Parse <float> arguments
for (int i = 0; i < 2; i++) {
errno = 0;
// Try converting string to floating point
// Skips whitespace and moves tail pointer
out->args[i] = (float) strtod(head, &tail);
if ((errno == ERANGE) ||
(out->args[i] == 0 && head == tail)) {
return false; // Conversion failed
}
head = tail;
}
return true;
}
return false;
}

18
src/common/parser.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef MAD_CORE_COMMON_PARSER
#define MAD_CORE_COMMON_PARSER
#include "common/types.h"
// Command types
#define T_SET 0
struct cmd_s {
int type;
float args[2];
};
typedef struct cmd_s cmd_t;
bool CMD_Parse(char ch, cmd_t *out);
#endif // MAD_CORE_COMMON_PARSER