From 919929c2aa6f78d50866484db6552cb3db381056 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 18 Jun 2024 13:42:23 +0200 Subject: [PATCH 2/3] jsonapi: Use const char * Apply const qualifiers to char * arguments and fields throughout the jsonapi. This allows the top-level APIs such as pg_parse_json_incremental() to declare their input argument as const. It also gets rid of a few unconstify() calls. --- src/backend/utils/adt/jsonfuncs.c | 37 ++++++++++++++++--------------- src/common/jsonapi.c | 26 +++++++++++----------- src/include/common/jsonapi.h | 14 ++++++------ 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 83125b06a43..2d7fe687d67 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -86,7 +86,7 @@ typedef struct GetState { JsonLexContext *lex; text *tresult; - char *result_start; + const char *result_start; bool normalize_results; bool next_scalar; int npath; /* length of each path-related array */ @@ -111,7 +111,7 @@ typedef struct EachState Tuplestorestate *tuple_store; TupleDesc ret_tdesc; MemoryContext tmp_cxt; - char *result_start; + const char *result_start; bool normalize_results; bool next_scalar; char *normalized_scalar; @@ -125,7 +125,7 @@ typedef struct ElementsState Tuplestorestate *tuple_store; TupleDesc ret_tdesc; MemoryContext tmp_cxt; - char *result_start; + const char *result_start; bool normalize_results; bool next_scalar; char *normalized_scalar; @@ -138,7 +138,7 @@ typedef struct JHashState const char *function_name; HTAB *hash; char *saved_scalar; - char *save_json_start; + const char *save_json_start; JsonTokenType saved_token_type; } JHashState; @@ -247,7 +247,7 @@ typedef struct PopulateRecordsetState const char *function_name; HTAB *json_hash; char *saved_scalar; - char *save_json_start; + const char *save_json_start; JsonTokenType saved_token_type; Tuplestorestate *tuple_store; HeapTupleHeader rec; @@ -273,7 +273,7 @@ typedef struct PopulateArrayState { JsonLexContext *lex; /* json lexer */ PopulateArrayContext *ctx; /* context */ - char *element_start; /* start of the current array element */ + const char *element_start; /* start of the current array element */ char *element_scalar; /* current array element token if it is a * scalar */ JsonTokenType element_type; /* current array element type */ @@ -295,7 +295,7 @@ typedef struct JsValue { struct { - char *str; /* json string */ + const char *str; /* json string */ int len; /* json string length or -1 if null-terminated */ JsonTokenType type; /* json type */ } json; /* json value */ @@ -390,7 +390,7 @@ static JsonParseErrorType elements_array_element_end(void *state, bool isnull); static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype); /* turn a json object into a hash table */ -static HTAB *get_json_object_as_hash(char *json, int len, const char *funcname, +static HTAB *get_json_object_as_hash(const char *json, int len, const char *funcname, Node *escontext); /* semantic actions for populate_array_json */ @@ -456,7 +456,7 @@ static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod, static RecordIOData *allocate_record_info(MemoryContext mcxt, int ncolumns); static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv); static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj); -static bool populate_array_json(PopulateArrayContext *ctx, char *json, int len); +static bool populate_array_json(PopulateArrayContext *ctx, const char *json, int len); static bool populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim); static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim); @@ -1181,7 +1181,7 @@ get_object_end(void *state) if (lex_level == 0 && _state->npath == 0) { /* Special case: return the entire object */ - char *start = _state->result_start; + const char *start = _state->result_start; int len = _state->lex->prev_token_terminator - start; _state->tresult = cstring_to_text_with_len(start, len); @@ -1275,7 +1275,7 @@ get_object_field_end(void *state, char *fname, bool isnull) _state->tresult = (text *) NULL; else { - char *start = _state->result_start; + const char *start = _state->result_start; int len = _state->lex->prev_token_terminator - start; _state->tresult = cstring_to_text_with_len(start, len); @@ -1337,7 +1337,7 @@ get_array_end(void *state) if (lex_level == 0 && _state->npath == 0) { /* Special case: return the entire array */ - char *start = _state->result_start; + const char *start = _state->result_start; int len = _state->lex->prev_token_terminator - start; _state->tresult = cstring_to_text_with_len(start, len); @@ -1426,7 +1426,7 @@ get_array_element_end(void *state, bool isnull) _state->tresult = (text *) NULL; else { - char *start = _state->result_start; + const char *start = _state->result_start; int len = _state->lex->prev_token_terminator - start; _state->tresult = cstring_to_text_with_len(start, len); @@ -1463,7 +1463,7 @@ get_scalar(void *state, char *token, JsonTokenType tokentype) * scalar token, but not whitespace before it. Probably not worth * doing our own space-skipping to avoid that. */ - char *start = _state->lex->input; + const char *start = _state->lex->input; int len = _state->lex->prev_token_terminator - start; _state->tresult = cstring_to_text_with_len(start, len); @@ -2782,7 +2782,7 @@ populate_array_scalar(void *_state, char *token, JsonTokenType tokentype) * Returns false if an error occurs when parsing. */ static bool -populate_array_json(PopulateArrayContext *ctx, char *json, int len) +populate_array_json(PopulateArrayContext *ctx, const char *json, int len) { PopulateArrayState state; JsonSemAction sem; @@ -3123,7 +3123,7 @@ populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv, { Datum res; char *str = NULL; - char *json = NULL; + const char *json = NULL; if (jsv->is_json) { @@ -3139,7 +3139,8 @@ populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv, str[len] = '\0'; } else - str = json; /* string is already null-terminated */ + str = unconstify(char *, json); /* string is already + * null-terminated */ /* If converting to json/jsonb, make string into valid JSON literal */ if ((typid == JSONOID || typid == JSONBOID) && @@ -3784,7 +3785,7 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, * Returns the hash table if the json is parsed successfully, NULL otherwise. */ static HTAB * -get_json_object_as_hash(char *json, int len, const char *funcname, +get_json_object_as_hash(const char *json, int len, const char *funcname, Node *escontext) { HASHCTL ctl; diff --git a/src/common/jsonapi.c b/src/common/jsonapi.c index f71c1c54b2a..0c6374b0fc2 100644 --- a/src/common/jsonapi.c +++ b/src/common/jsonapi.c @@ -211,7 +211,7 @@ static td_entry td_parser_table[JSON_NUM_NONTERMINALS][JSON_NUM_TERMINALS] = static char JSON_PROD_GOAL[] = {JSON_TOKEN_END, JSON_NT_JSON, 0}; static inline JsonParseErrorType json_lex_string(JsonLexContext *lex); -static inline JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s, +static inline JsonParseErrorType json_lex_number(JsonLexContext *lex, const char *s, bool *num_err, size_t *total_len); static inline JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem); static JsonParseErrorType parse_object_field(JsonLexContext *lex, JsonSemAction *sem); @@ -290,12 +290,12 @@ IsValidJsonNumber(const char *str, size_t len) */ if (*str == '-') { - dummy_lex.input = unconstify(char *, str) + 1; + dummy_lex.input = str + 1; dummy_lex.input_length = len - 1; } else { - dummy_lex.input = unconstify(char *, str); + dummy_lex.input = str; dummy_lex.input_length = len; } @@ -323,7 +323,7 @@ IsValidJsonNumber(const char *str, size_t len) * cleanup. */ JsonLexContext * -makeJsonLexContextCstringLen(JsonLexContext *lex, char *json, +makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes) { if (lex == NULL) @@ -649,7 +649,7 @@ json_count_array_elements(JsonLexContext *lex, int *elements) JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, JsonSemAction *sem, - char *json, + const char *json, size_t len, bool is_last) { @@ -1308,8 +1308,8 @@ parse_array(JsonLexContext *lex, JsonSemAction *sem) JsonParseErrorType json_lex(JsonLexContext *lex) { - char *s; - char *const end = lex->input + lex->input_length; + const char *s; + const char *const end = lex->input + lex->input_length; JsonParseErrorType result; if (lex->incremental && lex->inc_state->partial_completed) @@ -1593,7 +1593,7 @@ json_lex(JsonLexContext *lex) break; default: { - char *p; + const char *p; /* * We're not dealing with a string, number, legal @@ -1671,8 +1671,8 @@ json_lex(JsonLexContext *lex) static inline JsonParseErrorType json_lex_string(JsonLexContext *lex) { - char *s; - char *const end = lex->input + lex->input_length; + const char *s; + const char *const end = lex->input + lex->input_length; int hi_surrogate = -1; /* Convenience macros for error exits */ @@ -1689,7 +1689,7 @@ json_lex_string(JsonLexContext *lex) } while (0) #define FAIL_AT_CHAR_END(code) \ do { \ - char *term = s + pg_encoding_mblen(lex->input_encoding, s); \ + const char *term = s + pg_encoding_mblen(lex->input_encoding, s); \ lex->token_terminator = (term <= end) ? term : end; \ return code; \ } while (0) @@ -1854,7 +1854,7 @@ json_lex_string(JsonLexContext *lex) } else { - char *p = s; + const char *p = s; if (hi_surrogate != -1) FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE); @@ -1940,7 +1940,7 @@ json_lex_string(JsonLexContext *lex) * the distance from lex->input to the token end+1 is returned to *total_len. */ static inline JsonParseErrorType -json_lex_number(JsonLexContext *lex, char *s, +json_lex_number(JsonLexContext *lex, const char *s, bool *num_err, size_t *total_len) { bool error = false; diff --git a/src/include/common/jsonapi.h b/src/include/common/jsonapi.h index 5d3ae4e09b8..71a491d72dc 100644 --- a/src/include/common/jsonapi.h +++ b/src/include/common/jsonapi.h @@ -88,18 +88,18 @@ typedef struct JsonIncrementalState JsonIncrementalState; #define JSONLEX_FREE_STRVAL (1 << 1) typedef struct JsonLexContext { - char *input; + const char *input; size_t input_length; int input_encoding; - char *token_start; - char *token_terminator; - char *prev_token_terminator; + const char *token_start; + const char *token_terminator; + const char *prev_token_terminator; bool incremental; JsonTokenType token_type; int lex_level; bits32 flags; int line_number; /* line number, starting from 1 */ - char *line_start; /* where that line starts within input */ + const char *line_start; /* where that line starts within input */ JsonParserStack *pstack; JsonIncrementalState *inc_state; StringInfo strval; @@ -157,7 +157,7 @@ extern JsonParseErrorType pg_parse_json(JsonLexContext *lex, extern JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, JsonSemAction *sem, - char *json, + const char *json, size_t len, bool is_last); @@ -192,7 +192,7 @@ extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex, * cleanup. */ extern JsonLexContext *makeJsonLexContextCstringLen(JsonLexContext *lex, - char *json, + const char *json, size_t len, int encoding, bool need_escapes); -- 2.45.2