1 /*------------------------------------------------------------------------- 2 * 3 * jsonapi.h 4 * Declarations for JSON API support. 5 * 6 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * src/include/utils/jsonapi.h 10 * 11 *------------------------------------------------------------------------- 12 */ 13 14 #ifndef JSONAPI_H 15 #define JSONAPI_H 16 17 #include "lib/stringinfo.h" 18 19 typedef enum 20 { 21 JSON_TOKEN_INVALID, 22 JSON_TOKEN_STRING, 23 JSON_TOKEN_NUMBER, 24 JSON_TOKEN_OBJECT_START, 25 JSON_TOKEN_OBJECT_END, 26 JSON_TOKEN_ARRAY_START, 27 JSON_TOKEN_ARRAY_END, 28 JSON_TOKEN_COMMA, 29 JSON_TOKEN_COLON, 30 JSON_TOKEN_TRUE, 31 JSON_TOKEN_FALSE, 32 JSON_TOKEN_NULL, 33 JSON_TOKEN_END 34 } JsonTokenType; 35 36 37 /* 38 * All the fields in this structure should be treated as read-only. 39 * 40 * If strval is not null, then it should contain the de-escaped value 41 * of the lexeme if it's a string. Otherwise most of these field names 42 * should be self-explanatory. 43 * 44 * line_number and line_start are principally for use by the parser's 45 * error reporting routines. 46 * token_terminator and prev_token_terminator point to the character 47 * AFTER the end of the token, i.e. where there would be a nul byte 48 * if we were using nul-terminated strings. 49 */ 50 typedef struct JsonLexContext 51 { 52 char *input; 53 int input_length; 54 char *token_start; 55 char *token_terminator; 56 char *prev_token_terminator; 57 JsonTokenType token_type; 58 int lex_level; 59 int line_number; 60 char *line_start; 61 StringInfo strval; 62 } JsonLexContext; 63 64 typedef void (*json_struct_action) (void *state); 65 typedef void (*json_ofield_action) (void *state, char *fname, bool isnull); 66 typedef void (*json_aelem_action) (void *state, bool isnull); 67 typedef void (*json_scalar_action) (void *state, char *token, JsonTokenType tokentype); 68 69 70 /* 71 * Semantic Action structure for use in parsing json. 72 * Any of these actions can be NULL, in which case nothing is done at that 73 * point, Likewise, semstate can be NULL. Using an all-NULL structure amounts 74 * to doing a pure parse with no side-effects, and is therefore exactly 75 * what the json input routines do. 76 * 77 * The 'fname' and 'token' strings passed to these actions are palloc'd. 78 * They are not free'd or used further by the parser, so the action function 79 * is free to do what it wishes with them. 80 */ 81 typedef struct JsonSemAction 82 { 83 void *semstate; 84 json_struct_action object_start; 85 json_struct_action object_end; 86 json_struct_action array_start; 87 json_struct_action array_end; 88 json_ofield_action object_field_start; 89 json_ofield_action object_field_end; 90 json_aelem_action array_element_start; 91 json_aelem_action array_element_end; 92 json_scalar_action scalar; 93 } JsonSemAction; 94 95 /* 96 * parse_json will parse the string in the lex calling the 97 * action functions in sem at the appropriate points. It is 98 * up to them to keep what state they need in semstate. If they 99 * need access to the state of the lexer, then its pointer 100 * should be passed to them as a member of whatever semstate 101 * points to. If the action pointers are NULL the parser 102 * does nothing and just continues. 103 */ 104 extern void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem); 105 106 /* 107 * json_count_array_elements performs a fast secondary parse to determine the 108 * number of elements in passed array lex context. It should be called from an 109 * array_start action. 110 */ 111 extern int json_count_array_elements(JsonLexContext *lex); 112 113 /* 114 * constructors for JsonLexContext, with or without strval element. 115 * If supplied, the strval element will contain a de-escaped version of 116 * the lexeme. However, doing this imposes a performance penalty, so 117 * it should be avoided if the de-escaped lexeme is not required. 118 * 119 * If you already have the json as a text* value, use the first of these 120 * functions, otherwise use makeJsonLexContextCstringLen(). 121 */ 122 extern JsonLexContext *makeJsonLexContext(text *json, bool need_escapes); 123 extern JsonLexContext *makeJsonLexContextCstringLen(char *json, 124 int len, 125 bool need_escapes); 126 127 /* 128 * Utility function to check if a string is a valid JSON number. 129 * 130 * str agrument does not need to be nul-terminated. 131 */ 132 extern bool IsValidJsonNumber(const char *str, int len); 133 134 #endif /* JSONAPI_H */ 135