Commit aa53f832 by Paolo Carlini Committed by Benjamin Kosnik

localefwd.h (class locale): Add static member _S_num_extra_categories...


2002-10-08  Paolo Carlini  <pcarlini@unitus.it>
	    Benjamin Kosnik  <bkoz@redhat.com>

	* include/bits/localefwd.h (class locale): Add static member
	_S_num_extra_categories, encoding the number of additional
	categories.
	Change _S_num_categories to _S_categories_size.
	(class locale::_Impl): Add _M_c_cats.
	(class locale::_Impl::_M_names): Change to array of chars.
	(class locale::_Impl::_M_check_same_name): Use
	_S_extra_categories_size, tweak.
	(locale::locale(const locale&, _Facet*)): Ditto.
    	* src/locale.cc (locale::locale(const char* )): Rewrite to deal
	with the environment in a POSIX-compliant way while being thread
	safe.
	(locale::name()): Update to output POSIX environment strings.
	* src/localename.cc
	(locale::_Impl::_Impl(const _Impl&, size_t): Use
	_S_categories_size_*, tweak.
	(locale::_Impl::_Impl(facet**, size_t, bool)): Ditto.
	(locale::_Impl::_Impl(const char*, size_t)): Name each category
	individually.
	(locale::_Impl::_M_replace_categories): Use strcpy.

	* include/bits/locale_facets.h (numpunct::_M_initialize_numpunct):
	Change default argument to NULL from _S_c_locale.
	(timepunct::_M_initialize_timepunct): Same.
	_S_c_locale cleanups.
	* src/codecvt.c: _S_c_locale simplification.
	* src/ctype.c: Same.
	* src/globals.cc: Add fake_name.
	* src/locale-inst.cc: Remove extra includes.
	* src/locale.cc: Remove extra includes.
	Add _S_extra_categories_size definition.
	Correct "C" initialization.
	(locale::facet::facet): Don't initialize _S_c_locale.
	(locale::facet::_M_remove_reference): Adjust.
	* src/localename: Use facet_vec, facet_name.
	(locale::_Impl::_Impl(facet** __f, size_t __refs, bool)): Set
	facet ref counts to one. Initialize _S_c_locale.
	(locale::_Impl::_M_install_facet(id*, facet*)): Adjust facet ref
	counts when installing unilaterally.

	* config/locale/generic/c_locale.cc: Add _S_categories definition.
	* config/locale/generic/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
	* config/locale/generic/time_members.cc: _S_c_locale cleanup.

	* config/locale/gnu/c_locale.cc: Add _S_categories definition.
	(_S_destroy_c_locale): Move checks against _S_c_locale here.
	* config/locale/gnu/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
	* config/locale/gnu/ctype_members.cc: Simplify _S_destroy_c_locale
	calls, _S_c_locale usage.
	* config/locale/gnu/monetary_members.cc: Same, tweaks.
	* config/locale/gnu/monetary_members.cc: Same.
	* config/locale/gnu/time_members.cc: Same.
	* config/os/gnu-linux/ctype_noninline.h: Use locale::classic().

	* docs/html/22_locale/locale.html: Add bits about global locales
	and "C" setlocale.

	* testsuite/22_locale/facet.cc (test02): Add.
	* testsuite/22_locale/static_members.cc (test02): Add.
	* testsuite/22_locale/ctor_copy_dtor.cc (test04): Add.

Co-Authored-By: Benjamin Kosnik <bkoz@redhat.com>

From-SVN: r57964
parent 131d2c16
2002-10-08 Paolo Carlini <pcarlini@unitus.it>
Benjamin Kosnik <bkoz@redhat.com>
* include/bits/localefwd.h (class locale): Add static member
_S_num_extra_categories, encoding the number of additional
categories.
Change _S_num_categories to _S_categories_size.
(class locale::_Impl): Add _M_c_cats.
(class locale::_Impl::_M_names): Change to array of chars.
(class locale::_Impl::_M_check_same_name): Use
_S_extra_categories_size, tweak.
(locale::locale(const locale&, _Facet*)): Ditto.
* src/locale.cc (locale::locale(const char* )): Rewrite to deal
with the environment in a POSIX-compliant way while being thread
safe.
(locale::name()): Update to output POSIX environment strings.
* src/localename.cc
(locale::_Impl::_Impl(const _Impl&, size_t): Use
_S_categories_size_*, tweak.
(locale::_Impl::_Impl(facet**, size_t, bool)): Ditto.
(locale::_Impl::_Impl(const char*, size_t)): Name each category
individually.
(locale::_Impl::_M_replace_categories): Use strcpy.
* include/bits/locale_facets.h (numpunct::_M_initialize_numpunct):
Change default argument to NULL from _S_c_locale.
(timepunct::_M_initialize_timepunct): Same.
_S_c_locale cleanups.
* src/codecvt.c: _S_c_locale simplification.
* src/ctype.c: Same.
* src/globals.cc: Add fake_name.
* src/locale-inst.cc: Remove extra includes.
* src/locale.cc: Remove extra includes.
Add _S_extra_categories_size definition.
Correct "C" initialization.
(locale::facet::facet): Don't initialize _S_c_locale.
(locale::facet::_M_remove_reference): Adjust.
* src/localename: Use facet_vec, facet_name.
(locale::_Impl::_Impl(facet** __f, size_t __refs, bool)): Set
facet ref counts to one. Initialize _S_c_locale.
(locale::_Impl::_M_install_facet(id*, facet*)): Adjust facet ref
counts when installing unilaterally.
* config/locale/generic/c_locale.cc: Add _S_categories definition.
* config/locale/generic/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
* config/locale/generic/time_members.cc: _S_c_locale cleanup.
* config/locale/gnu/c_locale.cc: Add _S_categories definition.
(_S_destroy_c_locale): Move checks against _S_c_locale here.
* config/locale/gnu/c_locale.h: Add _GLIBCPP_NUM_CATEGORIES macro.
* config/locale/gnu/ctype_members.cc: Simplify _S_destroy_c_locale
calls, _S_c_locale usage.
* config/locale/gnu/monetary_members.cc: Same, tweaks.
* config/locale/gnu/monetary_members.cc: Same.
* config/locale/gnu/time_members.cc: Same.
* config/os/gnu-linux/ctype_noninline.h: Use locale::classic().
* docs/html/22_locale/locale.html: Add bits about global locales
and "C" setlocale.
* testsuite/22_locale/facet.cc (test02): Add.
* testsuite/22_locale/static_members.cc (test02): Add.
* testsuite/22_locale/ctor_copy_dtor.cc (test04): Add.
2002-10-07 Jonathan Wakely <jw@kayari.org>
* docs/html/configopts.html, docs/html/documentation.html,
......
......@@ -223,4 +223,15 @@ namespace std
__c_locale
locale::facet::_S_clone_c_locale(__c_locale&)
{ return __c_locale(); }
const char* locale::_S_categories[_S_categories_size
+ _S_extra_categories_size] =
{
"LC_CTYPE",
"LC_NUMERIC",
"LC_COLLATE",
"LC_TIME",
"LC_MONETARY",
"LC_MESSAGES"
};
} // namespace std
......@@ -35,6 +35,8 @@
#include <clocale>
#define _GLIBCPP_NUM_CATEGORIES 0
namespace std
{
typedef int* __c_locale;
......
......@@ -40,10 +40,7 @@ namespace std
{
template<>
__timepunct<char>::~__timepunct()
{
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
{ _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
......@@ -123,10 +120,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
__timepunct<wchar_t>::~__timepunct()
{
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
{ _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
......
......@@ -178,9 +178,29 @@ namespace std
void
locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
{ __freelocale(__cloc); }
{
if (_S_c_locale != __cloc)
__freelocale(__cloc);
}
__c_locale
locale::facet::_S_clone_c_locale(__c_locale& __cloc)
{ return __duplocale(__cloc); }
const char* locale::_S_categories[_S_categories_size
+ _S_extra_categories_size] =
{
"LC_CTYPE",
"LC_NUMERIC",
"LC_COLLATE",
"LC_TIME",
"LC_MONETARY",
"LC_MESSAGES",
"LC_PAPER",
"LC_NAME",
"LC_ADDRESS",
"LC_TELEPHONE",
"LC_MEASUREMENT",
"LC_IDENTIFICATION"
};
} // namespace std
......@@ -40,6 +40,8 @@
#define _GLIBCPP_C_LOCALE_GNU 1
#define _GLIBCPP_NUM_CATEGORIES 6
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
namespace __gnu_cxx
{
......
......@@ -44,8 +44,7 @@ namespace std
ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
: ctype<char>(0, false, __refs)
{
if (_M_c_locale_ctype != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_ctype);
_S_destroy_c_locale(_M_c_locale_ctype);
_S_create_c_locale(_M_c_locale_ctype, __s);
_M_toupper = _M_c_locale_ctype->__ctype_toupper;
_M_tolower = _M_c_locale_ctype->__ctype_tolower;
......
......@@ -220,7 +220,7 @@ namespace std
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char*)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
......@@ -265,7 +265,7 @@ namespace std
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char*)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
......@@ -319,7 +319,7 @@ namespace std
moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
const char* __name)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
......@@ -348,14 +348,12 @@ namespace std
_M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
mbstate_t __state;
size_t __len;
const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
// NB: Should swich to __cloc's ctype info first.
__len = strlen(__cpossign);
mbstate_t __state;
size_t __len = strlen(__cpossign);
if (__len)
{
++__len;
......@@ -418,7 +416,7 @@ namespace std
moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
const char* __name)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
......@@ -446,13 +444,12 @@ namespace std
_M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
mbstate_t __state;
size_t __len;
const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
// NB: Should swich to __cloc's ctype info first.
mbstate_t __state;
size_t __len;
__len = strlen(__cpossign);
if (__len)
{
......
......@@ -42,7 +42,7 @@ namespace std
void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
......@@ -76,7 +76,7 @@ namespace std
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
......
......@@ -41,10 +41,7 @@ namespace std
{
template<>
__timepunct<char>::~__timepunct()
{
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
{ _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
......@@ -67,11 +64,10 @@ namespace std
void
__timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_c_locale_timepunct = _S_c_locale;
_M_c_locale_timepunct = _S_c_locale;
_M_date_format = "%m/%d/%y";
_M_date_era_format = "%m/%d/%y";
......@@ -194,10 +190,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
__timepunct<wchar_t>::~__timepunct()
{
if (_M_c_locale_timepunct != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_timepunct);
}
{ _S_destroy_c_locale(_M_c_locale_timepunct); }
template<>
void
......@@ -220,11 +213,10 @@ namespace std
void
__timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
{
if (__cloc == _S_c_locale)
if (!__cloc)
{
// "C" locale
_M_c_locale_timepunct = _S_c_locale;
_M_c_locale_timepunct = _S_c_locale;
_M_date_format = L"%m/%d/%y";
_M_date_era_format = L"%m/%d/%y";
......
......@@ -38,8 +38,7 @@
const ctype_base::mask*
ctype<char>::classic_table() throw()
{
if (!_S_c_locale)
_S_create_c_locale(_S_c_locale, "C");
locale::classic();
return _S_c_locale->__ctype_b;
}
#else
......@@ -96,7 +95,7 @@
ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) :
__ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del)
{
_M_c_locale_ctype = _S_c_locale;
_M_c_locale_ctype = _S_c_locale;
_M_toupper = _M_c_locale_ctype->__ctype_toupper;
_M_tolower = _M_c_locale_ctype->__ctype_tolower;
_M_table = __table ? __table : _M_c_locale_ctype->__ctype_b;
......
......@@ -68,14 +68,36 @@ public:
The only other thing of interest in this class is the memory
management of facets. Each constructor of a facet class takes a
std::size_t __refs argument: if __refs == 0, the facet is deleted when
no longer used. if __refs == 1, the facet is not destroyed, even when
it is no longer reference.
the locale containing it is destroyed. If __refs == 1, the facet is
not destroyed, even when it is no longer referenced.
class id
Provides an index for looking up specific facets.
class _Impl
The internal representation of the std::locale object.
<h2>
5. Relationship to traditional "C" locales.
</h2>
From Josuttis, p. 697-698, which says, that "there is only *one*
relation (of the C++ locale mechanism) to the C locale mechanism: the
global C locale is modified if a named C++ locale object is set as the
global locale" (emphasis Paolo), that is:
std::locale::global(std::locale(""));
affects the C functions as if the following call was made:
std::setlocale(LC_ALL, "");
On the other hand, there is *no* viceversa, that is, calling setlocale
has *no* whatsoever on the C++ locale mechanism, in particular on the
working of locale(""), which constructs the locale object from the
environment of the running program, that is, in practice, the set of
LC_ALL, LANG, etc. variable of the shell.
<h2>
5. Examples
......@@ -87,8 +109,7 @@ class _Impl
More information can be found in the following testcases:
<ul>
<li> testsuite/22_locale/ctype_char_members.cc </li>
<li> testsuite/22_locale/ctype_wchar_t_members.cc </li>
<li> testsuite/22_locale/all </li>
</ul>
<h2>
......
......@@ -525,7 +525,7 @@ namespace std
// For use at construction time only.
void
_M_initialize_numpunct(__c_locale __cloc = _S_c_locale);
_M_initialize_numpunct(__c_locale __cloc = NULL);
};
template<typename _CharT>
......@@ -875,10 +875,7 @@ namespace std
protected:
virtual
~collate()
{
if (_M_c_locale_collate != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_collate);
}
{ _S_destroy_c_locale(_M_c_locale_collate); }
virtual int
do_compare(const _CharT* __lo1, const _CharT* __hi1,
......@@ -924,8 +921,7 @@ namespace std
collate_byname(const char* __s, size_t __refs = 0)
: collate<_CharT>(__refs)
{
if (_M_c_locale_collate != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_collate);
_S_destroy_c_locale(_M_c_locale_collate);
_S_create_c_locale(_M_c_locale_collate, __s);
}
......@@ -1123,7 +1119,7 @@ namespace std
// For use at construction time only.
void
_M_initialize_timepunct(__c_locale __cloc = _S_c_locale);
_M_initialize_timepunct(__c_locale __cloc = NULL);
};
template<typename _CharT>
......@@ -1459,7 +1455,7 @@ namespace std
// For use at construction time only.
void
_M_initialize_moneypunct(__c_locale __cloc = _S_c_locale,
_M_initialize_moneypunct(__c_locale __cloc = NULL,
const char* __name = NULL);
};
......@@ -1667,10 +1663,7 @@ namespace std
protected:
virtual
~messages()
{
if (_M_c_locale_messages != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_messages);
}
{ _S_destroy_c_locale(_M_c_locale_messages); }
virtual catalog
do_open(const basic_string<char>&, const locale&) const;
......@@ -1759,8 +1752,7 @@ namespace std
: messages<_CharT>(__refs)
{
_M_name_messages = __s;
if (_M_c_locale_messages != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_messages);
_S_destroy_c_locale(_M_c_locale_messages);
_S_create_c_locale(_M_c_locale_messages, __s);
}
......
......@@ -207,8 +207,8 @@ namespace std
static const category time = 1L << 3;
static const category monetary = 1L << 4;
static const category messages = 1L << 5;
static const category all = (collate | ctype | monetary |
numeric | time | messages);
static const category all = (ctype | numeric | collate |
time | monetary | messages);
// Construct/copy/destroy:
locale() throw();
......@@ -267,7 +267,26 @@ namespace std
// Current global reference locale
static _Impl* _S_global;
static const size_t _S_num_categories = 6;
// Number of standard categories. For C++, these categories are
// collate, ctype, monetary, numeric, time, and messages. These
// directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
// LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
// 1003.1-2001) specifies LC_MESSAGES.
static const size_t _S_categories_size = 6;
// In addition to the standard categories, the underlying
// operating system is allowed to define extra LC_*
// macros. For GNU systems, the following are also valid:
// LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
// and LC_IDENTIFICATION.
static const size_t _S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES;
// Names of underlying locale categories.
// NB: locale::global() has to know how to modify all the
// underlying categories, not just the ones required by the C++
// standard.
static const char* _S_categories[_S_categories_size
+ _S_extra_categories_size];
explicit
locale(_Impl*) throw();
......@@ -308,7 +327,9 @@ namespace std
_Atomic_word _M_references;
facet** _M_facets;
size_t _M_facets_size;
const char* _M_names[_S_num_categories];
char* _M_names[_S_categories_size
+ _S_extra_categories_size];
static const locale::id* const _S_id_ctype[];
static const locale::id* const _S_id_numeric[];
static const locale::id* const _S_id_collate[];
......@@ -348,8 +369,10 @@ namespace std
_M_check_same_name()
{
bool __ret = true;
for (size_t i = 0; __ret && i < _S_num_categories - 1; ++i)
__ret &= (strcmp(_M_names[i], _M_names[i + 1]) == 0);
for (size_t __i = 0;
__ret && __i < _S_categories_size + _S_extra_categories_size - 1;
++__i)
__ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
return __ret;
}
......@@ -376,8 +399,14 @@ namespace std
{
_M_impl = new _Impl(*__other._M_impl, 1);
_M_impl->_M_install_facet(&_Facet::id, __f);
for (size_t __i = 0; __i < _S_num_categories; ++__i)
_M_impl->_M_names[__i] = "*";
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
{
delete [] _M_impl->_M_names[__i];
char* __new = new char[2];
strcpy(__new, "*");
_M_impl->_M_names[__i] = __new;
}
}
// 22.1.1.1.2 Class locale::facet
......
......@@ -55,10 +55,7 @@ namespace std
codecvt<char, char, mbstate_t>::
~codecvt()
{
if (_M_c_locale_codecvt != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_codecvt);
}
{ _S_destroy_c_locale(_M_c_locale_codecvt); }
codecvt_base::result
codecvt<char, char, mbstate_t>::
......@@ -123,7 +120,7 @@ namespace std
codecvt<wchar_t, char, mbstate_t>::
codecvt(size_t __refs)
: __codecvt_abstract_base<wchar_t, char, mbstate_t>(__refs)
{ _M_c_locale_codecvt = _S_c_locale; }
{ _M_c_locale_codecvt = _S_c_locale; }
codecvt<wchar_t, char, mbstate_t>::
codecvt(__c_locale __cloc, size_t __refs)
......@@ -132,10 +129,7 @@ namespace std
codecvt<wchar_t, char, mbstate_t>::
~codecvt()
{
if (_M_c_locale_codecvt != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_codecvt);
}
{ _S_destroy_c_locale(_M_c_locale_codecvt); }
codecvt_base::result
codecvt<wchar_t, char, mbstate_t>::
......
......@@ -79,8 +79,7 @@ namespace std
ctype<char>::~ctype()
{
if (_M_c_locale_ctype != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_ctype);
_S_destroy_c_locale(_M_c_locale_ctype);
if (_M_del)
delete[] this->table();
}
......@@ -135,17 +134,13 @@ namespace std
{ _M_c_locale_ctype = _S_clone_c_locale(__cloc); }
ctype<wchar_t>::~ctype()
{
if (_M_c_locale_ctype != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_ctype);
}
{ _S_destroy_c_locale(_M_c_locale_ctype); }
template<>
ctype_byname<wchar_t>::ctype_byname(const char* __s, size_t __refs)
: ctype<wchar_t>(__refs)
{
if (_M_c_locale_ctype != _S_c_locale)
_S_destroy_c_locale(_M_c_locale_ctype);
_S_destroy_c_locale(_M_c_locale_ctype);
_S_create_c_locale(_M_c_locale_ctype, __s);
}
#endif
......
......@@ -59,6 +59,10 @@ namespace std
__attribute__ ((aligned(__alignof__(locale::facet*))));
fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS];
typedef char fake_facet_name[sizeof(char*)]
__attribute__ ((aligned(__alignof__(char*))));
fake_facet_name facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
typedef char fake_ctype_c[sizeof(std::ctype<char>)]
__attribute__ ((aligned(__alignof__(std::ctype<char>))));
fake_ctype_c ctype_c;
......@@ -200,7 +204,6 @@ namespace std
fake_wfilebuf buf_wcerr;
#endif
// Globals for once-only runtime initialization of mutex objects. This
// allows static initialization of these objects on systems that need a
// function call to initialize a mutex. For example, see stl_threads.h.
......
......@@ -35,11 +35,7 @@
#include <clocale>
#include <cstring>
#include <cassert>
#include <limits>
#include <exception>
#include <locale>
#include <istream>
#include <ostream>
namespace std
{
......
......@@ -31,11 +31,7 @@
#include <cassert>
#include <cctype>
#include <cwctype> // For towupper, etc.
#include <limits>
#include <exception>
#include <locale>
#include <istream>
#include <ostream>
#include <bits/atomicity.h>
namespace std
......@@ -43,7 +39,6 @@ namespace std
// Defined in globals.cc.
extern locale c_locale;
extern locale::_Impl c_locale_impl;
extern locale::facet** facet_vec;
// Definitions for static const data members of locale.
const locale::category locale::none;
......@@ -57,7 +52,8 @@ namespace std
locale::_Impl* locale::_S_classic;
locale::_Impl* locale::_S_global;
const size_t locale::_S_num_categories;
const size_t locale::_S_categories_size;
const size_t locale::_S_extra_categories_size;
// Definitions for static const data members of locale::id
_Atomic_word locale::id::_S_highwater; // init'd to 0 by linker
......@@ -146,8 +142,8 @@ namespace std
locale::_Impl::_S_id_ctype,
locale::_Impl::_S_id_numeric,
locale::_Impl::_S_id_collate,
locale::_Impl::_S_id_monetary,
locale::_Impl::_S_id_time,
locale::_Impl::_S_id_monetary,
locale::_Impl::_S_id_messages,
0
};
......@@ -192,18 +188,110 @@ namespace std
_S_initialize();
if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
(_M_impl = _S_classic)->_M_add_reference();
else if (strcmp(__s, "") == 0)
else if (strcmp(__s, "") != 0)
_M_impl = new _Impl(__s, 1);
else
{
// Get it from the environment.
char* __env = getenv("LC_ALL");
if (__env)
_M_impl = new _Impl(__env, 1);
else if ((__env = getenv("LANG")))
_M_impl = new _Impl(__env, 1);
// If LC_ALL is set we are done.
if (__env && strcmp(__env, "") != 0)
{
if (strcmp(__env, "C") == 0 || strcmp(__env, "POSIX") == 0)
(_M_impl = _S_classic)->_M_add_reference();
else
_M_impl = new _Impl(__env, 1);
}
else
(_M_impl = _S_classic)->_M_add_reference();
{
char* __res;
// LANG may set a default different from "C".
char* __env = getenv("LANG");
if (!__env || strcmp(__env, "") == 0 || strcmp(__env, "C") == 0
|| strcmp(__env, "POSIX") == 0)
__res = strdup("C");
else
__res = strdup(__env);
// Scan the categories looking for the first one
// different from LANG.
size_t __i = 0;
if (strcmp(__res, "C") == 0)
for (__i = 0;
__i < _S_categories_size + _S_extra_categories_size;
++__i)
{
__env = getenv(_S_categories[__i]);
if (__env && strcmp(__env, "") != 0
&& strcmp(__env, "C") != 0
&& strcmp(__env, "POSIX") != 0)
break;
}
else
for (__i = 0;
__i < _S_categories_size + _S_extra_categories_size;
++__i)
{
__env = getenv(_S_categories[__i]);
if (__env && strcmp(__env, "") != 0
&& strcmp(__env, __res) != 0)
break;
}
// If one is found, build the complete string of
// the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on...
if (__i < _S_categories_size + _S_extra_categories_size)
{
string __str;
for (size_t __j = 0; __j < __i; ++__j)
{
__str += _S_categories[__j];
__str += "=";
__str += __res;
__str += ";";
}
__str += _S_categories[__i];
__str += "=";
__str += __env;
__str += ";";
__i++;
for (; __i < _S_categories_size
+ _S_extra_categories_size; ++__i)
{
__env = getenv(_S_categories[__i]);
if (!__env || strcmp(__env, "") == 0)
{
__str += _S_categories[__i];
__str += '=';
__str += __res;
__str += ';';
}
else if (strcmp(__env, "C") == 0
|| strcmp(__env, "POSIX") == 0)
{
__str += _S_categories[__i];
__str += "=C;";
}
else
{
__str += _S_categories[__i];
__str += "=";
__str += __env;
__str += ";";
}
}
__str.erase(__str.end() - 1);
_M_impl = new _Impl(__str.c_str(), 1);
}
// ... otherwise either an additional instance of
// the "C" locale or LANG.
else if (strcmp(__res, "C") == 0)
(_M_impl = _S_classic)->_M_add_reference();
else
_M_impl = new _Impl(__res, 1);
free(__res);
}
}
else
_M_impl = new _Impl(__s, 1);
}
else
__throw_runtime_error("attempt to create locale from NULL name");
......@@ -261,20 +349,22 @@ namespace std
string
locale::name() const
{
// Need some kind of separator character. This one was pretty much
// arbitrarily chosen as to not conflict with glibc locales: the
// exact formatting is not set in stone.
const char __separator = '|';
string __ret;
if (_M_impl->_M_check_same_name())
__ret = _M_impl->_M_names[0];
else
{
for (size_t i = 0; i < _S_num_categories; ++i)
__ret += _S_categories[0];
__ret += "=";
__ret += _M_impl->_M_names[0];
for (size_t __i = 1;
__i < _S_categories_size + _S_extra_categories_size;
++__i)
{
__ret += __separator;
__ret += _M_impl->_M_names[i];
__ret += ";";
__ret += _S_categories[__i];
__ret += "=";
__ret += _M_impl->_M_names[__i];
}
}
return __ret;
......@@ -292,11 +382,7 @@ namespace std
{
// 26 Standard facets, 2 references.
// One reference for _M_classic, one for _M_global
facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS];
for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i)
f[__i] = 0;
_S_classic = new (&c_locale_impl) _Impl(f, 2, true);
_S_classic = new (&c_locale_impl) _Impl(0, 2, true);
_S_global = _S_classic;
new (&c_locale) locale(_S_classic);
}
......@@ -361,11 +447,8 @@ namespace std
~facet() { }
locale::facet::
facet(size_t __refs) throw() : _M_references(__refs)
{
if (!_S_c_locale)
_S_create_c_locale(_S_c_locale, "C");
}
facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0)
{ }
void
locale::facet::
......@@ -376,7 +459,7 @@ namespace std
locale::facet::
_M_remove_reference() throw()
{
if (__exchange_and_add(&_M_references, -1) == 0)
if (__exchange_and_add(&_M_references, -1) == 1)
{
try
{ delete this; }
......
......@@ -33,6 +33,9 @@
namespace std
{
// Defined in globals.cc.
extern locale::facet** facet_vec;
extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
extern std::ctype<char> ctype_c;
extern std::collate<char> collate_c;
extern numpunct<char> numpunct_c;
......@@ -71,6 +74,10 @@ namespace std
if (_M_facets[__i])
_M_facets[__i]->_M_remove_reference();
delete [] _M_facets;
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
delete [] _M_names[__i];
}
// Clone existing _Impl object.
......@@ -95,14 +102,19 @@ namespace std
if (_M_facets[__i])
_M_facets[__i]->_M_add_reference();
}
for (size_t __i = 0; __i < _S_num_categories; ++__i)
_M_names[__i] = __imp._M_names[__i];
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
{
char* __new = new char[strlen(__imp._M_names[__i]) + 1];
strcpy(__new, __imp._M_names[__i]);
_M_names[__i] = __new;
}
}
// Construct named _Impl.
locale::_Impl::
_Impl(const char* __s, size_t __refs)
: _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) // XXX
: _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
{
// Initialize the underlying locale model, which also checks
// to see if the given name is valid.
......@@ -122,11 +134,40 @@ namespace std
}
// Name all the categories.
for (size_t i = 0; i < _S_num_categories; ++i)
_M_names[i] = __s;
if (!strchr(__s, ';'))
{
size_t __len = strlen(__s) + 1;
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
{
_M_names[__i] = new char[__len];
strcpy(_M_names[__i], __s);
}
}
else
{
char* __tmp = strdup(__s);
__tmp[strlen(__tmp)] = ';';
strtok(__tmp, "=;");
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size - 1; ++__i)
{
char* __src = strtok(NULL, "=;");
char* __new = new char[strlen(__src) + 1];
strcpy(__new, __src);
_M_names[__i] = __new;
strtok(NULL, "=;");
}
char* __src = strtok(NULL, "=;");
char* __new = new char[strlen(__src) + 1];
strcpy(__new, __src);
_M_names[_S_categories_size + _S_extra_categories_size - 1] = __new;
// Construct all standard facets and add them to _M_facets.
_M_init_facet(new std::ctype<char>(__cloc));
free(__tmp);
}
// Construct all standard facets and add them to _M_facets.
_M_init_facet(new std::ctype<char>(__cloc, 0, false));
_M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
_M_init_facet(new numpunct<char>(__cloc));
_M_init_facet(new num_get<char>);
......@@ -162,47 +203,61 @@ namespace std
// Construct "C" _Impl.
locale::_Impl::
_Impl(facet** __f, size_t __refs, bool)
: _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS)
_Impl(facet**, size_t __refs, bool)
: _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
{
// Initialize the underlying locale model.
locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, "C");
_M_facets = new(&facet_vec) facet*[_M_facets_size];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = 0;
// Name all the categories.
for (size_t i = 0; i < _S_num_categories; ++i)
_M_names[i] = "C";
for (size_t __i = 0;
__i < _S_categories_size + _S_extra_categories_size; ++__i)
{
_M_names[__i] = new (&facet_name[__i]) char[2];
strcpy(_M_names[__i], "C");
}
// This is needed as presently the C++ version of "C" locales
// != data in the underlying locale model for __timepunct,
// numpunct, and moneypunct. Also, the "C" locales must be
// constructed in a way such that they are pre-allocated.
_M_init_facet(new (&ctype_c) std::ctype<char>);
_M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>);
_M_init_facet(new (&numpunct_c) numpunct<char>);
_M_init_facet(new (&num_get_c) num_get<char>);
_M_init_facet(new (&num_put_c) num_put<char>);
_M_init_facet(new (&collate_c) std::collate<char>);
_M_init_facet(new (&moneypunct_fc) moneypunct<char, false>);
_M_init_facet(new (&moneypunct_tc) moneypunct<char, true>);
_M_init_facet(new (&money_get_c) money_get<char>);
_M_init_facet(new (&money_put_c) money_put<char>);
_M_init_facet(new (&timepunct_c) __timepunct<char>);
_M_init_facet(new (&time_get_c) time_get<char>);
_M_init_facet(new (&time_put_c) time_put<char>);
_M_init_facet(new (&messages_c) std::messages<char>);
// NB: Set locale::facets(ref) count to one so that each individual
// facet is not destroyed when the locale (and thus locale::_Impl) is
// destroyed.
_M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
_M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
_M_init_facet(new (&numpunct_c) numpunct<char>(1));
_M_init_facet(new (&num_get_c) num_get<char>(1));
_M_init_facet(new (&num_put_c) num_put<char>(1));
_M_init_facet(new (&collate_c) std::collate<char>(1));
_M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
_M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
_M_init_facet(new (&money_get_c) money_get<char>(1));
_M_init_facet(new (&money_put_c) money_put<char>(1));
_M_init_facet(new (&timepunct_c) __timepunct<char>(1));
_M_init_facet(new (&time_get_c) time_get<char>(1));
_M_init_facet(new (&time_put_c) time_put<char>(1));
_M_init_facet(new (&messages_c) std::messages<char>(1));
#ifdef _GLIBCPP_USE_WCHAR_T
_M_init_facet(new (&ctype_w) std::ctype<wchar_t>);
_M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>);
_M_init_facet(new (&numpunct_w) numpunct<wchar_t>);
_M_init_facet(new (&num_get_w) num_get<wchar_t>);
_M_init_facet(new (&num_put_w) num_put<wchar_t>);
_M_init_facet(new (&collate_w) std::collate<wchar_t>);
_M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>);
_M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>);
_M_init_facet(new (&money_get_w) money_get<wchar_t>);
_M_init_facet(new (&money_put_w) money_put<wchar_t>);
_M_init_facet(new (&timepunct_w) __timepunct<wchar_t>);
_M_init_facet(new (&time_get_w) time_get<wchar_t>);
_M_init_facet(new (&time_put_w) time_put<wchar_t>);
_M_init_facet(new (&messages_w) std::messages<wchar_t>);
#endif
_M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
_M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
_M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
_M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
_M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
_M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
_M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
_M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
_M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
_M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
_M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
_M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
_M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
_M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
#endif
}
void
......@@ -210,7 +265,7 @@ namespace std
_M_replace_categories(const _Impl* __imp, category __cat)
{
category __mask;
for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix)
for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
{
__mask = 1 << __ix;
if (__mask & __cat)
......@@ -220,7 +275,12 @@ namespace std
// If both have names, go ahead and mangle.
if (strcmp(_M_names[__ix], "*") != 0
&& strcmp(__imp->_M_names[__ix], "*") != 0)
_M_names[__ix] = __imp->_M_names[__ix];
{
delete [] _M_names[__ix];
char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
strcpy(__new, __imp->_M_names[__ix]);
_M_names[__ix] = __new;
}
}
}
}
......@@ -250,6 +310,8 @@ namespace std
if (__fp)
{
size_t __index = __idp->_M_id();
// Check size of facet vector to ensure adequate room.
if (__index > _M_facets_size - 1)
{
facet** __old = _M_facets;
......@@ -266,11 +328,11 @@ namespace std
delete [] __old;
}
__fp->_M_add_reference();
facet*& __fpr = _M_facets[__index];
if (__fpr)
{
// Replacing an existing facet. Order matters.
__fp->_M_add_reference();
__fpr->_M_remove_reference();
__fpr = __fp;
}
......
......@@ -121,7 +121,7 @@ void test01()
string str1, str2;
// construct a locale object with the C facet
const locale& loc01 = locale::classic();
const locale loc01 = locale::classic();
// 1
// template <class Facet> locale(const locale& other, Facet* f)
......@@ -315,16 +315,92 @@ void test03()
{
bool test = true;
#ifdef _GLIBCPP_HAVE_SETENV
const char* oldLANG = getenv("LANG");
if (!setenv("LANG", "it_IT", 1))
const char* oldLC_ALL = getenv("LC_ALL");
if (!setenv("LC_ALL", "it_IT", 1))
{
std::locale loc("");
VERIFY( loc.name() == "it_IT" );
setenv("LANG", oldLANG ? oldLANG : "", 1);
setenv("LC_ALL", oldLC_ALL ? oldLC_ALL : "", 1);
}
#endif
}
// More tests for Posix locale::name.
void test04()
{
bool test = true;
#ifdef _GLIBCPP_HAVE_SETENV
const char* oldLC_ALL = getenv("LC_ALL") ? strdup(getenv("LC_ALL")) : "";
const char* oldLANG = getenv("LANG") ? strdup(getenv("LANG")) : "";
// Check that a "POSIX" LC_ALL is equivalent to "C".
if (!setenv("LC_ALL", "POSIX", 1))
{
std::locale loc("");
VERIFY( loc.name() == "C" );
}
// Check the default set by LANG.
if (!setenv("LC_ALL", "", 1) && !setenv("LANG", "fr_FR", 1))
{
std::locale loc("");
VERIFY( loc.name() == "fr_FR" );
}
// Check that a "POSIX" LANG is equivalent to "C".
if (!setenv("LANG", "POSIX", 1))
{
std::locale loc("");
VERIFY( loc.name() == "C" );
}
// Setting a category in the "C" default.
const char* oldLC_COLLATE =
getenv("LC_COLLATE") ? strdup(getenv("LC_COLLATE")) : "";
if (!setenv("LC_COLLATE", "de_DE", 1))
{
std::locale loc("");
VERIFY( loc.name() == "LC_CTYPE=C;LC_NUMERIC=C;LC_COLLATE=de_DE;"
"LC_TIME=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;"
"LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;"
"LC_IDENTIFICATION=C" );
}
// Changing the LANG default while LC_COLLATE is set.
if (!setenv("LANG", "fr_FR", 1))
{
std::locale loc("");
VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;"
"LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;"
"LC_MESSAGES=fr_FR;LC_PAPER=fr_FR;LC_NAME=fr_FR;"
"LC_ADDRESS=fr_FR;LC_TELEPHONE=fr_FR;LC_MEASUREMENT=fr_FR;"
"LC_IDENTIFICATION=fr_FR" );
}
// Changing another (C only) category.
const char* oldLC_IDENTIFICATION =
getenv("LC_IDENTIFICATION") ? strdup(getenv("LC_IDENTIFICATION")) : "";
if (!setenv("LC_IDENTIFICATION", "it_IT", 1))
{
std::locale loc("");
VERIFY( loc.name() == "LC_CTYPE=fr_FR;LC_NUMERIC=fr_FR;"
"LC_COLLATE=de_DE;LC_TIME=fr_FR;LC_MONETARY=fr_FR;"
"LC_MESSAGES=fr_FR;LC_PAPER=fr_FR;LC_NAME=fr_FR;"
"LC_ADDRESS=fr_FR;LC_TELEPHONE=fr_FR;LC_MEASUREMENT=fr_FR;"
"LC_IDENTIFICATION=it_IT" );
}
// Restore the environment.
setenv("LC_ALL", oldLC_ALL ? oldLC_ALL : "", 1);
setenv("LANG", oldLANG ? oldLANG : "", 1);
setenv("LC_COLLATE", oldLC_COLLATE ? oldLC_COLLATE : "", 1);
setenv("LC_IDENTIFICATION",
oldLC_IDENTIFICATION ? oldLC_IDENTIFICATION : "", 1);
#endif
}
int main()
{
test00();
......@@ -335,6 +411,7 @@ int main()
test02();
test03();
test04();
return 0;
}
// 2000-08-31 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2000 Free Software Foundation
// Copyright (C) 2000, 2002 Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
......@@ -25,6 +25,7 @@
#include <stdexcept>
#include <string>
#include <iterator>
#include <limits>
#include <testsuite_hooks.h>
// 1 a class if a facet if it is publicly derived from another facet
......@@ -233,9 +234,69 @@ void test01()
}
}
// Static counter for use in checking ctors/dtors.
static std::size_t counter;
class surf : public std::locale::facet
{
public:
static std::locale::id id;
surf(size_t refs = 0): std::locale::facet(refs) { ++counter; }
~surf() { --counter; }
};
std::locale::id surf::id;
typedef surf facet_type;
void test02()
{
using namespace std;
bool test = true;
// 1: Destroyed when out of scope.
VERIFY( counter == 0 );
{
locale loc01(locale::classic(), new facet_type);
VERIFY( counter == 1 );
}
VERIFY( counter == 0 );
// 2: Not destroyed when out of scope, deliberately leaked.
VERIFY( counter == 0 );
{
// Default refs argument is zero.
locale loc02(locale::classic(), new facet_type(1));
VERIFY( counter == 1 );
}
VERIFY( counter == 1 );
// 3: Pathological.
counter = 0;
{
// Test bounds.
facet_type* f = new facet_type(numeric_limits<size_t>::max());
VERIFY( counter == 1 );
// Add a reference.
locale loc01(locale::classic(), f);
{
// Add another reference...
locale loc02(locale::classic(), f);
}
VERIFY( counter == 1 );
}
// 4: Named locale should destroy facets when it goes out of scope.
// Not quite sure how to test for this w/o valgrind at the moment.
{
locale loc03("es_MX");
}
}
int main ()
{
test01();
test02();
return 0;
}
// 2000-09-13 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2000 Free Software Foundation
// Copyright (C) 2000, 2002 Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
......@@ -22,7 +22,9 @@
#include <cwchar> // for mbstate_t
#include <locale>
#include <testsuite_hooks.h>
#include <iostream>
//#include <testsuite_hooks.h>
#define VERIFY(x) test &= x
typedef std::codecvt<char, char, std::mbstate_t> ccodecvt;
class gnu_codecvt: public ccodecvt { };
......@@ -34,10 +36,12 @@ void test01()
bool test = true;
string str1, str2;
// construct a locale object with the C facet
const locale& loc01 = locale::classic();
// construct a locale object with the specialized facet.
locale loc02(locale::classic(), new gnu_codecvt);
// Construct a locale object with the C facet.
const locale loc_env("");
const locale loc01 = locale::classic();
// Construct a locale object with the specialized facet.
locale loc02(locale::classic(), new gnu_codecvt);
VERIFY ( loc01 != loc02 );
VERIFY ( !(loc01 == loc02) );
......@@ -54,11 +58,45 @@ void test01()
locale loc05;
VERIFY (loc05 != loc03);
VERIFY (loc05 == loc02);
// Reset global locale.
locale::global(loc_env);
}
// Sanity check locale::global(loc) and setlocale.
void test02()
{
using namespace std;
bool test = true;
const string ph("en_PH");
const string mx("es_MX");
const locale loc_ph(ph.c_str());
const locale loc_mx(mx.c_str());
// Get underlying current locale and environment settings.
const string lc_all_orig = std::setlocale(LC_ALL, NULL);
const locale loc_orig("");
// setlocale to en_PH
string lc_all_ph = std::setlocale(LC_ALL, ph.c_str());
const locale loc_env("");
VERIFY( loc_env == loc_orig );
locale::global(loc_mx);
string lc_all_mx = std::setlocale(LC_ALL, NULL);
VERIFY( lc_all_mx == mx.c_str() );
// Restore global info.
locale::global(loc_orig);
}
int main ()
{
test01();
test02();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment