LCOV - code coverage report
Current view: top level - src/common - jsonapi.c (source / functions) Hit Total Coverage
Test: PostgreSQL 14devel Lines: 441 489 90.2 %
Date: 2020-12-05 17:06:23 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * jsonapi.c
       4             :  *      JSON parser and lexer interfaces
       5             :  *
       6             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/common/jsonapi.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : #ifndef FRONTEND
      15             : #include "postgres.h"
      16             : #else
      17             : #include "postgres_fe.h"
      18             : #endif
      19             : 
      20             : #include "common/jsonapi.h"
      21             : #include "mb/pg_wchar.h"
      22             : 
      23             : #ifdef FRONTEND
      24             : #include "common/logging.h"
      25             : #else
      26             : #include "miscadmin.h"
      27             : #endif
      28             : 
      29             : #ifdef FRONTEND
      30             : #define check_stack_depth()
      31             : #define json_log_and_abort(...) \
      32             :     do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0)
      33             : #else
      34             : #define json_log_and_abort(...) elog(ERROR, __VA_ARGS__)
      35             : #endif
      36             : 
      37             : /*
      38             :  * The context of the parser is maintained by the recursive descent
      39             :  * mechanism, but is passed explicitly to the error reporting routine
      40             :  * for better diagnostics.
      41             :  */
      42             : typedef enum                    /* contexts of JSON parser */
      43             : {
      44             :     JSON_PARSE_VALUE,           /* expecting a value */
      45             :     JSON_PARSE_STRING,          /* expecting a string (for a field name) */
      46             :     JSON_PARSE_ARRAY_START,     /* saw '[', expecting value or ']' */
      47             :     JSON_PARSE_ARRAY_NEXT,      /* saw array element, expecting ',' or ']' */
      48             :     JSON_PARSE_OBJECT_START,    /* saw '{', expecting label or '}' */
      49             :     JSON_PARSE_OBJECT_LABEL,    /* saw object label, expecting ':' */
      50             :     JSON_PARSE_OBJECT_NEXT,     /* saw object value, expecting ',' or '}' */
      51             :     JSON_PARSE_OBJECT_COMMA,    /* saw object ',', expecting next label */
      52             :     JSON_PARSE_END              /* saw the end of a document, expect nothing */
      53             : } JsonParseContext;
      54             : 
      55             : static inline JsonParseErrorType json_lex_string(JsonLexContext *lex);
      56             : static inline JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s,
      57             :                                                  bool *num_err, int *total_len);
      58             : static inline JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem);
      59             : static JsonParseErrorType parse_object_field(JsonLexContext *lex, JsonSemAction *sem);
      60             : static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem);
      61             : static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem);
      62             : static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem);
      63             : static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex);
      64             : static char *extract_token(JsonLexContext *lex);
      65             : 
      66             : /* the null action object used for pure validation */
      67             : JsonSemAction nullSemAction =
      68             : {
      69             :     NULL, NULL, NULL, NULL, NULL,
      70             :     NULL, NULL, NULL, NULL, NULL
      71             : };
      72             : 
      73             : /* Recursive Descent parser support routines */
      74             : 
      75             : /*
      76             :  * lex_peek
      77             :  *
      78             :  * what is the current look_ahead token?
      79             : */
      80             : static inline JsonTokenType
      81     3641160 : lex_peek(JsonLexContext *lex)
      82             : {
      83     3641160 :     return lex->token_type;
      84             : }
      85             : 
      86             : /*
      87             :  * lex_expect
      88             :  *
      89             :  * move the lexer to the next token if the current look_ahead token matches
      90             :  * the parameter token. Otherwise, report an error.
      91             :  */
      92             : static inline JsonParseErrorType
      93      682560 : lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
      94             : {
      95      682560 :     if (lex_peek(lex) == token)
      96      682504 :         return json_lex(lex);
      97             :     else
      98          56 :         return report_parse_error(ctx, lex);
      99             : }
     100             : 
     101             : /* chars to consider as part of an alphanumeric token */
     102             : #define JSON_ALPHANUMERIC_CHAR(c)  \
     103             :     (((c) >= 'a' && (c) <= 'z') || \
     104             :      ((c) >= 'A' && (c) <= 'Z') || \
     105             :      ((c) >= '0' && (c) <= '9') || \
     106             :      (c) == '_' || \
     107             :      IS_HIGHBIT_SET(c))
     108             : 
     109             : /*
     110             :  * Utility function to check if a string is a valid JSON number.
     111             :  *
     112             :  * str is of length len, and need not be null-terminated.
     113             :  */
     114             : bool
     115        1590 : IsValidJsonNumber(const char *str, int len)
     116             : {
     117             :     bool        numeric_error;
     118             :     int         total_len;
     119             :     JsonLexContext dummy_lex;
     120             : 
     121        1590 :     if (len <= 0)
     122           0 :         return false;
     123             : 
     124             :     /*
     125             :      * json_lex_number expects a leading  '-' to have been eaten already.
     126             :      *
     127             :      * having to cast away the constness of str is ugly, but there's not much
     128             :      * easy alternative.
     129             :      */
     130        1590 :     if (*str == '-')
     131             :     {
     132          48 :         dummy_lex.input = unconstify(char *, str) + 1;
     133          48 :         dummy_lex.input_length = len - 1;
     134             :     }
     135             :     else
     136             :     {
     137        1542 :         dummy_lex.input = unconstify(char *, str);
     138        1542 :         dummy_lex.input_length = len;
     139             :     }
     140             : 
     141        1590 :     json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
     142             : 
     143        1590 :     return (!numeric_error) && (total_len == dummy_lex.input_length);
     144             : }
     145             : 
     146             : /*
     147             :  * makeJsonLexContextCstringLen
     148             :  *
     149             :  * lex constructor, with or without StringInfo object for de-escaped lexemes.
     150             :  *
     151             :  * Without is better as it makes the processing faster, so only make one
     152             :  * if really required.
     153             :  */
     154             : JsonLexContext *
     155       20796 : makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
     156             : {
     157       20796 :     JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
     158             : 
     159       20796 :     lex->input = lex->token_terminator = lex->line_start = json;
     160       20796 :     lex->line_number = 1;
     161       20796 :     lex->input_length = len;
     162       20796 :     lex->input_encoding = encoding;
     163       20796 :     if (need_escapes)
     164       17696 :         lex->strval = makeStringInfo();
     165       20796 :     return lex;
     166             : }
     167             : 
     168             : /*
     169             :  * pg_parse_json
     170             :  *
     171             :  * Publicly visible entry point for the JSON parser.
     172             :  *
     173             :  * lex is a lexing context, set up for the json to be processed by calling
     174             :  * makeJsonLexContext(). sem is a structure of function pointers to semantic
     175             :  * action routines to be called at appropriate spots during parsing, and a
     176             :  * pointer to a state object to be passed to those routines.
     177             :  */
     178             : JsonParseErrorType
     179       20756 : pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
     180             : {
     181             :     JsonTokenType tok;
     182             :     JsonParseErrorType result;
     183             : 
     184             :     /* get the initial token */
     185       20756 :     result = json_lex(lex);
     186       20756 :     if (result != JSON_SUCCESS)
     187         108 :         return result;
     188             : 
     189       20648 :     tok = lex_peek(lex);
     190             : 
     191             :     /* parse by recursive descent */
     192       20648 :     switch (tok)
     193             :     {
     194       14722 :         case JSON_TOKEN_OBJECT_START:
     195       14722 :             result = parse_object(lex, sem);
     196       14662 :             break;
     197        3046 :         case JSON_TOKEN_ARRAY_START:
     198        3046 :             result = parse_array(lex, sem);
     199        2976 :             break;
     200        2880 :         default:
     201        2880 :             result = parse_scalar(lex, sem);    /* json can be a bare scalar */
     202             :     }
     203             : 
     204       20470 :     if (result == JSON_SUCCESS)
     205       20322 :         result = lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
     206             : 
     207       20470 :     return result;
     208             : }
     209             : 
     210             : /*
     211             :  * json_count_array_elements
     212             :  *
     213             :  * Returns number of array elements in lex context at start of array token
     214             :  * until end of array token at same nesting level.
     215             :  *
     216             :  * Designed to be called from array_start routines.
     217             :  */
     218             : JsonParseErrorType
     219           4 : json_count_array_elements(JsonLexContext *lex, int *elements)
     220             : {
     221             :     JsonLexContext copylex;
     222             :     int         count;
     223             :     JsonParseErrorType result;
     224             : 
     225             :     /*
     226             :      * It's safe to do this with a shallow copy because the lexical routines
     227             :      * don't scribble on the input. They do scribble on the other pointers
     228             :      * etc, so doing this with a copy makes that safe.
     229             :      */
     230           4 :     memcpy(&copylex, lex, sizeof(JsonLexContext));
     231           4 :     copylex.strval = NULL;      /* not interested in values here */
     232           4 :     copylex.lex_level++;
     233             : 
     234           4 :     count = 0;
     235           4 :     result = lex_expect(JSON_PARSE_ARRAY_START, &copylex,
     236             :                         JSON_TOKEN_ARRAY_START);
     237           4 :     if (result != JSON_SUCCESS)
     238           0 :         return result;
     239           4 :     if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
     240             :     {
     241             :         while (1)
     242             :         {
     243          28 :             count++;
     244          32 :             result = parse_array_element(&copylex, &nullSemAction);
     245          32 :             if (result != JSON_SUCCESS)
     246           0 :                 return result;
     247          32 :             if (copylex.token_type != JSON_TOKEN_COMMA)
     248           4 :                 break;
     249          28 :             result = json_lex(&copylex);
     250          28 :             if (result != JSON_SUCCESS)
     251           0 :                 return result;
     252             :         }
     253             :     }
     254           4 :     result = lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex,
     255             :                         JSON_TOKEN_ARRAY_END);
     256           4 :     if (result != JSON_SUCCESS)
     257           0 :         return result;
     258             : 
     259           4 :     *elements = count;
     260           4 :     return JSON_SUCCESS;
     261             : }
     262             : 
     263             : /*
     264             :  *  Recursive Descent parse routines. There is one for each structural
     265             :  *  element in a json document:
     266             :  *    - scalar (string, number, true, false, null)
     267             :  *    - array  ( [ ] )
     268             :  *    - array element
     269             :  *    - object ( { } )
     270             :  *    - object field
     271             :  */
     272             : static inline JsonParseErrorType
     273      520918 : parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
     274             : {
     275      520918 :     char       *val = NULL;
     276      520918 :     json_scalar_action sfunc = sem->scalar;
     277      520918 :     JsonTokenType tok = lex_peek(lex);
     278             :     JsonParseErrorType result;
     279             : 
     280             :     /* a scalar must be a string, a number, true, false, or null */
     281      520918 :     if (tok != JSON_TOKEN_STRING && tok != JSON_TOKEN_NUMBER &&
     282        9626 :         tok != JSON_TOKEN_TRUE && tok != JSON_TOKEN_FALSE &&
     283             :         tok != JSON_TOKEN_NULL)
     284          32 :         return report_parse_error(JSON_PARSE_VALUE, lex);
     285             : 
     286             :     /* if no semantic function, just consume the token */
     287      520886 :     if (sfunc == NULL)
     288        4948 :         return json_lex(lex);
     289             : 
     290             :     /* extract the de-escaped string value, or the raw lexeme */
     291      515938 :     if (lex_peek(lex) == JSON_TOKEN_STRING)
     292             :     {
     293      349542 :         if (lex->strval != NULL)
     294      345670 :             val = pstrdup(lex->strval->data);
     295             :     }
     296             :     else
     297             :     {
     298      166396 :         int         len = (lex->token_terminator - lex->token_start);
     299             : 
     300      166396 :         val = palloc(len + 1);
     301      166396 :         memcpy(val, lex->token_start, len);
     302      166396 :         val[len] = '\0';
     303             :     }
     304             : 
     305             :     /* consume the token */
     306      515938 :     result = json_lex(lex);
     307      515938 :     if (result != JSON_SUCCESS)
     308           0 :         return result;
     309             : 
     310             :     /* invoke the callback */
     311      515938 :     (*sfunc) (sem->semstate, val, tok);
     312             : 
     313      515874 :     return JSON_SUCCESS;
     314             : }
     315             : 
     316             : static JsonParseErrorType
     317      523422 : parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
     318             : {
     319             :     /*
     320             :      * An object field is "fieldname" : value where value can be a scalar,
     321             :      * object or array.  Note: in user-facing docs and error messages, we
     322             :      * generally call a field name a "key".
     323             :      */
     324             : 
     325      523422 :     char       *fname = NULL;   /* keep compiler quiet */
     326      523422 :     json_ofield_action ostart = sem->object_field_start;
     327      523422 :     json_ofield_action oend = sem->object_field_end;
     328             :     bool        isnull;
     329             :     JsonTokenType tok;
     330             :     JsonParseErrorType result;
     331             : 
     332      523422 :     if (lex_peek(lex) != JSON_TOKEN_STRING)
     333           8 :         return report_parse_error(JSON_PARSE_STRING, lex);
     334      523414 :     if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
     335      494882 :         fname = pstrdup(lex->strval->data);
     336      523414 :     result = json_lex(lex);
     337      523414 :     if (result != JSON_SUCCESS)
     338           8 :         return result;
     339             : 
     340      523406 :     result = lex_expect(JSON_PARSE_OBJECT_LABEL, lex, JSON_TOKEN_COLON);
     341      523406 :     if (result != JSON_SUCCESS)
     342          60 :         return result;
     343             : 
     344      523346 :     tok = lex_peek(lex);
     345      523346 :     isnull = tok == JSON_TOKEN_NULL;
     346             : 
     347      523346 :     if (ostart != NULL)
     348      494826 :         (*ostart) (sem->semstate, fname, isnull);
     349             : 
     350      523338 :     switch (tok)
     351             :     {
     352        7908 :         case JSON_TOKEN_OBJECT_START:
     353        7908 :             result = parse_object(lex, sem);
     354        2646 :             break;
     355        9680 :         case JSON_TOKEN_ARRAY_START:
     356        9680 :             result = parse_array(lex, sem);
     357        9646 :             break;
     358      505750 :         default:
     359      505750 :             result = parse_scalar(lex, sem);
     360             :     }
     361      518038 :     if (result != JSON_SUCCESS)
     362           8 :         return result;
     363             : 
     364      518030 :     if (oend != NULL)
     365       72408 :         (*oend) (sem->semstate, fname, isnull);
     366      518030 :     return JSON_SUCCESS;
     367             : }
     368             : 
     369             : static JsonParseErrorType
     370      108712 : parse_object(JsonLexContext *lex, JsonSemAction *sem)
     371             : {
     372             :     /*
     373             :      * an object is a possibly empty sequence of object fields, separated by
     374             :      * commas and surrounded by curly braces.
     375             :      */
     376      108712 :     json_struct_action ostart = sem->object_start;
     377      108712 :     json_struct_action oend = sem->object_end;
     378             :     JsonTokenType tok;
     379             :     JsonParseErrorType result;
     380             : 
     381       29904 :     check_stack_depth();
     382             : 
     383      108704 :     if (ostart != NULL)
     384       96500 :         (*ostart) (sem->semstate);
     385             : 
     386             :     /*
     387             :      * Data inside an object is at a higher nesting level than the object
     388             :      * itself. Note that we increment this after we call the semantic routine
     389             :      * for the object start and restore it before we call the routine for the
     390             :      * object end.
     391             :      */
     392      108690 :     lex->lex_level++;
     393             : 
     394             :     Assert(lex_peek(lex) == JSON_TOKEN_OBJECT_START);
     395      108690 :     result = json_lex(lex);
     396      108690 :     if (result != JSON_SUCCESS)
     397           6 :         return result;
     398             : 
     399      108684 :     tok = lex_peek(lex);
     400      108684 :     switch (tok)
     401             :     {
     402      103928 :         case JSON_TOKEN_STRING:
     403      103928 :             result = parse_object_field(lex, sem);
     404      518114 :             while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
     405             :             {
     406      419494 :                 result = json_lex(lex);
     407      419494 :                 if (result != JSON_SUCCESS)
     408           0 :                     break;
     409      419494 :                 result = parse_object_field(lex, sem);
     410             :             }
     411       98620 :             break;
     412        4746 :         case JSON_TOKEN_OBJECT_END:
     413        4746 :             break;
     414          10 :         default:
     415             :             /* case of an invalid initial token inside the object */
     416          10 :             result = report_parse_error(JSON_PARSE_OBJECT_START, lex);
     417             :     }
     418      103376 :     if (result != JSON_SUCCESS)
     419          94 :         return result;
     420             : 
     421      103282 :     result = lex_expect(JSON_PARSE_OBJECT_NEXT, lex, JSON_TOKEN_OBJECT_END);
     422      103282 :     if (result != JSON_SUCCESS)
     423           8 :         return result;
     424             : 
     425      103274 :     lex->lex_level--;
     426             : 
     427      103274 :     if (oend != NULL)
     428       92178 :         (*oend) (sem->semstate);
     429             : 
     430      103232 :     return JSON_SUCCESS;
     431             : }
     432             : 
     433             : static JsonParseErrorType
     434      106438 : parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
     435             : {
     436      106438 :     json_aelem_action astart = sem->array_element_start;
     437      106438 :     json_aelem_action aend = sem->array_element_end;
     438      106438 :     JsonTokenType tok = lex_peek(lex);
     439             :     JsonParseErrorType result;
     440             : 
     441             :     bool        isnull;
     442             : 
     443      106438 :     isnull = tok == JSON_TOKEN_NULL;
     444             : 
     445      106438 :     if (astart != NULL)
     446        5200 :         (*astart) (sem->semstate, isnull);
     447             : 
     448             :     /* an array element is any object, array or scalar */
     449      106438 :     switch (tok)
     450             :     {
     451       86082 :         case JSON_TOKEN_OBJECT_START:
     452       86082 :             result = parse_object(lex, sem);
     453       86032 :             break;
     454        8068 :         case JSON_TOKEN_ARRAY_START:
     455        8068 :             result = parse_array(lex, sem);
     456        2136 :             break;
     457       12288 :         default:
     458       12288 :             result = parse_scalar(lex, sem);
     459             :     }
     460             : 
     461      100444 :     if (result != JSON_SUCCESS)
     462           8 :         return result;
     463             : 
     464      100436 :     if (aend != NULL)
     465        4860 :         (*aend) (sem->semstate, isnull);
     466             : 
     467      100428 :     return JSON_SUCCESS;
     468             : }
     469             : 
     470             : static JsonParseErrorType
     471       20794 : parse_array(JsonLexContext *lex, JsonSemAction *sem)
     472             : {
     473             :     /*
     474             :      * an array is a possibly empty sequence of array elements, separated by
     475             :      * commas and surrounded by square brackets.
     476             :      */
     477       20794 :     json_struct_action astart = sem->array_start;
     478       20794 :     json_struct_action aend = sem->array_end;
     479             :     JsonParseErrorType result;
     480             : 
     481       20582 :     check_stack_depth();
     482             : 
     483       20786 :     if (astart != NULL)
     484        9134 :         (*astart) (sem->semstate);
     485             : 
     486             :     /*
     487             :      * Data inside an array is at a higher nesting level than the array
     488             :      * itself. Note that we increment this after we call the semantic routine
     489             :      * for the array start and restore it before we call the routine for the
     490             :      * array end.
     491             :      */
     492       20776 :     lex->lex_level++;
     493             : 
     494       20776 :     result = lex_expect(JSON_PARSE_ARRAY_START, lex, JSON_TOKEN_ARRAY_START);
     495       20776 :     if (result == JSON_SUCCESS && lex_peek(lex) != JSON_TOKEN_ARRAY_END)
     496             :     {
     497       16422 :         result = parse_array_element(lex, sem);
     498             : 
     499      100404 :         while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
     500             :         {
     501       89984 :             result = json_lex(lex);
     502       89984 :             if (result != JSON_SUCCESS)
     503           0 :                 break;
     504       89984 :             result = parse_array_element(lex, sem);
     505             :         }
     506             :     }
     507       14774 :     if (result != JSON_SUCCESS)
     508           8 :         return result;
     509             : 
     510       14766 :     result = lex_expect(JSON_PARSE_ARRAY_NEXT, lex, JSON_TOKEN_ARRAY_END);
     511       14766 :     if (result != JSON_SUCCESS)
     512          16 :         return result;
     513             : 
     514       14750 :     lex->lex_level--;
     515             : 
     516       14750 :     if (aend != NULL)
     517        4650 :         (*aend) (sem->semstate);
     518             : 
     519       14734 :     return JSON_SUCCESS;
     520             : }
     521             : 
     522             : /*
     523             :  * Lex one token from the input stream.
     524             :  */
     525             : JsonParseErrorType
     526     2365796 : json_lex(JsonLexContext *lex)
     527             : {
     528             :     char       *s;
     529             :     int         len;
     530             :     JsonParseErrorType result;
     531             : 
     532             :     /* Skip leading whitespace. */
     533     2365796 :     s = lex->token_terminator;
     534     2365796 :     len = s - lex->input;
     535     5370048 :     while (len < lex->input_length &&
     536     5329346 :            (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
     537             :     {
     538     3004252 :         if (*s == '\n')
     539      189060 :             ++lex->line_number;
     540     3004252 :         ++s;
     541     3004252 :         ++len;
     542             :     }
     543     2365796 :     lex->token_start = s;
     544             : 
     545             :     /* Determine token type. */
     546     2365796 :     if (len >= lex->input_length)
     547             :     {
     548       40702 :         lex->token_start = NULL;
     549       40702 :         lex->prev_token_terminator = lex->token_terminator;
     550       40702 :         lex->token_terminator = s;
     551       40702 :         lex->token_type = JSON_TOKEN_END;
     552             :     }
     553             :     else
     554             :     {
     555     2325094 :         switch (*s)
     556             :         {
     557             :                 /* Single-character token, some kind of punctuation mark. */
     558      108720 :             case '{':
     559      108720 :                 lex->prev_token_terminator = lex->token_terminator;
     560      108720 :                 lex->token_terminator = s + 1;
     561      108720 :                 lex->token_type = JSON_TOKEN_OBJECT_START;
     562      108720 :                 break;
     563      103286 :             case '}':
     564      103286 :                 lex->prev_token_terminator = lex->token_terminator;
     565      103286 :                 lex->token_terminator = s + 1;
     566      103286 :                 lex->token_type = JSON_TOKEN_OBJECT_END;
     567      103286 :                 break;
     568       20802 :             case '[':
     569       20802 :                 lex->prev_token_terminator = lex->token_terminator;
     570       20802 :                 lex->token_terminator = s + 1;
     571       20802 :                 lex->token_type = JSON_TOKEN_ARRAY_START;
     572       20802 :                 break;
     573       14824 :             case ']':
     574       14824 :                 lex->prev_token_terminator = lex->token_terminator;
     575       14824 :                 lex->token_terminator = s + 1;
     576       14824 :                 lex->token_type = JSON_TOKEN_ARRAY_END;
     577       14824 :                 break;
     578      509534 :             case ',':
     579      509534 :                 lex->prev_token_terminator = lex->token_terminator;
     580      509534 :                 lex->token_terminator = s + 1;
     581      509534 :                 lex->token_type = JSON_TOKEN_COMMA;
     582      509534 :                 break;
     583      523406 :             case ':':
     584      523406 :                 lex->prev_token_terminator = lex->token_terminator;
     585      523406 :                 lex->token_terminator = s + 1;
     586      523406 :                 lex->token_type = JSON_TOKEN_COLON;
     587      523406 :                 break;
     588      874696 :             case '"':
     589             :                 /* string */
     590      874696 :                 result = json_lex_string(lex);
     591      874696 :                 if (result != JSON_SUCCESS)
     592          96 :                     return result;
     593      874600 :                 lex->token_type = JSON_TOKEN_STRING;
     594      874600 :                 break;
     595         106 :             case '-':
     596             :                 /* Negative number. */
     597         106 :                 result = json_lex_number(lex, s + 1, NULL, NULL);
     598         106 :                 if (result != JSON_SUCCESS)
     599           0 :                     return result;
     600         106 :                 lex->token_type = JSON_TOKEN_NUMBER;
     601         106 :                 break;
     602      155414 :             case '0':
     603             :             case '1':
     604             :             case '2':
     605             :             case '3':
     606             :             case '4':
     607             :             case '5':
     608             :             case '6':
     609             :             case '7':
     610             :             case '8':
     611             :             case '9':
     612             :                 /* Positive number. */
     613      155414 :                 result = json_lex_number(lex, s, NULL, NULL);
     614      155414 :                 if (result != JSON_SUCCESS)
     615          32 :                     return result;
     616      155382 :                 lex->token_type = JSON_TOKEN_NUMBER;
     617      155382 :                 break;
     618       14306 :             default:
     619             :                 {
     620             :                     char       *p;
     621             : 
     622             :                     /*
     623             :                      * We're not dealing with a string, number, legal
     624             :                      * punctuation mark, or end of string.  The only legal
     625             :                      * tokens we might find here are true, false, and null,
     626             :                      * but for error reporting purposes we scan until we see a
     627             :                      * non-alphanumeric character.  That way, we can report
     628             :                      * the whole word as an unexpected token, rather than just
     629             :                      * some unintuitive prefix thereof.
     630             :                      */
     631       78440 :                     for (p = s; p - s < lex->input_length - len && JSON_ALPHANUMERIC_CHAR(*p); p++)
     632             :                          /* skip */ ;
     633             : 
     634             :                     /*
     635             :                      * We got some sort of unexpected punctuation or an
     636             :                      * otherwise unexpected character, so just complain about
     637             :                      * that one character.
     638             :                      */
     639       14306 :                     if (p == s)
     640             :                     {
     641          16 :                         lex->prev_token_terminator = lex->token_terminator;
     642          16 :                         lex->token_terminator = s + 1;
     643          16 :                         return JSON_INVALID_TOKEN;
     644             :                     }
     645             : 
     646             :                     /*
     647             :                      * We've got a real alphanumeric token here.  If it
     648             :                      * happens to be true, false, or null, all is well.  If
     649             :                      * not, error out.
     650             :                      */
     651       14290 :                     lex->prev_token_terminator = lex->token_terminator;
     652       14290 :                     lex->token_terminator = p;
     653       14290 :                     if (p - s == 4)
     654             :                     {
     655        7328 :                         if (memcmp(s, "true", 4) == 0)
     656        4658 :                             lex->token_type = JSON_TOKEN_TRUE;
     657        2670 :                         else if (memcmp(s, "null", 4) == 0)
     658        2662 :                             lex->token_type = JSON_TOKEN_NULL;
     659             :                         else
     660           8 :                             return JSON_INVALID_TOKEN;
     661             :                     }
     662        6962 :                     else if (p - s == 5 && memcmp(s, "false", 5) == 0)
     663        6948 :                         lex->token_type = JSON_TOKEN_FALSE;
     664             :                     else
     665          14 :                         return JSON_INVALID_TOKEN;
     666             : 
     667             :                 }
     668             :         }                       /* end of switch */
     669             :     }
     670             : 
     671     2365630 :     return JSON_SUCCESS;
     672             : }
     673             : 
     674             : /*
     675             :  * The next token in the input stream is known to be a string; lex it.
     676             :  */
     677             : static inline JsonParseErrorType
     678      874696 : json_lex_string(JsonLexContext *lex)
     679             : {
     680             :     char       *s;
     681             :     int         len;
     682      874696 :     int         hi_surrogate = -1;
     683             : 
     684      874696 :     if (lex->strval != NULL)
     685      846440 :         resetStringInfo(lex->strval);
     686             : 
     687             :     Assert(lex->input_length > 0);
     688      874696 :     s = lex->token_start;
     689      874696 :     len = lex->token_start - lex->input;
     690             :     for (;;)
     691             :     {
     692     9804410 :         s++;
     693    10679106 :         len++;
     694             :         /* Premature end of the string. */
     695    10679106 :         if (len >= lex->input_length)
     696             :         {
     697           8 :             lex->token_terminator = s;
     698           8 :             return JSON_INVALID_TOKEN;
     699             :         }
     700    10679098 :         else if (*s == '"')
     701      874600 :             break;
     702     9804498 :         else if ((unsigned char) *s < 32)
     703             :         {
     704             :             /* Per RFC4627, these characters MUST be escaped. */
     705             :             /* Since *s isn't printable, exclude it from the context string */
     706           8 :             lex->token_terminator = s;
     707           8 :             return JSON_ESCAPING_REQUIRED;
     708             :         }
     709     9804490 :         else if (*s == '\\')
     710             :         {
     711             :             /* OK, we have an escape character. */
     712         488 :             s++;
     713         488 :             len++;
     714         488 :             if (len >= lex->input_length)
     715             :             {
     716           0 :                 lex->token_terminator = s;
     717           0 :                 return JSON_INVALID_TOKEN;
     718             :             }
     719         488 :             else if (*s == 'u')
     720             :             {
     721             :                 int         i;
     722         216 :                 int         ch = 0;
     723             : 
     724        1024 :                 for (i = 1; i <= 4; i++)
     725             :                 {
     726         832 :                     s++;
     727         832 :                     len++;
     728         832 :                     if (len >= lex->input_length)
     729             :                     {
     730           0 :                         lex->token_terminator = s;
     731           0 :                         return JSON_INVALID_TOKEN;
     732             :                     }
     733         832 :                     else if (*s >= '0' && *s <= '9')
     734         532 :                         ch = (ch * 16) + (*s - '0');
     735         300 :                     else if (*s >= 'a' && *s <= 'f')
     736         260 :                         ch = (ch * 16) + (*s - 'a') + 10;
     737          40 :                     else if (*s >= 'A' && *s <= 'F')
     738          16 :                         ch = (ch * 16) + (*s - 'A') + 10;
     739             :                     else
     740             :                     {
     741          24 :                         lex->token_terminator = s + pg_encoding_mblen(lex->input_encoding, s);
     742          24 :                         return JSON_UNICODE_ESCAPE_FORMAT;
     743             :                     }
     744             :                 }
     745         192 :                 if (lex->strval != NULL)
     746             :                 {
     747             :                     /*
     748             :                      * Combine surrogate pairs.
     749             :                      */
     750         120 :                     if (is_utf16_surrogate_first(ch))
     751             :                     {
     752          40 :                         if (hi_surrogate != -1)
     753           8 :                             return JSON_UNICODE_HIGH_SURROGATE;
     754          32 :                         hi_surrogate = ch;
     755          32 :                         continue;
     756             :                     }
     757          80 :                     else if (is_utf16_surrogate_second(ch))
     758             :                     {
     759          32 :                         if (hi_surrogate == -1)
     760          16 :                             return JSON_UNICODE_LOW_SURROGATE;
     761          16 :                         ch = surrogate_pair_to_codepoint(hi_surrogate, ch);
     762          16 :                         hi_surrogate = -1;
     763             :                     }
     764             : 
     765          64 :                     if (hi_surrogate != -1)
     766           0 :                         return JSON_UNICODE_LOW_SURROGATE;
     767             : 
     768             :                     /*
     769             :                      * Reject invalid cases.  We can't have a value above
     770             :                      * 0xFFFF here (since we only accepted 4 hex digits
     771             :                      * above), so no need to test for out-of-range chars.
     772             :                      */
     773          64 :                     if (ch == 0)
     774             :                     {
     775             :                         /* We can't allow this, since our TEXT type doesn't */
     776          16 :                         return JSON_UNICODE_CODE_POINT_ZERO;
     777             :                     }
     778             : 
     779             :                     /*
     780             :                      * Add the represented character to lex->strval.  In the
     781             :                      * backend, we can let pg_unicode_to_server() handle any
     782             :                      * required character set conversion; in frontend, we can
     783             :                      * only deal with trivial conversions.
     784             :                      *
     785             :                      * Note: pg_unicode_to_server() will throw an error for a
     786             :                      * conversion failure, rather than returning a failure
     787             :                      * indication.  That seems OK.
     788             :                      */
     789             : #ifndef FRONTEND
     790             :                     {
     791             :                         char        cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
     792             : 
     793          48 :                         pg_unicode_to_server(ch, (unsigned char *) cbuf);
     794          48 :                         appendStringInfoString(lex->strval, cbuf);
     795             :                     }
     796             : #else
     797           0 :                     if (lex->input_encoding == PG_UTF8)
     798             :                     {
     799             :                         /* OK, we can map the code point to UTF8 easily */
     800             :                         char        utf8str[5];
     801             :                         int         utf8len;
     802             : 
     803           0 :                         unicode_to_utf8(ch, (unsigned char *) utf8str);
     804           0 :                         utf8len = pg_utf_mblen((unsigned char *) utf8str);
     805           0 :                         appendBinaryStringInfo(lex->strval, utf8str, utf8len);
     806             :                     }
     807           0 :                     else if (ch <= 0x007f)
     808             :                     {
     809             :                         /* The ASCII range is the same in all encodings */
     810           0 :                         appendStringInfoChar(lex->strval, (char) ch);
     811             :                     }
     812             :                     else
     813           0 :                         return JSON_UNICODE_HIGH_ESCAPE;
     814             : #endif                          /* FRONTEND */
     815             :                 }
     816             :             }
     817         272 :             else if (lex->strval != NULL)
     818             :             {
     819         200 :                 if (hi_surrogate != -1)
     820           0 :                     return JSON_UNICODE_LOW_SURROGATE;
     821             : 
     822         200 :                 switch (*s)
     823             :                 {
     824         136 :                     case '"':
     825             :                     case '\\':
     826             :                     case '/':
     827         136 :                         appendStringInfoChar(lex->strval, *s);
     828         136 :                         break;
     829          24 :                     case 'b':
     830          24 :                         appendStringInfoChar(lex->strval, '\b');
     831          24 :                         break;
     832           0 :                     case 'f':
     833           0 :                         appendStringInfoChar(lex->strval, '\f');
     834           0 :                         break;
     835          36 :                     case 'n':
     836          36 :                         appendStringInfoChar(lex->strval, '\n');
     837          36 :                         break;
     838           0 :                     case 'r':
     839           0 :                         appendStringInfoChar(lex->strval, '\r');
     840           0 :                         break;
     841           0 :                     case 't':
     842           0 :                         appendStringInfoChar(lex->strval, '\t');
     843           0 :                         break;
     844           4 :                     default:
     845             :                         /* Not a valid string escape, so signal error. */
     846           4 :                         lex->token_start = s;
     847           4 :                         lex->token_terminator = s + pg_encoding_mblen(lex->input_encoding, s);
     848           4 :                         return JSON_ESCAPING_INVALID;
     849             :                 }
     850             :             }
     851          72 :             else if (strchr("\"\\/bfnrt", *s) == NULL)
     852             :             {
     853             :                 /*
     854             :                  * Simpler processing if we're not bothered about de-escaping
     855             :                  *
     856             :                  * It's very tempting to remove the strchr() call here and
     857             :                  * replace it with a switch statement, but testing so far has
     858             :                  * shown it's not a performance win.
     859             :                  */
     860           4 :                 lex->token_start = s;
     861           4 :                 lex->token_terminator = s + pg_encoding_mblen(lex->input_encoding, s);
     862           4 :                 return JSON_ESCAPING_INVALID;
     863             :             }
     864             : 
     865             :         }
     866     9804002 :         else if (lex->strval != NULL)
     867             :         {
     868     9554654 :             if (hi_surrogate != -1)
     869           8 :                 return JSON_UNICODE_LOW_SURROGATE;
     870             : 
     871     9554646 :             appendStringInfoChar(lex->strval, *s);
     872             :         }
     873             : 
     874             :     }
     875             : 
     876      874600 :     if (hi_surrogate != -1)
     877           0 :         return JSON_UNICODE_LOW_SURROGATE;
     878             : 
     879             :     /* Hooray, we found the end of the string! */
     880      874600 :     lex->prev_token_terminator = lex->token_terminator;
     881      874600 :     lex->token_terminator = s + 1;
     882      874600 :     return JSON_SUCCESS;
     883             : }
     884             : 
     885             : /*
     886             :  * The next token in the input stream is known to be a number; lex it.
     887             :  *
     888             :  * In JSON, a number consists of four parts:
     889             :  *
     890             :  * (1) An optional minus sign ('-').
     891             :  *
     892             :  * (2) Either a single '0', or a string of one or more digits that does not
     893             :  *     begin with a '0'.
     894             :  *
     895             :  * (3) An optional decimal part, consisting of a period ('.') followed by
     896             :  *     one or more digits.  (Note: While this part can be omitted
     897             :  *     completely, it's not OK to have only the decimal point without
     898             :  *     any digits afterwards.)
     899             :  *
     900             :  * (4) An optional exponent part, consisting of 'e' or 'E', optionally
     901             :  *     followed by '+' or '-', followed by one or more digits.  (Note:
     902             :  *     As with the decimal part, if 'e' or 'E' is present, it must be
     903             :  *     followed by at least one digit.)
     904             :  *
     905             :  * The 's' argument to this function points to the ostensible beginning
     906             :  * of part 2 - i.e. the character after any optional minus sign, or the
     907             :  * first character of the string if there is none.
     908             :  *
     909             :  * If num_err is not NULL, we return an error flag to *num_err rather than
     910             :  * raising an error for a badly-formed number.  Also, if total_len is not NULL
     911             :  * the distance from lex->input to the token end+1 is returned to *total_len.
     912             :  */
     913             : static inline JsonParseErrorType
     914      157110 : json_lex_number(JsonLexContext *lex, char *s,
     915             :                 bool *num_err, int *total_len)
     916             : {
     917      157110 :     bool        error = false;
     918      157110 :     int         len = s - lex->input;
     919             : 
     920             :     /* Part (1): leading sign indicator. */
     921             :     /* Caller already did this for us; so do nothing. */
     922             : 
     923             :     /* Part (2): parse main digit string. */
     924      157110 :     if (len < lex->input_length && *s == '0')
     925             :     {
     926       25022 :         s++;
     927       25022 :         len++;
     928             :     }
     929      264162 :     else if (len < lex->input_length && *s >= '1' && *s <= '9')
     930             :     {
     931             :         do
     932             :         {
     933      445814 :             s++;
     934      445814 :             len++;
     935      445814 :         } while (len < lex->input_length && *s >= '0' && *s <= '9');
     936             :     }
     937             :     else
     938          14 :         error = true;
     939             : 
     940             :     /* Part (3): parse optional decimal portion. */
     941      157110 :     if (len < lex->input_length && *s == '.')
     942             :     {
     943       25072 :         s++;
     944       25072 :         len++;
     945       25072 :         if (len == lex->input_length || *s < '0' || *s > '9')
     946           8 :             error = true;
     947             :         else
     948             :         {
     949             :             do
     950             :             {
     951       61680 :                 s++;
     952       61680 :                 len++;
     953       61680 :             } while (len < lex->input_length && *s >= '0' && *s <= '9');
     954             :         }
     955             :     }
     956             : 
     957             :     /* Part (4): parse optional exponent. */
     958      157110 :     if (len < lex->input_length && (*s == 'e' || *s == 'E'))
     959             :     {
     960          42 :         s++;
     961          42 :         len++;
     962          42 :         if (len < lex->input_length && (*s == '+' || *s == '-'))
     963             :         {
     964          10 :             s++;
     965          10 :             len++;
     966             :         }
     967          42 :         if (len == lex->input_length || *s < '0' || *s > '9')
     968           8 :             error = true;
     969             :         else
     970             :         {
     971             :             do
     972             :             {
     973          88 :                 s++;
     974          88 :                 len++;
     975          88 :             } while (len < lex->input_length && *s >= '0' && *s <= '9');
     976             :         }
     977             :     }
     978             : 
     979             :     /*
     980             :      * Check for trailing garbage.  As in json_lex(), any alphanumeric stuff
     981             :      * here should be considered part of the token for error-reporting
     982             :      * purposes.
     983             :      */
     984      157306 :     for (; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*s); s++, len++)
     985         196 :         error = true;
     986             : 
     987      157110 :     if (total_len != NULL)
     988        1590 :         *total_len = len;
     989             : 
     990      157110 :     if (num_err != NULL)
     991             :     {
     992             :         /* let the caller handle any error */
     993        1590 :         *num_err = error;
     994             :     }
     995             :     else
     996             :     {
     997             :         /* return token endpoint */
     998      155520 :         lex->prev_token_terminator = lex->token_terminator;
     999      155520 :         lex->token_terminator = s;
    1000             :         /* handle error if any */
    1001      155520 :         if (error)
    1002          32 :             return JSON_INVALID_TOKEN;
    1003             :     }
    1004             : 
    1005      157078 :     return JSON_SUCCESS;
    1006             : }
    1007             : 
    1008             : /*
    1009             :  * Report a parse error.
    1010             :  *
    1011             :  * lex->token_start and lex->token_terminator must identify the current token.
    1012             :  */
    1013             : static JsonParseErrorType
    1014         106 : report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
    1015             : {
    1016             :     /* Handle case where the input ended prematurely. */
    1017         106 :     if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END)
    1018          34 :         return JSON_EXPECTED_MORE;
    1019             : 
    1020             :     /* Otherwise choose the error type based on the parsing context. */
    1021          72 :     switch (ctx)
    1022             :     {
    1023          16 :         case JSON_PARSE_END:
    1024          16 :             return JSON_EXPECTED_END;
    1025          16 :         case JSON_PARSE_VALUE:
    1026          16 :             return JSON_EXPECTED_JSON;
    1027           8 :         case JSON_PARSE_STRING:
    1028           8 :             return JSON_EXPECTED_STRING;
    1029           0 :         case JSON_PARSE_ARRAY_START:
    1030           0 :             return JSON_EXPECTED_ARRAY_FIRST;
    1031           0 :         case JSON_PARSE_ARRAY_NEXT:
    1032           0 :             return JSON_EXPECTED_ARRAY_NEXT;
    1033           8 :         case JSON_PARSE_OBJECT_START:
    1034           8 :             return JSON_EXPECTED_OBJECT_FIRST;
    1035          16 :         case JSON_PARSE_OBJECT_LABEL:
    1036          16 :             return JSON_EXPECTED_COLON;
    1037           8 :         case JSON_PARSE_OBJECT_NEXT:
    1038           8 :             return JSON_EXPECTED_OBJECT_NEXT;
    1039           0 :         case JSON_PARSE_OBJECT_COMMA:
    1040           0 :             return JSON_EXPECTED_STRING;
    1041             :     }
    1042             : 
    1043             :     /*
    1044             :      * We don't use a default: case, so that the compiler will warn about
    1045             :      * unhandled enum values.  But this needs to be here anyway to cover the
    1046             :      * possibility of an incorrect input.
    1047             :      */
    1048           0 :     json_log_and_abort("unexpected json parse state: %d", (int) ctx);
    1049             :     return JSON_SUCCESS;        /* silence stupider compilers */
    1050             : }
    1051             : 
    1052             : /*
    1053             :  * Construct a detail message for a JSON error.
    1054             :  */
    1055             : char *
    1056         272 : json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
    1057             : {
    1058         272 :     switch (error)
    1059             :     {
    1060           0 :         case JSON_SUCCESS:
    1061             :             /* fall through to the error code after switch */
    1062           0 :             break;
    1063           8 :         case JSON_ESCAPING_INVALID:
    1064           8 :             return psprintf(_("Escape sequence \"\\%s\" is invalid."),
    1065             :                             extract_token(lex));
    1066           8 :         case JSON_ESCAPING_REQUIRED:
    1067           8 :             return psprintf(_("Character with value 0x%02x must be escaped."),
    1068           8 :                             (unsigned char) *(lex->token_terminator));
    1069          16 :         case JSON_EXPECTED_END:
    1070          16 :             return psprintf(_("Expected end of input, but found \"%s\"."),
    1071             :                             extract_token(lex));
    1072           0 :         case JSON_EXPECTED_ARRAY_FIRST:
    1073           0 :             return psprintf(_("Expected array element or \"]\", but found \"%s\"."),
    1074             :                             extract_token(lex));
    1075           0 :         case JSON_EXPECTED_ARRAY_NEXT:
    1076           0 :             return psprintf(_("Expected \",\" or \"]\", but found \"%s\"."),
    1077             :                             extract_token(lex));
    1078          16 :         case JSON_EXPECTED_COLON:
    1079          16 :             return psprintf(_("Expected \":\", but found \"%s\"."),
    1080             :                             extract_token(lex));
    1081          16 :         case JSON_EXPECTED_JSON:
    1082          16 :             return psprintf(_("Expected JSON value, but found \"%s\"."),
    1083             :                             extract_token(lex));
    1084          34 :         case JSON_EXPECTED_MORE:
    1085          34 :             return _("The input string ended unexpectedly.");
    1086           8 :         case JSON_EXPECTED_OBJECT_FIRST:
    1087           8 :             return psprintf(_("Expected string or \"}\", but found \"%s\"."),
    1088             :                             extract_token(lex));
    1089           8 :         case JSON_EXPECTED_OBJECT_NEXT:
    1090           8 :             return psprintf(_("Expected \",\" or \"}\", but found \"%s\"."),
    1091             :                             extract_token(lex));
    1092           8 :         case JSON_EXPECTED_STRING:
    1093           8 :             return psprintf(_("Expected string, but found \"%s\"."),
    1094             :                             extract_token(lex));
    1095          78 :         case JSON_INVALID_TOKEN:
    1096          78 :             return psprintf(_("Token \"%s\" is invalid."),
    1097             :                             extract_token(lex));
    1098          16 :         case JSON_UNICODE_CODE_POINT_ZERO:
    1099          16 :             return _("\\u0000 cannot be converted to text.");
    1100          24 :         case JSON_UNICODE_ESCAPE_FORMAT:
    1101          24 :             return _("\"\\u\" must be followed by four hexadecimal digits.");
    1102           0 :         case JSON_UNICODE_HIGH_ESCAPE:
    1103             :             /* note: this case is only reachable in frontend not backend */
    1104           0 :             return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
    1105           8 :         case JSON_UNICODE_HIGH_SURROGATE:
    1106           8 :             return _("Unicode high surrogate must not follow a high surrogate.");
    1107          24 :         case JSON_UNICODE_LOW_SURROGATE:
    1108          24 :             return _("Unicode low surrogate must follow a high surrogate.");
    1109             :     }
    1110             : 
    1111             :     /*
    1112             :      * We don't use a default: case, so that the compiler will warn about
    1113             :      * unhandled enum values.  But this needs to be here anyway to cover the
    1114             :      * possibility of an incorrect input.
    1115             :      */
    1116           0 :     json_log_and_abort("unexpected json parse error type: %d", (int) error);
    1117             :     return NULL;                /* silence stupider compilers */
    1118             : }
    1119             : 
    1120             : /*
    1121             :  * Extract the current token from a lexing context, for error reporting.
    1122             :  */
    1123             : static char *
    1124         158 : extract_token(JsonLexContext *lex)
    1125             : {
    1126         158 :     int         toklen = lex->token_terminator - lex->token_start;
    1127         158 :     char       *token = palloc(toklen + 1);
    1128             : 
    1129         158 :     memcpy(token, lex->token_start, toklen);
    1130         158 :     token[toklen] = '\0';
    1131         158 :     return token;
    1132             : }

Generated by: LCOV version 1.13