1
1
/* -----------------------------------------------------------------------
2
2
* formatting.c
3
3
*
4
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.142 2008/06/17 16:09:06 momjian Exp $
4
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.143 2008/06/23 19:27:19 momjian Exp $
5
5
*
6
6
*
7
7
* Portions Copyright (c) 1999-2008, PostgreSQL Global Development Group
@@ -925,9 +925,6 @@ static char *get_th(char *num, int type);
925
925
static char * str_numth (char * dest , char * num , int type );
926
926
static int strspace_len (char * str );
927
927
static int strdigits_len (char * str );
928
- static char * str_toupper (char * buff );
929
- static char * str_tolower (char * buff );
930
- static char * str_initcap (char * buff );
931
928
932
929
static int seq_search (char * name , char * * array , int type , int max , int * len );
933
930
static void do_to_timestamp (text * date_txt , text * fmt ,
@@ -1424,12 +1421,24 @@ str_numth(char *dest, char *num, int type)
1424
1421
return dest ;
1425
1422
}
1426
1423
1424
+ /*
1425
+ * If the system provides the needed functions for wide-character manipulation
1426
+ * (which are all standardized by C99), then we implement upper/lower/initcap
1427
+ * using wide-character functions, if necessary. Otherwise we use the
1428
+ * traditional <ctype.h> functions, which of course will not work as desired
1429
+ * in multibyte character sets. Note that in either case we are effectively
1430
+ * assuming that the database character encoding matches the encoding implied
1431
+ * by LC_CTYPE.
1432
+ */
1433
+
1427
1434
/* ----------
1428
- * Convert string to upper case. It is designed to be multibyte-aware.
1435
+ * wide-character-aware lower function
1436
+ * We pass the number of bytes so we can pass varlena and char*
1437
+ * to this function.
1429
1438
* ----------
1430
1439
*/
1431
- static char *
1432
- str_toupper (char * buff )
1440
+ char *
1441
+ str_tolower (char * buff , size_t nbytes )
1433
1442
{
1434
1443
char * result ;
1435
1444
@@ -1438,27 +1447,46 @@ str_toupper(char *buff)
1438
1447
1439
1448
#ifdef USE_WIDE_UPPER_LOWER
1440
1449
if (pg_database_encoding_max_length () > 1 && !lc_ctype_is_c ())
1441
- result = wstring_upper (buff );
1450
+ {
1451
+ wchar_t * workspace ;
1452
+ int curr_char = 0 ;
1453
+
1454
+ /* Output workspace cannot have more codes than input bytes */
1455
+ workspace = (wchar_t * ) palloc ((nbytes + 1 ) * sizeof (wchar_t ));
1456
+
1457
+ char2wchar (workspace , nbytes + 1 , buff , nbytes + 1 );
1458
+
1459
+ for (curr_char = 0 ; workspace [curr_char ] != 0 ; curr_char ++ )
1460
+ workspace [curr_char ] = towlower (workspace [curr_char ]);
1461
+
1462
+ /* Make result large enough; case change might change number of bytes */
1463
+ result = palloc (curr_char * MB_CUR_MAX + 1 );
1464
+
1465
+ wchar2char (result , workspace , curr_char * MB_CUR_MAX + 1 );
1466
+ pfree (workspace );
1467
+ }
1442
1468
else
1443
1469
#endif /* USE_WIDE_UPPER_LOWER */
1444
1470
{
1445
1471
char * p ;
1446
1472
1447
- result = pstrdup (buff );
1473
+ result = pnstrdup (buff , nbytes );
1448
1474
1449
1475
for (p = result ; * p ; p ++ )
1450
- * p = pg_toupper ((unsigned char ) * p );
1476
+ * p = pg_tolower ((unsigned char ) * p );
1451
1477
}
1452
1478
1453
1479
return result ;
1454
1480
}
1455
1481
1456
1482
/* ----------
1457
- * Convert string to lower case. It is designed to be multibyte-aware.
1483
+ * wide-character-aware upper function
1484
+ * We pass the number of bytes so we can pass varlena and char*
1485
+ * to this function.
1458
1486
* ----------
1459
1487
*/
1460
- static char *
1461
- str_tolower (char * buff )
1488
+ char *
1489
+ str_toupper (char * buff , size_t nbytes )
1462
1490
{
1463
1491
char * result ;
1464
1492
@@ -1467,27 +1495,46 @@ str_tolower(char *buff)
1467
1495
1468
1496
#ifdef USE_WIDE_UPPER_LOWER
1469
1497
if (pg_database_encoding_max_length () > 1 && !lc_ctype_is_c ())
1470
- result = wstring_lower (buff );
1498
+ {
1499
+ wchar_t * workspace ;
1500
+ int curr_char = 0 ;
1501
+
1502
+ /* Output workspace cannot have more codes than input bytes */
1503
+ workspace = (wchar_t * ) palloc ((nbytes + 1 ) * sizeof (wchar_t ));
1504
+
1505
+ char2wchar (workspace , nbytes + 1 , buff , nbytes + 1 );
1506
+
1507
+ for (curr_char = 0 ; workspace [curr_char ] != 0 ; curr_char ++ )
1508
+ workspace [curr_char ] = towupper (workspace [curr_char ]);
1509
+
1510
+ /* Make result large enough; case change might change number of bytes */
1511
+ result = palloc (curr_char * MB_CUR_MAX + 1 );
1512
+
1513
+ wchar2char (result , workspace , curr_char * MB_CUR_MAX + 1 );
1514
+ pfree (workspace );
1515
+ }
1471
1516
else
1472
1517
#endif /* USE_WIDE_UPPER_LOWER */
1473
1518
{
1474
1519
char * p ;
1475
1520
1476
- result = pstrdup (buff );
1521
+ result = pnstrdup (buff , nbytes );
1477
1522
1478
1523
for (p = result ; * p ; p ++ )
1479
- * p = pg_tolower ((unsigned char ) * p );
1524
+ * p = pg_toupper ((unsigned char ) * p );
1480
1525
}
1481
1526
1482
1527
return result ;
1483
1528
}
1484
-
1529
+
1485
1530
/* ----------
1486
1531
* wide-character-aware initcap function
1532
+ * We pass the number of bytes so we can pass varlena and char*
1533
+ * to this function.
1487
1534
* ----------
1488
1535
*/
1489
- static char *
1490
- str_initcap (char * buff )
1536
+ char *
1537
+ str_initcap (char * buff , size_t nbytes )
1491
1538
{
1492
1539
char * result ;
1493
1540
bool wasalnum = false;
@@ -1499,35 +1546,34 @@ str_initcap(char *buff)
1499
1546
if (pg_database_encoding_max_length () > 1 && !lc_ctype_is_c ())
1500
1547
{
1501
1548
wchar_t * workspace ;
1502
- text * in_text ;
1503
- text * out_text ;
1504
- int i ;
1549
+ int curr_char = 0 ;
1550
+
1551
+ /* Output workspace cannot have more codes than input bytes */
1552
+ workspace = (wchar_t * ) palloc ((nbytes + 1 ) * sizeof (wchar_t ));
1505
1553
1506
- in_text = cstring_to_text (buff );
1507
- workspace = texttowcs (in_text );
1554
+ char2wchar (workspace , nbytes + 1 , buff , nbytes + 1 );
1508
1555
1509
- for (i = 0 ; workspace [i ] != 0 ; i ++ )
1556
+ for (curr_char = 0 ; workspace [curr_char ] != 0 ; curr_char ++ )
1510
1557
{
1511
1558
if (wasalnum )
1512
- workspace [i ] = towlower (workspace [i ]);
1559
+ workspace [curr_char ] = towlower (workspace [curr_char ]);
1513
1560
else
1514
- workspace [i ] = towupper (workspace [i ]);
1515
- wasalnum = iswalnum (workspace [i ]);
1561
+ workspace [curr_char ] = towupper (workspace [curr_char ]);
1562
+ wasalnum = iswalnum (workspace [curr_char ]);
1516
1563
}
1517
1564
1518
- out_text = wcstotext ( workspace , i );
1519
- result = text_to_cstring ( out_text );
1565
+ /* Make result large enough; case change might change number of bytes */
1566
+ result = palloc ( curr_char * MB_CUR_MAX + 1 );
1520
1567
1568
+ wchar2char (result , workspace , curr_char * MB_CUR_MAX + 1 );
1521
1569
pfree (workspace );
1522
- pfree (in_text );
1523
- pfree (out_text );
1524
1570
}
1525
1571
else
1526
1572
#endif /* USE_WIDE_UPPER_LOWER */
1527
1573
{
1528
1574
char * p ;
1529
1575
1530
- result = pstrdup (buff );
1576
+ result = pnstrdup (buff , nbytes );
1531
1577
1532
1578
for (p = result ; * p ; p ++ )
1533
1579
{
@@ -1851,7 +1897,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1851
1897
{
1852
1898
char * p = pstrdup (tmtcTzn (in ));
1853
1899
1854
- strcpy (s , str_tolower (p ));
1900
+ strcpy (s , str_tolower (p , strlen ( p ) ));
1855
1901
pfree (p );
1856
1902
s += strlen (s );
1857
1903
}
@@ -1893,11 +1939,13 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1893
1939
if (!tm -> tm_mon )
1894
1940
break ;
1895
1941
if (S_TM (n -> suffix ))
1896
- strcpy (s , str_toupper (localized_full_months [tm -> tm_mon - 1 ]));
1942
+ strcpy (s , str_toupper (localized_full_months [tm -> tm_mon - 1 ],
1943
+ strlen (localized_full_months [tm -> tm_mon - 1 ])));
1897
1944
else
1898
1945
{
1899
1946
strcpy (workbuff , months_full [tm -> tm_mon - 1 ]);
1900
- sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 , str_toupper (workbuff ));
1947
+ sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 ,
1948
+ str_toupper (workbuff , strlen (workbuff )));
1901
1949
}
1902
1950
s += strlen (s );
1903
1951
break ;
@@ -1906,7 +1954,8 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1906
1954
if (!tm -> tm_mon )
1907
1955
break ;
1908
1956
if (S_TM (n -> suffix ))
1909
- strcpy (s , str_initcap (localized_full_months [tm -> tm_mon - 1 ]));
1957
+ strcpy (s , str_initcap (localized_full_months [tm -> tm_mon - 1 ],
1958
+ strlen (localized_full_months [tm -> tm_mon - 1 ])));
1910
1959
else
1911
1960
sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 , months_full [tm -> tm_mon - 1 ]);
1912
1961
s += strlen (s );
@@ -1916,7 +1965,8 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1916
1965
if (!tm -> tm_mon )
1917
1966
break ;
1918
1967
if (S_TM (n -> suffix ))
1919
- strcpy (s , str_tolower (localized_full_months [tm -> tm_mon - 1 ]));
1968
+ strcpy (s , str_tolower (localized_full_months [tm -> tm_mon - 1 ],
1969
+ strlen (localized_full_months [tm -> tm_mon - 1 ])));
1920
1970
else
1921
1971
{
1922
1972
sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 , months_full [tm -> tm_mon - 1 ]);
@@ -1929,17 +1979,20 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1929
1979
if (!tm -> tm_mon )
1930
1980
break ;
1931
1981
if (S_TM (n -> suffix ))
1932
- strcpy (s , str_toupper (localized_abbrev_months [tm -> tm_mon - 1 ]));
1982
+ strcpy (s , str_toupper (localized_abbrev_months [tm -> tm_mon - 1 ],
1983
+ strlen (localized_abbrev_months [tm -> tm_mon - 1 ])));
1933
1984
else
1934
- strcpy (s , str_toupper (months [tm -> tm_mon - 1 ]));
1985
+ strcpy (s , str_toupper (months [tm -> tm_mon - 1 ],
1986
+ strlen (months [tm -> tm_mon - 1 ])));
1935
1987
s += strlen (s );
1936
1988
break ;
1937
1989
case DCH_Mon :
1938
1990
INVALID_FOR_INTERVAL ;
1939
1991
if (!tm -> tm_mon )
1940
1992
break ;
1941
1993
if (S_TM (n -> suffix ))
1942
- strcpy (s , str_initcap (localized_abbrev_months [tm -> tm_mon - 1 ]));
1994
+ strcpy (s , str_initcap (localized_abbrev_months [tm -> tm_mon - 1 ],
1995
+ strlen (localized_abbrev_months [tm -> tm_mon - 1 ])));
1943
1996
else
1944
1997
strcpy (s , months [tm -> tm_mon - 1 ]);
1945
1998
s += strlen (s );
@@ -1949,7 +2002,8 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1949
2002
if (!tm -> tm_mon )
1950
2003
break ;
1951
2004
if (S_TM (n -> suffix ))
1952
- strcpy (s , str_tolower (localized_abbrev_months [tm -> tm_mon - 1 ]));
2005
+ strcpy (s , str_tolower (localized_abbrev_months [tm -> tm_mon - 1 ],
2006
+ strlen (localized_abbrev_months [tm -> tm_mon - 1 ])));
1953
2007
else
1954
2008
{
1955
2009
strcpy (s , months [tm -> tm_mon - 1 ]);
@@ -1966,26 +2020,30 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1966
2020
case DCH_DAY :
1967
2021
INVALID_FOR_INTERVAL ;
1968
2022
if (S_TM (n -> suffix ))
1969
- strcpy (s , str_toupper (localized_full_days [tm -> tm_wday ]));
2023
+ strcpy (s , str_toupper (localized_full_days [tm -> tm_wday ],
2024
+ strlen (localized_full_days [tm -> tm_wday ])));
1970
2025
else
1971
2026
{
1972
2027
strcpy (workbuff , days [tm -> tm_wday ]);
1973
- sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 , str_toupper (workbuff ));
2028
+ sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 ,
2029
+ str_toupper (workbuff , strlen (workbuff )));
1974
2030
}
1975
2031
s += strlen (s );
1976
2032
break ;
1977
2033
case DCH_Day :
1978
2034
INVALID_FOR_INTERVAL ;
1979
2035
if (S_TM (n -> suffix ))
1980
- strcpy (s , str_initcap (localized_full_days [tm -> tm_wday ]));
2036
+ strcpy (s , str_initcap (localized_full_days [tm -> tm_wday ],
2037
+ strlen (localized_full_days [tm -> tm_wday ])));
1981
2038
else
1982
2039
sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 , days [tm -> tm_wday ]);
1983
2040
s += strlen (s );
1984
2041
break ;
1985
2042
case DCH_day :
1986
2043
INVALID_FOR_INTERVAL ;
1987
2044
if (S_TM (n -> suffix ))
1988
- strcpy (s , str_tolower (localized_full_days [tm -> tm_wday ]));
2045
+ strcpy (s , str_tolower (localized_full_days [tm -> tm_wday ],
2046
+ strlen (localized_full_days [tm -> tm_wday ])));
1989
2047
else
1990
2048
{
1991
2049
sprintf (s , "%*s" , S_FM (n -> suffix ) ? 0 : -9 , days [tm -> tm_wday ]);
@@ -1996,23 +2054,27 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out)
1996
2054
case DCH_DY :
1997
2055
INVALID_FOR_INTERVAL ;
1998
2056
if (S_TM (n -> suffix ))
1999
- strcpy (s , str_toupper (localized_abbrev_days [tm -> tm_wday ]));
2057
+ strcpy (s , str_toupper (localized_abbrev_days [tm -> tm_wday ],
2058
+ strlen (localized_abbrev_days [tm -> tm_wday ])));
2000
2059
else
2001
- strcpy (s , str_toupper (days_short [tm -> tm_wday ]));
2060
+ strcpy (s , str_toupper (days_short [tm -> tm_wday ],
2061
+ strlen (days_short [tm -> tm_wday ])));
2002
2062
s += strlen (s );
2003
2063
break ;
2004
2064
case DCH_Dy :
2005
2065
INVALID_FOR_INTERVAL ;
2006
2066
if (S_TM (n -> suffix ))
2007
- strcpy (s , str_initcap (localized_abbrev_days [tm -> tm_wday ]));
2067
+ strcpy (s , str_initcap (localized_abbrev_days [tm -> tm_wday ],
2068
+ strlen (localized_abbrev_days [tm -> tm_wday ])));
2008
2069
else
2009
2070
strcpy (s , days_short [tm -> tm_wday ]);
2010
2071
s += strlen (s );
2011
2072
break ;
2012
2073
case DCH_dy :
2013
2074
INVALID_FOR_INTERVAL ;
2014
2075
if (S_TM (n -> suffix ))
2015
- strcpy (s , str_tolower (localized_abbrev_days [tm -> tm_wday ]));
2076
+ strcpy (s , str_tolower (localized_abbrev_days [tm -> tm_wday ],
2077
+ strlen (localized_abbrev_days [tm -> tm_wday ])));
2016
2078
else
2017
2079
{
2018
2080
strcpy (s , days_short [tm -> tm_wday ]);
@@ -4277,12 +4339,14 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
4277
4339
case NUM_rn :
4278
4340
if (IS_FILLMODE (Np -> Num ))
4279
4341
{
4280
- strcpy (Np -> inout_p , str_tolower (Np -> number_p ));
4342
+ strcpy (Np -> inout_p , str_tolower (Np -> number_p ,
4343
+ strlen (Np -> number_p )));
4281
4344
Np -> inout_p += strlen (Np -> inout_p ) - 1 ;
4282
4345
}
4283
4346
else
4284
4347
{
4285
- sprintf (Np -> inout_p , "%15s" , str_tolower (Np -> number_p ));
4348
+ sprintf (Np -> inout_p , "%15s" , str_tolower (Np -> number_p ,
4349
+ strlen (Np -> number_p )));
4286
4350
Np -> inout_p += strlen (Np -> inout_p ) - 1 ;
4287
4351
}
4288
4352
break ;
0 commit comments