PostgreSQL Source Code  git master
jsonapi.h File Reference
#include "lib/stringinfo.h"
Include dependency graph for jsonapi.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  JsonLexContext
 
struct  JsonSemAction
 

Macros

#define JSONLEX_FREE_STRUCT   (1 << 0)
 
#define JSONLEX_FREE_STRVAL   (1 << 1)
 

Typedefs

typedef enum JsonTokenType JsonTokenType
 
typedef enum JsonParseErrorType JsonParseErrorType
 
typedef struct JsonParserStack JsonParserStack
 
typedef struct JsonIncrementalState JsonIncrementalState
 
typedef struct JsonLexContext JsonLexContext
 
typedef JsonParseErrorType(* json_struct_action) (void *state)
 
typedef JsonParseErrorType(* json_ofield_action) (void *state, char *fname, bool isnull)
 
typedef JsonParseErrorType(* json_aelem_action) (void *state, bool isnull)
 
typedef JsonParseErrorType(* json_scalar_action) (void *state, char *token, JsonTokenType tokentype)
 
typedef struct JsonSemAction JsonSemAction
 

Enumerations

enum  JsonTokenType {
  JSON_TOKEN_INVALID , JSON_TOKEN_STRING , JSON_TOKEN_NUMBER , JSON_TOKEN_OBJECT_START ,
  JSON_TOKEN_OBJECT_END , JSON_TOKEN_ARRAY_START , JSON_TOKEN_ARRAY_END , JSON_TOKEN_COMMA ,
  JSON_TOKEN_COLON , JSON_TOKEN_TRUE , JSON_TOKEN_FALSE , JSON_TOKEN_NULL ,
  JSON_TOKEN_END
}
 
enum  JsonParseErrorType {
  JSON_SUCCESS , JSON_INCOMPLETE , JSON_INVALID_LEXER_TYPE , JSON_NESTING_TOO_DEEP ,
  JSON_ESCAPING_INVALID , JSON_ESCAPING_REQUIRED , JSON_EXPECTED_ARRAY_FIRST , JSON_EXPECTED_ARRAY_NEXT ,
  JSON_EXPECTED_COLON , JSON_EXPECTED_END , JSON_EXPECTED_JSON , JSON_EXPECTED_MORE ,
  JSON_EXPECTED_OBJECT_FIRST , JSON_EXPECTED_OBJECT_NEXT , JSON_EXPECTED_STRING , JSON_INVALID_TOKEN ,
  JSON_UNICODE_CODE_POINT_ZERO , JSON_UNICODE_ESCAPE_FORMAT , JSON_UNICODE_HIGH_ESCAPE , JSON_UNICODE_UNTRANSLATABLE ,
  JSON_UNICODE_HIGH_SURROGATE , JSON_UNICODE_LOW_SURROGATE , JSON_SEM_ACTION_FAILED
}
 

Functions

JsonParseErrorType pg_parse_json (JsonLexContext *lex, JsonSemAction *sem)
 
JsonParseErrorType pg_parse_json_incremental (JsonLexContext *lex, JsonSemAction *sem, char *json, int len, bool is_last)
 
JsonParseErrorType json_count_array_elements (JsonLexContext *lex, int *elements)
 
JsonLexContextmakeJsonLexContextCstringLen (JsonLexContext *lex, char *json, int len, int encoding, bool need_escapes)
 
JsonLexContextmakeJsonLexContextIncremental (JsonLexContext *lex, int encoding, bool need_escapes)
 
void freeJsonLexContext (JsonLexContext *lex)
 
JsonParseErrorType json_lex (JsonLexContext *lex)
 
char * json_errdetail (JsonParseErrorType error, JsonLexContext *lex)
 
bool IsValidJsonNumber (const char *str, int len)
 

Variables

PGDLLIMPORT JsonSemAction nullSemAction
 

Macro Definition Documentation

◆ JSONLEX_FREE_STRUCT

#define JSONLEX_FREE_STRUCT   (1 << 0)

Definition at line 87 of file jsonapi.h.

◆ JSONLEX_FREE_STRVAL

#define JSONLEX_FREE_STRVAL   (1 << 1)

Definition at line 88 of file jsonapi.h.

Typedef Documentation

◆ json_aelem_action

typedef JsonParseErrorType(* json_aelem_action) (void *state, bool isnull)

Definition at line 111 of file jsonapi.h.

◆ json_ofield_action

typedef JsonParseErrorType(* json_ofield_action) (void *state, char *fname, bool isnull)

Definition at line 110 of file jsonapi.h.

◆ json_scalar_action

typedef JsonParseErrorType(* json_scalar_action) (void *state, char *token, JsonTokenType tokentype)

Definition at line 112 of file jsonapi.h.

◆ json_struct_action

typedef JsonParseErrorType(* json_struct_action) (void *state)

Definition at line 109 of file jsonapi.h.

◆ JsonIncrementalState

Definition at line 1 of file jsonapi.h.

◆ JsonLexContext

◆ JsonParseErrorType

◆ JsonParserStack

Definition at line 1 of file jsonapi.h.

◆ JsonSemAction

typedef struct JsonSemAction JsonSemAction

◆ JsonTokenType

Enumeration Type Documentation

◆ JsonParseErrorType

Enumerator
JSON_SUCCESS 
JSON_INCOMPLETE 
JSON_INVALID_LEXER_TYPE 
JSON_NESTING_TOO_DEEP 
JSON_ESCAPING_INVALID 
JSON_ESCAPING_REQUIRED 
JSON_EXPECTED_ARRAY_FIRST 
JSON_EXPECTED_ARRAY_NEXT 
JSON_EXPECTED_COLON 
JSON_EXPECTED_END 
JSON_EXPECTED_JSON 
JSON_EXPECTED_MORE 
JSON_EXPECTED_OBJECT_FIRST 
JSON_EXPECTED_OBJECT_NEXT 
JSON_EXPECTED_STRING 
JSON_INVALID_TOKEN 
JSON_UNICODE_CODE_POINT_ZERO 
JSON_UNICODE_ESCAPE_FORMAT 
JSON_UNICODE_HIGH_ESCAPE 
JSON_UNICODE_UNTRANSLATABLE 
JSON_UNICODE_HIGH_SURROGATE 
JSON_UNICODE_LOW_SURROGATE 
JSON_SEM_ACTION_FAILED 

Definition at line 36 of file jsonapi.h.

37 {
60  JSON_SEM_ACTION_FAILED, /* error should already be reported */
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:60
@ JSON_EXPECTED_ARRAY_FIRST
Definition: jsonapi.h:44
@ JSON_EXPECTED_MORE
Definition: jsonapi.h:49
@ JSON_UNICODE_HIGH_SURROGATE
Definition: jsonapi.h:58
@ JSON_EXPECTED_COLON
Definition: jsonapi.h:46
@ JSON_EXPECTED_OBJECT_FIRST
Definition: jsonapi.h:50
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:54
@ JSON_INVALID_LEXER_TYPE
Definition: jsonapi.h:40
@ JSON_EXPECTED_STRING
Definition: jsonapi.h:52
@ JSON_UNICODE_ESCAPE_FORMAT
Definition: jsonapi.h:55
@ JSON_SUCCESS
Definition: jsonapi.h:38
@ JSON_UNICODE_UNTRANSLATABLE
Definition: jsonapi.h:57
@ JSON_EXPECTED_OBJECT_NEXT
Definition: jsonapi.h:51
@ JSON_ESCAPING_REQUIRED
Definition: jsonapi.h:43
@ JSON_EXPECTED_JSON
Definition: jsonapi.h:48
@ JSON_INVALID_TOKEN
Definition: jsonapi.h:53
@ JSON_ESCAPING_INVALID
Definition: jsonapi.h:42
@ JSON_INCOMPLETE
Definition: jsonapi.h:39
@ JSON_EXPECTED_END
Definition: jsonapi.h:47
@ JSON_EXPECTED_ARRAY_NEXT
Definition: jsonapi.h:45
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:56
@ JSON_NESTING_TOO_DEEP
Definition: jsonapi.h:41
@ JSON_UNICODE_LOW_SURROGATE
Definition: jsonapi.h:59

◆ JsonTokenType

Enumerator
JSON_TOKEN_INVALID 
JSON_TOKEN_STRING 
JSON_TOKEN_NUMBER 
JSON_TOKEN_OBJECT_START 
JSON_TOKEN_OBJECT_END 
JSON_TOKEN_ARRAY_START 
JSON_TOKEN_ARRAY_END 
JSON_TOKEN_COMMA 
JSON_TOKEN_COLON 
JSON_TOKEN_TRUE 
JSON_TOKEN_FALSE 
JSON_TOKEN_NULL 
JSON_TOKEN_END 

Definition at line 19 of file jsonapi.h.

20 {
JsonTokenType
Definition: jsonapi.h:20
@ JSON_TOKEN_INVALID
Definition: jsonapi.h:21
@ JSON_TOKEN_COMMA
Definition: jsonapi.h:28
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_END
Definition: jsonapi.h:33
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_OBJECT_END
Definition: jsonapi.h:25
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ JSON_TOKEN_ARRAY_END
Definition: jsonapi.h:27
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ JSON_TOKEN_COLON
Definition: jsonapi.h:29
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26

Function Documentation

◆ freeJsonLexContext()

void freeJsonLexContext ( JsonLexContext lex)

Definition at line 482 of file jsonapi.c.

484 {
485  if (lex->flags & JSONLEX_FREE_STRVAL)
487 
488  if (lex->errormsg)
490 
491  if (lex->incremental)
492  {
494  pfree(lex->inc_state);
495  pfree(lex->pstack->prediction);
496  pfree(lex->pstack->fnames);
497  pfree(lex->pstack->fnull);
498  pfree(lex->pstack);
499  }
500 
501  if (lex->flags & JSONLEX_FREE_STRUCT)
502  pfree(lex);
#define JSONLEX_FREE_STRVAL
Definition: jsonapi.h:88
#define JSONLEX_FREE_STRUCT
Definition: jsonapi.h:87
void pfree(void *pointer)
Definition: mcxt.c:1520
void destroyStringInfo(StringInfo str)
Definition: stringinfo.c:361
StringInfoData partial_token
Definition: jsonapi.c:106
bits32 flags
Definition: jsonapi.h:100
StringInfo strval
Definition: jsonapi.h:105
JsonParserStack * pstack
Definition: jsonapi.h:103
StringInfo errormsg
Definition: jsonapi.h:106
JsonIncrementalState * inc_state
Definition: jsonapi.h:104
bool incremental
Definition: jsonapi.h:97
bool * fnull
Definition: jsonapi.c:91
char * prediction
Definition: jsonapi.c:87
char ** fnames
Definition: jsonapi.c:90

References StringInfoData::data, destroyStringInfo(), JsonLexContext::errormsg, JsonLexContext::flags, JsonParserStack::fnames, JsonParserStack::fnull, JsonLexContext::inc_state, JsonLexContext::incremental, JSONLEX_FREE_STRUCT, JSONLEX_FREE_STRVAL, JsonIncrementalState::partial_token, pfree(), JsonParserStack::prediction, JsonLexContext::pstack, and JsonLexContext::strval.

Referenced by datum_to_jsonb_internal(), each_worker(), elements_worker(), get_json_object_as_hash(), get_worker(), iterate_json_values(), json_object_keys(), json_parse_manifest(), json_parse_manifest_incremental_shutdown(), json_validate(), main(), populate_array_json(), populate_recordset_worker(), and transform_json_string_values().

◆ IsValidJsonNumber()

bool IsValidJsonNumber ( const char *  str,
int  len 
)

Definition at line 272 of file jsonapi.c.

273 {
274  bool numeric_error;
275  int total_len;
276  JsonLexContext dummy_lex;
277 
278  if (len <= 0)
279  return false;
280 
281  dummy_lex.incremental = false;
282  dummy_lex.inc_state = NULL;
283  dummy_lex.pstack = NULL;
284 
285  /*
286  * json_lex_number expects a leading '-' to have been eaten already.
287  *
288  * having to cast away the constness of str is ugly, but there's not much
289  * easy alternative.
290  */
291  if (*str == '-')
292  {
293  dummy_lex.input = unconstify(char *, str) + 1;
294  dummy_lex.input_length = len - 1;
295  }
296  else
297  {
298  dummy_lex.input = unconstify(char *, str);
299  dummy_lex.input_length = len;
300  }
301 
302  dummy_lex.token_start = dummy_lex.input;
303 
304  json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
305 
306  return (!numeric_error) && (total_len == dummy_lex.input_length);
307 }
#define unconstify(underlying_type, expr)
Definition: c.h:1245
const char * str
static JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s, bool *num_err, int *total_len)
Definition: jsonapi.c:1942
const void size_t len
char * input
Definition: jsonapi.h:91
char * token_start
Definition: jsonapi.h:94
int input_length
Definition: jsonapi.h:92

References JsonLexContext::inc_state, JsonLexContext::incremental, JsonLexContext::input, JsonLexContext::input_length, json_lex_number(), len, JsonLexContext::pstack, str, JsonLexContext::token_start, and unconstify.

Referenced by hstore_to_json_loose(), and hstore_to_jsonb_loose().

◆ json_count_array_elements()

JsonParseErrorType json_count_array_elements ( JsonLexContext lex,
int *  elements 
)

Definition at line 587 of file jsonapi.c.

589 {
590  JsonLexContext copylex;
591  int count;
592  JsonParseErrorType result;
593 
594  /*
595  * It's safe to do this with a shallow copy because the lexical routines
596  * don't scribble on the input. They do scribble on the other pointers
597  * etc, so doing this with a copy makes that safe.
598  */
599  memcpy(&copylex, lex, sizeof(JsonLexContext));
600  copylex.strval = NULL; /* not interested in values here */
601  copylex.lex_level++;
602 
603  count = 0;
604  result = lex_expect(JSON_PARSE_ARRAY_START, &copylex,
606  if (result != JSON_SUCCESS)
607  return result;
608  if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
609  {
610  while (1)
611  {
612  count++;
613  result = parse_array_element(&copylex, &nullSemAction);
614  if (result != JSON_SUCCESS)
615  return result;
616  if (copylex.token_type != JSON_TOKEN_COMMA)
617  break;
618  result = json_lex(&copylex);
619  if (result != JSON_SUCCESS)
620  return result;
621  }
622  }
623  result = lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex,
625  if (result != JSON_SUCCESS)
626  return result;
627 
628  *elements = count;
629  return JSON_SUCCESS;
@ JSON_PARSE_ARRAY_START
Definition: jsonapi.c:37
@ JSON_PARSE_ARRAY_NEXT
Definition: jsonapi.c:38
static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:1187
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:238
JsonSemAction nullSemAction
Definition: jsonapi.c:224
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:250
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:1308
int lex_level
Definition: jsonapi.h:99
JsonTokenType token_type
Definition: jsonapi.h:98

References json_lex(), JSON_PARSE_ARRAY_NEXT, JSON_PARSE_ARRAY_START, JSON_SUCCESS, JSON_TOKEN_ARRAY_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COMMA, lex_expect(), JsonLexContext::lex_level, lex_peek(), nullSemAction, parse_array_element(), JsonLexContext::strval, and JsonLexContext::token_type.

Referenced by get_array_start().

◆ json_errdetail()

char* json_errdetail ( JsonParseErrorType  error,
JsonLexContext lex 
)

Definition at line 2096 of file jsonapi.c.

2098 {
2099  if (lex->errormsg)
2100  resetStringInfo(lex->errormsg);
2101  else
2102  lex->errormsg = makeStringInfo();
2103 
2104  /*
2105  * A helper for error messages that should print the current token. The
2106  * format must contain exactly one %.*s specifier.
2107  */
2108 #define json_token_error(lex, format) \
2109  appendStringInfo((lex)->errormsg, _(format), \
2110  (int) ((lex)->token_terminator - (lex)->token_start), \
2111  (lex)->token_start);
2112 
2113  switch (error)
2114  {
2115  case JSON_INCOMPLETE:
2116  case JSON_SUCCESS:
2117  /* fall through to the error code after switch */
2118  break;
2120  if (lex->incremental)
2121  return _("Recursive descent parser cannot use incremental lexer");
2122  else
2123  return _("Incremental parser requires incremental lexer");
2124  case JSON_NESTING_TOO_DEEP:
2125  return (_("JSON nested too deep, maximum permitted depth is 6400"));
2126  case JSON_ESCAPING_INVALID:
2127  json_token_error(lex, "Escape sequence \"\\%.*s\" is invalid.");
2128  break;
2131  _("Character with value 0x%02x must be escaped."),
2132  (unsigned char) *(lex->token_terminator));
2133  break;
2134  case JSON_EXPECTED_END:
2135  json_token_error(lex, "Expected end of input, but found \"%.*s\".");
2136  break;
2138  json_token_error(lex, "Expected array element or \"]\", but found \"%.*s\".");
2139  break;
2141  json_token_error(lex, "Expected \",\" or \"]\", but found \"%.*s\".");
2142  break;
2143  case JSON_EXPECTED_COLON:
2144  json_token_error(lex, "Expected \":\", but found \"%.*s\".");
2145  break;
2146  case JSON_EXPECTED_JSON:
2147  json_token_error(lex, "Expected JSON value, but found \"%.*s\".");
2148  break;
2149  case JSON_EXPECTED_MORE:
2150  return _("The input string ended unexpectedly.");
2152  json_token_error(lex, "Expected string or \"}\", but found \"%.*s\".");
2153  break;
2155  json_token_error(lex, "Expected \",\" or \"}\", but found \"%.*s\".");
2156  break;
2157  case JSON_EXPECTED_STRING:
2158  json_token_error(lex, "Expected string, but found \"%.*s\".");
2159  break;
2160  case JSON_INVALID_TOKEN:
2161  json_token_error(lex, "Token \"%.*s\" is invalid.");
2162  break;
2164  return _("\\u0000 cannot be converted to text.");
2166  return _("\"\\u\" must be followed by four hexadecimal digits.");
2168  /* note: this case is only reachable in frontend not backend */
2169  return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
2171 
2172  /*
2173  * Note: this case is only reachable in backend and not frontend.
2174  * #ifdef it away so the frontend doesn't try to link against
2175  * backend functionality.
2176  */
2177 #ifndef FRONTEND
2178  return psprintf(_("Unicode escape value could not be translated to the server's encoding %s."),
2180 #else
2181  Assert(false);
2182  break;
2183 #endif
2185  return _("Unicode high surrogate must not follow a high surrogate.");
2187  return _("Unicode low surrogate must follow a high surrogate.");
2189  /* fall through to the error code after switch */
2190  break;
2191  }
2192 #undef json_token_error
2193 
2194  /*
2195  * We don't use a default: case, so that the compiler will warn about
2196  * unhandled enum values. But this needs to be here anyway to cover the
2197  * possibility of an incorrect input.
2198  */
2199  if (lex->errormsg->len == 0)
2201  _("unexpected json parse error type: %d"),
2202  (int) error);
2203 
2204  return lex->errormsg->data;
#define Assert(condition)
Definition: c.h:858
#define _(x)
Definition: elog.c:90
#define json_token_error(lex, format)
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static void error(void)
Definition: sql-dyntest.c:147
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
char * token_terminator
Definition: jsonapi.h:95

References _, appendStringInfo(), Assert, StringInfoData::data, error(), JsonLexContext::errormsg, GetDatabaseEncodingName(), JsonLexContext::incremental, JSON_ESCAPING_INVALID, JSON_ESCAPING_REQUIRED, JSON_EXPECTED_ARRAY_FIRST, JSON_EXPECTED_ARRAY_NEXT, JSON_EXPECTED_COLON, JSON_EXPECTED_END, JSON_EXPECTED_JSON, JSON_EXPECTED_MORE, JSON_EXPECTED_OBJECT_FIRST, JSON_EXPECTED_OBJECT_NEXT, JSON_EXPECTED_STRING, JSON_INCOMPLETE, JSON_INVALID_LEXER_TYPE, JSON_INVALID_TOKEN, JSON_NESTING_TOO_DEEP, JSON_SEM_ACTION_FAILED, JSON_SUCCESS, json_token_error, JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_ESCAPE_FORMAT, JSON_UNICODE_HIGH_ESCAPE, JSON_UNICODE_HIGH_SURROGATE, JSON_UNICODE_LOW_SURROGATE, JSON_UNICODE_UNTRANSLATABLE, StringInfoData::len, makeStringInfo(), psprintf(), resetStringInfo(), and JsonLexContext::token_terminator.

Referenced by json_errsave_error(), json_parse_manifest(), json_parse_manifest_incremental_chunk(), and main().

◆ json_lex()

JsonParseErrorType json_lex ( JsonLexContext lex)

Definition at line 1308 of file jsonapi.c.

1310 {
1311  char *s;
1312  char *const end = lex->input + lex->input_length;
1313  JsonParseErrorType result;
1314 
1315  if (lex->incremental && lex->inc_state->partial_completed)
1316  {
1317  /*
1318  * We just lexed a completed partial token on the last call, so reset
1319  * everything
1320  */
1322  lex->token_terminator = lex->input;
1323  lex->inc_state->partial_completed = false;
1324  }
1325 
1326  s = lex->token_terminator;
1327 
1328  if (lex->incremental && lex->inc_state->partial_token.len)
1329  {
1330  /*
1331  * We have a partial token. Extend it and if completed lex it by a
1332  * recursive call
1333  */
1334  StringInfo ptok = &(lex->inc_state->partial_token);
1335  int added = 0;
1336  bool tok_done = false;
1337  JsonLexContext dummy_lex;
1338  JsonParseErrorType partial_result;
1339 
1340  if (ptok->data[0] == '"')
1341  {
1342  /*
1343  * It's a string. Accumulate characters until we reach an
1344  * unescaped '"'.
1345  */
1346  int escapes = 0;
1347 
1348  for (int i = ptok->len - 1; i > 0; i--)
1349  {
1350  /* count the trailing backslashes on the partial token */
1351  if (ptok->data[i] == '\\')
1352  escapes++;
1353  else
1354  break;
1355  }
1356 
1357  for (int i = 0; i < lex->input_length; i++)
1358  {
1359  char c = lex->input[i];
1360 
1362  added++;
1363  if (c == '"' && escapes % 2 == 0)
1364  {
1365  tok_done = true;
1366  break;
1367  }
1368  if (c == '\\')
1369  escapes++;
1370  else
1371  escapes = 0;
1372  }
1373  }
1374  else
1375  {
1376  /* not a string */
1377  char c = ptok->data[0];
1378 
1379  if (c == '-' || (c >= '0' && c <= '9'))
1380  {
1381  /* for numbers look for possible numeric continuations */
1382 
1383  bool numend = false;
1384 
1385  for (int i = 0; i < lex->input_length && !numend; i++)
1386  {
1387  char cc = lex->input[i];
1388 
1389  switch (cc)
1390  {
1391  case '+':
1392  case '-':
1393  case 'e':
1394  case 'E':
1395  case '0':
1396  case '1':
1397  case '2':
1398  case '3':
1399  case '4':
1400  case '5':
1401  case '6':
1402  case '7':
1403  case '8':
1404  case '9':
1405  {
1406  appendStringInfoCharMacro(ptok, cc);
1407  added++;
1408  }
1409  break;
1410  default:
1411  numend = true;
1412  }
1413  }
1414  }
1415 
1416  /*
1417  * Add any remaining alphanumeric chars. This takes care of the
1418  * {null, false, true} literals as well as any trailing
1419  * alphanumeric junk on non-string tokens.
1420  */
1421  for (int i = added; i < lex->input_length; i++)
1422  {
1423  char cc = lex->input[i];
1424 
1425  if (JSON_ALPHANUMERIC_CHAR(cc))
1426  {
1427  appendStringInfoCharMacro(ptok, cc);
1428  added++;
1429  }
1430  else
1431  {
1432  tok_done = true;
1433  break;
1434  }
1435  }
1436  if (added == lex->input_length &&
1437  lex->inc_state->is_last_chunk)
1438  {
1439  tok_done = true;
1440  }
1441  }
1442 
1443  if (!tok_done)
1444  {
1445  /* We should have consumed the whole chunk in this case. */
1446  Assert(added == lex->input_length);
1447 
1448  if (!lex->inc_state->is_last_chunk)
1449  return JSON_INCOMPLETE;
1450 
1451  /* json_errdetail() needs access to the accumulated token. */
1452  lex->token_start = ptok->data;
1453  lex->token_terminator = ptok->data + ptok->len;
1454  return JSON_INVALID_TOKEN;
1455  }
1456 
1457  /*
1458  * Everything up to lex->input[added] has been added to the partial
1459  * token, so move the input past it.
1460  */
1461  lex->input += added;
1462  lex->input_length -= added;
1463 
1464  dummy_lex.input = dummy_lex.token_terminator =
1465  dummy_lex.line_start = ptok->data;
1466  dummy_lex.line_number = lex->line_number;
1467  dummy_lex.input_length = ptok->len;
1468  dummy_lex.input_encoding = lex->input_encoding;
1469  dummy_lex.incremental = false;
1470  dummy_lex.strval = lex->strval;
1471 
1472  partial_result = json_lex(&dummy_lex);
1473 
1474  /*
1475  * We either have a complete token or an error. In either case we need
1476  * to point to the partial token data for the semantic or error
1477  * routines. If it's not an error we'll readjust on the next call to
1478  * json_lex.
1479  */
1480  lex->token_type = dummy_lex.token_type;
1481  lex->line_number = dummy_lex.line_number;
1482 
1483  /*
1484  * We know the prev_token_terminator must be back in some previous
1485  * piece of input, so we just make it NULL.
1486  */
1487  lex->prev_token_terminator = NULL;
1488 
1489  /*
1490  * Normally token_start would be ptok->data, but it could be later,
1491  * see json_lex_string's handling of invalid escapes.
1492  */
1493  lex->token_start = dummy_lex.token_start;
1494  lex->token_terminator = dummy_lex.token_terminator;
1495  if (partial_result == JSON_SUCCESS)
1496  {
1497  /* make sure we've used all the input */
1498  if (lex->token_terminator - lex->token_start != ptok->len)
1499  {
1500  Assert(false);
1501  return JSON_INVALID_TOKEN;
1502  }
1503 
1504  lex->inc_state->partial_completed = true;
1505  }
1506  return partial_result;
1507  /* end of partial token processing */
1508  }
1509 
1510  /* Skip leading whitespace. */
1511  while (s < end && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
1512  {
1513  if (*s++ == '\n')
1514  {
1515  ++lex->line_number;
1516  lex->line_start = s;
1517  }
1518  }
1519  lex->token_start = s;
1520 
1521  /* Determine token type. */
1522  if (s >= end)
1523  {
1524  lex->token_start = NULL;
1526  lex->token_terminator = s;
1527  lex->token_type = JSON_TOKEN_END;
1528  }
1529  else
1530  {
1531  switch (*s)
1532  {
1533  /* Single-character token, some kind of punctuation mark. */
1534  case '{':
1536  lex->token_terminator = s + 1;
1538  break;
1539  case '}':
1541  lex->token_terminator = s + 1;
1543  break;
1544  case '[':
1546  lex->token_terminator = s + 1;
1548  break;
1549  case ']':
1551  lex->token_terminator = s + 1;
1553  break;
1554  case ',':
1556  lex->token_terminator = s + 1;
1558  break;
1559  case ':':
1561  lex->token_terminator = s + 1;
1563  break;
1564  case '"':
1565  /* string */
1566  result = json_lex_string(lex);
1567  if (result != JSON_SUCCESS)
1568  return result;
1570  break;
1571  case '-':
1572  /* Negative number. */
1573  result = json_lex_number(lex, s + 1, NULL, NULL);
1574  if (result != JSON_SUCCESS)
1575  return result;
1577  break;
1578  case '0':
1579  case '1':
1580  case '2':
1581  case '3':
1582  case '4':
1583  case '5':
1584  case '6':
1585  case '7':
1586  case '8':
1587  case '9':
1588  /* Positive number. */
1589  result = json_lex_number(lex, s, NULL, NULL);
1590  if (result != JSON_SUCCESS)
1591  return result;
1593  break;
1594  default:
1595  {
1596  char *p;
1597 
1598  /*
1599  * We're not dealing with a string, number, legal
1600  * punctuation mark, or end of string. The only legal
1601  * tokens we might find here are true, false, and null,
1602  * but for error reporting purposes we scan until we see a
1603  * non-alphanumeric character. That way, we can report
1604  * the whole word as an unexpected token, rather than just
1605  * some unintuitive prefix thereof.
1606  */
1607  for (p = s; p < end && JSON_ALPHANUMERIC_CHAR(*p); p++)
1608  /* skip */ ;
1609 
1610  /*
1611  * We got some sort of unexpected punctuation or an
1612  * otherwise unexpected character, so just complain about
1613  * that one character.
1614  */
1615  if (p == s)
1616  {
1618  lex->token_terminator = s + 1;
1619  return JSON_INVALID_TOKEN;
1620  }
1621 
1622  if (lex->incremental && !lex->inc_state->is_last_chunk &&
1623  p == lex->input + lex->input_length)
1624  {
1626  &(lex->inc_state->partial_token), s, end - s);
1627  return JSON_INCOMPLETE;
1628  }
1629 
1630  /*
1631  * We've got a real alphanumeric token here. If it
1632  * happens to be true, false, or null, all is well. If
1633  * not, error out.
1634  */
1636  lex->token_terminator = p;
1637  if (p - s == 4)
1638  {
1639  if (memcmp(s, "true", 4) == 0)
1640  lex->token_type = JSON_TOKEN_TRUE;
1641  else if (memcmp(s, "null", 4) == 0)
1642  lex->token_type = JSON_TOKEN_NULL;
1643  else
1644  return JSON_INVALID_TOKEN;
1645  }
1646  else if (p - s == 5 && memcmp(s, "false", 5) == 0)
1648  else
1649  return JSON_INVALID_TOKEN;
1650  }
1651  } /* end of switch */
1652  }
1653 
1654  if (lex->incremental && lex->token_type == JSON_TOKEN_END && !lex->inc_state->is_last_chunk)
1655  return JSON_INCOMPLETE;
1656  else
1657  return JSON_SUCCESS;
int i
Definition: isn.c:73
static JsonParseErrorType json_lex_string(JsonLexContext *lex)
Definition: jsonapi.c:1671
#define JSON_ALPHANUMERIC_CHAR(c)
Definition: jsonapi.c:259
char * c
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
int input_encoding
Definition: jsonapi.h:93
char * prev_token_terminator
Definition: jsonapi.h:96
char * line_start
Definition: jsonapi.h:102
int line_number
Definition: jsonapi.h:101

References appendBinaryStringInfo(), appendStringInfoCharMacro, Assert, StringInfoData::data, i, JsonLexContext::inc_state, JsonLexContext::incremental, JsonLexContext::input, JsonLexContext::input_encoding, JsonLexContext::input_length, JsonIncrementalState::is_last_chunk, JSON_ALPHANUMERIC_CHAR, JSON_INCOMPLETE, JSON_INVALID_TOKEN, json_lex_number(), json_lex_string(), JSON_SUCCESS, JSON_TOKEN_ARRAY_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COLON, JSON_TOKEN_COMMA, JSON_TOKEN_END, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_OBJECT_END, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, StringInfoData::len, JsonLexContext::line_number, JsonLexContext::line_start, JsonIncrementalState::partial_completed, JsonIncrementalState::partial_token, JsonLexContext::prev_token_terminator, resetStringInfo(), JsonLexContext::strval, JsonLexContext::token_start, JsonLexContext::token_terminator, and JsonLexContext::token_type.

Referenced by json_count_array_elements(), json_get_first_token(), json_typeof(), lex_expect(), parse_array(), parse_object(), parse_object_field(), parse_scalar(), pg_parse_json(), and pg_parse_json_incremental().

◆ makeJsonLexContextCstringLen()

JsonLexContext* makeJsonLexContextCstringLen ( JsonLexContext lex,
char *  json,
int  len,
int  encoding,
bool  need_escapes 
)

Definition at line 326 of file jsonapi.c.

328 {
329  if (lex == NULL)
330  {
331  lex = palloc0(sizeof(JsonLexContext));
332  lex->flags |= JSONLEX_FREE_STRUCT;
333  }
334  else
335  memset(lex, 0, sizeof(JsonLexContext));
336 
337  lex->errormsg = NULL;
338  lex->input = lex->token_terminator = lex->line_start = json;
339  lex->line_number = 1;
340  lex->input_length = len;
341  lex->input_encoding = encoding;
342  if (need_escapes)
343  {
344  lex->strval = makeStringInfo();
345  lex->flags |= JSONLEX_FREE_STRVAL;
346  }
347 
348  return lex;
349 }
void * palloc0(Size size)
Definition: mcxt.c:1346
int32 encoding
Definition: pg_database.h:41

References encoding, JsonLexContext::errormsg, JsonLexContext::flags, JsonLexContext::input, JsonLexContext::input_encoding, JsonLexContext::input_length, JSONLEX_FREE_STRUCT, JSONLEX_FREE_STRVAL, len, JsonLexContext::line_number, JsonLexContext::line_start, makeStringInfo(), palloc0(), JsonLexContext::strval, and JsonLexContext::token_terminator.

Referenced by get_json_object_as_hash(), json_parse_manifest(), json_recv(), jsonb_from_cstring(), main(), makeJsonLexContext(), and populate_array_json().

◆ makeJsonLexContextIncremental()

JsonLexContext* makeJsonLexContextIncremental ( JsonLexContext lex,
int  encoding,
bool  need_escapes 
)

Definition at line 366 of file jsonapi.c.

369 {
370  if (lex == NULL)
371  {
372  lex = palloc0(sizeof(JsonLexContext));
373  lex->flags |= JSONLEX_FREE_STRUCT;
374  }
375  else
376  memset(lex, 0, sizeof(JsonLexContext));
377 
378  lex->line_number = 1;
379  lex->input_encoding = encoding;
380  lex->incremental = true;
381  lex->inc_state = palloc0(sizeof(JsonIncrementalState));
383  lex->pstack = palloc(sizeof(JsonParserStack));
386  lex->pstack->pred_index = 0;
387  lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *));
388  lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool));
389  if (need_escapes)
390  {
391  lex->strval = makeStringInfo();
392  lex->flags |= JSONLEX_FREE_STRVAL;
393  }
394  return lex;
#define JS_MAX_PROD_LEN
Definition: jsonapi.c:362
#define JS_STACK_CHUNK_SIZE
Definition: jsonapi.c:361
void * palloc(Size size)
Definition: mcxt.c:1316
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
int stack_size
Definition: jsonapi.c:86
int pred_index
Definition: jsonapi.c:88

References encoding, JsonLexContext::flags, JsonParserStack::fnames, JsonParserStack::fnull, JsonLexContext::inc_state, JsonLexContext::incremental, initStringInfo(), JsonLexContext::input_encoding, JS_MAX_PROD_LEN, JS_STACK_CHUNK_SIZE, JSONLEX_FREE_STRUCT, JSONLEX_FREE_STRVAL, JsonLexContext::line_number, makeStringInfo(), palloc(), palloc0(), JsonIncrementalState::partial_token, JsonParserStack::pred_index, JsonParserStack::prediction, JsonLexContext::pstack, JsonParserStack::stack_size, and JsonLexContext::strval.

Referenced by json_parse_manifest_incremental_init(), and main().

◆ pg_parse_json()

JsonParseErrorType pg_parse_json ( JsonLexContext lex,
JsonSemAction sem 
)

Definition at line 521 of file jsonapi.c.

523 {
524 #ifdef FORCE_JSON_PSTACK
525 
526  lex->incremental = true;
527  lex->inc_state = palloc0(sizeof(JsonIncrementalState));
528 
529  /*
530  * We don't need partial token processing, there is only one chunk. But we
531  * still need to init the partial token string so that freeJsonLexContext
532  * works.
533  */
535  lex->pstack = palloc(sizeof(JsonParserStack));
538  lex->pstack->pred_index = 0;
539  lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *));
540  lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool));
541 
542  return pg_parse_json_incremental(lex, sem, lex->input, lex->input_length, true);
543 
544 #else
545 
546  JsonTokenType tok;
547  JsonParseErrorType result;
548 
549  if (lex->incremental)
551 
552  /* get the initial token */
553  result = json_lex(lex);
554  if (result != JSON_SUCCESS)
555  return result;
556 
557  tok = lex_peek(lex);
558 
559  /* parse by recursive descent */
560  switch (tok)
561  {
563  result = parse_object(lex, sem);
564  break;
566  result = parse_array(lex, sem);
567  break;
568  default:
569  result = parse_scalar(lex, sem); /* json can be a bare scalar */
570  }
571 
572  if (result == JSON_SUCCESS)
573  result = lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
574 
575  return result;
576 #endif
@ JSON_PARSE_END
Definition: jsonapi.c:43
JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, JsonSemAction *sem, char *json, int len, bool is_last)
Definition: jsonapi.c:649
static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:1113
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:1231
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:1007
JsonSemAction sem

References JsonParserStack::fnames, JsonParserStack::fnull, JsonLexContext::inc_state, JsonLexContext::incremental, initStringInfo(), JsonLexContext::input, JsonLexContext::input_length, JS_MAX_PROD_LEN, JS_STACK_CHUNK_SIZE, JSON_INVALID_LEXER_TYPE, json_lex(), JSON_PARSE_END, JSON_SUCCESS, JSON_TOKEN_ARRAY_START, JSON_TOKEN_END, JSON_TOKEN_OBJECT_START, lex_expect(), lex_peek(), palloc(), palloc0(), parse_array(), parse_object(), parse_scalar(), JsonIncrementalState::partial_token, pg_parse_json_incremental(), JsonParserStack::pred_index, JsonParserStack::prediction, JsonLexContext::pstack, sem, and JsonParserStack::stack_size.

Referenced by json_parse_manifest(), json_validate(), main(), and pg_parse_json_or_errsave().

◆ pg_parse_json_incremental()

JsonParseErrorType pg_parse_json_incremental ( JsonLexContext lex,
JsonSemAction sem,
char *  json,
int  len,
bool  is_last 
)

Definition at line 649 of file jsonapi.c.

655 {
656  JsonTokenType tok;
657  JsonParseErrorType result;
659  JsonParserStack *pstack = lex->pstack;
660 
661 
662  if (!lex->incremental)
664 
665  lex->input = lex->token_terminator = lex->line_start = json;
666  lex->input_length = len;
667  lex->inc_state->is_last_chunk = is_last;
668 
669  /* get the initial token */
670  result = json_lex(lex);
671  if (result != JSON_SUCCESS)
672  return result;
673 
674  tok = lex_peek(lex);
675 
676  /* use prediction stack for incremental parsing */
677 
678  if (!have_prediction(pstack))
679  {
681 
682  push_prediction(pstack, goal);
683  }
684 
685  while (have_prediction(pstack))
686  {
687  char top = pop_prediction(pstack);
688  td_entry entry;
689 
690  /*
691  * these first two branches are the guts of the Table Driven method
692  */
693  if (top == tok)
694  {
695  /*
696  * tok can only be a terminal symbol, so top must be too. the
697  * token matches the top of the stack, so get the next token.
698  */
699  if (tok < JSON_TOKEN_END)
700  {
701  result = json_lex(lex);
702  if (result != JSON_SUCCESS)
703  return result;
704  tok = lex_peek(lex);
705  }
706  }
707  else if (IS_NT(top) && (entry = td_parser_table[OFS(top)][tok]).prod != NULL)
708  {
709  /*
710  * the token is in the director set for a production of the
711  * non-terminal at the top of the stack, so push the reversed RHS
712  * of the production onto the stack.
713  */
714  push_prediction(pstack, entry);
715  }
716  else if (IS_SEM(top))
717  {
718  /*
719  * top is a semantic action marker, so take action accordingly.
720  * It's important to have these markers in the prediction stack
721  * before any token they might need so we don't advance the token
722  * prematurely. Note in a couple of cases we need to do something
723  * both before and after the token.
724  */
725  switch (top)
726  {
727  case JSON_SEM_OSTART:
728  {
730 
731  if (lex->lex_level >= JSON_TD_MAX_STACK)
732  return JSON_NESTING_TOO_DEEP;
733 
734  if (ostart != NULL)
735  {
736  result = (*ostart) (sem->semstate);
737  if (result != JSON_SUCCESS)
738  return result;
739  }
740  inc_lex_level(lex);
741  }
742  break;
743  case JSON_SEM_OEND:
744  {
746 
747  dec_lex_level(lex);
748  if (oend != NULL)
749  {
750  result = (*oend) (sem->semstate);
751  if (result != JSON_SUCCESS)
752  return result;
753  }
754  }
755  break;
756  case JSON_SEM_ASTART:
757  {
759 
760  if (lex->lex_level >= JSON_TD_MAX_STACK)
761  return JSON_NESTING_TOO_DEEP;
762 
763  if (astart != NULL)
764  {
765  result = (*astart) (sem->semstate);
766  if (result != JSON_SUCCESS)
767  return result;
768  }
769  inc_lex_level(lex);
770  }
771  break;
772  case JSON_SEM_AEND:
773  {
775 
776  dec_lex_level(lex);
777  if (aend != NULL)
778  {
779  result = (*aend) (sem->semstate);
780  if (result != JSON_SUCCESS)
781  return result;
782  }
783  }
784  break;
786  {
787  /*
788  * all we do here is save out the field name. We have
789  * to wait to get past the ':' to see if the next
790  * value is null so we can call the semantic routine
791  */
792  char *fname = NULL;
795 
796  if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
797  {
798  fname = pstrdup(lex->strval->data);
799  }
800  set_fname(lex, fname);
801  }
802  break;
804  {
805  /*
806  * the current token should be the first token of the
807  * value
808  */
809  bool isnull = tok == JSON_TOKEN_NULL;
811 
812  set_fnull(lex, isnull);
813 
814  if (ostart != NULL)
815  {
816  char *fname = get_fname(lex);
817 
818  result = (*ostart) (sem->semstate, fname, isnull);
819  if (result != JSON_SUCCESS)
820  return result;
821  }
822  }
823  break;
824  case JSON_SEM_OFIELD_END:
825  {
827 
828  if (oend != NULL)
829  {
830  char *fname = get_fname(lex);
831  bool isnull = get_fnull(lex);
832 
833  result = (*oend) (sem->semstate, fname, isnull);
834  if (result != JSON_SUCCESS)
835  return result;
836  }
837  }
838  break;
840  {
842  bool isnull = tok == JSON_TOKEN_NULL;
843 
844  set_fnull(lex, isnull);
845 
846  if (astart != NULL)
847  {
848  result = (*astart) (sem->semstate, isnull);
849  if (result != JSON_SUCCESS)
850  return result;
851  }
852  }
853  break;
854  case JSON_SEM_AELEM_END:
855  {
857 
858  if (aend != NULL)
859  {
860  bool isnull = get_fnull(lex);
861 
862  result = (*aend) (sem->semstate, isnull);
863  if (result != JSON_SUCCESS)
864  return result;
865  }
866  }
867  break;
869  {
870  json_scalar_action sfunc = sem->scalar;
871 
872  pstack->scalar_val = NULL;
873 
874  if (sfunc != NULL)
875  {
876  /*
877  * extract the de-escaped string value, or the raw
878  * lexeme
879  */
880  /*
881  * XXX copied from RD parser but looks like a
882  * buglet
883  */
884  if (tok == JSON_TOKEN_STRING)
885  {
886  if (lex->strval != NULL)
887  pstack->scalar_val = pstrdup(lex->strval->data);
888  }
889  else
890  {
891  int tlen = (lex->token_terminator - lex->token_start);
892 
893  pstack->scalar_val = palloc(tlen + 1);
894  memcpy(pstack->scalar_val, lex->token_start, tlen);
895  pstack->scalar_val[tlen] = '\0';
896  }
897  pstack->scalar_tok = tok;
898  }
899  }
900  break;
902  {
903  /*
904  * We'd like to be able to get rid of this business of
905  * two bits of scalar action, but we can't. It breaks
906  * certain semantic actions which expect that when
907  * called the lexer has consumed the item. See for
908  * example get_scalar() in jsonfuncs.c.
909  */
910  json_scalar_action sfunc = sem->scalar;
911 
912  if (sfunc != NULL)
913  {
914  result = (*sfunc) (sem->semstate, pstack->scalar_val, pstack->scalar_tok);
915  if (result != JSON_SUCCESS)
916  return result;
917  }
918  }
919  break;
920  default:
921  /* should not happen */
922  break;
923  }
924  }
925  else
926  {
927  /*
928  * The token didn't match the stack top if it's a terminal nor a
929  * production for the stack top if it's a non-terminal.
930  *
931  * Various cases here are Asserted to be not possible, as the
932  * token would not appear at the top of the prediction stack
933  * unless the lookahead matched.
934  */
935  switch (top)
936  {
937  case JSON_TOKEN_STRING:
938  if (next_prediction(pstack) == JSON_TOKEN_COLON)
939  ctx = JSON_PARSE_STRING;
940  else
941  {
942  Assert(false);
943  ctx = JSON_PARSE_VALUE;
944  }
945  break;
946  case JSON_TOKEN_NUMBER:
947  case JSON_TOKEN_TRUE:
948  case JSON_TOKEN_FALSE:
949  case JSON_TOKEN_NULL:
952  Assert(false);
953  ctx = JSON_PARSE_VALUE;
954  break;
956  Assert(false);
957  ctx = JSON_PARSE_ARRAY_NEXT;
958  break;
960  Assert(false);
962  break;
963  case JSON_TOKEN_COMMA:
964  Assert(false);
965  if (next_prediction(pstack) == JSON_TOKEN_STRING)
967  else
968  ctx = JSON_PARSE_ARRAY_NEXT;
969  break;
970  case JSON_TOKEN_COLON:
972  break;
973  case JSON_TOKEN_END:
974  ctx = JSON_PARSE_END;
975  break;
977  ctx = JSON_PARSE_ARRAY_NEXT;
978  break;
981  break;
984  break;
985  case JSON_NT_KEY_PAIRS:
987  break;
988  default:
989  ctx = JSON_PARSE_VALUE;
990  }
991  return report_parse_error(ctx, lex);
992  }
993  }
994 
995  return JSON_SUCCESS;
#define JSON_TD_MAX_STACK
Definition: jsonapi.c:363
JsonParseContext
Definition: jsonapi.c:34
@ JSON_PARSE_OBJECT_LABEL
Definition: jsonapi.c:40
@ JSON_PARSE_VALUE
Definition: jsonapi.c:35
@ JSON_PARSE_OBJECT_START
Definition: jsonapi.c:39
@ JSON_PARSE_OBJECT_NEXT
Definition: jsonapi.c:41
@ JSON_PARSE_STRING
Definition: jsonapi.c:36
#define TD_ENTRY(PROD)
Definition: jsonapi.c:178
@ JSON_SEM_SCALAR_CALL
Definition: jsonapi.c:74
@ JSON_SEM_OSTART
Definition: jsonapi.c:64
@ JSON_SEM_AELEM_START
Definition: jsonapi.c:71
@ JSON_SEM_AELEM_END
Definition: jsonapi.c:72
@ JSON_SEM_SCALAR_INIT
Definition: jsonapi.c:73
@ JSON_SEM_ASTART
Definition: jsonapi.c:66
@ JSON_SEM_OFIELD_INIT
Definition: jsonapi.c:68
@ JSON_SEM_OFIELD_END
Definition: jsonapi.c:70
@ JSON_SEM_OEND
Definition: jsonapi.c:65
@ JSON_SEM_OFIELD_START
Definition: jsonapi.c:69
@ JSON_SEM_AEND
Definition: jsonapi.c:67
static void set_fnull(JsonLexContext *lex, bool fnull)
Definition: jsonapi.c:463
static void inc_lex_level(JsonLexContext *lex)
Definition: jsonapi.c:397
#define OFS(NT)
Definition: jsonapi.c:116
static bool have_prediction(JsonParserStack *pstack)
Definition: jsonapi.c:445
static void set_fname(JsonLexContext *lex, char *fname)
Definition: jsonapi.c:451
static char next_prediction(JsonParserStack *pstack)
Definition: jsonapi.c:438
static void push_prediction(JsonParserStack *pstack, td_entry entry)
Definition: jsonapi.c:424
#define IS_NT(x)
Definition: jsonapi.c:119
static char JSON_PROD_GOAL[]
Definition: jsonapi.c:211
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
Definition: jsonapi.c:2052
#define IS_SEM(x)
Definition: jsonapi.c:118
static td_entry td_parser_table[JSON_NUM_NONTERMINALS][JSON_NUM_TERMINALS]
Definition: jsonapi.c:180
static char * get_fname(JsonLexContext *lex)
Definition: jsonapi.c:457
static char pop_prediction(JsonParserStack *pstack)
Definition: jsonapi.c:431
static bool get_fnull(JsonLexContext *lex)
Definition: jsonapi.c:469
@ JSON_NT_MORE_ARRAY_ELEMENTS
Definition: jsonapi.c:57
@ JSON_NT_MORE_KEY_PAIRS
Definition: jsonapi.c:59
@ JSON_NT_ARRAY_ELEMENTS
Definition: jsonapi.c:56
@ JSON_NT_KEY_PAIRS
Definition: jsonapi.c:58
static void dec_lex_level(JsonLexContext *lex)
Definition: jsonapi.c:418
JsonParseErrorType(* json_struct_action)(void *state)
Definition: jsonapi.h:109
JsonParseErrorType(* json_aelem_action)(void *state, bool isnull)
Definition: jsonapi.h:111
JsonParseErrorType(* json_ofield_action)(void *state, char *fname, bool isnull)
Definition: jsonapi.h:110
JsonParseErrorType(* json_scalar_action)(void *state, char *token, JsonTokenType tokentype)
Definition: jsonapi.h:112
char * pstrdup(const char *in)
Definition: mcxt.c:1695
JsonTokenType scalar_tok
Definition: jsonapi.c:92
char * scalar_val
Definition: jsonapi.c:93
json_struct_action array_end
Definition: jsonapi.h:138
json_struct_action object_start
Definition: jsonapi.h:135
json_ofield_action object_field_start
Definition: jsonapi.h:139
json_aelem_action array_element_start
Definition: jsonapi.h:141
json_scalar_action scalar
Definition: jsonapi.h:143
void * semstate
Definition: jsonapi.h:134
json_aelem_action array_element_end
Definition: jsonapi.h:142
json_struct_action array_start
Definition: jsonapi.h:137
json_struct_action object_end
Definition: jsonapi.h:136
json_ofield_action object_field_end
Definition: jsonapi.h:140
Definition: jsonapi.c:173

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, Assert, StringInfoData::data, dec_lex_level(), get_fname(), get_fnull(), have_prediction(), inc_lex_level(), JsonLexContext::inc_state, JsonLexContext::incremental, JsonLexContext::input, JsonLexContext::input_length, JsonIncrementalState::is_last_chunk, IS_NT, IS_SEM, JSON_INVALID_LEXER_TYPE, json_lex(), JSON_NESTING_TOO_DEEP, JSON_NT_ARRAY_ELEMENTS, JSON_NT_KEY_PAIRS, JSON_NT_MORE_ARRAY_ELEMENTS, JSON_NT_MORE_KEY_PAIRS, JSON_PARSE_ARRAY_NEXT, JSON_PARSE_ARRAY_START, JSON_PARSE_END, JSON_PARSE_OBJECT_LABEL, JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_START, JSON_PARSE_STRING, JSON_PARSE_VALUE, JSON_PROD_GOAL, JSON_SEM_AELEM_END, JSON_SEM_AELEM_START, JSON_SEM_AEND, JSON_SEM_ASTART, JSON_SEM_OEND, JSON_SEM_OFIELD_END, JSON_SEM_OFIELD_INIT, JSON_SEM_OFIELD_START, JSON_SEM_OSTART, JSON_SEM_SCALAR_CALL, JSON_SEM_SCALAR_INIT, JSON_SUCCESS, JSON_TD_MAX_STACK, JSON_TOKEN_ARRAY_END, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COLON, JSON_TOKEN_COMMA, JSON_TOKEN_END, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_OBJECT_END, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, len, JsonLexContext::lex_level, lex_peek(), JsonLexContext::line_start, next_prediction(), JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, OFS, palloc(), pop_prediction(), JsonLexContext::pstack, pstrdup(), push_prediction(), report_parse_error(), JsonSemAction::scalar, JsonParserStack::scalar_tok, JsonParserStack::scalar_val, sem, JsonSemAction::semstate, set_fname(), set_fnull(), JsonLexContext::strval, TD_ENTRY, td_parser_table, JsonLexContext::token_start, and JsonLexContext::token_terminator.

Referenced by json_parse_manifest_incremental_chunk(), main(), and pg_parse_json().

Variable Documentation

◆ nullSemAction

PGDLLIMPORT JsonSemAction nullSemAction
extern

Definition at line 224 of file jsonapi.c.

Referenced by json_count_array_elements(), json_in(), json_recv(), json_validate(), and main().