X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=input.c;h=fa2ae924c3aba2e146cba6039529d74fa6aa793e;hb=a4ad64eb41a4fc3393fb264922925aa041421c11;hp=748a0cad3405a45a63e127fa39369b3faf967944;hpb=5e80d9852edea8472cd478655d70f5c4a1eddbdc;p=cparser diff --git a/input.c b/input.c index 748a0ca..fa2ae92 100644 --- a/input.c +++ b/input.c @@ -1,15 +1,23 @@ #include "config.h" +#include "diagnostic.h" #include "input.h" #include -#include "lexer.h" -#include "diagnostic.h" typedef size_t (*decode_func)(input_t *input, utf32 *buffer, size_t buffer_size); +typedef enum { + INPUT_FILE, + INPUT_STRING +} input_kind_t; + struct input_t { - FILE *file; + input_kind_t kind; + union { + FILE *file; + const char *string; + } in; decode_func decode; /* state for utf-8 decoder */ @@ -25,25 +33,36 @@ void set_input_error_callback(input_error_callback_func new_func) input_error = new_func; } -static size_t read_block(FILE *file, unsigned char *const read_buf, +static size_t read_block(input_t *input, unsigned char *const read_buf, size_t const n) { - size_t const s = fread(read_buf, 1, n, file); - if (s == 0) { - /* on OS/X ferror appears to return true on eof as well when running - * the application in gdb... */ - if (!feof(file) && ferror(file)) - input_error(0, 0, "read from input failed"); - return 0; + if (input->kind == INPUT_FILE) { + FILE *file = input->in.file; + size_t const s = fread(read_buf, 1, n, file); + if (s == 0) { + /* on OS/X ferror appears to return true on eof as well when running + * the application in gdb... */ + if (!feof(file) && ferror(file)) + input_error(0, 0, "read from input failed"); + return 0; + } + return s; + } else { + assert(input->kind == INPUT_STRING); + size_t len = strlen(input->in.string); + if (len > n) + len = n; + memcpy(read_buf, input->in.string, len); + input->in.string += len; + return len; } - return s; } static size_t decode_iso_8859_1(input_t *input, utf32 *buffer, size_t buffer_size) { unsigned char read_buf[buffer_size]; - size_t const s = read_block(input->file, read_buf, sizeof(read_buf)); + size_t const s = read_block(input, read_buf, sizeof(read_buf)); unsigned char const *src = read_buf; unsigned char const *end = read_buf + s; @@ -58,7 +77,7 @@ static size_t decode_iso_8859_15(input_t *input, utf32 *buffer, size_t buffer_size) { unsigned char read_buf[buffer_size]; - size_t const s = read_block(input->file, read_buf, sizeof(read_buf)); + size_t const s = read_block(input, read_buf, sizeof(read_buf)); unsigned char const *src = read_buf; unsigned char const *end = read_buf + s; @@ -85,8 +104,8 @@ static size_t decode_utf8(input_t *input, utf32 *buffer, size_t buffer_size) { unsigned char read_buf[buffer_size]; - while (true) { - size_t const s = read_block(input->file, read_buf, sizeof(read_buf)); + for (;;) { + size_t const s = read_block(input, read_buf, sizeof(read_buf)); if (s == 0) { if (input->utf8_part_decoded_rest_len > 0) input_error(0, 0, "incomplete input char at end of input"); @@ -195,7 +214,7 @@ static size_t decode_windows_1252(input_t *input, utf32 *buffer, size_t buffer_size) { unsigned char read_buf[buffer_size]; - size_t const s = read_block(input->file, read_buf, sizeof(read_buf)); + size_t const s = read_block(input, read_buf, sizeof(read_buf)); unsigned char const *src = read_buf; unsigned char const *end = read_buf + s; @@ -274,26 +293,38 @@ static int my_strcasecmp(const char *s1, const char *s2) return (unsigned char)*s1 - (unsigned char)*s2; } -input_t *input_from_stream(FILE *file, const char *encoding) +static void choose_decoder(input_t *result, const char *encoding) { - input_t *result = XMALLOCZ(input_t); - result->file = file; - - if (encoding == NULL) { - result->decode = decode_utf8; - } else { + if (encoding) { for (named_decoder_t const *i = decoders; i->name != NULL; ++i) { if (my_strcasecmp(encoding, i->name) != 0) continue; result->decode = i->decoder; - break; - } - if (result->decode == NULL) { - fprintf(stderr, "error: input encoding \"%s\" not supported\n", - encoding); - result->decode = decode_utf8; + return; } + errorf(NULL, "input encoding \"%s\" not supported", encoding); } + result->decode = decode_utf8; +} + +input_t *input_from_stream(FILE *file, const char *encoding) +{ + input_t *result = XMALLOCZ(input_t); + result->kind = INPUT_FILE; + result->in.file = file; + + choose_decoder(result, encoding); + + return result; +} + +input_t *input_from_string(const char *string, const char *encoding) +{ + input_t *result = XMALLOCZ(input_t); + result->kind = INPUT_STRING; + result->in.string = string; + + choose_decoder(result, encoding); return result; }