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 5483 : static inline void json_token_reader_private_skip_whitespace ( json_token_reader_t *this_ )
8 : {
9 5483 : bool ws_end_reached = false;
10 5483 : char current = ' ';
11 24071 : while ( ( ! ws_end_reached ) && ( current != '\0' ) )
12 : {
13 18588 : current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
14 18588 : if ( ( JSON_CONSTANTS_CHAR_NL != current )
15 17139 : && ( JSON_CONSTANTS_CHAR_CR != current )
16 17134 : && ( JSON_CONSTANTS_CHAR_TAB != current )
17 17129 : && ( JSON_CONSTANTS_CHAR_SPACE != current ))
18 : {
19 5483 : ws_end_reached = true;
20 : }
21 : else
22 : {
23 13105 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
24 13105 : if ( current == JSON_CONSTANTS_CHAR_NL )
25 : {
26 1449 : (*this_).input_line ++;
27 : }
28 : }
29 : }
30 5483 : }
31 :
32 23 : static inline unsigned int json_token_reader_get_input_line ( json_token_reader_t *this_ )
33 : {
34 23 : 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 1862 : static inline bool json_token_reader_private_is_value_end ( json_token_reader_t *this_ )
43 : {
44 1862 : char next = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
45 :
46 1862 : const bool result = (( next == '\0' )
47 1854 : || ( next == JSON_CONSTANTS_CHAR_NL )
48 1796 : || ( next == JSON_CONSTANTS_CHAR_CR )
49 1795 : || ( next == JSON_CONSTANTS_CHAR_TAB )
50 1794 : || ( next == JSON_CONSTANTS_CHAR_SPACE )
51 1735 : || ( next == JSON_CONSTANTS_CHAR_BEGIN_OBJECT )
52 1735 : || ( next == JSON_CONSTANTS_CHAR_END_OBJECT )
53 1734 : || ( next == JSON_CONSTANTS_CHAR_BEGIN_ARRAY )
54 1734 : || ( next == JSON_CONSTANTS_CHAR_END_ARRAY )
55 1733 : || ( next == JSON_CONSTANTS_CHAR_NAME_SEPARATOR )
56 3716 : || ( next == JSON_CONSTANTS_CHAR_VALUE_SEPARATOR ));
57 :
58 1862 : return result;
59 : }
60 :
61 1465 : static inline u8_error_t json_token_reader_private_read_string ( json_token_reader_t *this_, universal_output_stream_t *out_stream )
62 : {
63 1465 : assert( out_stream != NULL );
64 1465 : u8_error_t result = U8_ERROR_NONE;
65 1465 : bool str_end_reached = false;
66 1465 : char esc_incomplete = false;
67 : char out_buffer[64];
68 1465 : size_t ouf_buf_len = 0;
69 19069 : while ( ! str_end_reached )
70 : {
71 17604 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
72 17604 : if ( '\0' == current )
73 : {
74 1 : str_end_reached = true;
75 1 : result = U8_ERROR_LEXICAL_STRUCTURE;
76 : }
77 17603 : else if (( JSON_CONSTANTS_CHAR_END_STRING == current )&&( ! esc_incomplete ))
78 : {
79 1464 : str_end_reached = true;
80 : }
81 : else
82 : {
83 16139 : assert( ouf_buf_len < sizeof(out_buffer) );
84 16139 : out_buffer[ouf_buf_len] = universal_buffer_input_stream_read_next( &((*this_).in_stream) );
85 16139 : ouf_buf_len ++;
86 : }
87 17604 : if (( JSON_CONSTANTS_CHAR_ESC == current ) && ( ! esc_incomplete ))
88 : {
89 134 : esc_incomplete = true;
90 : }
91 : else
92 : {
93 17470 : esc_incomplete = false;
94 17470 : 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 1465 : = universal_output_stream_write( out_stream, &out_buffer, ouf_buf_len );
111 1465 : ouf_buf_len = 0;
112 1465 : if ( err2 != 0 )
113 : {
114 64 : U8_TRACE_INFO( "could not write all data to output stream in json_token_reader_private_read_string" );
115 64 : result = U8_ERROR_STRING_BUFFER_EXCEEDED;
116 : }
117 : }
118 :
119 1465 : return result;
120 : }
121 :
122 371 : static inline u8_error_t json_token_reader_private_parse_integer ( json_token_reader_t *this_, int64_t *out_int )
123 : {
124 371 : assert( out_int != NULL );
125 : int64_t result;
126 371 : u8_error_t err = U8_ERROR_NONE;
127 :
128 371 : char first = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
129 371 : if ( '0' == first )
130 : {
131 : /* only zero may begin with digit zero */
132 41 : result = 0;
133 41 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
134 : }
135 : else
136 : {
137 330 : bool minus = false;
138 330 : bool has_digits = false;
139 330 : bool minus_zero_error = false;
140 330 : result = 0;
141 :
142 : /* check for minus */
143 330 : if ( '-' == first )
144 : {
145 70 : minus = true;
146 70 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
147 70 : 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 330 : bool int_end_reached = false;
155 1819 : while ( ! int_end_reached )
156 : {
157 1489 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) );
158 1489 : if (( '0' <= current )&&( current <= '9'))
159 : {
160 1159 : has_digits = true;
161 1159 : universal_buffer_input_stream_read_next( &((*this_).in_stream) );
162 1159 : result = (result*10)+((int) (current-'0'));
163 : }
164 : else
165 : {
166 330 : int_end_reached = true;
167 : }
168 : }
169 :
170 330 : if ( minus )
171 : {
172 70 : result = -result;
173 : }
174 :
175 330 : if ( ( ! has_digits ) || minus_zero_error )
176 : {
177 3 : result = 0;
178 3 : err = U8_ERROR_LEXICAL_STRUCTURE;
179 : }
180 : }
181 :
182 371 : *out_int = result;
183 371 : 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-2026 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 : */
|