Simplify the general-purpose 64-bit integer parsing APIs
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 17 Dec 2021 05:05:54 +0000 (06:05 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 17 Dec 2021 05:32:07 +0000 (06:32 +0100)
pg_strtouint64() is a wrapper around strtoull/strtoul/_strtoui64, but
it seems no longer necessary to have this indirection.
msvc/Solution.pm claims HAVE_STRTOULL, so the "MSVC only" part seems
unnecessary.  Also, we have code in c.h to substitute alternatives for
strtoull() if not found, and that would appear to cover all currently
supported platforms, so having a further fallback in pg_strtouint64()
seems unnecessary.

Therefore, we could remove pg_strtouint64(), and use strtoull()
directly in all call sites.  However, it seems useful to keep a
separate notation for parsing exactly 64-bit integers, matching the
type definition int64/uint64.  For that, add new macros strtoi64() and
strtou64() in c.h as thin wrappers around strtol()/strtoul() or
strtoll()/stroull().  This makes these functions available everywhere
instead of just in the server code, and it makes the function naming
notably different from the pg_strtointNN() functions in numutils.c,
which have a different API.

Discussion: https://www.postgresql.org/message-id/flat/a3df47c9-b1b4-29f2-7e91-427baf8b75a3%40enterprisedb.com

src/backend/nodes/readfuncs.c
src/backend/utils/adt/numutils.c
src/backend/utils/adt/xid.c
src/backend/utils/adt/xid8funcs.c
src/backend/utils/misc/guc.c
src/include/c.h
src/include/utils/builtins.h

index dcec3b728f2d2fb3227f4b7e8d130f90570eed7b..76cff8a2b15ed18b6013af95b1bf78b7a6b5fe01 100644 (file)
@@ -80,7 +80,7 @@
 #define READ_UINT64_FIELD(fldname) \
    token = pg_strtok(&length);     /* skip :fldname */ \
    token = pg_strtok(&length);     /* get field value */ \
-   local_node->fldname = pg_strtouint64(token, NULL, 10)
+   local_node->fldname = strtou64(token, NULL, 10)
 
 /* Read a long integer field (anything written as ":fldname %ld") */
 #define READ_LONG_FIELD(fldname) \
index b93096f288f38ac846d6e1eb70e8a41e16dbed2b..6a9c00fdd3ef49d1f9713787f9dfa00b48736ccf 100644 (file)
@@ -606,25 +606,3 @@ pg_ultostr(char *str, uint32 value)
 
    return str + len;
 }
-
-/*
- * pg_strtouint64
- *     Converts 'str' into an unsigned 64-bit integer.
- *
- * This has the identical API to strtoul(3), except that it will handle
- * 64-bit ints even where "long" is narrower than that.
- *
- * For the moment it seems sufficient to assume that the platform has
- * such a function somewhere; let's not roll our own.
- */
-uint64
-pg_strtouint64(const char *str, char **endptr, int base)
-{
-#ifdef _MSC_VER                    /* MSVC only */
-   return _strtoui64(str, endptr, base);
-#elif defined(HAVE_STRTOULL) && SIZEOF_LONG < 8
-   return strtoull(str, endptr, base);
-#else
-   return strtoul(str, endptr, base);
-#endif
-}
index 24c1c9373265d2de7561b20603e4011d2e4e79bb..a09096d0187f7b10618292f738cadf5e2d66ca08 100644 (file)
@@ -158,7 +158,7 @@ xid8in(PG_FUNCTION_ARGS)
 {
    char       *str = PG_GETARG_CSTRING(0);
 
-   PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(pg_strtouint64(str, NULL, 0)));
+   PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(strtou64(str, NULL, 0)));
 }
 
 Datum
index f1870a73668c1d0d7d32c0c17ce2a2c2756e6928..68985dca5a683f98ffe3ab2ea8b4b3679d19970a 100644 (file)
@@ -295,12 +295,12 @@ parse_snapshot(const char *str)
    char       *endp;
    StringInfo  buf;
 
-   xmin = FullTransactionIdFromU64(pg_strtouint64(str, &endp, 10));
+   xmin = FullTransactionIdFromU64(strtou64(str, &endp, 10));
    if (*endp != ':')
        goto bad_format;
    str = endp + 1;
 
-   xmax = FullTransactionIdFromU64(pg_strtouint64(str, &endp, 10));
+   xmax = FullTransactionIdFromU64(strtou64(str, &endp, 10));
    if (*endp != ':')
        goto bad_format;
    str = endp + 1;
@@ -318,7 +318,7 @@ parse_snapshot(const char *str)
    while (*str != '\0')
    {
        /* read next value */
-       val = FullTransactionIdFromU64(pg_strtouint64(str, &endp, 10));
+       val = FullTransactionIdFromU64(strtou64(str, &endp, 10));
        str = endp;
 
        /* require the input to be in order */
index f736e8d8725389255b035fd8bf09d1bff6cefbd7..7b030463013c4b761f348ef18fce0f513be66848 100644 (file)
@@ -12438,7 +12438,7 @@ check_recovery_target_xid(char **newval, void **extra, GucSource source)
        TransactionId *myextra;
 
        errno = 0;
-       xid = (TransactionId) pg_strtouint64(*newval, NULL, 0);
+       xid = (TransactionId) strtou64(*newval, NULL, 0);
        if (errno == EINVAL || errno == ERANGE)
            return false;
 
index 7e591171a84c27d1299da97e56b10a5acf8064c6..98c0b053c989f432c8b54d90471aff21784e88c8 100644 (file)
@@ -1312,6 +1312,19 @@ extern long long strtoll(const char *str, char **endptr, int base);
 extern unsigned long long strtoull(const char *str, char **endptr, int base);
 #endif
 
+/*
+ * Thin wrappers that convert strings to exactly 64-bit integers, matching our
+ * definition of int64.  (For the naming, compare that POSIX has
+ * strtoimax()/strtoumax() which return intmax_t/uintmax_t.)
+ */
+#ifdef HAVE_LONG_INT_64
+#define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base))
+#define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base))
+#else
+#define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base))
+#define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base))
+#endif
+
 /*
  * Use "extern PGDLLIMPORT ..." to declare variables that are defined
  * in the core backend and need to be accessible by loadable modules.
index 40fcb0ab6d74e5e28524b085a6dde77672eac30f..b07eefaf1ed3d78b657c6c0e8d7fa8d16fe92a07 100644 (file)
@@ -53,7 +53,6 @@ extern int    pg_ltoa(int32 l, char *a);
 extern int pg_lltoa(int64 ll, char *a);
 extern char *pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth);
 extern char *pg_ultostr(char *str, uint32 value);
-extern uint64 pg_strtouint64(const char *str, char **endptr, int base);
 
 /* oid.c */
 extern oidvector *buildoidvector(const Oid *oids, int n);