Line data Source code
1 : /* File: json_token_reader.inl; Copyright and License: see below */
2 :
3 : #include "json/json_constants.h"
4 : #include "u8/u8_trace.h"
5 : #include <assert.h>
6 :
7 4342 : static inline void json_token_reader_private_skip_whitespace ( json_token_reader_t *this_ )
8 : {
9 4342 : bool ws_end_reached = false;
10 4342 : char current = ' ';
11 18895 : while ( ( ! ws_end_reached ) && ( current != '\0' ) )
12 : {
13 14553 : current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
14 14553 : if ( ( JSON_CONSTANTS_CHAR_NL != current )
15 13399 : && ( JSON_CONSTANTS_CHAR_CR != current )
16 13394 : && ( JSON_CONSTANTS_CHAR_TAB != current )
17 13389 : && ( JSON_CONSTANTS_CHAR_SPACE != current ))
18 : {
19 4342 : ws_end_reached = true;
20 : }
21 : else
22 : {
23 10211 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
24 10211 : if ( current == JSON_CONSTANTS_CHAR_NL )
25 : {
26 1154 : (*this_).input_line ++;
27 : }
28 : }
29 : }
30 4342 : }
31 :
32 22 : static inline unsigned int json_token_reader_get_input_line ( json_token_reader_t *this_ )
33 : {
34 22 : return (*this_).input_line;
35 : }
36 :
37 52 : static inline size_t json_token_reader_get_input_pos ( json_token_reader_t *this_ )
38 : {
39 52 : return universal_buffer_input_stream_read_pos( &((*this_).in_stream) );
40 : }
41 :
42 1470 : static inline bool json_token_reader_private_is_value_end ( json_token_reader_t *this_ )
43 : {
44 1470 : char next = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
45 :
46 1470 : const bool result = (( next == '\0' )
47 1462 : || ( next == JSON_CONSTANTS_CHAR_NL )
48 1413 : || ( next == JSON_CONSTANTS_CHAR_CR )
49 1412 : || ( next == JSON_CONSTANTS_CHAR_TAB )
50 1411 : || ( next == JSON_CONSTANTS_CHAR_SPACE )
51 1362 : || ( next == JSON_CONSTANTS_CHAR_BEGIN_OBJECT )
52 1362 : || ( next == JSON_CONSTANTS_CHAR_END_OBJECT )
53 1361 : || ( next == JSON_CONSTANTS_CHAR_BEGIN_ARRAY )
54 1361 : || ( next == JSON_CONSTANTS_CHAR_END_ARRAY )
55 1360 : || ( next == JSON_CONSTANTS_CHAR_NAME_SEPARATOR )
56 2932 : || ( next == JSON_CONSTANTS_CHAR_VALUE_SEPARATOR ));
57 :
58 1470 : return result;
59 : }
60 :
61 1149 : static inline u8_error_t json_token_reader_private_read_string ( json_token_reader_t *this_, universal_output_stream_t *out_stream )
62 : {
63 1149 : assert( out_stream != NULL );
64 1149 : u8_error_t result = U8_ERROR_NONE;
65 1149 : bool str_end_reached = false;
66 1149 : char esc_incomplete = false;
67 : char out_buffer[64];
68 1149 : size_t ouf_buf_len = 0;
69 14564 : while ( ! str_end_reached )
70 : {
71 13415 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
72 13415 : if ( '\0' == current )
73 : {
74 1 : str_end_reached = true;
75 1 : result = U8_ERROR_LEXICAL_STRUCTURE;
76 : }
77 13414 : else if (( JSON_CONSTANTS_CHAR_END_STRING == current )&&( ! esc_incomplete ))
78 : {
79 1148 : str_end_reached = true;
80 : }
81 : else
82 : {
83 12266 : assert( ouf_buf_len < sizeof(out_buffer) );
84 12266 : out_buffer[ouf_buf_len] = universal_buffer_input_stream_read_next( &((*this_).in_stream) );
85 12266 : ouf_buf_len ++;
86 : }
87 13415 : if (( JSON_CONSTANTS_CHAR_ESC == current ) && ( ! esc_incomplete ))
88 : {
89 107 : esc_incomplete = true;
90 : }
91 : else
92 : {
93 13308 : esc_incomplete = false;
94 13308 : if ( ouf_buf_len >= (sizeof(out_buffer)-sizeof(char)) )
95 : {
96 : /* only if not in the middle of an escape character, write to out_stream */
97 : const int err
98 0 : = universal_output_stream_write( out_stream, &out_buffer, ouf_buf_len );
99 0 : ouf_buf_len = 0;
100 0 : if ( err != 0 )
101 : {
102 0 : U8_TRACE_INFO( "could not write all data to output stream in json_token_reader_private_read_string." );
103 0 : result = U8_ERROR_STRING_BUFFER_EXCEEDED;
104 : }
105 : }
106 : }
107 : }
108 : {
109 : const int err2
110 1149 : = universal_output_stream_write( out_stream, &out_buffer, ouf_buf_len );
111 1149 : ouf_buf_len = 0;
112 1149 : if ( err2 != 0 )
113 : {
114 43 : U8_TRACE_INFO( "could not write all data to output stream in json_token_reader_private_read_string" );
115 43 : result = U8_ERROR_STRING_BUFFER_EXCEEDED;
116 : }
117 : }
118 :
119 1149 : return result;
120 : }
121 :
122 295 : static inline u8_error_t json_token_reader_private_parse_integer ( json_token_reader_t *this_, int64_t *out_int )
123 : {
124 295 : assert( out_int != NULL );
125 : int64_t result;
126 295 : u8_error_t err = U8_ERROR_NONE;
127 :
128 295 : char first = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
129 295 : if ( '0' == first )
130 : {
131 : /* only zero may begin with digit zero */
132 27 : result = 0;
133 27 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
134 : }
135 : else
136 : {
137 268 : bool minus = false;
138 268 : bool has_digits = false;
139 268 : bool minus_zero_error = false;
140 268 : result = 0;
141 :
142 : /* check for minus */
143 268 : if ( '-' == first )
144 : {
145 54 : minus = true;
146 54 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
147 54 : if ( '0' == universal_buffer_input_stream_peek_next( &((*this_).in_stream) ) )
148 : {
149 : /* number starts with -0 which is invalid */
150 1 : minus_zero_error = true;
151 : }
152 : }
153 :
154 268 : bool int_end_reached = false;
155 1514 : while ( ! int_end_reached )
156 : {
157 1246 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
158 1246 : if (( '0' <= current )&&( current <= '9'))
159 : {
160 978 : has_digits = true;
161 978 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
162 978 : result = (result*10)+((int) (current-'0'));
163 : }
164 : else
165 : {
166 268 : int_end_reached = true;
167 : }
168 : }
169 :
170 268 : if ( minus )
171 : {
172 54 : result = -result;
173 : }
174 :
175 268 : if ( ( ! has_digits ) || minus_zero_error )
176 : {
177 3 : result = 0;
178 3 : err = U8_ERROR_LEXICAL_STRUCTURE;
179 : }
180 : }
181 :
182 295 : *out_int = result;
183 295 : return err;
184 : }
185 :
186 15 : static inline u8_error_t json_token_reader_private_skip_number ( json_token_reader_t *this_ )
187 : {
188 15 : u8_error_t result = U8_ERROR_LEXICAL_STRUCTURE;
189 :
190 15 : bool num_end_reached = false;
191 91 : while ( ! num_end_reached )
192 : {
193 76 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
194 76 : if ( (( '0' <= current )&&( current <= '9'))
195 34 : || ( 'e' == current )
196 31 : || ( 'E' == current )
197 28 : || ( '.' == current )
198 22 : || ( '+' == current )
199 18 : || ( '-' == current ) )
200 : {
201 : /* could be part of a valid number */
202 61 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
203 61 : result = U8_ERROR_NONE;
204 : }
205 : else
206 : {
207 15 : num_end_reached = true;
208 : }
209 : }
210 :
211 15 : return result;
212 : }
213 :
214 :
215 : /*
216 : Copyright 2016-2025 Andreas Warnke
217 :
218 : Licensed under the Apache License, Version 2.0 (the "License");
219 : you may not use this file except in compliance with the License.
220 : You may obtain a copy of the License at
221 :
222 : http://www.apache.org/licenses/LICENSE-2.0
223 :
224 : Unless required by applicable law or agreed to in writing, software
225 : distributed under the License is distributed on an "AS IS" BASIS,
226 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
227 : See the License for the specific language governing permissions and
228 : limitations under the License.
229 : */
|