PostgreSQL Source Code  git master
jsonapi.c File Reference
#include "postgres.h"
#include "common/jsonapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
Include dependency graph for jsonapi.c:

Go to the source code of this file.

Macros

#define JSON_ALPHANUMERIC_CHAR(c)
 

Enumerations

enum  JsonParseContext {
  JSON_PARSE_VALUE, JSON_PARSE_STRING, JSON_PARSE_ARRAY_START, JSON_PARSE_ARRAY_NEXT,
  JSON_PARSE_OBJECT_START, JSON_PARSE_OBJECT_LABEL, JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_COMMA,
  JSON_PARSE_END
}
 

Functions

static JsonParseErrorType json_lex_string (JsonLexContext *lex)
 
static JsonParseErrorType json_lex_number (JsonLexContext *lex, char *s, bool *num_err, int *total_len)
 
static JsonParseErrorType parse_scalar (JsonLexContext *lex, JsonSemAction *sem)
 
static JsonParseErrorType parse_object_field (JsonLexContext *lex, JsonSemAction *sem)
 
static JsonParseErrorType parse_object (JsonLexContext *lex, JsonSemAction *sem)
 
static JsonParseErrorType parse_array_element (JsonLexContext *lex, JsonSemAction *sem)
 
static JsonParseErrorType parse_array (JsonLexContext *lex, JsonSemAction *sem)
 
static JsonParseErrorType report_parse_error (JsonParseContext ctx, JsonLexContext *lex)
 
static JsonTokenType lex_peek (JsonLexContext *lex)
 
static JsonParseErrorType lex_expect (JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
 
bool IsValidJsonNumber (const char *str, int len)
 
JsonLexContextmakeJsonLexContextCstringLen (char *json, int len, int encoding, bool need_escapes)
 
JsonParseErrorType pg_parse_json (JsonLexContext *lex, JsonSemAction *sem)
 
JsonParseErrorType json_count_array_elements (JsonLexContext *lex, int *elements)
 
JsonParseErrorType json_lex (JsonLexContext *lex)
 
static char * extract_token (JsonLexContext *lex)
 
char * json_errdetail (JsonParseErrorType error, JsonLexContext *lex)
 

Variables

JsonSemAction nullSemAction
 

Macro Definition Documentation

◆ JSON_ALPHANUMERIC_CHAR

#define JSON_ALPHANUMERIC_CHAR (   c)
Value:
(((c) >= 'a' && (c) <= 'z') || \
((c) >= 'A' && (c) <= 'Z') || \
((c) >= '0' && (c) <= '9') || \
(c) == '_' || \
IS_HIGHBIT_SET(c))
char * c

Definition at line 91 of file jsonapi.c.

Referenced by json_lex(), and json_lex_number().

Enumeration Type Documentation

◆ JsonParseContext

Enumerator
JSON_PARSE_VALUE 
JSON_PARSE_STRING 
JSON_PARSE_ARRAY_START 
JSON_PARSE_ARRAY_NEXT 
JSON_PARSE_OBJECT_START 
JSON_PARSE_OBJECT_LABEL 
JSON_PARSE_OBJECT_NEXT 
JSON_PARSE_OBJECT_COMMA 
JSON_PARSE_END 

Definition at line 32 of file jsonapi.c.

33 {
34  JSON_PARSE_VALUE, /* expecting a value */
35  JSON_PARSE_STRING, /* expecting a string (for a field name) */
36  JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
37  JSON_PARSE_ARRAY_NEXT, /* saw array element, expecting ',' or ']' */
38  JSON_PARSE_OBJECT_START, /* saw '{', expecting label or '}' */
39  JSON_PARSE_OBJECT_LABEL, /* saw object label, expecting ':' */
40  JSON_PARSE_OBJECT_NEXT, /* saw object value, expecting ',' or '}' */
41  JSON_PARSE_OBJECT_COMMA, /* saw object ',', expecting next label */
42  JSON_PARSE_END /* saw the end of a document, expect nothing */
JsonParseContext
Definition: jsonapi.c:32

Function Documentation

◆ extract_token()

static char* extract_token ( JsonLexContext lex)
static

Definition at line 1052 of file jsonapi.c.

References palloc(), JsonLexContext::token_start, and JsonLexContext::token_terminator.

Referenced by json_errdetail().

1053 {
1054  int toklen = lex->token_terminator - lex->token_start;
1055  char *token = palloc(toklen + 1);
1056 
1057  memcpy(token, lex->token_start, toklen);
1058  token[toklen] = '\0';
1059  return token;
1060 }
char * token_start
Definition: jsonapi.h:77
char * token_terminator
Definition: jsonapi.h:78
void * palloc(Size size)
Definition: mcxt.c:1062

◆ IsValidJsonNumber()

bool IsValidJsonNumber ( const char *  str,
int  len 
)

Definition at line 104 of file jsonapi.c.

References JsonLexContext::input, JsonLexContext::input_length, json_lex_number(), and unconstify.

Referenced by datum_to_json(), hstore_to_json_loose(), and hstore_to_jsonb_loose().

105 {
106  bool numeric_error;
107  int total_len;
108  JsonLexContext dummy_lex;
109 
110  if (len <= 0)
111  return false;
112 
113  /*
114  * json_lex_number expects a leading '-' to have been eaten already.
115  *
116  * having to cast away the constness of str is ugly, but there's not much
117  * easy alternative.
118  */
119  if (*str == '-')
120  {
121  dummy_lex.input = unconstify(char *, str) + 1;
122  dummy_lex.input_length = len - 1;
123  }
124  else
125  {
126  dummy_lex.input = unconstify(char *, str);
127  dummy_lex.input_length = len;
128  }
129 
130  json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
131 
132  return (!numeric_error) && (total_len == dummy_lex.input_length);
133 }
int input_length
Definition: jsonapi.h:75
#define unconstify(underlying_type, expr)
Definition: c.h:1243
char * input
Definition: jsonapi.h:74
static JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s, bool *num_err, int *total_len)
Definition: jsonapi.c:909

◆ json_count_array_elements()

JsonParseErrorType json_count_array_elements ( JsonLexContext lex,
int *  elements 
)

Definition at line 208 of file jsonapi.c.

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(), parse_array_element(), JsonLexContext::strval, and JsonLexContext::token_type.

Referenced by get_array_start().

209 {
210  JsonLexContext copylex;
211  int count;
212  JsonParseErrorType result;
213 
214  /*
215  * It's safe to do this with a shallow copy because the lexical routines
216  * don't scribble on the input. They do scribble on the other pointers
217  * etc, so doing this with a copy makes that safe.
218  */
219  memcpy(&copylex, lex, sizeof(JsonLexContext));
220  copylex.strval = NULL; /* not interested in values here */
221  copylex.lex_level++;
222 
223  count = 0;
224  result = lex_expect(JSON_PARSE_ARRAY_START, &copylex,
226  if (result != JSON_SUCCESS)
227  return result;
228  if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
229  {
230  while (1)
231  {
232  count++;
233  result = parse_array_element(&copylex, &nullSemAction);
234  if (result != JSON_SUCCESS)
235  return result;
236  if (copylex.token_type != JSON_TOKEN_COMMA)
237  break;
238  result = json_lex(&copylex);
239  if (result != JSON_SUCCESS)
240  return result;
241  }
242  }
243  result = lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex,
245  if (result != JSON_SUCCESS)
246  return result;
247 
248  *elements = count;
249  return JSON_SUCCESS;
250 }
JsonTokenType token_type
Definition: jsonapi.h:80
JsonSemAction nullSemAction
Definition: jsonapi.c:56
int lex_level
Definition: jsonapi.h:81
StringInfo strval
Definition: jsonapi.h:84
JsonParseErrorType
Definition: jsonapi.h:36
static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:425
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:82

◆ json_errdetail()

char* json_errdetail ( JsonParseErrorType  error,
JsonLexContext lex 
)

Definition at line 1070 of file jsonapi.c.

References _, elog, ERROR, extract_token(), 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_SUCCESS, JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_ESCAPE_FORMAT, JSON_UNICODE_HIGH_ESCAPE, JSON_UNICODE_HIGH_SURROGATE, JSON_UNICODE_LOW_SURROGATE, psprintf(), and JsonLexContext::token_terminator.

Referenced by json_ereport_error().

1071 {
1072  switch (error)
1073  {
1074  case JSON_SUCCESS:
1075  /* fall through to the error code after switch */
1076  break;
1077  case JSON_ESCAPING_INVALID:
1078  return psprintf(_("Escape sequence \"\\%s\" is invalid."),
1079  extract_token(lex));
1081  return psprintf(_("Character with value 0x%02x must be escaped."),
1082  (unsigned char) *(lex->token_terminator));
1083  case JSON_EXPECTED_END:
1084  return psprintf(_("Expected end of input, but found \"%s\"."),
1085  extract_token(lex));
1087  return psprintf(_("Expected array element or \"]\", but found \"%s\"."),
1088  extract_token(lex));
1090  return psprintf(_("Expected \",\" or \"]\", but found \"%s\"."),
1091  extract_token(lex));
1092  case JSON_EXPECTED_COLON:
1093  return psprintf(_("Expected \":\", but found \"%s\"."),
1094  extract_token(lex));
1095  case JSON_EXPECTED_JSON:
1096  return psprintf(_("Expected JSON value, but found \"%s\"."),
1097  extract_token(lex));
1098  case JSON_EXPECTED_MORE:
1099  return _("The input string ended unexpectedly.");
1101  return psprintf(_("Expected string or \"}\", but found \"%s\"."),
1102  extract_token(lex));
1104  return psprintf(_("Expected \",\" or \"}\", but found \"%s\"."),
1105  extract_token(lex));
1106  case JSON_EXPECTED_STRING:
1107  return psprintf(_("Expected string, but found \"%s\"."),
1108  extract_token(lex));
1109  case JSON_INVALID_TOKEN:
1110  return psprintf(_("Token \"%s\" is invalid."),
1111  extract_token(lex));
1113  return _("\\u0000 cannot be converted to text.");
1115  return _("\"\\u\" must be followed by four hexadecimal digits.");
1117  /* note: this case is only reachable in frontend not backend */
1118  return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
1120  return _("Unicode high surrogate must not follow a high surrogate.");
1122  return _("Unicode low surrogate must follow a high surrogate.");
1123  }
1124 
1125  /*
1126  * We don't use a default: case, so that the compiler will warn about
1127  * unhandled enum values. But this needs to be here anyway to cover the
1128  * possibility of an incorrect input.
1129  */
1130  elog(ERROR, "unexpected json parse error type: %d", (int) error);
1131  return NULL;
1132 }
static void error(void)
Definition: sql-dyntest.c:147
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static char * extract_token(JsonLexContext *lex)
Definition: jsonapi.c:1052
#define ERROR
Definition: elog.h:46
char * token_terminator
Definition: jsonapi.h:78
#define elog(elevel,...)
Definition: elog.h:232
#define _(x)
Definition: elog.c:89

◆ json_lex()

JsonParseErrorType json_lex ( JsonLexContext lex)

Definition at line 519 of file jsonapi.c.

References JsonLexContext::input, JsonLexContext::input_length, JSON_ALPHANUMERIC_CHAR, 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, JsonLexContext::line_number, JsonLexContext::line_start, JsonLexContext::prev_token_terminator, JsonLexContext::token_start, JsonLexContext::token_terminator, and JsonLexContext::token_type.

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

520 {
521  char *s;
522  int len;
523  JsonParseErrorType result;
524 
525  /* Skip leading whitespace. */
526  s = lex->token_terminator;
527  len = s - lex->input;
528  while (len < lex->input_length &&
529  (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
530  {
531  if (*s++ == '\n')
532  {
533  ++lex->line_number;
534  lex->line_start = s;
535  }
536  len++;
537  }
538  lex->token_start = s;
539 
540  /* Determine token type. */
541  if (len >= lex->input_length)
542  {
543  lex->token_start = NULL;
545  lex->token_terminator = s;
546  lex->token_type = JSON_TOKEN_END;
547  }
548  else
549  {
550  switch (*s)
551  {
552  /* Single-character token, some kind of punctuation mark. */
553  case '{':
555  lex->token_terminator = s + 1;
557  break;
558  case '}':
560  lex->token_terminator = s + 1;
562  break;
563  case '[':
565  lex->token_terminator = s + 1;
567  break;
568  case ']':
570  lex->token_terminator = s + 1;
572  break;
573  case ',':
575  lex->token_terminator = s + 1;
577  break;
578  case ':':
580  lex->token_terminator = s + 1;
582  break;
583  case '"':
584  /* string */
585  result = json_lex_string(lex);
586  if (result != JSON_SUCCESS)
587  return result;
589  break;
590  case '-':
591  /* Negative number. */
592  result = json_lex_number(lex, s + 1, NULL, NULL);
593  if (result != JSON_SUCCESS)
594  return result;
596  break;
597  case '0':
598  case '1':
599  case '2':
600  case '3':
601  case '4':
602  case '5':
603  case '6':
604  case '7':
605  case '8':
606  case '9':
607  /* Positive number. */
608  result = json_lex_number(lex, s, NULL, NULL);
609  if (result != JSON_SUCCESS)
610  return result;
612  break;
613  default:
614  {
615  char *p;
616 
617  /*
618  * We're not dealing with a string, number, legal
619  * punctuation mark, or end of string. The only legal
620  * tokens we might find here are true, false, and null,
621  * but for error reporting purposes we scan until we see a
622  * non-alphanumeric character. That way, we can report
623  * the whole word as an unexpected token, rather than just
624  * some unintuitive prefix thereof.
625  */
626  for (p = s; p - s < lex->input_length - len && JSON_ALPHANUMERIC_CHAR(*p); p++)
627  /* skip */ ;
628 
629  /*
630  * We got some sort of unexpected punctuation or an
631  * otherwise unexpected character, so just complain about
632  * that one character.
633  */
634  if (p == s)
635  {
637  lex->token_terminator = s + 1;
638  return JSON_INVALID_TOKEN;
639  }
640 
641  /*
642  * We've got a real alphanumeric token here. If it
643  * happens to be true, false, or null, all is well. If
644  * not, error out.
645  */
647  lex->token_terminator = p;
648  if (p - s == 4)
649  {
650  if (memcmp(s, "true", 4) == 0)
652  else if (memcmp(s, "null", 4) == 0)
654  else
655  return JSON_INVALID_TOKEN;
656  }
657  else if (p - s == 5 && memcmp(s, "false", 5) == 0)
659  else
660  return JSON_INVALID_TOKEN;
661 
662  }
663  } /* end of switch */
664  }
665 
666  return JSON_SUCCESS;
667 }
int line_number
Definition: jsonapi.h:82
static JsonParseErrorType json_lex_string(JsonLexContext *lex)
Definition: jsonapi.c:673
JsonTokenType token_type
Definition: jsonapi.h:80
char * prev_token_terminator
Definition: jsonapi.h:79
char * line_start
Definition: jsonapi.h:83
int input_length
Definition: jsonapi.h:75
char * token_start
Definition: jsonapi.h:77
#define JSON_ALPHANUMERIC_CHAR(c)
Definition: jsonapi.c:91
char * token_terminator
Definition: jsonapi.h:78
JsonParseErrorType
Definition: jsonapi.h:36
char * input
Definition: jsonapi.h:74
static JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s, bool *num_err, int *total_len)
Definition: jsonapi.c:909

◆ json_lex_number()

static JsonParseErrorType json_lex_number ( JsonLexContext lex,
char *  s,
bool num_err,
int *  total_len 
)
inlinestatic

Definition at line 909 of file jsonapi.c.

References error(), JsonLexContext::input, JsonLexContext::input_length, JSON_ALPHANUMERIC_CHAR, JSON_INVALID_TOKEN, JSON_SUCCESS, JsonLexContext::prev_token_terminator, and JsonLexContext::token_terminator.

Referenced by IsValidJsonNumber(), and json_lex().

911 {
912  bool error = false;
913  int len = s - lex->input;
914 
915  /* Part (1): leading sign indicator. */
916  /* Caller already did this for us; so do nothing. */
917 
918  /* Part (2): parse main digit string. */
919  if (len < lex->input_length && *s == '0')
920  {
921  s++;
922  len++;
923  }
924  else if (len < lex->input_length && *s >= '1' && *s <= '9')
925  {
926  do
927  {
928  s++;
929  len++;
930  } while (len < lex->input_length && *s >= '0' && *s <= '9');
931  }
932  else
933  error = true;
934 
935  /* Part (3): parse optional decimal portion. */
936  if (len < lex->input_length && *s == '.')
937  {
938  s++;
939  len++;
940  if (len == lex->input_length || *s < '0' || *s > '9')
941  error = true;
942  else
943  {
944  do
945  {
946  s++;
947  len++;
948  } while (len < lex->input_length && *s >= '0' && *s <= '9');
949  }
950  }
951 
952  /* Part (4): parse optional exponent. */
953  if (len < lex->input_length && (*s == 'e' || *s == 'E'))
954  {
955  s++;
956  len++;
957  if (len < lex->input_length && (*s == '+' || *s == '-'))
958  {
959  s++;
960  len++;
961  }
962  if (len == lex->input_length || *s < '0' || *s > '9')
963  error = true;
964  else
965  {
966  do
967  {
968  s++;
969  len++;
970  } while (len < lex->input_length && *s >= '0' && *s <= '9');
971  }
972  }
973 
974  /*
975  * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
976  * here should be considered part of the token for error-reporting
977  * purposes.
978  */
979  for (; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*s); s++, len++)
980  error = true;
981 
982  if (total_len != NULL)
983  *total_len = len;
984 
985  if (num_err != NULL)
986  {
987  /* let the caller handle any error */
988  *num_err = error;
989  }
990  else
991  {
992  /* return token endpoint */
994  lex->token_terminator = s;
995  /* handle error if any */
996  if (error)
997  return JSON_INVALID_TOKEN;
998  }
999 
1000  return JSON_SUCCESS;
1001 }
static void error(void)
Definition: sql-dyntest.c:147
char * prev_token_terminator
Definition: jsonapi.h:79
int input_length
Definition: jsonapi.h:75
#define JSON_ALPHANUMERIC_CHAR(c)
Definition: jsonapi.c:91
char * token_terminator
Definition: jsonapi.h:78
char * input
Definition: jsonapi.h:74

◆ json_lex_string()

static JsonParseErrorType json_lex_string ( JsonLexContext lex)
inlinestatic

Definition at line 673 of file jsonapi.c.

References appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, i, JsonLexContext::input, JsonLexContext::input_encoding, JsonLexContext::input_length, is_utf16_surrogate_first(), is_utf16_surrogate_second(), JSON_ESCAPING_INVALID, JSON_ESCAPING_REQUIRED, JSON_INVALID_TOKEN, JSON_SUCCESS, JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_ESCAPE_FORMAT, JSON_UNICODE_HIGH_ESCAPE, JSON_UNICODE_HIGH_SURROGATE, JSON_UNICODE_LOW_SURROGATE, MAX_UNICODE_EQUIVALENT_STRING, pg_encoding_mblen_bounded(), pg_unicode_to_server(), PG_UTF8, pg_utf_mblen(), JsonLexContext::prev_token_terminator, resetStringInfo(), JsonLexContext::strval, surrogate_pair_to_codepoint(), JsonLexContext::token_start, JsonLexContext::token_terminator, and unicode_to_utf8().

Referenced by json_lex().

674 {
675  char *s;
676  int len;
677  int hi_surrogate = -1;
678 
679  if (lex->strval != NULL)
680  resetStringInfo(lex->strval);
681 
682  Assert(lex->input_length > 0);
683  s = lex->token_start;
684  len = lex->token_start - lex->input;
685  for (;;)
686  {
687  s++;
688  len++;
689  /* Premature end of the string. */
690  if (len >= lex->input_length)
691  {
692  lex->token_terminator = s;
693  return JSON_INVALID_TOKEN;
694  }
695  else if (*s == '"')
696  break;
697  else if ((unsigned char) *s < 32)
698  {
699  /* Per RFC4627, these characters MUST be escaped. */
700  /* Since *s isn't printable, exclude it from the context string */
701  lex->token_terminator = s;
702  return JSON_ESCAPING_REQUIRED;
703  }
704  else if (*s == '\\')
705  {
706  /* OK, we have an escape character. */
707  s++;
708  len++;
709  if (len >= lex->input_length)
710  {
711  lex->token_terminator = s;
712  return JSON_INVALID_TOKEN;
713  }
714  else if (*s == 'u')
715  {
716  int i;
717  int ch = 0;
718 
719  for (i = 1; i <= 4; i++)
720  {
721  s++;
722  len++;
723  if (len >= lex->input_length)
724  {
725  lex->token_terminator = s;
726  return JSON_INVALID_TOKEN;
727  }
728  else if (*s >= '0' && *s <= '9')
729  ch = (ch * 16) + (*s - '0');
730  else if (*s >= 'a' && *s <= 'f')
731  ch = (ch * 16) + (*s - 'a') + 10;
732  else if (*s >= 'A' && *s <= 'F')
733  ch = (ch * 16) + (*s - 'A') + 10;
734  else
735  {
738  }
739  }
740  if (lex->strval != NULL)
741  {
742  /*
743  * Combine surrogate pairs.
744  */
745  if (is_utf16_surrogate_first(ch))
746  {
747  if (hi_surrogate != -1)
749  hi_surrogate = ch;
750  continue;
751  }
752  else if (is_utf16_surrogate_second(ch))
753  {
754  if (hi_surrogate == -1)
756  ch = surrogate_pair_to_codepoint(hi_surrogate, ch);
757  hi_surrogate = -1;
758  }
759 
760  if (hi_surrogate != -1)
762 
763  /*
764  * Reject invalid cases. We can't have a value above
765  * 0xFFFF here (since we only accepted 4 hex digits
766  * above), so no need to test for out-of-range chars.
767  */
768  if (ch == 0)
769  {
770  /* We can't allow this, since our TEXT type doesn't */
772  }
773 
774  /*
775  * Add the represented character to lex->strval. In the
776  * backend, we can let pg_unicode_to_server() handle any
777  * required character set conversion; in frontend, we can
778  * only deal with trivial conversions.
779  *
780  * Note: pg_unicode_to_server() will throw an error for a
781  * conversion failure, rather than returning a failure
782  * indication. That seems OK.
783  */
784 #ifndef FRONTEND
785  {
786  char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
787 
788  pg_unicode_to_server(ch, (unsigned char *) cbuf);
789  appendStringInfoString(lex->strval, cbuf);
790  }
791 #else
792  if (lex->input_encoding == PG_UTF8)
793  {
794  /* OK, we can map the code point to UTF8 easily */
795  char utf8str[5];
796  int utf8len;
797 
798  unicode_to_utf8(ch, (unsigned char *) utf8str);
799  utf8len = pg_utf_mblen((unsigned char *) utf8str);
800  appendBinaryStringInfo(lex->strval, utf8str, utf8len);
801  }
802  else if (ch <= 0x007f)
803  {
804  /* The ASCII range is the same in all encodings */
805  appendStringInfoChar(lex->strval, (char) ch);
806  }
807  else
809 #endif /* FRONTEND */
810  }
811  }
812  else if (lex->strval != NULL)
813  {
814  if (hi_surrogate != -1)
816 
817  switch (*s)
818  {
819  case '"':
820  case '\\':
821  case '/':
822  appendStringInfoChar(lex->strval, *s);
823  break;
824  case 'b':
825  appendStringInfoChar(lex->strval, '\b');
826  break;
827  case 'f':
828  appendStringInfoChar(lex->strval, '\f');
829  break;
830  case 'n':
831  appendStringInfoChar(lex->strval, '\n');
832  break;
833  case 'r':
834  appendStringInfoChar(lex->strval, '\r');
835  break;
836  case 't':
837  appendStringInfoChar(lex->strval, '\t');
838  break;
839  default:
840  /* Not a valid string escape, so signal error. */
841  lex->token_start = s;
843  return JSON_ESCAPING_INVALID;
844  }
845  }
846  else if (strchr("\"\\/bfnrt", *s) == NULL)
847  {
848  /*
849  * Simpler processing if we're not bothered about de-escaping
850  *
851  * It's very tempting to remove the strchr() call here and
852  * replace it with a switch statement, but testing so far has
853  * shown it's not a performance win.
854  */
855  lex->token_start = s;
857  return JSON_ESCAPING_INVALID;
858  }
859 
860  }
861  else if (lex->strval != NULL)
862  {
863  if (hi_surrogate != -1)
865 
866  appendStringInfoChar(lex->strval, *s);
867  }
868 
869  }
870 
871  if (hi_surrogate != -1)
873 
874  /* Hooray, we found the end of the string! */
876  lex->token_terminator = s + 1;
877  return JSON_SUCCESS;
878 }
unsigned char * unicode_to_utf8(pg_wchar c, unsigned char *utf8string)
Definition: wchar.c:483
char * prev_token_terminator
Definition: jsonapi.h:79
static bool is_utf16_surrogate_second(pg_wchar c)
Definition: pg_wchar.h:551
#define MAX_UNICODE_EQUIVALENT_STRING
Definition: pg_wchar.h:343
int input_length
Definition: jsonapi.h:75
int input_encoding
Definition: jsonapi.h:76
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
StringInfo strval
Definition: jsonapi.h:84
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
char * token_start
Definition: jsonapi.h:77
static pg_wchar surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second)
Definition: pg_wchar.h:557
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
char * token_terminator
Definition: jsonapi.h:78
void pg_unicode_to_server(pg_wchar c, unsigned char *s)
Definition: mbutils.c:864
int pg_encoding_mblen_bounded(int encoding, const char *mbstr)
Definition: wchar.c:1926
#define Assert(condition)
Definition: c.h:804
char * input
Definition: jsonapi.h:74
int pg_utf_mblen(const unsigned char *s)
Definition: wchar.c:549
int i
static bool is_utf16_surrogate_first(pg_wchar c)
Definition: pg_wchar.h:545
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ lex_expect()

static JsonParseErrorType lex_expect ( JsonParseContext  ctx,
JsonLexContext lex,
JsonTokenType  token 
)
inlinestatic

Definition at line 82 of file jsonapi.c.

References json_lex(), lex_peek(), and report_parse_error().

Referenced by json_count_array_elements(), parse_array(), parse_object(), parse_object_field(), and pg_parse_json().

83 {
84  if (lex_peek(lex) == token)
85  return json_lex(lex);
86  else
87  return report_parse_error(ctx, lex);
88 }
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
Definition: jsonapi.c:1009
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70

◆ lex_peek()

static JsonTokenType lex_peek ( JsonLexContext lex)
inlinestatic

◆ makeJsonLexContextCstringLen()

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

Definition at line 144 of file jsonapi.c.

References encoding, JsonLexContext::input, JsonLexContext::input_encoding, JsonLexContext::input_length, 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(), makeJsonLexContext(), and populate_array_json().

145 {
146  JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
147 
148  lex->input = lex->token_terminator = lex->line_start = json;
149  lex->line_number = 1;
150  lex->input_length = len;
151  lex->input_encoding = encoding;
152  if (need_escapes)
153  lex->strval = makeStringInfo();
154  return lex;
155 }
int line_number
Definition: jsonapi.h:82
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
char * line_start
Definition: jsonapi.h:83
int input_length
Definition: jsonapi.h:75
int input_encoding
Definition: jsonapi.h:76
StringInfo strval
Definition: jsonapi.h:84
void * palloc0(Size size)
Definition: mcxt.c:1093
char * token_terminator
Definition: jsonapi.h:78
char * input
Definition: jsonapi.h:74
int32 encoding
Definition: pg_database.h:41

◆ parse_array()

static JsonParseErrorType parse_array ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 462 of file jsonapi.c.

References JsonSemAction::array_end, JsonSemAction::array_start, check_stack_depth(), 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(), parse_array_element(), and JsonSemAction::semstate.

Referenced by parse_array_element(), parse_object_field(), and pg_parse_json().

463 {
464  /*
465  * an array is a possibly empty sequence of array elements, separated by
466  * commas and surrounded by square brackets.
467  */
468  json_struct_action astart = sem->array_start;
469  json_struct_action aend = sem->array_end;
470  JsonParseErrorType result;
471 
472 #ifndef FRONTEND
474 #endif
475 
476  if (astart != NULL)
477  (*astart) (sem->semstate);
478 
479  /*
480  * Data inside an array is at a higher nesting level than the array
481  * itself. Note that we increment this after we call the semantic routine
482  * for the array start and restore it before we call the routine for the
483  * array end.
484  */
485  lex->lex_level++;
486 
488  if (result == JSON_SUCCESS && lex_peek(lex) != JSON_TOKEN_ARRAY_END)
489  {
490  result = parse_array_element(lex, sem);
491 
492  while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
493  {
494  result = json_lex(lex);
495  if (result != JSON_SUCCESS)
496  break;
497  result = parse_array_element(lex, sem);
498  }
499  }
500  if (result != JSON_SUCCESS)
501  return result;
502 
504  if (result != JSON_SUCCESS)
505  return result;
506 
507  lex->lex_level--;
508 
509  if (aend != NULL)
510  (*aend) (sem->semstate);
511 
512  return JSON_SUCCESS;
513 }
json_struct_action array_end
Definition: jsonapi.h:110
int lex_level
Definition: jsonapi.h:81
void check_stack_depth(void)
Definition: postgres.c:3469
JsonParseErrorType
Definition: jsonapi.h:36
static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:425
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
json_struct_action array_start
Definition: jsonapi.h:109
void(* json_struct_action)(void *state)
Definition: jsonapi.h:87
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:82
void * semstate
Definition: jsonapi.h:106

◆ parse_array_element()

static JsonParseErrorType parse_array_element ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 425 of file jsonapi.c.

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JSON_SUCCESS, JSON_TOKEN_ARRAY_START, JSON_TOKEN_NULL, JSON_TOKEN_OBJECT_START, lex_peek(), parse_array(), parse_object(), parse_scalar(), and JsonSemAction::semstate.

Referenced by json_count_array_elements(), and parse_array().

426 {
429  JsonTokenType tok = lex_peek(lex);
430  JsonParseErrorType result;
431 
432  bool isnull;
433 
434  isnull = tok == JSON_TOKEN_NULL;
435 
436  if (astart != NULL)
437  (*astart) (sem->semstate, isnull);
438 
439  /* an array element is any object, array or scalar */
440  switch (tok)
441  {
443  result = parse_object(lex, sem);
444  break;
446  result = parse_array(lex, sem);
447  break;
448  default:
449  result = parse_scalar(lex, sem);
450  }
451 
452  if (result != JSON_SUCCESS)
453  return result;
454 
455  if (aend != NULL)
456  (*aend) (sem->semstate, isnull);
457 
458  return JSON_SUCCESS;
459 }
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:262
JsonParseErrorType
Definition: jsonapi.h:36
json_aelem_action array_element_start
Definition: jsonapi.h:113
static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:359
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
void(* json_aelem_action)(void *state, bool isnull)
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:106
json_aelem_action array_element_end
Definition: jsonapi.h:114
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:462
JsonTokenType
Definition: jsonapi.h:19

◆ parse_object()

static JsonParseErrorType parse_object ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 359 of file jsonapi.c.

References Assert, check_stack_depth(), json_lex(), JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_START, JSON_SUCCESS, JSON_TOKEN_COMMA, JSON_TOKEN_OBJECT_END, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, lex_expect(), JsonLexContext::lex_level, lex_peek(), JsonSemAction::object_end, JsonSemAction::object_start, parse_object_field(), report_parse_error(), and JsonSemAction::semstate.

Referenced by parse_array_element(), parse_object_field(), and pg_parse_json().

360 {
361  /*
362  * an object is a possibly empty sequence of object fields, separated by
363  * commas and surrounded by curly braces.
364  */
365  json_struct_action ostart = sem->object_start;
366  json_struct_action oend = sem->object_end;
367  JsonTokenType tok;
368  JsonParseErrorType result;
369 
370 #ifndef FRONTEND
372 #endif
373 
374  if (ostart != NULL)
375  (*ostart) (sem->semstate);
376 
377  /*
378  * Data inside an object is at a higher nesting level than the object
379  * itself. Note that we increment this after we call the semantic routine
380  * for the object start and restore it before we call the routine for the
381  * object end.
382  */
383  lex->lex_level++;
384 
386  result = json_lex(lex);
387  if (result != JSON_SUCCESS)
388  return result;
389 
390  tok = lex_peek(lex);
391  switch (tok)
392  {
393  case JSON_TOKEN_STRING:
394  result = parse_object_field(lex, sem);
395  while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
396  {
397  result = json_lex(lex);
398  if (result != JSON_SUCCESS)
399  break;
400  result = parse_object_field(lex, sem);
401  }
402  break;
404  break;
405  default:
406  /* case of an invalid initial token inside the object */
408  }
409  if (result != JSON_SUCCESS)
410  return result;
411 
413  if (result != JSON_SUCCESS)
414  return result;
415 
416  lex->lex_level--;
417 
418  if (oend != NULL)
419  (*oend) (sem->semstate);
420 
421  return JSON_SUCCESS;
422 }
json_struct_action object_end
Definition: jsonapi.h:108
json_struct_action object_start
Definition: jsonapi.h:107
int lex_level
Definition: jsonapi.h:81
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
Definition: jsonapi.c:1009
void check_stack_depth(void)
Definition: postgres.c:3469
JsonParseErrorType
Definition: jsonapi.h:36
static JsonParseErrorType parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:306
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
#define Assert(condition)
Definition: c.h:804
void(* json_struct_action)(void *state)
Definition: jsonapi.h:87
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:82
void * semstate
Definition: jsonapi.h:106
JsonTokenType
Definition: jsonapi.h:19

◆ parse_object_field()

static JsonParseErrorType parse_object_field ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 306 of file jsonapi.c.

References StringInfoData::data, json_lex(), JSON_PARSE_OBJECT_LABEL, JSON_PARSE_STRING, JSON_SUCCESS, JSON_TOKEN_ARRAY_START, JSON_TOKEN_COLON, JSON_TOKEN_NULL, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, lex_expect(), lex_peek(), JsonSemAction::object_field_end, JsonSemAction::object_field_start, parse_array(), parse_object(), parse_scalar(), pstrdup(), report_parse_error(), JsonSemAction::semstate, and JsonLexContext::strval.

Referenced by parse_object().

307 {
308  /*
309  * An object field is "fieldname" : value where value can be a scalar,
310  * object or array. Note: in user-facing docs and error messages, we
311  * generally call a field name a "key".
312  */
313 
314  char *fname = NULL; /* keep compiler quiet */
317  bool isnull;
318  JsonTokenType tok;
319  JsonParseErrorType result;
320 
321  if (lex_peek(lex) != JSON_TOKEN_STRING)
323  if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
324  fname = pstrdup(lex->strval->data);
325  result = json_lex(lex);
326  if (result != JSON_SUCCESS)
327  return result;
328 
330  if (result != JSON_SUCCESS)
331  return result;
332 
333  tok = lex_peek(lex);
334  isnull = tok == JSON_TOKEN_NULL;
335 
336  if (ostart != NULL)
337  (*ostart) (sem->semstate, fname, isnull);
338 
339  switch (tok)
340  {
342  result = parse_object(lex, sem);
343  break;
345  result = parse_array(lex, sem);
346  break;
347  default:
348  result = parse_scalar(lex, sem);
349  }
350  if (result != JSON_SUCCESS)
351  return result;
352 
353  if (oend != NULL)
354  (*oend) (sem->semstate, fname, isnull);
355  return JSON_SUCCESS;
356 }
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:262
char * pstrdup(const char *in)
Definition: mcxt.c:1299
void(* json_ofield_action)(void *state, char *fname, bool isnull)
Definition: jsonapi.h:88
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
Definition: jsonapi.c:1009
StringInfo strval
Definition: jsonapi.h:84
json_ofield_action object_field_end
Definition: jsonapi.h:112
JsonParseErrorType
Definition: jsonapi.h:36
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:359
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
json_ofield_action object_field_start
Definition: jsonapi.h:111
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:82
void * semstate
Definition: jsonapi.h:106
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:462
JsonTokenType
Definition: jsonapi.h:19

◆ parse_scalar()

static JsonParseErrorType parse_scalar ( JsonLexContext lex,
JsonSemAction sem 
)
inlinestatic

Definition at line 262 of file jsonapi.c.

References StringInfoData::data, json_lex(), JSON_PARSE_VALUE, JSON_SUCCESS, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, lex_peek(), palloc(), pstrdup(), report_parse_error(), JsonSemAction::scalar, JsonSemAction::semstate, JsonLexContext::strval, JsonLexContext::token_start, JsonLexContext::token_terminator, and val.

Referenced by parse_array_element(), parse_object_field(), and pg_parse_json().

263 {
264  char *val = NULL;
265  json_scalar_action sfunc = sem->scalar;
266  JsonTokenType tok = lex_peek(lex);
267  JsonParseErrorType result;
268 
269  /* a scalar must be a string, a number, true, false, or null */
270  if (tok != JSON_TOKEN_STRING && tok != JSON_TOKEN_NUMBER &&
271  tok != JSON_TOKEN_TRUE && tok != JSON_TOKEN_FALSE &&
272  tok != JSON_TOKEN_NULL)
274 
275  /* if no semantic function, just consume the token */
276  if (sfunc == NULL)
277  return json_lex(lex);
278 
279  /* extract the de-escaped string value, or the raw lexeme */
280  if (lex_peek(lex) == JSON_TOKEN_STRING)
281  {
282  if (lex->strval != NULL)
283  val = pstrdup(lex->strval->data);
284  }
285  else
286  {
287  int len = (lex->token_terminator - lex->token_start);
288 
289  val = palloc(len + 1);
290  memcpy(val, lex->token_start, len);
291  val[len] = '\0';
292  }
293 
294  /* consume the token */
295  result = json_lex(lex);
296  if (result != JSON_SUCCESS)
297  return result;
298 
299  /* invoke the callback */
300  (*sfunc) (sem->semstate, val, tok);
301 
302  return JSON_SUCCESS;
303 }
void(* json_scalar_action)(void *state, char *token, JsonTokenType tokentype)
Definition: jsonapi.h:90
char * pstrdup(const char *in)
Definition: mcxt.c:1299
json_scalar_action scalar
Definition: jsonapi.h:115
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
Definition: jsonapi.c:1009
StringInfo strval
Definition: jsonapi.h:84
char * token_start
Definition: jsonapi.h:77
char * token_terminator
Definition: jsonapi.h:78
JsonParseErrorType
Definition: jsonapi.h:36
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
void * palloc(Size size)
Definition: mcxt.c:1062
void * semstate
Definition: jsonapi.h:106
long val
Definition: informix.c:664
JsonTokenType
Definition: jsonapi.h:19

◆ pg_parse_json()

JsonParseErrorType pg_parse_json ( JsonLexContext lex,
JsonSemAction sem 
)

Definition at line 168 of file jsonapi.c.

References json_lex(), JSON_PARSE_END, JSON_SUCCESS, JSON_TOKEN_ARRAY_START, JSON_TOKEN_END, JSON_TOKEN_OBJECT_START, lex_expect(), lex_peek(), parse_array(), parse_object(), and parse_scalar().

Referenced by json_parse_manifest(), and pg_parse_json_or_ereport().

169 {
170  JsonTokenType tok;
171  JsonParseErrorType result;
172 
173  /* get the initial token */
174  result = json_lex(lex);
175  if (result != JSON_SUCCESS)
176  return result;
177 
178  tok = lex_peek(lex);
179 
180  /* parse by recursive descent */
181  switch (tok)
182  {
184  result = parse_object(lex, sem);
185  break;
187  result = parse_array(lex, sem);
188  break;
189  default:
190  result = parse_scalar(lex, sem); /* json can be a bare scalar */
191  }
192 
193  if (result == JSON_SUCCESS)
194  result = lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
195 
196  return result;
197 }
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:262
JsonParseErrorType
Definition: jsonapi.h:36
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:359
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:70
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:82
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:462
JsonTokenType
Definition: jsonapi.h:19

◆ report_parse_error()

static JsonParseErrorType report_parse_error ( JsonParseContext  ctx,
JsonLexContext lex 
)
static

Definition at line 1009 of file jsonapi.c.

References Assert, 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_PARSE_ARRAY_NEXT, JSON_PARSE_ARRAY_START, JSON_PARSE_END, JSON_PARSE_OBJECT_COMMA, JSON_PARSE_OBJECT_LABEL, JSON_PARSE_OBJECT_NEXT, JSON_PARSE_OBJECT_START, JSON_PARSE_STRING, JSON_PARSE_VALUE, JSON_SUCCESS, JSON_TOKEN_END, JsonLexContext::token_start, and JsonLexContext::token_type.

Referenced by lex_expect(), parse_object(), parse_object_field(), and parse_scalar().

1010 {
1011  /* Handle case where the input ended prematurely. */
1012  if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END)
1013  return JSON_EXPECTED_MORE;
1014 
1015  /* Otherwise choose the error type based on the parsing context. */
1016  switch (ctx)
1017  {
1018  case JSON_PARSE_END:
1019  return JSON_EXPECTED_END;
1020  case JSON_PARSE_VALUE:
1021  return JSON_EXPECTED_JSON;
1022  case JSON_PARSE_STRING:
1023  return JSON_EXPECTED_STRING;
1026  case JSON_PARSE_ARRAY_NEXT:
1027  return JSON_EXPECTED_ARRAY_NEXT;
1031  return JSON_EXPECTED_COLON;
1035  return JSON_EXPECTED_STRING;
1036  }
1037 
1038  /*
1039  * We don't use a default: case, so that the compiler will warn about
1040  * unhandled enum values.
1041  */
1042  Assert(false);
1043  return JSON_SUCCESS; /* silence stupider compilers */
1044 }
JsonTokenType token_type
Definition: jsonapi.h:80
char * token_start
Definition: jsonapi.h:77
#define Assert(condition)
Definition: c.h:804

Variable Documentation

◆ nullSemAction

JsonSemAction nullSemAction
Initial value:
=
{
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL
}

Definition at line 56 of file jsonapi.c.

Referenced by json_in(), and json_recv().