PostgreSQL Source Code git master
Loading...
Searching...
No Matches
numutils.c File Reference
#include "postgres.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)
 
charpg_ultostr_zeropad (char *str, uint32 value, int32 minwidth)
 
charpg_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}
uint32_t uint32
Definition c.h:546
static int pg_leftmost_one_pos32(uint32 word)
Definition pg_bitutils.h:41
static int fb(int x)

References fb(), and 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[] = {
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}
uint64_t uint64
Definition c.h:547
#define UINT64CONST(x)
Definition c.h:561
static int pg_leftmost_one_pos64(uint64 word)
Definition pg_bitutils.h:72

References fb(), pg_leftmost_one_pos64(), and UINT64CONST.

Referenced by pg_ulltoa_n().

◆ pg_itoa()

int pg_itoa ( int16  i,
char a 
)

Definition at line 1041 of file numutils.c.

1042{
1043 return pg_ltoa((int32) i, a);
1044}
int32_t int32
Definition c.h:542
int a
Definition isn.c:73
int i
Definition isn.c:77
int pg_ltoa(int32 value, char *a)
Definition numutils.c:1119

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

1227{
1229 int len = 0;
1230
1231 if (value < 0)
1232 {
1233 uvalue = (uint64) 0 - uvalue;
1234 a[len++] = '-';
1235 }
1236
1237 len += pg_ulltoa_n(uvalue, a + len);
1238 a[len] = '\0';
1239 return len;
1240}
static struct @172 value
int pg_ulltoa_n(uint64 value, char *a)
Definition numutils.c:1139
const void size_t len

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

Referenced by int8out(), and printsimple().

◆ pg_ltoa()

int pg_ltoa ( int32  value,
char a 
)

Definition at line 1119 of file numutils.c.

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

References a, fb(), 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 fb(), and 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 int16 result;
135
136 /*
137 * The majority of cases are likely to be base-10 digits without any
138 * underscore separator characters. We'll first try to parse the string
139 * with the assumption that's the case and only fallback on a slower
140 * implementation which handles hex, octal and binary strings and
141 * underscores if the fastpath version cannot parse the string.
142 */
143
144 /* leave it up to the slow path to look for leading spaces */
145
146 if (*ptr == '-')
147 {
148 ptr++;
149 neg = true;
150 }
151
152 /* a leading '+' is uncommon so leave that for the slow path */
153
154 /* process the first digit */
155 digit = (*ptr - '0');
156
157 /*
158 * Exploit unsigned arithmetic to save having to check both the upper and
159 * lower bounds of the digit.
160 */
161 if (likely(digit < 10))
162 {
163 ptr++;
164 tmp = digit;
165 }
166 else
167 {
168 /* we need at least one digit */
169 goto slow;
170 }
171
172 /* process remaining digits */
173 for (;;)
174 {
175 digit = (*ptr - '0');
176
177 if (digit >= 10)
178 break;
179
180 ptr++;
181
182 if (unlikely(tmp > -(PG_INT16_MIN / 10)))
183 goto out_of_range;
184
185 tmp = tmp * 10 + digit;
186 }
187
188 /* when the string does not end in a digit, let the slow path handle it */
189 if (unlikely(*ptr != '\0'))
190 goto slow;
191
192 if (neg)
193 {
194 if (unlikely(pg_neg_u16_overflow(tmp, &result)))
195 goto out_of_range;
196 return result;
197 }
198
199 if (unlikely(tmp > PG_INT16_MAX))
200 goto out_of_range;
201
202 return (int16) tmp;
203
204slow:
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 if (unlikely(pg_neg_u16_overflow(tmp, &result)))
337 goto out_of_range;
338 return result;
339 }
340
341 if (tmp > PG_INT16_MAX)
342 goto out_of_range;
343
344 return (int16) tmp;
345
347 ereturn(escontext, 0,
349 errmsg("value \"%s\" is out of range for type %s",
350 s, "smallint")));
351
353 ereturn(escontext, 0,
355 errmsg("invalid input syntax for type %s: \"%s\"",
356 "smallint", s)));
357}
#define likely(x)
Definition c.h:411
int16_t int16
Definition c.h:541
#define PG_INT16_MIN
Definition c.h:599
uint16_t uint16
Definition c.h:545
#define unlikely(x)
Definition c.h:412
#define PG_INT16_MAX
Definition c.h:600
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ereturn(context, dummy_value,...)
Definition elog.h:278
static bool pg_neg_u16_overflow(uint16 a, int16 *result)
Definition int.h:420
static const int8 hexlookup[128]
Definition numutils.c:87

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

Referenced by dependencies_scalar(), int2in(), ndistinct_scalar(), and pg_strtoint16().

◆ pg_strtoint32()

int32 pg_strtoint32 ( const char s)

Definition at line 382 of file numutils.c.

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

References fb(), and 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 388 of file numutils.c.

389{
390 const char *ptr = s;
391 const char *firstdigit;
392 uint32 tmp = 0;
393 bool neg = false;
394 unsigned char digit;
395 int32 result;
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 if (unlikely(pg_neg_u32_overflow(tmp, &result)))
456 goto out_of_range;
457 return result;
458 }
459
460 if (unlikely(tmp > PG_INT32_MAX))
461 goto out_of_range;
462
463 return (int32) tmp;
464
465slow:
466 tmp = 0;
467 ptr = s;
468 /* no need to reset neg */
469
470 /* skip leading spaces */
471 while (isspace((unsigned char) *ptr))
472 ptr++;
473
474 /* handle sign */
475 if (*ptr == '-')
476 {
477 ptr++;
478 neg = true;
479 }
480 else if (*ptr == '+')
481 ptr++;
482
483 /* process digits */
484 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
485 {
486 firstdigit = ptr += 2;
487
488 for (;;)
489 {
490 if (isxdigit((unsigned char) *ptr))
491 {
492 if (unlikely(tmp > -(PG_INT32_MIN / 16)))
493 goto out_of_range;
494
495 tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
496 }
497 else if (*ptr == '_')
498 {
499 /* underscore must be followed by more digits */
500 ptr++;
501 if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
502 goto invalid_syntax;
503 }
504 else
505 break;
506 }
507 }
508 else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
509 {
510 firstdigit = ptr += 2;
511
512 for (;;)
513 {
514 if (*ptr >= '0' && *ptr <= '7')
515 {
516 if (unlikely(tmp > -(PG_INT32_MIN / 8)))
517 goto out_of_range;
518
519 tmp = tmp * 8 + (*ptr++ - '0');
520 }
521 else if (*ptr == '_')
522 {
523 /* underscore must be followed by more digits */
524 ptr++;
525 if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
526 goto invalid_syntax;
527 }
528 else
529 break;
530 }
531 }
532 else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
533 {
534 firstdigit = ptr += 2;
535
536 for (;;)
537 {
538 if (*ptr >= '0' && *ptr <= '1')
539 {
540 if (unlikely(tmp > -(PG_INT32_MIN / 2)))
541 goto out_of_range;
542
543 tmp = tmp * 2 + (*ptr++ - '0');
544 }
545 else if (*ptr == '_')
546 {
547 /* underscore must be followed by more digits */
548 ptr++;
549 if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
550 goto invalid_syntax;
551 }
552 else
553 break;
554 }
555 }
556 else
557 {
558 firstdigit = ptr;
559
560 for (;;)
561 {
562 if (*ptr >= '0' && *ptr <= '9')
563 {
564 if (unlikely(tmp > -(PG_INT32_MIN / 10)))
565 goto out_of_range;
566
567 tmp = tmp * 10 + (*ptr++ - '0');
568 }
569 else if (*ptr == '_')
570 {
571 /* underscore may not be first */
572 if (unlikely(ptr == firstdigit))
573 goto invalid_syntax;
574 /* and it must be followed by more digits */
575 ptr++;
576 if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
577 goto invalid_syntax;
578 }
579 else
580 break;
581 }
582 }
583
584 /* require at least one digit */
585 if (unlikely(ptr == firstdigit))
586 goto invalid_syntax;
587
588 /* allow trailing whitespace, but not other trailing chars */
589 while (isspace((unsigned char) *ptr))
590 ptr++;
591
592 if (unlikely(*ptr != '\0'))
593 goto invalid_syntax;
594
595 if (neg)
596 {
597 if (unlikely(pg_neg_u32_overflow(tmp, &result)))
598 goto out_of_range;
599 return result;
600 }
601
602 if (tmp > PG_INT32_MAX)
603 goto out_of_range;
604
605 return (int32) tmp;
606
608 ereturn(escontext, 0,
610 errmsg("value \"%s\" is out of range for type %s",
611 s, "integer")));
612
614 ereturn(escontext, 0,
616 errmsg("invalid input syntax for type %s: \"%s\"",
617 "integer", s)));
618}
#define PG_INT32_MAX
Definition c.h:603
#define PG_INT32_MIN
Definition c.h:602
static bool pg_neg_u32_overflow(uint32 a, int32 *result)
Definition int.h:493

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

Referenced by defGetCopyHeaderOption(), int4in(), ndistinct_scalar(), pg_strtoint32(), and process_integer_literal().

◆ pg_strtoint64()

int64 pg_strtoint64 ( const char s)

Definition at line 643 of file numutils.c.

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

References fb(), and pg_strtoint64_safe().

Referenced by defGetCopyRejectLimitOption().

◆ pg_strtoint64_safe()

int64 pg_strtoint64_safe ( const char s,
Node escontext 
)

Definition at line 649 of file numutils.c.

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

References ereturn, errcode(), errmsg(), fb(), 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 1139 of file numutils.c.

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

Referenced by BuildQueryCompletionString(), oid8out(), and pg_lltoa().

◆ pg_ultoa_n()

int pg_ultoa_n ( uint32  value,
char a 
)

Definition at line 1054 of file numutils.c.

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

References a, decimalLength32(), DIGIT_TABLE, fb(), 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 1306 of file numutils.c.

1307{
1308 int len = pg_ultoa_n(value, str);
1309
1310 return str + len;
1311}
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 1266 of file numutils.c.

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

References Assert, DIGIT_TABLE, fb(), 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 897 of file numutils.c.

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

References ereturn, errcode(), errmsg(), fb(), 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 984 of file numutils.c.

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

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

Referenced by oid8in(), and 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(), 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.

87 {
88 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
89 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
90 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
91 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
92 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
93 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
94 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
95 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
96};

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