]> git.lizzy.rs Git - nothing.git/blob - src/system/line_stream.c
(#612) Remove lt_adapters
[nothing.git] / src / system / line_stream.c
1 #include "system/stacktrace.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <stdbool.h>
7
8 #include "line_stream.h"
9 #include "lt.h"
10 #include "system/nth_alloc.h"
11 #include "system/log.h"
12
13 struct LineStream
14 {
15     Lt *lt;
16     FILE *stream;
17     char *buffer;
18     size_t capacity;
19     bool unfinished;
20 };
21
22 static void fclose_lt(void* file)
23 {
24     fclose(file);
25 }
26
27 LineStream *create_line_stream(const char *filename,
28                                const char *mode,
29                                size_t capacity)
30 {
31     trace_assert(filename);
32     trace_assert(mode);
33
34     Lt *lt = create_lt();
35
36     LineStream *line_stream = PUSH_LT(
37         lt,
38         nth_calloc(1, sizeof(LineStream)),
39         free);
40     if (line_stream == NULL) {
41         RETURN_LT(lt, NULL);
42     }
43     line_stream->lt = lt;
44
45     line_stream->stream = PUSH_LT(
46         lt,
47         fopen(filename, mode),
48         fclose_lt);
49     if (line_stream->stream == NULL) {
50         log_fail("Could not open file '%s': %s\n", filename, strerror(errno));
51         RETURN_LT(lt, NULL);
52     }
53
54     line_stream->buffer = PUSH_LT(
55         lt,
56         nth_calloc(1, sizeof(char) * capacity),
57         free);
58     if (line_stream->buffer == NULL) {
59         RETURN_LT(lt, NULL);
60     }
61
62     line_stream->capacity = capacity;
63     line_stream->unfinished = false;
64
65     return line_stream;
66 }
67
68 void destroy_line_stream(LineStream *line_stream)
69 {
70     trace_assert(line_stream);
71
72     RETURN_LT0(line_stream->lt);
73 }
74
75
76 const char *line_stream_next_chunk(LineStream *line_stream)
77 {
78     trace_assert(line_stream);
79
80     const char *s = fgets(line_stream->buffer,
81                           (int) line_stream->capacity,
82                           line_stream->stream);
83     if (s == NULL) {
84         return NULL;
85     }
86     size_t n = strlen(s);
87     line_stream->unfinished = s[n - 1] != '\n';
88
89     return s;
90 }
91
92 const char *line_stream_next(LineStream *line_stream)
93 {
94     trace_assert(line_stream);
95
96     while (line_stream->unfinished) {
97         line_stream_next_chunk(line_stream);
98     }
99
100     return line_stream_next_chunk(line_stream);
101 }