From 1efda72797797ceb2a1693c88e4f5cc1f421e241 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Wed, 21 Nov 2018 22:32:22 -0500 Subject: Read files in edi --- bin/edi/file.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 bin/edi/file.c (limited to 'bin/edi/file.c') diff --git a/bin/edi/file.c b/bin/edi/file.c new file mode 100644 index 00000000..322b5616 --- /dev/null +++ b/bin/edi/file.c @@ -0,0 +1,85 @@ +/* Copyright (C) 2018 Curtis McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "edi.h" + +enum { + BufCap = 8192, + LogCap = 8, +}; + +struct File fileAlloc(char *path) { + struct File file = { + .path = path, + .buf = bufferAlloc(BufCap), + .log = logAlloc(LogCap), + .clean = 0, + }; + if (!path) logPush(&file.log, TableEmpty); + return file; +} + +void fileFree(struct File *file) { + logFree(&file->log); + bufferFree(&file->buf); + free(file->path); +} + +static const mbstate_t MBStateInit; + +// TODO: Error handling. +void fileRead(struct File *file) { + if (!file->path) return; + + FILE *stream = fopen(file->path, "r"); + if (!stream) { + if (errno != ENOENT) err(EX_NOINPUT, "%s", file->path); + logPush(&file->log, TableEmpty); + file->clean = file->log.state; + return; + } + + struct Table table = tableAlloc(1); + + char buf[BufCap]; + mbstate_t mbState = MBStateInit; + while (!feof(stream)) { + size_t mbsLen = fread(buf, 1, sizeof(buf), stream); + if (ferror(stream)) err(EX_IOERR, "%s", file->path); + + const char *mbs = buf; + mbstate_t mbLenState = mbState; + size_t wcsLen = mbsnrtowcs(NULL, &mbs, mbsLen, 0, &mbLenState); + if (wcsLen == (size_t)-1) err(EX_DATAERR, "%s", file->path); + + wchar_t *wcs = bufferDest(&file->buf, wcsLen); + assert(wcsLen == mbsnrtowcs(wcs, &mbs, mbsLen, wcsLen, &mbState)); + + tablePush(&table, file->buf.slice); + } + logPush(&file->log, table); + file->clean = file->log.state; + + fclose(stream); +} -- cgit 1.4.1