Add apfl_string_source_reader
A useful source reader implementation to pass in a source saved as an in-memory string into the tokenizer. This replaces the string_src_reader in the tokenizer_test and is even a bit more flexible, by allowing any aplf_string_view as the source.
This commit is contained in:
parent
e79945a398
commit
025fd61abd
4 changed files with 64 additions and 32 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
47
src/source_readers.c
Normal file
47
src/source_readers.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue