Commits

Andrew Dunstan committed 011b0bc

Make parser more efficient, by reducing calls to lex_peek.

Comments (0)

Files changed (1)

src/backend/utils/adt/json.c

 static void json_lex(JsonLexContext *lex);
 static void json_lex_string(JsonLexContext *lex);
 static void json_lex_number(JsonLexContext *lex, char *s);
-static void parse_scalar(JsonLexContext *lex, JsonSemAction sem);
+static inline void parse_scalar(JsonLexContext *lex, JsonSemAction sem);
 static void parse_object_field(JsonLexContext *lex, JsonSemAction sem);
 static void parse_object(JsonLexContext *lex, JsonSemAction sem);
 static void parse_array_element(JsonLexContext *lex, JsonSemAction sem);
 void
 pg_parse_json(JsonLexContext *lex, JsonSemAction sem)
 {
+	JsonTokenType tok;
+
 	/* get the initial token */
 	json_lex(lex);
 
+	tok = lex_peek(lex);
 
 	/* parse by recursive descent */
-	if (lex_peek(lex) == JSON_TOKEN_OBJECT_START)
-		parse_object(lex, sem);
-	else if (lex_peek(lex) == JSON_TOKEN_ARRAY_START)
-		parse_array(lex, sem);
-	else
-		parse_scalar(lex, sem); /* json can be a bare scalar */
+	switch(tok)
+	{
+		case JSON_TOKEN_OBJECT_START:
+			parse_object(lex, sem);
+			break;
+		case JSON_TOKEN_ARRAY_START:
+			parse_array(lex, sem);
+			break;
+		default:
+			parse_scalar(lex, sem); /* json can be a bare scalar */
+	}
 
 	lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
 
 }
 
-static void
+static inline void
 parse_scalar(JsonLexContext *lex, JsonSemAction sem)
 {
 	char	   *val = NULL;
 
 	valaddr  = sfunc == NULL ? NULL : &val;
 
-	if (lex_accept(lex, JSON_TOKEN_TRUE, valaddr) ||
-		lex_accept(lex, JSON_TOKEN_FALSE, valaddr) ||
-		lex_accept(lex, JSON_TOKEN_NULL, valaddr) ||
-		lex_accept(lex, JSON_TOKEN_NUMBER, valaddr) ||
-		lex_accept(lex, JSON_TOKEN_STRING, valaddr))
-	{
-		if (sfunc != NULL)
-			(*sfunc) (sem->semstate, val, tok);
-	}
-	else
+	switch(tok)
 	{
-		report_parse_error(JSON_PARSE_VALUE, lex);
+		case JSON_TOKEN_TRUE:
+			lex_accept(lex, JSON_TOKEN_TRUE, valaddr);
+			break;
+		case JSON_TOKEN_FALSE:
+			lex_accept(lex, JSON_TOKEN_FALSE, valaddr);
+			break;
+		case JSON_TOKEN_NULL:
+			lex_accept(lex, JSON_TOKEN_NULL, valaddr);
+			break;
+		case JSON_TOKEN_NUMBER:
+			lex_accept(lex, JSON_TOKEN_NUMBER, valaddr);
+			break;
+		case JSON_TOKEN_STRING:
+			lex_accept(lex, JSON_TOKEN_STRING, valaddr);
+			break;
+		default:
+			report_parse_error(JSON_PARSE_VALUE, lex);	
 	}
+
+	if (sfunc != NULL)
+			(*sfunc) (sem->semstate, val, tok);
 }
 
 static void
 {
 	json_struct_action ostart = sem->object_start;
 	json_struct_action oend = sem->object_end;
+	JsonTokenType tok;
 
 	if (ostart != NULL)
 		(*ostart) (sem->semstate);
 
 	/* we know this will succeeed, just clearing the token */
 	lex_expect(JSON_PARSE_OBJECT_START, lex, JSON_TOKEN_OBJECT_START);
-	if (lex_peek(lex) == JSON_TOKEN_STRING)
-	{
-		parse_object_field(lex, sem);
-
-		while (lex_accept(lex, JSON_TOKEN_COMMA, NULL))
-			parse_object_field(lex, sem);
 
-	}
-	else if (lex_peek(lex) != JSON_TOKEN_OBJECT_END)
+	tok  = lex_peek(lex);
+	switch(tok)
 	{
-		/* case of an invalid initial token inside the object */
-		report_parse_error(JSON_PARSE_OBJECT_START, lex);
+		case JSON_TOKEN_STRING:
+			parse_object_field(lex, sem);
+			while (lex_accept(lex, JSON_TOKEN_COMMA, NULL))
+				parse_object_field(lex, sem);
+			break;
+		case JSON_TOKEN_OBJECT_END:
+			break;
+		default:
+			/* case of an invalid initial token inside the object */
+			report_parse_error(JSON_PARSE_OBJECT_START, lex);
 	}
 
 	lex_expect(JSON_PARSE_OBJECT_NEXT, lex, JSON_TOKEN_OBJECT_END);
 {
 	json_aelem_action astart = sem->array_element_start;
 	json_aelem_action aend = sem->array_element_end;
+	JsonTokenType tok = lex_peek(lex);
+	
 	bool		isnull;
 
-	isnull = lex_peek(lex) == JSON_TOKEN_NULL;
+	isnull = tok == JSON_TOKEN_NULL;
 
 	if (astart != NULL)
 		(*astart) (sem->semstate, isnull);
 
-	if (lex_peek(lex) == JSON_TOKEN_OBJECT_START)
-		parse_object(lex, sem);
-	else if (lex_peek(lex) == JSON_TOKEN_ARRAY_START)
-		parse_array(lex, sem);
-	else
-		parse_scalar(lex, sem);
+	switch(tok)
+	{
+		case JSON_TOKEN_OBJECT_START:
+			parse_object(lex, sem);
+			break;
+		case JSON_TOKEN_ARRAY_START:
+			parse_array(lex, sem);
+			break;
+		default:
+			parse_scalar(lex, sem);
+	}
 
 	if (aend != NULL)
 		(*aend) (sem->semstate, isnull);