PostgreSQL Source Code  git master
numutils.c File Reference
#include "postgres.h"
#include <math.h>
#include <limits.h>
#include <ctype.h>
#include "common/int.h"
#include "utils/builtins.h"
#include "port/pg_bitutils.h"
Include dependency graph for numutils.c:

Go to the source code of this file.

Functions

static int decimalLength32 (const uint32 v)
 
static int decimalLength64 (const uint64 v)
 
int32 pg_atoi (const char *s, int size, int c)
 
int16 pg_strtoint16 (const char *s)
 
int32 pg_strtoint32 (const char *s)
 
void pg_itoa (int16 i, char *a)
 
int pg_ultoa_n (uint32 value, char *a)
 
void pg_ltoa (int32 value, char *a)
 
int pg_ulltoa_n (uint64 value, char *a)
 
void pg_lltoa (int64 value, char *a)
 
char * pg_ultostr_zeropad (char *str, uint32 value, int32 minwidth)
 
char * pg_ultostr (char *str, uint32 value)
 
uint64 pg_strtouint64 (const char *str, char **endptr, int base)
 

Variables

static const char DIGIT_TABLE [200]
 

Function Documentation

◆ decimalLength32()

static int decimalLength32 ( const uint32  v)
inlinestatic

Definition at line 45 of file numutils.c.

References pg_leftmost_one_pos32().

Referenced by pg_ultoa_n().

46 {
47  int t;
48  static uint32 PowersOfTen[] =
49  {1, 10, 100,
50  1000, 10000, 100000,
51  1000000, 10000000, 100000000,
52  1000000000};
53  /*
54  * Compute base-10 logarithm by dividing the base-2 logarithm by a
55  * good-enough approximation of the base-2 logarithm of 10
56  */
57  t = (pg_leftmost_one_pos32(v) + 1) * 1233 / 4096;
58  return t + (v >= PowersOfTen[t]);
59 }
static int pg_leftmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:26
unsigned int uint32
Definition: c.h:367

◆ decimalLength64()

static int decimalLength64 ( const uint64  v)
inlinestatic

Definition at line 62 of file numutils.c.

References pg_leftmost_one_pos64().

Referenced by pg_ulltoa_n().

63 {
64  int t;
65  static uint64 PowersOfTen[] = {
66  UINT64CONST(1), UINT64CONST(10),
67  UINT64CONST(100), UINT64CONST(1000),
68  UINT64CONST(10000), UINT64CONST(100000),
69  UINT64CONST(1000000), UINT64CONST(10000000),
70  UINT64CONST(100000000), UINT64CONST(1000000000),
71  UINT64CONST(10000000000), UINT64CONST(100000000000),
72  UINT64CONST(1000000000000), UINT64CONST(10000000000000),
73  UINT64CONST(100000000000000), UINT64CONST(1000000000000000),
74  UINT64CONST(10000000000000000), UINT64CONST(100000000000000000),
75  UINT64CONST(1000000000000000000), UINT64CONST(10000000000000000000)
76  };
77 
78  /*
79  * Compute base-10 logarithm by dividing the base-2 logarithm by a
80  * good-enough approximation of the base-2 logarithm of 10
81  */
82  t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096;
83  return t + (v >= PowersOfTen[t]);
84 }
static int pg_leftmost_one_pos64(uint64 word)
Definition: pg_bitutils.h:49

◆ pg_atoi()

int32 pg_atoi ( const char *  s,
int  size,
int  c 
)

Definition at line 100 of file numutils.c.

References elog, ereport, errcode(), errmsg(), and ERROR.

Referenced by int2vectorin().

101 {
102  long l;
103  char *badp;
104 
105  /*
106  * Some versions of strtol treat the empty string as an error, but some
107  * seem not to. Make an explicit test to be sure we catch it.
108  */
109  if (s == NULL)
110  elog(ERROR, "NULL pointer");
111  if (*s == 0)
112  ereport(ERROR,
113  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
114  errmsg("invalid input syntax for type %s: \"%s\"",
115  "integer", s)));
116 
117  errno = 0;
118  l = strtol(s, &badp, 10);
119 
120  /* We made no progress parsing the string, so bail out */
121  if (s == badp)
122  ereport(ERROR,
123  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
124  errmsg("invalid input syntax for type %s: \"%s\"",
125  "integer", s)));
126 
127  switch (size)
128  {
129  case sizeof(int32):
130  if (errno == ERANGE
131 #if defined(HAVE_LONG_INT_64)
132  /* won't get ERANGE on these with 64-bit longs... */
133  || l < INT_MIN || l > INT_MAX
134 #endif
135  )
136  ereport(ERROR,
137  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
138  errmsg("value \"%s\" is out of range for type %s", s,
139  "integer")));
140  break;
141  case sizeof(int16):
142  if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
143  ereport(ERROR,
144  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
145  errmsg("value \"%s\" is out of range for type %s", s,
146  "smallint")));
147  break;
148  case sizeof(int8):
149  if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
150  ereport(ERROR,
151  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
152  errmsg("value \"%s\" is out of range for 8-bit integer", s)));
153  break;
154  default:
155  elog(ERROR, "unsupported result size: %d", size);
156  }
157 
158  /*
159  * Skip any trailing whitespace; if anything but whitespace remains before
160  * the terminating character, bail out
161  */
162  while (*badp && *badp != c && isspace((unsigned char) *badp))
163  badp++;
164 
165  if (*badp && *badp != c)
166  ereport(ERROR,
167  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
168  errmsg("invalid input syntax for type %s: \"%s\"",
169  "integer", s)));
170 
171  return (int32) l;
172 }
signed short int16
Definition: c.h:354
int errcode(int sqlerrcode)
Definition: elog.c:610
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
char * c
signed char int8
Definition: c.h:353
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214

◆ pg_itoa()

void pg_itoa ( int16  i,
char *  a 
)

Definition at line 335 of file numutils.c.

References pg_ltoa().

Referenced by int2out(), int2vectorout(), LogicalTapeSetCreate(), and ltsConcatWorkerTapes().

336 {
337  pg_ltoa((int32) i, a);
338 }
signed int int32
Definition: c.h:355
int i
void pg_ltoa(int32 value, char *a)
Definition: numutils.c:412

◆ pg_lltoa()

void pg_lltoa ( int64  value,
char *  a 
)

Definition at line 519 of file numutils.c.

References pg_ulltoa_n(), and value.

Referenced by int8out(), and printsimple().

520 {
521  int len;
522  uint64 uvalue = value;
523 
524  if (value < 0)
525  {
526  *a++ = '-';
527  uvalue = (uint64) 0 - uvalue;
528  }
529  len = pg_ulltoa_n(uvalue, a);
530  a[len] = 0;
531 }
int pg_ulltoa_n(uint64 value, char *a)
Definition: numutils.c:432
static struct @143 value

◆ pg_ltoa()

void pg_ltoa ( int32  value,
char *  a 
)

Definition at line 412 of file numutils.c.

References pg_ultoa_n().

Referenced by int4out(), pg_itoa(), and printsimple().

413 {
414 
415  uint32 uvalue = (uint32) value;
416  int len;
417 
418  if (value < 0)
419  {
420  uvalue = (uint32) 0 - uvalue;
421  *a++ = '-';
422  }
423  len = pg_ultoa_n(uvalue, a);
424  a[len] = '\0';
425 }
unsigned int uint32
Definition: c.h:367
static struct @143 value
int pg_ultoa_n(uint32 value, char *a)
Definition: numutils.c:348

◆ pg_strtoint16()

int16 pg_strtoint16 ( const char *  s)

Definition at line 185 of file numutils.c.

References ereport, errcode(), errmsg(), ERROR, likely, PG_INT16_MIN, pg_mul_s16_overflow(), pg_sub_s16_overflow(), and unlikely.

Referenced by int2in().

186 {
187  const char *ptr = s;
188  int16 tmp = 0;
189  bool neg = false;
190 
191  /* skip leading spaces */
192  while (likely(*ptr) && isspace((unsigned char) *ptr))
193  ptr++;
194 
195  /* handle sign */
196  if (*ptr == '-')
197  {
198  ptr++;
199  neg = true;
200  }
201  else if (*ptr == '+')
202  ptr++;
203 
204  /* require at least one digit */
205  if (unlikely(!isdigit((unsigned char) *ptr)))
206  goto invalid_syntax;
207 
208  /* process digits */
209  while (*ptr && isdigit((unsigned char) *ptr))
210  {
211  int8 digit = (*ptr++ - '0');
212 
213  if (unlikely(pg_mul_s16_overflow(tmp, 10, &tmp)) ||
214  unlikely(pg_sub_s16_overflow(tmp, digit, &tmp)))
215  goto out_of_range;
216  }
217 
218  /* allow trailing whitespace, but not other trailing chars */
219  while (*ptr != '\0' && isspace((unsigned char) *ptr))
220  ptr++;
221 
222  if (unlikely(*ptr != '\0'))
223  goto invalid_syntax;
224 
225  if (!neg)
226  {
227  /* could fail if input is most negative number */
228  if (unlikely(tmp == PG_INT16_MIN))
229  goto out_of_range;
230  tmp = -tmp;
231  }
232 
233  return tmp;
234 
235 out_of_range:
236  ereport(ERROR,
237  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
238  errmsg("value \"%s\" is out of range for type %s",
239  s, "smallint")));
240 
241 invalid_syntax:
242  ereport(ERROR,
243  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
244  errmsg("invalid input syntax for type %s: \"%s\"",
245  "smallint", s)));
246 
247  return 0; /* keep compiler quiet */
248 }
signed short int16
Definition: c.h:354
#define likely(x)
Definition: c.h:205
int errcode(int sqlerrcode)
Definition: elog.c:610
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:83
#define ERROR
Definition: elog.h:43
#define PG_INT16_MIN
Definition: c.h:446
signed char int8
Definition: c.h:353
#define ereport(elevel,...)
Definition: elog.h:144
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define unlikely(x)
Definition: c.h:206

◆ pg_strtoint32()

int32 pg_strtoint32 ( const char *  s)

Definition at line 261 of file numutils.c.

References ereport, errcode(), errmsg(), ERROR, likely, PG_INT32_MIN, pg_mul_s32_overflow(), pg_sub_s32_overflow(), and unlikely.

Referenced by ArrayGetIntegerTypmods(), check_foreign_key(), int4in(), libpqrcv_endstreaming(), libpqrcv_identify_system(), pq_parse_errornotice(), prsd_headline(), and text_format().

262 {
263  const char *ptr = s;
264  int32 tmp = 0;
265  bool neg = false;
266 
267  /* skip leading spaces */
268  while (likely(*ptr) && isspace((unsigned char) *ptr))
269  ptr++;
270 
271  /* handle sign */
272  if (*ptr == '-')
273  {
274  ptr++;
275  neg = true;
276  }
277  else if (*ptr == '+')
278  ptr++;
279 
280  /* require at least one digit */
281  if (unlikely(!isdigit((unsigned char) *ptr)))
282  goto invalid_syntax;
283 
284  /* process digits */
285  while (*ptr && isdigit((unsigned char) *ptr))
286  {
287  int8 digit = (*ptr++ - '0');
288 
289  if (unlikely(pg_mul_s32_overflow(tmp, 10, &tmp)) ||
290  unlikely(pg_sub_s32_overflow(tmp, digit, &tmp)))
291  goto out_of_range;
292  }
293 
294  /* allow trailing whitespace, but not other trailing chars */
295  while (*ptr != '\0' && isspace((unsigned char) *ptr))
296  ptr++;
297 
298  if (unlikely(*ptr != '\0'))
299  goto invalid_syntax;
300 
301  if (!neg)
302  {
303  /* could fail if input is most negative number */
304  if (unlikely(tmp == PG_INT32_MIN))
305  goto out_of_range;
306  tmp = -tmp;
307  }
308 
309  return tmp;
310 
311 out_of_range:
312  ereport(ERROR,
313  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
314  errmsg("value \"%s\" is out of range for type %s",
315  s, "integer")));
316 
317 invalid_syntax:
318  ereport(ERROR,
319  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
320  errmsg("invalid input syntax for type %s: \"%s\"",
321  "integer", s)));
322 
323  return 0; /* keep compiler quiet */
324 }
#define likely(x)
Definition: c.h:205
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:140
int errcode(int sqlerrcode)
Definition: elog.c:610
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:122
#define PG_INT32_MIN
Definition: c.h:449
signed char int8
Definition: c.h:353
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define unlikely(x)
Definition: c.h:206

◆ pg_strtouint64()

uint64 pg_strtouint64 ( const char *  str,
char **  endptr,
int  base 
)

Definition at line 615 of file numutils.c.

616 {
617 #ifdef _MSC_VER /* MSVC only */
618  return _strtoui64(str, endptr, base);
619 #elif defined(HAVE_STRTOULL) && SIZEOF_LONG < 8
620  return strtoull(str, endptr, base);
621 #else
622  return strtoul(str, endptr, base);
623 #endif
624 }

◆ pg_ulltoa_n()

int pg_ulltoa_n ( uint64  value,
char *  a 
)

Definition at line 432 of file numutils.c.

References decimalLength64(), DIGIT_TABLE, and i.

Referenced by pg_lltoa().

433 {
434  int olength,
435  i = 0;
436  uint32 value2;
437 
438 
439  /* Degenerate case */
440  if (value == 0)
441  {
442  *a = '0';
443  return 1;
444  }
445 
446  olength = decimalLength64(value);
447 
448  /* Compute the result string. */
449  while (value >= 100000000)
450  {
451  const uint64 q = value / 100000000;
452  uint32 value2 = (uint32) (value - 100000000 * q);
453 
454  const uint32 c = value2 % 10000;
455  const uint32 d = value2 / 10000;
456  const uint32 c0 = (c % 100) << 1;
457  const uint32 c1 = (c / 100) << 1;
458  const uint32 d0 = (d % 100) << 1;
459  const uint32 d1 = (d / 100) << 1;
460 
461  char *pos = a + olength - i;
462 
463  value = q;
464 
465  memcpy(pos - 2, DIGIT_TABLE + c0, 2);
466  memcpy(pos - 4, DIGIT_TABLE + c1, 2);
467  memcpy(pos - 6, DIGIT_TABLE + d0, 2);
468  memcpy(pos - 8, DIGIT_TABLE + d1, 2);
469  i += 8;
470  }
471 
472  /* Switch to 32-bit for speed */
473  value2 = (uint32) value;
474 
475  if (value2 >= 10000)
476  {
477  const uint32 c = value2 - 10000 * (value2 / 10000);
478  const uint32 c0 = (c % 100) << 1;
479  const uint32 c1 = (c / 100) << 1;
480 
481  char *pos = a + olength - i;
482 
483  value2 /= 10000;
484 
485  memcpy(pos - 2, DIGIT_TABLE + c0, 2);
486  memcpy(pos - 4, DIGIT_TABLE + c1, 2);
487  i += 4;
488  }
489  if (value2 >= 100)
490  {
491  const uint32 c = (value2 % 100) << 1;
492  char *pos = a + olength - i;
493 
494  value2 /= 100;
495 
496  memcpy(pos - 2, DIGIT_TABLE + c, 2);
497  i += 2;
498  }
499  if (value2 >= 10)
500  {
501  const uint32 c = value2 << 1;
502  char *pos = a + olength - i;
503 
504  memcpy(pos - 2, DIGIT_TABLE + c, 2);
505  }
506  else
507  *a = (char) ('0' + value2);
508 
509  return olength;
510 }
static int decimalLength64(const uint64 v)
Definition: numutils.c:62
char * c
unsigned int uint32
Definition: c.h:367
static struct @143 value
int i
static const char DIGIT_TABLE[200]
Definition: numutils.c:29

◆ pg_ultoa_n()

int pg_ultoa_n ( uint32  value,
char *  a 
)

Definition at line 348 of file numutils.c.

References decimalLength32(), DIGIT_TABLE, and i.

Referenced by pg_ltoa(), pg_ultostr(), and pg_ultostr_zeropad().

349 {
350  int olength,
351  i = 0;
352 
353  /* Degenerate case */
354  if (value == 0)
355  {
356  *a = '0';
357  return 1;
358  }
359 
360  olength = decimalLength32(value);
361 
362  /* Compute the result string. */
363  while (value >= 10000)
364  {
365  const uint32 c = value - 10000 * (value / 10000);
366  const uint32 c0 = (c % 100) << 1;
367  const uint32 c1 = (c / 100) << 1;
368 
369  char *pos = a + olength - i;
370 
371  value /= 10000;
372 
373  memcpy(pos - 2, DIGIT_TABLE + c0, 2);
374  memcpy(pos - 4, DIGIT_TABLE + c1, 2);
375  i += 4;
376  }
377  if (value >= 100)
378  {
379  const uint32 c = (value % 100) << 1;
380 
381  char *pos = a + olength - i;
382 
383  value /= 100;
384 
385  memcpy(pos - 2, DIGIT_TABLE + c, 2);
386  i += 2;
387  }
388  if (value >= 10)
389  {
390  const uint32 c = value << 1;
391 
392  char *pos = a + olength - i;
393 
394  memcpy(pos - 2, DIGIT_TABLE + c, 2);
395  }
396  else
397  {
398  *a = (char) ('0' + value);
399  }
400 
401  return olength;
402 }
static int decimalLength32(const uint32 v)
Definition: numutils.c:45
char * c
unsigned int uint32
Definition: c.h:367
static struct @143 value
int i
static const char DIGIT_TABLE[200]
Definition: numutils.c:29

◆ pg_ultostr()

char* pg_ultostr ( char *  str,
uint32  value 
)

Definition at line 597 of file numutils.c.

References pg_ultoa_n().

Referenced by AppendSeconds().

598 {
599  int len = pg_ultoa_n(value, str);
600 
601  return str + len;
602 }
static struct @143 value
int pg_ultoa_n(uint32 value, char *a)
Definition: numutils.c:348

◆ pg_ultostr_zeropad()

char* pg_ultostr_zeropad ( char *  str,
uint32  value,
int32  minwidth 
)

Definition at line 557 of file numutils.c.

References Assert, DIGIT_TABLE, and pg_ultoa_n().

Referenced by AppendSeconds(), EncodeDateOnly(), EncodeDateTime(), EncodeTimeOnly(), and EncodeTimezone().

558 {
559  int len;
560 
561  Assert(minwidth > 0);
562 
563  if (value < 100 && minwidth == 2) /* Short cut for common case */
564  {
565  memcpy(str, DIGIT_TABLE + value * 2, 2);
566  return str + 2;
567  }
568 
569  len = pg_ultoa_n(value, str);
570  if (len >= minwidth)
571  return str + len;
572 
573  memmove(str + minwidth - len, str, len);
574  memset(str, '0', minwidth - len);
575  return str + minwidth;
576 }
static struct @143 value
int pg_ultoa_n(uint32 value, char *a)
Definition: numutils.c:348
#define Assert(condition)
Definition: c.h:738
static const char DIGIT_TABLE[200]
Definition: numutils.c:29

Variable Documentation

◆ DIGIT_TABLE

const char DIGIT_TABLE[200]
static
Initial value:
=
"00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
"10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
"20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
"30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
"40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
"50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
"60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
"70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
"80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
"90" "91" "92" "93" "94" "95" "96" "97" "98" "99"

Definition at line 29 of file numutils.c.

Referenced by pg_ulltoa_n(), pg_ultoa_n(), pg_ultostr_zeropad(), to_chars(), to_chars_df(), and to_chars_f().