LCOV - code coverage report
Current view: top level - io/include/json - json_token_reader.inl (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.2_covts Lines: 95.4 % 109 104
Test Date: 2026-05-03 11:56:31 Functions: 100.0 % 7 7

            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              : */
        

Generated by: LCOV version 2.0-1