]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/numutils.c
Add comment to pg_atoi.
[postgresql] / src / backend / utils / adt / numutils.c
1 /*-------------------------------------------------------------------------
2  *
3  * numutils.c
4  *        utility functions for I/O of built-in numeric types.
5  *
6  *              integer:                                pg_atoi, pg_itoa, pg_ltoa
7  *
8  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.71 2005/12/01 21:16:13 momjian Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include "postgres.h"
18
19 #include <math.h>
20 #include <limits.h>
21 #include <ctype.h>
22
23 #include "utils/builtins.h"
24
25 #ifndef INT_MAX
26 #define INT_MAX (0x7FFFFFFFL)
27 #endif
28 #ifndef INT_MIN
29 #define INT_MIN (-INT_MAX-1)
30 #endif
31 #ifndef SHRT_MAX
32 #define SHRT_MAX (0x7FFF)
33 #endif
34 #ifndef SHRT_MIN
35 #define SHRT_MIN (-SHRT_MAX-1)
36 #endif
37 #ifndef SCHAR_MAX
38 #define SCHAR_MAX (0x7F)
39 #endif
40 #ifndef SCHAR_MIN
41 #define SCHAR_MIN (-SCHAR_MAX-1)
42 #endif
43
44
45 /*
46  * pg_atoi: convert string to integer
47  *
48  * allows any number of leading or trailing whitespace characters.
49  *
50  * 'size' is the sizeof() the desired integral result (1, 2, or 4 bytes).
51  *
52  * c, if not 0, is a terminator character that may appear after the
53  * integer (plus whitespace).  If 0, the string must end after the integer.
54  *
55  * Unlike plain atoi(), this will throw ereport() upon bad input format or
56  * overflow.
57  */
58 int32
59 pg_atoi(char *s, int size, int c)
60 {
61         long            l;
62         char       *badp;
63
64         /*
65          * Some versions of strtol treat the empty string as an error, but some
66          * seem not to.  Make an explicit test to be sure we catch it.
67          */
68         if (s == NULL)
69                 elog(ERROR, "NULL pointer");
70         if (*s == 0)
71                 ereport(ERROR,
72                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
73                                  errmsg("invalid input syntax for integer: \"%s\"",
74                                                 s)));
75
76         errno = 0;      /* avoid having to check the result for failure */
77         l = strtol(s, &badp, 10);
78
79         /* We made no progress parsing the string, so bail out */
80         if (s == badp)
81                 ereport(ERROR,
82                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
83                                  errmsg("invalid input syntax for integer: \"%s\"",
84                                                 s)));
85
86         switch (size)
87         {
88                 case sizeof(int32):
89                         if (errno == ERANGE
90 #if defined(HAVE_LONG_INT_64)
91                         /* won't get ERANGE on these with 64-bit longs... */
92                                 || l < INT_MIN || l > INT_MAX
93 #endif
94                                 )
95                                 ereport(ERROR,
96                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
97                                 errmsg("value \"%s\" is out of range for type integer", s)));
98                         break;
99                 case sizeof(int16):
100                         if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
101                                 ereport(ERROR,
102                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
103                                 errmsg("value \"%s\" is out of range for type smallint", s)));
104                         break;
105                 case sizeof(int8):
106                         if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
107                                 ereport(ERROR,
108                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109                                 errmsg("value \"%s\" is out of range for 8-bit integer", s)));
110                         break;
111                 default:
112                         elog(ERROR, "unsupported result size: %d", size);
113         }
114
115         /*
116          * Skip any trailing whitespace; if anything but whitespace remains before
117          * the terminating character, bail out
118          */
119         while (*badp && *badp != c && isspace((unsigned char) *badp))
120                 badp++;
121
122         if (*badp && *badp != c)
123                 ereport(ERROR,
124                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
125                                  errmsg("invalid input syntax for integer: \"%s\"",
126                                                 s)));
127
128         return (int32) l;
129 }
130
131 /*
132  *              pg_itoa                 - converts a short int to its string represention
133  *
134  *              Note:
135  *                              previously based on ~ingres/source/gutil/atoi.c
136  *                              now uses vendor's sprintf conversion
137  */
138 void
139 pg_itoa(int16 i, char *a)
140 {
141         sprintf(a, "%hd", (short) i);
142 }
143
144 /*
145  *              pg_ltoa                 - converts a long int to its string represention
146  *
147  *              Note:
148  *                              previously based on ~ingres/source/gutil/atoi.c
149  *                              now uses vendor's sprintf conversion
150  */
151 void
152 pg_ltoa(int32 l, char *a)
153 {
154         sprintf(a, "%d", l);
155 }