Line data Source code
1 : /* File: json_writer.c; Copyright and License: see below */
2 :
3 : #include "json/json_writer.h"
4 : #include "entity/data_id.h"
5 : #include "utf8stringbuf/utf8stringlines.h"
6 : #include "u8/u8_trace.h"
7 : #include "u8/u8_log.h"
8 : #include <stdio.h>
9 : #include <stdbool.h>
10 : #include <assert.h>
11 :
12 : static const char * const JSON_WRITER_PRIVATE_ENCODE_JSON_STRINGS[][2] = {
13 : { "\x09", "\\t" }, /* tab */
14 : { "\x0a", "\\n" }, /* newline */
15 : { "\x0d", "\\r" }, /* return */
16 : { "\x08", "\\b" }, /* backspace */
17 : { "\x0c", "\\f" }, /* form feed */
18 : { "\"", "\\\"" }, /* double quote */
19 : { "\\", "\\\\" }, /* backslash*/
20 : { NULL, NULL } /* for JSON, see rfc7159 */
21 : };
22 :
23 : const char JSON_CONSTANTS_INDENT[(2*JSON_WRITER_MAX_INDENT)+sizeof("")]
24 : = JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB
25 : JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB;
26 :
27 : const char JSON_CONSTANTS_INDENT_QUOTE[(2*JSON_WRITER_MAX_INDENT)+sizeof(JSON_CONSTANTS_QUOTE)]
28 : = JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB
29 : JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_TAB JSON_CONSTANTS_QUOTE;
30 :
31 2 : void json_writer_init( json_writer_t *this_,
32 : universal_output_stream_t *output )
33 : {
34 2 : U8_TRACE_BEGIN();
35 2 : assert( NULL != output );
36 :
37 2 : (*this_).output = output;
38 2 : universal_escaping_output_stream_init( &((*this_).esc_output), &JSON_WRITER_PRIVATE_ENCODE_JSON_STRINGS, output );
39 :
40 2 : (*this_).json_string_encode_table = &JSON_WRITER_PRIVATE_ENCODE_JSON_STRINGS;
41 :
42 2 : U8_TRACE_END();
43 2 : }
44 :
45 2 : void json_writer_destroy( json_writer_t *this_ )
46 : {
47 2 : U8_TRACE_BEGIN();
48 :
49 2 : universal_escaping_output_stream_destroy( &((*this_).esc_output) );
50 2 : (*this_).output = NULL;
51 :
52 2 : U8_TRACE_END();
53 2 : }
54 :
55 0 : u8_error_t json_writer_write_plain_id ( json_writer_t *this_, data_id_t id )
56 : {
57 0 : U8_TRACE_BEGIN();
58 0 : assert( DATA_TABLE_VOID != data_id_get_table(&id) );
59 0 : assert( DATA_ROW_VOID != data_id_get_row_id(&id) );
60 0 : u8_error_t result = U8_ERROR_NONE;
61 :
62 : /* print id */
63 : {
64 : char id_buf[DATA_ID_MAX_UTF8STRING_SIZE];
65 0 : utf8stringbuf_t id_str = UTF8STRINGBUF( id_buf );
66 0 : utf8stringbuf_clear( &id_str );
67 0 : data_id_to_utf8stringbuf( &id, id_str );
68 :
69 0 : const unsigned int len = utf8stringbuf_get_length( &id_str );
70 0 : universal_escaping_output_stream_change_rules( &((*this_).esc_output), (*this_).json_string_encode_table );
71 0 : result = universal_escaping_output_stream_write( &((*this_).esc_output), utf8stringbuf_get_string( &id_str ), len );
72 : }
73 :
74 0 : U8_TRACE_END_ERR( result );
75 0 : return result;
76 : }
77 :
78 4 : u8_error_t json_writer_write_int ( json_writer_t *this_, int64_t number )
79 : {
80 4 : U8_TRACE_BEGIN();
81 : char numberStr[21]; /* this is sufficient for signed 64 bit integers: -9223372036854775806 */
82 4 : u8_error_t result = U8_ERROR_NONE;
83 :
84 : /* Note: snprintf is not available on every OS */
85 4 : sprintf( numberStr, "%" PRIi64, number );
86 4 : result = json_writer_write_plain( this_, &(numberStr[0]) );
87 :
88 4 : U8_TRACE_END_ERR( result );
89 4 : return result;
90 : }
91 :
92 0 : u8_error_t json_writer_write_member_string_array ( json_writer_t *this_,
93 : unsigned int indent,
94 : utf8string_t *enc_name,
95 : utf8string_t *unenc_value,
96 : bool next_follows )
97 : {
98 0 : U8_TRACE_BEGIN();
99 : assert( 7 == JSON_WRITER_MAX_INDENT );
100 0 : assert( indent <= JSON_WRITER_MAX_INDENT );
101 0 : assert( NULL != enc_name );
102 0 : assert( NULL != unenc_value );
103 : u8_error_t write_err;
104 :
105 : utf8stringview_t line_list;
106 0 : utf8stringview_init_str( &line_list, unenc_value );
107 : utf8stringlines_t line_iter;
108 0 : utf8stringlines_init( &line_iter,
109 : &line_list,
110 : 80 /*line_length*/
111 : );
112 :
113 0 : write_err = json_writer_write_plain( this_, &(JSON_CONSTANTS_INDENT_QUOTE[2*(JSON_WRITER_MAX_INDENT-indent)]) );
114 0 : write_err |= json_writer_write_plain( this_, enc_name );
115 0 : write_err |= json_writer_write_plain( this_,
116 : JSON_CONSTANTS_QUOTE
117 : JSON_CONSTANTS_DEF
118 : JSON_CONSTANTS_BEGIN_ARRAY
119 : JSON_CONSTANTS_NL
120 : );
121 0 : while ( utf8stringlines_has_next( &line_iter ) )
122 : {
123 0 : utf8stringview_t line = utf8stringlines_next( &line_iter );
124 0 : write_err |= json_writer_write_plain( this_,
125 : JSON_CONSTANTS_TAB
126 : JSON_CONSTANTS_TAB
127 : JSON_CONSTANTS_TAB
128 : JSON_CONSTANTS_TAB
129 : JSON_CONSTANTS_TAB
130 : JSON_CONSTANTS_TAB
131 : JSON_CONSTANTS_TAB
132 : JSON_CONSTANTS_TAB
133 : JSON_CONSTANTS_QUOTE
134 : );
135 0 : write_err |= json_writer_write_string_view_enc( this_, &line );
136 0 : if ( utf8stringlines_has_next( &line_iter ) )
137 : {
138 0 : write_err |= json_writer_write_plain( this_,
139 : JSON_CONSTANTS_QUOTE
140 : JSON_CONSTANTS_NEXT_NL
141 : );
142 : }
143 : else
144 : {
145 0 : write_err |= json_writer_write_plain( this_,
146 : JSON_CONSTANTS_QUOTE
147 : JSON_CONSTANTS_NL
148 : );
149 : }
150 : }
151 0 : write_err = json_writer_write_plain( this_, &(JSON_CONSTANTS_INDENT[2*(JSON_WRITER_MAX_INDENT-indent)]) );
152 0 : write_err |= json_writer_write_plain( this_,
153 : next_follows
154 : ? JSON_CONSTANTS_END_ARRAY JSON_CONSTANTS_NEXT_NL
155 : : JSON_CONSTANTS_END_ARRAY JSON_CONSTANTS_NL
156 : );
157 :
158 0 : utf8stringlines_destroy( &line_iter );
159 0 : utf8stringview_destroy( &line_list );
160 :
161 0 : U8_TRACE_END_ERR( write_err );
162 0 : return write_err;
163 : }
164 :
165 :
166 : /*
167 : Copyright 2021-2025 Andreas Warnke
168 :
169 : Licensed under the Apache License, Version 2.0 (the "License");
170 : you may not use this file except in compliance with the License.
171 : You may obtain a copy of the License at
172 :
173 : http://www.apache.org/licenses/LICENSE-2.0
174 :
175 : Unless required by applicable law or agreed to in writing, software
176 : distributed under the License is distributed on an "AS IS" BASIS,
177 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
178 : See the License for the specific language governing permissions and
179 : limitations under the License.
180 : */
|