Browse Source

Return enum Error from file functions in edi

June 2 weeks ago
parent
commit
065792b3b0
Signed by: Curtis McEnroe <june@causal.agency> GPG Key ID: CEA2F97ADCFCD77C
4 changed files with 58 additions and 64 deletions
  1. 16
    18
      bin/edi/edi.c
  2. 4
    4
      bin/edi/edi.h
  3. 34
    31
      bin/edi/file.c
  4. 4
    11
      bin/edi/log.c

+ 16
- 18
bin/edi/edi.c View File

@@ -23,24 +23,27 @@
23 23
 
24 24
 #include "edi.h"
25 25
 
26
+static void errorExit(enum Error error, const char *prefix) {
27
+	if (error > Errno) errc(EX_IOERR, error - Errno, "%s", prefix);
28
+	else errx(EX_DATAERR, "%s: %d", prefix, error);
29
+}
30
+
26 31
 int main(int argc, char *argv[]) {
27 32
 	setlocale(LC_CTYPE, "");
28 33
 
29 34
 	if (argc < 2) return EX_USAGE;
30 35
 
36
+	enum Error error;
37
+
31 38
 	struct File file = fileAlloc(strdup(argv[1]));
32
-	fileRead(&file);
33
-	
34
-	struct Edit edit = { file.buf, file.log };
39
+	error = fileRead(&file);
40
+	if (error) errorExit(error, file.path);
35 41
 
36 42
 	FILE *store = fopen("store.edi", "w");
37 43
 	if (!store) err(EX_CANTCREAT, "store.edi");
38 44
 
39
-	enum Error error = storeWrite(store, &edit);
40
-	if (error) {
41
-		if (error > Errno) errc(EX_IOERR, error - Errno, "store.edi");
42
-		else errx(EX_IOERR, "store.edi: %d", error);
43
-	}
45
+	error = storeWrite(store, &file.edit);
46
+	if (error) errorExit(error, "store.edi");
44 47
 
45 48
 	fclose(store);
46 49
 	if (ferror(store)) err(EX_IOERR, "store.edi");
@@ -48,21 +51,16 @@ int main(int argc, char *argv[]) {
48 51
 	store = fopen("store.edi", "r");
49 52
 	if (!store) err(EX_CANTCREAT, "store.edi");
50 53
 
51
-	error = storeRead(store, &edit);
52
-	if (error) {
53
-		if (error > Errno) errc(EX_IOERR, error - Errno, "store.edi");
54
-		else errx(EX_DATAERR, "store.edi: %d", error);
55
-	}
56
-
57
-	file.buf = edit.buf;
58
-	file.log = edit.log;
54
+	error = storeRead(store, &file.edit);
55
+	if (error) errorExit(error, "store.edi");
59 56
 
60
-	const struct Table *table = logTable(&file.log);
57
+	const struct Table *table = logTable(&file.edit.log);
61 58
 	for (struct Iter it = iter(table, 0); it.ch != WEOF; it = iterNext(it)) {
62 59
 		printf("%lc", it.ch);
63 60
 	}
64 61
 
65
-	fileWrite(&file);
62
+	error = fileWrite(&file);
63
+	if (error) errorExit(error, file.path);
66 64
 
67 65
 	fileFree(&file);
68 66
 }

+ 4
- 4
bin/edi/edi.h View File

@@ -98,6 +98,7 @@ enum Error {
98 98
 	StoreMagic,
99 99
 	StoreVersion,
100 100
 	StoreEOF,
101
+	FileNoPath,
101 102
 	Errno,
102 103
 };
103 104
 
@@ -106,11 +107,10 @@ enum Error storeRead(FILE *stream, struct Edit *edit);
106 107
 
107 108
 struct File {
108 109
 	char *path;
109
-	struct Buffer buf;
110
-	struct Log log;
111 110
 	size_t clean;
111
+	struct Edit edit;
112 112
 };
113 113
 struct File fileAlloc(char *path);
114 114
 void fileFree(struct File *file);
115
-void fileRead(struct File *file);
116
-void fileWrite(struct File *file);
115
+enum Error fileRead(struct File *file);
116
+enum Error fileWrite(struct File *file);

+ 34
- 31
bin/edi/file.c View File

@@ -14,11 +14,10 @@
14 14
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 15
  */
16 16
 
17
-#include <err.h>
17
+#include <assert.h>
18 18
 #include <errno.h>
19 19
 #include <stdio.h>
20 20
 #include <stdlib.h>
21
-#include <sysexits.h>
22 21
 #include <wchar.h>
23 22
 
24 23
 #include "edi.h"
@@ -32,31 +31,32 @@ enum {
32 31
 struct File fileAlloc(char *path) {
33 32
 	struct File file = {
34 33
 		.path = path,
35
-		.buf = bufferAlloc(BufferCap),
36
-		.log = logAlloc(LogCap),
34
+		.edit = {
35
+			.buf = bufferAlloc(BufferCap),
36
+			.log = logAlloc(LogCap),
37
+		},
37 38
 	};
38
-	if (!path) logPush(&file.log, TableEmpty);
39
+	if (!path) logPush(&file.edit.log, TableEmpty);
39 40
 	return file;
40 41
 }
41 42
 
42 43
 void fileFree(struct File *file) {
43
-	logFree(&file->log);
44
-	bufferFree(&file->buf);
44
+	logFree(&file->edit.log);
45
+	bufferFree(&file->edit.buf);
45 46
 	free(file->path);
46 47
 }
47 48
 
48 49
 static const mbstate_t StateInit;
49 50
 
50
-// TODO: Error handling.
51
-void fileRead(struct File *file) {
52
-	if (!file->path) return;
51
+enum Error fileRead(struct File *file) {
52
+	if (!file->path) return FileNoPath;
53 53
 
54 54
 	FILE *stream = fopen(file->path, "r");
55 55
 	if (!stream) {
56
-		if (errno != ENOENT) err(EX_NOINPUT, "%s", file->path);
57
-		logPush(&file->log, TableEmpty);
58
-		file->clean = file->log.state;
59
-		return;
56
+		if (errno != ENOENT) return Errno + errno;
57
+		logPush(&file->edit.log, TableEmpty);
58
+		file->clean = file->edit.log.state;
59
+		return Ok;
60 60
 	}
61 61
 
62 62
 	struct Table table = tableAlloc(TableCap);
@@ -64,49 +64,52 @@ void fileRead(struct File *file) {
64 64
 	mbstate_t state = StateInit;
65 65
 	while (!feof(stream)) {
66 66
 		size_t mbsLen = fread(buf, 1, sizeof(buf), stream);
67
-		if (ferror(stream)) err(EX_IOERR, "%s", file->path);
67
+		if (ferror(stream)) return Errno + errno;
68 68
 
69
+		// FIXME: Handle null bytes specially.
69 70
 		const char *mbs = buf;
70
-		wchar_t *wcs = bufferDest(&file->buf, mbsLen);
71
+		wchar_t *wcs = bufferDest(&file->edit.buf, mbsLen);
71 72
 		size_t wcsLen = mbsnrtowcs(wcs, &mbs, mbsLen, mbsLen, &state);
72
-		if (wcsLen == (size_t)-1) err(EX_DATAERR, "%s", file->path);
73
+		if (wcsLen == (size_t)-1) return Errno + errno;
73 74
 
74
-		bufferTruncate(&file->buf, wcsLen);
75
-		tablePush(&table, file->buf.slice);
75
+		bufferTruncate(&file->edit.buf, wcsLen);
76
+		tablePush(&table, file->edit.buf.slice);
76 77
 	}
77
-	logPush(&file->log, table);
78
-	file->clean = file->log.state;
78
+	logPush(&file->edit.log, table);
79
+	file->clean = file->edit.log.state;
79 80
 
80 81
 	fclose(stream);
82
+	return Ok;
81 83
 }
82 84
 
83
-// TODO: Error handling.
84
-void fileWrite(struct File *file) {
85
-	if (!file->path) return;
85
+enum Error fileWrite(struct File *file) {
86
+	if (!file->path) return FileNoPath;
86 87
 
87 88
 	FILE *stream = fopen(file->path, "w");
88
-	if (!stream) err(EX_CANTCREAT, "%s", file->path);
89
+	if (!stream) return Errno + errno;
89 90
 
90
-	const struct Table *table = logTable(&file->log);
91
-	if (!table) errx(EX_SOFTWARE, "fileWrite: no table");
91
+	const struct Table *table = logTable(&file->edit.log);
92
+	assert(table);
92 93
 
93 94
 	char buf[BufferCap];
94 95
 	mbstate_t state = StateInit;
95 96
 	for (size_t i = 0; i < table->len; ++i) {
96 97
 		struct Slice slice = table->slices[i];
97 98
 		while (slice.len) {
99
+			// FIXME: Handle null bytes specially.
98 100
 			size_t mbsLen = wcsnrtombs(
99 101
 				buf, &slice.ptr, slice.len, sizeof(buf), &state
100 102
 			);
101
-			if (mbsLen == (size_t)-1) err(EX_DATAERR, "%s", file->path);
103
+			if (mbsLen == (size_t)-1) return Errno + errno;
104
+			// FIXME: This only works once.
102 105
 			slice.len -= slice.ptr - table->slices[i].ptr;
103 106
 
104 107
 			fwrite(buf, 1, mbsLen, stream);
105
-			if (ferror(stream)) err(EX_IOERR, "%s", file->path);
108
+			if (ferror(stream)) return Errno + errno;
106 109
 		}
107 110
 	}
108
-	file->clean = file->log.state;
111
+	file->clean = file->edit.log.state;
109 112
 
110 113
 	fclose(stream);
111
-	if (ferror(stream)) err(EX_IOERR, "%s", file->path);
114
+	return (ferror(stream) ? Errno + errno : Ok);
112 115
 }

+ 4
- 11
bin/edi/log.c View File

@@ -25,12 +25,7 @@
25 25
 struct Log logAlloc(size_t cap) {
26 26
 	struct State *states = malloc(sizeof(*states) * cap);
27 27
 	if (!states) err(EX_OSERR, "malloc");
28
-	return (struct Log) {
29
-		.cap = cap,
30
-		.len = 0,
31
-		.state = 0,
32
-		.states = states,
33
-	};
28
+	return (struct Log) { .cap = cap, .states = states };
34 29
 }
35 30
 
36 31
 void logFree(struct Log *log) {
@@ -47,11 +42,9 @@ void logPush(struct Log *log, struct Table table) {
47 42
 		if (!log->states) err(EX_OSERR, "realloc");
48 43
 	}
49 44
 	size_t next = log->len++;
50
-	log->states[next] = (struct State) {
51
-		.table = table,
52
-		.prev = log->state,
53
-		.next = next,
54
-	};
45
+	log->states[next].table = table;
46
+	log->states[next].prev = log->state;
47
+	log->states[next].next = next;
55 48
 	log->states[log->state].next = next;
56 49
 	log->state = next;
57 50
 }

Loading…
Cancel
Save