aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/formatting.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2015-03-22 22:56:52 -0400
committerBruce Momjian <bruce@momjian.us>2015-03-22 22:56:56 -0400
commit33a2c5ecd60a2cf68cfcdd37916f3989bb956581 (patch)
treeb3de9b956a74c0d0537aa3a78929570b4f3a783c /src/backend/utils/adt/formatting.c
parent59b0a98af07cf8decfe94739f92bf18ebb34ffc6 (diff)
downloadpostgresql-33a2c5ecd60a2cf68cfcdd37916f3989bb956581.tar.gz
postgresql-33a2c5ecd60a2cf68cfcdd37916f3989bb956581.zip
to_char: revert cc0d90b73b2e6dd2f301d46818a7265742c41a14
Revert "to_char(float4/8): zero pad to specified length". There are too many platform-specific problems, and the proper rounding is missing. Also revert companion patch 9d61b9953c1489cbb458ca70013cf5fca1bb7710.
Diffstat (limited to 'src/backend/utils/adt/formatting.c')
-rw-r--r--src/backend/utils/adt/formatting.c114
1 files changed, 39 insertions, 75 deletions
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 25b247ee78d..40a353f5134 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -113,6 +113,13 @@
#define DCH_MAX_ITEM_SIZ 12 /* max localized day name */
#define NUM_MAX_ITEM_SIZ 8 /* roman number (RN has 15 chars) */
+/* ----------
+ * More is in float.c
+ * ----------
+ */
+#define MAXFLOATWIDTH 60
+#define MAXDOUBLEWIDTH 500
+
/* ----------
* Format parser structs
@@ -5207,7 +5214,8 @@ int4_to_char(PG_FUNCTION_ARGS)
/* we can do it easily because float8 won't lose any precision */
float8 val = (float8) value;
- orgnum = psprintf("%+.*e", Num.post, val);
+ orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
+ snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, val);
/*
* Swap a leading positive sign for a space.
@@ -5406,6 +5414,7 @@ float4_to_char(PG_FUNCTION_ARGS)
numstr = orgnum = int_to_roman((int) rint(value));
else if (IS_EEEE(&Num))
{
+ numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
if (isnan(value) || is_infinite(value))
{
/*
@@ -5419,29 +5428,15 @@ float4_to_char(PG_FUNCTION_ARGS)
}
else
{
- numstr = psprintf("%+.*e", Num.post, value);
-
- /* prevent the display of imprecise/junk digits */
- if (Num.pre + Num.post > FLT_DIG)
- {
- int digits = 0;
- char *numstr_p;
-
- for (numstr_p = numstr; *numstr_p && *numstr_p != 'e'; numstr_p++)
- {
- if (isdigit(*numstr_p))
- {
- if (++digits > FLT_DIG)
- *numstr_p = '0';
- }
- }
- }
+ snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
/*
* Swap a leading positive sign for a space.
*/
- if (*numstr == '+')
- *numstr = ' ';
+ if (*orgnum == '+')
+ *orgnum = ' ';
+
+ numstr = orgnum;
}
}
else
@@ -5457,24 +5452,16 @@ float4_to_char(PG_FUNCTION_ARGS)
Num.pre += Num.multi;
}
- /* let psprintf() do the rounding */
- orgnum = psprintf("%.*f", Num.post, val);
+ orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
+ snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
+ numstr_pre_len = strlen(orgnum);
- /* prevent the display of imprecise/junk digits */
- if (Num.pre + Num.post > FLT_DIG)
- {
- int digits = 0;
- char *orgnum_p;
-
- for (orgnum_p = orgnum; *orgnum_p; orgnum_p++)
- {
- if (isdigit(*orgnum_p))
- {
- if (++digits > FLT_DIG)
- *orgnum_p = '0';
- }
- }
- }
+ /* adjust post digits to fit max float digits */
+ if (numstr_pre_len >= FLT_DIG)
+ Num.post = 0;
+ else if (numstr_pre_len + Num.post > FLT_DIG)
+ Num.post = FLT_DIG - numstr_pre_len;
+ snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
if (*orgnum == '-')
{ /* < 0 */
@@ -5533,6 +5520,7 @@ float8_to_char(PG_FUNCTION_ARGS)
numstr = orgnum = int_to_roman((int) rint(value));
else if (IS_EEEE(&Num))
{
+ numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
if (isnan(value) || is_infinite(value))
{
/*
@@ -5546,29 +5534,15 @@ float8_to_char(PG_FUNCTION_ARGS)
}
else
{
- numstr = psprintf("%+.*e", Num.post, value);
-
- /* prevent the display of imprecise/junk digits */
- if (Num.pre + Num.post > DBL_DIG)
- {
- int digits = 0;
- char *numstr_p;
-
- for (numstr_p = numstr; *numstr_p && *numstr_p != 'e'; numstr_p++)
- {
- if (isdigit(*numstr_p))
- {
- if (++digits > DBL_DIG)
- *numstr_p = '0';
- }
- }
- }
+ snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
/*
* Swap a leading positive sign for a space.
*/
- if (*numstr == '+')
- *numstr = ' ';
+ if (*orgnum == '+')
+ *orgnum = ' ';
+
+ numstr = orgnum;
}
}
else
@@ -5583,25 +5557,15 @@ float8_to_char(PG_FUNCTION_ARGS)
val = value * multi;
Num.pre += Num.multi;
}
-
- /* let psprintf() do the rounding */
- orgnum = psprintf("%.*f", Num.post, val);
-
- /* prevent the display of imprecise/junk digits */
- if (Num.pre + Num.post > DBL_DIG)
- {
- int digits = 0;
- char *orgnum_p;
-
- for (orgnum_p = orgnum; *orgnum_p; orgnum_p++)
- {
- if (isdigit(*orgnum_p))
- {
- if (++digits > DBL_DIG)
- *orgnum_p = '0';
- }
- }
- }
+ orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
+ numstr_pre_len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
+
+ /* adjust post digits to fit max double digits */
+ if (numstr_pre_len >= DBL_DIG)
+ Num.post = 0;
+ else if (numstr_pre_len + Num.post > DBL_DIG)
+ Num.post = DBL_DIG - numstr_pre_len;
+ snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
if (*orgnum == '-')
{ /* < 0 */