LCOV - code coverage report
Current view: top level - src/backend/utils/adt - numutils.c (source / functions) Hit Total Coverage
Test: PostgreSQL 14devel Lines: 187 204 91.7 %
Date: 2020-11-27 10:06:39 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * numutils.c
       4             :  *    utility functions for I/O of built-in numeric types.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/adt/numutils.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include <math.h>
      18             : #include <limits.h>
      19             : #include <ctype.h>
      20             : 
      21             : #include "common/int.h"
      22             : #include "utils/builtins.h"
      23             : #include "port/pg_bitutils.h"
      24             : 
      25             : /*
      26             :  * A table of all two-digit numbers. This is used to speed up decimal digit
      27             :  * generation by copying pairs of digits into the final output.
      28             :  */
      29             : static const char DIGIT_TABLE[200] =
      30             : "00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
      31             : "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
      32             : "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
      33             : "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
      34             : "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
      35             : "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
      36             : "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
      37             : "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
      38             : "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
      39             : "90" "91" "92" "93" "94" "95" "96" "97" "98" "99";
      40             : 
      41             : /*
      42             :  * Adapted from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
      43             :  */
      44             : static inline int
      45     6631090 : decimalLength32(const uint32 v)
      46             : {
      47             :     int         t;
      48             :     static const uint32 PowersOfTen[] = {
      49             :         1, 10, 100,
      50             :         1000, 10000, 100000,
      51             :         1000000, 10000000, 100000000,
      52             :         1000000000
      53             :     };
      54             : 
      55             :     /*
      56             :      * Compute base-10 logarithm by dividing the base-2 logarithm by a
      57             :      * good-enough approximation of the base-2 logarithm of 10
      58             :      */
      59     6631090 :     t = (pg_leftmost_one_pos32(v) + 1) * 1233 / 4096;
      60     6631090 :     return t + (v >= PowersOfTen[t]);
      61             : }
      62             : 
      63             : static inline int
      64      174386 : decimalLength64(const uint64 v)
      65             : {
      66             :     int         t;
      67             :     static const uint64 PowersOfTen[] = {
      68             :         UINT64CONST(1), UINT64CONST(10),
      69             :         UINT64CONST(100), UINT64CONST(1000),
      70             :         UINT64CONST(10000), UINT64CONST(100000),
      71             :         UINT64CONST(1000000), UINT64CONST(10000000),
      72             :         UINT64CONST(100000000), UINT64CONST(1000000000),
      73             :         UINT64CONST(10000000000), UINT64CONST(100000000000),
      74             :         UINT64CONST(1000000000000), UINT64CONST(10000000000000),
      75             :         UINT64CONST(100000000000000), UINT64CONST(1000000000000000),
      76             :         UINT64CONST(10000000000000000), UINT64CONST(100000000000000000),
      77             :         UINT64CONST(1000000000000000000), UINT64CONST(10000000000000000000)
      78             :     };
      79             : 
      80             :     /*
      81             :      * Compute base-10 logarithm by dividing the base-2 logarithm by a
      82             :      * good-enough approximation of the base-2 logarithm of 10
      83             :      */
      84      174386 :     t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096;
      85      174386 :     return t + (v >= PowersOfTen[t]);
      86             : }
      87             : 
      88             : /*
      89             :  * pg_atoi: convert string to integer
      90             :  *
      91             :  * allows any number of leading or trailing whitespace characters.
      92             :  *
      93             :  * 'size' is the sizeof() the desired integral result (1, 2, or 4 bytes).
      94             :  *
      95             :  * c, if not 0, is a terminator character that may appear after the
      96             :  * integer (plus whitespace).  If 0, the string must end after the integer.
      97             :  *
      98             :  * Unlike plain atoi(), this will throw ereport() upon bad input format or
      99             :  * overflow.
     100             :  */
     101             : int32
     102         278 : pg_atoi(const char *s, int size, int c)
     103             : {
     104             :     long        l;
     105             :     char       *badp;
     106             : 
     107             :     /*
     108             :      * Some versions of strtol treat the empty string as an error, but some
     109             :      * seem not to.  Make an explicit test to be sure we catch it.
     110             :      */
     111         278 :     if (s == NULL)
     112           0 :         elog(ERROR, "NULL pointer");
     113         278 :     if (*s == 0)
     114           0 :         ereport(ERROR,
     115             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     116             :                  errmsg("invalid input syntax for type %s: \"%s\"",
     117             :                         "integer", s)));
     118             : 
     119         278 :     errno = 0;
     120         278 :     l = strtol(s, &badp, 10);
     121             : 
     122             :     /* We made no progress parsing the string, so bail out */
     123         278 :     if (s == badp)
     124           0 :         ereport(ERROR,
     125             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     126             :                  errmsg("invalid input syntax for type %s: \"%s\"",
     127             :                         "integer", s)));
     128             : 
     129         278 :     switch (size)
     130             :     {
     131         188 :         case sizeof(int32):
     132         188 :             if (errno == ERANGE
     133             : #if defined(HAVE_LONG_INT_64)
     134             :             /* won't get ERANGE on these with 64-bit longs... */
     135         188 :                 || l < INT_MIN || l > INT_MAX
     136             : #endif
     137             :                 )
     138           0 :                 ereport(ERROR,
     139             :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     140             :                          errmsg("value \"%s\" is out of range for type %s", s,
     141             :                                 "integer")));
     142         188 :             break;
     143          90 :         case sizeof(int16):
     144          90 :             if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
     145           0 :                 ereport(ERROR,
     146             :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     147             :                          errmsg("value \"%s\" is out of range for type %s", s,
     148             :                                 "smallint")));
     149          90 :             break;
     150           0 :         case sizeof(int8):
     151           0 :             if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
     152           0 :                 ereport(ERROR,
     153             :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     154             :                          errmsg("value \"%s\" is out of range for 8-bit integer", s)));
     155           0 :             break;
     156           0 :         default:
     157           0 :             elog(ERROR, "unsupported result size: %d", size);
     158             :     }
     159             : 
     160             :     /*
     161             :      * Skip any trailing whitespace; if anything but whitespace remains before
     162             :      * the terminating character, bail out
     163             :      */
     164         278 :     while (*badp && *badp != c && isspace((unsigned char) *badp))
     165           0 :         badp++;
     166             : 
     167         278 :     if (*badp && *badp != c)
     168           0 :         ereport(ERROR,
     169             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     170             :                  errmsg("invalid input syntax for type %s: \"%s\"",
     171             :                         "integer", s)));
     172             : 
     173         278 :     return (int32) l;
     174             : }
     175             : 
     176             : /*
     177             :  * Convert input string to a signed 16 bit integer.
     178             :  *
     179             :  * Allows any number of leading or trailing whitespace characters. Will throw
     180             :  * ereport() upon bad input format or overflow.
     181             :  *
     182             :  * NB: Accumulate input as a negative number, to deal with two's complement
     183             :  * representation of the most negative number, which can't be represented as a
     184             :  * positive number.
     185             :  */
     186             : int16
     187     3119064 : pg_strtoint16(const char *s)
     188             : {
     189     3119064 :     const char *ptr = s;
     190     3119064 :     int16       tmp = 0;
     191     3119064 :     bool        neg = false;
     192             : 
     193             :     /* skip leading spaces */
     194     3119104 :     while (likely(*ptr) && isspace((unsigned char) *ptr))
     195          40 :         ptr++;
     196             : 
     197             :     /* handle sign */
     198     3119064 :     if (*ptr == '-')
     199             :     {
     200       65590 :         ptr++;
     201       65590 :         neg = true;
     202             :     }
     203     3053474 :     else if (*ptr == '+')
     204           0 :         ptr++;
     205             : 
     206             :     /* require at least one digit */
     207     3119064 :     if (unlikely(!isdigit((unsigned char) *ptr)))
     208          20 :         goto invalid_syntax;
     209             : 
     210             :     /* process digits */
     211     6319496 :     while (*ptr && isdigit((unsigned char) *ptr))
     212             :     {
     213     3200456 :         int8        digit = (*ptr++ - '0');
     214             : 
     215     3200456 :         if (unlikely(pg_mul_s16_overflow(tmp, 10, &tmp)) ||
     216     3200452 :             unlikely(pg_sub_s16_overflow(tmp, digit, &tmp)))
     217           4 :             goto out_of_range;
     218             :     }
     219             : 
     220             :     /* allow trailing whitespace, but not other trailing chars */
     221     3119064 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
     222          24 :         ptr++;
     223             : 
     224     3119040 :     if (unlikely(*ptr != '\0'))
     225          12 :         goto invalid_syntax;
     226             : 
     227     3119028 :     if (!neg)
     228             :     {
     229             :         /* could fail if input is most negative number */
     230     3053442 :         if (unlikely(tmp == PG_INT16_MIN))
     231           0 :             goto out_of_range;
     232     3053442 :         tmp = -tmp;
     233             :     }
     234             : 
     235     3119028 :     return tmp;
     236             : 
     237           4 : out_of_range:
     238           4 :     ereport(ERROR,
     239             :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     240             :              errmsg("value \"%s\" is out of range for type %s",
     241             :                     s, "smallint")));
     242             : 
     243          32 : invalid_syntax:
     244          32 :     ereport(ERROR,
     245             :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     246             :              errmsg("invalid input syntax for type %s: \"%s\"",
     247             :                     "smallint", s)));
     248             : 
     249             :     return 0;                   /* keep compiler quiet */
     250             : }
     251             : 
     252             : /*
     253             :  * Convert input string to a signed 32 bit integer.
     254             :  *
     255             :  * Allows any number of leading or trailing whitespace characters. Will throw
     256             :  * ereport() upon bad input format or overflow.
     257             :  *
     258             :  * NB: Accumulate input as a negative number, to deal with two's complement
     259             :  * representation of the most negative number, which can't be represented as a
     260             :  * positive number.
     261             :  */
     262             : int32
     263     4767142 : pg_strtoint32(const char *s)
     264             : {
     265     4767142 :     const char *ptr = s;
     266     4767142 :     int32       tmp = 0;
     267     4767142 :     bool        neg = false;
     268             : 
     269             :     /* skip leading spaces */
     270     4767224 :     while (likely(*ptr) && isspace((unsigned char) *ptr))
     271          82 :         ptr++;
     272             : 
     273             :     /* handle sign */
     274     4767142 :     if (*ptr == '-')
     275             :     {
     276      251616 :         ptr++;
     277      251616 :         neg = true;
     278             :     }
     279     4515526 :     else if (*ptr == '+')
     280           0 :         ptr++;
     281             : 
     282             :     /* require at least one digit */
     283     4767142 :     if (unlikely(!isdigit((unsigned char) *ptr)))
     284          74 :         goto invalid_syntax;
     285             : 
     286             :     /* process digits */
     287    15206196 :     while (*ptr && isdigit((unsigned char) *ptr))
     288             :     {
     289    10439132 :         int8        digit = (*ptr++ - '0');
     290             : 
     291    10439132 :         if (unlikely(pg_mul_s32_overflow(tmp, 10, &tmp)) ||
     292    10439128 :             unlikely(pg_sub_s32_overflow(tmp, digit, &tmp)))
     293           4 :             goto out_of_range;
     294             :     }
     295             : 
     296             :     /* allow trailing whitespace, but not other trailing chars */
     297     4767120 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
     298          56 :         ptr++;
     299             : 
     300     4767064 :     if (unlikely(*ptr != '\0'))
     301          12 :         goto invalid_syntax;
     302             : 
     303     4767052 :     if (!neg)
     304             :     {
     305             :         /* could fail if input is most negative number */
     306     4515440 :         if (unlikely(tmp == PG_INT32_MIN))
     307           0 :             goto out_of_range;
     308     4515440 :         tmp = -tmp;
     309             :     }
     310             : 
     311     4767052 :     return tmp;
     312             : 
     313           4 : out_of_range:
     314           4 :     ereport(ERROR,
     315             :             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     316             :              errmsg("value \"%s\" is out of range for type %s",
     317             :                     s, "integer")));
     318             : 
     319          86 : invalid_syntax:
     320          86 :     ereport(ERROR,
     321             :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     322             :              errmsg("invalid input syntax for type %s: \"%s\"",
     323             :                     "integer", s)));
     324             : 
     325             :     return 0;                   /* keep compiler quiet */
     326             : }
     327             : 
     328             : /*
     329             :  * pg_itoa: converts a signed 16-bit integer to its string representation
     330             :  * and returns strlen(a).
     331             :  *
     332             :  * Caller must ensure that 'a' points to enough memory to hold the result
     333             :  * (at least 7 bytes, counting a leading sign and trailing NUL).
     334             :  *
     335             :  * It doesn't seem worth implementing this separately.
     336             :  */
     337             : int
     338      112192 : pg_itoa(int16 i, char *a)
     339             : {
     340      112192 :     return pg_ltoa((int32) i, a);
     341             : }
     342             : 
     343             : /*
     344             :  * pg_ultoa_n: converts an unsigned 32-bit integer to its string representation,
     345             :  * not NUL-terminated, and returns the length of that string representation
     346             :  *
     347             :  * Caller must ensure that 'a' points to enough memory to hold the result (at
     348             :  * least 10 bytes)
     349             :  */
     350             : int
     351     7422592 : pg_ultoa_n(uint32 value, char *a)
     352             : {
     353             :     int         olength,
     354     7422592 :                 i = 0;
     355             : 
     356             :     /* Degenerate case */
     357     7422592 :     if (value == 0)
     358             :     {
     359      791502 :         *a = '0';
     360      791502 :         return 1;
     361             :     }
     362             : 
     363     6631090 :     olength = decimalLength32(value);
     364             : 
     365             :     /* Compute the result string. */
     366     7668006 :     while (value >= 10000)
     367             :     {
     368     1036916 :         const uint32 c = value - 10000 * (value / 10000);
     369     1036916 :         const uint32 c0 = (c % 100) << 1;
     370     1036916 :         const uint32 c1 = (c / 100) << 1;
     371             : 
     372     1036916 :         char       *pos = a + olength - i;
     373             : 
     374     1036916 :         value /= 10000;
     375             : 
     376     1036916 :         memcpy(pos - 2, DIGIT_TABLE + c0, 2);
     377     1036916 :         memcpy(pos - 4, DIGIT_TABLE + c1, 2);
     378     1036916 :         i += 4;
     379             :     }
     380     6631090 :     if (value >= 100)
     381             :     {
     382     3351584 :         const uint32 c = (value % 100) << 1;
     383             : 
     384     3351584 :         char       *pos = a + olength - i;
     385             : 
     386     3351584 :         value /= 100;
     387             : 
     388     3351584 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     389     3351584 :         i += 2;
     390             :     }
     391     6631090 :     if (value >= 10)
     392             :     {
     393     3633320 :         const uint32 c = value << 1;
     394             : 
     395     3633320 :         char       *pos = a + olength - i;
     396             : 
     397     3633320 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     398             :     }
     399             :     else
     400             :     {
     401     2997770 :         *a = (char) ('0' + value);
     402             :     }
     403             : 
     404     6631090 :     return olength;
     405             : }
     406             : 
     407             : /*
     408             :  * pg_ltoa: converts a signed 32-bit integer to its string representation and
     409             :  * returns strlen(a).
     410             :  *
     411             :  * It is the caller's responsibility to ensure that a is at least 12 bytes long,
     412             :  * which is enough room to hold a minus sign, a maximally long int32, and the
     413             :  * above terminating NUL.
     414             :  */
     415             : int
     416     7333286 : pg_ltoa(int32 value, char *a)
     417             : {
     418     7333286 :     uint32      uvalue = (uint32) value;
     419     7333286 :     int         len = 0;
     420             : 
     421     7333286 :     if (value < 0)
     422             :     {
     423       87536 :         uvalue = (uint32) 0 - uvalue;
     424       87536 :         a[len++] = '-';
     425             :     }
     426     7333286 :     len += pg_ultoa_n(uvalue, a + len);
     427     7333286 :     a[len] = '\0';
     428     7333286 :     return len;
     429             : }
     430             : 
     431             : /*
     432             :  * Get the decimal representation, not NUL-terminated, and return the length of
     433             :  * same.  Caller must ensure that a points to at least MAXINT8LEN bytes.
     434             :  */
     435             : int
     436      183922 : pg_ulltoa_n(uint64 value, char *a)
     437             : {
     438             :     int         olength,
     439      183922 :                 i = 0;
     440             :     uint32      value2;
     441             : 
     442             :     /* Degenerate case */
     443      183922 :     if (value == 0)
     444             :     {
     445        9536 :         *a = '0';
     446        9536 :         return 1;
     447             :     }
     448             : 
     449      174386 :     olength = decimalLength64(value);
     450             : 
     451             :     /* Compute the result string. */
     452      181630 :     while (value >= 100000000)
     453             :     {
     454        7244 :         const uint64 q = value / 100000000;
     455        7244 :         uint32      value2 = (uint32) (value - 100000000 * q);
     456             : 
     457        7244 :         const uint32 c = value2 % 10000;
     458        7244 :         const uint32 d = value2 / 10000;
     459        7244 :         const uint32 c0 = (c % 100) << 1;
     460        7244 :         const uint32 c1 = (c / 100) << 1;
     461        7244 :         const uint32 d0 = (d % 100) << 1;
     462        7244 :         const uint32 d1 = (d / 100) << 1;
     463             : 
     464        7244 :         char       *pos = a + olength - i;
     465             : 
     466        7244 :         value = q;
     467             : 
     468        7244 :         memcpy(pos - 2, DIGIT_TABLE + c0, 2);
     469        7244 :         memcpy(pos - 4, DIGIT_TABLE + c1, 2);
     470        7244 :         memcpy(pos - 6, DIGIT_TABLE + d0, 2);
     471        7244 :         memcpy(pos - 8, DIGIT_TABLE + d1, 2);
     472        7244 :         i += 8;
     473             :     }
     474             : 
     475             :     /* Switch to 32-bit for speed */
     476      174386 :     value2 = (uint32) value;
     477             : 
     478      174386 :     if (value2 >= 10000)
     479             :     {
     480       15672 :         const uint32 c = value2 - 10000 * (value2 / 10000);
     481       15672 :         const uint32 c0 = (c % 100) << 1;
     482       15672 :         const uint32 c1 = (c / 100) << 1;
     483             : 
     484       15672 :         char       *pos = a + olength - i;
     485             : 
     486       15672 :         value2 /= 10000;
     487             : 
     488       15672 :         memcpy(pos - 2, DIGIT_TABLE + c0, 2);
     489       15672 :         memcpy(pos - 4, DIGIT_TABLE + c1, 2);
     490       15672 :         i += 4;
     491             :     }
     492      174386 :     if (value2 >= 100)
     493             :     {
     494      127780 :         const uint32 c = (value2 % 100) << 1;
     495      127780 :         char       *pos = a + olength - i;
     496             : 
     497      127780 :         value2 /= 100;
     498             : 
     499      127780 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     500      127780 :         i += 2;
     501             :     }
     502      174386 :     if (value2 >= 10)
     503             :     {
     504       61784 :         const uint32 c = value2 << 1;
     505       61784 :         char       *pos = a + olength - i;
     506             : 
     507       61784 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     508             :     }
     509             :     else
     510      112602 :         *a = (char) ('0' + value2);
     511             : 
     512      174386 :     return olength;
     513             : }
     514             : 
     515             : /*
     516             :  * pg_lltoa: converts a signed 64-bit integer to its string representation and
     517             :  * returns strlen(a).
     518             :  *
     519             :  * Caller must ensure that 'a' points to enough memory to hold the result
     520             :  * (at least MAXINT8LEN + 1 bytes, counting a leading sign and trailing NUL).
     521             :  */
     522             : int
     523      183922 : pg_lltoa(int64 value, char *a)
     524             : {
     525      183922 :     uint64      uvalue = value;
     526      183922 :     int         len = 0;
     527             : 
     528      183922 :     if (value < 0)
     529             :     {
     530        1512 :         uvalue = (uint64) 0 - uvalue;
     531        1512 :         a[len++] = '-';
     532             :     }
     533             : 
     534      183922 :     len += pg_ulltoa_n(uvalue, a + len);
     535      183922 :     a[len] = '\0';
     536      183922 :     return len;
     537             : }
     538             : 
     539             : 
     540             : /*
     541             :  * pg_ultostr_zeropad
     542             :  *      Converts 'value' into a decimal string representation stored at 'str'.
     543             :  *      'minwidth' specifies the minimum width of the result; any extra space
     544             :  *      is filled up by prefixing the number with zeros.
     545             :  *
     546             :  * Returns the ending address of the string result (the last character written
     547             :  * plus 1).  Note that no NUL terminator is written.
     548             :  *
     549             :  * The intended use-case for this function is to build strings that contain
     550             :  * multiple individual numbers, for example:
     551             :  *
     552             :  *  str = pg_ultostr_zeropad(str, hours, 2);
     553             :  *  *str++ = ':';
     554             :  *  str = pg_ultostr_zeropad(str, mins, 2);
     555             :  *  *str++ = ':';
     556             :  *  str = pg_ultostr_zeropad(str, secs, 2);
     557             :  *  *str = '\0';
     558             :  *
     559             :  * Note: Caller must ensure that 'str' points to enough memory to hold the
     560             :  * result.
     561             :  */
     562             : char *
     563      544238 : pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth)
     564             : {
     565             :     int         len;
     566             : 
     567             :     Assert(minwidth > 0);
     568             : 
     569      544238 :     if (value < 100 && minwidth == 2)    /* Short cut for common case */
     570             :     {
     571      457060 :         memcpy(str, DIGIT_TABLE + value * 2, 2);
     572      457060 :         return str + 2;
     573             :     }
     574             : 
     575       87178 :     len = pg_ultoa_n(value, str);
     576       87178 :     if (len >= minwidth)
     577       86758 :         return str + len;
     578             : 
     579         420 :     memmove(str + minwidth - len, str, len);
     580         420 :     memset(str, '0', minwidth - len);
     581         420 :     return str + minwidth;
     582             : }
     583             : 
     584             : /*
     585             :  * pg_ultostr
     586             :  *      Converts 'value' into a decimal string representation stored at 'str'.
     587             :  *
     588             :  * Returns the ending address of the string result (the last character written
     589             :  * plus 1).  Note that no NUL terminator is written.
     590             :  *
     591             :  * The intended use-case for this function is to build strings that contain
     592             :  * multiple individual numbers, for example:
     593             :  *
     594             :  *  str = pg_ultostr(str, a);
     595             :  *  *str++ = ' ';
     596             :  *  str = pg_ultostr(str, b);
     597             :  *  *str = '\0';
     598             :  *
     599             :  * Note: Caller must ensure that 'str' points to enough memory to hold the
     600             :  * result.
     601             :  */
     602             : char *
     603        2128 : pg_ultostr(char *str, uint32 value)
     604             : {
     605        2128 :     int         len = pg_ultoa_n(value, str);
     606             : 
     607        2128 :     return str + len;
     608             : }
     609             : 
     610             : /*
     611             :  * pg_strtouint64
     612             :  *      Converts 'str' into an unsigned 64-bit integer.
     613             :  *
     614             :  * This has the identical API to strtoul(3), except that it will handle
     615             :  * 64-bit ints even where "long" is narrower than that.
     616             :  *
     617             :  * For the moment it seems sufficient to assume that the platform has
     618             :  * such a function somewhere; let's not roll our own.
     619             :  */
     620             : uint64
     621      300564 : pg_strtouint64(const char *str, char **endptr, int base)
     622             : {
     623             : #ifdef _MSC_VER                 /* MSVC only */
     624             :     return _strtoui64(str, endptr, base);
     625             : #elif defined(HAVE_STRTOULL) && SIZEOF_LONG < 8
     626             :     return strtoull(str, endptr, base);
     627             : #else
     628      300564 :     return strtoul(str, endptr, base);
     629             : #endif
     630             : }

Generated by: LCOV version 1.13