From 8ec6f93203684d63bf3c5d006c2499a71a1a9dad Mon Sep 17 00:00:00 2001
From: Nikita Glukhov <n.gluhov@postgrespro.ru>
Date: Thu, 5 Mar 2020 17:34:59 +0300
Subject: [PATCH 1/2] Replace 'if' with 'switch' in ltree code

---
 contrib/ltree/ltree_io.c | 402 ++++++++++++++++++++++++-----------------------
 1 file changed, 204 insertions(+), 198 deletions(-)

diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
index 900a46a..e97f035 100644
--- a/contrib/ltree/ltree_io.c
+++ b/contrib/ltree/ltree_io.c
@@ -69,40 +69,43 @@ ltree_in(PG_FUNCTION_ARGS)
 	{
 		charlen = pg_mblen(ptr);
 
-		if (state == LTPRS_WAITNAME)
+		switch (state)
 		{
-			if (ISALNUM(ptr))
-			{
-				lptr->start = ptr;
-				lptr->wlen = 0;
-				state = LTPRS_WAITDELIM;
-			}
-			else
-				UNCHAR;
-		}
-		else if (state == LTPRS_WAITDELIM)
-		{
-			if (charlen == 1 && t_iseq(ptr, '.'))
-			{
-				lptr->len = ptr - lptr->start;
-				if (lptr->wlen > 255)
-					ereport(ERROR,
-							(errcode(ERRCODE_NAME_TOO_LONG),
-							 errmsg("name of level is too long"),
-							 errdetail("Name length is %d, must "
-									   "be < 256, in position %d.",
-									   lptr->wlen, pos)));
-
-				totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
-				lptr++;
-				state = LTPRS_WAITNAME;
-			}
-			else if (!ISALNUM(ptr))
-				UNCHAR;
+			case LTPRS_WAITNAME:
+				if (ISALNUM(ptr))
+				{
+					lptr->start = ptr;
+					lptr->wlen = 0;
+					state = LTPRS_WAITDELIM;
+				}
+				else
+					UNCHAR;
+				break;
+
+			case LTPRS_WAITDELIM:
+				if (charlen == 1 && t_iseq(ptr, '.'))
+				{
+					lptr->len = ptr - lptr->start;
+					if (lptr->wlen > 255)
+						ereport(ERROR,
+								(errcode(ERRCODE_NAME_TOO_LONG),
+								 errmsg("name of level is too long"),
+								 errdetail("Name length is %d, must "
+										   "be < 256, in position %d.",
+										   lptr->wlen, pos)));
+
+					totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
+					lptr++;
+					state = LTPRS_WAITNAME;
+				}
+				else if (!ISALNUM(ptr))
+					UNCHAR;
+				break;
+
+			default:
+				/* internal error */
+				elog(ERROR, "internal error in parser");
 		}
-		else
-			/* internal error */
-			elog(ERROR, "internal error in parser");
 
 		ptr += charlen;
 		lptr->wlen++;
@@ -238,178 +241,181 @@ lquery_in(PG_FUNCTION_ARGS)
 	{
 		charlen = pg_mblen(ptr);
 
-		if (state == LQPRS_WAITLEVEL)
-		{
-			if (ISALNUM(ptr))
-			{
-				GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
-				lptr->start = ptr;
-				state = LQPRS_WAITDELIM;
-				curqlevel->numvar = 1;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '!'))
-			{
-				GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
-				lptr->start = ptr + 1;
-				state = LQPRS_WAITDELIM;
-				curqlevel->numvar = 1;
-				curqlevel->flag |= LQL_NOT;
-				hasnot = true;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '*'))
-				state = LQPRS_WAITOPEN;
-			else
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITVAR)
-		{
-			if (ISALNUM(ptr))
-			{
-				lptr++;
-				lptr->start = ptr;
-				state = LQPRS_WAITDELIM;
-				curqlevel->numvar++;
-			}
-			else
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITDELIM)
+		switch (state)
 		{
-			if (charlen == 1 && t_iseq(ptr, '@'))
-			{
-				if (lptr->start == ptr)
+			case LQPRS_WAITLEVEL:
+				if (ISALNUM(ptr))
+				{
+					GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+					lptr->start = ptr;
+					state = LQPRS_WAITDELIM;
+					curqlevel->numvar = 1;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '!'))
+				{
+					GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+					lptr->start = ptr + 1;
+					state = LQPRS_WAITDELIM;
+					curqlevel->numvar = 1;
+					curqlevel->flag |= LQL_NOT;
+					hasnot = true;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '*'))
+					state = LQPRS_WAITOPEN;
+				else
 					UNCHAR;
-				lptr->flag |= LVAR_INCASE;
-				curqlevel->flag |= LVAR_INCASE;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '*'))
-			{
-				if (lptr->start == ptr)
+				break;
+
+			case LQPRS_WAITVAR:
+				if (ISALNUM(ptr))
+				{
+					lptr++;
+					lptr->start = ptr;
+					state = LQPRS_WAITDELIM;
+					curqlevel->numvar++;
+				}
+				else
 					UNCHAR;
-				lptr->flag |= LVAR_ANYEND;
-				curqlevel->flag |= LVAR_ANYEND;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '%'))
-			{
-				if (lptr->start == ptr)
+				break;
+
+			case LQPRS_WAITDELIM:
+				if (charlen == 1 && t_iseq(ptr, '@'))
+				{
+					if (lptr->start == ptr)
+						UNCHAR;
+					lptr->flag |= LVAR_INCASE;
+					curqlevel->flag |= LVAR_INCASE;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '*'))
+				{
+					if (lptr->start == ptr)
+						UNCHAR;
+					lptr->flag |= LVAR_ANYEND;
+					curqlevel->flag |= LVAR_ANYEND;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '%'))
+				{
+					if (lptr->start == ptr)
+						UNCHAR;
+					lptr->flag |= LVAR_SUBLEXEME;
+					curqlevel->flag |= LVAR_SUBLEXEME;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '|'))
+				{
+					lptr->len = ptr - lptr->start -
+						((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
+						((lptr->flag & LVAR_INCASE) ? 1 : 0) -
+						((lptr->flag & LVAR_ANYEND) ? 1 : 0);
+					if (lptr->wlen > 255)
+						ereport(ERROR,
+								(errcode(ERRCODE_NAME_TOO_LONG),
+								 errmsg("name of level is too long"),
+								 errdetail("Name length is %d, must "
+										   "be < 256, in position %d.",
+										   lptr->wlen, pos)));
+
+					state = LQPRS_WAITVAR;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '.'))
+				{
+					lptr->len = ptr - lptr->start -
+						((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
+						((lptr->flag & LVAR_INCASE) ? 1 : 0) -
+						((lptr->flag & LVAR_ANYEND) ? 1 : 0);
+					if (lptr->wlen > 255)
+						ereport(ERROR,
+								(errcode(ERRCODE_NAME_TOO_LONG),
+								 errmsg("name of level is too long"),
+								 errdetail("Name length is %d, must "
+										   "be < 256, in position %d.",
+										   lptr->wlen, pos)));
+
+					state = LQPRS_WAITLEVEL;
+					curqlevel = NEXTLEV(curqlevel);
+				}
+				else if (ISALNUM(ptr))
+				{
+					if (lptr->flag)
+						UNCHAR;
+				}
+				else
 					UNCHAR;
-				lptr->flag |= LVAR_SUBLEXEME;
-				curqlevel->flag |= LVAR_SUBLEXEME;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '|'))
-			{
-				lptr->len = ptr - lptr->start -
-					((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
-					((lptr->flag & LVAR_INCASE) ? 1 : 0) -
-					((lptr->flag & LVAR_ANYEND) ? 1 : 0);
-				if (lptr->wlen > 255)
-					ereport(ERROR,
-							(errcode(ERRCODE_NAME_TOO_LONG),
-							 errmsg("name of level is too long"),
-							 errdetail("Name length is %d, must "
-									   "be < 256, in position %d.",
-									   lptr->wlen, pos)));
-
-				state = LQPRS_WAITVAR;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '.'))
-			{
-				lptr->len = ptr - lptr->start -
-					((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
-					((lptr->flag & LVAR_INCASE) ? 1 : 0) -
-					((lptr->flag & LVAR_ANYEND) ? 1 : 0);
-				if (lptr->wlen > 255)
-					ereport(ERROR,
-							(errcode(ERRCODE_NAME_TOO_LONG),
-							 errmsg("name of level is too long"),
-							 errdetail("Name length is %d, must "
-									   "be < 256, in position %d.",
-									   lptr->wlen, pos)));
-
-				state = LQPRS_WAITLEVEL;
-				curqlevel = NEXTLEV(curqlevel);
-			}
-			else if (ISALNUM(ptr))
-			{
-				if (lptr->flag)
+				break;
+
+			case LQPRS_WAITOPEN:
+				if (charlen == 1 && t_iseq(ptr, '{'))
+					state = LQPRS_WAITFNUM;
+				else if (charlen == 1 && t_iseq(ptr, '.'))
+				{
+					curqlevel->low = 0;
+					curqlevel->high = 0xffff;
+					curqlevel = NEXTLEV(curqlevel);
+					state = LQPRS_WAITLEVEL;
+				}
+				else
 					UNCHAR;
-			}
-			else
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITOPEN)
-		{
-			if (charlen == 1 && t_iseq(ptr, '{'))
-				state = LQPRS_WAITFNUM;
-			else if (charlen == 1 && t_iseq(ptr, '.'))
-			{
-				curqlevel->low = 0;
-				curqlevel->high = 0xffff;
-				curqlevel = NEXTLEV(curqlevel);
-				state = LQPRS_WAITLEVEL;
-			}
-			else
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITFNUM)
-		{
-			if (charlen == 1 && t_iseq(ptr, ','))
-				state = LQPRS_WAITSNUM;
-			else if (t_isdigit(ptr))
-			{
-				curqlevel->low = atoi(ptr);
-				state = LQPRS_WAITND;
-			}
-			else
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITSNUM)
-		{
-			if (t_isdigit(ptr))
-			{
-				curqlevel->high = atoi(ptr);
-				state = LQPRS_WAITCLOSE;
-			}
-			else if (charlen == 1 && t_iseq(ptr, '}'))
-			{
-				curqlevel->high = 0xffff;
-				state = LQPRS_WAITEND;
-			}
-			else
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITCLOSE)
-		{
-			if (charlen == 1 && t_iseq(ptr, '}'))
-				state = LQPRS_WAITEND;
-			else if (!t_isdigit(ptr))
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITND)
-		{
-			if (charlen == 1 && t_iseq(ptr, '}'))
-			{
-				curqlevel->high = curqlevel->low;
-				state = LQPRS_WAITEND;
-			}
-			else if (charlen == 1 && t_iseq(ptr, ','))
-				state = LQPRS_WAITSNUM;
-			else if (!t_isdigit(ptr))
-				UNCHAR;
-		}
-		else if (state == LQPRS_WAITEND)
-		{
-			if (charlen == 1 && t_iseq(ptr, '.'))
-			{
-				state = LQPRS_WAITLEVEL;
-				curqlevel = NEXTLEV(curqlevel);
-			}
-			else
-				UNCHAR;
+				break;
+
+			case LQPRS_WAITFNUM:
+				if (charlen == 1 && t_iseq(ptr, ','))
+					state = LQPRS_WAITSNUM;
+				else if (t_isdigit(ptr))
+				{
+					curqlevel->low = atoi(ptr);
+					state = LQPRS_WAITND;
+				}
+				else
+					UNCHAR;
+				break;
+
+			case LQPRS_WAITSNUM:
+				if (t_isdigit(ptr))
+				{
+					curqlevel->high = atoi(ptr);
+					state = LQPRS_WAITCLOSE;
+				}
+				else if (charlen == 1 && t_iseq(ptr, '}'))
+				{
+					curqlevel->high = 0xffff;
+					state = LQPRS_WAITEND;
+				}
+				else
+					UNCHAR;
+				break;
+
+			case LQPRS_WAITCLOSE:
+				if (charlen == 1 && t_iseq(ptr, '}'))
+					state = LQPRS_WAITEND;
+				else if (!t_isdigit(ptr))
+					UNCHAR;
+				break;
+
+			case LQPRS_WAITND:
+				if (charlen == 1 && t_iseq(ptr, '}'))
+				{
+					curqlevel->high = curqlevel->low;
+					state = LQPRS_WAITEND;
+				}
+				else if (charlen == 1 && t_iseq(ptr, ','))
+					state = LQPRS_WAITSNUM;
+				else if (!t_isdigit(ptr))
+					UNCHAR;
+				break;
+
+			case LQPRS_WAITEND:
+				if (charlen == 1 && t_iseq(ptr, '.'))
+				{
+					state = LQPRS_WAITLEVEL;
+					curqlevel = NEXTLEV(curqlevel);
+				}
+				else
+					UNCHAR;
+				break;
+
+			default:
+				/* internal error */
+				elog(ERROR, "internal error in parser");
 		}
-		else
-			/* internal error */
-			elog(ERROR, "internal error in parser");
 
 		ptr += charlen;
 		if (state == LQPRS_WAITDELIM)
-- 
2.7.4

