/* -----------------------------------------------------------------------
* formatting.c
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.129 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.130 2007/06/29 01:51:35 tgl Exp $
*
*
* Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
#include <unistd.h>
#include <math.h>
#include <float.h>
+#include <limits.h>
#include <locale.h>
#include "utils/builtins.h"
* More is in float.c
* ----------
*/
-#define MAXFLOATWIDTH 64
-#define MAXDOUBLEWIDTH 128
+#define MAXFLOATWIDTH 60
+#define MAXDOUBLEWIDTH 500
/* ----------
static char *localize_day_full(int index);
static char *localize_day(int index);
-/*
- * External (defined in oracle_compat.c
- */
#if defined(HAVE_WCSTOMBS) && defined(HAVE_TOWLOWER)
#define USE_WIDE_UPPER_LOWER
+/* externs are in oracle_compat.c */
extern char *wstring_upper(char *str);
extern char *wstring_lower(char *str);
+
static char *localized_str_toupper(char *buff);
static char *localized_str_tolower(char *buff);
#else
}
/* ----------
- * Convert string to upper-string. Input string is modified in place.
+ * Convert string to upper case. Input string is modified in place.
* ----------
*/
static char *
}
/* ----------
- * Convert string to lower-string. Input string is modified in place.
+ * Convert string to lower case. Input string is modified in place.
* ----------
*/
static char *
#ifdef USE_WIDE_UPPER_LOWER
/* ----------
- * Convert localized string to upper string. Input string is modified in place.
+ * Convert localized string to upper case.
+ * Input string may be modified in place ... or we might make a copy.
* ----------
*/
static char *
}
/* ----------
- * Convert localized string to upper string. Input string is modified in place.
+ * Convert localized string to lower case.
+ * Input string may be modified in place ... or we might make a copy.
* ----------
*/
static char *
INVALID_FOR_INTERVAL;
if (is_to_char && tmtcTzn(tmtc))
{
- int siz = strlen(tmtcTzn(tmtc));
-
if (arg == DCH_TZ)
strcpy(inout, tmtcTzn(tmtc));
else
{
- char *p = palloc(siz);
+ char *p = pstrdup(tmtcTzn(tmtc));
- strcpy(p, tmtcTzn(tmtc));
strcpy(inout, str_tolower(p));
pfree(p);
}
- return siz;
+ return strlen(inout);
}
else if (!is_to_char)
ereport(ERROR,
fill_str(char *str, int c, int max)
{
memset(str, c, max);
- *(str + max + 1) = '\0';
+ *(str + max) = '\0';
return str;
}
#define NUM_TOCHAR_prepare \
do { \
len = VARSIZE(fmt) - VARHDRSZ; \
- if (len <= 0) \
+ if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ) \
return DirectFunctionCall1(textin, CStringGetDatum("")); \
- result = (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
- memset(result, 0, (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ ); \
+ result = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree); \
} while (0)
*/
#define NUM_TOCHAR_finish \
do { \
- NUM_processor(format, &Num, VARDATA(result), \
- numstr, plen, sign, true); \
- pfree(orgnum); \
+ NUM_processor(format, &Num, VARDATA(result), numstr, plen, sign, true); \
\
- if (shouldFree) \
- pfree(format); \
+ if (shouldFree) \
+ pfree(format); \
\
- /*
- * for result is allocated max memory, which current format-picture\
- * needs, now it must be re-allocate to result real size \
+ /* \
+ * Convert null-terminated representation of result to standard text. \
+ * The result is usually much bigger than it needs to be, but there \
+ * seems little point in realloc'ing it smaller. \
*/ \
- if (!(len = strlen(VARDATA(result)))) \
- { \
- pfree(result); \
- PG_RETURN_NULL(); \
- } \
- \
- result_tmp = result; \
- result = (text *) palloc(len + VARHDRSZ); \
- \
- memcpy(VARDATA(result), VARDATA(result_tmp), len); \
- SET_VARSIZE(result, len + VARHDRSZ); \
- pfree(result_tmp); \
-} while(0)
+ len = strlen(VARDATA(result)); \
+ SET_VARSIZE(result, len + VARHDRSZ); \
+} while (0)
/* -------------------
* NUMERIC to_number() (convert string to numeric)
len = VARSIZE(fmt) - VARHDRSZ;
- if (len <= 0)
+ if (len <= 0 || len >= INT_MAX/NUM_MAX_ITEM_SIZ)
PG_RETURN_NULL();
format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);
text *fmt = PG_GETARG_TEXT_P(1);
NUMDesc Num;
FormatNode *format;
- text *result,
- *result_tmp;
+ text *result;
bool shouldFree;
int len = 0,
plen = 0,
numstr = orgnum =
int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
NumericGetDatum(x))));
- pfree(x);
}
else
{
val = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
NumericGetDatum(value),
NumericGetDatum(x)));
- pfree(x);
- pfree(a);
- pfree(b);
Num.pre += Num.multi;
}
Int32GetDatum(Num.post)));
orgnum = DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(x)));
- pfree(x);
if (*orgnum == '-')
- { /* < 0 */
+ {
sign = '-';
numstr = orgnum + 1;
}
plen = Num.pre - len;
else if (len > Num.pre)
{
- fill_str(numstr, '#', Num.pre);
+ numstr = (char *) palloc(Num.pre + Num.post + 2);
+ fill_str(numstr, '#', Num.pre + Num.post + 1);
*(numstr + Num.pre) = '.';
- fill_str(numstr + 1 + Num.pre, '#', Num.post);
}
-
- if (IS_MULTI(&Num))
- pfree(val);
}
NUM_TOCHAR_finish;
text *fmt = PG_GETARG_TEXT_P(1);
NUMDesc Num;
FormatNode *format;
- text *result,
- *result_tmp;
+ text *result;
bool shouldFree;
int len = 0,
plen = 0,
orgnum = DatumGetCString(DirectFunctionCall1(int4out,
Int32GetDatum(value)));
}
- len = strlen(orgnum);
if (*orgnum == '-')
- { /* < 0 */
+ {
sign = '-';
- --len;
+ orgnum++;
}
else
sign = '+';
+ len = strlen(orgnum);
if (Num.post)
{
- int i;
-
numstr = (char *) palloc(len + Num.post + 2);
- strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0));
+ strcpy(numstr, orgnum);
*(numstr + len) = '.';
-
- for (i = len + 1; i <= len + Num.post; i++)
- *(numstr + i) = '0';
+ memset(numstr + len + 1, '0', Num.post);
*(numstr + len + Num.post + 1) = '\0';
- pfree(orgnum);
- orgnum = numstr;
}
else
- numstr = orgnum + (*orgnum == '-' ? 1 : 0);
+ numstr = orgnum;
if (Num.pre > len)
plen = Num.pre - len;
else if (len > Num.pre)
{
- fill_str(numstr, '#', Num.pre);
+ numstr = (char *) palloc(Num.pre + Num.post + 2);
+ fill_str(numstr, '#', Num.pre + Num.post + 1);
*(numstr + Num.pre) = '.';
- fill_str(numstr + 1 + Num.pre, '#', Num.post);
}
}
text *fmt = PG_GETARG_TEXT_P(1);
NUMDesc Num;
FormatNode *format;
- text *result,
- *result_tmp;
+ text *result;
bool shouldFree;
int len = 0,
plen = 0,
orgnum = DatumGetCString(DirectFunctionCall1(int8out,
Int64GetDatum(value)));
- len = strlen(orgnum);
if (*orgnum == '-')
- { /* < 0 */
+ {
sign = '-';
- --len;
+ orgnum++;
}
else
sign = '+';
+ len = strlen(orgnum);
if (Num.post)
{
- int i;
-
numstr = (char *) palloc(len + Num.post + 2);
- strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0));
+ strcpy(numstr, orgnum);
*(numstr + len) = '.';
-
- for (i = len + 1; i <= len + Num.post; i++)
- *(numstr + i) = '0';
+ memset(numstr + len + 1, '0', Num.post);
*(numstr + len + Num.post + 1) = '\0';
- pfree(orgnum);
- orgnum = numstr;
}
else
- numstr = orgnum + (*orgnum == '-' ? 1 : 0);
+ numstr = orgnum;
if (Num.pre > len)
plen = Num.pre - len;
else if (len > Num.pre)
{
- fill_str(numstr, '#', Num.pre);
+ numstr = (char *) palloc(Num.pre + Num.post + 2);
+ fill_str(numstr, '#', Num.pre + Num.post + 1);
*(numstr + Num.pre) = '.';
- fill_str(numstr + 1 + Num.pre, '#', Num.post);
}
}
text *fmt = PG_GETARG_TEXT_P(1);
NUMDesc Num;
FormatNode *format;
- text *result,
- *result_tmp;
+ text *result;
bool shouldFree;
int len = 0,
plen = 0,
plen = Num.pre - len;
else if (len > Num.pre)
{
- fill_str(numstr, '#', Num.pre);
+ numstr = (char *) palloc(Num.pre + Num.post + 2);
+ fill_str(numstr, '#', Num.pre + Num.post + 1);
*(numstr + Num.pre) = '.';
- fill_str(numstr + 1 + Num.pre, '#', Num.post);
}
}
text *fmt = PG_GETARG_TEXT_P(1);
NUMDesc Num;
FormatNode *format;
- text *result,
- *result_tmp;
+ text *result;
bool shouldFree;
int len = 0,
plen = 0,
plen = Num.pre - len;
else if (len > Num.pre)
{
- fill_str(numstr, '#', Num.pre);
+ numstr = (char *) palloc(Num.pre + Num.post + 2);
+ fill_str(numstr, '#', Num.pre + Num.post + 1);
*(numstr + Num.pre) = '.';
- fill_str(numstr + 1 + Num.pre, '#', Num.post);
}
}