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_log_and_abort(...)   elog(ERROR, __VA_ARGS__)
 
#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 char * extract_token (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)
 
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 102 of file jsonapi.c.

Referenced by json_lex(), and json_lex_number().

◆ json_log_and_abort

#define json_log_and_abort (   ...)    elog(ERROR, __VA_ARGS__)

Definition at line 34 of file jsonapi.c.

Referenced by json_errdetail(), and report_parse_error().

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 42 of file jsonapi.c.

43 {
44  JSON_PARSE_VALUE, /* expecting a value */
45  JSON_PARSE_STRING, /* expecting a string (for a field name) */
46  JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
47  JSON_PARSE_ARRAY_NEXT, /* saw array element, expecting ',' or ']' */
48  JSON_PARSE_OBJECT_START, /* saw '{', expecting label or '}' */
49  JSON_PARSE_OBJECT_LABEL, /* saw object label, expecting ':' */
50  JSON_PARSE_OBJECT_NEXT, /* saw object value, expecting ',' or '}' */
51  JSON_PARSE_OBJECT_COMMA, /* saw object ',', expecting next label */
52  JSON_PARSE_END /* saw the end of a document, expect nothing */
JsonParseContext
Definition: jsonapi.c:42

Function Documentation

◆ extract_token()

static char * extract_token ( JsonLexContext lex)
static

Definition at line 1126 of file jsonapi.c.

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

Referenced by json_errdetail().

1127 {
1128  int toklen = lex->token_terminator - lex->token_start;
1129  char *token = palloc(toklen + 1);
1130 
1131  memcpy(token, lex->token_start, toklen);
1132  token[toklen] = '\0';
1133  return token;
1134 }
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 115 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().

116 {
117  bool numeric_error;
118  int total_len;
119  JsonLexContext dummy_lex;
120 
121  if (len <= 0)
122  return false;
123 
124  /*
125  * json_lex_number expects a leading '-' to have been eaten already.
126  *
127  * having to cast away the constness of str is ugly, but there's not much
128  * easy alternative.
129  */
130  if (*str == '-')
131  {
132  dummy_lex.input = unconstify(char *, str) + 1;
133  dummy_lex.input_length = len - 1;
134  }
135  else
136  {
137  dummy_lex.input = unconstify(char *, str);
138  dummy_lex.input_length = len;
139  }
140 
141  json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
142 
143  return (!numeric_error) && (total_len == dummy_lex.input_length);
144 }
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:916

◆ json_count_array_elements()

JsonParseErrorType json_count_array_elements ( JsonLexContext lex,
int *  elements 
)

Definition at line 219 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().

220 {
221  JsonLexContext copylex;
222  int count;
223  JsonParseErrorType result;
224 
225  /*
226  * It's safe to do this with a shallow copy because the lexical routines
227  * don't scribble on the input. They do scribble on the other pointers
228  * etc, so doing this with a copy makes that safe.
229  */
230  memcpy(&copylex, lex, sizeof(JsonLexContext));
231  copylex.strval = NULL; /* not interested in values here */
232  copylex.lex_level++;
233 
234  count = 0;
235  result = lex_expect(JSON_PARSE_ARRAY_START, &copylex,
237  if (result != JSON_SUCCESS)
238  return result;
239  if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
240  {
241  while (1)
242  {
243  count++;
244  result = parse_array_element(&copylex, &nullSemAction);
245  if (result != JSON_SUCCESS)
246  return result;
247  if (copylex.token_type != JSON_TOKEN_COMMA)
248  break;
249  result = json_lex(&copylex);
250  if (result != JSON_SUCCESS)
251  return result;
252  }
253  }
254  result = lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex,
256  if (result != JSON_SUCCESS)
257  return result;
258 
259  *elements = count;
260  return JSON_SUCCESS;
261 }
JsonTokenType token_type
Definition: jsonapi.h:80
JsonSemAction nullSemAction
Definition: jsonapi.c:67
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:434
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:526
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:81
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:93

◆ json_errdetail()

char* json_errdetail ( JsonParseErrorType  error,
JsonLexContext lex 
)

Definition at line 1058 of file jsonapi.c.

References _, 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_log_and_abort, 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(), and json_parse_manifest().

1059 {
1060  switch (error)
1061  {
1062  case JSON_SUCCESS:
1063  /* fall through to the error code after switch */
1064  break;
1065  case JSON_ESCAPING_INVALID:
1066  return psprintf(_("Escape sequence \"\\%s\" is invalid."),
1067  extract_token(lex));
1069  return psprintf(_("Character with value 0x%02x must be escaped."),
1070  (unsigned char) *(lex->token_terminator));
1071  case JSON_EXPECTED_END:
1072  return psprintf(_("Expected end of input, but found \"%s\"."),
1073  extract_token(lex));
1075  return psprintf(_("Expected array element or \"]\", but found \"%s\"."),
1076  extract_token(lex));
1078  return psprintf(_("Expected \",\" or \"]\", but found \"%s\"."),
1079  extract_token(lex));
1080  case JSON_EXPECTED_COLON:
1081  return psprintf(_("Expected \":\", but found \"%s\"."),
1082  extract_token(lex));
1083  case JSON_EXPECTED_JSON:
1084  return psprintf(_("Expected JSON value, but found \"%s\"."),
1085  extract_token(lex));
1086  case JSON_EXPECTED_MORE:
1087  return _("The input string ended unexpectedly.");
1089  return psprintf(_("Expected string or \"}\", but found \"%s\"."),
1090  extract_token(lex));
1092  return psprintf(_("Expected \",\" or \"}\", but found \"%s\"."),
1093  extract_token(lex));
1094  case JSON_EXPECTED_STRING:
1095  return psprintf(_("Expected string, but found \"%s\"."),
1096  extract_token(lex));
1097  case JSON_INVALID_TOKEN:
1098  return psprintf(_("Token \"%s\" is invalid."),
1099  extract_token(lex));
1101  return _("\\u0000 cannot be converted to text.");
1103  return _("\"\\u\" must be followed by four hexadecimal digits.");
1105  /* note: this case is only reachable in frontend not backend */
1106  return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
1108  return _("Unicode high surrogate must not follow a high surrogate.");
1110  return _("Unicode low surrogate must follow a high surrogate.");
1111  }
1112 
1113  /*
1114  * We don't use a default: case, so that the compiler will warn about
1115  * unhandled enum values. But this needs to be here anyway to cover the
1116  * possibility of an incorrect input.
1117  */
1118  json_log_and_abort("unexpected json parse error type: %d", (int) error);
1119  return NULL; /* silence stupider compilers */
1120 }
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:1126
char * token_terminator
Definition: jsonapi.h:78
#define json_log_and_abort(...)
Definition: jsonapi.c:34
#define _(x)
Definition: elog.c:89

◆ json_lex()

JsonParseErrorType json_lex ( JsonLexContext lex)

Definition at line 526 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().

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

◆ json_lex_number()

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

Definition at line 916 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().

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

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

94 {
95  if (lex_peek(lex) == token)
96  return json_lex(lex);
97  else
98  return report_parse_error(ctx, lex);
99 }
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
Definition: jsonapi.c:1016
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:526
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:81

◆ lex_peek()

static JsonTokenType lex_peek ( JsonLexContext lex)
inlinestatic

◆ makeJsonLexContextCstringLen()

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

Definition at line 155 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().

156 {
157  JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
158 
159  lex->input = lex->token_terminator = lex->line_start = json;
160  lex->line_number = 1;
161  lex->input_length = len;
162  lex->input_encoding = encoding;
163  if (need_escapes)
164  lex->strval = makeStringInfo();
165  return lex;
166 }
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 471 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().

472 {
473  /*
474  * an array is a possibly empty sequence of array elements, separated by
475  * commas and surrounded by square brackets.
476  */
477  json_struct_action astart = sem->array_start;
478  json_struct_action aend = sem->array_end;
479  JsonParseErrorType result;
480 
482 
483  if (astart != NULL)
484  (*astart) (sem->semstate);
485 
486  /*
487  * Data inside an array is at a higher nesting level than the array
488  * itself. Note that we increment this after we call the semantic routine
489  * for the array start and restore it before we call the routine for the
490  * array end.
491  */
492  lex->lex_level++;
493 
495  if (result == JSON_SUCCESS && lex_peek(lex) != JSON_TOKEN_ARRAY_END)
496  {
497  result = parse_array_element(lex, sem);
498 
499  while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
500  {
501  result = json_lex(lex);
502  if (result != JSON_SUCCESS)
503  break;
504  result = parse_array_element(lex, sem);
505  }
506  }
507  if (result != JSON_SUCCESS)
508  return result;
509 
511  if (result != JSON_SUCCESS)
512  return result;
513 
514  lex->lex_level--;
515 
516  if (aend != NULL)
517  (*aend) (sem->semstate);
518 
519  return JSON_SUCCESS;
520 }
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:434
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:526
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:81
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:93
void * semstate
Definition: jsonapi.h:106

◆ parse_array_element()

static JsonParseErrorType parse_array_element ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 434 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().

435 {
438  JsonTokenType tok = lex_peek(lex);
439  JsonParseErrorType result;
440 
441  bool isnull;
442 
443  isnull = tok == JSON_TOKEN_NULL;
444 
445  if (astart != NULL)
446  (*astart) (sem->semstate, isnull);
447 
448  /* an array element is any object, array or scalar */
449  switch (tok)
450  {
452  result = parse_object(lex, sem);
453  break;
455  result = parse_array(lex, sem);
456  break;
457  default:
458  result = parse_scalar(lex, sem);
459  }
460 
461  if (result != JSON_SUCCESS)
462  return result;
463 
464  if (aend != NULL)
465  (*aend) (sem->semstate, isnull);
466 
467  return JSON_SUCCESS;
468 }
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:273
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:370
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:81
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:471
JsonTokenType
Definition: jsonapi.h:19

◆ parse_object()

static JsonParseErrorType parse_object ( JsonLexContext lex,
JsonSemAction sem 
)
static

Definition at line 370 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().

371 {
372  /*
373  * an object is a possibly empty sequence of object fields, separated by
374  * commas and surrounded by curly braces.
375  */
376  json_struct_action ostart = sem->object_start;
377  json_struct_action oend = sem->object_end;
378  JsonTokenType tok;
379  JsonParseErrorType result;
380 
382 
383  if (ostart != NULL)
384  (*ostart) (sem->semstate);
385 
386  /*
387  * Data inside an object is at a higher nesting level than the object
388  * itself. Note that we increment this after we call the semantic routine
389  * for the object start and restore it before we call the routine for the
390  * object end.
391  */
392  lex->lex_level++;
393 
395  result = json_lex(lex);
396  if (result != JSON_SUCCESS)
397  return result;
398 
399  tok = lex_peek(lex);
400  switch (tok)
401  {
402  case JSON_TOKEN_STRING:
403  result = parse_object_field(lex, sem);
404  while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
405  {
406  result = json_lex(lex);
407  if (result != JSON_SUCCESS)
408  break;
409  result = parse_object_field(lex, sem);
410  }
411  break;
413  break;
414  default:
415  /* case of an invalid initial token inside the object */
417  }
418  if (result != JSON_SUCCESS)
419  return result;
420 
422  if (result != JSON_SUCCESS)
423  return result;
424 
425  lex->lex_level--;
426 
427  if (oend != NULL)
428  (*oend) (sem->semstate);
429 
430  return JSON_SUCCESS;
431 }
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:1016
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:317
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:526
#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:81
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:93
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 317 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().

318 {
319  /*
320  * An object field is "fieldname" : value where value can be a scalar,
321  * object or array. Note: in user-facing docs and error messages, we
322  * generally call a field name a "key".
323  */
324 
325  char *fname = NULL; /* keep compiler quiet */
328  bool isnull;
329  JsonTokenType tok;
330  JsonParseErrorType result;
331 
332  if (lex_peek(lex) != JSON_TOKEN_STRING)
334  if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
335  fname = pstrdup(lex->strval->data);
336  result = json_lex(lex);
337  if (result != JSON_SUCCESS)
338  return result;
339 
341  if (result != JSON_SUCCESS)
342  return result;
343 
344  tok = lex_peek(lex);
345  isnull = tok == JSON_TOKEN_NULL;
346 
347  if (ostart != NULL)
348  (*ostart) (sem->semstate, fname, isnull);
349 
350  switch (tok)
351  {
353  result = parse_object(lex, sem);
354  break;
356  result = parse_array(lex, sem);
357  break;
358  default:
359  result = parse_scalar(lex, sem);
360  }
361  if (result != JSON_SUCCESS)
362  return result;
363 
364  if (oend != NULL)
365  (*oend) (sem->semstate, fname, isnull);
366  return JSON_SUCCESS;
367 }
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:273
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:1016
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:526
static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:370
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:81
json_ofield_action object_field_start
Definition: jsonapi.h:111
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:93
void * semstate
Definition: jsonapi.h:106
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:471
JsonTokenType
Definition: jsonapi.h:19

◆ parse_scalar()

static JsonParseErrorType parse_scalar ( JsonLexContext lex,
JsonSemAction sem 
)
inlinestatic

Definition at line 273 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().

274 {
275  char *val = NULL;
276  json_scalar_action sfunc = sem->scalar;
277  JsonTokenType tok = lex_peek(lex);
278  JsonParseErrorType result;
279 
280  /* a scalar must be a string, a number, true, false, or null */
281  if (tok != JSON_TOKEN_STRING && tok != JSON_TOKEN_NUMBER &&
282  tok != JSON_TOKEN_TRUE && tok != JSON_TOKEN_FALSE &&
283  tok != JSON_TOKEN_NULL)
285 
286  /* if no semantic function, just consume the token */
287  if (sfunc == NULL)
288  return json_lex(lex);
289 
290  /* extract the de-escaped string value, or the raw lexeme */
291  if (lex_peek(lex) == JSON_TOKEN_STRING)
292  {
293  if (lex->strval != NULL)
294  val = pstrdup(lex->strval->data);
295  }
296  else
297  {
298  int len = (lex->token_terminator - lex->token_start);
299 
300  val = palloc(len + 1);
301  memcpy(val, lex->token_start, len);
302  val[len] = '\0';
303  }
304 
305  /* consume the token */
306  result = json_lex(lex);
307  if (result != JSON_SUCCESS)
308  return result;
309 
310  /* invoke the callback */
311  (*sfunc) (sem->semstate, val, tok);
312 
313  return JSON_SUCCESS;
314 }
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:1016
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:526
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:81
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 179 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().

180 {
181  JsonTokenType tok;
182  JsonParseErrorType result;
183 
184  /* get the initial token */
185  result = json_lex(lex);
186  if (result != JSON_SUCCESS)
187  return result;
188 
189  tok = lex_peek(lex);
190 
191  /* parse by recursive descent */
192  switch (tok)
193  {
195  result = parse_object(lex, sem);
196  break;
198  result = parse_array(lex, sem);
199  break;
200  default:
201  result = parse_scalar(lex, sem); /* json can be a bare scalar */
202  }
203 
204  if (result == JSON_SUCCESS)
205  result = lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
206 
207  return result;
208 }
static JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:273
JsonParseErrorType
Definition: jsonapi.h:36
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:526
static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:370
static JsonTokenType lex_peek(JsonLexContext *lex)
Definition: jsonapi.c:81
static JsonParseErrorType lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
Definition: jsonapi.c:93
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:471
JsonTokenType
Definition: jsonapi.h:19

◆ report_parse_error()

static JsonParseErrorType report_parse_error ( JsonParseContext  ctx,
JsonLexContext lex 
)
static

Definition at line 1016 of file jsonapi.c.

References 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_log_and_abort, 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().

1017 {
1018  /* Handle case where the input ended prematurely. */
1019  if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END)
1020  return JSON_EXPECTED_MORE;
1021 
1022  /* Otherwise choose the error type based on the parsing context. */
1023  switch (ctx)
1024  {
1025  case JSON_PARSE_END:
1026  return JSON_EXPECTED_END;
1027  case JSON_PARSE_VALUE:
1028  return JSON_EXPECTED_JSON;
1029  case JSON_PARSE_STRING:
1030  return JSON_EXPECTED_STRING;
1033  case JSON_PARSE_ARRAY_NEXT:
1034  return JSON_EXPECTED_ARRAY_NEXT;
1038  return JSON_EXPECTED_COLON;
1042  return JSON_EXPECTED_STRING;
1043  }
1044 
1045  /*
1046  * We don't use a default: case, so that the compiler will warn about
1047  * unhandled enum values. But this needs to be here anyway to cover the
1048  * possibility of an incorrect input.
1049  */
1050  json_log_and_abort("unexpected json parse state: %d", (int) ctx);
1051  return JSON_SUCCESS; /* silence stupider compilers */
1052 }
JsonTokenType token_type
Definition: jsonapi.h:80
char * token_start
Definition: jsonapi.h:77
#define json_log_and_abort(...)
Definition: jsonapi.c:34

Variable Documentation

◆ nullSemAction

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

Definition at line 67 of file jsonapi.c.

Referenced by json_in(), and json_recv().