+/*
+ * This file is part of cparser.
+ * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
+ */
#include "config.h"
+#include "diagnostic.h"
#include "input.h"
#include <ctype.h>
-#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 */
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;
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;
{
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");
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;
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;
}