static JsonParseErrorType json_collection_object_field_start()

in src/collection_parse.c [60:171]


static JsonParseErrorType json_collection_object_field_start(void *state,
															 char *fname,
															 bool isnull);
static JsonParseErrorType json_collection_scalar(void *state,
												 char *token,
												 JsonTokenType tokentype);

CollectionHeader *
parse_collection(char *json)
{
	CollectionHeader *colhdr;
	MemoryContext oldcxt;
	ListCell   *lc1;
	ListCell   *lc2;
	Oid			typInput;
	Oid			typIOParam;
	int			i = 0;

	JsonParseErrorType json_error;
	JsonSemAction sem;
	JsonCollectionParseState parse;
	JsonCollectionParseContext context;

	colhdr = construct_empty_collection(CurrentMemoryContext);

	oldcxt = MemoryContextSwitchTo(colhdr->hdr.eoh_context);

	context.private_data = json;

	parse.context = &context;
	parse.state = EXPECT_TOPLEVEL_START;
#if (PG_VERSION_NUM >= 170000)
	parse.lex = makeJsonLexContextCstringLen(NULL, json, strlen(json), PG_UTF8, true);
#else
	parse.lex = makeJsonLexContextCstringLen(json, strlen(json), PG_UTF8, true);
#endif
	parse.keys = NIL;
	parse.values = NIL;
	parse.typname = NULL;

	/* Set up semantic actions. */
	sem.semstate = &parse;

#if (PG_VERSION_NUM >= 160000)
	sem.object_start = json_collection_object_start;
	sem.object_end = json_collection_object_end;
	sem.array_start = json_collection_array_start;
	sem.object_field_start = json_collection_object_field_start;
	sem.scalar = json_collection_scalar;
#else
	/* Quiet the compiler */
	sem.object_start = (void *) json_collection_object_start;
	sem.object_end = (void *) json_collection_object_end;
	sem.array_start = (void *) json_collection_array_start;
	sem.object_field_start = (void *) json_collection_object_field_start;
	sem.scalar = (void *) json_collection_scalar;
#endif
	sem.array_end = NULL;
	sem.object_field_end = NULL;
	sem.array_element_start = NULL;
	sem.array_element_end = NULL;

	json_error = pg_parse_json(parse.lex, &sem);
	if (json_error != JSON_SUCCESS)
		elog(ERROR, "Invalid format");

	if (parse.typname)
	{
		Oid			typid;

		typid = DatumGetObjectId(DirectFunctionCall1(regtypein, CStringGetDatum(parse.typname)));
		colhdr->value_type = typid;
		colhdr->value_type_len = get_typlen(typid);
		colhdr->value_byval = get_typbyval(typid);
	}
	else
	{
		colhdr->value_type = TEXTOID;
		colhdr->value_type_len = -1;
		colhdr->value_byval = false;
	}

	getTypeInputInfo(colhdr->value_type, &typInput, &typIOParam);

	forboth(lc1, parse.keys, lc2, parse.values)
	{
		collection *item;
		char	   *key = lfirst(lc1);
		char	   *vstr = lfirst(lc2);
		Datum		value;

		item = (collection *) palloc(sizeof(collection));

		item->key = key;

		value = OidFunctionCall1(typInput, CStringGetDatum(vstr));
		item->value = datumCopy(value, colhdr->value_byval, colhdr->value_type_len);

		HASH_ADD_KEYPTR(hh, colhdr->current, key, strlen(key), item);

		if (i == 0)
			colhdr->head = colhdr->current;

		i++;
	}

	colhdr->current = colhdr->head;

	MemoryContextSwitchTo(oldcxt);

	return colhdr;
}