PostgreSQL Source Code  git master
numutils.c File Reference
#include "postgres.h"
#include <math.h>
#include <limits.h>
#include <ctype.h>
#include "port/pg_bitutils.h"
#include "utils/builtins.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)
 
int16 pg_strtoint16_safe (const char *s, Node *escontext)
 
int32 pg_strtoint32 (const char *s)
 
int32 pg_strtoint32_safe (const char *s, Node *escontext)
 
int64 pg_strtoint64 (const char *s)
 
int64 pg_strtoint64_safe (const char *s, Node *escontext)
 
uint32 uint32in_subr (const char *s, char **endloc, const char *typname, Node *escontext)
 
uint64 uint64in_subr (const char *s, char **endloc, const char *typname, Node *escontext)
 
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]
 
static const int8 hexlookup [128]
 

Function Documentation

◆ decimalLength32()

static int decimalLength32 ( const uint32  v)
inlinestatic

Definition at line 44 of file numutils.c.

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

References pg_leftmost_one_pos32().

Referenced by pg_ultoa_n().

◆ decimalLength64()

static int decimalLength64 ( const uint64  v)
inlinestatic

Definition at line 63 of file numutils.c.

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

References pg_leftmost_one_pos64().

Referenced by pg_ulltoa_n().

◆ pg_itoa()

int pg_itoa ( int16  i,
char *  a 
)

Definition at line 1044 of file numutils.c.

1045 {
1046  return pg_ltoa((int32) i, a);
1047 }
signed int int32
Definition: c.h:481
int a
Definition: isn.c:69
int i
Definition: isn.c:73
int pg_ltoa(int32 value, char *a)
Definition: numutils.c:1122

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 1229 of file numutils.c.

1230 {
1231  uint64 uvalue = value;
1232  int len = 0;
1233 
1234  if (value < 0)
1235  {
1236  uvalue = (uint64) 0 - uvalue;
1237  a[len++] = '-';
1238  }
1239 
1240  len += pg_ulltoa_n(uvalue, a + len);
1241  a[len] = '\0';
1242  return len;
1243 }
static struct @150 value
int pg_ulltoa_n(uint64 value, char *a)
Definition: numutils.c:1142
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 1122 of file numutils.c.

1123 {
1124  uint32 uvalue = (uint32) value;
1125  int len = 0;
1126 
1127  if (value < 0)
1128  {
1129  uvalue = (uint32) 0 - uvalue;
1130  a[len++] = '-';
1131  }
1132  len += pg_ultoa_n(uvalue, a + len);
1133  a[len] = '\0';
1134  return len;
1135 }
int pg_ultoa_n(uint32 value, char *a)
Definition: numutils.c:1057

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

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

◆ pg_strtoint16()

int16 pg_strtoint16 ( const char *  s)

Definition at line 121 of file numutils.c.

122 {
123  return pg_strtoint16_safe(s, NULL);
124 }
int16 pg_strtoint16_safe(const char *s, Node *escontext)
Definition: numutils.c:127

References pg_strtoint16_safe().

◆ pg_strtoint16_safe()

int16 pg_strtoint16_safe ( const char *  s,
Node escontext 
)

Definition at line 127 of file numutils.c.

128 {
129  const char *ptr = s;
130  const char *firstdigit;
131  uint16 tmp = 0;
132  bool neg = false;
133  unsigned char digit;
134 
135  /*
136  * The majority of cases are likely to be base-10 digits without any
137  * underscore separator characters. We'll first try to parse the string
138  * with the assumption that's the case and only fallback on a slower
139  * implementation which handles hex, octal and binary strings and
140  * underscores if the fastpath version cannot parse the string.
141  */
142 
143  /* leave it up to the slow path to look for leading spaces */
144 
145  if (*ptr == '-')
146  {
147  ptr++;
148  neg = true;
149  }
150 
151  /* a leading '+' is uncommon so leave that for the slow path */
152 
153  /* process the first digit */
154  digit = (*ptr - '0');
155 
156  /*
157  * Exploit unsigned arithmetic to save having to check both the upper and
158  * lower bounds of the digit.
159  */
160  if (likely(digit < 10))
161  {
162  ptr++;
163  tmp = digit;
164  }
165  else
166  {
167  /* we need at least one digit */
168  goto slow;
169  }
170 
171  /* process remaining digits */
172  for (;;)
173  {
174  digit = (*ptr - '0');
175 
176  if (digit >= 10)
177  break;
178 
179  ptr++;
180 
181  if (unlikely(tmp > -(PG_INT16_MIN / 10)))
182  goto out_of_range;
183 
184  tmp = tmp * 10 + digit;
185  }
186 
187  /* when the string does not end in a digit, let the slow path handle it */
188  if (unlikely(*ptr != '\0'))
189  goto slow;
190 
191  if (neg)
192  {
193  /* check the negative equivalent will fit without overflowing */
194  if (unlikely(tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1))
195  goto out_of_range;
196  return -((int16) tmp);
197  }
198 
199  if (unlikely(tmp > PG_INT16_MAX))
200  goto out_of_range;
201 
202  return (int16) tmp;
203 
204 slow:
205  tmp = 0;
206  ptr = s;
207  /* no need to reset neg */
208 
209  /* skip leading spaces */
210  while (isspace((unsigned char) *ptr))
211  ptr++;
212 
213  /* handle sign */
214  if (*ptr == '-')
215  {
216  ptr++;
217  neg = true;
218  }
219  else if (*ptr == '+')
220  ptr++;
221 
222  /* process digits */
223  if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
224  {
225  firstdigit = ptr += 2;
226 
227  for (;;)
228  {
229  if (isxdigit((unsigned char) *ptr))
230  {
231  if (unlikely(tmp > -(PG_INT16_MIN / 16)))
232  goto out_of_range;
233 
234  tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
235  }
236  else if (*ptr == '_')
237  {
238  /* underscore must be followed by more digits */
239  ptr++;
240  if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
241  goto invalid_syntax;
242  }
243  else
244  break;
245  }
246  }
247  else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
248  {
249  firstdigit = ptr += 2;
250 
251  for (;;)
252  {
253  if (*ptr >= '0' && *ptr <= '7')
254  {
255  if (unlikely(tmp > -(PG_INT16_MIN / 8)))
256  goto out_of_range;
257 
258  tmp = tmp * 8 + (*ptr++ - '0');
259  }
260  else if (*ptr == '_')
261  {
262  /* underscore must be followed by more digits */
263  ptr++;
264  if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
265  goto invalid_syntax;
266  }
267  else
268  break;
269  }
270  }
271  else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
272  {
273  firstdigit = ptr += 2;
274 
275  for (;;)
276  {
277  if (*ptr >= '0' && *ptr <= '1')
278  {
279  if (unlikely(tmp > -(PG_INT16_MIN / 2)))
280  goto out_of_range;
281 
282  tmp = tmp * 2 + (*ptr++ - '0');
283  }
284  else if (*ptr == '_')
285  {
286  /* underscore must be followed by more digits */
287  ptr++;
288  if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
289  goto invalid_syntax;
290  }
291  else
292  break;
293  }
294  }
295  else
296  {
297  firstdigit = ptr;
298 
299  for (;;)
300  {
301  if (*ptr >= '0' && *ptr <= '9')
302  {
303  if (unlikely(tmp > -(PG_INT16_MIN / 10)))
304  goto out_of_range;
305 
306  tmp = tmp * 10 + (*ptr++ - '0');
307  }
308  else if (*ptr == '_')
309  {
310  /* underscore may not be first */
311  if (unlikely(ptr == firstdigit))
312  goto invalid_syntax;
313  /* and it must be followed by more digits */
314  ptr++;
315  if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
316  goto invalid_syntax;
317  }
318  else
319  break;
320  }
321  }
322 
323  /* require at least one digit */
324  if (unlikely(ptr == firstdigit))
325  goto invalid_syntax;
326 
327  /* allow trailing whitespace, but not other trailing chars */
328  while (isspace((unsigned char) *ptr))
329  ptr++;
330 
331  if (unlikely(*ptr != '\0'))
332  goto invalid_syntax;
333 
334  if (neg)
335  {
336  /* check the negative equivalent will fit without overflowing */
337  if (tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1)
338  goto out_of_range;
339  return -((int16) tmp);
340  }
341 
342  if (tmp > PG_INT16_MAX)
343  goto out_of_range;
344 
345  return (int16) tmp;
346 
347 out_of_range:
348  ereturn(escontext, 0,
349  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
350  errmsg("value \"%s\" is out of range for type %s",
351  s, "smallint")));
352 
353 invalid_syntax:
354  ereturn(escontext, 0,
355  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
356  errmsg("invalid input syntax for type %s: \"%s\"",
357  "smallint", s)));
358 }
unsigned short uint16
Definition: c.h:492
#define likely(x)
Definition: c.h:297
signed short int16
Definition: c.h:480
#define PG_INT16_MIN
Definition: c.h:572
#define unlikely(x)
Definition: c.h:298
#define PG_INT16_MAX
Definition: c.h:573
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
static const int8 hexlookup[128]
Definition: numutils.c:87

References ereturn, errcode(), errmsg(), hexlookup, likely, PG_INT16_MAX, PG_INT16_MIN, and unlikely.

Referenced by int2in(), and pg_strtoint16().

◆ pg_strtoint32()

int32 pg_strtoint32 ( const char *  s)

Definition at line 383 of file numutils.c.

384 {
385  return pg_strtoint32_safe(s, NULL);
386 }
int32 pg_strtoint32_safe(const char *s, Node *escontext)
Definition: numutils.c:389

References pg_strtoint32_safe().

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

◆ pg_strtoint32_safe()

int32 pg_strtoint32_safe ( const char *  s,
Node escontext 
)

Definition at line 389 of file numutils.c.

390 {
391  const char *ptr = s;
392  const char *firstdigit;
393  uint32 tmp = 0;
394  bool neg = false;
395  unsigned char digit;
396 
397  /*
398  * The majority of cases are likely to be base-10 digits without any
399  * underscore separator characters. We'll first try to parse the string
400  * with the assumption that's the case and only fallback on a slower
401  * implementation which handles hex, octal and binary strings and
402  * underscores if the fastpath version cannot parse the string.
403  */
404 
405  /* leave it up to the slow path to look for leading spaces */
406 
407  if (*ptr == '-')
408  {
409  ptr++;
410  neg = true;
411  }
412 
413  /* a leading '+' is uncommon so leave that for the slow path */
414 
415  /* process the first digit */
416  digit = (*ptr - '0');
417 
418  /*
419  * Exploit unsigned arithmetic to save having to check both the upper and
420  * lower bounds of the digit.
421  */
422  if (likely(digit < 10))
423  {
424  ptr++;
425  tmp = digit;
426  }
427  else
428  {
429  /* we need at least one digit */
430  goto slow;
431  }
432 
433  /* process remaining digits */
434  for (;;)
435  {
436  digit = (*ptr - '0');
437 
438  if (digit >= 10)
439  break;
440 
441  ptr++;
442 
443  if (unlikely(tmp > -(PG_INT32_MIN / 10)))
444  goto out_of_range;
445 
446  tmp = tmp * 10 + digit;
447  }
448 
449  /* when the string does not end in a digit, let the slow path handle it */
450  if (unlikely(*ptr != '\0'))
451  goto slow;
452 
453  if (neg)
454  {
455  /* check the negative equivalent will fit without overflowing */
456  if (unlikely(tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1))
457  goto out_of_range;
458  return -((int32) tmp);
459  }
460 
461  if (unlikely(tmp > PG_INT32_MAX))
462  goto out_of_range;
463 
464  return (int32) tmp;
465 
466 slow:
467  tmp = 0;
468  ptr = s;
469  /* no need to reset neg */
470 
471  /* skip leading spaces */
472  while (isspace((unsigned char) *ptr))
473  ptr++;
474 
475  /* handle sign */
476  if (*ptr == '-')
477  {
478  ptr++;
479  neg = true;
480  }
481  else if (*ptr == '+')
482  ptr++;
483 
484  /* process digits */
485  if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
486  {
487  firstdigit = ptr += 2;
488 
489  for (;;)
490  {
491  if (isxdigit((unsigned char) *ptr))
492  {
493  if (unlikely(tmp > -(PG_INT32_MIN / 16)))
494  goto out_of_range;
495 
496  tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
497  }
498  else if (*ptr == '_')
499  {
500  /* underscore must be followed by more digits */
501  ptr++;
502  if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
503  goto invalid_syntax;
504  }
505  else
506  break;
507  }
508  }
509  else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
510  {
511  firstdigit = ptr += 2;
512 
513  for (;;)
514  {
515  if (*ptr >= '0' && *ptr <= '7')
516  {
517  if (unlikely(tmp > -(PG_INT32_MIN / 8)))
518  goto out_of_range;
519 
520  tmp = tmp * 8 + (*ptr++ - '0');
521  }
522  else if (*ptr == '_')
523  {
524  /* underscore must be followed by more digits */
525  ptr++;
526  if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
527  goto invalid_syntax;
528  }
529  else
530  break;
531  }
532  }
533  else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
534  {
535  firstdigit = ptr += 2;
536 
537  for (;;)
538  {
539  if (*ptr >= '0' && *ptr <= '1')
540  {
541  if (unlikely(tmp > -(PG_INT32_MIN / 2)))
542  goto out_of_range;
543 
544  tmp = tmp * 2 + (*ptr++ - '0');
545  }
546  else if (*ptr == '_')
547  {
548  /* underscore must be followed by more digits */
549  ptr++;
550  if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
551  goto invalid_syntax;
552  }
553  else
554  break;
555  }
556  }
557  else
558  {
559  firstdigit = ptr;
560 
561  for (;;)
562  {
563  if (*ptr >= '0' && *ptr <= '9')
564  {
565  if (unlikely(tmp > -(PG_INT32_MIN / 10)))
566  goto out_of_range;
567 
568  tmp = tmp * 10 + (*ptr++ - '0');
569  }
570  else if (*ptr == '_')
571  {
572  /* underscore may not be first */
573  if (unlikely(ptr == firstdigit))
574  goto invalid_syntax;
575  /* and it must be followed by more digits */
576  ptr++;
577  if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
578  goto invalid_syntax;
579  }
580  else
581  break;
582  }
583  }
584 
585  /* require at least one digit */
586  if (unlikely(ptr == firstdigit))
587  goto invalid_syntax;
588 
589  /* allow trailing whitespace, but not other trailing chars */
590  while (isspace((unsigned char) *ptr))
591  ptr++;
592 
593  if (unlikely(*ptr != '\0'))
594  goto invalid_syntax;
595 
596  if (neg)
597  {
598  /* check the negative equivalent will fit without overflowing */
599  if (tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1)
600  goto out_of_range;
601  return -((int32) tmp);
602  }
603 
604  if (tmp > PG_INT32_MAX)
605  goto out_of_range;
606 
607  return (int32) tmp;
608 
609 out_of_range:
610  ereturn(escontext, 0,
611  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
612  errmsg("value \"%s\" is out of range for type %s",
613  s, "integer")));
614 
615 invalid_syntax:
616  ereturn(escontext, 0,
617  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
618  errmsg("invalid input syntax for type %s: \"%s\"",
619  "integer", s)));
620 }
#define PG_INT32_MAX
Definition: c.h:576
#define PG_INT32_MIN
Definition: c.h:575

References ereturn, errcode(), errmsg(), hexlookup, likely, PG_INT32_MAX, PG_INT32_MIN, and unlikely.

Referenced by int4in(), and pg_strtoint32().

◆ pg_strtoint64()

int64 pg_strtoint64 ( const char *  s)

Definition at line 645 of file numutils.c.

646 {
647  return pg_strtoint64_safe(s, NULL);
648 }
int64 pg_strtoint64_safe(const char *s, Node *escontext)
Definition: numutils.c:651

References pg_strtoint64_safe().

◆ pg_strtoint64_safe()

int64 pg_strtoint64_safe ( const char *  s,
Node escontext 
)

Definition at line 651 of file numutils.c.

652 {
653  const char *ptr = s;
654  const char *firstdigit;
655  uint64 tmp = 0;
656  bool neg = false;
657  unsigned char digit;
658 
659  /*
660  * The majority of cases are likely to be base-10 digits without any
661  * underscore separator characters. We'll first try to parse the string
662  * with the assumption that's the case and only fallback on a slower
663  * implementation which handles hex, octal and binary strings and
664  * underscores if the fastpath version cannot parse the string.
665  */
666 
667  /* leave it up to the slow path to look for leading spaces */
668 
669  if (*ptr == '-')
670  {
671  ptr++;
672  neg = true;
673  }
674 
675  /* a leading '+' is uncommon so leave that for the slow path */
676 
677  /* process the first digit */
678  digit = (*ptr - '0');
679 
680  /*
681  * Exploit unsigned arithmetic to save having to check both the upper and
682  * lower bounds of the digit.
683  */
684  if (likely(digit < 10))
685  {
686  ptr++;
687  tmp = digit;
688  }
689  else
690  {
691  /* we need at least one digit */
692  goto slow;
693  }
694 
695  /* process remaining digits */
696  for (;;)
697  {
698  digit = (*ptr - '0');
699 
700  if (digit >= 10)
701  break;
702 
703  ptr++;
704 
705  if (unlikely(tmp > -(PG_INT64_MIN / 10)))
706  goto out_of_range;
707 
708  tmp = tmp * 10 + digit;
709  }
710 
711  /* when the string does not end in a digit, let the slow path handle it */
712  if (unlikely(*ptr != '\0'))
713  goto slow;
714 
715  if (neg)
716  {
717  /* check the negative equivalent will fit without overflowing */
718  if (unlikely(tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1))
719  goto out_of_range;
720  return -((int64) tmp);
721  }
722 
723  if (unlikely(tmp > PG_INT64_MAX))
724  goto out_of_range;
725 
726  return (int64) tmp;
727 
728 slow:
729  tmp = 0;
730  ptr = s;
731  /* no need to reset neg */
732 
733  /* skip leading spaces */
734  while (isspace((unsigned char) *ptr))
735  ptr++;
736 
737  /* handle sign */
738  if (*ptr == '-')
739  {
740  ptr++;
741  neg = true;
742  }
743  else if (*ptr == '+')
744  ptr++;
745 
746  /* process digits */
747  if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
748  {
749  firstdigit = ptr += 2;
750 
751  for (;;)
752  {
753  if (isxdigit((unsigned char) *ptr))
754  {
755  if (unlikely(tmp > -(PG_INT64_MIN / 16)))
756  goto out_of_range;
757 
758  tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
759  }
760  else if (*ptr == '_')
761  {
762  /* underscore must be followed by more digits */
763  ptr++;
764  if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
765  goto invalid_syntax;
766  }
767  else
768  break;
769  }
770  }
771  else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
772  {
773  firstdigit = ptr += 2;
774 
775  for (;;)
776  {
777  if (*ptr >= '0' && *ptr <= '7')
778  {
779  if (unlikely(tmp > -(PG_INT64_MIN / 8)))
780  goto out_of_range;
781 
782  tmp = tmp * 8 + (*ptr++ - '0');
783  }
784  else if (*ptr == '_')
785  {
786  /* underscore must be followed by more digits */
787  ptr++;
788  if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
789  goto invalid_syntax;
790  }
791  else
792  break;
793  }
794  }
795  else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
796  {
797  firstdigit = ptr += 2;
798 
799  for (;;)
800  {
801  if (*ptr >= '0' && *ptr <= '1')
802  {
803  if (unlikely(tmp > -(PG_INT64_MIN / 2)))
804  goto out_of_range;
805 
806  tmp = tmp * 2 + (*ptr++ - '0');
807  }
808  else if (*ptr == '_')
809  {
810  /* underscore must be followed by more digits */
811  ptr++;
812  if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
813  goto invalid_syntax;
814  }
815  else
816  break;
817  }
818  }
819  else
820  {
821  firstdigit = ptr;
822 
823  for (;;)
824  {
825  if (*ptr >= '0' && *ptr <= '9')
826  {
827  if (unlikely(tmp > -(PG_INT64_MIN / 10)))
828  goto out_of_range;
829 
830  tmp = tmp * 10 + (*ptr++ - '0');
831  }
832  else if (*ptr == '_')
833  {
834  /* underscore may not be first */
835  if (unlikely(ptr == firstdigit))
836  goto invalid_syntax;
837  /* and it must be followed by more digits */
838  ptr++;
839  if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
840  goto invalid_syntax;
841  }
842  else
843  break;
844  }
845  }
846 
847  /* require at least one digit */
848  if (unlikely(ptr == firstdigit))
849  goto invalid_syntax;
850 
851  /* allow trailing whitespace, but not other trailing chars */
852  while (isspace((unsigned char) *ptr))
853  ptr++;
854 
855  if (unlikely(*ptr != '\0'))
856  goto invalid_syntax;
857 
858  if (neg)
859  {
860  /* check the negative equivalent will fit without overflowing */
861  if (tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1)
862  goto out_of_range;
863  return -((int64) tmp);
864  }
865 
866  if (tmp > PG_INT64_MAX)
867  goto out_of_range;
868 
869  return (int64) tmp;
870 
871 out_of_range:
872  ereturn(escontext, 0,
873  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
874  errmsg("value \"%s\" is out of range for type %s",
875  s, "bigint")));
876 
877 invalid_syntax:
878  ereturn(escontext, 0,
879  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
880  errmsg("invalid input syntax for type %s: \"%s\"",
881  "bigint", s)));
882 }
#define PG_INT64_MAX
Definition: c.h:579
#define PG_INT64_MIN
Definition: c.h:578

References ereturn, errcode(), errmsg(), hexlookup, likely, PG_INT64_MAX, PG_INT64_MIN, and unlikely.

Referenced by int8in(), make_const(), and pg_strtoint64().

◆ pg_ulltoa_n()

int pg_ulltoa_n ( uint64  value,
char *  a 
)

Definition at line 1142 of file numutils.c.

1143 {
1144  int olength,
1145  i = 0;
1146  uint32 value2;
1147 
1148  /* Degenerate case */
1149  if (value == 0)
1150  {
1151  *a = '0';
1152  return 1;
1153  }
1154 
1155  olength = decimalLength64(value);
1156 
1157  /* Compute the result string. */
1158  while (value >= 100000000)
1159  {
1160  const uint64 q = value / 100000000;
1161  uint32 value3 = (uint32) (value - 100000000 * q);
1162 
1163  const uint32 c = value3 % 10000;
1164  const uint32 d = value3 / 10000;
1165  const uint32 c0 = (c % 100) << 1;
1166  const uint32 c1 = (c / 100) << 1;
1167  const uint32 d0 = (d % 100) << 1;
1168  const uint32 d1 = (d / 100) << 1;
1169 
1170  char *pos = a + olength - i;
1171 
1172  value = q;
1173 
1174  memcpy(pos - 2, DIGIT_TABLE + c0, 2);
1175  memcpy(pos - 4, DIGIT_TABLE + c1, 2);
1176  memcpy(pos - 6, DIGIT_TABLE + d0, 2);
1177  memcpy(pos - 8, DIGIT_TABLE + d1, 2);
1178  i += 8;
1179  }
1180 
1181  /* Switch to 32-bit for speed */
1182  value2 = (uint32) value;
1183 
1184  if (value2 >= 10000)
1185  {
1186  const uint32 c = value2 - 10000 * (value2 / 10000);
1187  const uint32 c0 = (c % 100) << 1;
1188  const uint32 c1 = (c / 100) << 1;
1189 
1190  char *pos = a + olength - i;
1191 
1192  value2 /= 10000;
1193 
1194  memcpy(pos - 2, DIGIT_TABLE + c0, 2);
1195  memcpy(pos - 4, DIGIT_TABLE + c1, 2);
1196  i += 4;
1197  }
1198  if (value2 >= 100)
1199  {
1200  const uint32 c = (value2 % 100) << 1;
1201  char *pos = a + olength - i;
1202 
1203  value2 /= 100;
1204 
1205  memcpy(pos - 2, DIGIT_TABLE + c, 2);
1206  i += 2;
1207  }
1208  if (value2 >= 10)
1209  {
1210  const uint32 c = value2 << 1;
1211  char *pos = a + olength - i;
1212 
1213  memcpy(pos - 2, DIGIT_TABLE + c, 2);
1214  }
1215  else
1216  *a = (char) ('0' + value2);
1217 
1218  return olength;
1219 }
static const char DIGIT_TABLE[200]
Definition: numutils.c:28
static int decimalLength64(const uint64 v)
Definition: numutils.c:63
char * c

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

Referenced by BuildQueryCompletionString(), and pg_lltoa().

◆ pg_ultoa_n()

int pg_ultoa_n ( uint32  value,
char *  a 
)

Definition at line 1057 of file numutils.c.

1058 {
1059  int olength,
1060  i = 0;
1061 
1062  /* Degenerate case */
1063  if (value == 0)
1064  {
1065  *a = '0';
1066  return 1;
1067  }
1068 
1069  olength = decimalLength32(value);
1070 
1071  /* Compute the result string. */
1072  while (value >= 10000)
1073  {
1074  const uint32 c = value - 10000 * (value / 10000);
1075  const uint32 c0 = (c % 100) << 1;
1076  const uint32 c1 = (c / 100) << 1;
1077 
1078  char *pos = a + olength - i;
1079 
1080  value /= 10000;
1081 
1082  memcpy(pos - 2, DIGIT_TABLE + c0, 2);
1083  memcpy(pos - 4, DIGIT_TABLE + c1, 2);
1084  i += 4;
1085  }
1086  if (value >= 100)
1087  {
1088  const uint32 c = (value % 100) << 1;
1089 
1090  char *pos = a + olength - i;
1091 
1092  value /= 100;
1093 
1094  memcpy(pos - 2, DIGIT_TABLE + c, 2);
1095  i += 2;
1096  }
1097  if (value >= 10)
1098  {
1099  const uint32 c = value << 1;
1100 
1101  char *pos = a + olength - i;
1102 
1103  memcpy(pos - 2, DIGIT_TABLE + c, 2);
1104  }
1105  else
1106  {
1107  *a = (char) ('0' + value);
1108  }
1109 
1110  return olength;
1111 }
static int decimalLength32(const uint32 v)
Definition: numutils.c:44

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

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

◆ pg_ultostr()

char* pg_ultostr ( char *  str,
uint32  value 
)

Definition at line 1309 of file numutils.c.

1310 {
1311  int len = pg_ultoa_n(value, str);
1312 
1313  return str + len;
1314 }

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 1269 of file numutils.c.

1270 {
1271  int len;
1272 
1273  Assert(minwidth > 0);
1274 
1275  if (value < 100 && minwidth == 2) /* Short cut for common case */
1276  {
1277  memcpy(str, DIGIT_TABLE + value * 2, 2);
1278  return str + 2;
1279  }
1280 
1281  len = pg_ultoa_n(value, str);
1282  if (len >= minwidth)
1283  return str + len;
1284 
1285  memmove(str + minwidth - len, str, len);
1286  memset(str, '0', minwidth - len);
1287  return str + minwidth;
1288 }
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().

◆ uint32in_subr()

uint32 uint32in_subr ( const char *  s,
char **  endloc,
const char *  typname,
Node escontext 
)

Definition at line 900 of file numutils.c.

902 {
903  uint32 result;
904  unsigned long cvt;
905  char *endptr;
906 
907  errno = 0;
908  cvt = strtoul(s, &endptr, 0);
909 
910  /*
911  * strtoul() normally only sets ERANGE. On some systems it may also set
912  * EINVAL, which simply means it couldn't parse the input string. Be sure
913  * to report that the same way as the standard error indication (that
914  * endptr == s).
915  */
916  if ((errno && errno != ERANGE) || endptr == s)
917  ereturn(escontext, 0,
918  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
919  errmsg("invalid input syntax for type %s: \"%s\"",
920  typname, s)));
921 
922  if (errno == ERANGE)
923  ereturn(escontext, 0,
924  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
925  errmsg("value \"%s\" is out of range for type %s",
926  s, typname)));
927 
928  if (endloc)
929  {
930  /* caller wants to deal with rest of string */
931  *endloc = endptr;
932  }
933  else
934  {
935  /* allow only whitespace after number */
936  while (*endptr && isspace((unsigned char) *endptr))
937  endptr++;
938  if (*endptr)
939  ereturn(escontext, 0,
940  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
941  errmsg("invalid input syntax for type %s: \"%s\"",
942  typname, s)));
943  }
944 
945  result = (uint32) cvt;
946 
947  /*
948  * Cope with possibility that unsigned long is wider than uint32, in which
949  * case strtoul will not raise an error for some values that are out of
950  * the range of uint32.
951  *
952  * For backwards compatibility, we want to accept inputs that are given
953  * with a minus sign, so allow the input value if it matches after either
954  * signed or unsigned extension to long.
955  *
956  * To ensure consistent results on 32-bit and 64-bit platforms, make sure
957  * the error message is the same as if strtoul() had returned ERANGE.
958  */
959 #if PG_UINT32_MAX != ULONG_MAX
960  if (cvt != (unsigned long) result &&
961  cvt != (unsigned long) ((int) result))
962  ereturn(escontext, 0,
963  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
964  errmsg("value \"%s\" is out of range for type %s",
965  s, typname)));
966 #endif
967 
968  return result;
969 }
NameData typname
Definition: pg_type.h:41

References ereturn, errcode(), errmsg(), and typname.

Referenced by cidin(), oidin(), oidparse(), oidvectorin(), and xidin().

◆ uint64in_subr()

uint64 uint64in_subr ( const char *  s,
char **  endloc,
const char *  typname,
Node escontext 
)

Definition at line 987 of file numutils.c.

989 {
990  uint64 result;
991  char *endptr;
992 
993  errno = 0;
994  result = strtou64(s, &endptr, 0);
995 
996  /*
997  * strtoul[l] normally only sets ERANGE. On some systems it may also set
998  * EINVAL, which simply means it couldn't parse the input string. Be sure
999  * to report that the same way as the standard error indication (that
1000  * endptr == s).
1001  */
1002  if ((errno && errno != ERANGE) || endptr == s)
1003  ereturn(escontext, 0,
1004  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1005  errmsg("invalid input syntax for type %s: \"%s\"",
1006  typname, s)));
1007 
1008  if (errno == ERANGE)
1009  ereturn(escontext, 0,
1010  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1011  errmsg("value \"%s\" is out of range for type %s",
1012  s, typname)));
1013 
1014  if (endloc)
1015  {
1016  /* caller wants to deal with rest of string */
1017  *endloc = endptr;
1018  }
1019  else
1020  {
1021  /* allow only whitespace after number */
1022  while (*endptr && isspace((unsigned char) *endptr))
1023  endptr++;
1024  if (*endptr)
1025  ereturn(escontext, 0,
1026  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1027  errmsg("invalid input syntax for type %s: \"%s\"",
1028  typname, s)));
1029  }
1030 
1031  return result;
1032 }
#define strtou64(str, endptr, base)
Definition: c.h:1285

References ereturn, errcode(), errmsg(), strtou64, and typname.

Referenced by xid8in().

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 28 of file numutils.c.

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

◆ hexlookup

const int8 hexlookup[128]
static
Initial value:
= {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
}

Definition at line 87 of file numutils.c.

Referenced by pg_strtoint16_safe(), pg_strtoint32_safe(), and pg_strtoint64_safe().