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)
 
int16 pg_strtoint16 (const char *s)
 
int32 pg_strtoint32 (const char *s)
 
int64 pg_strtoint64 (const char *s)
 
int pg_itoa (int16 i, char *a)
 
int pg_ultoa_n (uint32 value, char *a)
 
int pg_ltoa (int32 value, char *a)
 
int pg_ulltoa_n (uint64 value, char *a)
 
int pg_lltoa (int64 value, char *a)
 
char * pg_ultostr_zeropad (char *str, uint32 value, int32 minwidth)
 
char * pg_ultostr (char *str, uint32 value)
 

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.

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  t = (pg_leftmost_one_pos32(v) + 1) * 1233 / 4096;
60  return t + (v >= PowersOfTen[t]);
61 }
unsigned int uint32
Definition: c.h:452
static int pg_leftmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:26

References pg_leftmost_one_pos32().

Referenced by pg_ultoa_n().

◆ decimalLength64()

static int decimalLength64 ( const uint64  v)
inlinestatic

Definition at line 64 of file numutils.c.

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  t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096;
85  return t + (v >= PowersOfTen[t]);
86 }
static int pg_leftmost_one_pos64(uint64 word)
Definition: pg_bitutils.h:49

References pg_leftmost_one_pos64().

Referenced by pg_ulltoa_n().

◆ pg_itoa()

int pg_itoa ( int16  i,
char *  a 
)

Definition at line 334 of file numutils.c.

335 {
336  return pg_ltoa((int32) i, a);
337 }
signed int int32
Definition: c.h:440
int a
Definition: isn.c:69
int i
Definition: isn.c:73
int pg_ltoa(int32 value, char *a)
Definition: numutils.c:412

References a, i, and pg_ltoa().

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

◆ pg_lltoa()

int pg_lltoa ( int64  value,
char *  a 
)

Definition at line 519 of file numutils.c.

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

References a, len, pg_ulltoa_n(), and value.

Referenced by int8out(), and printsimple().

◆ pg_ltoa()

int pg_ltoa ( int32  value,
char *  a 
)

Definition at line 412 of file numutils.c.

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

References a, len, pg_ultoa_n(), and value.

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

◆ pg_strtoint16()

int16 pg_strtoint16 ( const char *  s)

Definition at line 99 of file numutils.c.

100 {
101  const char *ptr = s;
102  int16 tmp = 0;
103  bool neg = false;
104 
105  /* skip leading spaces */
106  while (likely(*ptr) && isspace((unsigned char) *ptr))
107  ptr++;
108 
109  /* handle sign */
110  if (*ptr == '-')
111  {
112  ptr++;
113  neg = true;
114  }
115  else if (*ptr == '+')
116  ptr++;
117 
118  /* require at least one digit */
119  if (unlikely(!isdigit((unsigned char) *ptr)))
120  goto invalid_syntax;
121 
122  /* process digits */
123  while (*ptr && isdigit((unsigned char) *ptr))
124  {
125  int8 digit = (*ptr++ - '0');
126 
127  if (unlikely(pg_mul_s16_overflow(tmp, 10, &tmp)) ||
128  unlikely(pg_sub_s16_overflow(tmp, digit, &tmp)))
129  goto out_of_range;
130  }
131 
132  /* allow trailing whitespace, but not other trailing chars */
133  while (*ptr != '\0' && isspace((unsigned char) *ptr))
134  ptr++;
135 
136  if (unlikely(*ptr != '\0'))
137  goto invalid_syntax;
138 
139  if (!neg)
140  {
141  /* could fail if input is most negative number */
142  if (unlikely(tmp == PG_INT16_MIN))
143  goto out_of_range;
144  tmp = -tmp;
145  }
146 
147  return tmp;
148 
149 out_of_range:
150  ereport(ERROR,
151  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
152  errmsg("value \"%s\" is out of range for type %s",
153  s, "smallint")));
154 
155 invalid_syntax:
156  ereport(ERROR,
157  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
158  errmsg("invalid input syntax for type %s: \"%s\"",
159  "smallint", s)));
160 
161  return 0; /* keep compiler quiet */
162 }
signed char int8
Definition: c.h:438
#define likely(x)
Definition: c.h:283
signed short int16
Definition: c.h:439
#define PG_INT16_MIN
Definition: c.h:531
#define unlikely(x)
Definition: c.h:284
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:65
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:83

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

Referenced by int2in().

◆ pg_strtoint32()

int32 pg_strtoint32 ( const char *  s)

Definition at line 175 of file numutils.c.

176 {
177  const char *ptr = s;
178  int32 tmp = 0;
179  bool neg = false;
180 
181  /* skip leading spaces */
182  while (likely(*ptr) && isspace((unsigned char) *ptr))
183  ptr++;
184 
185  /* handle sign */
186  if (*ptr == '-')
187  {
188  ptr++;
189  neg = true;
190  }
191  else if (*ptr == '+')
192  ptr++;
193 
194  /* require at least one digit */
195  if (unlikely(!isdigit((unsigned char) *ptr)))
196  goto invalid_syntax;
197 
198  /* process digits */
199  while (*ptr && isdigit((unsigned char) *ptr))
200  {
201  int8 digit = (*ptr++ - '0');
202 
203  if (unlikely(pg_mul_s32_overflow(tmp, 10, &tmp)) ||
204  unlikely(pg_sub_s32_overflow(tmp, digit, &tmp)))
205  goto out_of_range;
206  }
207 
208  /* allow trailing whitespace, but not other trailing chars */
209  while (*ptr != '\0' && isspace((unsigned char) *ptr))
210  ptr++;
211 
212  if (unlikely(*ptr != '\0'))
213  goto invalid_syntax;
214 
215  if (!neg)
216  {
217  /* could fail if input is most negative number */
218  if (unlikely(tmp == PG_INT32_MIN))
219  goto out_of_range;
220  tmp = -tmp;
221  }
222 
223  return tmp;
224 
225 out_of_range:
226  ereport(ERROR,
227  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
228  errmsg("value \"%s\" is out of range for type %s",
229  s, "integer")));
230 
231 invalid_syntax:
232  ereport(ERROR,
233  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
234  errmsg("invalid input syntax for type %s: \"%s\"",
235  "integer", s)));
236 
237  return 0; /* keep compiler quiet */
238 }
#define PG_INT32_MIN
Definition: c.h:534
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:140
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:122

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().

◆ pg_strtoint64()

int64 pg_strtoint64 ( const char *  s)

Definition at line 251 of file numutils.c.

252 {
253  const char *ptr = s;
254  int64 tmp = 0;
255  bool neg = false;
256 
257  /*
258  * Do our own scan, rather than relying on sscanf which might be broken
259  * for long long.
260  *
261  * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
262  * value as a negative number.
263  */
264 
265  /* skip leading spaces */
266  while (*ptr && isspace((unsigned char) *ptr))
267  ptr++;
268 
269  /* handle sign */
270  if (*ptr == '-')
271  {
272  ptr++;
273  neg = true;
274  }
275  else if (*ptr == '+')
276  ptr++;
277 
278  /* require at least one digit */
279  if (unlikely(!isdigit((unsigned char) *ptr)))
280  goto invalid_syntax;
281 
282  /* process digits */
283  while (*ptr && isdigit((unsigned char) *ptr))
284  {
285  int8 digit = (*ptr++ - '0');
286 
287  if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
288  unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
289  goto out_of_range;
290  }
291 
292  /* allow trailing whitespace, but not other trailing chars */
293  while (*ptr != '\0' && isspace((unsigned char) *ptr))
294  ptr++;
295 
296  if (unlikely(*ptr != '\0'))
297  goto invalid_syntax;
298 
299  if (!neg)
300  {
301  /* could fail if input is most negative number */
302  if (unlikely(tmp == PG_INT64_MIN))
303  goto out_of_range;
304  tmp = -tmp;
305  }
306 
307  return tmp;
308 
309 out_of_range:
310  ereport(ERROR,
311  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
312  errmsg("value \"%s\" is out of range for type %s",
313  s, "bigint")));
314 
315 invalid_syntax:
316  ereport(ERROR,
317  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
318  errmsg("invalid input syntax for type %s: \"%s\"",
319  "bigint", s)));
320 
321  return 0; /* keep compiler quiet */
322 }
#define PG_INT64_MIN
Definition: c.h:537
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:188

References ereport, errcode(), errmsg(), ERROR, PG_INT64_MIN, pg_mul_s64_overflow(), pg_sub_s64_overflow(), and unlikely.

Referenced by int8in().

◆ pg_ulltoa_n()

int pg_ulltoa_n ( uint64  value,
char *  a 
)

Definition at line 432 of file numutils.c.

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

References a, decimalLength64(), DIGIT_TABLE, i, and value.

Referenced by pg_lltoa().

◆ pg_ultoa_n()

int pg_ultoa_n ( uint32  value,
char *  a 
)

Definition at line 347 of file numutils.c.

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

References a, decimalLength32(), DIGIT_TABLE, i, and value.

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

◆ pg_ultostr()

char* pg_ultostr ( char *  str,
uint32  value 
)

Definition at line 599 of file numutils.c.

600 {
601  int len = pg_ultoa_n(value, str);
602 
603  return str + len;
604 }

References len, pg_ultoa_n(), generate_unaccent_rules::str, and value.

Referenced by AppendSeconds().

◆ pg_ultostr_zeropad()

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

Definition at line 559 of file numutils.c.

560 {
561  int len;
562 
563  Assert(minwidth > 0);
564 
565  if (value < 100 && minwidth == 2) /* Short cut for common case */
566  {
567  memcpy(str, DIGIT_TABLE + value * 2, 2);
568  return str + 2;
569  }
570 
571  len = pg_ultoa_n(value, str);
572  if (len >= minwidth)
573  return str + len;
574 
575  memmove(str + minwidth - len, str, len);
576  memset(str, '0', minwidth - len);
577  return str + minwidth;
578 }
Assert(fmt[strlen(fmt) - 1] !='\n')

References Assert(), DIGIT_TABLE, len, pg_ultoa_n(), generate_unaccent_rules::str, and value.

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

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().