first commit
This commit is contained in:
399
extern/stdcxx/4.2.1/tests/localization/22.locale.numpunct.cpp
vendored
Normal file
399
extern/stdcxx/4.2.1/tests/localization/22.locale.numpunct.cpp
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.numpunct.cpp
|
||||
*
|
||||
* test exercising the std::numpunct facet
|
||||
*
|
||||
* $Id: 22.locale.numpunct.cpp 648752 2008-04-16 17:01:56Z faridz $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <rw/_defs.h>
|
||||
|
||||
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
|
||||
// Disable implicit inclusion to work around
|
||||
// a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959)
|
||||
|
||||
# define _RWSTD_NO_IMPLICIT_INCLUSION
|
||||
#endif
|
||||
|
||||
|
||||
#include <clocale> // for struct lconv, setlocale()
|
||||
#include <cstdio> // for sprintf()
|
||||
#include <cstdlib> // for getenv()
|
||||
#include <cstring> // for strcmp()
|
||||
#include <locale>
|
||||
|
||||
#include <driver.h>
|
||||
#include <environ.h>
|
||||
#include <rw_locale.h>
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void run_test (charT*);
|
||||
|
||||
template <class charT>
|
||||
void check_decimal_point (charT, const char*, const std::locale*);
|
||||
|
||||
template <class charT>
|
||||
void check_thousands_sep (charT, const char*, const std::locale*);
|
||||
|
||||
template <class charT>
|
||||
void check_grouping (charT, const char*, const std::string&, const std::locale*);
|
||||
|
||||
template <class charT>
|
||||
void check_falsename (const std::basic_string<charT>&,
|
||||
const char*, const std::locale*);
|
||||
|
||||
template <class charT>
|
||||
void check_truename (const std::basic_string<charT>&,
|
||||
const char*, const std::locale*);
|
||||
|
||||
template <class charT>
|
||||
bool check_numpunct (charT, const char*, const char*, const std::locale*);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void run_test (charT, const char *tname)
|
||||
{
|
||||
rw_info (0, 0, __LINE__, "classic \"C\" locale");
|
||||
|
||||
// create a copy of the classic ("C") locale
|
||||
std::locale *loc = new std::locale (std::locale::classic ());
|
||||
|
||||
// verify (at compile time) that _byname facets can be used
|
||||
// to specialize use_facet() and has_facet()
|
||||
typedef std::numpunct_byname<charT> NumpunctByname;
|
||||
|
||||
if (_STD_HAS_FACET (NumpunctByname, *loc))
|
||||
_STD_USE_FACET (NumpunctByname, *loc);
|
||||
|
||||
// verify values as per 7.4 of C89, and 7.11, p2 of C99
|
||||
check_decimal_point (charT ('.'), tname, loc);
|
||||
|
||||
// verify 22.2.3.1.2, p2
|
||||
check_thousands_sep (charT (','), tname, loc);
|
||||
check_grouping (charT (), tname, "", loc);
|
||||
|
||||
const charT fn[] = { 'f', 'a', 'l', 's', 'e', '\0' };
|
||||
const charT tn[] = { 't', 'r', 'u', 'e', '\0' };
|
||||
|
||||
check_falsename (std::basic_string<charT>(fn), tname, loc);
|
||||
check_truename (std::basic_string<charT>(tn), tname, loc);
|
||||
|
||||
delete loc;
|
||||
loc = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// verify that the facet can be safely used on its own, without
|
||||
// first having to be installed in a locale and retrieved using
|
||||
// use_facet
|
||||
|
||||
check_decimal_point (charT ('.'), tname, loc);
|
||||
check_thousands_sep (charT (','), tname, loc);
|
||||
check_grouping (charT (), tname, "", loc);
|
||||
|
||||
check_falsename (std::basic_string<charT>(fn), tname, loc);
|
||||
check_truename (std::basic_string<charT>(tn), tname, loc);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise the native locale (affected by the environment
|
||||
// variables LANG, LC_ALL, LC_NUMERIC, etc.)
|
||||
check_numpunct (charT (), tname, "", loc); // native locale
|
||||
|
||||
// the name of the first non-C (and non-POSIX) locale
|
||||
const char *first_non_c = 0;
|
||||
|
||||
// exercise named locales (including "C" and "POSIX")
|
||||
for (const char* s = rw_locales (); *s; s += std::strlen (s) + 1) {
|
||||
if (check_numpunct (charT (), tname, s, loc))
|
||||
if ( !first_non_c
|
||||
&& std::strcmp ("C", s)
|
||||
&& std::strcmp ("POSIX", s))
|
||||
first_non_c = s;
|
||||
}
|
||||
|
||||
// verify that numpunct behaves correctly when LC_ALL is set
|
||||
// to the name of the (non-C, non-POSIX) locale
|
||||
char envvar [80];
|
||||
std::sprintf (envvar, "LC_ALL=%s", first_non_c);
|
||||
rw_putenv (envvar);
|
||||
check_numpunct (charT (), tname, "", loc);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
char widen (char, const char *s)
|
||||
{
|
||||
return *s;
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t widen (wchar_t, const char *s)
|
||||
{
|
||||
wchar_t wc = 0;
|
||||
|
||||
# ifndef _RWSTD_NO_MBTOWC
|
||||
|
||||
const int n = s && *s ? std::mbtowc (&wc, s, std::strlen (s)) : 0;
|
||||
|
||||
# else // if defined (_RWSTD_NO_MBTOWC)
|
||||
|
||||
const int n = 1;
|
||||
|
||||
wc = s ? wchar_t (_RWSTD_STATIC_CAST (unsigned char, *s)) : 0;
|
||||
|
||||
# endif // _RWSTD_NO_MBTOWC
|
||||
|
||||
return n > 0 ? wc : n ? -1 : 0;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
|
||||
template <class charT>
|
||||
bool check_numpunct (charT,
|
||||
const char *tname,
|
||||
const char *locname,
|
||||
const std::locale *loc)
|
||||
{
|
||||
// (try to) set the global C locale
|
||||
const char *tmploc = std::setlocale (LC_ALL, locname);
|
||||
if (!tmploc)
|
||||
return false;
|
||||
|
||||
// future setlocale() calls may change tmploc's value, so make a copy
|
||||
// (fixed-size char buf is clunky but avoids memory-leak potential)
|
||||
char locnamebuf [1024];
|
||||
RW_ASSERT ((std::strlen (tmploc) + 1) < sizeof locnamebuf);
|
||||
std::strcpy (locnamebuf, tmploc);
|
||||
|
||||
_TRY {
|
||||
|
||||
rw_info (0, 0, __LINE__,
|
||||
"locale (%s) -> \"%s\"; LANG=%s, "
|
||||
"LC_ALL=%s, LC_NUMERIC=%s",
|
||||
locname, loc,
|
||||
std::getenv ("LANG"),
|
||||
std::getenv ("LC_ALL"),
|
||||
std::getenv ("LC_NUMERIC"));
|
||||
|
||||
// get a pointer to lconv
|
||||
const std::lconv *plconv = std::localeconv ();
|
||||
|
||||
if (!plconv)
|
||||
return false;
|
||||
|
||||
// copy important data; the contents of *plconv may
|
||||
// be overwritten by the call sto setlocale() below
|
||||
// note that decimal_point at al may be multbyte character
|
||||
// strings that need to be widened according to the rules
|
||||
// of the same locale
|
||||
const charT decimal_point = widen (charT (), plconv->decimal_point);
|
||||
const charT thousands_sep = widen (charT (), plconv->thousands_sep);
|
||||
|
||||
const std::string grouping =
|
||||
plconv->grouping ? plconv->grouping : "";
|
||||
|
||||
// reset to default locale given by LC_LANG
|
||||
std::setlocale (LC_ALL, "");
|
||||
|
||||
loc = new std::locale (locname);
|
||||
|
||||
// check that newly constructed locale matches
|
||||
|
||||
if ( 'C' == locnamebuf [0] && '\0' == locnamebuf [1]
|
||||
|| 'C' == locname [0] && '\0' == locname [1]
|
||||
|| *loc == std::locale::classic ()) {
|
||||
// follow requirements in 22.2.3.1.2. p1, 2, and 3
|
||||
check_decimal_point (charT ('.'), tname, loc);
|
||||
check_thousands_sep (charT (','), tname, loc);
|
||||
|
||||
check_grouping (charT (), tname, "", loc);
|
||||
}
|
||||
else {
|
||||
// cast to prevent sign extension between (signed) char and wchar_t
|
||||
// tmp guards against possibly passing along a "(nil)" pointer
|
||||
check_decimal_point (decimal_point, tname, loc);
|
||||
check_thousands_sep (thousands_sep, tname, loc);
|
||||
check_grouping (charT (), tname, grouping.c_str (), loc);
|
||||
}
|
||||
|
||||
// FIXME: exercise falsename() and truename() in named locales
|
||||
|
||||
delete loc;
|
||||
loc = 0;
|
||||
}
|
||||
_CATCH (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void check_decimal_point (charT expect,
|
||||
const char *tname,
|
||||
const std::locale *loc)
|
||||
{
|
||||
typedef std::numpunct<charT> Punct;
|
||||
typedef std::char_traits<charT> Traits;
|
||||
|
||||
const charT c = loc ?
|
||||
_STD_USE_FACET (Punct, *loc).decimal_point ()
|
||||
: Punct ().decimal_point ();
|
||||
|
||||
|
||||
rw_assert (Traits::eq (c, expect), 0, __LINE__,
|
||||
"numpunct<%s>::decimal_point() == %{#lc}, got %{#lc}",
|
||||
tname, expect, c);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void check_thousands_sep (charT expect,
|
||||
const char *tname,
|
||||
const std::locale *loc)
|
||||
{
|
||||
typedef std::numpunct<charT> Punct;
|
||||
typedef std::char_traits<charT> Traits;
|
||||
|
||||
const charT c = loc ?
|
||||
_STD_USE_FACET (Punct, *loc).thousands_sep ()
|
||||
: Punct ().thousands_sep ();
|
||||
|
||||
rw_assert (Traits::eq (c, expect), 0, __LINE__,
|
||||
"numpunct<%s>::thousands_sep() == %{#lc}, got %{#lc}",
|
||||
tname, expect, c);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void check_grouping (charT,
|
||||
const char *tname,
|
||||
const std::string &expect,
|
||||
const std::locale *loc)
|
||||
{
|
||||
typedef std::numpunct<charT> Punct;
|
||||
|
||||
const std::string s = loc ?
|
||||
_STD_USE_FACET (Punct, *loc).grouping ()
|
||||
: Punct ().grouping ();
|
||||
|
||||
if ( s != expect
|
||||
&& s.size () != expect.size () && s.size () && expect.size ()) {
|
||||
|
||||
// if the grouping is not exactly the same as the expected result,
|
||||
// verify that the actual grouping is equivalent to the expected
|
||||
// one, e.g., that "\003\003" is equivalent to "\003"
|
||||
|
||||
const std::string *lng = s.size () > expect.size () ? &expect : &s;
|
||||
const std::string *shrt = s.size () < expect.size () ? &expect : &s;
|
||||
|
||||
std::size_t i = shrt->size () - 1;
|
||||
|
||||
for ( ; i != lng->size (); ++i)
|
||||
if ((*shrt) [shrt->size () - 1] != (*lng)[i])
|
||||
break;
|
||||
|
||||
rw_assert (i == lng->size (), 0, __LINE__,
|
||||
"numpunct<%s>::grouping() equivalent to %{#S}, got %{#S}",
|
||||
tname, &expect, &s);
|
||||
}
|
||||
else
|
||||
rw_assert (s == expect, 0, __LINE__,
|
||||
"numpunct<%s>::grouping() == %{#S}, got %{#S}",
|
||||
tname, &expect, &s);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void check_falsename (const std::basic_string<charT> &expect,
|
||||
const char *tname,
|
||||
const std::locale *loc)
|
||||
{
|
||||
typedef std::numpunct<charT> Punct;
|
||||
|
||||
const std::basic_string<charT> s = loc ?
|
||||
_STD_USE_FACET (Punct, *loc).falsename ()
|
||||
: Punct ().falsename ();
|
||||
|
||||
const int char_size = int (sizeof (charT));
|
||||
|
||||
rw_assert (s == expect, 0, __LINE__,
|
||||
"numpunct<%s>::falsename() == %{#*S}, got %{#*S}",
|
||||
tname, char_size, &expect, char_size, &s);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void check_truename (const std::basic_string<charT> &expect,
|
||||
const char *tname,
|
||||
const std::locale *loc)
|
||||
{
|
||||
typedef std::numpunct<charT> Punct;
|
||||
|
||||
const std::basic_string<charT> s = loc ?
|
||||
_STD_USE_FACET (Punct, *loc).truename ()
|
||||
: Punct ().truename ();
|
||||
|
||||
const int char_size = int (sizeof (charT));
|
||||
|
||||
rw_assert (s == expect, 0, __LINE__,
|
||||
"numpunct<%s>::truename() == %{#*S}, got %{#*S}",
|
||||
tname, char_size, &expect, char_size, &s);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
run_test (char (), "char");
|
||||
|
||||
#ifndef _RWSTD_WCHAR_T
|
||||
|
||||
run_test (wchar_t (), "wchar_t");
|
||||
|
||||
#endif // _RWSTD_WCHAR_T
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.numpunct",
|
||||
"", run_test,
|
||||
"",
|
||||
(void*)0);
|
||||
}
|
||||
Reference in New Issue
Block a user