PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
numutils.c File Reference
#include "postgres.h"
#include <math.h>
#include <limits.h>
#include <ctype.h>
#include "common/int.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 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:518
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 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:72

References pg_leftmost_one_pos64().

Referenced by pg_ulltoa_n().

◆ pg_itoa()

int pg_itoa ( int16  i,
char *  a 
)

Definition at line 1042 of file numutils.c.

1043 {
1044  return pg_ltoa((int32) i, a);
1045 }
signed int int32
Definition: c.h:508
int a
Definition: isn.c:68
int i
Definition: isn.c:72
int pg_ltoa(int32 value, char *a)
Definition: numutils.c:1120

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

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

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

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

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

References pg_strtoint16_safe().

◆ pg_strtoint16_safe()

int16 pg_strtoint16_safe ( const char *  s,
Node escontext 
)

Definition at line 128 of file numutils.c.

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

References ereturn, errcode(), errmsg(), hexlookup, likely, PG_INT16_MAX, PG_INT16_MIN, pg_neg_u16_overflow(), 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  int32 result;
397 
398  /*
399  * The majority of cases are likely to be base-10 digits without any
400  * underscore separator characters. We'll first try to parse the string
401  * with the assumption that's the case and only fallback on a slower
402  * implementation which handles hex, octal and binary strings and
403  * underscores if the fastpath version cannot parse the string.
404  */
405 
406  /* leave it up to the slow path to look for leading spaces */
407 
408  if (*ptr == '-')
409  {
410  ptr++;
411  neg = true;
412  }
413 
414  /* a leading '+' is uncommon so leave that for the slow path */
415 
416  /* process the first digit */
417  digit = (*ptr - '0');
418 
419  /*
420  * Exploit unsigned arithmetic to save having to check both the upper and
421  * lower bounds of the digit.
422  */
423  if (likely(digit < 10))
424  {
425  ptr++;
426  tmp = digit;
427  }
428  else
429  {
430  /* we need at least one digit */
431  goto slow;
432  }
433 
434  /* process remaining digits */
435  for (;;)
436  {
437  digit = (*ptr - '0');
438 
439  if (digit >= 10)
440  break;
441 
442  ptr++;
443 
444  if (unlikely(tmp > -(PG_INT32_MIN / 10)))
445  goto out_of_range;
446 
447  tmp = tmp * 10 + digit;
448  }
449 
450  /* when the string does not end in a digit, let the slow path handle it */
451  if (unlikely(*ptr != '\0'))
452  goto slow;
453 
454  if (neg)
455  {
456  if (unlikely(pg_neg_u32_overflow(tmp, &result)))
457  goto out_of_range;
458  return result;
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  if (unlikely(pg_neg_u32_overflow(tmp, &result)))
599  goto out_of_range;
600  return result;
601  }
602 
603  if (tmp > PG_INT32_MAX)
604  goto out_of_range;
605 
606  return (int32) tmp;
607 
608 out_of_range:
609  ereturn(escontext, 0,
610  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
611  errmsg("value \"%s\" is out of range for type %s",
612  s, "integer")));
613 
614 invalid_syntax:
615  ereturn(escontext, 0,
616  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
617  errmsg("invalid input syntax for type %s: \"%s\"",
618  "integer", s)));
619 }
#define PG_INT32_MAX
Definition: c.h:592
#define PG_INT32_MIN
Definition: c.h:591
static bool pg_neg_u32_overflow(uint32 a, int32 *result)
Definition: int.h:445

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

Referenced by int4in(), and pg_strtoint32().

◆ pg_strtoint64()

int64 pg_strtoint64 ( const char *  s)

Definition at line 644 of file numutils.c.

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

References pg_strtoint64_safe().

Referenced by defGetCopyRejectLimitOption().

◆ pg_strtoint64_safe()

int64 pg_strtoint64_safe ( const char *  s,
Node escontext 
)

Definition at line 650 of file numutils.c.

651 {
652  const char *ptr = s;
653  const char *firstdigit;
654  uint64 tmp = 0;
655  bool neg = false;
656  unsigned char digit;
657  int64 result;
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  if (unlikely(pg_neg_u64_overflow(tmp, &result)))
718  goto out_of_range;
719  return result;
720  }
721 
722  if (unlikely(tmp > PG_INT64_MAX))
723  goto out_of_range;
724 
725  return (int64) tmp;
726 
727 slow:
728  tmp = 0;
729  ptr = s;
730  /* no need to reset neg */
731 
732  /* skip leading spaces */
733  while (isspace((unsigned char) *ptr))
734  ptr++;
735 
736  /* handle sign */
737  if (*ptr == '-')
738  {
739  ptr++;
740  neg = true;
741  }
742  else if (*ptr == '+')
743  ptr++;
744 
745  /* process digits */
746  if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
747  {
748  firstdigit = ptr += 2;
749 
750  for (;;)
751  {
752  if (isxdigit((unsigned char) *ptr))
753  {
754  if (unlikely(tmp > -(PG_INT64_MIN / 16)))
755  goto out_of_range;
756 
757  tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
758  }
759  else if (*ptr == '_')
760  {
761  /* underscore must be followed by more digits */
762  ptr++;
763  if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
764  goto invalid_syntax;
765  }
766  else
767  break;
768  }
769  }
770  else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
771  {
772  firstdigit = ptr += 2;
773 
774  for (;;)
775  {
776  if (*ptr >= '0' && *ptr <= '7')
777  {
778  if (unlikely(tmp > -(PG_INT64_MIN / 8)))
779  goto out_of_range;
780 
781  tmp = tmp * 8 + (*ptr++ - '0');
782  }
783  else if (*ptr == '_')
784  {
785  /* underscore must be followed by more digits */
786  ptr++;
787  if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
788  goto invalid_syntax;
789  }
790  else
791  break;
792  }
793  }
794  else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
795  {
796  firstdigit = ptr += 2;
797 
798  for (;;)
799  {
800  if (*ptr >= '0' && *ptr <= '1')
801  {
802  if (unlikely(tmp > -(PG_INT64_MIN / 2)))
803  goto out_of_range;
804 
805  tmp = tmp * 2 + (*ptr++ - '0');
806  }
807  else if (*ptr == '_')
808  {
809  /* underscore must be followed by more digits */
810  ptr++;
811  if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
812  goto invalid_syntax;
813  }
814  else
815  break;
816  }
817  }
818  else
819  {
820  firstdigit = ptr;
821 
822  for (;;)
823  {
824  if (*ptr >= '0' && *ptr <= '9')
825  {
826  if (unlikely(tmp > -(PG_INT64_MIN / 10)))
827  goto out_of_range;
828 
829  tmp = tmp * 10 + (*ptr++ - '0');
830  }
831  else if (*ptr == '_')
832  {
833  /* underscore may not be first */
834  if (unlikely(ptr == firstdigit))
835  goto invalid_syntax;
836  /* and it must be followed by more digits */
837  ptr++;
838  if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
839  goto invalid_syntax;
840  }
841  else
842  break;
843  }
844  }
845 
846  /* require at least one digit */
847  if (unlikely(ptr == firstdigit))
848  goto invalid_syntax;
849 
850  /* allow trailing whitespace, but not other trailing chars */
851  while (isspace((unsigned char) *ptr))
852  ptr++;
853 
854  if (unlikely(*ptr != '\0'))
855  goto invalid_syntax;
856 
857  if (neg)
858  {
859  if (unlikely(pg_neg_u64_overflow(tmp, &result)))
860  goto out_of_range;
861  return result;
862  }
863 
864  if (tmp > PG_INT64_MAX)
865  goto out_of_range;
866 
867  return (int64) tmp;
868 
869 out_of_range:
870  ereturn(escontext, 0,
871  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
872  errmsg("value \"%s\" is out of range for type %s",
873  s, "bigint")));
874 
875 invalid_syntax:
876  ereturn(escontext, 0,
877  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
878  errmsg("invalid input syntax for type %s: \"%s\"",
879  "bigint", s)));
880 }
#define PG_INT64_MAX
Definition: c.h:595
#define PG_INT64_MIN
Definition: c.h:594
static bool pg_neg_u64_overflow(uint64 a, int64 *result)
Definition: int.h:528

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

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

◆ pg_ulltoa_n()

int pg_ulltoa_n ( uint64  value,
char *  a 
)

Definition at line 1140 of file numutils.c.

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

◆ pg_ultoa_n()

int pg_ultoa_n ( uint32  value,
char *  a 
)

Definition at line 1055 of file numutils.c.

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

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

1308 {
1309  int len = pg_ultoa_n(value, str);
1310 
1311  return str + len;
1312 }
const char * str

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

Referenced by AppendSeconds().

◆ pg_ultostr_zeropad()

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

Definition at line 1267 of file numutils.c.

1268 {
1269  int len;
1270 
1271  Assert(minwidth > 0);
1272 
1273  if (value < 100 && minwidth == 2) /* Short cut for common case */
1274  {
1275  memcpy(str, DIGIT_TABLE + value * 2, 2);
1276  return str + 2;
1277  }
1278 
1279  len = pg_ultoa_n(value, str);
1280  if (len >= minwidth)
1281  return str + len;
1282 
1283  memmove(str + minwidth - len, str, len);
1284  memset(str, '0', minwidth - len);
1285  return str + minwidth;
1286 }
#define Assert(condition)
Definition: c.h:861

References Assert, DIGIT_TABLE, len, pg_ultoa_n(), 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 898 of file numutils.c.

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

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

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

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

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