Age Owner TLA 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
1163 rhodiumtoad 45 CBC 7125011 : 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 7125011 : t = (pg_leftmost_one_pos32(v) + 1) * 1233 / 4096;
60 7125011 : return t + (v >= PowersOfTen[t]);
61 : }
62 :
63 : static inline int
64 269388 : 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 269388 : t = (pg_leftmost_one_pos64(v) + 1) * 1233 / 4096;
85 269388 : 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
1722 andres 113 UIC 0 : pg_strtoint16(const char *s)
114 : {
121 tgl 115 UNC 0 : return pg_strtoint16_safe(s, NULL);
116 : }
117 :
118 : int16
121 tgl 119 GNC 2839236 : pg_strtoint16_safe(const char *s, Node *escontext)
120 : {
1722 andres 121 GIC 2839236 : const char *ptr = s;
122 : const char *firstdigit;
126 drowley 123 GNC 2839236 : uint16 tmp = 0;
1722 andres 124 GIC 2839236 : bool neg = false;
125 :
126 : /* skip leading spaces */
127 2839266 : while (likely(*ptr) && isspace((unsigned char) *ptr))
128 30 : ptr++;
129 :
130 : /* handle sign */
131 2839236 : if (*ptr == '-')
132 : {
133 92468 : ptr++;
1722 andres 134 GBC 92468 : neg = true;
135 : }
136 2746768 : else if (*ptr == '+')
1722 andres 137 UIC 0 : ptr++;
138 :
139 : /* process digits */
116 peter 140 GNC 2839236 : if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
1722 andres 141 ECB : {
116 peter 142 GNC 21 : firstdigit = ptr += 2;
143 :
64 dean.a.rasheed 144 90 : while (*ptr)
145 : {
146 69 : if (isxdigit((unsigned char) *ptr))
147 : {
148 66 : if (unlikely(tmp > -(PG_INT16_MIN / 16)))
64 dean.a.rasheed 149 UNC 0 : goto out_of_range;
150 :
64 dean.a.rasheed 151 GNC 66 : tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
152 : }
153 3 : else if (*ptr == '_')
154 : {
155 : /* underscore must be followed by more digits */
156 3 : ptr++;
157 3 : if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
64 dean.a.rasheed 158 UNC 0 : goto invalid_syntax;
159 : }
160 : else
161 0 : break;
162 : }
163 : }
116 peter 164 GNC 2839215 : else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
165 : {
166 21 : firstdigit = ptr += 2;
167 :
64 dean.a.rasheed 168 111 : while (*ptr)
169 : {
170 90 : if (*ptr >= '0' && *ptr <= '7')
171 : {
172 87 : if (unlikely(tmp > -(PG_INT16_MIN / 8)))
64 dean.a.rasheed 173 UNC 0 : goto out_of_range;
174 :
64 dean.a.rasheed 175 GNC 87 : tmp = tmp * 8 + (*ptr++ - '0');
176 : }
177 3 : else if (*ptr == '_')
178 : {
179 : /* underscore must be followed by more digits */
180 3 : ptr++;
181 3 : if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
64 dean.a.rasheed 182 UNC 0 : goto invalid_syntax;
183 : }
184 : else
185 0 : break;
186 : }
187 : }
116 peter 188 GNC 2839194 : else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
189 : {
190 21 : firstdigit = ptr += 2;
191 :
64 dean.a.rasheed 192 252 : while (*ptr)
193 : {
194 231 : if (*ptr >= '0' && *ptr <= '1')
195 : {
196 225 : if (unlikely(tmp > -(PG_INT16_MIN / 2)))
64 dean.a.rasheed 197 UNC 0 : goto out_of_range;
198 :
64 dean.a.rasheed 199 GNC 225 : tmp = tmp * 2 + (*ptr++ - '0');
200 : }
201 6 : else if (*ptr == '_')
202 : {
203 : /* underscore must be followed by more digits */
204 6 : ptr++;
205 6 : if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
64 dean.a.rasheed 206 UNC 0 : goto invalid_syntax;
207 : }
208 : else
209 0 : break;
210 : }
211 : }
212 : else
213 : {
116 peter 214 GNC 2839173 : firstdigit = ptr;
215 :
64 dean.a.rasheed 216 5755048 : while (*ptr)
217 : {
218 2915921 : if (isdigit((unsigned char) *ptr))
219 : {
220 2915875 : if (unlikely(tmp > -(PG_INT16_MIN / 10)))
221 9 : goto out_of_range;
222 :
223 2915866 : tmp = tmp * 10 + (*ptr++ - '0');
224 : }
225 46 : else if (*ptr == '_')
226 : {
227 : /* underscore may not be first */
228 18 : if (unlikely(ptr == firstdigit))
229 3 : goto invalid_syntax;
230 : /* and it must be followed by more digits */
231 15 : ptr++;
232 15 : if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
233 6 : goto invalid_syntax;
234 : }
235 : else
236 28 : break;
237 : }
238 : }
239 :
240 : /* require at least one digit */
116 peter 241 2839218 : if (unlikely(ptr == firstdigit))
242 27 : goto invalid_syntax;
1722 andres 243 ECB :
244 : /* allow trailing whitespace, but not other trailing chars */
1722 andres 245 CBC 2839209 : while (*ptr != '\0' && isspace((unsigned char) *ptr))
246 18 : ptr++;
247 :
248 2839191 : if (unlikely(*ptr != '\0'))
1722 andres 249 GBC 10 : goto invalid_syntax;
250 :
126 drowley 251 GNC 2839181 : if (neg)
1722 andres 252 ECB : {
253 : /* check the negative equivalent will fit without overflowing */
126 drowley 254 GNC 92465 : if (tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1)
1722 andres 255 GIC 9 : goto out_of_range;
126 drowley 256 GNC 92456 : return -((int16) tmp);
257 : }
1722 andres 258 ECB :
126 drowley 259 GNC 2746716 : if (tmp > PG_INT16_MAX)
260 9 : goto out_of_range;
261 :
262 2746707 : return (int16) tmp;
1722 andres 263 ECB :
1722 andres 264 GBC 27 : out_of_range:
121 tgl 265 GNC 27 : ereturn(escontext, 0,
1722 andres 266 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
267 : errmsg("value \"%s\" is out of range for type %s",
268 : s, "smallint")));
269 :
1722 andres 270 GIC 46 : invalid_syntax:
121 tgl 271 GNC 46 : ereturn(escontext, 0,
1722 andres 272 ECB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1722 andres 273 EUB : errmsg("invalid input syntax for type %s: \"%s\"",
274 : "smallint", s)));
275 : }
276 :
1722 andres 277 ECB : /*
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.
1722 andres 289 EUB : */
290 : int32
1722 andres 291 CBC 5811 : pg_strtoint32(const char *s)
292 : {
121 tgl 293 GNC 5811 : return pg_strtoint32_safe(s, NULL);
294 : }
295 :
296 : int32
297 3790902 : pg_strtoint32_safe(const char *s, Node *escontext)
298 : {
1722 andres 299 CBC 3790902 : const char *ptr = s;
300 : const char *firstdigit;
126 drowley 301 GNC 3790902 : uint32 tmp = 0;
1722 andres 302 GIC 3790902 : bool neg = false;
1722 andres 303 ECB :
304 : /* skip leading spaces */
1722 andres 305 GBC 3790971 : while (likely(*ptr) && isspace((unsigned char) *ptr))
1722 andres 306 GIC 69 : ptr++;
307 :
1722 andres 308 EUB : /* handle sign */
1722 andres 309 GIC 3790902 : if (*ptr == '-')
310 : {
1722 andres 311 CBC 162292 : ptr++;
1722 andres 312 GIC 162292 : neg = true;
1722 andres 313 ECB : }
1722 andres 314 GIC 3628610 : else if (*ptr == '+')
1722 andres 315 LBC 0 : ptr++;
316 :
317 : /* process digits */
116 peter 318 GNC 3790902 : if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
319 : {
320 1566 : firstdigit = ptr += 2;
321 :
64 dean.a.rasheed 322 7986 : while (*ptr)
323 : {
324 6432 : if (isxdigit((unsigned char) *ptr))
325 : {
326 6426 : if (unlikely(tmp > -(PG_INT32_MIN / 16)))
327 12 : goto out_of_range;
328 :
329 6414 : tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
330 : }
331 6 : else if (*ptr == '_')
332 : {
333 : /* underscore must be followed by more digits */
334 6 : ptr++;
335 6 : if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
64 dean.a.rasheed 336 UNC 0 : goto invalid_syntax;
337 : }
338 : else
339 0 : break;
340 : }
1722 andres 341 EUB : }
116 peter 342 GNC 3789336 : else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
343 : {
344 51 : firstdigit = ptr += 2;
345 :
64 dean.a.rasheed 346 486 : while (*ptr)
347 : {
348 447 : if (*ptr >= '0' && *ptr <= '7')
349 : {
350 441 : if (unlikely(tmp > -(PG_INT32_MIN / 8)))
351 12 : goto out_of_range;
352 :
353 429 : tmp = tmp * 8 + (*ptr++ - '0');
354 : }
355 6 : else if (*ptr == '_')
356 : {
357 : /* underscore must be followed by more digits */
358 6 : ptr++;
359 6 : if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
64 dean.a.rasheed 360 UNC 0 : goto invalid_syntax;
361 : }
362 : else
363 0 : break;
364 : }
365 : }
116 peter 366 GNC 3789285 : else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
367 : {
368 52 : firstdigit = ptr += 2;
369 :
64 dean.a.rasheed 370 1311 : while (*ptr)
371 : {
372 1272 : if (*ptr >= '0' && *ptr <= '1')
373 : {
374 1260 : if (unlikely(tmp > -(PG_INT32_MIN / 2)))
375 13 : goto out_of_range;
376 :
377 1247 : tmp = tmp * 2 + (*ptr++ - '0');
378 : }
379 12 : else if (*ptr == '_')
380 : {
381 : /* underscore must be followed by more digits */
382 12 : ptr++;
383 12 : if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
64 dean.a.rasheed 384 UNC 0 : goto invalid_syntax;
385 : }
386 : else
387 0 : break;
388 : }
389 : }
390 : else
391 : {
116 peter 392 GNC 3789233 : firstdigit = ptr;
393 :
64 dean.a.rasheed 394 12517752 : while (*ptr)
395 : {
396 8729164 : if (isdigit((unsigned char) *ptr))
397 : {
398 8728999 : if (unlikely(tmp > -(PG_INT32_MIN / 10)))
399 549 : goto out_of_range;
400 :
401 8728450 : tmp = tmp * 10 + (*ptr++ - '0');
402 : }
403 165 : else if (*ptr == '_')
404 : {
405 : /* underscore may not be first */
406 78 : if (unlikely(ptr == firstdigit))
407 3 : goto invalid_syntax;
408 : /* and it must be followed by more digits */
409 75 : ptr++;
410 75 : if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
411 6 : goto invalid_syntax;
412 : }
413 : else
414 87 : break;
415 : }
416 : }
417 :
418 : /* require at least one digit */
116 peter 419 3790307 : if (unlikely(ptr == firstdigit))
420 90 : goto invalid_syntax;
421 :
422 : /* allow trailing whitespace, but not other trailing chars */
1722 andres 423 GBC 3790259 : while (*ptr != '\0' && isspace((unsigned char) *ptr))
1722 andres 424 GIC 42 : ptr++;
425 :
426 3790217 : if (unlikely(*ptr != '\0'))
427 9 : goto invalid_syntax;
1722 andres 428 ECB :
126 drowley 429 GNC 3790208 : if (neg)
1722 andres 430 ECB : {
431 : /* check the negative equivalent will fit without overflowing */
126 drowley 432 GNC 162289 : if (tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1)
1722 andres 433 GIC 9 : goto out_of_range;
126 drowley 434 GNC 162280 : return -((int32) tmp);
1722 andres 435 ECB : }
436 :
126 drowley 437 GNC 3627919 : if (tmp > PG_INT32_MAX)
438 107 : goto out_of_range;
439 :
440 3627812 : return (int32) tmp;
441 :
1722 andres 442 CBC 702 : out_of_range:
121 tgl 443 GNC 702 : ereturn(escontext, 0,
444 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1722 andres 445 ECB : errmsg("value \"%s\" is out of range for type %s",
446 : s, "integer")));
447 :
1722 andres 448 CBC 108 : invalid_syntax:
121 tgl 449 GNC 108 : ereturn(escontext, 0,
1722 andres 450 ECB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
451 : errmsg("invalid input syntax for type %s: \"%s\"",
452 : "integer", s)));
453 : }
454 :
455 : /*
419 peter 456 : * Convert input string to a signed 64 bit integer.
457 : *
458 : * Allows any number of leading or trailing whitespace characters.
121 tgl 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.
419 peter 467 : */
468 : int64
419 peter 469 LBC 0 : pg_strtoint64(const char *s)
470 : {
121 tgl 471 UNC 0 : return pg_strtoint64_safe(s, NULL);
472 : }
121 tgl 473 ECB :
474 : int64
121 tgl 475 GNC 69193 : pg_strtoint64_safe(const char *s, Node *escontext)
476 : {
419 peter 477 69193 : const char *ptr = s;
478 : const char *firstdigit;
126 drowley 479 69193 : uint64 tmp = 0;
419 peter 480 69193 : bool neg = false;
419 peter 481 ECB :
482 : /* skip leading spaces */
419 peter 483 GIC 69230 : while (*ptr && isspace((unsigned char) *ptr))
484 37 : ptr++;
485 :
486 : /* handle sign */
419 peter 487 CBC 69193 : if (*ptr == '-')
419 peter 488 ECB : {
419 peter 489 GIC 721 : ptr++;
490 721 : neg = true;
491 : }
492 68472 : else if (*ptr == '+')
493 21 : ptr++;
494 :
495 : /* process digits */
116 peter 496 GNC 69193 : if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
497 : {
498 42 : firstdigit = ptr += 2;
499 :
64 dean.a.rasheed 500 534 : while (*ptr)
501 : {
502 492 : if (isxdigit((unsigned char) *ptr))
503 : {
504 489 : if (unlikely(tmp > -(PG_INT64_MIN / 16)))
64 dean.a.rasheed 505 UNC 0 : goto out_of_range;
506 :
64 dean.a.rasheed 507 GNC 489 : tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
508 : }
509 3 : else if (*ptr == '_')
510 : {
511 : /* underscore must be followed by more digits */
512 3 : ptr++;
513 3 : if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
64 dean.a.rasheed 514 UNC 0 : goto invalid_syntax;
515 : }
516 : else
517 0 : break;
518 : }
519 : }
116 peter 520 GNC 69151 : else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
521 : {
522 42 : firstdigit = ptr += 2;
523 :
64 dean.a.rasheed 524 684 : while (*ptr)
525 : {
526 642 : if (*ptr >= '0' && *ptr <= '7')
527 : {
528 639 : if (unlikely(tmp > -(PG_INT64_MIN / 8)))
64 dean.a.rasheed 529 UNC 0 : goto out_of_range;
530 :
64 dean.a.rasheed 531 GNC 639 : tmp = tmp * 8 + (*ptr++ - '0');
532 : }
533 3 : else if (*ptr == '_')
534 : {
535 : /* underscore must be followed by more digits */
536 3 : ptr++;
537 3 : if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
64 dean.a.rasheed 538 UNC 0 : goto invalid_syntax;
539 : }
540 : else
541 0 : break;
542 : }
543 : }
116 peter 544 GNC 69109 : else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
545 : {
546 42 : firstdigit = ptr += 2;
547 :
64 dean.a.rasheed 548 1902 : while (*ptr)
549 : {
550 1860 : if (*ptr >= '0' && *ptr <= '1')
551 : {
552 1854 : if (unlikely(tmp > -(PG_INT64_MIN / 2)))
64 dean.a.rasheed 553 UNC 0 : goto out_of_range;
554 :
64 dean.a.rasheed 555 GNC 1854 : tmp = tmp * 2 + (*ptr++ - '0');
556 : }
557 6 : else if (*ptr == '_')
558 : {
559 : /* underscore must be followed by more digits */
560 6 : ptr++;
561 6 : if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
64 dean.a.rasheed 562 UNC 0 : goto invalid_syntax;
563 : }
564 : else
565 0 : break;
566 : }
567 : }
568 : else
569 : {
116 peter 570 GNC 69067 : firstdigit = ptr;
571 :
64 dean.a.rasheed 572 255870 : while (*ptr)
573 : {
574 191641 : if (isdigit((unsigned char) *ptr))
575 : {
576 186856 : if (unlikely(tmp > -(PG_INT64_MIN / 10)))
577 114 : goto out_of_range;
578 :
579 186742 : tmp = tmp * 10 + (*ptr++ - '0');
580 : }
581 4785 : else if (*ptr == '_')
582 : {
583 : /* underscore may not be first */
584 70 : if (unlikely(ptr == firstdigit))
585 3 : goto invalid_syntax;
586 : /* and it must be followed by more digits */
587 67 : ptr++;
588 67 : if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
589 6 : goto invalid_syntax;
590 : }
591 : else
592 4715 : break;
593 : }
594 : }
595 :
596 : /* require at least one digit */
116 peter 597 69070 : if (unlikely(ptr == firstdigit))
598 47 : goto invalid_syntax;
419 peter 599 ECB :
600 : /* allow trailing whitespace, but not other trailing chars */
419 peter 601 CBC 69056 : while (*ptr != '\0' && isspace((unsigned char) *ptr))
419 peter 602 GIC 33 : ptr++;
603 :
604 69023 : if (unlikely(*ptr != '\0'))
419 peter 605 CBC 4677 : goto invalid_syntax;
606 :
126 drowley 607 GNC 64346 : if (neg)
608 : {
609 : /* check the negative equivalent will fit without overflowing */
610 497 : if (tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1)
419 peter 611 GIC 27 : goto out_of_range;
126 drowley 612 GNC 470 : return -((int64) tmp);
419 peter 613 ECB : }
614 :
126 drowley 615 GNC 63849 : if (tmp > PG_INT64_MAX)
616 27 : goto out_of_range;
617 :
618 63822 : return (int64) tmp;
619 :
419 peter 620 CBC 168 : out_of_range:
121 tgl 621 GNC 168 : ereturn(escontext, 0,
419 peter 622 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
623 : errmsg("value \"%s\" is out of range for type %s",
624 : s, "bigint")));
625 :
419 peter 626 GBC 4733 : invalid_syntax:
121 tgl 627 GNC 4733 : ereturn(escontext, 0,
628 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
419 peter 629 ECB : 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
103 tgl 649 GNC 19202698 : 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 19202698 : errno = 0;
657 19202698 : 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 19202698 : if ((errno && errno != ERANGE) || endptr == s)
666 30 : ereturn(escontext, 0,
667 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
668 : errmsg("invalid input syntax for type %s: \"%s\"",
669 : typname, s)));
670 :
671 19202668 : if (errno == ERANGE)
672 6 : 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 19202662 : if (endloc)
678 : {
679 : /* caller wants to deal with rest of string */
680 1846623 : *endloc = endptr;
681 : }
682 : else
683 : {
684 : /* allow only whitespace after number */
685 17356096 : while (*endptr && isspace((unsigned char) *endptr))
686 57 : endptr++;
687 17356039 : if (*endptr)
688 18 : ereturn(escontext, 0,
689 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
690 : errmsg("invalid input syntax for type %s: \"%s\"",
691 : typname, s)));
692 : }
693 :
694 19202644 : 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 19202644 : if (cvt != (unsigned long) result &&
710 21 : cvt != (unsigned long) ((int) result))
711 15 : 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 19202629 : 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 433 : uint64in_subr(const char *s, char **endloc,
737 : const char *typname, Node *escontext)
738 : {
739 : uint64 result;
740 : char *endptr;
741 :
742 433 : errno = 0;
743 433 : 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 433 : if ((errno && errno != ERANGE) || endptr == s)
752 9 : ereturn(escontext, 0,
753 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
754 : errmsg("invalid input syntax for type %s: \"%s\"",
755 : typname, s)));
756 :
757 424 : if (errno == ERANGE)
758 3 : 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 421 : if (endloc)
764 : {
765 : /* caller wants to deal with rest of string */
103 tgl 766 UNC 0 : *endloc = endptr;
767 : }
768 : else
769 : {
770 : /* allow only whitespace after number */
103 tgl 771 GNC 421 : while (*endptr && isspace((unsigned char) *endptr))
103 tgl 772 UNC 0 : endptr++;
103 tgl 773 GNC 421 : if (*endptr)
103 tgl 774 UNC 0 : ereturn(escontext, 0,
775 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
776 : errmsg("invalid input syntax for type %s: \"%s\"",
777 : typname, s)));
778 : }
779 :
103 tgl 780 GNC 421 : return result;
103 tgl 781 ECB : }
782 :
9770 scrappy 783 : /*
784 : * pg_itoa: converts a signed 16-bit integer to its string representation
1030 drowley 785 : * and returns strlen(a).
4524 rhaas 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
8286 tgl 793 CBC 116946 : pg_itoa(int16 i, char *a)
9770 scrappy 794 ECB : {
1030 drowley 795 GBC 116946 : return pg_ltoa((int32) i, a);
796 : }
797 :
4524 rhaas 798 EUB : /*
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
4524 rhaas 801 ECB : *
802 : * Caller must ensure that 'a' points to enough memory to hold the result (at
1163 rhodiumtoad 803 : * least 10 bytes)
804 : */
805 : int
1163 rhodiumtoad 806 GIC 9102061 : pg_ultoa_n(uint32 value, char *a)
4524 rhaas 807 ECB : {
808 : int olength,
1163 rhodiumtoad 809 CBC 9102061 : i = 0;
4524 rhaas 810 ECB :
811 : /* Degenerate case */
1163 rhodiumtoad 812 CBC 9102061 : if (value == 0)
813 : {
814 1977050 : *a = '0';
1163 rhodiumtoad 815 GIC 1977050 : return 1;
816 : }
4524 rhaas 817 ECB :
1163 rhodiumtoad 818 CBC 7125011 : olength = decimalLength32(value);
1163 rhodiumtoad 819 EUB :
820 : /* Compute the result string. */
1163 rhodiumtoad 821 GIC 8329457 : while (value >= 10000)
4524 rhaas 822 EUB : {
1163 rhodiumtoad 823 GIC 1204446 : const uint32 c = value - 10000 * (value / 10000);
824 1204446 : const uint32 c0 = (c % 100) << 1;
1163 rhodiumtoad 825 CBC 1204446 : const uint32 c1 = (c / 100) << 1;
826 :
827 1204446 : char *pos = a + olength - i;
828 :
829 1204446 : value /= 10000;
830 :
831 1204446 : memcpy(pos - 2, DIGIT_TABLE + c0, 2);
1163 rhodiumtoad 832 GIC 1204446 : memcpy(pos - 4, DIGIT_TABLE + c1, 2);
1163 rhodiumtoad 833 CBC 1204446 : i += 4;
1163 rhodiumtoad 834 ECB : }
1163 rhodiumtoad 835 GIC 7125011 : if (value >= 100)
1163 rhodiumtoad 836 ECB : {
1163 rhodiumtoad 837 GIC 3011180 : const uint32 c = (value % 100) << 1;
1163 rhodiumtoad 838 ECB :
1163 rhodiumtoad 839 GIC 3011180 : char *pos = a + olength - i;
840 :
1163 rhodiumtoad 841 CBC 3011180 : value /= 100;
4524 rhaas 842 ECB :
1163 rhodiumtoad 843 GBC 3011180 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
1163 rhodiumtoad 844 GIC 3011180 : i += 2;
845 : }
1163 rhodiumtoad 846 GBC 7125011 : if (value >= 10)
847 : {
1163 rhodiumtoad 848 GIC 3467438 : const uint32 c = value << 1;
849 :
850 3467438 : char *pos = a + olength - i;
4523 tgl 851 ECB :
1163 rhodiumtoad 852 GIC 3467438 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
1163 rhodiumtoad 853 ECB : }
854 : else
855 : {
1163 rhodiumtoad 856 GIC 3657573 : *a = (char) ('0' + value);
4524 rhaas 857 ECB : }
1163 rhodiumtoad 858 :
1163 rhodiumtoad 859 GIC 7125011 : return olength;
9770 scrappy 860 ECB : }
861 :
862 : /*
863 : * pg_ltoa: converts a signed 32-bit integer to its string representation and
864 : * returns strlen(a).
865 : *
1163 rhodiumtoad 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.
9770 scrappy 869 : */
1030 drowley 870 : int
1163 rhodiumtoad 871 GIC 9035743 : pg_ltoa(int32 value, char *a)
872 : {
1163 rhodiumtoad 873 CBC 9035743 : uint32 uvalue = (uint32) value;
1030 drowley 874 GIC 9035743 : int len = 0;
875 :
1163 rhodiumtoad 876 9035743 : if (value < 0)
877 : {
1163 rhodiumtoad 878 CBC 45769 : uvalue = (uint32) 0 - uvalue;
1030 drowley 879 45769 : a[len++] = '-';
880 : }
1030 drowley 881 GIC 9035743 : len += pg_ultoa_n(uvalue, a + len);
1163 rhodiumtoad 882 CBC 9035743 : a[len] = '\0';
1030 drowley 883 9035743 : return len;
884 : }
1163 rhodiumtoad 885 ECB :
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
1163 rhodiumtoad 891 CBC 291901 : pg_ulltoa_n(uint64 value, char *a)
1163 rhodiumtoad 892 ECB : {
893 : int olength,
1163 rhodiumtoad 894 GIC 291901 : i = 0;
895 : uint32 value2;
1163 rhodiumtoad 896 ECB :
897 : /* Degenerate case */
1163 rhodiumtoad 898 GIC 291901 : if (value == 0)
4524 rhaas 899 ECB : {
1163 rhodiumtoad 900 GIC 22513 : *a = '0';
1163 rhodiumtoad 901 CBC 22513 : return 1;
4524 rhaas 902 ECB : }
903 :
1163 rhodiumtoad 904 GIC 269388 : olength = decimalLength64(value);
905 :
906 : /* Compute the result string. */
1163 rhodiumtoad 907 CBC 277395 : while (value >= 100000000)
4524 rhaas 908 ECB : {
1163 rhodiumtoad 909 GIC 8007 : const uint64 q = value / 100000000;
186 drowley 910 GNC 8007 : uint32 value3 = (uint32) (value - 100000000 * q);
911 :
912 8007 : const uint32 c = value3 % 10000;
913 8007 : const uint32 d = value3 / 10000;
1163 rhodiumtoad 914 GIC 8007 : const uint32 c0 = (c % 100) << 1;
915 8007 : const uint32 c1 = (c / 100) << 1;
916 8007 : const uint32 d0 = (d % 100) << 1;
917 8007 : const uint32 d1 = (d / 100) << 1;
918 :
919 8007 : char *pos = a + olength - i;
920 :
921 8007 : value = q;
922 :
923 8007 : memcpy(pos - 2, DIGIT_TABLE + c0, 2);
924 8007 : memcpy(pos - 4, DIGIT_TABLE + c1, 2);
925 8007 : memcpy(pos - 6, DIGIT_TABLE + d0, 2);
926 8007 : memcpy(pos - 8, DIGIT_TABLE + d1, 2);
927 8007 : i += 8;
1163 rhodiumtoad 928 EUB : }
929 :
930 : /* Switch to 32-bit for speed */
1163 rhodiumtoad 931 GIC 269388 : value2 = (uint32) value;
932 :
933 269388 : if (value2 >= 10000)
1163 rhodiumtoad 934 ECB : {
1163 rhodiumtoad 935 GIC 13146 : const uint32 c = value2 - 10000 * (value2 / 10000);
1163 rhodiumtoad 936 CBC 13146 : const uint32 c0 = (c % 100) << 1;
1163 rhodiumtoad 937 GIC 13146 : const uint32 c1 = (c / 100) << 1;
1163 rhodiumtoad 938 ECB :
1163 rhodiumtoad 939 CBC 13146 : char *pos = a + olength - i;
940 :
1163 rhodiumtoad 941 GIC 13146 : value2 /= 10000;
1163 rhodiumtoad 942 ECB :
1163 rhodiumtoad 943 CBC 13146 : memcpy(pos - 2, DIGIT_TABLE + c0, 2);
1163 rhodiumtoad 944 GIC 13146 : memcpy(pos - 4, DIGIT_TABLE + c1, 2);
945 13146 : i += 4;
1163 rhodiumtoad 946 ECB : }
1163 rhodiumtoad 947 GIC 269388 : if (value2 >= 100)
4524 rhaas 948 ECB : {
1163 rhodiumtoad 949 CBC 107670 : const uint32 c = (value2 % 100) << 1;
1163 rhodiumtoad 950 GIC 107670 : char *pos = a + olength - i;
4523 tgl 951 ECB :
1163 rhodiumtoad 952 CBC 107670 : value2 /= 100;
953 :
1163 rhodiumtoad 954 GIC 107670 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
1163 rhodiumtoad 955 CBC 107670 : i += 2;
956 : }
957 269388 : if (value2 >= 10)
958 : {
959 62193 : const uint32 c = value2 << 1;
1163 rhodiumtoad 960 GIC 62193 : char *pos = a + olength - i;
1163 rhodiumtoad 961 ECB :
1163 rhodiumtoad 962 GIC 62193 : memcpy(pos - 2, DIGIT_TABLE + c, 2);
1163 rhodiumtoad 963 ECB : }
1163 rhodiumtoad 964 EUB : else
1163 rhodiumtoad 965 GIC 207195 : *a = (char) ('0' + value2);
1163 rhodiumtoad 966 ECB :
1163 rhodiumtoad 967 GIC 269388 : return olength;
1163 rhodiumtoad 968 ECB : }
969 :
970 : /*
1030 drowley 971 : * pg_lltoa: converts a signed 64-bit integer to its string representation and
972 : * returns strlen(a).
1163 rhodiumtoad 973 EUB : *
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
1163 rhodiumtoad 978 GIC 150974 : pg_lltoa(int64 value, char *a)
1163 rhodiumtoad 979 ECB : {
1163 rhodiumtoad 980 GIC 150974 : uint64 uvalue = value;
1030 drowley 981 CBC 150974 : int len = 0;
982 :
1163 rhodiumtoad 983 150974 : if (value < 0)
984 : {
985 1181 : uvalue = (uint64) 0 - uvalue;
1030 drowley 986 GIC 1181 : a[len++] = '-';
1163 rhodiumtoad 987 ECB : }
1030 drowley 988 EUB :
1030 drowley 989 GIC 150974 : len += pg_ulltoa_n(uvalue, a + len);
1030 drowley 990 CBC 150974 : a[len] = '\0';
1030 drowley 991 GIC 150974 : return len;
9770 scrappy 992 ECB : }
993 :
994 :
2619 tgl 995 : /*
1163 rhodiumtoad 996 : * pg_ultostr_zeropad
2619 tgl 997 EUB : * 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.
2619 tgl 1003 ECB : *
1004 : * The intended use-case for this function is to build strings that contain
1005 : * multiple individual numbers, for example:
1006 : *
1034 drowley 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);
2619 tgl 1012 EUB : * *str = '\0';
1013 : *
2619 tgl 1014 ECB : * Note: Caller must ensure that 'str' points to enough memory to hold the
1015 : * result.
1016 : */
1017 : char *
1163 rhodiumtoad 1018 GIC 412262 : pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth)
2619 tgl 1019 ECB : {
1163 rhodiumtoad 1020 : int len;
2619 tgl 1021 EUB :
2619 tgl 1022 GIC 412262 : Assert(minwidth > 0);
1023 :
1163 rhodiumtoad 1024 GBC 412262 : if (value < 100 && minwidth == 2) /* Short cut for common case */
1025 : {
1163 rhodiumtoad 1026 GIC 347598 : memcpy(str, DIGIT_TABLE + value * 2, 2);
1027 347598 : return str + 2;
1028 : }
2619 tgl 1029 ECB :
1163 rhodiumtoad 1030 GIC 64664 : len = pg_ultoa_n(value, str);
1163 rhodiumtoad 1031 CBC 64664 : if (len >= minwidth)
1163 rhodiumtoad 1032 GIC 64325 : return str + len;
2619 tgl 1033 ECB :
1163 rhodiumtoad 1034 GIC 339 : memmove(str + minwidth - len, str, len);
1163 rhodiumtoad 1035 CBC 339 : memset(str, '0', minwidth - len);
1036 339 : return str + minwidth;
1037 : }
2619 tgl 1038 ECB :
1039 : /*
1034 drowley 1040 : * pg_ultostr
1041 : * Converts 'value' into a decimal string representation stored at 'str'.
1042 : *
2619 tgl 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++ = ' ';
1034 drowley 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.
2619 tgl 1056 : */
1057 : char *
1163 rhodiumtoad 1058 GIC 1638 : pg_ultostr(char *str, uint32 value)
1059 : {
1163 rhodiumtoad 1060 CBC 1638 : int len = pg_ultoa_n(value, str);
2619 tgl 1061 ECB :
1163 rhodiumtoad 1062 GIC 1638 : return str + len;
2619 tgl 1063 ECB : }
|