Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * numutils.c
4 : * utility functions for I/O of built-in numeric types.
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/utils/adt/numutils.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include <math.h>
18 : #include <limits.h>
19 : #include <ctype.h>
20 :
21 : #include "common/int.h"
22 : #include "utils/builtins.h"
23 : #include "port/pg_bitutils.h"
24 :
25 : /*
26 : * A table of all two-digit numbers. This is used to speed up decimal digit
27 : * generation by copying pairs of digits into the final output.
28 : */
29 : static const char DIGIT_TABLE[200] =
30 : "00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
31 : "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
32 : "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
33 : "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
34 : "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
35 : "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
36 : "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
37 : "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
38 : "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
39 : "90" "91" "92" "93" "94" "95" "96" "97" "98" "99";
40 :
41 : /*
42 : * Adapted from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
43 : */
44 : static inline int
45 13993744 : decimalLength32(const uint32 v)
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 13993744 : t = (pg_leftmost_one_pos32(v) + 1) * 1233 / 4096;
60 13993744 : return t + (v >= PowersOfTen[t]);
61 : }
62 :
63 : static inline int
64 543142 : decimalLength64(const uint64 v)
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 543142 : t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096;
85 543142 : return t + (v >= PowersOfTen[t]);
86 : }
87 :
88 : static const int8 hexlookup[128] = {
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 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
92 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
93 : -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
94 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
95 : -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
96 : -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
97 : };
98 :
99 : /*
100 : * Convert input string to a signed 16 bit integer.
101 : *
102 : * Allows any number of leading or trailing whitespace characters.
103 : *
104 : * pg_strtoint16() will throw ereport() upon bad input format or overflow;
105 : * while pg_strtoint16_safe() instead returns such complaints in *escontext,
106 : * if it's an ErrorSaveContext.
107 : *
108 : * NB: Accumulate input as an unsigned number, to deal with two's complement
109 : * representation of the most negative number, which can't be represented as a
110 : * signed positive number.
111 : */
112 : int16
113 0 : pg_strtoint16(const char *s)
114 : {
115 0 : return pg_strtoint16_safe(s, NULL);
116 : }
117 :
118 : int16
119 5631568 : pg_strtoint16_safe(const char *s, Node *escontext)
120 : {
121 5631568 : const char *ptr = s;
122 : const char *firstdigit;
123 5631568 : uint16 tmp = 0;
124 5631568 : bool neg = false;
125 :
126 : /* skip leading spaces */
127 5631628 : while (likely(*ptr) && isspace((unsigned char) *ptr))
128 60 : ptr++;
129 :
130 : /* handle sign */
131 5631568 : if (*ptr == '-')
132 : {
133 183728 : ptr++;
134 183728 : neg = true;
135 : }
136 5447840 : else if (*ptr == '+')
137 0 : ptr++;
138 :
139 : /* process digits */
140 5631568 : if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
141 : {
142 42 : firstdigit = ptr += 2;
143 :
144 180 : while (*ptr)
145 : {
146 138 : if (isxdigit((unsigned char) *ptr))
147 : {
148 132 : if (unlikely(tmp > -(PG_INT16_MIN / 16)))
149 0 : goto out_of_range;
150 :
151 132 : tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
152 : }
153 6 : else if (*ptr == '_')
154 : {
155 : /* underscore must be followed by more digits */
156 6 : ptr++;
157 6 : if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
158 0 : goto invalid_syntax;
159 : }
160 : else
161 0 : break;
162 : }
163 : }
164 5631526 : else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
165 : {
166 42 : firstdigit = ptr += 2;
167 :
168 222 : while (*ptr)
169 : {
170 180 : if (*ptr >= '0' && *ptr <= '7')
171 : {
172 174 : if (unlikely(tmp > -(PG_INT16_MIN / 8)))
173 0 : goto out_of_range;
174 :
175 174 : tmp = tmp * 8 + (*ptr++ - '0');
176 : }
177 6 : else if (*ptr == '_')
178 : {
179 : /* underscore must be followed by more digits */
180 6 : ptr++;
181 6 : if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
182 0 : goto invalid_syntax;
183 : }
184 : else
185 0 : break;
186 : }
187 : }
188 5631484 : else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
189 : {
190 42 : firstdigit = ptr += 2;
191 :
192 504 : while (*ptr)
193 : {
194 462 : if (*ptr >= '0' && *ptr <= '1')
195 : {
196 450 : if (unlikely(tmp > -(PG_INT16_MIN / 2)))
197 0 : goto out_of_range;
198 :
199 450 : tmp = tmp * 2 + (*ptr++ - '0');
200 : }
201 12 : else if (*ptr == '_')
202 : {
203 : /* underscore must be followed by more digits */
204 12 : ptr++;
205 12 : if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
206 0 : goto invalid_syntax;
207 : }
208 : else
209 0 : break;
210 : }
211 : }
212 : else
213 : {
214 5631442 : firstdigit = ptr;
215 :
216 11415318 : while (*ptr)
217 : {
218 5783968 : if (isdigit((unsigned char) *ptr))
219 : {
220 5783876 : if (unlikely(tmp > -(PG_INT16_MIN / 10)))
221 18 : goto out_of_range;
222 :
223 5783858 : tmp = tmp * 10 + (*ptr++ - '0');
224 : }
225 92 : else if (*ptr == '_')
226 : {
227 : /* underscore may not be first */
228 36 : if (unlikely(ptr == firstdigit))
229 6 : goto invalid_syntax;
230 : /* and it must be followed by more digits */
231 30 : ptr++;
232 30 : if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
233 12 : goto invalid_syntax;
234 : }
235 : else
236 56 : break;
237 : }
238 : }
239 :
240 : /* require at least one digit */
241 5631532 : if (unlikely(ptr == firstdigit))
242 54 : goto invalid_syntax;
243 :
244 : /* allow trailing whitespace, but not other trailing chars */
245 5631514 : while (*ptr != '\0' && isspace((unsigned char) *ptr))
246 36 : ptr++;
247 :
248 5631478 : if (unlikely(*ptr != '\0'))
249 20 : goto invalid_syntax;
250 :
251 5631458 : if (neg)
252 : {
253 : /* check the negative equivalent will fit without overflowing */
254 183722 : if (tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1)
255 18 : goto out_of_range;
256 183704 : return -((int16) tmp);
257 : }
258 :
259 5447736 : if (tmp > PG_INT16_MAX)
260 18 : goto out_of_range;
261 :
262 5447718 : return (int16) tmp;
263 :
264 54 : out_of_range:
265 54 : ereturn(escontext, 0,
266 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
267 : errmsg("value \"%s\" is out of range for type %s",
268 : s, "smallint")));
269 :
270 92 : invalid_syntax:
271 92 : ereturn(escontext, 0,
272 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
273 : errmsg("invalid input syntax for type %s: \"%s\"",
274 : "smallint", s)));
275 : }
276 :
277 : /*
278 : * Convert input string to a signed 32 bit integer.
279 : *
280 : * Allows any number of leading or trailing whitespace characters.
281 : *
282 : * pg_strtoint32() will throw ereport() upon bad input format or overflow;
283 : * while pg_strtoint32_safe() instead returns such complaints in *escontext,
284 : * if it's an ErrorSaveContext.
285 : *
286 : * NB: Accumulate input as an unsigned number, to deal with two's complement
287 : * representation of the most negative number, which can't be represented as a
288 : * signed positive number.
289 : */
290 : int32
291 11722 : pg_strtoint32(const char *s)
292 : {
293 11722 : return pg_strtoint32_safe(s, NULL);
294 : }
295 :
296 : int32
297 7360356 : pg_strtoint32_safe(const char *s, Node *escontext)
298 : {
299 7360356 : const char *ptr = s;
300 : const char *firstdigit;
301 7360356 : uint32 tmp = 0;
302 7360356 : bool neg = false;
303 :
304 : /* skip leading spaces */
305 7360494 : while (likely(*ptr) && isspace((unsigned char) *ptr))
306 138 : ptr++;
307 :
308 : /* handle sign */
309 7360356 : if (*ptr == '-')
310 : {
311 322546 : ptr++;
312 322546 : neg = true;
313 : }
314 7037810 : else if (*ptr == '+')
315 0 : ptr++;
316 :
317 : /* process digits */
318 7360356 : if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
319 : {
320 3112 : firstdigit = ptr += 2;
321 :
322 15872 : while (*ptr)
323 : {
324 12784 : if (isxdigit((unsigned char) *ptr))
325 : {
326 12772 : if (unlikely(tmp > -(PG_INT32_MIN / 16)))
327 24 : goto out_of_range;
328 :
329 12748 : tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
330 : }
331 12 : else if (*ptr == '_')
332 : {
333 : /* underscore must be followed by more digits */
334 12 : ptr++;
335 12 : if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
336 0 : goto invalid_syntax;
337 : }
338 : else
339 0 : break;
340 : }
341 : }
342 7357244 : else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
343 : {
344 102 : firstdigit = ptr += 2;
345 :
346 972 : while (*ptr)
347 : {
348 894 : if (*ptr >= '0' && *ptr <= '7')
349 : {
350 882 : if (unlikely(tmp > -(PG_INT32_MIN / 8)))
351 24 : goto out_of_range;
352 :
353 858 : tmp = tmp * 8 + (*ptr++ - '0');
354 : }
355 12 : else if (*ptr == '_')
356 : {
357 : /* underscore must be followed by more digits */
358 12 : ptr++;
359 12 : if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
360 0 : goto invalid_syntax;
361 : }
362 : else
363 0 : break;
364 : }
365 : }
366 7357142 : else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
367 : {
368 104 : firstdigit = ptr += 2;
369 :
370 2622 : while (*ptr)
371 : {
372 2544 : if (*ptr >= '0' && *ptr <= '1')
373 : {
374 2520 : if (unlikely(tmp > -(PG_INT32_MIN / 2)))
375 26 : goto out_of_range;
376 :
377 2494 : tmp = tmp * 2 + (*ptr++ - '0');
378 : }
379 24 : else if (*ptr == '_')
380 : {
381 : /* underscore must be followed by more digits */
382 24 : ptr++;
383 24 : if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
384 0 : goto invalid_syntax;
385 : }
386 : else
387 0 : break;
388 : }
389 : }
390 : else
391 : {
392 7357038 : firstdigit = ptr;
393 :
394 23821974 : while (*ptr)
395 : {
396 16466238 : if (isdigit((unsigned char) *ptr))
397 : {
398 16465908 : if (unlikely(tmp > -(PG_INT32_MIN / 10)))
399 1110 : goto out_of_range;
400 :
401 16464798 : tmp = tmp * 10 + (*ptr++ - '0');
402 : }
403 330 : else if (*ptr == '_')
404 : {
405 : /* underscore may not be first */
406 156 : if (unlikely(ptr == firstdigit))
407 6 : goto invalid_syntax;
408 : /* and it must be followed by more digits */
409 150 : ptr++;
410 150 : if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
411 12 : goto invalid_syntax;
412 : }
413 : else
414 174 : break;
415 : }
416 : }
417 :
418 : /* require at least one digit */
419 7359154 : if (unlikely(ptr == firstdigit))
420 180 : goto invalid_syntax;
421 :
422 : /* allow trailing whitespace, but not other trailing chars */
423 7359058 : while (*ptr != '\0' && isspace((unsigned char) *ptr))
424 84 : ptr++;
425 :
426 7358974 : if (unlikely(*ptr != '\0'))
427 18 : goto invalid_syntax;
428 :
429 7358956 : if (neg)
430 : {
431 : /* check the negative equivalent will fit without overflowing */
432 322540 : if (tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1)
433 18 : goto out_of_range;
434 322522 : return -((int32) tmp);
435 : }
436 :
437 7036416 : if (tmp > PG_INT32_MAX)
438 214 : goto out_of_range;
439 :
440 7036202 : return (int32) tmp;
441 :
442 1416 : out_of_range:
443 1416 : ereturn(escontext, 0,
444 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
445 : errmsg("value \"%s\" is out of range for type %s",
446 : s, "integer")));
447 :
448 216 : invalid_syntax:
449 216 : ereturn(escontext, 0,
450 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
451 : errmsg("invalid input syntax for type %s: \"%s\"",
452 : "integer", s)));
453 : }
454 :
455 : /*
456 : * Convert input string to a signed 64 bit integer.
457 : *
458 : * Allows any number of leading or trailing whitespace characters.
459 : *
460 : * pg_strtoint64() will throw ereport() upon bad input format or overflow;
461 : * while pg_strtoint64_safe() instead returns such complaints in *escontext,
462 : * if it's an ErrorSaveContext.
463 : *
464 : * NB: Accumulate input as an unsigned number, to deal with two's complement
465 : * representation of the most negative number, which can't be represented as a
466 : * signed positive number.
467 : */
468 : int64
469 0 : pg_strtoint64(const char *s)
470 : {
471 0 : return pg_strtoint64_safe(s, NULL);
472 : }
473 :
474 : int64
475 138486 : pg_strtoint64_safe(const char *s, Node *escontext)
476 : {
477 138486 : const char *ptr = s;
478 : const char *firstdigit;
479 138486 : uint64 tmp = 0;
480 138486 : bool neg = false;
481 :
482 : /* skip leading spaces */
483 138560 : while (*ptr && isspace((unsigned char) *ptr))
484 74 : ptr++;
485 :
486 : /* handle sign */
487 138486 : if (*ptr == '-')
488 : {
489 1442 : ptr++;
490 1442 : neg = true;
491 : }
492 137044 : else if (*ptr == '+')
493 42 : ptr++;
494 :
495 : /* process digits */
496 138486 : if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
497 : {
498 84 : firstdigit = ptr += 2;
499 :
500 1068 : while (*ptr)
501 : {
502 984 : if (isxdigit((unsigned char) *ptr))
503 : {
504 978 : if (unlikely(tmp > -(PG_INT64_MIN / 16)))
505 0 : goto out_of_range;
506 :
507 978 : tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
508 : }
509 6 : else if (*ptr == '_')
510 : {
511 : /* underscore must be followed by more digits */
512 6 : ptr++;
513 6 : if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
514 0 : goto invalid_syntax;
515 : }
516 : else
517 0 : break;
518 : }
519 : }
520 138402 : else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
521 : {
522 84 : firstdigit = ptr += 2;
523 :
524 1368 : while (*ptr)
525 : {
526 1284 : if (*ptr >= '0' && *ptr <= '7')
527 : {
528 1278 : if (unlikely(tmp > -(PG_INT64_MIN / 8)))
529 0 : goto out_of_range;
530 :
531 1278 : tmp = tmp * 8 + (*ptr++ - '0');
532 : }
533 6 : else if (*ptr == '_')
534 : {
535 : /* underscore must be followed by more digits */
536 6 : ptr++;
537 6 : if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
538 0 : goto invalid_syntax;
539 : }
540 : else
541 0 : break;
542 : }
543 : }
544 138318 : else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
545 : {
546 84 : firstdigit = ptr += 2;
547 :
548 3804 : while (*ptr)
549 : {
550 3720 : if (*ptr >= '0' && *ptr <= '1')
551 : {
552 3708 : if (unlikely(tmp > -(PG_INT64_MIN / 2)))
553 0 : goto out_of_range;
554 :
555 3708 : tmp = tmp * 2 + (*ptr++ - '0');
556 : }
557 12 : else if (*ptr == '_')
558 : {
559 : /* underscore must be followed by more digits */
560 12 : ptr++;
561 12 : if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
562 0 : goto invalid_syntax;
563 : }
564 : else
565 0 : break;
566 : }
567 : }
568 : else
569 : {
570 138234 : firstdigit = ptr;
571 :
572 512162 : while (*ptr)
573 : {
574 383640 : if (isdigit((unsigned char) *ptr))
575 : {
576 374034 : if (unlikely(tmp > -(PG_INT64_MIN / 10)))
577 228 : goto out_of_range;
578 :
579 373806 : tmp = tmp * 10 + (*ptr++ - '0');
580 : }
581 9606 : else if (*ptr == '_')
582 : {
583 : /* underscore may not be first */
584 140 : if (unlikely(ptr == firstdigit))
585 6 : goto invalid_syntax;
586 : /* and it must be followed by more digits */
587 134 : ptr++;
588 134 : if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
589 12 : goto invalid_syntax;
590 : }
591 : else
592 9466 : break;
593 : }
594 : }
595 :
596 : /* require at least one digit */
597 138240 : if (unlikely(ptr == firstdigit))
598 94 : goto invalid_syntax;
599 :
600 : /* allow trailing whitespace, but not other trailing chars */
601 138212 : while (*ptr != '\0' && isspace((unsigned char) *ptr))
602 66 : ptr++;
603 :
604 138146 : if (unlikely(*ptr != '\0'))
605 9390 : goto invalid_syntax;
606 :
607 128756 : if (neg)
608 : {
609 : /* check the negative equivalent will fit without overflowing */
610 994 : if (tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1)
611 54 : goto out_of_range;
612 940 : return -((int64) tmp);
613 : }
614 :
615 127762 : if (tmp > PG_INT64_MAX)
616 54 : goto out_of_range;
617 :
618 127708 : return (int64) tmp;
619 :
620 336 : out_of_range:
621 336 : ereturn(escontext, 0,
622 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
623 : errmsg("value \"%s\" is out of range for type %s",
624 : s, "bigint")));
625 :
626 9502 : invalid_syntax:
627 9502 : ereturn(escontext, 0,
628 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
629 : errmsg("invalid input syntax for type %s: \"%s\"",
630 : "bigint", s)));
631 : }
632 :
633 : /*
634 : * Convert input string to an unsigned 32 bit integer.
635 : *
636 : * Allows any number of leading or trailing whitespace characters.
637 : *
638 : * If endloc isn't NULL, store a pointer to the rest of the string there,
639 : * so that caller can parse the rest. Otherwise, it's an error if anything
640 : * but whitespace follows.
641 : *
642 : * typname is what is reported in error messges.
643 : *
644 : * If escontext points to an ErrorSaveContext node, that is filled instead
645 : * of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
646 : * to detect errors.
647 : */
648 : uint32
649 38097794 : uint32in_subr(const char *s, char **endloc,
650 : const char *typname, Node *escontext)
651 : {
652 : uint32 result;
653 : unsigned long cvt;
654 : char *endptr;
655 :
656 38097794 : errno = 0;
657 38097794 : cvt = strtoul(s, &endptr, 0);
658 :
659 : /*
660 : * strtoul() normally only sets ERANGE. On some systems it may also set
661 : * EINVAL, which simply means it couldn't parse the input string. Be sure
662 : * to report that the same way as the standard error indication (that
663 : * endptr == s).
664 : */
665 38097794 : if ((errno && errno != ERANGE) || endptr == s)
666 60 : ereturn(escontext, 0,
667 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
668 : errmsg("invalid input syntax for type %s: \"%s\"",
669 : typname, s)));
670 :
671 38097734 : if (errno == ERANGE)
672 12 : ereturn(escontext, 0,
673 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
674 : errmsg("value \"%s\" is out of range for type %s",
675 : s, typname)));
676 :
677 38097722 : if (endloc)
678 : {
679 : /* caller wants to deal with rest of string */
680 3666606 : *endloc = endptr;
681 : }
682 : else
683 : {
684 : /* allow only whitespace after number */
685 34431230 : while (*endptr && isspace((unsigned char) *endptr))
686 114 : endptr++;
687 34431116 : if (*endptr)
688 36 : ereturn(escontext, 0,
689 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
690 : errmsg("invalid input syntax for type %s: \"%s\"",
691 : typname, s)));
692 : }
693 :
694 38097686 : result = (uint32) cvt;
695 :
696 : /*
697 : * Cope with possibility that unsigned long is wider than uint32, in which
698 : * case strtoul will not raise an error for some values that are out of
699 : * the range of uint32.
700 : *
701 : * For backwards compatibility, we want to accept inputs that are given
702 : * with a minus sign, so allow the input value if it matches after either
703 : * signed or unsigned extension to long.
704 : *
705 : * To ensure consistent results on 32-bit and 64-bit platforms, make sure
706 : * the error message is the same as if strtoul() had returned ERANGE.
707 : */
708 : #if PG_UINT32_MAX != ULONG_MAX
709 38097686 : if (cvt != (unsigned long) result &&
710 42 : cvt != (unsigned long) ((int) result))
711 30 : ereturn(escontext, 0,
712 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
713 : errmsg("value \"%s\" is out of range for type %s",
714 : s, typname)));
715 : #endif
716 :
717 38097656 : return result;
718 : }
719 :
720 : /*
721 : * Convert input string to an unsigned 64 bit integer.
722 : *
723 : * Allows any number of leading or trailing whitespace characters.
724 : *
725 : * If endloc isn't NULL, store a pointer to the rest of the string there,
726 : * so that caller can parse the rest. Otherwise, it's an error if anything
727 : * but whitespace follows.
728 : *
729 : * typname is what is reported in error messges.
730 : *
731 : * If escontext points to an ErrorSaveContext node, that is filled instead
732 : * of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
733 : * to detect errors.
734 : */
735 : uint64
736 866 : uint64in_subr(const char *s, char **endloc,
737 : const char *typname, Node *escontext)
738 : {
739 : uint64 result;
740 : char *endptr;
741 :
742 866 : errno = 0;
743 866 : result = strtou64(s, &endptr, 0);
744 :
745 : /*
746 : * strtoul[l] normally only sets ERANGE. On some systems it may also set
747 : * EINVAL, which simply means it couldn't parse the input string. Be sure
748 : * to report that the same way as the standard error indication (that
749 : * endptr == s).
750 : */
751 866 : if ((errno && errno != ERANGE) || endptr == s)
752 18 : ereturn(escontext, 0,
753 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
754 : errmsg("invalid input syntax for type %s: \"%s\"",
755 : typname, s)));
756 :
757 848 : if (errno == ERANGE)
758 6 : ereturn(escontext, 0,
759 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
760 : errmsg("value \"%s\" is out of range for type %s",
761 : s, typname)));
762 :
763 842 : if (endloc)
764 : {
765 : /* caller wants to deal with rest of string */
766 0 : *endloc = endptr;
767 : }
768 : else
769 : {
770 : /* allow only whitespace after number */
771 842 : while (*endptr && isspace((unsigned char) *endptr))
772 0 : endptr++;
773 842 : if (*endptr)
774 0 : ereturn(escontext, 0,
775 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
776 : errmsg("invalid input syntax for type %s: \"%s\"",
777 : typname, s)));
778 : }
779 :
780 842 : return result;
781 : }
782 :
783 : /*
784 : * pg_itoa: converts a signed 16-bit integer to its string representation
785 : * and returns strlen(a).
786 : *
787 : * Caller must ensure that 'a' points to enough memory to hold the result
788 : * (at least 7 bytes, counting a leading sign and trailing NUL).
789 : *
790 : * It doesn't seem worth implementing this separately.
791 : */
792 : int
793 229906 : pg_itoa(int16 i, char *a)
794 : {
795 229906 : return pg_ltoa((int32) i, a);
796 : }
797 :
798 : /*
799 : * pg_ultoa_n: converts an unsigned 32-bit integer to its string representation,
800 : * not NUL-terminated, and returns the length of that string representation
801 : *
802 : * Caller must ensure that 'a' points to enough memory to hold the result (at
803 : * least 10 bytes)
804 : */
805 : int
806 17905712 : pg_ultoa_n(uint32 value, char *a)
807 : {
808 : int olength,
809 17905712 : i = 0;
810 :
811 : /* Degenerate case */
812 17905712 : if (value == 0)
813 : {
814 3911968 : *a = '0';
815 3911968 : return 1;
816 : }
817 :
818 13993744 : olength = decimalLength32(value);
819 :
820 : /* Compute the result string. */
821 16222736 : while (value >= 10000)
822 : {
823 2228992 : const uint32 c = value - 10000 * (value / 10000);
824 2228992 : const uint32 c0 = (c % 100) << 1;
825 2228992 : const uint32 c1 = (c / 100) << 1;
826 :
827 2228992 : char *pos = a + olength - i;
828 :
829 2228992 : value /= 10000;
830 :
831 2228992 : memcpy(pos - 2, DIGIT_TABLE + c0, 2);
832 2228992 : memcpy(pos - 4, DIGIT_TABLE + c1, 2);
833 2228992 : i += 4;
834 : }
835 13993744 : if (value >= 100)
836 : {
837 5948884 : const uint32 c = (value % 100) << 1;
838 :
839 5948884 : char *pos = a + olength - i;
840 :
841 5948884 : value /= 100;
842 :
843 5948884 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
844 5948884 : i += 2;
845 : }
846 13993744 : if (value >= 10)
847 : {
848 6860892 : const uint32 c = value << 1;
849 :
850 6860892 : char *pos = a + olength - i;
851 :
852 6860892 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
853 : }
854 : else
855 : {
856 7132852 : *a = (char) ('0' + value);
857 : }
858 :
859 13993744 : return olength;
860 : }
861 :
862 : /*
863 : * pg_ltoa: converts a signed 32-bit integer to its string representation and
864 : * returns strlen(a).
865 : *
866 : * It is the caller's responsibility to ensure that a is at least 12 bytes long,
867 : * which is enough room to hold a minus sign, a maximally long int32, and the
868 : * above terminating NUL.
869 : */
870 : int
871 17778686 : pg_ltoa(int32 value, char *a)
872 : {
873 17778686 : uint32 uvalue = (uint32) value;
874 17778686 : int len = 0;
875 :
876 17778686 : if (value < 0)
877 : {
878 91068 : uvalue = (uint32) 0 - uvalue;
879 91068 : a[len++] = '-';
880 : }
881 17778686 : len += pg_ultoa_n(uvalue, a + len);
882 17778686 : a[len] = '\0';
883 17778686 : return len;
884 : }
885 :
886 : /*
887 : * Get the decimal representation, not NUL-terminated, and return the length of
888 : * same. Caller must ensure that a points to at least MAXINT8LEN bytes.
889 : */
890 : int
891 587590 : pg_ulltoa_n(uint64 value, char *a)
892 : {
893 : int olength,
894 587590 : i = 0;
895 : uint32 value2;
896 :
897 : /* Degenerate case */
898 587590 : if (value == 0)
899 : {
900 44448 : *a = '0';
901 44448 : return 1;
902 : }
903 :
904 543142 : olength = decimalLength64(value);
905 :
906 : /* Compute the result string. */
907 559174 : while (value >= 100000000)
908 : {
909 16032 : const uint64 q = value / 100000000;
910 16032 : uint32 value3 = (uint32) (value - 100000000 * q);
911 :
912 16032 : const uint32 c = value3 % 10000;
913 16032 : const uint32 d = value3 / 10000;
914 16032 : const uint32 c0 = (c % 100) << 1;
915 16032 : const uint32 c1 = (c / 100) << 1;
916 16032 : const uint32 d0 = (d % 100) << 1;
917 16032 : const uint32 d1 = (d / 100) << 1;
918 :
919 16032 : char *pos = a + olength - i;
920 :
921 16032 : value = q;
922 :
923 16032 : memcpy(pos - 2, DIGIT_TABLE + c0, 2);
924 16032 : memcpy(pos - 4, DIGIT_TABLE + c1, 2);
925 16032 : memcpy(pos - 6, DIGIT_TABLE + d0, 2);
926 16032 : memcpy(pos - 8, DIGIT_TABLE + d1, 2);
927 16032 : i += 8;
928 : }
929 :
930 : /* Switch to 32-bit for speed */
931 543142 : value2 = (uint32) value;
932 :
933 543142 : if (value2 >= 10000)
934 : {
935 26292 : const uint32 c = value2 - 10000 * (value2 / 10000);
936 26292 : const uint32 c0 = (c % 100) << 1;
937 26292 : const uint32 c1 = (c / 100) << 1;
938 :
939 26292 : char *pos = a + olength - i;
940 :
941 26292 : value2 /= 10000;
942 :
943 26292 : memcpy(pos - 2, DIGIT_TABLE + c0, 2);
944 26292 : memcpy(pos - 4, DIGIT_TABLE + c1, 2);
945 26292 : i += 4;
946 : }
947 543142 : if (value2 >= 100)
948 : {
949 215358 : const uint32 c = (value2 % 100) << 1;
950 215358 : char *pos = a + olength - i;
951 :
952 215358 : value2 /= 100;
953 :
954 215358 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
955 215358 : i += 2;
956 : }
957 543142 : if (value2 >= 10)
958 : {
959 124096 : const uint32 c = value2 << 1;
960 124096 : char *pos = a + olength - i;
961 :
962 124096 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
963 : }
964 : else
965 419046 : *a = (char) ('0' + value2);
966 :
967 543142 : return olength;
968 : }
969 :
970 : /*
971 : * pg_lltoa: converts a signed 64-bit integer to its string representation and
972 : * returns strlen(a).
973 : *
974 : * Caller must ensure that 'a' points to enough memory to hold the result
975 : * (at least MAXINT8LEN + 1 bytes, counting a leading sign and trailing NUL).
976 : */
977 : int
978 301862 : pg_lltoa(int64 value, char *a)
979 : {
980 301862 : uint64 uvalue = value;
981 301862 : int len = 0;
982 :
983 301862 : if (value < 0)
984 : {
985 2362 : uvalue = (uint64) 0 - uvalue;
986 2362 : a[len++] = '-';
987 : }
988 :
989 301862 : len += pg_ulltoa_n(uvalue, a + len);
990 301862 : a[len] = '\0';
991 301862 : return len;
992 : }
993 :
994 :
995 : /*
996 : * pg_ultostr_zeropad
997 : * Converts 'value' into a decimal string representation stored at 'str'.
998 : * 'minwidth' specifies the minimum width of the result; any extra space
999 : * is filled up by prefixing the number with zeros.
1000 : *
1001 : * Returns the ending address of the string result (the last character written
1002 : * plus 1). Note that no NUL terminator is written.
1003 : *
1004 : * The intended use-case for this function is to build strings that contain
1005 : * multiple individual numbers, for example:
1006 : *
1007 : * str = pg_ultostr_zeropad(str, hours, 2);
1008 : * *str++ = ':';
1009 : * str = pg_ultostr_zeropad(str, mins, 2);
1010 : * *str++ = ':';
1011 : * str = pg_ultostr_zeropad(str, secs, 2);
1012 : * *str = '\0';
1013 : *
1014 : * Note: Caller must ensure that 'str' points to enough memory to hold the
1015 : * result.
1016 : */
1017 : char *
1018 785076 : pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth)
1019 : {
1020 : int len;
1021 :
1022 : Assert(minwidth > 0);
1023 :
1024 785076 : if (value < 100 && minwidth == 2) /* Short cut for common case */
1025 : {
1026 661382 : memcpy(str, DIGIT_TABLE + value * 2, 2);
1027 661382 : return str + 2;
1028 : }
1029 :
1030 123694 : len = pg_ultoa_n(value, str);
1031 123694 : if (len >= minwidth)
1032 123016 : return str + len;
1033 :
1034 678 : memmove(str + minwidth - len, str, len);
1035 678 : memset(str, '0', minwidth - len);
1036 678 : return str + minwidth;
1037 : }
1038 :
1039 : /*
1040 : * pg_ultostr
1041 : * Converts 'value' into a decimal string representation stored at 'str'.
1042 : *
1043 : * Returns the ending address of the string result (the last character written
1044 : * plus 1). Note that no NUL terminator is written.
1045 : *
1046 : * The intended use-case for this function is to build strings that contain
1047 : * multiple individual numbers, for example:
1048 : *
1049 : * str = pg_ultostr(str, a);
1050 : * *str++ = ' ';
1051 : * str = pg_ultostr(str, b);
1052 : * *str = '\0';
1053 : *
1054 : * Note: Caller must ensure that 'str' points to enough memory to hold the
1055 : * result.
1056 : */
1057 : char *
1058 3276 : pg_ultostr(char *str, uint32 value)
1059 : {
1060 3276 : int len = pg_ultoa_n(value, str);
1061 :
1062 3276 : return str + len;
1063 : }
|