1
1
/* -----------------------------------------------------------------------
2
2
* formatting.c
3
3
*
4
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.129 2007/02/27 23:48:08 tgl Exp $
4
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.130 2007/06/29 01:51:35 tgl Exp $
5
5
*
6
6
*
7
7
* Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
74
74
#include <unistd.h>
75
75
#include <math.h>
76
76
#include <float.h>
77
+ #include <limits.h>
77
78
#include <locale.h>
78
79
79
80
#include "utils/builtins.h"
112
113
* More is in float.c
113
114
* ----------
114
115
*/
115
- #define MAXFLOATWIDTH 64
116
- #define MAXDOUBLEWIDTH 128
116
+ #define MAXFLOATWIDTH 60
117
+ #define MAXDOUBLEWIDTH 500
117
118
118
119
119
120
/* ----------
@@ -958,13 +959,12 @@ static char *localize_month(int index);
958
959
static char * localize_day_full (int index );
959
960
static char * localize_day (int index );
960
961
961
- /*
962
- * External (defined in oracle_compat.c
963
- */
964
962
#if defined(HAVE_WCSTOMBS ) && defined(HAVE_TOWLOWER )
965
963
#define USE_WIDE_UPPER_LOWER
964
+ /* externs are in oracle_compat.c */
966
965
extern char * wstring_upper (char * str );
967
966
extern char * wstring_lower (char * str );
967
+
968
968
static char * localized_str_toupper (char * buff );
969
969
static char * localized_str_tolower (char * buff );
970
970
#else
@@ -1510,7 +1510,7 @@ str_numth(char *dest, char *num, int type)
1510
1510
}
1511
1511
1512
1512
/* ----------
1513
- * Convert string to upper-string . Input string is modified in place.
1513
+ * Convert string to upper case . Input string is modified in place.
1514
1514
* ----------
1515
1515
*/
1516
1516
static char *
@@ -1531,7 +1531,7 @@ str_toupper(char *buff)
1531
1531
}
1532
1532
1533
1533
/* ----------
1534
- * Convert string to lower-string . Input string is modified in place.
1534
+ * Convert string to lower case . Input string is modified in place.
1535
1535
* ----------
1536
1536
*/
1537
1537
static char *
@@ -1553,7 +1553,8 @@ str_tolower(char *buff)
1553
1553
1554
1554
#ifdef USE_WIDE_UPPER_LOWER
1555
1555
/* ----------
1556
- * Convert localized string to upper string. Input string is modified in place.
1556
+ * Convert localized string to upper case.
1557
+ * Input string may be modified in place ... or we might make a copy.
1557
1558
* ----------
1558
1559
*/
1559
1560
static char *
@@ -1579,7 +1580,8 @@ localized_str_toupper(char *buff)
1579
1580
}
1580
1581
1581
1582
/* ----------
1582
- * Convert localized string to upper string. Input string is modified in place.
1583
+ * Convert localized string to lower case.
1584
+ * Input string may be modified in place ... or we might make a copy.
1583
1585
* ----------
1584
1586
*/
1585
1587
static char *
@@ -2107,19 +2109,16 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
2107
2109
INVALID_FOR_INTERVAL ;
2108
2110
if (is_to_char && tmtcTzn (tmtc ))
2109
2111
{
2110
- int siz = strlen (tmtcTzn (tmtc ));
2111
-
2112
2112
if (arg == DCH_TZ )
2113
2113
strcpy (inout , tmtcTzn (tmtc ));
2114
2114
else
2115
2115
{
2116
- char * p = palloc ( siz );
2116
+ char * p = pstrdup ( tmtcTzn ( tmtc ) );
2117
2117
2118
- strcpy (p , tmtcTzn (tmtc ));
2119
2118
strcpy (inout , str_tolower (p ));
2120
2119
pfree (p );
2121
2120
}
2122
- return siz ;
2121
+ return strlen ( inout ) ;
2123
2122
}
2124
2123
else if (!is_to_char )
2125
2124
ereport (ERROR ,
@@ -3624,7 +3623,7 @@ static char *
3624
3623
fill_str (char * str , int c , int max )
3625
3624
{
3626
3625
memset (str , c , max );
3627
- * (str + max + 1 ) = '\0' ;
3626
+ * (str + max ) = '\0' ;
3628
3627
return str ;
3629
3628
}
3630
3629
@@ -4798,10 +4797,9 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
4798
4797
#define NUM_TOCHAR_prepare \
4799
4798
do { \
4800
4799
len = VARSIZE(fmt) - VARHDRSZ; \
4801
- if (len <= 0) \
4800
+ if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ) \
4802
4801
return DirectFunctionCall1(textin, CStringGetDatum("")); \
4803
- result = (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
4804
- memset(result, 0, (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ ); \
4802
+ result = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
4805
4803
format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree); \
4806
4804
} while (0)
4807
4805
@@ -4811,30 +4809,19 @@ do { \
4811
4809
*/
4812
4810
#define NUM_TOCHAR_finish \
4813
4811
do { \
4814
- NUM_processor(format, &Num, VARDATA(result), \
4815
- numstr, plen, sign, true); \
4816
- pfree(orgnum); \
4812
+ NUM_processor(format, &Num, VARDATA(result), numstr, plen, sign, true); \
4817
4813
\
4818
- if (shouldFree) \
4819
- pfree(format); \
4814
+ if (shouldFree) \
4815
+ pfree(format); \
4820
4816
\
4821
- /*
4822
- * for result is allocated max memory, which current format-picture\
4823
- * needs, now it must be re-allocate to result real size \
4817
+ /* \
4818
+ * Convert null-terminated representation of result to standard text. \
4819
+ * The result is usually much bigger than it needs to be, but there \
4820
+ * seems little point in realloc'ing it smaller. \
4824
4821
*/ \
4825
- if (!(len = strlen (VARDATA (result )))) \
4826
- { \
4827
- pfree (result ); \
4828
- PG_RETURN_NULL (); \
4829
- } \
4830
- \
4831
- result_tmp = result ; \
4832
- result = (text * ) palloc (len + VARHDRSZ ); \
4833
- \
4834
- memcpy (VARDATA (result ), VARDATA (result_tmp ), len ); \
4835
- SET_VARSIZE (result , len + VARHDRSZ ); \
4836
- pfree (result_tmp ); \
4837
- } while (0 )
4822
+ len = strlen (VARDATA (result )); \
4823
+ SET_VARSIZE (result , len + VARHDRSZ ); \
4824
+ } while (0 )
4838
4825
4839
4826
/* -------------------
4840
4827
* NUMERIC to_number() (convert string to numeric)
@@ -4856,7 +4843,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
4856
4843
4857
4844
len = VARSIZE (fmt ) - VARHDRSZ ;
4858
4845
4859
- if (len <= 0 )
4846
+ if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ )
4860
4847
PG_RETURN_NULL ();
4861
4848
4862
4849
format = NUM_cache (len , & Num , VARDATA (fmt ), & shouldFree );
@@ -4891,8 +4878,7 @@ numeric_to_char(PG_FUNCTION_ARGS)
4891
4878
text * fmt = PG_GETARG_TEXT_P (1 );
4892
4879
NUMDesc Num ;
4893
4880
FormatNode * format ;
4894
- text * result ,
4895
- * result_tmp ;
4881
+ text * result ;
4896
4882
bool shouldFree ;
4897
4883
int len = 0 ,
4898
4884
plen = 0 ,
@@ -4915,7 +4901,6 @@ numeric_to_char(PG_FUNCTION_ARGS)
4915
4901
numstr = orgnum =
4916
4902
int_to_roman (DatumGetInt32 (DirectFunctionCall1 (numeric_int4 ,
4917
4903
NumericGetDatum (x ))));
4918
- pfree (x );
4919
4904
}
4920
4905
else
4921
4906
{
@@ -4934,9 +4919,6 @@ numeric_to_char(PG_FUNCTION_ARGS)
4934
4919
val = DatumGetNumeric (DirectFunctionCall2 (numeric_mul ,
4935
4920
NumericGetDatum (value ),
4936
4921
NumericGetDatum (x )));
4937
- pfree (x );
4938
- pfree (a );
4939
- pfree (b );
4940
4922
Num .pre += Num .multi ;
4941
4923
}
4942
4924
@@ -4945,10 +4927,9 @@ numeric_to_char(PG_FUNCTION_ARGS)
4945
4927
Int32GetDatum (Num .post )));
4946
4928
orgnum = DatumGetCString (DirectFunctionCall1 (numeric_out ,
4947
4929
NumericGetDatum (x )));
4948
- pfree (x );
4949
4930
4950
4931
if (* orgnum == '-' )
4951
- { /* < 0 */
4932
+ {
4952
4933
sign = '-' ;
4953
4934
numstr = orgnum + 1 ;
4954
4935
}
@@ -4966,13 +4947,10 @@ numeric_to_char(PG_FUNCTION_ARGS)
4966
4947
plen = Num .pre - len ;
4967
4948
else if (len > Num .pre )
4968
4949
{
4969
- fill_str (numstr , '#' , Num .pre );
4950
+ numstr = (char * ) palloc (Num .pre + Num .post + 2 );
4951
+ fill_str (numstr , '#' , Num .pre + Num .post + 1 );
4970
4952
* (numstr + Num .pre ) = '.' ;
4971
- fill_str (numstr + 1 + Num .pre , '#' , Num .post );
4972
4953
}
4973
-
4974
- if (IS_MULTI (& Num ))
4975
- pfree (val );
4976
4954
}
4977
4955
4978
4956
NUM_TOCHAR_finish ;
@@ -4990,8 +4968,7 @@ int4_to_char(PG_FUNCTION_ARGS)
4990
4968
text * fmt = PG_GETARG_TEXT_P (1 );
4991
4969
NUMDesc Num ;
4992
4970
FormatNode * format ;
4993
- text * result ,
4994
- * result_tmp ;
4971
+ text * result ;
4995
4972
bool shouldFree ;
4996
4973
int len = 0 ,
4997
4974
plen = 0 ,
@@ -5019,40 +4996,34 @@ int4_to_char(PG_FUNCTION_ARGS)
5019
4996
orgnum = DatumGetCString (DirectFunctionCall1 (int4out ,
5020
4997
Int32GetDatum (value )));
5021
4998
}
5022
- len = strlen (orgnum );
5023
4999
5024
5000
if (* orgnum == '-' )
5025
- { /* < 0 */
5001
+ {
5026
5002
sign = '-' ;
5027
- -- len ;
5003
+ orgnum ++ ;
5028
5004
}
5029
5005
else
5030
5006
sign = '+' ;
5007
+ len = strlen (orgnum );
5031
5008
5032
5009
if (Num .post )
5033
5010
{
5034
- int i ;
5035
-
5036
5011
numstr = (char * ) palloc (len + Num .post + 2 );
5037
- strcpy (numstr , orgnum + ( * orgnum == '-' ? 1 : 0 ) );
5012
+ strcpy (numstr , orgnum );
5038
5013
* (numstr + len ) = '.' ;
5039
-
5040
- for (i = len + 1 ; i <= len + Num .post ; i ++ )
5041
- * (numstr + i ) = '0' ;
5014
+ memset (numstr + len + 1 , '0' , Num .post );
5042
5015
* (numstr + len + Num .post + 1 ) = '\0' ;
5043
- pfree (orgnum );
5044
- orgnum = numstr ;
5045
5016
}
5046
5017
else
5047
- numstr = orgnum + ( * orgnum == '-' ? 1 : 0 ) ;
5018
+ numstr = orgnum ;
5048
5019
5049
5020
if (Num .pre > len )
5050
5021
plen = Num .pre - len ;
5051
5022
else if (len > Num .pre )
5052
5023
{
5053
- fill_str (numstr , '#' , Num .pre );
5024
+ numstr = (char * ) palloc (Num .pre + Num .post + 2 );
5025
+ fill_str (numstr , '#' , Num .pre + Num .post + 1 );
5054
5026
* (numstr + Num .pre ) = '.' ;
5055
- fill_str (numstr + 1 + Num .pre , '#' , Num .post );
5056
5027
}
5057
5028
}
5058
5029
@@ -5071,8 +5042,7 @@ int8_to_char(PG_FUNCTION_ARGS)
5071
5042
text * fmt = PG_GETARG_TEXT_P (1 );
5072
5043
NUMDesc Num ;
5073
5044
FormatNode * format ;
5074
- text * result ,
5075
- * result_tmp ;
5045
+ text * result ;
5076
5046
bool shouldFree ;
5077
5047
int len = 0 ,
5078
5048
plen = 0 ,
@@ -5106,40 +5076,34 @@ int8_to_char(PG_FUNCTION_ARGS)
5106
5076
5107
5077
orgnum = DatumGetCString (DirectFunctionCall1 (int8out ,
5108
5078
Int64GetDatum (value )));
5109
- len = strlen (orgnum );
5110
5079
5111
5080
if (* orgnum == '-' )
5112
- { /* < 0 */
5081
+ {
5113
5082
sign = '-' ;
5114
- -- len ;
5083
+ orgnum ++ ;
5115
5084
}
5116
5085
else
5117
5086
sign = '+' ;
5087
+ len = strlen (orgnum );
5118
5088
5119
5089
if (Num .post )
5120
5090
{
5121
- int i ;
5122
-
5123
5091
numstr = (char * ) palloc (len + Num .post + 2 );
5124
- strcpy (numstr , orgnum + ( * orgnum == '-' ? 1 : 0 ) );
5092
+ strcpy (numstr , orgnum );
5125
5093
* (numstr + len ) = '.' ;
5126
-
5127
- for (i = len + 1 ; i <= len + Num .post ; i ++ )
5128
- * (numstr + i ) = '0' ;
5094
+ memset (numstr + len + 1 , '0' , Num .post );
5129
5095
* (numstr + len + Num .post + 1 ) = '\0' ;
5130
- pfree (orgnum );
5131
- orgnum = numstr ;
5132
5096
}
5133
5097
else
5134
- numstr = orgnum + ( * orgnum == '-' ? 1 : 0 ) ;
5098
+ numstr = orgnum ;
5135
5099
5136
5100
if (Num .pre > len )
5137
5101
plen = Num .pre - len ;
5138
5102
else if (len > Num .pre )
5139
5103
{
5140
- fill_str (numstr , '#' , Num .pre );
5104
+ numstr = (char * ) palloc (Num .pre + Num .post + 2 );
5105
+ fill_str (numstr , '#' , Num .pre + Num .post + 1 );
5141
5106
* (numstr + Num .pre ) = '.' ;
5142
- fill_str (numstr + 1 + Num .pre , '#' , Num .post );
5143
5107
}
5144
5108
}
5145
5109
@@ -5158,8 +5122,7 @@ float4_to_char(PG_FUNCTION_ARGS)
5158
5122
text * fmt = PG_GETARG_TEXT_P (1 );
5159
5123
NUMDesc Num ;
5160
5124
FormatNode * format ;
5161
- text * result ,
5162
- * result_tmp ;
5125
+ text * result ;
5163
5126
bool shouldFree ;
5164
5127
int len = 0 ,
5165
5128
plen = 0 ,
@@ -5214,9 +5177,9 @@ float4_to_char(PG_FUNCTION_ARGS)
5214
5177
plen = Num .pre - len ;
5215
5178
else if (len > Num .pre )
5216
5179
{
5217
- fill_str (numstr , '#' , Num .pre );
5180
+ numstr = (char * ) palloc (Num .pre + Num .post + 2 );
5181
+ fill_str (numstr , '#' , Num .pre + Num .post + 1 );
5218
5182
* (numstr + Num .pre ) = '.' ;
5219
- fill_str (numstr + 1 + Num .pre , '#' , Num .post );
5220
5183
}
5221
5184
}
5222
5185
@@ -5235,8 +5198,7 @@ float8_to_char(PG_FUNCTION_ARGS)
5235
5198
text * fmt = PG_GETARG_TEXT_P (1 );
5236
5199
NUMDesc Num ;
5237
5200
FormatNode * format ;
5238
- text * result ,
5239
- * result_tmp ;
5201
+ text * result ;
5240
5202
bool shouldFree ;
5241
5203
int len = 0 ,
5242
5204
plen = 0 ,
@@ -5289,9 +5251,9 @@ float8_to_char(PG_FUNCTION_ARGS)
5289
5251
plen = Num .pre - len ;
5290
5252
else if (len > Num .pre )
5291
5253
{
5292
- fill_str (numstr , '#' , Num .pre );
5254
+ numstr = (char * ) palloc (Num .pre + Num .post + 2 );
5255
+ fill_str (numstr , '#' , Num .pre + Num .post + 1 );
5293
5256
* (numstr + Num .pre ) = '.' ;
5294
- fill_str (numstr + 1 + Num .pre , '#' , Num .post );
5295
5257
}
5296
5258
}
5297
5259
0 commit comments