1 /*
2 Copyright (C) 2015-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4stt.ctr
12 */
13
14 /** @file dk4stt.c The dk4stt module.
15 */
16
17
18 #include "dk4conf.h"
19 #include <libdk4base/dk4error.h>
20 #include <libdk4base/dk4mem.h>
21 #include <libdk4base/dk4strd.h>
22 #include <libdk4c/dk4strm.h>
23 #include <libdk4c/dk4stt.h>
24 #include <libdk4c/dk4tspdk.h>
25 #include <libdk4c/dk4enc.h>
26 #include <libdk4base/dk4unused.h>
27
28 #if DK4_HAVE_ASSERT_H
29 #ifndef ASSERT_H_INCLUDED
30 #include <assert.h>
31 #define ASSERT_H_INCLUDED 1
32 #endif
33 #endif
34
35
36
37
38
39
40 void
dk4stt_close(dk4_string_table_t * ptr)41 dk4stt_close(dk4_string_table_t *ptr)
42 {
43 dkChar **stptr;
44 size_t nstrings;
45
46 #if DK4_USE_ASSERT
47 assert(NULL != ptr);
48 #endif
49 if (NULL != ptr) {
50 if (NULL != ptr->strings) {
51 stptr = ptr->strings;
52 nstrings = ptr->nstrings;
53 while (0 < nstrings--) {
54 dk4mem_release(*stptr);
55 stptr++;
56 }
57 dk4mem_release(ptr->strings);
58 }
59 dk4mem_release(ptr->shrtfn);
60 ptr->nstrings = 0;
61 dk4mem_free(ptr);
62 }
63 }
64
65
66
67 dk4_string_table_t *
dk4stt_open(const dkChar * fn,size_t sz,dk4_er_t * erp)68 dk4stt_open(const dkChar *fn, size_t sz, dk4_er_t *erp)
69 {
70 dk4_string_table_t *back = NULL;
71 dkChar **stptr = NULL;
72 int ok = 0;
73
74 #if DK4_USE_ASSERT
75 assert(NULL != fn);
76 assert(0 < sz);
77 #endif
78 if ((NULL != fn) && (0 < sz)) {
79 back = dk4mem_new(dk4_string_table_t,1,erp);
80 if (NULL != back) {
81 back->strings = NULL;
82 back->nstrings = 0;
83 back->shrtfn = dk4str_dup(fn, erp);
84 if (NULL != back->shrtfn) {
85 back->nstrings = sz;
86 back->strings = dk4mem_new(DK4_PDKCHAR,sz,erp);
87 if (NULL != back->strings) {
88 stptr = back->strings;
89 while (0 < sz--) { *(stptr++) = NULL; }
90 ok = 1;
91 }
92 }
93 if (1 > ok) {
94 dk4stt_close(back);
95 back = NULL;
96 }
97 }
98 } else {
99 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
100 }
101 return back;
102 }
103
104
105
106 int
dk4stt_compare(const void * l,const void * r,int cr)107 dk4stt_compare(const void *l, const void *r, int cr)
108 {
109 int back = 0;
110 const dk4_string_table_t *pl;
111 const dk4_string_table_t *pr;
112
113 if (NULL != l) {
114 if (NULL != r) {
115 pl = (const dk4_string_table_t *)l;
116 switch (cr) {
117 case 1: {
118 if (NULL != pl->shrtfn) {
119 back = dk4str_cmp(pl->shrtfn, (const dkChar *)r);
120 } else {
121 back = -1;
122 }
123 } break;
124 default: {
125 pr = (const dk4_string_table_t *)r;
126 if (NULL != pl->shrtfn) {
127 if (NULL != pr->shrtfn) {
128 back = dk4str_cmp(pl->shrtfn, pr->shrtfn);
129 } else {
130 back = 1;
131 }
132 } else {
133 if (NULL != pr->shrtfn) {
134 back = -1;
135 }
136 }
137 } break;
138 }
139 } else {
140 back = 1;
141 }
142 } else {
143 if (NULL != r) {
144 back = -1;
145 }
146 }
147 return back;
148 }
149
150
151
152 /** Structure to read a string table from stream.
153 */
154 typedef struct {
155 dk4_string_table_t *dptr; /**< String table to configure. */
156 size_t curpos; /**< Current line number. */
157 } dk4_string_table_reader_t;
158
159
160
161 /** Handler function for text lines.
162 @param obj Object to modify while processing the character.
163 @param line Text line to process.
164 @param lineno Current line number.
165 @param erp Error report, may be NULL.
166 @return DK4_TSP_RES_OK if the character was processed
167 successfully,
168 DK4_TSP_RES_ERROR if there was an error but we can
169 continue,
170 DK4_TSP_RES_FATAL if there was a fatal error so we
171 should abort processing.
172 */
173 static
174 int
dk4stt_line_handler(void * obj,dkChar * line,dk4_um_t DK4_ARG_UNUSED (lineno),dk4_er_t * DK4_ARG_UNUSED (erp))175 dk4stt_line_handler(
176 void *obj,
177 dkChar *line,
178 dk4_um_t DK4_ARG_UNUSED(lineno),
179 dk4_er_t * DK4_ARG_UNUSED(erp)
180 )
181 {
182 dk4_string_table_reader_t *reader; /* Reader structure */
183 #if TRACE_DEBUG
184 dkChar *olcp; /* Original pointer */
185 #endif
186 dkChar *linecp; /* Copy of line */
187 int back = DK4_TSP_RES_ERROR;
188
189 DK4_UNUSED_ARG(lineno)
190 DK4_UNUSED_ARG(erp)
191 reader = (dk4_string_table_reader_t *)obj;
192 if (dkT('#') != line[0]) {
193 if (reader->curpos < reader->dptr->nstrings) {
194 linecp = dk4str_dup(line, NULL);
195 if (NULL != linecp) {
196 #if TRACE_DEBUG
197 olcp = linecp;
198 #endif
199 /* Save copy of line to string table */
200 (reader->dptr->strings)[reader->curpos] = linecp;
201 reader->curpos += 1;
202 back = DK4_TSP_RES_OK;
203 /* Handle backslash escape sequences, remove trailing newline */
204 while (dkT('\0') != *linecp) {
205 if (dkT('\\') == *linecp) {
206 if (dkT('r') == linecp[1]) {
207 *linecp = dkT('\r');
208 dk4str_cpy_to_left(&(linecp[1]), &(linecp[2]));
209 } else {
210 if (dkT('n') == linecp[1]) {
211 *linecp = dkT('\n');
212 dk4str_cpy_to_left(&(linecp[1]), &(linecp[2]));
213 } else {
214 if (dkT('t') == linecp[1]) {
215 *linecp = dkT('\t');
216 dk4str_cpy_to_left(&(linecp[1]), &(linecp[2]));
217 } else {
218 dk4str_cpy_to_left(linecp, &(linecp[1]));
219 if (dkT('\0') == *linecp) { linecp--; }
220 }
221 }
222 }
223 } else {
224 if (dkT('\n') == *linecp) {
225 *linecp = dkT('\0');
226 linecp--;
227 } else {
228 if ((dkT('\r') == *linecp) && (dkT('\n') == linecp[1])) {
229 *linecp = dkT('\0');
230 linecp--;
231 }
232 }
233 }
234 linecp++;
235 }
236 } else {
237 /* Not enough memory. */
238 back = DK4_TSP_RES_FATAL;
239 }
240 } else {
241 /* More lines than expected, ignore additional lines. */
242 back = DK4_TSP_RES_OK;
243 }
244 } else {
245 /* Comment line, no processing required. */
246 back = DK4_TSP_RES_OK;
247 }
248 return back;
249 }
250
251
252
253 int
dk4stt_apply_stream(dk4_string_table_t * tptr,dk4_stream_t * strm,int pre,dk4_er_t * erp2)254 dk4stt_apply_stream(
255 dk4_string_table_t *tptr,
256 dk4_stream_t *strm,
257 int pre,
258 dk4_er_t *erp2
259 )
260 {
261 dkChar line[1024]; /* Input line buffer */
262 char buf[4096]; /* Buffer for stream input */
263 dk4_string_table_reader_t reader; /* Reader structure */
264 dk4_tspdk_t tspdk; /* Text stream processor */
265 dk4_er_t e1; /* Error report f decoding */
266 dk4_er_t e2; /* Error report f processing */
267 size_t rdb; /* Bytes read */
268 int cc; /* Flag: Can continue */
269 int back = 0;
270
271 #if DK4_USE_ASSERT
272 assert(NULL != tptr);
273 assert(NULL != strm);
274 #endif
275 if ((NULL != tptr) && (NULL != strm)) {
276 dk4error_init(&e1);
277 dk4error_init(&e2);
278 reader.dptr = tptr;
279 reader.curpos = 0;
280 back = dk4tspdk_setup_line(
281 &tspdk, (void *)(&reader), dk4stt_line_handler,
282 line, DK4_SIZEOF(line,dkChar),
283 pre, DK4_FILE_ENCODING_UTF8, &e2
284 );
285 if (0 < back) {
286 #if VERSION_BEFORE_20150821
287 cc = 1;
288 #endif
289 do {
290 cc = 0;
291 rdb = sizeof(buf);
292 if (0 < dk4stream_read(buf, &rdb, strm, NULL)) {
293 if (0 < rdb) {
294 switch (dk4tspdk_add_bytes(&tspdk, (unsigned char *)buf, rdb)) {
295 case DK4_TSP_RES_OK: {
296 cc = 1;
297 } break;
298 case DK4_TSP_RES_ERROR: {
299 cc = 1;
300 } break;
301 default: {
302 back = 0;
303 } break;
304 }
305 } else {
306 }
307 } else {
308 }
309 } while (cc);
310 if (0 < back) {
311 if (DK4_TSP_RES_FATAL == dk4tspdk_finish(&tspdk)) {
312 back = 0;
313 }
314 if (0 < back) {
315 if (reader.curpos < (reader.dptr)->nstrings) {
316 back = 0;
317
318
319 }
320 }
321 }
322 } else {
323 }
324 } else {
325 dk4error_set_simple_error_code(erp2, DK4_E_INVALID_ARGUMENTS);
326 }
327 return back;
328 }
329
330
331