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}
uint32_t uint32
Definition: c.h:485
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[] = {
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}
uint64_t uint64
Definition: c.h:486
#define UINT64CONST(x)
Definition: c.h:500
static int pg_leftmost_one_pos64(uint64 word)
Definition: pg_bitutils.h:72

References pg_leftmost_one_pos64(), and UINT64CONST.

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}
int32_t int32
Definition: c.h:481
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 @161 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
205slow:
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
347out_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
353invalid_syntax:
354 ereturn(escontext, 0,
355 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
356 errmsg("invalid input syntax for type %s: \"%s\"",
357 "smallint", s)));
358}
#define likely(x)
Definition: c.h:329
int16_t int16
Definition: c.h:480
#define PG_INT16_MIN
Definition: c.h:539
uint16_t uint16
Definition: c.h:484
#define unlikely(x)
Definition: c.h:330
#define PG_INT16_MAX
Definition: c.h:540
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:420
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
466slow:
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
608out_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
614invalid_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:543
#define PG_INT32_MIN
Definition: c.h:542
static bool pg_neg_u32_overflow(uint32 a, int32 *result)
Definition: int.h:493

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

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

◆ 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
727slow:
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
869out_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
875invalid_syntax:
876 ereturn(escontext, 0,
877 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
878 errmsg("invalid input syntax for type %s: \"%s\"",
879 "bigint", s)));
880}
int64_t int64
Definition: c.h:482
#define PG_INT64_MAX
Definition: c.h:546
#define PG_INT64_MIN
Definition: c.h:545
static bool pg_neg_u64_overflow(uint64 a, int64 *result)
Definition: int.h:576

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:812

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}

References ereturn, errcode(), errmsg(), 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().