write line parser
This commit is contained in:
commit
b7ca22ba79
|
@ -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 $@
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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 *);
|
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue