diff options
author | June McEnroe <june@causal.agency> | 2018-11-25 20:53:34 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2018-11-25 20:53:34 -0500 |
commit | 3106ccf7551ef1dc8b0279b032b8c53655fe3c42 (patch) | |
tree | d80585c6099857af440460e504f92255a1c4001a | |
parent | Implement deserialization in edi (diff) | |
download | src-3106ccf7551ef1dc8b0279b032b8c53655fe3c42.tar.gz src-3106ccf7551ef1dc8b0279b032b8c53655fe3c42.zip |
Return enum Error from file functions in edi
-rw-r--r-- | bin/edi/edi.c | 34 | ||||
-rw-r--r-- | bin/edi/edi.h | 8 | ||||
-rw-r--r-- | bin/edi/file.c | 65 | ||||
-rw-r--r-- | bin/edi/log.c | 15 |
4 files changed, 58 insertions, 64 deletions
diff --git a/bin/edi/edi.c b/bin/edi/edi.c index 9418f1d9..1ef2e055 100644 --- a/bin/edi/edi.c +++ b/bin/edi/edi.c @@ -23,24 +23,27 @@ #include "edi.h" +static void errorExit(enum Error error, const char *prefix) { + if (error > Errno) errc(EX_IOERR, error - Errno, "%s", prefix); + else errx(EX_DATAERR, "%s: %d", prefix, error); +} + int main(int argc, char *argv[]) { setlocale(LC_CTYPE, ""); if (argc < 2) return EX_USAGE; + enum Error error; + struct File file = fileAlloc(strdup(argv[1])); - fileRead(&file); - - struct Edit edit = { file.buf, file.log }; + error = fileRead(&file); + if (error) errorExit(error, file.path); FILE *store = fopen("store.edi", "w"); if (!store) err(EX_CANTCREAT, "store.edi"); - enum Error error = storeWrite(store, &edit); - if (error) { - if (error > Errno) errc(EX_IOERR, error - Errno, "store.edi"); - else errx(EX_IOERR, "store.edi: %d", error); - } + error = storeWrite(store, &file.edit); + if (error) errorExit(error, "store.edi"); fclose(store); if (ferror(store)) err(EX_IOERR, "store.edi"); @@ -48,21 +51,16 @@ int main(int argc, char *argv[]) { store = fopen("store.edi", "r"); if (!store) err(EX_CANTCREAT, "store.edi"); - error = storeRead(store, &edit); - if (error) { - if (error > Errno) errc(EX_IOERR, error - Errno, "store.edi"); - else errx(EX_DATAERR, "store.edi: %d", error); - } - - file.buf = edit.buf; - file.log = edit.log; + error = storeRead(store, &file.edit); + if (error) errorExit(error, "store.edi"); - const struct Table *table = logTable(&file.log); + const struct Table *table = logTable(&file.edit.log); for (struct Iter it = iter(table, 0); it.ch != WEOF; it = iterNext(it)) { printf("%lc", it.ch); } - fileWrite(&file); + error = fileWrite(&file); + if (error) errorExit(error, file.path); fileFree(&file); } diff --git a/bin/edi/edi.h b/bin/edi/edi.h index c12aceb0..f35af64a 100644 --- a/bin/edi/edi.h +++ b/bin/edi/edi.h @@ -98,6 +98,7 @@ enum Error { StoreMagic, StoreVersion, StoreEOF, + FileNoPath, Errno, }; @@ -106,11 +107,10 @@ enum Error storeRead(FILE *stream, struct Edit *edit); struct File { char *path; - struct Buffer buf; - struct Log log; size_t clean; + struct Edit edit; }; struct File fileAlloc(char *path); void fileFree(struct File *file); -void fileRead(struct File *file); -void fileWrite(struct File *file); +enum Error fileRead(struct File *file); +enum Error fileWrite(struct File *file); diff --git a/bin/edi/file.c b/bin/edi/file.c index 7f9fef45..7bcef76d 100644 --- a/bin/edi/file.c +++ b/bin/edi/file.c @@ -14,11 +14,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <err.h> +#include <assert.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <sysexits.h> #include <wchar.h> #include "edi.h" @@ -32,31 +31,32 @@ enum { struct File fileAlloc(char *path) { struct File file = { .path = path, - .buf = bufferAlloc(BufferCap), - .log = logAlloc(LogCap), + .edit = { + .buf = bufferAlloc(BufferCap), + .log = logAlloc(LogCap), + }, }; - if (!path) logPush(&file.log, TableEmpty); + if (!path) logPush(&file.edit.log, TableEmpty); return file; } void fileFree(struct File *file) { - logFree(&file->log); - bufferFree(&file->buf); + logFree(&file->edit.log); + bufferFree(&file->edit.buf); free(file->path); } static const mbstate_t StateInit; -// TODO: Error handling. -void fileRead(struct File *file) { - if (!file->path) return; +enum Error fileRead(struct File *file) { + if (!file->path) return FileNoPath; 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; + if (errno != ENOENT) return Errno + errno; + logPush(&file->edit.log, TableEmpty); + file->clean = file->edit.log.state; + return Ok; } struct Table table = tableAlloc(TableCap); @@ -64,49 +64,52 @@ void fileRead(struct File *file) { mbstate_t state = StateInit; while (!feof(stream)) { size_t mbsLen = fread(buf, 1, sizeof(buf), stream); - if (ferror(stream)) err(EX_IOERR, "%s", file->path); + if (ferror(stream)) return Errno + errno; + // FIXME: Handle null bytes specially. const char *mbs = buf; - wchar_t *wcs = bufferDest(&file->buf, mbsLen); + wchar_t *wcs = bufferDest(&file->edit.buf, mbsLen); size_t wcsLen = mbsnrtowcs(wcs, &mbs, mbsLen, mbsLen, &state); - if (wcsLen == (size_t)-1) err(EX_DATAERR, "%s", file->path); + if (wcsLen == (size_t)-1) return Errno + errno; - bufferTruncate(&file->buf, wcsLen); - tablePush(&table, file->buf.slice); + bufferTruncate(&file->edit.buf, wcsLen); + tablePush(&table, file->edit.buf.slice); } - logPush(&file->log, table); - file->clean = file->log.state; + logPush(&file->edit.log, table); + file->clean = file->edit.log.state; fclose(stream); + return Ok; } -// TODO: Error handling. -void fileWrite(struct File *file) { - if (!file->path) return; +enum Error fileWrite(struct File *file) { + if (!file->path) return FileNoPath; FILE *stream = fopen(file->path, "w"); - if (!stream) err(EX_CANTCREAT, "%s", file->path); + if (!stream) return Errno + errno; - const struct Table *table = logTable(&file->log); - if (!table) errx(EX_SOFTWARE, "fileWrite: no table"); + const struct Table *table = logTable(&file->edit.log); + assert(table); char buf[BufferCap]; mbstate_t state = StateInit; for (size_t i = 0; i < table->len; ++i) { struct Slice slice = table->slices[i]; while (slice.len) { + // FIXME: Handle null bytes specially. size_t mbsLen = wcsnrtombs( buf, &slice.ptr, slice.len, sizeof(buf), &state ); - if (mbsLen == (size_t)-1) err(EX_DATAERR, "%s", file->path); + if (mbsLen == (size_t)-1) return Errno + errno; + // FIXME: This only works once. slice.len -= slice.ptr - table->slices[i].ptr; fwrite(buf, 1, mbsLen, stream); - if (ferror(stream)) err(EX_IOERR, "%s", file->path); + if (ferror(stream)) return Errno + errno; } } - file->clean = file->log.state; + file->clean = file->edit.log.state; fclose(stream); - if (ferror(stream)) err(EX_IOERR, "%s", file->path); + return (ferror(stream) ? Errno + errno : Ok); } diff --git a/bin/edi/log.c b/bin/edi/log.c index 267833ec..253554fd 100644 --- a/bin/edi/log.c +++ b/bin/edi/log.c @@ -25,12 +25,7 @@ struct Log logAlloc(size_t cap) { struct State *states = malloc(sizeof(*states) * cap); if (!states) err(EX_OSERR, "malloc"); - return (struct Log) { - .cap = cap, - .len = 0, - .state = 0, - .states = states, - }; + return (struct Log) { .cap = cap, .states = states }; } void logFree(struct Log *log) { @@ -47,11 +42,9 @@ void logPush(struct Log *log, struct Table table) { if (!log->states) err(EX_OSERR, "realloc"); } size_t next = log->len++; - log->states[next] = (struct State) { - .table = table, - .prev = log->state, - .next = next, - }; + log->states[next].table = table; + log->states[next].prev = log->state; + log->states[next].next = next; log->states[log->state].next = next; log->state = next; } |