LCOV - code coverage report
Current view: top level - src/backend/utils/adt - numutils.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 186 203 91.6 %
Date: 2020-05-28 23:07:14 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     6158522 : 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     6158522 :     t = (pg_leftmost_one_pos32(v) + 1) * 1233 / 4096;
      60     6158522 :     return t + (v >= PowersOfTen[t]);
      61             : }
      62             : 
      63             : static inline int
      64      171674 : 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      171674 :     t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096;
      85      171674 :     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     2809222 : pg_strtoint16(const char *s)
     188             : {
     189     2809222 :     const char *ptr = s;
     190     2809222 :     int16       tmp = 0;
     191     2809222 :     bool        neg = false;
     192             : 
     193             :     /* skip leading spaces */
     194     2809262 :     while (likely(*ptr) && isspace((unsigned char) *ptr))
     195          40 :         ptr++;
     196             : 
     197             :     /* handle sign */
     198     2809222 :     if (*ptr == '-')
     199             :     {
     200       57926 :         ptr++;
     201       57926 :         neg = true;
     202             :     }
     203     2751296 :     else if (*ptr == '+')
     204           0 :         ptr++;
     205             : 
     206             :     /* require at least one digit */
     207     2809222 :     if (unlikely(!isdigit((unsigned char) *ptr)))
     208          20 :         goto invalid_syntax;
     209             : 
     210             :     /* process digits */
     211     5692002 :     while (*ptr && isdigit((unsigned char) *ptr))
     212             :     {
     213     2882804 :         int8        digit = (*ptr++ - '0');
     214             : 
     215     2882804 :         if (unlikely(pg_mul_s16_overflow(tmp, 10, &tmp)) ||
     216     2882800 :             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     2809222 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
     222          24 :         ptr++;
     223             : 
     224     2809198 :     if (unlikely(*ptr != '\0'))
     225          12 :         goto invalid_syntax;
     226             : 
     227     2809186 :     if (!neg)
     228             :     {
     229             :         /* could fail if input is most negative number */
     230     2751264 :         if (unlikely(tmp == PG_INT16_MIN))
     231           0 :             goto out_of_range;
     232     2751264 :         tmp = -tmp;
     233             :     }
     234             : 
     235     2809186 :     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     4469194 : pg_strtoint32(const char *s)
     264             : {
     265     4469194 :     const char *ptr = s;
     266     4469194 :     int32       tmp = 0;
     267     4469194 :     bool        neg = false;
     268             : 
     269             :     /* skip leading spaces */
     270     4469276 :     while (likely(*ptr) && isspace((unsigned char) *ptr))
     271          82 :         ptr++;
     272             : 
     273             :     /* handle sign */
     274     4469194 :     if (*ptr == '-')
     275             :     {
     276      211670 :         ptr++;
     277      211670 :         neg = true;
     278             :     }
     279     4257524 :     else if (*ptr == '+')
     280           0 :         ptr++;
     281             : 
     282             :     /* require at least one digit */
     283     4469194 :     if (unlikely(!isdigit((unsigned char) *ptr)))
     284          74 :         goto invalid_syntax;
     285             : 
     286             :     /* process digits */
     287    14318598 :     while (*ptr && isdigit((unsigned char) *ptr))
     288             :     {
     289     9849482 :         int8        digit = (*ptr++ - '0');
     290             : 
     291     9849482 :         if (unlikely(pg_mul_s32_overflow(tmp, 10, &tmp)) ||
     292     9849478 :             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     4469172 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
     298          56 :         ptr++;
     299             : 
     300     4469116 :     if (unlikely(*ptr != '\0'))
     301          12 :         goto invalid_syntax;
     302             : 
     303     4469104 :     if (!neg)
     304             :     {
     305             :         /* could fail if input is most negative number */
     306     4257438 :         if (unlikely(tmp == PG_INT32_MIN))
     307           0 :             goto out_of_range;
     308     4257438 :         tmp = -tmp;
     309             :     }
     310             : 
     311     4469104 :     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             :  *
     331             :  * Caller must ensure that 'a' points to enough memory to hold the result
     332             :  * (at least 7 bytes, counting a leading sign and trailing NUL).
     333             :  *
     334             :  * It doesn't seem worth implementing this separately.
     335             :  */
     336             : void
     337      110430 : pg_itoa(int16 i, char *a)
     338             : {
     339      110430 :     pg_ltoa((int32) i, a);
     340      110430 : }
     341             : 
     342             : /*
     343             :  * pg_ultoa_n: converts an unsigned 32-bit integer to its string representation,
     344             :  * not NUL-terminated, and returns the length of that string representation
     345             :  *
     346             :  * Caller must ensure that 'a' points to enough memory to hold the result (at
     347             :  * least 10 bytes)
     348             :  */
     349             : int
     350     6928722 : pg_ultoa_n(uint32 value, char *a)
     351             : {
     352             :     int         olength,
     353     6928722 :                 i = 0;
     354             : 
     355             :     /* Degenerate case */
     356     6928722 :     if (value == 0)
     357             :     {
     358      770200 :         *a = '0';
     359      770200 :         return 1;
     360             :     }
     361             : 
     362     6158522 :     olength = decimalLength32(value);
     363             : 
     364             :     /* Compute the result string. */
     365     7010030 :     while (value >= 10000)
     366             :     {
     367      851508 :         const uint32 c = value - 10000 * (value / 10000);
     368      851508 :         const uint32 c0 = (c % 100) << 1;
     369      851508 :         const uint32 c1 = (c / 100) << 1;
     370             : 
     371      851508 :         char       *pos = a + olength - i;
     372             : 
     373      851508 :         value /= 10000;
     374             : 
     375      851508 :         memcpy(pos - 2, DIGIT_TABLE + c0, 2);
     376      851508 :         memcpy(pos - 4, DIGIT_TABLE + c1, 2);
     377      851508 :         i += 4;
     378             :     }
     379     6158522 :     if (value >= 100)
     380             :     {
     381     3088590 :         const uint32 c = (value % 100) << 1;
     382             : 
     383     3088590 :         char       *pos = a + olength - i;
     384             : 
     385     3088590 :         value /= 100;
     386             : 
     387     3088590 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     388     3088590 :         i += 2;
     389             :     }
     390     6158522 :     if (value >= 10)
     391             :     {
     392     3414150 :         const uint32 c = value << 1;
     393             : 
     394     3414150 :         char       *pos = a + olength - i;
     395             : 
     396     3414150 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     397             :     }
     398             :     else
     399             :     {
     400     2744372 :         *a = (char) ('0' + value);
     401             :     }
     402             : 
     403     6158522 :     return olength;
     404             : }
     405             : 
     406             : /*
     407             :  * NUL-terminate the output of pg_ultoa_n.
     408             :  *
     409             :  * It is the caller's responsibility to ensure that a is at least 12 bytes long,
     410             :  * which is enough room to hold a minus sign, a maximally long int32, and the
     411             :  * above terminating NUL.
     412             :  */
     413             : void
     414     6839572 : pg_ltoa(int32 value, char *a)
     415             : {
     416             : 
     417     6839572 :     uint32      uvalue = (uint32) value;
     418             :     int         len;
     419             : 
     420     6839572 :     if (value < 0)
     421             :     {
     422       71090 :         uvalue = (uint32) 0 - uvalue;
     423       71090 :         *a++ = '-';
     424             :     }
     425     6839572 :     len = pg_ultoa_n(uvalue, a);
     426     6839572 :     a[len] = '\0';
     427     6839572 : }
     428             : 
     429             : /*
     430             :  * Get the decimal representation, not NUL-terminated, and return the length of
     431             :  * same.  Caller must ensure that a points to at least MAXINT8LEN bytes.
     432             :  */
     433             : int
     434      177452 : pg_ulltoa_n(uint64 value, char *a)
     435             : {
     436             :     int         olength,
     437      177452 :                 i = 0;
     438             :     uint32      value2;
     439             : 
     440             : 
     441             :     /* Degenerate case */
     442      177452 :     if (value == 0)
     443             :     {
     444        5778 :         *a = '0';
     445        5778 :         return 1;
     446             :     }
     447             : 
     448      171674 :     olength = decimalLength64(value);
     449             : 
     450             :     /* Compute the result string. */
     451      178832 :     while (value >= 100000000)
     452             :     {
     453        7158 :         const uint64 q = value / 100000000;
     454        7158 :         uint32      value2 = (uint32) (value - 100000000 * q);
     455             : 
     456        7158 :         const uint32 c = value2 % 10000;
     457        7158 :         const uint32 d = value2 / 10000;
     458        7158 :         const uint32 c0 = (c % 100) << 1;
     459        7158 :         const uint32 c1 = (c / 100) << 1;
     460        7158 :         const uint32 d0 = (d % 100) << 1;
     461        7158 :         const uint32 d1 = (d / 100) << 1;
     462             : 
     463        7158 :         char       *pos = a + olength - i;
     464             : 
     465        7158 :         value = q;
     466             : 
     467        7158 :         memcpy(pos - 2, DIGIT_TABLE + c0, 2);
     468        7158 :         memcpy(pos - 4, DIGIT_TABLE + c1, 2);
     469        7158 :         memcpy(pos - 6, DIGIT_TABLE + d0, 2);
     470        7158 :         memcpy(pos - 8, DIGIT_TABLE + d1, 2);
     471        7158 :         i += 8;
     472             :     }
     473             : 
     474             :     /* Switch to 32-bit for speed */
     475      171674 :     value2 = (uint32) value;
     476             : 
     477      171674 :     if (value2 >= 10000)
     478             :     {
     479       14350 :         const uint32 c = value2 - 10000 * (value2 / 10000);
     480       14350 :         const uint32 c0 = (c % 100) << 1;
     481       14350 :         const uint32 c1 = (c / 100) << 1;
     482             : 
     483       14350 :         char       *pos = a + olength - i;
     484             : 
     485       14350 :         value2 /= 10000;
     486             : 
     487       14350 :         memcpy(pos - 2, DIGIT_TABLE + c0, 2);
     488       14350 :         memcpy(pos - 4, DIGIT_TABLE + c1, 2);
     489       14350 :         i += 4;
     490             :     }
     491      171674 :     if (value2 >= 100)
     492             :     {
     493      126248 :         const uint32 c = (value2 % 100) << 1;
     494      126248 :         char       *pos = a + olength - i;
     495             : 
     496      126248 :         value2 /= 100;
     497             : 
     498      126248 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     499      126248 :         i += 2;
     500             :     }
     501      171674 :     if (value2 >= 10)
     502             :     {
     503       60372 :         const uint32 c = value2 << 1;
     504       60372 :         char       *pos = a + olength - i;
     505             : 
     506       60372 :         memcpy(pos - 2, DIGIT_TABLE + c, 2);
     507             :     }
     508             :     else
     509      111302 :         *a = (char) ('0' + value2);
     510             : 
     511      171674 :     return olength;
     512             : }
     513             : 
     514             : /*
     515             :  * pg_lltoa: convert a signed 64-bit integer to its string representation
     516             :  *
     517             :  * Caller must ensure that 'a' points to enough memory to hold the result
     518             :  * (at least MAXINT8LEN + 1 bytes, counting a leading sign and trailing NUL).
     519             :  */
     520             : void
     521      177452 : pg_lltoa(int64 value, char *a)
     522             : {
     523             :     int         len;
     524      177452 :     uint64      uvalue = value;
     525             : 
     526      177452 :     if (value < 0)
     527             :     {
     528        1512 :         *a++ = '-';
     529        1512 :         uvalue = (uint64) 0 - uvalue;
     530             :     }
     531      177452 :     len = pg_ulltoa_n(uvalue, a);
     532      177452 :     a[len] = 0;
     533      177452 : }
     534             : 
     535             : 
     536             : /*
     537             :  * pg_ultostr_zeropad
     538             :  *      Converts 'value' into a decimal string representation stored at 'str'.
     539             :  *      'minwidth' specifies the minimum width of the result; any extra space
     540             :  *      is filled up by prefixing the number with zeros.
     541             :  *
     542             :  * Returns the ending address of the string result (the last character written
     543             :  * plus 1).  Note that no NUL terminator is written.
     544             :  *
     545             :  * The intended use-case for this function is to build strings that contain
     546             :  * multiple individual numbers, for example:
     547             :  *
     548             :  *  str = pg_ltostr_zeropad(str, hours, 2);
     549             :  *  *str++ = ':';
     550             :  *  str = pg_ltostr_zeropad(str, mins, 2);
     551             :  *  *str++ = ':';
     552             :  *  str = pg_ltostr_zeropad(str, secs, 2);
     553             :  *  *str = '\0';
     554             :  *
     555             :  * Note: Caller must ensure that 'str' points to enough memory to hold the
     556             :  * result.
     557             :  */
     558             : char *
     559      543594 : pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth)
     560             : {
     561             :     int         len;
     562             : 
     563             :     Assert(minwidth > 0);
     564             : 
     565      543594 :     if (value < 100 && minwidth == 2)    /* Short cut for common case */
     566             :     {
     567      456564 :         memcpy(str, DIGIT_TABLE + value * 2, 2);
     568      456564 :         return str + 2;
     569             :     }
     570             : 
     571       87030 :     len = pg_ultoa_n(value, str);
     572       87030 :     if (len >= minwidth)
     573       86642 :         return str + len;
     574             : 
     575         388 :     memmove(str + minwidth - len, str, len);
     576         388 :     memset(str, '0', minwidth - len);
     577         388 :     return str + minwidth;
     578             : }
     579             : 
     580             : /*
     581             :  * pg_ltostr
     582             :  *      Converts 'value' into a decimal string representation stored at 'str'.
     583             :  *
     584             :  * Returns the ending address of the string result (the last character written
     585             :  * plus 1).  Note that no NUL terminator is written.
     586             :  *
     587             :  * The intended use-case for this function is to build strings that contain
     588             :  * multiple individual numbers, for example:
     589             :  *
     590             :  *  str = pg_ltostr(str, a);
     591             :  *  *str++ = ' ';
     592             :  *  str = pg_ltostr(str, b);
     593             :  *  *str = '\0';
     594             :  *
     595             :  * Note: Caller must ensure that 'str' points to enough memory to hold the
     596             :  * result.
     597             :  */
     598             : char *
     599        2120 : pg_ultostr(char *str, uint32 value)
     600             : {
     601        2120 :     int         len = pg_ultoa_n(value, str);
     602             : 
     603        2120 :     return str + len;
     604             : }
     605             : 
     606             : /*
     607             :  * pg_strtouint64
     608             :  *      Converts 'str' into an unsigned 64-bit integer.
     609             :  *
     610             :  * This has the identical API to strtoul(3), except that it will handle
     611             :  * 64-bit ints even where "long" is narrower than that.
     612             :  *
     613             :  * For the moment it seems sufficient to assume that the platform has
     614             :  * such a function somewhere; let's not roll our own.
     615             :  */
     616             : uint64
     617      289436 : pg_strtouint64(const char *str, char **endptr, int base)
     618             : {
     619             : #ifdef _MSC_VER                 /* MSVC only */
     620             :     return _strtoui64(str, endptr, base);
     621             : #elif defined(HAVE_STRTOULL) && SIZEOF_LONG < 8
     622             :     return strtoull(str, endptr, base);
     623             : #else
     624      289436 :     return strtoul(str, endptr, base);
     625             : #endif
     626             : }

Generated by: LCOV version 1.13