diff --git a/src/Makefile.am b/src/Makefile.am index 92ae728..2eb2648 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,7 @@ libapfl_a_SOURCES += strings.c libapfl_a_SOURCES += token.c libapfl_a_SOURCES += tokenizer.c libapfl_a_SOURCES += parser.c +libapfl_a_SOURCES += source_readers.c apfl_internal_headers = apfl_internal_headers += common.h diff --git a/src/apfl.h b/src/apfl.h index 98fac6c..4a3b446 100644 --- a/src/apfl.h +++ b/src/apfl.h @@ -419,6 +419,15 @@ struct apfl_token apfl_tokenizer_get_token(apfl_tokenizer_ptr); struct apfl_error apfl_tokenizer_get_error(apfl_tokenizer_ptr); +/* An apfl_source_reader_cb implementation to have a string view as a source. + * Use together with apfl_string_source_reader_new. + */ +bool apfl_string_source_reader(void *, char *, size_t *len, bool); + +void *apfl_string_source_reader_new(struct apfl_string_view); +void apfl_string_source_reader_destroy(void *); + + struct apfl_parser_token_source { enum apfl_parse_result (*next)(void *, bool need); struct apfl_token (*get_token)(void *); diff --git a/src/source_readers.c b/src/source_readers.c new file mode 100644 index 0000000..0af337b --- /dev/null +++ b/src/source_readers.c @@ -0,0 +1,47 @@ +#include +#include + +#include "apfl.h" +#include "internal.h" + +struct string_source_reader { + struct apfl_string_view sv; + size_t off; +}; + +bool +apfl_string_source_reader(void *opaque, char *buf, size_t *len, bool need) +{ + (void)need; + + struct string_source_reader *ctx = opaque; + + size_t maxlen = *len; + size_t remain_len = ctx->sv.len - ctx->off; + *len = maxlen < remain_len ? maxlen : remain_len; + memcpy(buf, ctx->sv.bytes + ctx->off, *len); + ctx->off += *len; + assert(ctx->off <= ctx->sv.len); + + return true; +} + +void * +apfl_string_source_reader_new(struct apfl_string_view sv) +{ + struct string_source_reader *ctx = ALLOC(struct string_source_reader); + if (ctx == NULL) { + return NULL; + } + + ctx->sv = sv; + ctx->off = 0; + + return ctx; +} + +void +apfl_string_source_reader_destroy(void *opaque) +{ + free(opaque); +} diff --git a/src/tokenizer_test.c b/src/tokenizer_test.c index 39c53f6..60455c4 100644 --- a/src/tokenizer_test.c +++ b/src/tokenizer_test.c @@ -4,12 +4,6 @@ #include "test.h" -struct string_src_reader_ctx { - char *text; - char *remain_text; - size_t remain_len; -}; - static void * must_alloc(testctx t, size_t size) { @@ -20,39 +14,21 @@ must_alloc(testctx t, size_t size) return out; } -static bool -string_src_reader(void *_ctx, char *buf, size_t *len, bool need) -{ - (void)need; - - struct string_src_reader_ctx *ctx = _ctx; - - size_t maxlen = *len; - *len = maxlen < ctx->remain_len ? maxlen : ctx->remain_len; - memcpy(buf, ctx->remain_text, *len); - ctx->remain_text += *len; - assert(*len <= ctx->remain_len); - ctx->remain_len -= *len; - - return true; -} - struct tokenizer_test { testctx t; apfl_tokenizer_ptr tokenizer; - struct string_src_reader_ctx *ctx; + void *ctx; }; static struct tokenizer_test * new_tokenizer_test(testctx t, const char *text) { - struct string_src_reader_ctx *ctx = must_alloc(t, sizeof(struct string_src_reader_ctx)); - ctx->remain_len = strlen(text); - ctx->text = must_alloc(t, ctx->remain_len + 1); - strcpy(ctx->text, text); - ctx->remain_text = ctx->text; + void *ctx = apfl_string_source_reader_new(apfl_string_view_from(text)); + if (ctx == NULL) { + test_fatalf(t, "Failed to initialize the source reader"); + } - apfl_tokenizer_ptr tokenizer = apfl_tokenizer_new(string_src_reader, ctx); + apfl_tokenizer_ptr tokenizer = apfl_tokenizer_new(apfl_string_source_reader, ctx); if (tokenizer == NULL) { test_fatalf(t, "Failed to initialize the tokenizer"); } @@ -71,8 +47,7 @@ new_tokenizer_test(testctx t, const char *text) static void destroy_tokenizer_test(struct tokenizer_test *tt) { - free(tt->ctx->text); - free(tt->ctx); + apfl_string_source_reader_destroy(tt->ctx); apfl_tokenizer_destroy(tt->tokenizer); free(tt); }