]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/numutils.c
OK, folks, here is the pgindent output.
[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:                                itoa, ltoa
7  *              floating point:                 ftoa, atof1
8  *
9  * Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/numutils.c,v 1.26 1998/09/01 04:32:43 momjian Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include <stdio.h>                              /* for sprintf() */
18 #include <errno.h>
19 #include <math.h>
20 #ifdef HAVE_LIMITS
21 #include <limits.h>
22 #endif
23 #include "postgres.h"
24 #include "utils/builtins.h"             /* where the declarations go */
25 #ifndef HAVE_MEMMOVE
26 #include <regex/utils.h>
27 #else
28 #include <string.h>
29 #endif
30
31 #ifndef INT_MAX
32 #define INT_MAX (0x7FFFFFFFL)
33 #endif
34 #ifndef INT_MIN
35 #define INT_MIN (-0x80000000L)
36 #endif
37 #ifndef SHRT_MAX
38 #define SHRT_MAX (0x7FFF)
39 #endif
40 #ifndef SHRT_MIN
41 #define SHRT_MIN (-0x8000)
42 #endif
43 #ifndef SCHAR_MAX
44 #define SCHAR_MAX (0x7F)
45 #endif
46 #ifndef SCHAR_MIN
47 #define SCHAR_MIN (-0x80)
48 #endif
49
50 int32
51 pg_atoi(char *s, int size, int c)
52 {
53         long            l;
54         char       *badp = (char *) NULL;
55
56         Assert(s);
57
58         errno = 0;
59         l = strtol(s, &badp, 10);
60         if (errno)                                      /* strtol must set ERANGE */
61                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
62         if (badp && *badp && (*badp != c))
63                 elog(ERROR, "pg_atoi: error in \"%s\": can\'t parse \"%s\"", s, badp);
64
65         switch (size)
66         {
67                 case sizeof(int32):
68 #ifdef HAS_LONG_LONG
69                         /* won't get ERANGE on these with 64-bit longs... */
70                         if (l < INT_MIN)
71                         {
72                                 errno = ERANGE;
73                                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
74                         }
75                         if (l > INT_MAX)
76                         {
77                                 errno = ERANGE;
78                                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
79                         }
80 #endif   /* HAS_LONG_LONG */
81                         break;
82                 case sizeof(int16):
83                         if (l < SHRT_MIN)
84                         {
85                                 errno = ERANGE;
86                                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
87                         }
88                         if (l > SHRT_MAX)
89                         {
90                                 errno = ERANGE;
91                                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
92                         }
93                         break;
94                 case sizeof(int8):
95                         if (l < SCHAR_MIN)
96                         {
97                                 errno = ERANGE;
98                                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
99                         }
100                         if (l > SCHAR_MAX)
101                         {
102                                 errno = ERANGE;
103                                 elog(ERROR, "pg_atoi: error reading \"%s\": %m", s);
104                         }
105                         break;
106                 default:
107                         elog(ERROR, "pg_atoi: invalid result size: %d", size);
108         }
109         return (int32) l;
110 }
111
112 /*
113  *              itoa                    - converts a short int to its string represention
114  *
115  *              Note:
116  *                              previously based on ~ingres/source/gutil/atoi.c
117  *                              now uses vendor's sprintf conversion
118  */
119 void
120 itoa(int i, char *a)
121 {
122         sprintf(a, "%hd", (short) i);
123 }
124
125 /*
126  *              ltoa                    - converts a long int to its string represention
127  *
128  *              Note:
129  *                              previously based on ~ingres/source/gutil/atoi.c
130  *                              now uses vendor's sprintf conversion
131  */
132 void
133 ltoa(int32 l, char *a)
134 {
135         sprintf(a, "%d", l);
136 }
137
138 /*
139  **  ftoa               - FLOATING POINT TO ASCII CONVERSION
140  **
141  **             CODE derived from ingres, ~ingres/source/gutil/ftoa.c
142  **
143  **             'Value' is converted to an ascii character string and stored
144  **             into 'ascii'.  Ascii should have room for at least 'width' + 1
145  **             characters.  'Width' is the width of the output field (max).
146  **             'Prec' is the number of characters to put after the decimal
147  **             point.  The format of the output string is controlled by
148  **             'format'.
149  **
150  **             'Format' can be:
151  **                             e or E: "E" format output
152  **                             f or F:  "F" format output
153  **                             g or G:  "F" format output if it will fit, otherwise
154  **                                             use "E" format.
155  **                             n or N:  same as G, but decimal points will not always
156  **                                             be aligned.
157  **
158  **             If 'format' is upper case, the "E" comes out in upper case;
159  **             otherwise it comes out in lower case.
160  **
161  **             When the field width is not big enough, it fills the field with
162  **             stars ("*****") and returns zero.  Normal return is the width
163  **             of the output field (sometimes shorter than 'width').
164  */
165 #ifdef NOT_USED
166 int
167 ftoa(double value, char *ascii, int width, int prec1, char format)
168 {
169 #ifndef HAVE_FCVT
170         char            out[256];
171         char            fmt[256];
172         int                     ret;
173
174         sprintf(fmt, "%%%d.%d%c", width, prec1, format);
175         sprintf(out, fmt, value);
176         if ((ret = strlen(out)) > width)
177         {
178                 MemSet(ascii, '*', width - 2);
179                 ascii[width] = 0;
180                 return 0;
181         }
182         strcpy(ascii, out);
183         return ret;
184 #else
185         auto int        expon;
186         auto int        sign;
187         int                     avail = 0;
188         char       *a = NULL;
189         char       *p = NULL;
190         char            mode;
191         int                     lowercase;
192         int                     prec;
193
194 /*        extern char           *ecvt(), *fcvt();*/
195
196         prec = prec1;
197         mode = format;
198         lowercase = 'a' - 'A';
199         if (mode >= 'a')
200                 mode -= 'a' - 'A';
201         else
202                 lowercase = 0;
203
204         if (mode != 'E')
205         {
206                 /* try 'F' style output */
207                 p = fcvt(value, prec, &expon, &sign);
208                 avail = width;
209                 a = ascii;
210
211                 /* output sign */
212                 if (sign)
213                 {
214                         avail--;
215                         *a++ = '-';
216                 }
217
218                 /* output '0' before the decimal point */
219                 if (expon <= 0)
220                 {
221                         *a++ = '0';
222                         avail--;
223                 }
224
225                 /* compute space length left after dec pt and fraction */
226                 avail -= prec + 1;
227                 if (mode == 'G')
228                         avail -= 4;
229
230                 if (avail >= expon)
231                 {
232
233                         /* it fits.  output */
234                         while (expon > 0)
235                         {
236                                 /* output left of dp */
237                                 expon--;
238                                 if (*p)
239                                         *a++ = *p++;
240                                 else
241                                         *a++ = '0';
242                         }
243
244                         /* output fraction (right of dec pt) */
245                         avail = expon;
246                         goto frac_out;
247                 }
248                 /* won't fit; let's hope for G format */
249         }
250
251         if (mode != 'F')
252         {
253                 /* try to do E style output */
254                 p = ecvt(value, prec + 1, &expon, &sign);
255                 avail = width - 5;
256                 a = ascii;
257
258                 /* output the sign */
259                 if (sign)
260                 {
261                         *a++ = '-';
262                         avail--;
263                 }
264         }
265
266         /* check for field too small */
267         if (mode == 'F' || avail < prec)
268         {
269                 /* sorry joker, you lose */
270                 a = ascii;
271                 for (avail = width; avail > 0; avail--)
272                         *a++ = '*';
273                 *a = 0;
274                 return 0;
275         }
276
277         /* it fits; output the number */
278         mode = 'E';
279
280         /* output the LHS single digit */
281         *a++ = *p++;
282         expon--;
283
284         /* output the rhs */
285         avail = 1;
286
287 frac_out:
288         *a++ = '.';
289         while (prec > 0)
290         {
291                 prec--;
292                 if (avail < 0)
293                 {
294                         avail++;
295                         *a++ = '0';
296                 }
297                 else
298                 {
299                         if (*p)
300                                 *a++ = *p++;
301                         else
302                                 *a++ = '0';
303                 }
304         }
305
306         /* output the exponent */
307         if (mode == 'E')
308         {
309                 *a++ = 'E' + lowercase;
310                 if (expon < 0)
311                 {
312                         *a++ = '-';
313                         expon = -expon;
314                 }
315                 else
316                         *a++ = '+';
317                 *a++ = (expon / 10) % 10 + '0';
318                 *a++ = expon % 10 + '0';
319         }
320
321         /* output spaces on the end in G format */
322         if (mode == 'G')
323         {
324                 *a++ = ' ';
325                 *a++ = ' ';
326                 *a++ = ' ';
327                 *a++ = ' ';
328         }
329
330         /* finally, we can return */
331         *a = 0;
332         avail = a - ascii;
333         return avail;
334 #endif
335 }
336
337 #endif
338
339 /*
340  **   atof1             - ASCII TO FLOATING CONVERSION
341  **
342  **             CODE derived from ~ingres/source/gutil/atof.c
343  **
344  **             Converts the string 'str' to floating point and stores the
345  **             result into the cell pointed to by 'val'.
346  **
347  **             The syntax which it accepts is pretty much what you would
348  **             expect.  Basically, it is:
349  **                             {<sp>} [+|-] {<sp>} {<digit>} [.{digit}] {<sp>} [<exp>]
350  **             where <exp> is "e" or "E" followed by an integer, <sp> is a
351  **             space character, <digit> is zero through nine, [] is zero or
352  **             one, and {} is zero or more.
353  **
354  **             Parameters:
355  **                             str -- string to convert.
356  **                             val -- pointer to place to put the result (which
357  **                                             must be type double).
358  **
359  **             Returns:
360  **                             zero -- ok.
361  **                             -1 -- syntax error.
362  **                             +1 -- overflow (not implemented).
363  **
364  **             Side Effects:
365  **                             clobbers *val.
366  */
367 #ifdef NOT_USED
368 int
369 atof1(char *str, double *val)
370 {
371         char       *p;
372         double          v;
373         double          fact;
374         int                     minus;
375         char            c;
376         int                     expon;
377         int                     gotmant;
378
379         v = 0.0;
380         p = str;
381         minus = 0;
382
383         /* skip leading blanks */
384         while ((c = *p) != '\0')
385         {
386                 if (c != ' ')
387                         break;
388                 p++;
389         }
390
391         /* handle possible sign */
392         switch (c)
393         {
394                 case '-':
395                         minus++;
396
397                 case '+':
398                         p++;
399         }
400
401         /* skip blanks after sign */
402         while ((c = *p) != '\0')
403         {
404                 if (c != ' ')
405                         break;
406                 p++;
407         }
408
409         /* start collecting the number to the decimal point */
410         gotmant = 0;
411         for (;;)
412         {
413                 c = *p;
414                 if (c < '0' || c > '9')
415                         break;
416                 v = v * 10.0 + (c - '0');
417                 gotmant++;
418                 p++;
419         }
420
421         /* check for fractional part */
422         if (c == '.')
423         {
424                 fact = 1.0;
425                 for (;;)
426                 {
427                         c = *++p;
428                         if (c < '0' || c > '9')
429                                 break;
430                         fact *= 0.1;
431                         v += (c - '0') * fact;
432                         gotmant++;
433                 }
434         }
435
436         /* skip blanks before possible exponent */
437         while ((c = *p) != '\0')
438         {
439                 if (c != ' ')
440                         break;
441                 p++;
442         }
443
444         /* test for exponent */
445         if (c == 'e' || c == 'E')
446         {
447                 p++;
448                 expon = pg_atoi(p, sizeof(expon), '\0');
449                 if (!gotmant)
450                         v = 1.0;
451                 fact = expon;
452                 v *= pow(10.0, fact);
453         }
454         else
455         {
456                 /* if no exponent, then nothing */
457                 if (c != 0)
458                         return -1;
459         }
460
461         /* store the result and exit */
462         if (minus)
463                 v = -v;
464         *val = v;
465         return 0;
466 }
467
468 #endif