write line parser

This commit is contained in:
Peter McGoron 2021-07-10 15:10:00 -04:00
commit b7ca22ba79
6 changed files with 1410 additions and 0 deletions

10
Makefile Normal file
View File

@ -0,0 +1,10 @@
TESTS=test/input
tests: $(TESTS)
for i in $(TESTS); do ./$$i; done
TEST_INPUT=test/input.o input.o
test/input: $(TEST_INPUT)
$(CC) -Wall $(TEST_INPUT) -o test/input
.c.o:
$(CC) -std=c89 -Wall -c $< -o $@

10
README Normal file
View File

@ -0,0 +1,10 @@
# libscomp -- Simple Control Protocol #
This is a C89+ library for parsing and executing commands. It is written
for a freestanding implementation, meaning that
* It does no dynamic allocation
* It does not require any standard library functions
* It can run on anything with a C compiler
This is designed for microcontrollers that take ASCII input from serial.

60
input.c Normal file
View File

@ -0,0 +1,60 @@
#include "input.h"
enum { READ, DISCARD };
void libscomm_reset(struct libscomm_input *in) {
in->state = READ;
in->len = 0;
}
static enum libscomm_input_r parse(struct libscomm_input *in,
struct libscomm_line *line) {
char *s = in->intbuf;
line->name = (*s == ':');
line->len = 0;
while (line->len < LIBSCOMM_MAXARG) {
line->buf[line->len++] = s;
for (; *s && *s != '\t'; s++);
if (!*s) {
return LIBSCOMM_COMPLETE;
} else {
*s = 0;
s++;
}
}
return LIBSCOMM_ARG_OVERFLOW;
}
enum libscomm_input_r libscomm_read(struct libscomm_input *in,
struct libscomm_inbuf *buf,
struct libscomm_line *line) {
char c;
while (buf->l > 0) {
buf->l--;
c = *buf->s++;
if (in->state == DISCARD) {
if (c == '\n') {
libscomm_reset(in);
return LIBSCOMM_OVERFLOW;
}
} else {
switch (c) {
case '\n':
in->intbuf[in->len] = 0;
return parse(in, line);
default:
in->intbuf[in->len++] = c;
if (in->len == LIBSCOMM_MAXBUF)
in->state = DISCARD;
}
}
}
return LIBSCOMM_MORE;
}

35
input.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <stddef.h>
#define LIBSCOMM_MAXARG 32
#define LIBSCOMM_MAXBUF 1024
struct libscomm_line {
size_t name;
char *buf[LIBSCOMM_MAXARG];
size_t len;
};
struct libscomm_inbuf {
const char *s;
size_t l;
};
struct libscomm_input {
int state;
char intbuf[LIBSCOMM_MAXBUF];
size_t len;
};
enum libscomm_input_r {
LIBSCOMM_MORE,
LIBSCOMM_OVERFLOW,
LIBSCOMM_ARG_OVERFLOW,
LIBSCOMM_COMPLETE
};
void libscomm_reset(struct libscomm_input *);
enum libscomm_input_r libscomm_read(struct libscomm_input *,
struct libscomm_inbuf *,
struct libscomm_line *);

1266
test/greatest.h Normal file

File diff suppressed because it is too large Load Diff

29
test/input.c Normal file
View File

@ -0,0 +1,29 @@
#include "greatest.h"
#include "../input.h"
#define s(x) {x, sizeof(x) - 1}
TEST one_pass(void) {
struct libscomm_input in;
struct libscomm_inbuf b = s("Arg 1\tArg \r\v\t!\n");
struct libscomm_line l;
libscomm_reset(&in);
ASSERT_EQ(libscomm_read(&in, &b, &l), LIBSCOMM_COMPLETE);
ASSERT_EQ(l.len, 3);
ASSERT_EQ(l.name, 0);
ASSERT_STR_EQ(l.buf[0], "Arg 1");
ASSERT_STR_EQ(l.buf[1], "Arg \r\v");
ASSERT_STR_EQ(l.buf[2], "!");
PASS();
}
GREATEST_MAIN_DEFS();
int main(int argc, char *argv[]) {
GREATEST_MAIN_BEGIN();
RUN_TEST(one_pass);
GREATEST_MAIN_END();
}