Line data Source code
1 : /* File: io_xml_writer.c; Copyright and License: see below */
2 :
3 : #include "format/io_xml_writer.h"
4 : #include "entity/data_id.h"
5 : #include "u8/u8_trace.h"
6 : #include "u8/u8_log.h"
7 : #include <stdio.h>
8 : #include <stdbool.h>
9 : #include <assert.h>
10 :
11 : const char IO_XML_WRITER_START_TAG_START[2] = "<";
12 : const char IO_XML_WRITER_START_TAG_END[2] = ">";
13 : const char IO_XML_WRITER_END_TAG_START[3] = "</";
14 : const char IO_XML_WRITER_END_TAG_END[2] = ">";
15 : const char IO_XML_WRITER_EMPTY_TAG_START[2] = "<";
16 : const char IO_XML_WRITER_EMPTY_TAG_END[3] = "/>";
17 : const char IO_XML_WRITER_ATTR_SEPARATOR[2] = " ";
18 : const char IO_XML_WRITER_ATTR_VALUE_START[3] = "=\"";
19 : const char IO_XML_WRITER_ATTR_VALUE_END[2] = "\"";
20 : const char IO_XML_WRITER_COMMENT_START[5] = "<!--";
21 : const char IO_XML_WRITER_COMMENT_END[4] = "-->";
22 : const char IO_XML_WRITER_NL[2] = "\n";
23 : #define IO_XML_WRITER_PRIVATE_MAX_INDENT_LEVELS (12)
24 :
25 : static const char *const IO_XML_WRITER_PRIVATE_ENCODE_XML_STRINGS[IO_XML_WRITER_PRIVATE_MAX_INDENT_LEVELS][6][2] = {
26 : {
27 : { "<", "<" },
28 : { ">", ">" },
29 : { "\"", """ },
30 : { "&", "&" },
31 : { "\n", "\n" }, /* indentation level */
32 : { NULL, NULL } /* end translation table */
33 : },
34 : {
35 : { "<", "<" },
36 : { ">", ">" },
37 : { "\"", """ },
38 : { "&", "&" },
39 : { "\n", "\n " }, /* indentation level */
40 : { NULL, NULL } /* end translation table */
41 : },
42 : {
43 : { "<", "<" },
44 : { ">", ">" },
45 : { "\"", """ },
46 : { "&", "&" },
47 : { "\n", "\n " }, /* indentation level */
48 : { NULL, NULL } /* end translation table */
49 : },
50 : {
51 : { "<", "<" },
52 : { ">", ">" },
53 : { "\"", """ },
54 : { "&", "&" },
55 : { "\n", "\n " }, /* indentation level */
56 : { NULL, NULL } /* end translation table */
57 : },
58 : {
59 : { "<", "<" },
60 : { ">", ">" },
61 : { "\"", """ },
62 : { "&", "&" },
63 : { "\n", "\n " }, /* indentation level */
64 : { NULL, NULL } /* end translation table */
65 : },
66 : {
67 : { "<", "<" },
68 : { ">", ">" },
69 : { "\"", """ },
70 : { "&", "&" },
71 : { "\n", "\n " }, /* indentation level */
72 : { NULL, NULL } /* end translation table */
73 : },
74 : {
75 : { "<", "<" },
76 : { ">", ">" },
77 : { "\"", """ },
78 : { "&", "&" },
79 : { "\n", "\n " }, /* indentation level */
80 : { NULL, NULL } /* end translation table */
81 : },
82 : {
83 : { "<", "<" },
84 : { ">", ">" },
85 : { "\"", """ },
86 : { "&", "&" },
87 : { "\n", "\n " }, /* indentation level */
88 : { NULL, NULL } /* end translation table */
89 : },
90 : {
91 : { "<", "<" },
92 : { ">", ">" },
93 : { "\"", """ },
94 : { "&", "&" },
95 : { "\n", "\n " }, /* indentation level */
96 : { NULL, NULL } /* end translation table */
97 : },
98 : {
99 : { "<", "<" },
100 : { ">", ">" },
101 : { "\"", """ },
102 : { "&", "&" },
103 : { "\n", "\n " }, /* indentation level */
104 : { NULL, NULL } /* end translation table */
105 : },
106 : {
107 : { "<", "<" },
108 : { ">", ">" },
109 : { "\"", """ },
110 : { "&", "&" },
111 : { "\n", "\n " }, /* indentation level */
112 : { NULL, NULL } /* end translation table */
113 : },
114 : {
115 : { "<", "<" },
116 : { ">", ">" },
117 : { "\"", """ },
118 : { "&", "&" },
119 : { "\n", "\n " }, /* indentation level */
120 : { NULL, NULL } /* end translation table */
121 : }
122 : };
123 :
124 : static const char *const IO_XML_WRITER_PRIVATE_ENCODE_XML_COMMENTS[IO_XML_WRITER_PRIVATE_MAX_INDENT_LEVELS][8][2] = {
125 : {
126 : { "\n", "\n" },
127 : { "<", "<" },
128 : { ">", ">" },
129 : { "\"", """ },
130 : { "&", "&" },
131 : { "-", " - " },
132 : { "\n", "\n" }, /* indentation level */
133 : { NULL, NULL } /* end translation table */
134 : },
135 : {
136 : { "\n", "\n" },
137 : { "<", "<" },
138 : { ">", ">" },
139 : { "\"", """ },
140 : { "&", "&" },
141 : { "-", " - " },
142 : { "\n", "\n " }, /* indentation level */
143 : { NULL, NULL } /* end translation table */
144 : },
145 : {
146 : { "\n", "\n" },
147 : { "<", "<" },
148 : { ">", ">" },
149 : { "\"", """ },
150 : { "&", "&" },
151 : { "-", " - " },
152 : { "\n", "\n " }, /* indentation level */
153 : { NULL, NULL } /* end translation table */
154 : },
155 : {
156 : { "\n", "\n" },
157 : { "<", "<" },
158 : { ">", ">" },
159 : { "\"", """ },
160 : { "&", "&" },
161 : { "-", " - " },
162 : { "\n", "\n " }, /* indentation level */
163 : { NULL, NULL } /* end translation table */
164 : },
165 : {
166 : { "\n", "\n" },
167 : { "<", "<" },
168 : { ">", ">" },
169 : { "\"", """ },
170 : { "&", "&" },
171 : { "-", " - " },
172 : { "\n", "\n " }, /* indentation level */
173 : { NULL, NULL } /* end translation table */
174 : },
175 : {
176 : { "\n", "\n" },
177 : { "<", "<" },
178 : { ">", ">" },
179 : { "\"", """ },
180 : { "&", "&" },
181 : { "-", " - " },
182 : { "\n", "\n " }, /* indentation level */
183 : { NULL, NULL } /* end translation table */
184 : },
185 : {
186 : { "\n", "\n" },
187 : { "<", "<" },
188 : { ">", ">" },
189 : { "\"", """ },
190 : { "&", "&" },
191 : { "-", " - " },
192 : { "\n", "\n " }, /* indentation level */
193 : { NULL, NULL } /* end translation table */
194 : },
195 : {
196 : { "\n", "\n" },
197 : { "<", "<" },
198 : { ">", ">" },
199 : { "\"", """ },
200 : { "&", "&" },
201 : { "-", " - " },
202 : { "\n", "\n " }, /* indentation level */
203 : { NULL, NULL } /* end translation table */
204 : },
205 : {
206 : { "\n", "\n" },
207 : { "<", "<" },
208 : { ">", ">" },
209 : { "\"", """ },
210 : { "&", "&" },
211 : { "-", " - " },
212 : { "\n", "\n " }, /* indentation level */
213 : { NULL, NULL } /* end translation table */
214 : },
215 : {
216 : { "\n", "\n" },
217 : { "<", "<" },
218 : { ">", ">" },
219 : { "\"", """ },
220 : { "&", "&" },
221 : { "-", " - " },
222 : { "\n", "\n " }, /* indentation level */
223 : { NULL, NULL } /* end translation table */
224 : },
225 : {
226 : { "\n", "\n" },
227 : { "<", "<" },
228 : { ">", ">" },
229 : { "\"", """ },
230 : { "&", "&" },
231 : { "-", " - " },
232 : { "\n", "\n " }, /* indentation level */
233 : { NULL, NULL } /* end translation table */
234 : },
235 : {
236 : { "\n", "\n" },
237 : { "<", "<" },
238 : { ">", ">" },
239 : { "\"", """ },
240 : { "&", "&" },
241 : { "-", " - " },
242 : { "\n", "\n " }, /* indentation level */
243 : { NULL, NULL } /* end translation table */
244 : }
245 : };
246 :
247 : static const char *const IO_XML_WRITER_PRIVATE_INDENT_PLAIN[IO_XML_WRITER_PRIVATE_MAX_INDENT_LEVELS][2][2] = {
248 : {
249 : { "\n", "\n" }, /* indentation level */
250 : { NULL, NULL } /* end translation table */
251 : },
252 : {
253 : { "\n", "\n " }, /* indentation level */
254 : { NULL, NULL } /* end translation table */
255 : },
256 : {
257 : { "\n", "\n " }, /* indentation level */
258 : { NULL, NULL } /* end translation table */
259 : },
260 : {
261 : { "\n", "\n " }, /* indentation level */
262 : { NULL, NULL } /* end translation table */
263 : },
264 : {
265 : { "\n", "\n " }, /* indentation level */
266 : { NULL, NULL } /* end translation table */
267 : },
268 : {
269 : { "\n", "\n " }, /* indentation level */
270 : { NULL, NULL } /* end translation table */
271 : },
272 : {
273 : { "\n", "\n " }, /* indentation level */
274 : { NULL, NULL } /* end translation table */
275 : },
276 : {
277 : { "\n", "\n " }, /* indentation level */
278 : { NULL, NULL } /* end translation table */
279 : },
280 : {
281 : { "\n", "\n " }, /* indentation level */
282 : { NULL, NULL } /* end translation table */
283 : },
284 : {
285 : { "\n", "\n " }, /* indentation level */
286 : { NULL, NULL } /* end translation table */
287 : },
288 : {
289 : { "\n", "\n " }, /* indentation level */
290 : { NULL, NULL } /* end translation table */
291 : },
292 : {
293 : { "\n", "\n " }, /* indentation level */
294 : { NULL, NULL } /* end translation table */
295 : }
296 : };
297 :
298 3 : void io_xml_writer_init ( io_xml_writer_t *this_, universal_output_stream_t *output )
299 : {
300 3 : U8_TRACE_BEGIN();
301 3 : assert( NULL != output );
302 :
303 3 : (*this_).output = output;
304 3 : universal_escaping_output_stream_init( &((*this_).esc_output), &(IO_XML_WRITER_PRIVATE_ENCODE_XML_STRINGS[0]), output );
305 3 : (*this_).indent_level = 0;
306 :
307 3 : (*this_).xml_encode_table = &(IO_XML_WRITER_PRIVATE_ENCODE_XML_STRINGS[0]);
308 3 : (*this_).xml_comments_encode_table = &(IO_XML_WRITER_PRIVATE_ENCODE_XML_COMMENTS[0]);
309 3 : (*this_).xml_plain_table = &(IO_XML_WRITER_PRIVATE_INDENT_PLAIN[0]);
310 :
311 3 : U8_TRACE_END();
312 3 : }
313 :
314 3 : void io_xml_writer_destroy( io_xml_writer_t *this_ )
315 : {
316 3 : U8_TRACE_BEGIN();
317 :
318 3 : universal_escaping_output_stream_destroy( &((*this_).esc_output) );
319 3 : (*this_).output = NULL;
320 :
321 3 : U8_TRACE_END();
322 3 : }
323 :
324 0 : u8_error_t io_xml_writer_write_plain_id ( io_xml_writer_t *this_, data_id_t id )
325 : {
326 0 : U8_TRACE_BEGIN();
327 0 : assert( DATA_TABLE_VOID != data_id_get_table(&id) );
328 0 : assert( DATA_ROW_ID_VOID != data_id_get_row_id(&id) );
329 0 : u8_error_t result = U8_ERROR_NONE;
330 :
331 : /* print id */
332 : {
333 : char id_buf[DATA_ID_MAX_UTF8STRING_SIZE];
334 0 : utf8stringbuf_t id_str = UTF8STRINGBUF( id_buf );
335 0 : utf8stringbuf_clear( id_str );
336 0 : data_id_to_utf8stringbuf( &id, id_str );
337 :
338 0 : const unsigned int len = utf8stringbuf_get_length(id_str);
339 0 : universal_escaping_output_stream_change_rules( &((*this_).esc_output), (*this_).xml_plain_table );
340 0 : result = universal_escaping_output_stream_write( &((*this_).esc_output), utf8stringbuf_get_string(id_str), len );
341 : }
342 :
343 0 : U8_TRACE_END_ERR( result );
344 0 : return result;
345 : }
346 :
347 0 : u8_error_t io_xml_writer_write_int ( io_xml_writer_t *this_, int64_t number )
348 : {
349 0 : U8_TRACE_BEGIN();
350 : char numberStr[21]; /* this is sufficient for signed 64 bit integers: -9223372036854775806 */
351 0 : u8_error_t result = U8_ERROR_NONE;
352 :
353 : /* Note: snprintf is not available on every OS */
354 0 : sprintf( numberStr, "%" PRIi64, number );
355 0 : result = io_xml_writer_write_plain( this_, &(numberStr[0]) );
356 :
357 0 : U8_TRACE_END_ERR( result );
358 0 : return result;
359 : }
360 :
361 0 : void io_xml_writer_private_update_encoding_tables ( io_xml_writer_t *this_ )
362 : {
363 0 : U8_TRACE_BEGIN();
364 :
365 0 : const unsigned int level
366 0 : = ( (*this_).indent_level >= IO_XML_WRITER_PRIVATE_MAX_INDENT_LEVELS )
367 : ? ( IO_XML_WRITER_PRIVATE_MAX_INDENT_LEVELS - 1 )
368 : : ( (*this_).indent_level );
369 0 : (*this_).xml_encode_table = &(IO_XML_WRITER_PRIVATE_ENCODE_XML_STRINGS[level]);
370 0 : (*this_).xml_comments_encode_table = &(IO_XML_WRITER_PRIVATE_ENCODE_XML_COMMENTS[level]);
371 0 : (*this_).xml_plain_table = &(IO_XML_WRITER_PRIVATE_INDENT_PLAIN[level]);
372 :
373 0 : U8_TRACE_END();
374 0 : }
375 :
376 :
377 : /*
378 : Copyright 2017-2024 Andreas Warnke
379 :
380 : Licensed under the Apache License, Version 2.0 (the "License");
381 : you may not use this file except in compliance with the License.
382 : You may obtain a copy of the License at
383 :
384 : http://www.apache.org/licenses/LICENSE-2.0
385 :
386 : Unless required by applicable law or agreed to in writing, software
387 : distributed under the License is distributed on an "AS IS" BASIS,
388 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
389 : See the License for the specific language governing permissions and
390 : limitations under the License.
391 : */
|