From 9c34fec11a9fc478b5333bb220b923695325a212 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Fri, 17 Jan 2020 14:06:41 -0500
Subject: [PATCH v2 3/4] Remove jsonapi.c's lex_accept().

At first glance, this function seems useful, but it actually increases
the amount of code required rather than decreasing it. Inline the
logic into the callers instead; most callers don't use the 'lexeme'
argument for anything and as a result considerable simplification is
possible.
---
 src/backend/utils/adt/jsonapi.c | 124 +++++++++++++-------------------
 1 file changed, 51 insertions(+), 73 deletions(-)

diff --git a/src/backend/utils/adt/jsonapi.c b/src/backend/utils/adt/jsonapi.c
index fc8af9f861..9e14306b6f 100644
--- a/src/backend/utils/adt/jsonapi.c
+++ b/src/backend/utils/adt/jsonapi.c
@@ -69,44 +69,7 @@ lex_peek(JsonLexContext *lex)
 }
 
 /*
- * lex_accept
- *
- * accept the look_ahead token and move the lexer to the next token if the
- * look_ahead token matches the token parameter. In that case, and if required,
- * also hand back the de-escaped lexeme.
- *
- * returns true if the token matched, false otherwise.
- */
-static inline bool
-lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
-{
-	if (lex->token_type == token)
-	{
-		if (lexeme != NULL)
-		{
-			if (lex->token_type == JSON_TOKEN_STRING)
-			{
-				if (lex->strval != NULL)
-					*lexeme = pstrdup(lex->strval->data);
-			}
-			else
-			{
-				int			len = (lex->token_terminator - lex->token_start);
-				char	   *tokstr = palloc(len + 1);
-
-				memcpy(tokstr, lex->token_start, len);
-				tokstr[len] = '\0';
-				*lexeme = tokstr;
-			}
-		}
-		json_lex(lex);
-		return true;
-	}
-	return false;
-}
-
-/*
- * lex_accept
+ * lex_expect
  *
  * move the lexer to the next token if the current look_ahead token matches
  * the parameter token. Otherwise, report an error.
@@ -114,7 +77,9 @@ lex_accept(JsonLexContext *lex, JsonTokenType token, char **lexeme)
 static inline void
 lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
 {
-	if (!lex_accept(lex, token, NULL))
+	if (lex_peek(lex) == token)
+		json_lex(lex);
+	else
 		report_parse_error(ctx, lex);
 }
 
@@ -260,12 +225,14 @@ json_count_array_elements(JsonLexContext *lex)
 	lex_expect(JSON_PARSE_ARRAY_START, &copylex, JSON_TOKEN_ARRAY_START);
 	if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
 	{
-		do
+		while (1)
 		{
 			count++;
 			parse_array_element(&copylex, &nullSemAction);
+			if (copylex.token_type != JSON_TOKEN_COMMA)
+				break;
+			json_lex(&copylex);
 		}
-		while (lex_accept(&copylex, JSON_TOKEN_COMMA, NULL));
 	}
 	lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex, JSON_TOKEN_ARRAY_END);
 
@@ -286,35 +253,41 @@ parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
 {
 	char	   *val = NULL;
 	json_scalar_action sfunc = sem->scalar;
-	char	  **valaddr;
 	JsonTokenType tok = lex_peek(lex);
 
-	valaddr = sfunc == NULL ? NULL : &val;
-
 	/* a scalar must be a string, a number, true, false, or null */
-	switch (tok)
+	if (tok != JSON_TOKEN_STRING && tok != JSON_TOKEN_NUMBER &&
+		tok != JSON_TOKEN_TRUE && tok != JSON_TOKEN_FALSE &&
+		tok != JSON_TOKEN_NULL)
+		report_parse_error(JSON_PARSE_VALUE, lex);
+
+	/* if no semantic function, just consume the token */
+	if (sfunc == NULL)
 	{
-		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);
+		json_lex(lex);
+		return;
+	}
+
+	/* extract the de-escaped string value, or the raw lexeme */
+	if (lex_peek(lex) == JSON_TOKEN_STRING)
+	{
+		if (lex->strval != NULL)
+			val = pstrdup(lex->strval->data);
+	}
+	else
+	{
+		int			len = (lex->token_terminator - lex->token_start);
+
+		val = palloc(len + 1);
+		memcpy(val, lex->token_start, len);
+		val[len] = '\0';
 	}
 
-	if (sfunc != NULL)
-		(*sfunc) (sem->semstate, val, tok);
+	/* consume the token */
+	json_lex(lex);
+
+	/* invoke the callback */
+	(*sfunc) (sem->semstate, val, tok);
 }
 
 static void
@@ -330,14 +303,13 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
 	json_ofield_action ostart = sem->object_field_start;
 	json_ofield_action oend = sem->object_field_end;
 	bool		isnull;
-	char	  **fnameaddr = NULL;
 	JsonTokenType tok;
 
-	if (ostart != NULL || oend != NULL)
-		fnameaddr = &fname;
-
-	if (!lex_accept(lex, JSON_TOKEN_STRING, fnameaddr))
+	if (lex_peek(lex) != JSON_TOKEN_STRING)
 		report_parse_error(JSON_PARSE_STRING, lex);
+	if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
+		fname = pstrdup(lex->strval->data);
+	json_lex(lex);
 
 	lex_expect(JSON_PARSE_OBJECT_LABEL, lex, JSON_TOKEN_COLON);
 
@@ -387,16 +359,19 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem)
 	 */
 	lex->lex_level++;
 
-	/* we know this will succeed, just clearing the token */
-	lex_expect(JSON_PARSE_OBJECT_START, lex, JSON_TOKEN_OBJECT_START);
+	Assert(lex_peek(lex) == JSON_TOKEN_OBJECT_START);
+	json_lex(lex);
 
 	tok = lex_peek(lex);
 	switch (tok)
 	{
 		case JSON_TOKEN_STRING:
 			parse_object_field(lex, sem);
-			while (lex_accept(lex, JSON_TOKEN_COMMA, NULL))
+			while (lex_peek(lex) == JSON_TOKEN_COMMA)
+			{
+				json_lex(lex);
 				parse_object_field(lex, sem);
+			}
 			break;
 		case JSON_TOKEN_OBJECT_END:
 			break;
@@ -473,8 +448,11 @@ parse_array(JsonLexContext *lex, JsonSemAction *sem)
 
 		parse_array_element(lex, sem);
 
-		while (lex_accept(lex, JSON_TOKEN_COMMA, NULL))
+		while (lex_peek(lex) == JSON_TOKEN_COMMA)
+		{
+			json_lex(lex);
 			parse_array_element(lex, sem);
+		}
 	}
 
 	lex_expect(JSON_PARSE_ARRAY_NEXT, lex, JSON_TOKEN_ARRAY_END);
-- 
2.17.2 (Apple Git-113)

