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 4153 : static inline void json_token_reader_private_skip_whitespace ( json_token_reader_t *this_ ) 8 : { 9 4153 : bool ws_end_reached = false; 10 4153 : char current = ' '; 11 18256 : while ( ( ! ws_end_reached ) && ( current != '\0' ) ) 12 : { 13 14103 : current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) ); 14 14103 : if ( ( JSON_CONSTANTS_CHAR_NL != current ) 15 13018 : && ( JSON_CONSTANTS_CHAR_CR != current ) 16 13013 : && ( JSON_CONSTANTS_CHAR_TAB != current ) 17 13008 : && ( JSON_CONSTANTS_CHAR_SPACE != current )) 18 : { 19 4153 : ws_end_reached = true; 20 : } 21 : else 22 : { 23 9950 : universal_buffer_input_stream_read_next( &((*this_).in_stream) ); 24 9950 : if ( current == JSON_CONSTANTS_CHAR_NL ) 25 : { 26 1085 : (*this_).input_line ++; 27 : } 28 : } 29 : } 30 4153 : } 31 : 32 19 : static inline unsigned int json_token_reader_get_input_line ( json_token_reader_t *this_ ) 33 : { 34 19 : 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 1416 : static inline bool json_token_reader_private_is_value_end ( json_token_reader_t *this_ ) 43 : { 44 1416 : char next = universal_buffer_input_stream_peek_next( &((*this_).in_stream) ); 45 : 46 1416 : const bool result = (( next == '\0' ) 47 1408 : || ( next == JSON_CONSTANTS_CHAR_NL ) 48 1362 : || ( next == JSON_CONSTANTS_CHAR_CR ) 49 1361 : || ( next == JSON_CONSTANTS_CHAR_TAB ) 50 1360 : || ( next == JSON_CONSTANTS_CHAR_SPACE ) 51 1311 : || ( next == JSON_CONSTANTS_CHAR_BEGIN_OBJECT ) 52 1311 : || ( next == JSON_CONSTANTS_CHAR_END_OBJECT ) 53 1310 : || ( next == JSON_CONSTANTS_CHAR_BEGIN_ARRAY ) 54 1310 : || ( next == JSON_CONSTANTS_CHAR_END_ARRAY ) 55 1309 : || ( next == JSON_CONSTANTS_CHAR_NAME_SEPARATOR ) 56 2824 : || ( next == JSON_CONSTANTS_CHAR_VALUE_SEPARATOR )); 57 : 58 1416 : return result; 59 : } 60 : 61 1101 : static inline u8_error_t json_token_reader_private_read_string ( json_token_reader_t *this_, universal_output_stream_t *out_stream ) 62 : { 63 1101 : assert( out_stream != NULL ); 64 1101 : u8_error_t result = U8_ERROR_NONE; 65 1101 : bool str_end_reached = false; 66 1101 : char esc_incomplete = false; 67 : char out_buffer[64]; 68 1101 : size_t ouf_buf_len = 0; 69 13946 : while ( ! str_end_reached ) 70 : { 71 12845 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) ); 72 12845 : if ( '\0' == current ) 73 : { 74 1 : str_end_reached = true; 75 1 : result = U8_ERROR_LEXICAL_STRUCTURE; 76 : } 77 12844 : else if (( JSON_CONSTANTS_CHAR_END_STRING == current )&&( ! esc_incomplete )) 78 : { 79 1100 : str_end_reached = true; 80 : } 81 : else 82 : { 83 11744 : assert( ouf_buf_len < sizeof(out_buffer) ); 84 11744 : out_buffer[ouf_buf_len] = universal_buffer_input_stream_read_next( &((*this_).in_stream) ); 85 11744 : ouf_buf_len ++; 86 : } 87 12845 : if (( JSON_CONSTANTS_CHAR_ESC == current ) && ( ! esc_incomplete )) 88 : { 89 107 : esc_incomplete = true; 90 : } 91 : else 92 : { 93 12738 : esc_incomplete = false; 94 12738 : 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 1101 : = universal_output_stream_write( out_stream, &out_buffer, ouf_buf_len ); 111 1101 : ouf_buf_len = 0; 112 1101 : if ( err2 != 0 ) 113 : { 114 28 : U8_TRACE_INFO( "could not write all data to output stream in json_token_reader_private_read_string" ); 115 28 : result = U8_ERROR_STRING_BUFFER_EXCEEDED; 116 : } 117 : } 118 : 119 1101 : 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 9 : static inline u8_error_t json_token_reader_private_skip_number ( json_token_reader_t *this_ ) 187 : { 188 9 : u8_error_t result = U8_ERROR_LEXICAL_STRUCTURE; 189 : 190 9 : bool num_end_reached = false; 191 73 : while ( ! num_end_reached ) 192 : { 193 64 : char current = universal_buffer_input_stream_peek_next( &((*this_).in_stream) ); 194 64 : if ( (( '0' <= current )&&( current <= '9')) 195 28 : || ( 'e' == current ) 196 25 : || ( 'E' == current ) 197 22 : || ( '.' == current ) 198 16 : || ( '+' == current ) 199 12 : || ( '-' == current ) ) 200 : { 201 : /* could be part of a valid number */ 202 55 : universal_buffer_input_stream_read_next( &((*this_).in_stream) ); 203 55 : result = U8_ERROR_NONE; 204 : } 205 : else 206 : { 207 9 : num_end_reached = true; 208 : } 209 : } 210 : 211 9 : return result; 212 : } 213 : 214 : 215 : /* 216 : Copyright 2016-2024 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 : */