106 More features for convenient use of the buffer can be enabled, like automatic |
106 More features for convenient use of the buffer can be enabled, like automatic |
107 memory management and automatic resizing of the buffer space. |
107 memory management and automatic resizing of the buffer space. |
108 See the documentation of the macro constants in the header file for more |
108 See the documentation of the macro constants in the header file for more |
109 information. |
109 information. |
110 |
110 |
|
111 ### Add line numbers to a file |
|
112 |
|
113 When reading a file line by line, you have three options: first, you could limit |
|
114 the maximum supported line length. |
|
115 Second, you allocate a god buffer large |
|
116 enough for the most lines a text file could have. |
|
117 And third, undoubtedly the best option, you start with a small buffer, which |
|
118 adjusts on demand. |
|
119 An `UcxBuffer` can be created to do just that for you. |
|
120 Just pass the `UCX_BUFFER_AUTOEXTEND` option to the initialization function. |
|
121 Here is a full working program, which adds line numbers to a file. |
|
122 ```C |
|
123 #include <stdio.h> |
|
124 #include <ucx/buffer.h> |
|
125 #include <ucx/utils.h> |
|
126 |
|
127 int main(int argc, char** argv) { |
|
128 |
|
129 if (argc != 2) { |
|
130 fprintf(stderr, "Usage: %s <file>\n", argv[0]); |
|
131 return 1; |
|
132 } |
|
133 |
|
134 FILE* input = fopen(argv[1], "r"); |
|
135 if (!input) { |
|
136 perror("Canno read input"); |
|
137 return 1; |
|
138 } |
|
139 |
|
140 const size_t chunksize = 256; |
|
141 |
|
142 UcxBuffer* linebuf = |
|
143 ucx_buffer_new( |
|
144 NULL, // the buffer should manage the memory area for us |
|
145 chunksize, // initial buffer size should be the chunk size |
|
146 UCX_BUFFER_AUTOEXTEND); // the buffer will grow when necessary |
|
147 |
|
148 size_t lineno = 1; |
|
149 do { |
|
150 // read line chunk |
|
151 size_t read = ucx_stream_ncopy( |
|
152 input, linebuf, fread, ucx_buffer_write, chunksize); |
|
153 if (read == 0) break; |
|
154 |
|
155 // handle line endings |
|
156 do { |
|
157 sstr_t bufstr = ucx_buffer_to_sstr(linebuf); |
|
158 sstr_t nl = sstrchr(bufstr, '\n'); |
|
159 if (nl.length == 0) break; |
|
160 |
|
161 size_t linelen = bufstr.length - nl.length; |
|
162 sstr_t linestr = sstrsubsl(bufstr, 0, linelen); |
|
163 |
|
164 printf("%zu: %" PRIsstr "\n", lineno++, SFMT(linestr)); |
|
165 |
|
166 // shift the buffer to the next line |
|
167 ucx_buffer_shift_left(linebuf, linelen+1); |
|
168 } while(1); |
|
169 |
|
170 } while(1); |
|
171 |
|
172 // print the 'noeol' line, if any |
|
173 sstr_t lastline = ucx_buffer_to_sstr(linebuf); |
|
174 if (lastline.length > 0) { |
|
175 printf("%zu: %" PRIsstr, lineno, SFMT(lastline)); |
|
176 } |
|
177 |
|
178 fclose(input); |
|
179 ucx_buffer_free(linebuf); |
|
180 |
|
181 return 0; |
|
182 } |
|
183 ``` |
|
184 |
111 ## List |
185 ## List |
112 |
186 |
113 *Header file:* [list.h](api/list_8h.html) |
187 *Header file:* [list.h](api/list_8h.html) |
114 *Required modules:* [Allocator](#allocator) |
188 *Required modules:* [Allocator](#allocator) |
115 |
189 |