]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/numutils.c
Update copyrights in source tree to 2008.
[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-2008, 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.76 2008/01/01 19:45:52 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 /*
26  * pg_atoi: convert string to integer
27  *
28  * allows any number of leading or trailing whitespace characters.
29  *
30  * 'size' is the sizeof() the desired integral result (1, 2, or 4 bytes).
31  *
32  * c, if not 0, is a terminator character that may appear after the
33  * integer (plus whitespace).  If 0, the string must end after the integer.
34  *
35  * Unlike plain atoi(), this will throw ereport() upon bad input format or
36  * overflow.
37  */
38 int32
39 pg_atoi(char *s, int size, int c)
40 {
41         long            l;
42         char       *badp;
43
44         /*
45          * Some versions of strtol treat the empty string as an error, but some
46          * seem not to.  Make an explicit test to be sure we catch it.
47          */
48         if (s == NULL)
49                 elog(ERROR, "NULL pointer");
50         if (*s == 0)
51                 ereport(ERROR,
52                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
53                                  errmsg("invalid input syntax for integer: \"%s\"",
54                                                 s)));
55
56         errno = 0;
57         l = strtol(s, &badp, 10);
58
59         /* We made no progress parsing the string, so bail out */
60         if (s == badp)
61                 ereport(ERROR,
62                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
63                                  errmsg("invalid input syntax for integer: \"%s\"",
64                                                 s)));
65
66         switch (size)
67         {
68                 case sizeof(int32):
69                         if (errno == ERANGE
70 #if defined(HAVE_LONG_INT_64)
71                         /* won't get ERANGE on these with 64-bit longs... */
72                                 || l < INT_MIN || l > INT_MAX
73 #endif
74                                 )
75                                 ereport(ERROR,
76                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
77                                 errmsg("value \"%s\" is out of range for type integer", s)));
78                         break;
79                 case sizeof(int16):
80                         if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
81                                 ereport(ERROR,
82                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
83                                 errmsg("value \"%s\" is out of range for type smallint", s)));
84                         break;
85                 case sizeof(int8):
86                         if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
87                                 ereport(ERROR,
88                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
89                                 errmsg("value \"%s\" is out of range for 8-bit integer", s)));
90                         break;
91                 default:
92                         elog(ERROR, "unsupported result size: %d", size);
93         }
94
95         /*
96          * Skip any trailing whitespace; if anything but whitespace remains before
97          * the terminating character, bail out
98          */
99         while (*badp && *badp != c && isspace((unsigned char) *badp))
100                 badp++;
101
102         if (*badp && *badp != c)
103                 ereport(ERROR,
104                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
105                                  errmsg("invalid input syntax for integer: \"%s\"",
106                                                 s)));
107
108         return (int32) l;
109 }
110
111 /*
112  *              pg_itoa                 - converts a short int to its string represention
113  *
114  *              Note:
115  *                              previously based on ~ingres/source/gutil/atoi.c
116  *                              now uses vendor's sprintf conversion
117  */
118 void
119 pg_itoa(int16 i, char *a)
120 {
121         sprintf(a, "%hd", (short) i);
122 }
123
124 /*
125  *              pg_ltoa                 - converts a long int to its string represention
126  *
127  *              Note:
128  *                              previously based on ~ingres/source/gutil/atoi.c
129  *                              now uses vendor's sprintf conversion
130  */
131 void
132 pg_ltoa(int32 l, char *a)
133 {
134         sprintf(a, "%d", l);
135 }