From f190083fbc4ea2b9752950bf37a78f61abad12a0 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 6 Dec 2024 09:31:16 +1300
Subject: [PATCH v2 4/5] pgbench: Modernize integer parsing routine.

strtoint64() is from pre-C99 times and had comments about scanf() not
being sure to handle long long.   Even though C99 scanf() can do SCNi64,
it seems like we'd lose a bit of error reporting.  A more obvious modern
drop-in is strtoi64().  Then strtoint64() can log the same errors as
before.
---
 src/bin/pgbench/pgbench.c | 72 ++++++---------------------------------
 1 file changed, 11 insertions(+), 61 deletions(-)

diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index acf55eccafb..0a9d3eefc8f 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -1003,9 +1003,6 @@ is_an_int(const char *str)
 /*
  * strtoint64 -- convert a string to 64-bit integer
  *
- * This function is a slightly modified version of pg_strtoint64() from
- * src/backend/utils/adt/numutils.c.
- *
  * The function returns whether the conversion worked, and if so
  * "*result" is set to the result.
  *
@@ -1014,71 +1011,24 @@ is_an_int(const char *str)
 bool
 strtoint64(const char *str, bool errorOK, int64 *result)
 {
-	const char *ptr = str;
-	int64		tmp = 0;
-	bool		neg = false;
-
-	/*
-	 * Do our own scan, rather than relying on sscanf which might be broken
-	 * for long long.
-	 *
-	 * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
-	 * value as a negative number.
-	 */
+	char	   *end;
 
-	/* skip leading spaces */
-	while (*ptr && isspace((unsigned char) *ptr))
-		ptr++;
+	errno = 0;
+	*result = strtoi64(str, &end, 10);
 
-	/* handle sign */
-	if (*ptr == '-')
+	if (errno == ERANGE)
 	{
-		ptr++;
-		neg = true;
-	}
-	else if (*ptr == '+')
-		ptr++;
-
-	/* require at least one digit */
-	if (unlikely(!isdigit((unsigned char) *ptr)))
-		goto invalid_syntax;
-
-	/* process digits */
-	while (*ptr && isdigit((unsigned char) *ptr))
-	{
-		int8		digit = (*ptr++ - '0');
-
-		if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
-			unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
-			goto out_of_range;
+		if (!errorOK)
+			pg_log_error("value \"%s\" is out of range for type bigint", str);
+		return false;
 	}
-
-	/* allow trailing whitespace, but not other trailing chars */
-	while (*ptr != '\0' && isspace((unsigned char) *ptr))
-		ptr++;
-
-	if (unlikely(*ptr != '\0'))
-		goto invalid_syntax;
-
-	if (!neg)
+	if (str == end || *end != '\0')
 	{
-		if (unlikely(tmp == PG_INT64_MIN))
-			goto out_of_range;
-		tmp = -tmp;
+		if (!errorOK)
+			pg_log_error("invalid input syntax for type bigint: \"%s\"", str);
+		return false;
 	}
-
-	*result = tmp;
 	return true;
-
-out_of_range:
-	if (!errorOK)
-		pg_log_error("value \"%s\" is out of range for type bigint", str);
-	return false;
-
-invalid_syntax:
-	if (!errorOK)
-		pg_log_error("invalid input syntax for type bigint: \"%s\"", str);
-	return false;
 }
 
 /* convert string to double, detecting overflows/underflows */
-- 
2.48.1

