242
242
static void free_var(NumericVar *var);
243
243
static void zero_var(NumericVar *var);
245
static void set_var_from_str(const char *str, NumericVar *dest);
245
static const char *set_var_from_str(const char *str, const char *cp,
246
247
static void set_var_from_num(Numeric value, NumericVar *dest);
247
248
static void set_var_from_var(NumericVar *value, NumericVar *dest);
248
249
static char *get_str_from_var(NumericVar *var, int dscale);
321
322
Oid typelem = PG_GETARG_OID(1);
323
324
int32 typmod = PG_GETARG_INT32(2);
328
/* Skip leading spaces */
332
if (!isspace((unsigned char) *cp))
330
if (pg_strcasecmp(str, "NaN") == 0)
331
PG_RETURN_NUMERIC(make_result(&const_nan));
334
* Use set_var_from_str() to parse the input string and return it in the
335
* packed DB storage format
338
set_var_from_str(str, &value);
340
apply_typmod(&value, typmod);
342
res = make_result(&value);
340
if (pg_strncasecmp(cp, "NaN", 3) == 0)
342
res = make_result(&const_nan);
344
/* Should be nothing left but spaces */
348
if (!isspace((unsigned char) *cp))
350
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
351
errmsg("invalid input syntax for type numeric: \"%s\"",
359
* Use set_var_from_str() to parse a normal numeric value
365
cp = set_var_from_str(str, cp, &value);
368
* We duplicate a few lines of code here because we would like to
369
* throw any trailing-junk syntax error before any semantic error
370
* resulting from apply_typmod. We can't easily fold the two
371
* cases together because we mustn't apply apply_typmod to a NaN.
375
if (!isspace((unsigned char) *cp))
377
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
378
errmsg("invalid input syntax for type numeric: \"%s\"",
383
apply_typmod(&value, typmod);
385
res = make_result(&value);
345
389
PG_RETURN_NUMERIC(res);
2122
2166
init_var(&result);
2124
set_var_from_str(buf, &result);
2168
/* Assume we need not worry about leading/trailing spaces */
2169
(void) set_var_from_str(buf, buf, &result);
2125
2171
res = make_result(&result);
2127
2173
free_var(&result);
2182
2228
init_var(&result);
2184
set_var_from_str(buf, &result);
2230
/* Assume we need not worry about leading/trailing spaces */
2231
(void) set_var_from_str(buf, buf, &result);
2185
2233
res = make_result(&result);
2187
2235
free_var(&result);
2972
3020
* set_var_from_str()
2974
3022
* Parse a string and put the number into a variable
3024
* This function does not handle leading or trailing spaces, and it doesn't
3025
* accept "NaN" either. It returns the end+1 position so that caller can
3026
* check for trailing spaces/garbage if deemed necessary.
3028
* cp is the place to actually start parsing; str is what to use in error
3029
* reports. (Typically cp would be the same except advanced over spaces.)
2977
set_var_from_str(const char *str, NumericVar *dest)
3032
set_var_from_str(const char *str, const char *cp, NumericVar *dest)
2979
const char *cp = str;
2980
3034
bool have_dp = FALSE;
2982
3036
unsigned char *decdigits;
3089
/* Should be nothing left but spaces */
3092
if (!isspace((unsigned char) *cp))
3094
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3095
errmsg("invalid input syntax for type numeric: \"%s\"",
3101
3135
* Okay, convert pure-decimal representation to base NBASE. First we need
3102
3136
* to determine the converted weight and ndigits. offset is the number of