first commit
This commit is contained in:
814
extern/stdcxx/4.2.1/tests/localization/22.locale.codecvt.length.cpp
vendored
Normal file
814
extern/stdcxx/4.2.1/tests/localization/22.locale.codecvt.length.cpp
vendored
Normal file
@@ -0,0 +1,814 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* codecvt_length.cpp - test exercising the std::codecvt::length()
|
||||
*
|
||||
* $Id: 22.locale.codecvt.length.cpp 604041 2007-12-13 21:43:43Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2004-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifdef __SUNPRO_CC
|
||||
// working around a SunPro/SunOS 5.8 bug (PR #26255)
|
||||
# include <time.h>
|
||||
#endif // __SUNPRO_CC
|
||||
|
||||
#include <locale> // for codecvt
|
||||
|
||||
#include <climits> // for MB_LEN_MAX
|
||||
#include <clocale> // for LC_CTYPE, setlocale()
|
||||
#include <cstdlib> // for MB_CUR_MAX, free(), size_t
|
||||
#include <cstring> // for strcpy(), strlen()
|
||||
#include <cwchar> // for mbstate_t
|
||||
|
||||
#include <any.h> // for rw_any
|
||||
#include <cmdopt.h> // for rw_enabled()
|
||||
#include <driver.h> // for rw_test()
|
||||
#include <file.h> // for rw_fwrite()
|
||||
#include <rw_locale.h> // for rw_localedef(), rw_find_mb_locale()
|
||||
#include <rw_printf.h> // for rw_printf()
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
typedef std::codecvt<char, char, std::mbstate_t> Codecvt;
|
||||
typedef std::codecvt_byname<char, char, std::mbstate_t> CodecvtByname;
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
typedef std::codecvt<wchar_t, char, std::mbstate_t> WCodecvt;
|
||||
typedef std::codecvt_byname<wchar_t, char, std::mbstate_t> WCodecvtByname;
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
// the root of the locale directory (RWSTD_LOCALE_ROOT)
|
||||
// set in main() instead of here to avoid Solaris 7 putenv() bug (PR #30017)
|
||||
const char* locale_root /* = set in main() */;
|
||||
|
||||
|
||||
// creates a table-based multibyte locale
|
||||
const char* create_locale ()
|
||||
{
|
||||
char cm_fname [1024];
|
||||
if (rw_snprintf (cm_fname, sizeof cm_fname, "%s%c%s",
|
||||
locale_root, _RWSTD_PATH_SEP, "charmap") < 0)
|
||||
return 0;
|
||||
|
||||
static const char charmap[] = {
|
||||
"<code_set_name> test_charmap\n"
|
||||
"<comment_char> %\n"
|
||||
"<escape_char> /\n"
|
||||
"<mb_cur_min> 1\n"
|
||||
"<mb_cur_max> 9\n"
|
||||
"CHARMAP\n"
|
||||
"<U0000> /x30 0 \n"
|
||||
"<U0001> /x31 1 \n"
|
||||
"<U0002> /x32/x32 22 \n"
|
||||
"<U0003> /x33/x33/x33 333 \n"
|
||||
"<U0004> /x34/x34/x34/x34 4444 \n"
|
||||
"<U0005> /x35/x35/x35/x35/x35 55555 \n"
|
||||
"<U0006> /x36/x36/x36/x36/x36/x36 666666 \n"
|
||||
"<U0007> /x37/x37/x37/x37/x37/x37/x37 7777777 \n"
|
||||
"<U0008> /x38/x38/x38/x38/x38/x38/x38/x38 88888888 \n"
|
||||
"<U0009> /x39/x39/x39/x39/x39/x39/x39/x39/x39 999999999 \n"
|
||||
"<U0010> /x41 A \n"
|
||||
"<U0011> /x42 B \n"
|
||||
"<U0012> /x43 C \n"
|
||||
"END CHARMAP\n"
|
||||
};
|
||||
|
||||
if (std::size_t (-1) == rw_fwrite (cm_fname, charmap))
|
||||
return 0;
|
||||
|
||||
char src_fname [1024];
|
||||
if (rw_snprintf (src_fname, sizeof src_fname, "%s%c%s",
|
||||
locale_root, _RWSTD_PATH_SEP, "source") < 0)
|
||||
return 0;
|
||||
|
||||
if (std::size_t (-1) == rw_fwrite (src_fname, "LC_CTYPE\nEND LC_CTYPE\n"))
|
||||
return 0;
|
||||
|
||||
// invoke localedef to create the named locale
|
||||
// silence the following warnings:
|
||||
// 701: no compatible locale found
|
||||
// 702: member of portable character set <x> not found
|
||||
// in the character map
|
||||
// 706: iconv_open() failed
|
||||
const char* const locname =
|
||||
rw_localedef ("-w701 -w702 -w706",
|
||||
src_fname, cm_fname, "mb_cur_max-9");
|
||||
|
||||
return locname;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
template <class internT>
|
||||
void test_length (internT /* dummy */,
|
||||
int line,
|
||||
const std::mbstate_t *pstate,
|
||||
const std::codecvt<internT, char, std::mbstate_t> &cvt,
|
||||
const char *from,
|
||||
std::size_t nchars,
|
||||
int maxi,
|
||||
int result)
|
||||
{
|
||||
static const std::mbstate_t initial_state = std::mbstate_t ();
|
||||
|
||||
const char* const tname = rw_any_t (internT ()).type_name ();
|
||||
|
||||
std::mbstate_t state = pstate ? *pstate : initial_state;
|
||||
|
||||
if (std::size_t (-1) == nchars)
|
||||
nchars = std::strlen (from);
|
||||
|
||||
const int res = cvt.length (state, from, from + nchars, maxi);
|
||||
|
||||
rw_assert (res == result, 0, line,
|
||||
"line %d: codecvt<%s, char, mbstate_t>::length("
|
||||
"state, from=%{*s}, from + %zu, %d) == %d, got %d",
|
||||
__LINE__, tname, sizeof *from, from, nchars, maxi, result, res);
|
||||
|
||||
rw_assert (!pstate || 0 == std::memcmp (pstate, &state, sizeof state),
|
||||
0, line,
|
||||
"line %d: codecvt<%s, char, mbstate_t>::length("
|
||||
"state, from=%{*s}, from + %zu, %d) unexpected state",
|
||||
__LINE__, tname, from, nchars, maxi);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void test_codecvt (const Codecvt *pcvt = 0)
|
||||
{
|
||||
if (0 == pcvt)
|
||||
rw_info (0, 0, 0,
|
||||
"std::codecvt<char, char, mbstate_t>::length "
|
||||
"(state_type&, const extern_type*, const "
|
||||
"extern_type*, size_t)");
|
||||
|
||||
const std::locale classic = std::locale::classic ();
|
||||
|
||||
const Codecvt &cvt = pcvt ? *pcvt : std::use_facet<Codecvt>(classic);
|
||||
|
||||
#undef TEST
|
||||
#define TEST(from, nchars, maxi, result) \
|
||||
test_length (char (), __LINE__, 0, cvt, from, nchars, maxi, result)
|
||||
|
||||
// +--------------- source sequence of externT characters
|
||||
// | +-------- size of sequence in externT characters
|
||||
// | | +----- maximum number of internT characters
|
||||
// | | | +-- expected result
|
||||
// | | | |
|
||||
// V V V V
|
||||
TEST (0, 0, 0, 0);
|
||||
TEST ("", 0, 0, 0);
|
||||
TEST ("a", 1, 0, 0);
|
||||
TEST ("ab", 2, 1, 1);
|
||||
TEST ("ab", 2, 2, 2);
|
||||
TEST ("ab", 2, 3, 2);
|
||||
TEST ("abc", 3, 0, 0);
|
||||
TEST ("abc", 3, 1, 1);
|
||||
TEST ("abc", 3, 2, 2);
|
||||
TEST ("abc", 3, 3, 3);
|
||||
TEST ("abc", 3, 4, 3);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void
|
||||
test_codecvt_byname ()
|
||||
{
|
||||
rw_info (0, 0, 0,
|
||||
"std::codecvt_byname<char, char, mbstate_t>::length "
|
||||
"(state_type&, const extern_type*, const extern_type*, "
|
||||
"size_t)");
|
||||
|
||||
const CodecvtByname cvt ("");
|
||||
|
||||
test_codecvt (&cvt);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void
|
||||
test_wcodecvt ()
|
||||
{
|
||||
rw_info (0, 0, 0,
|
||||
"std::codecvt<wchar_t, char, mbstate_t>::length "
|
||||
"(state_type&, const extern_type*, const extern_type*, "
|
||||
"size_t)");
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::locale classic = std::locale::classic ();
|
||||
|
||||
const WCodecvt &cvt = std::use_facet<WCodecvt>(classic);
|
||||
|
||||
#undef TEST
|
||||
#define TEST(from, nchars, maxi, result) \
|
||||
test_length (wchar_t (), __LINE__, 0, cvt, from, nchars, maxi, result)
|
||||
|
||||
// +--------------- source sequence of externT characters
|
||||
// | +-------- size of sequence in externT characters
|
||||
// | | +----- maximum number of internT characters
|
||||
// | | | +-- expected result
|
||||
// | | | |
|
||||
// V V V V
|
||||
TEST (0, 0, 0, 0);
|
||||
TEST ("", 0, 0, 0);
|
||||
TEST ("a", 1, 0, 0);
|
||||
TEST ("ab", 2, 1, 1);
|
||||
TEST ("ab", 2, 2, 2);
|
||||
TEST ("ab", 2, 3, 2);
|
||||
TEST ("abc", 3, 0, 0);
|
||||
TEST ("abc", 3, 1, 1);
|
||||
TEST ("abc", 3, 2, 2);
|
||||
TEST ("abc", 3, 3, 3);
|
||||
TEST ("abc", 3, 4, 3);
|
||||
|
||||
#else // if defined (_RWSTD_NO_WCHAR_T)
|
||||
|
||||
rw_warn (0, 0, __LINE__, "_RWSTD_NO_WCHAR_T #defined, cannot test");
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
// exercises an algorithmic multibyte encoding
|
||||
static void
|
||||
test_wcodecvt_byname_algorithmic ()
|
||||
{
|
||||
rw_info (0, 0, 0, "locale (\"UTF-8@UCS\") [algorithmic encoding]");
|
||||
|
||||
// lowercase utf ==> relaxed checking (i.e., some, but not all,
|
||||
// invalid UTF-8 sequence are accepted)
|
||||
const WCodecvtByname cvt_relaxd ("utf-8@UCS");
|
||||
|
||||
// capital UTF ==> strict checking
|
||||
const WCodecvtByname cvt_strict ("UTF-8@UCS");
|
||||
|
||||
#undef STRICT
|
||||
#define STRICT(from, nc, maxi, res) \
|
||||
test_length (wchar_t (), __LINE__, 0, cvt_strict, from, nc, maxi, res)
|
||||
|
||||
#undef RELAXD
|
||||
#define RELAXD(from, nc, maxi, res) \
|
||||
test_length (wchar_t (), __LINE__, 0, cvt_relaxd, from, nc, maxi, res)
|
||||
|
||||
#undef TEST
|
||||
#define TEST(from, nc, maxi, res) \
|
||||
STRICT (from, nc, maxi, res); \
|
||||
RELAXD (from, nc, maxi, res)
|
||||
|
||||
// 22.2.1.5.2 [lib.locale.codecvt.virtuals]
|
||||
// including the resolution of lwg issue 305
|
||||
//
|
||||
// -9- Preconditions: (from<=from_end) well-defined and true; state
|
||||
// initialized, if at the beginning of a sequence, or else equal
|
||||
// to the result of converting the preceding characters in the
|
||||
// sequence.
|
||||
//
|
||||
// -9a- Effects: The effect on the state argument is "as if" it called
|
||||
// do_in(state, from, from_end, from, to, to+max, to) for to pointing
|
||||
// to a buffer of at least max elements.
|
||||
//
|
||||
// -10- Returns: (from_next-from) where from_next is the largest value
|
||||
// in the range [from,from_end] such that the sequence of values
|
||||
// in the range [from,from_next) represents max or fewer valid
|
||||
// complete characters of type internT. The instantiation
|
||||
// codecvt<char, char, mbstate_t> returns the lesser of max
|
||||
// and (from_end-from).
|
||||
|
||||
// Note that the function returns the number of externT characters
|
||||
// (i.e., those of type char for the required instantiations)
|
||||
|
||||
// +--------------- source sequence of externT characters
|
||||
// | +-------- size of sequence in externT characters
|
||||
// | | +----- maximum number of internT characters
|
||||
// | | | +-- expected result in externT characters
|
||||
// | | | |
|
||||
// V V V V
|
||||
TEST (0, 0, 0, 0);
|
||||
TEST ("", 0, 0, 0);
|
||||
TEST ("a", 1, 0, 0);
|
||||
TEST ("ab", 2, 1, 1);
|
||||
TEST ("ab", 2, 2, 2);
|
||||
TEST ("ab", 2, 3, 2);
|
||||
TEST ("abc", 3, 0, 0);
|
||||
TEST ("abc", 3, 1, 1);
|
||||
TEST ("abc", 3, 2, 2);
|
||||
TEST ("abc", 3, 3, 3);
|
||||
TEST ("abc", 3, 4, 3);
|
||||
|
||||
// invalid sequences rejected in both the strict and relaxed mode
|
||||
TEST ("\x80", 1, 0, 0);
|
||||
TEST ("\xc0", 1, 0, 0);
|
||||
TEST ("\x80\x00", 2, 0, 0);
|
||||
TEST ("\xc0\x00", 2, 0, 0);
|
||||
|
||||
// valid 2-byte UTF-8 sequences (except for overlong sequences)
|
||||
// 110x xxxx 10xx xxxx
|
||||
// i.e., first byte: c0-df
|
||||
// second byte: 80-bf
|
||||
TEST ("\xc2", 1, 0, 0);
|
||||
TEST ("\xc2\x81", 1, 1, 0);
|
||||
TEST ("\xc2\x82", 2, 1, 2);
|
||||
TEST ("\xc2\x83", 2, 2, 2);
|
||||
|
||||
// the second byte doesn't follow the correct pattern
|
||||
// and will be rejected in strict mode (but will be
|
||||
// accepted in relaxed mode)
|
||||
STRICT ("\xc2\x01", 2, 1, 0);
|
||||
RELAXD ("\xc2\x01", 2, 1, 2);
|
||||
|
||||
TEST ("\xc2\x80\xc0", 3, 0, 0);
|
||||
TEST ("\xc2\x80\xc0\x81", 3, 1, 2);
|
||||
TEST ("\xc2\x80\xc0\x82", 3, 2, 2);
|
||||
|
||||
STRICT ("\xc2\x80\xc2\x01", 4, 2, 2);
|
||||
RELAXD ("\xc2\x80\xc2\x01", 4, 2, 4);
|
||||
|
||||
TEST ("\xc2\x80\xc2\x81", 4, 0, 0);
|
||||
TEST ("\xc2\x80\xc2\x82", 4, 1, 2);
|
||||
TEST ("\xc2\x80\xc2\x83", 4, 2, 4);
|
||||
TEST ("\xc2\x80\xc2\x84", 4, 3, 4);
|
||||
}
|
||||
|
||||
|
||||
// exercises a table-based multibyte encoding
|
||||
static void
|
||||
test_wcodecvt_byname_table_based ()
|
||||
{
|
||||
const char* const locname = create_locale ();
|
||||
|
||||
if (!rw_error (0 != locname, 0, __LINE__,
|
||||
"failed to create a locale database")) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::locale loc;
|
||||
|
||||
_TRY {
|
||||
loc = std::locale (locname);
|
||||
}
|
||||
_CATCH (...) {
|
||||
rw_error (0, 0, __LINE__,
|
||||
"locale(\"%s\") unexpectedly threw an exception", locname);
|
||||
return;
|
||||
}
|
||||
|
||||
const WCodecvt &cvt_table = std::use_facet<WCodecvt>(loc);
|
||||
|
||||
rw_info (0, 0, 0, "locale (\"%s\") [table-based encoding]", locname);
|
||||
|
||||
#undef TEST
|
||||
#define TEST(from, nc, maxi, res) \
|
||||
test_length (wchar_t (), __LINE__, 0, cvt_table, \
|
||||
from, std::size_t (nc), maxi, res)
|
||||
|
||||
TEST (0, 0, 0, 0);
|
||||
TEST ("", 0, 0, 0);
|
||||
TEST ("A", 1, 0, 0);
|
||||
TEST ("AB", 2, 1, 1);
|
||||
TEST ("AB", 2, 2, 2);
|
||||
TEST ("AB", 2, 3, 2);
|
||||
TEST ("ABC", 3, 0, 0);
|
||||
TEST ("ABC", 3, 1, 1);
|
||||
TEST ("ABC", 3, 2, 2);
|
||||
TEST ("ABC", 3, 3, 3);
|
||||
TEST ("ABC", 3, 4, 3);
|
||||
|
||||
TEST ("22", 1, 1, 0); // "22" --> L'2'
|
||||
TEST ("22", 2, 1, 2);
|
||||
TEST ("22", 2, 2, 2);
|
||||
|
||||
TEST ("333", 1, 1, 0); // "333" --> L'3'
|
||||
TEST ("333", 2, 1, 0);
|
||||
TEST ("333", 3, 1, 3);
|
||||
TEST ("333", 3, 2, 3);
|
||||
|
||||
TEST ("4444", 1, 1, 0); // "4444" --> L'4'
|
||||
TEST ("4444", 2, 1, 0);
|
||||
TEST ("4444", 3, 1, 0);
|
||||
TEST ("4444", 4, 1, 4);
|
||||
TEST ("4444", 4, 2, 4);
|
||||
|
||||
TEST ("122", 1, 0, 0); // "122" --> L"12"
|
||||
TEST ("122", 1, 1, 1);
|
||||
TEST ("122", 1, 2, 1);
|
||||
TEST ("122", 2, 2, 1);
|
||||
TEST ("122", 3, 2, 3);
|
||||
TEST ("122", 3, 3, 3);
|
||||
|
||||
TEST ("122333", 1, 0, 0); // "122333" --> L"123"
|
||||
TEST ("122333", 1, 1, 1);
|
||||
TEST ("122333", 1, 2, 1);
|
||||
TEST ("122333", 4, 1, 1);
|
||||
TEST ("122333", 4, 2, 3);
|
||||
TEST ("122333", 4, 3, 3);
|
||||
TEST ("122333", 5, 1, 1);
|
||||
TEST ("122333", 5, 2, 3);
|
||||
TEST ("122333", 5, 3, 3);
|
||||
TEST ("122333", 5, 1, 1);
|
||||
TEST ("122333", 5, 2, 3);
|
||||
TEST ("122333", 5, 3, 3);
|
||||
TEST ("122333", 6, 1, 1);
|
||||
TEST ("122333", 6, 2, 3);
|
||||
TEST ("122333", 6, 3, 6);
|
||||
TEST ("122333", 6, 4, 6);
|
||||
|
||||
// 0 12 3 45 67 89
|
||||
// I: +---++----+------++------++--++- (intern_type characters)
|
||||
// E: 0....:....1....:....2....:....3. (extern_type characters)
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 1, 4);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 2, 5);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 3, 10);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 4, 11);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 5, 17);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 6, 18);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 7, 25);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 8, 26);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 9, 29);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 10, 30);
|
||||
TEST ("4444A55555B666666C77777770333122", -1, 11, 32);
|
||||
|
||||
TEST ("4444.55555B666666C77777770333122", -1, 11, 4);
|
||||
TEST ("4444A55555.666666C77777770333122", -1, 11, 10);
|
||||
TEST ("4444A55555B666666.77777770333122", -1, 11, 17);
|
||||
TEST ("4444A55555B666666C7777777.333122", -1, 11, 25);
|
||||
TEST ("4444A55555B666666C77777770333.22", -1, 11, 29);
|
||||
}
|
||||
|
||||
|
||||
// exercises a libc-based multibyte encoding
|
||||
static void
|
||||
test_wcodecvt_byname_libc_based ()
|
||||
{
|
||||
// compute `mb_cur_max' multibyte characters in increasing
|
||||
// length from 1 to mb_cur_max bytes long
|
||||
|
||||
// i.e., initialize the first (N + 1) elements of mb_chars as follows:
|
||||
// mb_chars [0] = "0"; // where "0" is a single byte character
|
||||
// mb_chars [1] = "11"; // where "11" is a two-byte character
|
||||
// mb_chars [2] = "222"; // where "222" is a three-byte character
|
||||
// mb_chars [N] = "NNN...N"; // where "NNN...N" is an N-byte character
|
||||
|
||||
std::size_t mb_cur_max = 0;
|
||||
|
||||
rw_mbchar_array_t mb_chars;
|
||||
|
||||
const char* const locname = rw_find_mb_locale (&mb_cur_max, mb_chars);
|
||||
|
||||
if (!rw_warn (0 != locname, 0, __LINE__,
|
||||
"failed to find a multibyte locale")) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::locale loc;
|
||||
|
||||
_TRY {
|
||||
loc = std::locale (locname);
|
||||
}
|
||||
_CATCH (...) {
|
||||
rw_error (0, 0, __LINE__,
|
||||
"locale(\"%s\") unexpectedly threw an exception", locname);
|
||||
return;
|
||||
}
|
||||
|
||||
const WCodecvt &cvt_libc = std::use_facet<WCodecvt>(loc);
|
||||
|
||||
rw_info (0, 0, 0, "locale (\"%s\") [libc-based encoding, "
|
||||
"single-byte characters]", locname);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise sequences containing single-byte characters
|
||||
|
||||
#undef TEST
|
||||
#define TEST(from, nc, maxi, res) \
|
||||
test_length (wchar_t (), __LINE__, 0, cvt_libc, \
|
||||
from, std::size_t (nc), std::size_t (maxi), res)
|
||||
|
||||
TEST (0, 0, 0, 0);
|
||||
TEST ("", 0, 0, 0);
|
||||
TEST ("A", 1, 0, 0);
|
||||
TEST ("AB", 2, 1, 1);
|
||||
TEST ("AB", 2, 2, 2);
|
||||
TEST ("AB", 2, 3, 2);
|
||||
TEST ("ABC", 3, 0, 0);
|
||||
TEST ("ABC", 3, 1, 1);
|
||||
TEST ("ABC", 3, 2, 2);
|
||||
TEST ("ABC", 3, 3, 3);
|
||||
TEST ("ABC", 3, 4, 3);
|
||||
|
||||
// exercise embedded NULs
|
||||
TEST ("\0BC", 3, 3, 3);
|
||||
TEST ("A\0C", 3, 3, 3);
|
||||
TEST ("AB\0", 3, 3, 3);
|
||||
TEST ("\0\0C", 3, 3, 3);
|
||||
TEST ("A\0\0", 3, 3, 3);
|
||||
TEST ("\0B\0", 3, 3, 3);
|
||||
TEST ("\0\0\0", 3, 3, 3);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise sequences containing 2-byte characters
|
||||
|
||||
if (!rw_warn (2 <= mb_cur_max, 0, __LINE__,
|
||||
"no multibyte characters found, skipping test")) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* sequences = 0;
|
||||
|
||||
// verify the length of each character
|
||||
for (std::size_t i = 0; i < mb_cur_max; ++i) {
|
||||
const std::size_t mb_len = std::strlen (mb_chars [i]);
|
||||
|
||||
if (!rw_error (i + 1 == mb_len, 0, __LINE__,
|
||||
"unexpected multibyte character length: "
|
||||
"%zu, expected %zu", mb_len, i + 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sequences = rw_sprintfa ("%s%s%#s",
|
||||
sequences ? sequences : "",
|
||||
i ? ", " : "", mb_chars [i]);
|
||||
}
|
||||
|
||||
rw_info (0, 0, 0, "locale (\"%s\") [libc-based encoding, "
|
||||
"MB_CUR_MAX = %zu, multi-byte characters: %s]",
|
||||
locname, mb_cur_max, sequences);
|
||||
|
||||
std::free (sequences);
|
||||
|
||||
#ifdef _RWSTD_OS_SUNOS
|
||||
|
||||
if (!rw_warn (std::strcmp ("5.7", _RWSTD_OS_RELEASE), 0, __LINE__,
|
||||
"skipping tests due to a SunOS 5.7 libc bug")) {
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_OS_SUNOS
|
||||
|
||||
char mb_string [256];
|
||||
|
||||
// create a sequence of two multibyte characters
|
||||
rw_sprintf (mb_string, "%s%s", mb_chars [0], mb_chars [1]);
|
||||
|
||||
// +------------------- source sequence of multibyte externT characters
|
||||
// | +-------- lenght of externT sequence in chars (bytes)
|
||||
// | | +----- maximum number of internT characters
|
||||
// | | | +-- expected result in externT characters (bytes)
|
||||
// | | | |
|
||||
// V V V V
|
||||
TEST (mb_string, 0, 0, 0);
|
||||
TEST (mb_string, 1, 1, 1);
|
||||
TEST (mb_string, 1, 1, 1);
|
||||
TEST (mb_string, 2, 1, 1);
|
||||
TEST (mb_string, 2, 2, 1);
|
||||
TEST (mb_string, 3, 1, 1);
|
||||
TEST (mb_string, 3, 2, 3);
|
||||
TEST (mb_string, 3, 3, 3);
|
||||
|
||||
TEST (mb_string, 3, -1, 3);
|
||||
|
||||
// exercise embedded NULs
|
||||
rw_sprintf (mb_string, "%c%s%s", '\0', mb_chars [0], mb_chars [1]);
|
||||
TEST (mb_string, 4, 3, 4);
|
||||
|
||||
rw_sprintf (mb_string, "%s%c%s", mb_chars [0], '\0', mb_chars [1]);
|
||||
TEST (mb_string, 4, 3, 4);
|
||||
|
||||
rw_sprintf (mb_string, "%s%s%c", mb_chars [0], mb_chars [1], '\0');
|
||||
TEST (mb_string, 4, 3, 4);
|
||||
|
||||
rw_sprintf (mb_string, "%c%c%s", '\0', '\0', mb_chars [0]);
|
||||
TEST (mb_string, 3, 3, 3);
|
||||
|
||||
rw_sprintf (mb_string, "%c%c%s", '\0', '\0', mb_chars [1]);
|
||||
TEST (mb_string, 4, 3, 4);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise sequences containing 3-byte characters
|
||||
|
||||
if (mb_cur_max < 3)
|
||||
return;
|
||||
|
||||
// create a sequence of three multibyte characters, 3, 2,
|
||||
// and 1 byte long (and total length of (3+2+1)=6 bytes)
|
||||
// with the following pattern: "<333><22><1>"
|
||||
rw_sprintf (mb_string, "%s%s%s",
|
||||
mb_chars [2], mb_chars [1], mb_chars [0]);
|
||||
|
||||
TEST (mb_string, 0, 3, 0); // ""
|
||||
TEST (mb_string, 1, 3, 0); // "3"
|
||||
TEST (mb_string, 2, 3, 0); // "33"
|
||||
TEST (mb_string, 3, 3, 3); // "333" -> 1 complete internT
|
||||
TEST (mb_string, 4, 3, 3); // "3332"
|
||||
TEST (mb_string, 5, 3, 5); // "33322" -> 2 complete internT's
|
||||
TEST (mb_string, 6, 3, 6); // "333221" -> 3 complete internT's
|
||||
TEST (mb_string, 6, 4, 6);
|
||||
TEST (mb_string, 6, -1, 6);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise sequences containing 4-byte characters
|
||||
|
||||
if (mb_cur_max < 4)
|
||||
return;
|
||||
|
||||
// create a sequence of four multibyte characters, 4, 3, 2,
|
||||
// and 1 byte long (and total length of (4+3+2+1)=10 bytes)
|
||||
// with the following pattern: "<4444><333><22><1>"
|
||||
rw_sprintf (mb_string, "%s%s%s%s",
|
||||
mb_chars [3], mb_chars [2], mb_chars [1], mb_chars [0]);
|
||||
|
||||
TEST (mb_string, 0, 4, 0); // ""
|
||||
TEST (mb_string, 1, 4, 0); // "4"
|
||||
TEST (mb_string, 2, 4, 0); // "44"
|
||||
TEST (mb_string, 3, 4, 0); // "444"
|
||||
TEST (mb_string, 4, 4, 4); // "4444" -> 1 complete internT
|
||||
TEST (mb_string, 5, 4, 4); // "44443"
|
||||
TEST (mb_string, 6, 4, 4); // "444433"
|
||||
TEST (mb_string, 7, 4, 7); // "4444333" -> 2 complete internT's
|
||||
TEST (mb_string, 8, 4, 7); // "44443332"
|
||||
TEST (mb_string, 9, 4, 9); // "444433322" -> 3 complete internT's
|
||||
TEST (mb_string, 10, 4, 10); // "4444333221" -> 4 complete internT's
|
||||
TEST (mb_string, 10, 5, 10);
|
||||
TEST (mb_string, 10, -1, 10);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise sequences containing 5-byte characters
|
||||
|
||||
if (mb_cur_max < 5)
|
||||
return;
|
||||
|
||||
// create a sequence of five multibyte characters, 5, 4, 3, 2,
|
||||
// and 1 byte long (and total length of (5+4+3+2+1)=15 bytes)
|
||||
// with the following pattern: "<55555><4444><333><22><1>"
|
||||
rw_sprintf (mb_string, "%s%s%s%s%s",
|
||||
mb_chars [4], mb_chars [3], mb_chars [2], mb_chars [1],
|
||||
mb_chars [0]);
|
||||
|
||||
TEST (mb_string, 0, 5, 0); // ""
|
||||
TEST (mb_string, 1, 5, 0); // "5"
|
||||
TEST (mb_string, 2, 5, 0); // "55"
|
||||
TEST (mb_string, 3, 5, 0); // "555"
|
||||
TEST (mb_string, 4, 5, 0); // "5555"
|
||||
TEST (mb_string, 5, 5, 5); // "55555"
|
||||
TEST (mb_string, 6, 5, 5); // "555554"
|
||||
TEST (mb_string, 7, 5, 5); // "5555544"
|
||||
TEST (mb_string, 8, 5, 5); // "55555444"
|
||||
TEST (mb_string, 9, 5, 9); // "555554444"
|
||||
TEST (mb_string, 10, 5, 9); // "5555544443"
|
||||
TEST (mb_string, 11, 5, 9); // "55555444433"
|
||||
TEST (mb_string, 12, 5, 12); // "555554444333"
|
||||
TEST (mb_string, 13, 5, 12); // "5555544443332"
|
||||
TEST (mb_string, 14, 5, 14); // "55555444433322"
|
||||
TEST (mb_string, 15, 5, 15); // "555554444333221"
|
||||
TEST (mb_string, 15, 6, 15);
|
||||
TEST (mb_string, 15, -1, 15);
|
||||
|
||||
// create a sequence of five multibyte characters, each 5 bytes long
|
||||
// with the following pattern: "<55555><55555><55555><55555><55555>"
|
||||
rw_sprintf (mb_string, "%s%s%s%s%s",
|
||||
mb_chars [4], mb_chars [4], mb_chars [4], mb_chars [4],
|
||||
mb_chars [4]);
|
||||
|
||||
TEST (mb_string, 5, 5, 5); // "<55555>"
|
||||
TEST (mb_string, 6, 5, 5); // "<55555><5"
|
||||
TEST (mb_string, 9, 5, 5); // "<55555><5555"
|
||||
TEST (mb_string, 10, 1, 5); // "<55555><55555>"
|
||||
TEST (mb_string, 10, 2, 10);
|
||||
TEST (mb_string, 10, 5, 10);
|
||||
TEST (mb_string, 11, 5, 10); // "<55555><55555><5"
|
||||
TEST (mb_string, 14, 5, 10); // "<55555><55555><5555"
|
||||
TEST (mb_string, 15, 5, 15); // "<55555><55555><55555>"
|
||||
|
||||
rw_sprintf (mb_string, "%s%s%s%s%s",
|
||||
mb_chars [4], mb_chars [0], mb_chars [4], mb_chars [4],
|
||||
mb_chars [4]);
|
||||
|
||||
// internT: 0 1 2 3 4 5
|
||||
// externT: <-----><-><-----><-----><-----><
|
||||
// "<55555><1><55555><55555><55555>"
|
||||
TEST (mb_string, 5, 5, 5); // |-----> > > > >
|
||||
TEST (mb_string, 6, 5, 6); // |--------> > > >
|
||||
TEST (mb_string, 7, 5, 6); // |----------- > > >
|
||||
TEST (mb_string, 8, 5, 6); // |------------ > > >
|
||||
TEST (mb_string, 9, 5, 6); // |------------- > > >
|
||||
TEST (mb_string, 10, 5, 6); // |-------------- > > >
|
||||
TEST (mb_string, 11, 5, 11); // |---------------> > >
|
||||
TEST (mb_string, 12, 5, 11); // |---------------- > >
|
||||
TEST (mb_string, 15, 5, 11); // |--------------------- > >
|
||||
TEST (mb_string, 16, 5, 16); // |----------------------> >
|
||||
TEST (mb_string, 21, 5, 21); // |----------------------------->
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
|
||||
static void
|
||||
test_wcodecvt_byname ()
|
||||
{
|
||||
rw_info (0, 0, 0,
|
||||
"std::codecvt_byname<wchar_t, char, mbstate_t>::length "
|
||||
"(state_type&, const extern_type*, const extern_type*, "
|
||||
"size_t)");
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
test_wcodecvt_byname_algorithmic ();
|
||||
test_wcodecvt_byname_table_based ();
|
||||
test_wcodecvt_byname_libc_based ();
|
||||
|
||||
#else // if defined (_RWSTD_NO_WCHAR_T)
|
||||
|
||||
rw_warn (0, 0, __LINE__, "_RWSTD_NO_WCHAR_T #defined, cannot test");
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int no_codecvt;
|
||||
static int no_codecvt_byname;
|
||||
static int no_wcodecvt;
|
||||
static int no_wcodecvt_byname;
|
||||
|
||||
static int
|
||||
run_test (int, char*[])
|
||||
{
|
||||
// set up RWSTD_LOCALE_ROOT and other environment variables
|
||||
// here as opposed to at program startup to work around a
|
||||
// SunOS 5.7 bug in putenv() (PR #30017)
|
||||
locale_root = rw_set_locale_root ();
|
||||
|
||||
#undef TEST
|
||||
#define TEST(what) \
|
||||
if (no_ ## what) { \
|
||||
rw_note (0, 0, __LINE__, "%s test disabled", #what); \
|
||||
} \
|
||||
else { \
|
||||
test_ ## what (); \
|
||||
} typedef void unused_typedef
|
||||
|
||||
|
||||
if (rw_enabled ("char")) {
|
||||
TEST (codecvt);
|
||||
TEST (codecvt_byname);
|
||||
}
|
||||
else {
|
||||
rw_note (0, 0, 0, "char tests disabled");
|
||||
}
|
||||
|
||||
if (rw_enabled ("wchar_t")) {
|
||||
TEST (wcodecvt);
|
||||
TEST (wcodecvt_byname);
|
||||
}
|
||||
else {
|
||||
rw_note (0, 0, 0, "wchar_t tests disabled");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.codecvt.virtuals",
|
||||
0 /* no comment */, run_test,
|
||||
"|-no-codecvt# "
|
||||
"|-no-codecvt_byname# "
|
||||
"|-no-wcodecvt# "
|
||||
"|-no-wcodecvt_byname# ",
|
||||
&no_codecvt,
|
||||
&no_codecvt_byname,
|
||||
&no_wcodecvt,
|
||||
&no_wcodecvt_byname);
|
||||
}
|
||||
564
extern/stdcxx/4.2.1/tests/localization/22.locale.codecvt.mt.cpp
vendored
Normal file
564
extern/stdcxx/4.2.1/tests/localization/22.locale.codecvt.mt.cpp
vendored
Normal file
@@ -0,0 +1,564 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.codecvt.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the codecvt facet
|
||||
*
|
||||
* $Id: 22.locale.codecvt.mt.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 <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, codecvt
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
#include <cwchar> // for codecvt
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h>
|
||||
#include <valcmp.h> // for rw_strncmp ()
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int rw_opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int rw_opt_nloops = 5000;
|
||||
|
||||
// number of locales to use
|
||||
int rw_opt_nlocales = MAX_THREADS;
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int rw_opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
//
|
||||
template <class internT> //, class externT = char, class stateT = std::mbstate_t>
|
||||
struct MyCodecvtData_T
|
||||
{
|
||||
enum { BufferSize = 16 };
|
||||
|
||||
typedef char externT;
|
||||
typedef std::mbstate_t stateT;
|
||||
typedef std::codecvt_base::result resultT;
|
||||
typedef std::size_t sizeT;
|
||||
|
||||
int encoding_;
|
||||
sizeT length_;
|
||||
int max_length_;
|
||||
bool always_noconv_;
|
||||
|
||||
externT out_buffer_ [BufferSize];
|
||||
resultT out_result_;
|
||||
sizeT out_length_;
|
||||
stateT out_state_;
|
||||
|
||||
internT in_buffer_ [BufferSize];
|
||||
resultT in_result_;
|
||||
sizeT in_length_;
|
||||
stateT in_state_;
|
||||
};
|
||||
|
||||
//
|
||||
struct MyCodecvtData
|
||||
{
|
||||
// out, unshift, in, encoding, always_noconv, length, max_length
|
||||
enum CvtId {
|
||||
cvt_out,
|
||||
cvt_unshift,
|
||||
cvt_in,
|
||||
cvt_encoding,
|
||||
cvt_length,
|
||||
cvt_max_length,
|
||||
cvt_always_noconv,
|
||||
cvt_max
|
||||
};
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
MyCodecvtData_T<char> char_data_;
|
||||
MyCodecvtData_T<wchar_t> wchar_data_;
|
||||
|
||||
} my_codecvt_data [MAX_THREADS];
|
||||
|
||||
template <class charT>
|
||||
struct MyBuffer {
|
||||
const charT* const str;
|
||||
const int str_len;
|
||||
};
|
||||
|
||||
const MyBuffer<char> nsrc [] = {
|
||||
{ "a\x80", 2 },
|
||||
{ "b", 1 },
|
||||
{ "c\0c", 3 },
|
||||
{ "ddd", 3 },
|
||||
{ "e\fce\0", 4 },
|
||||
{ "ff\0ffff", 5 },
|
||||
{ "gggg\0g", 6 },
|
||||
{ "hh\0hhhh", 7 },
|
||||
{ "i\ni\tiiii", 8 },
|
||||
{ "jjjjjjjjj", 9 },
|
||||
{ "kkkkkkkkkk", 10 }
|
||||
};
|
||||
|
||||
const MyBuffer<wchar_t> wsrc [] = {
|
||||
{ L"\x0905\x0916", 2 },
|
||||
{ L"bb", 2 },
|
||||
{ L"\x106c", 2 },
|
||||
{ L"dddd", 4 },
|
||||
{ L"\xd800\xd801", 2 },
|
||||
{ L"ffffff", 6 },
|
||||
{ L"\xdfff\xffff", 2 },
|
||||
{ L"hhhhhhhh", 8 },
|
||||
{ L"i\0i\1i", 4 },
|
||||
{ L"jjjjjjjjjj", 10 },
|
||||
{ L"kkkkkkkkkkk", 11 }
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <typename T>
|
||||
struct test_is_char
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
template <>
|
||||
struct test_is_char<char>
|
||||
{
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class internT>
|
||||
void test_codecvt (const std::locale& loc,
|
||||
const MyBuffer<internT>& in,
|
||||
const MyBuffer<char>& out,
|
||||
const MyCodecvtData_T<internT>& data,
|
||||
const MyCodecvtData::CvtId id)
|
||||
{
|
||||
|
||||
typedef char externT;
|
||||
typedef std::mbstate_t stateT;
|
||||
typedef std::size_t sizeT;
|
||||
|
||||
typedef std::codecvt<internT, externT, stateT> code_cvt_type;
|
||||
|
||||
const code_cvt_type& cvt =
|
||||
std::use_facet<code_cvt_type>(loc);
|
||||
|
||||
switch (id) {
|
||||
case MyCodecvtData::cvt_out:
|
||||
{
|
||||
externT out_buffer [MyCodecvtData_T<internT>::BufferSize];
|
||||
out_buffer [0] = externT ();
|
||||
|
||||
const int out_len = RW_COUNT_OF (out_buffer);
|
||||
|
||||
const internT* from = in.str;
|
||||
const internT* from_end = in.str + in.str_len;
|
||||
const internT* from_next = 0;
|
||||
|
||||
externT* to = out_buffer;
|
||||
externT* to_limit = out_buffer + out_len;
|
||||
externT* to_next = 0;
|
||||
|
||||
std::mbstate_t state = std::mbstate_t ();
|
||||
|
||||
const typename MyCodecvtData_T<internT>::resultT result =
|
||||
cvt.out (state, from, from_end, from_next,
|
||||
to, to_limit, to_next);
|
||||
|
||||
const sizeT len = to_next - to;
|
||||
|
||||
RW_ASSERT (data.out_result_ == result);
|
||||
RW_ASSERT (len == data.out_length_);
|
||||
RW_ASSERT (!rw_strncmp (out_buffer, data.out_buffer_, len));
|
||||
}
|
||||
break;
|
||||
case MyCodecvtData::cvt_unshift:
|
||||
{
|
||||
externT out_buffer [MyCodecvtData_T<internT>::BufferSize];
|
||||
out_buffer [0] = externT ();
|
||||
|
||||
const int out_len = RW_COUNT_OF (out_buffer);
|
||||
|
||||
externT* to = out_buffer;
|
||||
externT* to_limit = out_buffer + out_len;
|
||||
externT* to_next = 0;
|
||||
|
||||
std::mbstate_t state = std::mbstate_t ();
|
||||
|
||||
const typename MyCodecvtData_T<internT>::resultT result =
|
||||
cvt.unshift (state, to, to_limit, to_next);
|
||||
|
||||
// 22.2.1.5.2 p5
|
||||
RW_ASSERT (to == to_next);
|
||||
|
||||
// 22.2.1.5.2 p6 required only for codecvt<char, char, mbstate_t>
|
||||
RW_ASSERT ( !test_is_char<internT>::value
|
||||
|| result == std::codecvt_base::noconv);
|
||||
}
|
||||
break;
|
||||
case MyCodecvtData::cvt_in:
|
||||
{
|
||||
internT in_buffer [MyCodecvtData_T<internT>::BufferSize];
|
||||
in_buffer [0] = internT ();
|
||||
|
||||
const int in_len = RW_COUNT_OF (in_buffer);
|
||||
const int out_len = RW_COUNT_OF (data.out_buffer_);
|
||||
|
||||
const externT* from = data.out_buffer_;
|
||||
const externT* from_end = data.out_buffer_ + out_len;
|
||||
const externT* from_next = 0;
|
||||
|
||||
internT* to = in_buffer;
|
||||
internT* to_limit = in_buffer + in_len;
|
||||
internT* to_next = 0;
|
||||
|
||||
std::mbstate_t state = std::mbstate_t ();
|
||||
|
||||
const typename MyCodecvtData_T<internT>::resultT result =
|
||||
cvt.in (state, from, from_end, from_next,
|
||||
to, to_limit, to_next);
|
||||
|
||||
const sizeT len = to_next - to;
|
||||
|
||||
RW_ASSERT (data.in_result_ == result);
|
||||
RW_ASSERT (len == data.in_length_);
|
||||
RW_ASSERT (!rw_strncmp (in_buffer, data.in_buffer_, len));
|
||||
}
|
||||
break;
|
||||
case MyCodecvtData::cvt_encoding:
|
||||
RW_ASSERT (data.encoding_ == cvt.encoding ());
|
||||
break;
|
||||
|
||||
case MyCodecvtData::cvt_length:
|
||||
{
|
||||
const externT* from = out.str;
|
||||
const externT* from_end = out.str + out.str_len;
|
||||
const size_t max = 32;
|
||||
|
||||
std::mbstate_t state = std::mbstate_t ();
|
||||
|
||||
const sizeT len = cvt.length (state, from, from_end, max);
|
||||
|
||||
RW_ASSERT (data.length_ == len);
|
||||
}
|
||||
break;
|
||||
|
||||
case MyCodecvtData::cvt_max_length:
|
||||
RW_ASSERT (data.max_length_ == cvt.max_length ());
|
||||
break;
|
||||
case MyCodecvtData::cvt_always_noconv:
|
||||
RW_ASSERT (data.always_noconv_ == cvt.always_noconv ());
|
||||
break;
|
||||
case MyCodecvtData::cvt_max:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise codecvt<char,char>
|
||||
bool test_wchar; // exercise codecvt<wchar_t,char>
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
const int ni = RW_COUNT_OF (nsrc);
|
||||
const int wi = RW_COUNT_OF (wsrc);
|
||||
|
||||
for (int i = 0; i != rw_opt_nloops; ++i) {
|
||||
|
||||
const int inx = i % nlocales;
|
||||
const MyCodecvtData& data = my_codecvt_data [inx];
|
||||
|
||||
// construct a named locale, get a reference to the codecvt
|
||||
// facet from it and use it to format a random money value
|
||||
const std::locale loc =
|
||||
rw_opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
const MyCodecvtData::CvtId op =
|
||||
MyCodecvtData::CvtId (i % MyCodecvtData::cvt_max);
|
||||
|
||||
if (test_char) {
|
||||
test_codecvt<char>(loc, nsrc [inx % ni], nsrc [inx % ni],
|
||||
data.char_data_, op);
|
||||
}
|
||||
|
||||
if (test_wchar) {
|
||||
test_codecvt<wchar_t>(loc, wsrc [inx % wi], nsrc [inx % ni],
|
||||
data.wchar_data_, op);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class internT>
|
||||
void run_test_fill (const std::locale& loc,
|
||||
const MyBuffer<internT>& in,
|
||||
const MyBuffer<char>& out,
|
||||
MyCodecvtData_T<internT>& data)
|
||||
{
|
||||
|
||||
typedef char externT;
|
||||
typedef std::mbstate_t stateT;
|
||||
|
||||
typedef std::codecvt<internT, externT, stateT> code_cvt_type;
|
||||
|
||||
const code_cvt_type& cvt =
|
||||
std::use_facet<code_cvt_type>(loc);
|
||||
|
||||
//fill in the appropriate fields of data
|
||||
data.encoding_ = cvt.encoding ();
|
||||
data.max_length_ = cvt.max_length ();
|
||||
data.always_noconv_ = cvt.always_noconv ();
|
||||
|
||||
// length
|
||||
{
|
||||
const externT* from = out.str;
|
||||
const externT* from_end = out.str + out.str_len;
|
||||
const size_t max = 32;
|
||||
|
||||
std::mbstate_t state = std::mbstate_t ();
|
||||
|
||||
data.length_ = cvt.length (state, from, from_end, max);
|
||||
}
|
||||
|
||||
// out
|
||||
{
|
||||
const int out_len = RW_COUNT_OF (data.out_buffer_);
|
||||
|
||||
const internT* from = in.str;
|
||||
const internT* from_end = in.str + in.str_len;
|
||||
const internT* from_next = 0;
|
||||
|
||||
externT* to = data.out_buffer_;
|
||||
externT* to_limit = data.out_buffer_ + out_len;
|
||||
externT* to_next = 0;
|
||||
|
||||
data.out_result_ = cvt.out (data.out_state_,
|
||||
from, from_end, from_next,
|
||||
to, to_limit, to_next);
|
||||
|
||||
data.out_length_ = to_next - to;
|
||||
}
|
||||
|
||||
//// unshift
|
||||
//{
|
||||
// externT* to = data.out_buffer_;
|
||||
// externT* to_limit = data.out_buffer_ + RW_COUNT_OF (data.out_buffer_);
|
||||
// externT* to_next = 0;
|
||||
|
||||
// std::mbstate_t state = std::mbstate_t ();
|
||||
|
||||
// data.shift_result_ = cvt.unshift (state, to, to_limit, to_next);
|
||||
//}
|
||||
|
||||
// in
|
||||
{
|
||||
const int out_len = RW_COUNT_OF (data.out_buffer_);
|
||||
const int in_len = RW_COUNT_OF (data.in_buffer_);
|
||||
|
||||
const externT* from = data.out_buffer_;
|
||||
const externT* from_end = data.out_buffer_ + out_len;
|
||||
const externT* from_next = 0;
|
||||
|
||||
internT* to = data.in_buffer_;
|
||||
internT* to_limit = data.in_buffer_ + in_len;
|
||||
internT* to_next = 0;
|
||||
|
||||
data.in_result_ = cvt.in (data.in_state_,
|
||||
from, from_end, from_next,
|
||||
to, to_limit, to_next);
|
||||
|
||||
data.in_length_ = to_next - to;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// find all installed locales for which setlocale (LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
const int ni = RW_COUNT_OF (nsrc);
|
||||
const int wi = RW_COUNT_OF (wsrc);
|
||||
|
||||
for (const char* name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the money and results for this locale
|
||||
MyCodecvtData& data = my_codecvt_data [inx];
|
||||
data.locale_name_ = name;
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
run_test_fill<char>
|
||||
(loc, nsrc [inx % ni], nsrc [inx % ni], data.char_data_);
|
||||
|
||||
run_test_fill<wchar_t>
|
||||
(loc, wsrc [inx % wi], nsrc [inx % ni], data.wchar_data_);
|
||||
|
||||
if (rw_opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::codecvt<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
rw_opt_nthreads, 1 != rw_opt_nthreads,
|
||||
rw_opt_nloops, 1 != rw_opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::codecvt<char, char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::codecvt<wchar_t, char>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::codecvt<char, char> and "
|
||||
"std::codecvt<wchar_t, char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
rw_opt_nthreads = rw_get_cpus ();
|
||||
if (rw_opt_nthreads < 2)
|
||||
rw_opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.codecvt",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&rw_opt_nthreads,
|
||||
&rw_opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&rw_opt_shared_locale);
|
||||
}
|
||||
1124
extern/stdcxx/4.2.1/tests/localization/22.locale.codecvt.out.cpp
vendored
Normal file
1124
extern/stdcxx/4.2.1/tests/localization/22.locale.codecvt.out.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
221
extern/stdcxx/4.2.1/tests/localization/22.locale.cons.mt.cpp
vendored
Normal file
221
extern/stdcxx/4.2.1/tests/localization/22.locale.cons.mt.cpp
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.cons.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of locale ctors
|
||||
*
|
||||
* $Id: 22.locale.cons.mt.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 <locale> // for locale
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h> // for rw_get_processors (), rw_thread_pool()
|
||||
#include <driver.h>
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int opt_nloops = 20000;
|
||||
|
||||
// tristate flag set in response to the --no-combine/--enable-combine
|
||||
// command line option
|
||||
int opt_combine;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void*
|
||||
test_ctors (void*)
|
||||
{
|
||||
static const std::locale::category cats[] = {
|
||||
std::locale::all,
|
||||
std::locale::collate,
|
||||
std::locale::ctype,
|
||||
std::locale::messages,
|
||||
std::locale::monetary,
|
||||
std::locale::numeric,
|
||||
std::locale::time,
|
||||
std::locale::none
|
||||
};
|
||||
|
||||
static const std::size_t ncats = sizeof cats / sizeof *cats;
|
||||
|
||||
// the next locale "advanced" in each iteration of the loop
|
||||
std::locale next (locales [0]);
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
// compute an index into the array of locales
|
||||
const std::size_t linx = i % nlocales;
|
||||
|
||||
// create two locale objects from the same name and verify
|
||||
// they are equal
|
||||
const std::locale first (next.name ().c_str ());
|
||||
const std::locale second (next.name ().c_str ());
|
||||
|
||||
RW_ASSERT (first == second);
|
||||
|
||||
// create another locale object as a copy of one of the two
|
||||
// above and verify it's equal to the other
|
||||
const std::locale third (first);
|
||||
|
||||
RW_ASSERT (second == third);
|
||||
|
||||
// compute the next index into the array of locales
|
||||
const std::size_t ninx = (i + 1) % nlocales;
|
||||
const char* const next_name = locales [ninx];
|
||||
|
||||
// create the next locale from a name
|
||||
next = std::locale (next_name);
|
||||
|
||||
if (0 <= opt_combine) {
|
||||
// compute an index into the array of categories
|
||||
const std::size_t cinx = i % ncats;
|
||||
const std::locale::category cat = cats [cinx];
|
||||
|
||||
// create a locale from another object and the name of yet
|
||||
// another locale, combining some (none, one, or all) of their
|
||||
// categories
|
||||
const std::locale combined (first, next_name, cat);
|
||||
|
||||
// verify that the locales were created correctly
|
||||
if ( std::locale::none == cat
|
||||
#ifdef _MSC_VER
|
||||
|| std::locale::messages == cat
|
||||
#endif
|
||||
|| first == next) {
|
||||
RW_ASSERT (combined == first);
|
||||
}
|
||||
else if (std::locale::all == cat)
|
||||
RW_ASSERT (combined == next);
|
||||
else
|
||||
RW_ASSERT (combined != first && combined != next);
|
||||
|
||||
// repeat the step above but with a locale object
|
||||
const std::locale combined_2 (first, next, cat);
|
||||
|
||||
if ( std::locale::none == cat
|
||||
#ifdef _MSC_VER
|
||||
|| std::locale::messages == cat
|
||||
#endif
|
||||
|| first == next) {
|
||||
RW_ASSERT (combined_2 == first);
|
||||
}
|
||||
else if (std::locale::all == cat)
|
||||
RW_ASSERT (combined_2 == next);
|
||||
else
|
||||
RW_ASSERT (combined_2 != first && combined_2 != next);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = sizeof locales / sizeof *locales;
|
||||
|
||||
for (const char *name = locale_list; *name; name += std::strlen (name) +1) {
|
||||
|
||||
locales [nlocales++] = name;
|
||||
|
||||
if (nlocales == maxinx)
|
||||
break;
|
||||
}
|
||||
|
||||
int result;
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::locale ctors with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
|
||||
test_ctors, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, test_ctors);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.cons",
|
||||
"thread safety", run_test,
|
||||
"|-combine~ "
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-locales=", // must be provided
|
||||
&opt_combine,
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&rw_opt_setlocales);
|
||||
}
|
||||
1718
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.cpp
vendored
Normal file
1718
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1070
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.is.cpp
vendored
Normal file
1070
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.is.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
335
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.mt.cpp
vendored
Normal file
335
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.mt.cpp
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.ctype.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the ctype facet
|
||||
*
|
||||
* $Id: 22.locale.ctype.mt.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 <locale> // for locale, ctype
|
||||
|
||||
#include <clocale> // for lconv, localeconv()
|
||||
#include <cstdlib> // for mbstowcs()
|
||||
#include <cstring> // for size_t, strcpy()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h>
|
||||
#include <valcmp.h>
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 16
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int opt_nloops = 200000;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around an inefficiency (small cache size?) on HP-UX
|
||||
// in LP64 mode (see STDCXX-812)
|
||||
int opt_nlocales = 10;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
struct CtypeData
|
||||
{
|
||||
// the name of the locale the data corresponds to
|
||||
const char *locale_name_;
|
||||
|
||||
// optionally set to the named locale for the threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// results of ctype<charT>::widen(char) for char and wchar_t
|
||||
char widened_ [256];
|
||||
wchar_t wwidened_ [256];
|
||||
|
||||
// array of wide characters to narrow and the number
|
||||
// of valid elements in the array
|
||||
wchar_t wide_ [1024];
|
||||
std::size_t nwide_;
|
||||
|
||||
// results of ctype<charT>::narrow(charT, char) for char
|
||||
// and wchar_t values of wide_ [i]
|
||||
char narrowed_ [256];
|
||||
char wnarrowed_ [1024];
|
||||
|
||||
} ctype_data [MAX_THREADS];
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise num_put<char>
|
||||
bool test_wchar; // exercise num_put<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
// number of narrow characters to test (should be 256)
|
||||
const std::size_t nchars =
|
||||
sizeof ctype_data->widened_ / sizeof *ctype_data->widened_;
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
const std::size_t inx = std::size_t (i) % nlocales;
|
||||
|
||||
// save the name of the locale
|
||||
const char* const locale_name = locales [inx];
|
||||
|
||||
const CtypeData* const data = ctype_data + inx;
|
||||
|
||||
// construct a named locale
|
||||
const std::locale loc =
|
||||
opt_shared_locale ? data->locale_ : std::locale (locale_name);
|
||||
|
||||
// "random" index/character value
|
||||
const std::size_t cinx = std::size_t (i) % nchars;
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::ctype<char> &ct =
|
||||
std::use_facet<std::ctype<char> >(loc);
|
||||
|
||||
const char wc = ct.widen (char (cinx));
|
||||
|
||||
RW_ASSERT (wc == data->widened_ [cinx]);
|
||||
|
||||
const char nc = ct.narrow (char (cinx), '\0');
|
||||
|
||||
RW_ASSERT (nc == data->narrowed_ [cinx]);
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::ctype<wchar_t> &wct =
|
||||
std::use_facet<std::ctype<wchar_t> >(loc);
|
||||
|
||||
// "random" index into the wide character array
|
||||
const std::size_t winx =
|
||||
std::size_t (i) % data->nwide_;
|
||||
|
||||
const wchar_t wc = wct.widen (char (cinx));
|
||||
|
||||
RW_ASSERT (wc == data->wwidened_ [cinx]);
|
||||
|
||||
const char nc = wct.narrow (data->wide_ [winx], L'\0');
|
||||
|
||||
RW_ASSERT (nc == data->wnarrowed_ [winx]);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = sizeof locales / sizeof *locales;
|
||||
|
||||
// iterate over locales, initializing a global ctype_data array
|
||||
// with LC_CTYPE data obtained from each locale
|
||||
for (const char *name = locale_list; *name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
|
||||
locales [inx] = name;
|
||||
|
||||
CtypeData* const pdata = ctype_data + nlocales;
|
||||
|
||||
// compute the number of wide characters to populate
|
||||
const std::size_t nwide =
|
||||
sizeof pdata->wide_ / sizeof pdata->wide_ [0];
|
||||
|
||||
try {
|
||||
const std::locale loc (name);
|
||||
|
||||
const std::ctype<char> &ct =
|
||||
std::use_facet<std::ctype<char> >(loc);
|
||||
|
||||
const std::ctype<wchar_t> &wct =
|
||||
std::use_facet<std::ctype<wchar_t> >(loc);
|
||||
|
||||
pdata->locale_name_ = name;
|
||||
|
||||
const std::size_t nchars =
|
||||
sizeof pdata->widened_ / sizeof *pdata->widened_;
|
||||
|
||||
for (std::size_t i = 0; i != nchars; ++i) {
|
||||
pdata->widened_ [i] = ct.widen (char (i));
|
||||
pdata->wwidened_ [i] = wct.widen (char (i));
|
||||
pdata->narrowed_ [i] = ct.narrow (char (i), '\0');
|
||||
}
|
||||
|
||||
pdata->nwide_ = rw_get_wchars (pdata->wide_, nwide);
|
||||
for (std::size_t i = 0; i != pdata->nwide_; ++i)
|
||||
pdata->wnarrowed_ [i] = wct.narrow (pdata->wide_ [i], L'\0');
|
||||
|
||||
if (opt_shared_locale)
|
||||
pdata->locale_ = loc;
|
||||
|
||||
++nlocales;
|
||||
}
|
||||
catch (...) {
|
||||
// skip over a bad locale
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::ctype<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::ctype<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::ctype<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise the thread safety
|
||||
// of the wchar_t specialization
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::ctype<char> and std::ctype<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.ctype",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // arg must be non-negative
|
||||
"|-nthreads#0-* " // arg must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // arg must be provided
|
||||
"|-shared-locale# ",
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&opt_shared_locale);
|
||||
}
|
||||
730
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.narrow.cpp
vendored
Normal file
730
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.narrow.cpp
vendored
Normal file
@@ -0,0 +1,730 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.ctype.narrow.cpp - tests exercising the narrow() and widen()
|
||||
* member functions of the ctype facet
|
||||
*
|
||||
* $Id: 22.locale.ctype.narrow.cpp 650350 2008-04-22 01:35:17Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2001-2008 Rogue Wave Software, Inc.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// DESCRIPTION: The test iterates over a subset of locales installed
|
||||
// on a machine, calling the C character classification functions and
|
||||
// their C++ counterpart(s), comparing the results of the calls against
|
||||
// one another.
|
||||
|
||||
|
||||
#include <rw/_defs.h>
|
||||
|
||||
#if defined __linux__
|
||||
// on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
|
||||
# define _XOPEN_SOURCE 500 /* Single Unix conformance */
|
||||
// bring __int32_t into scope (otherwise <wctype.h> fails to compile)
|
||||
# include <sys/types.h>
|
||||
#endif // __linux__
|
||||
|
||||
// see Onyx PR #28150
|
||||
#if defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
# include <wchar.h>
|
||||
#endif // defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cwchar> // for WEOF, btowc(), wctob()
|
||||
#include <cwctype> // for iswxxx()
|
||||
|
||||
|
||||
#if !defined (_MSC_VER)
|
||||
# if !defined (LC_MESSAGES)
|
||||
# define LC_MESSAGES _RWSTD_LC_MESSAGES
|
||||
# endif // LC_MESSAGES
|
||||
# include <langinfo.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <driver.h>
|
||||
#include <file.h> // for SLASH
|
||||
#include <rw_locale.h> // for rw_locale_query()
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// the root of the locale directory (RWSTD_LOCALE_ROOT)
|
||||
// not set here to avoid Solaris 7 putenv() bug (PR #30017)
|
||||
const char* locale_root;
|
||||
|
||||
#define NLOOPS 25
|
||||
#define MAX_STR_SIZE 16
|
||||
|
||||
#define LOCALES "{{en-US,de-DE,fr-FR,es-ES}-*-{ISO-8859-*,UTF-8,CP125?}," \
|
||||
"{ja-JP-*-{EUC-JP,SHIFT_JIS,UTF-8,CP125?}}," \
|
||||
"{zh-CN-*-{GB*,UTF-8,CP125?}}," \
|
||||
"{ru-RU-*-{KOI*,UTF-8,CP125?}}}"
|
||||
|
||||
const char* locale_list = 0;
|
||||
|
||||
#define BEGIN_LOCALE_LOOP(num, locname, loop_cntrl) \
|
||||
if (!locale_list) locale_list = rw_locale_query (LC_CTYPE, LOCALES); \
|
||||
for (const char* locname = locale_list; \
|
||||
locname && *locname; locname += std::strlen (locname) + 1) { \
|
||||
_TRY { \
|
||||
const std::locale loc (locname); \
|
||||
const std::ctype<char> &ctc = \
|
||||
_STD_USE_FACET (std::ctype<char>, loc); \
|
||||
_RWSTD_UNUSED (ctc); \
|
||||
const std::ctype<charT> &ctp = \
|
||||
_STD_USE_FACET (std::ctype<charT>, loc); \
|
||||
for (int loop_cntrl = 0; loop_cntrl < int (num); loop_cntrl++)
|
||||
|
||||
#define END_LOCALE_LOOP(locname) \
|
||||
} \
|
||||
_CATCH (...) { \
|
||||
rw_assert (0, 0, __LINE__, \
|
||||
"locale (\"%s\") threw an exception", locname); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// for notational convenience
|
||||
typedef unsigned char UChar;
|
||||
|
||||
#define ALPHA std::ctype_base::alpha
|
||||
#define UPPER std::ctype_base::upper
|
||||
#define LOWER std::ctype_base::lower
|
||||
#define DIGIT std::ctype_base::digit
|
||||
#define SPACE std::ctype_base::space
|
||||
#define CNTRL std::ctype_base::cntrl
|
||||
#define PUNCT std::ctype_base::punct
|
||||
#define XDIGIT std::ctype_base::xdigit
|
||||
#define GRAPH std::ctype_base::graph
|
||||
#define PRINT std::ctype_base::print
|
||||
|
||||
|
||||
// wrapper functions for the c library char and wchar_t functions
|
||||
|
||||
std::ctype_base::mask libc_mask (int mask, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
|
||||
if (locname) {
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return std::ctype_base::mask ();
|
||||
}
|
||||
|
||||
const int c = UChar (ch);
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (mask & ALPHA && (std::isalpha)(c))
|
||||
result |= ALPHA;
|
||||
if (mask & CNTRL && (std::iscntrl)(c))
|
||||
result |= CNTRL;
|
||||
if (mask & DIGIT && (std::isdigit)(c))
|
||||
result |= DIGIT;
|
||||
if (mask & GRAPH && (std::isgraph)(c))
|
||||
result |= GRAPH;
|
||||
if (mask & LOWER && (std::islower)(c))
|
||||
result |= LOWER;
|
||||
if (mask & PRINT && (std::isprint)(c))
|
||||
result |= PRINT;
|
||||
if (mask & PUNCT && (std::ispunct)(c))
|
||||
result |= PUNCT;
|
||||
if (mask & SPACE && (std::isspace)(c))
|
||||
result |= SPACE;
|
||||
if (mask & UPPER && (std::isupper)(c))
|
||||
result |= UPPER;
|
||||
if (mask & XDIGIT && (std::isxdigit)(c))
|
||||
result |= XDIGIT;
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return std::ctype_base::mask (result);
|
||||
}
|
||||
|
||||
inline bool libc_is (std::ctype_base::mask mask, char ch, const char *locname)
|
||||
{
|
||||
const std::ctype_base::mask m = libc_mask (mask, ch, locname);
|
||||
|
||||
return 0 != (m & mask);
|
||||
}
|
||||
|
||||
const char* narrow (char *dst, const char *src)
|
||||
{
|
||||
if (src == dst || !src || !dst)
|
||||
return src;
|
||||
|
||||
std::memcpy (dst, src, std::strlen (src) + 1);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
const char* widen (char *dst, const char *src)
|
||||
{
|
||||
if (src == dst || !src || !dst)
|
||||
return src;
|
||||
|
||||
std::memcpy (dst, src, std::strlen (src) + 1);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
char widen (char, char ch, const char*)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
char narrow (char ch, const char*)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
// cond1() verifies condition [1] in test_narrow_widen()
|
||||
// below using libc functions
|
||||
bool cond1 (std::ctype_base::mask mask, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return false;
|
||||
|
||||
#ifdef __SUNPRO_CC
|
||||
|
||||
// working around a SunPro bug (PR #28150)
|
||||
using std::wint_t;
|
||||
|
||||
#endif // __SUNPRO_CC
|
||||
|
||||
#ifndef _RWSTD_NO_BTOWC
|
||||
|
||||
const std::wint_t wc = std::btowc (UChar (ch));
|
||||
|
||||
#elif !defined (_RWSTD_NO_MBSTOWCS)
|
||||
|
||||
wchar_t tmp;
|
||||
const std::wint_t wc = 1 == std::mbstowcs (&tmp, &ch, 1) ? tmp : WEOF;
|
||||
|
||||
#else
|
||||
|
||||
const std::wint_t wc = WEOF;
|
||||
|
||||
#endif // _RWSTD_NO_BTOWC, _RWSTD_NO_MBSTOWCS
|
||||
|
||||
const bool result =
|
||||
WEOF == wc || libc_is (mask, ch, 0) || !libc_is (mask, wchar_t (wc), 0);
|
||||
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// cond3() overloads verify condition [3] in test_narrow_widen()
|
||||
// below using libc functions
|
||||
bool cond3 (std::ctype_base::mask, char, const char*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const char* narrow (char *dst, const wchar_t *src)
|
||||
{
|
||||
static char buf [4096];
|
||||
|
||||
if (!src)
|
||||
return 0;
|
||||
|
||||
if (!dst)
|
||||
dst = buf;
|
||||
|
||||
std::size_t len = std::wcslen (src);
|
||||
|
||||
_RWSTD_ASSERT (len < sizeof buf);
|
||||
|
||||
len = std::wcstombs (dst, src, sizeof buf / sizeof *buf);
|
||||
|
||||
if (std::size_t (-1) == len)
|
||||
*dst = 0;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
const wchar_t* widen (wchar_t *dst, const char *src)
|
||||
{
|
||||
static wchar_t buf [4096];
|
||||
|
||||
if (!src)
|
||||
return 0;
|
||||
|
||||
if (!dst)
|
||||
dst = buf;
|
||||
|
||||
std::size_t len = std::strlen (src);
|
||||
|
||||
_RWSTD_ASSERT (len < sizeof buf /sizeof *buf);
|
||||
|
||||
len = std::mbstowcs (dst, src, sizeof buf / sizeof *buf);
|
||||
|
||||
if (std::size_t (-1) == len)
|
||||
*dst = 0;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
std::ctype_base::mask libc_mask (int mask, wchar_t ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
|
||||
if (locname) {
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return std::ctype_base::mask ();
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (mask & ALPHA && (std::iswalpha)(ch))
|
||||
result |= ALPHA;
|
||||
if (mask & CNTRL && (std::iswcntrl)(ch))
|
||||
result |= CNTRL;
|
||||
if (mask & DIGIT && (std::iswdigit)(ch))
|
||||
result |= DIGIT;
|
||||
if (mask & GRAPH && (std::iswgraph)(ch))
|
||||
result |= GRAPH;
|
||||
if (mask & LOWER && (std::iswlower)(ch))
|
||||
result |= LOWER;
|
||||
if (mask & PRINT && (std::iswprint)(ch))
|
||||
result |= PRINT;
|
||||
if (mask & PUNCT && (std::iswpunct)(ch))
|
||||
result |= PUNCT;
|
||||
if (mask & SPACE && (std::iswspace)(ch))
|
||||
result |= SPACE;
|
||||
if (mask & UPPER && (std::iswupper)(ch))
|
||||
result |= UPPER;
|
||||
if (mask & XDIGIT && (std::iswxdigit)(ch))
|
||||
result |= XDIGIT;
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return std::ctype_base::mask (result);
|
||||
}
|
||||
|
||||
bool libc_is (std::ctype_base::mask mask, wchar_t ch, const char *locname)
|
||||
{
|
||||
const std::ctype_base::mask m = libc_mask (mask, ch, locname);
|
||||
|
||||
return 0 != (m & mask);
|
||||
}
|
||||
|
||||
wchar_t widen (wchar_t, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return UChar (ch);
|
||||
|
||||
wchar_t result;
|
||||
|
||||
#ifndef _RWSTD_NO_BTOWC
|
||||
|
||||
result = std::btowc (UChar (ch));
|
||||
|
||||
#elif !defined (_RWSTD_NO_MBTOWC)
|
||||
|
||||
if (1 != std::mbtowc (&result, &ch, 1))
|
||||
result = wchar_t (WEOF);
|
||||
|
||||
#else
|
||||
|
||||
result = UChar (ch);
|
||||
|
||||
#endif // _RWSTD_NO_BTOWC, _RWSTD_NO_MBTOWC
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char narrow (wchar_t ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return UChar (ch);
|
||||
|
||||
char result [MB_LEN_MAX];
|
||||
|
||||
#ifndef _RWSTD_NO_WCTOB
|
||||
|
||||
result [0] = std::wctob (ch);
|
||||
|
||||
#elif !defined (_RWSTD_NO_WCTOMB)
|
||||
|
||||
if (1 != std::wctomb (result, ch))
|
||||
result [0] = '\377';
|
||||
|
||||
#else
|
||||
|
||||
result [0] = char (ch);
|
||||
|
||||
#endif // _RWSTD_NO_WCTOB, _RWSTD_NO_WCTOMB
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result [0];
|
||||
}
|
||||
|
||||
bool cond3 (std::ctype_base::mask mask, wchar_t ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return false;
|
||||
|
||||
#ifndef _RWSTD_NO_WCTOB
|
||||
|
||||
const int byte = std::wctob (ch);
|
||||
|
||||
#elif !defined (_RWSTD_NO_WCTOMB)
|
||||
|
||||
char buf [MB_LEN_MAX];
|
||||
const int byte = 1 == std::wctomb (buf, ch) ? buf [0] : EOF;
|
||||
|
||||
#else
|
||||
|
||||
const int byte = EOF;
|
||||
|
||||
#endif // _RWSTD_NO_WCTOB, _RWSTD_NO_WCTOMB
|
||||
|
||||
const bool result =
|
||||
EOF == byte || !libc_is (mask, char (byte), 0) || libc_is (mask, ch, 0);
|
||||
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_narrow_widen (charT, const char *cname)
|
||||
{
|
||||
// 22.2.1.1.2, p11 requires that the conditions below hold for all
|
||||
// facets ctc and ct whose types are ctype<char> and ctype<charT>,
|
||||
// respectively:
|
||||
|
||||
// [1] (ctc.is (M, c) || !ct.is (M, ctc.do_widen (c))) holds for
|
||||
// all narrow characters c
|
||||
// i.e., narrow characters that are NOT members of a certain
|
||||
// category may not belong to the same category when widened
|
||||
// Note: this implies that some sort of code conversion may
|
||||
// be necessary in order to implement a conforming do_widen()
|
||||
|
||||
// 22.2.1.1.2, p13 requires that:
|
||||
// [2] (ct.do_widen (ct.do_narrow (c, dfault)) == c) holds unless
|
||||
// (ct.do_narrow (c, dfault) == dfault) holds
|
||||
// [3] (ct.is (M, c) || !ctc.is (M, ct.do_narrow (c, dfault))) holds
|
||||
// unless (ct.do_narrow(c, dfault) == dfault) holds
|
||||
//
|
||||
// C99: each of the iswxxx() functions returns true for each
|
||||
// wide character that corresponds (as if by a call to the
|
||||
// wctob() function) to a single-byte character for which the
|
||||
// corresponding character classification function from 7.4.1
|
||||
// returns true, except that the iswgraph() and iswpunct()
|
||||
// functions may differ with respect to wide characters other
|
||||
// than L' ' that are both printing and white-space wide
|
||||
// characters.
|
||||
//
|
||||
// [4] (ct.do_narrow (c, default) - '0') evaluates to the digit
|
||||
// value of the character for all c for which ct.is(digit, c)
|
||||
// returns true
|
||||
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::ctype<%s>::narrow(%1$s), widen(char)",
|
||||
cname);
|
||||
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::ctype<%s>::narrow(const %1$s*, const %1$s*, char*), "
|
||||
"widen(const char*, const char*, %1$s*)", cname);
|
||||
|
||||
#define STR(x) #x
|
||||
|
||||
// verify condition [1] above; if it fails, verify that
|
||||
// the same condition also fails to hold when using the
|
||||
// corresponding libc functions
|
||||
#define COND1(what) \
|
||||
if (!(ctc.is (what, c) || !ctp.is (what, ctp.widen (c)))) { \
|
||||
rw_assert (!cond1 (what, c, locname), 0, __LINE__, \
|
||||
"ctype<char>::is (" STR (what) ", %{#lc})" \
|
||||
" || !ctype<%1$s>::is (" STR (what) ", " \
|
||||
"ctype<%s>::widen (%{#lc}) = %{#lc})" \
|
||||
" returned false in locale(%#s)", \
|
||||
c, cname, c, ctp.widen (c), locname); \
|
||||
} else (void)0
|
||||
|
||||
// verify condition [3] above; if it fails, verify that
|
||||
// the same condition also fails to hold when using the
|
||||
// corresponding libc functions
|
||||
#define COND3(what) \
|
||||
if ( ctp.narrow (ch, dfault) != dfault \
|
||||
&& !(ctp.is (what, ch) || !ctc.is (what, ctp.narrow (ch, dfault)))) { \
|
||||
rw_assert (!cond3 (what, ch, locname), 0, __LINE__, \
|
||||
"ctype<%s>::is (" STR (what) ", %{#lc})" \
|
||||
" || !ctype<char>::is (" STR (what) ", " \
|
||||
"ctype<%1$s>::narrow (%{#lc}, %{#c}) = %{#lc})" \
|
||||
" returned false in locale(%#s)", cname, ch, \
|
||||
ch, dfault, ctp.narrow (ch, '\0'), \
|
||||
locname); \
|
||||
} else (void)0
|
||||
|
||||
|
||||
char c_locname [256];
|
||||
std::strcpy (c_locname, std::setlocale (LC_ALL, 0));
|
||||
|
||||
BEGIN_LOCALE_LOOP (UCHAR_MAX, locname, i) {
|
||||
|
||||
#if defined (_RWSTD_OS_SUNOS) && _RWSTD_OS_MAJOR == 5 && _RWSTD_OS_MINOR <= 10
|
||||
|
||||
// avoid a libc SIGSEGV in mbtowc() in zh_HK and zh_TW
|
||||
// locales encoded using the BIG5 codeset (see bug #603)
|
||||
if ( 0 == std::strncmp ("zh_HK.BIG5", locname, 10)
|
||||
|| 0 == std::strncmp ("zh_TW.BIG5", locname, 10))
|
||||
continue;
|
||||
|
||||
#endif // SunOS < 5.10
|
||||
|
||||
{
|
||||
// verify that the global C locale stays unchanged
|
||||
const char* const curlocname = std::setlocale (LC_ALL, 0);
|
||||
|
||||
rw_assert (!std::strcmp (c_locname, curlocname), 0, __LINE__,
|
||||
"setlocale(LC_ALL, 0) == \"%s\", got \"%s\"",
|
||||
c_locname, curlocname);
|
||||
}
|
||||
|
||||
if (0 == i)
|
||||
rw_info (0, 0, __LINE__, "std::ctype<%s> in locale(%#s)",
|
||||
cname, locname);
|
||||
|
||||
const char c = char (i);
|
||||
const charT ch = charT (i);
|
||||
|
||||
// verify that condition [1] holds
|
||||
COND1 (ALPHA);
|
||||
COND1 (CNTRL);
|
||||
COND1 (DIGIT);
|
||||
COND1 (GRAPH);
|
||||
COND1 (LOWER);
|
||||
COND1 (PRINT);
|
||||
COND1 (PUNCT);
|
||||
COND1 (SPACE);
|
||||
COND1 (UPPER);
|
||||
COND1 (XDIGIT);
|
||||
|
||||
// verify that condition [2] holds
|
||||
char dfault = c ? '\0' : '\1';
|
||||
const charT ret = ctp.widen (ctp.narrow (ch, dfault));
|
||||
|
||||
if (ret != charT (dfault) && ret != ch) {
|
||||
rw_assert (ch != widen (ch, narrow (ch, locname), locname),
|
||||
0, __LINE__,
|
||||
"ctype<%s>::widen (ctype<%1$s>::narrow "
|
||||
"(%{#lc}, %{#c})) == %{#c}; got %{#c} "
|
||||
"in locale (%#s)",
|
||||
cname, ch, dfault, ch, ret, locname);
|
||||
}
|
||||
|
||||
// finally verify that condition [3] holds
|
||||
COND3 (ALPHA);
|
||||
COND3 (CNTRL);
|
||||
COND3 (DIGIT);
|
||||
COND3 (GRAPH);
|
||||
COND3 (LOWER);
|
||||
COND3 (PRINT);
|
||||
COND3 (PUNCT);
|
||||
COND3 (SPACE);
|
||||
COND3 (UPPER);
|
||||
COND3 (XDIGIT);
|
||||
|
||||
// now perform a relitively simple sanity check on the 3-argument
|
||||
// overloads of narrow() and widen(). Make sure that the 3-argument
|
||||
// overloads return the same value that the other overload produces
|
||||
// Only do this the first time through the locale list.
|
||||
|
||||
if (i == 0) {
|
||||
// arrays of all tested narrow and wide characters
|
||||
charT wide_chars [UCHAR_MAX + 1];
|
||||
char narrow_chars [UCHAR_MAX + 1];
|
||||
charT narrow_in [UCHAR_MAX + 1];
|
||||
char widen_in [UCHAR_MAX + 1];
|
||||
|
||||
// zero out the last element to allow printing
|
||||
wide_chars [UCHAR_MAX] = charT ();
|
||||
narrow_chars [UCHAR_MAX] = char ();
|
||||
narrow_in [UCHAR_MAX] = charT ();
|
||||
widen_in [UCHAR_MAX] = char ();
|
||||
|
||||
// set the `dfault' character to something unlikely
|
||||
// but other than '\0'
|
||||
dfault = '\377';
|
||||
|
||||
for (unsigned j = 0; j <= UCHAR_MAX; j++) {
|
||||
wide_chars [j] = ctp.widen (char (j));
|
||||
narrow_chars [j] = ctp.narrow (wide_chars [j], dfault);
|
||||
narrow_in [j] = ctp.widen (char (j));
|
||||
widen_in [j] = char (j);
|
||||
}
|
||||
|
||||
charT widen_out [UCHAR_MAX + 1];
|
||||
char narrow_out [UCHAR_MAX + 1];
|
||||
|
||||
widen_out [UCHAR_MAX] = charT ();
|
||||
narrow_out [UCHAR_MAX] = char ();
|
||||
|
||||
// narrow source buffer into the destination
|
||||
// and compare with expected values
|
||||
ctp.narrow (narrow_in,
|
||||
narrow_in + UCHAR_MAX + 1,
|
||||
dfault,
|
||||
narrow_out);
|
||||
|
||||
bool success =
|
||||
!std::memcmp (narrow_chars, narrow_out, sizeof narrow_chars);
|
||||
|
||||
rw_assert (success, 0, __LINE__,
|
||||
"ctype<%s>::narrow (%{*.*Ac}\", ... , %{#c}) "
|
||||
"== %{.*Ac}, got %{.*Ac} in locale (%#s)", cname,
|
||||
int (sizeof *narrow_in), UCHAR_MAX, narrow_in, dfault,
|
||||
UCHAR_MAX, narrow_chars, UCHAR_MAX, narrow_out,
|
||||
locname);
|
||||
|
||||
// widen source buffer into the destination
|
||||
// and compare with expected values
|
||||
ctp.widen (widen_in,
|
||||
widen_in + UCHAR_MAX + 1,
|
||||
widen_out);
|
||||
|
||||
success = !std::memcmp (wide_chars, widen_out, sizeof wide_chars);
|
||||
|
||||
rw_assert (success, 0, __LINE__,
|
||||
"ctype<%s>::widen (%{.*Ac}, ...) == "
|
||||
"%{*.*Ac}, got %{*.*Ac} in locale (%#s)",
|
||||
cname, UCHAR_MAX, widen_in,
|
||||
int (sizeof *wide_chars), UCHAR_MAX, wide_chars,
|
||||
int (sizeof *wide_chars), UCHAR_MAX, widen_out,
|
||||
locname);
|
||||
}
|
||||
|
||||
} END_LOCALE_LOOP (locname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// exercise the behavior of the libc-based C++ locale implementation
|
||||
template <class charT>
|
||||
void test_libc (charT, const char *cname)
|
||||
{
|
||||
test_narrow_widen (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// exercise the behavior of our own C++ locale implementation
|
||||
template <class charT>
|
||||
void test_libstd (charT, const char *cname)
|
||||
{
|
||||
rw_warn (0, 0, __LINE__,
|
||||
"stdcxx implementation of std::ctype<%s> not exercised",
|
||||
cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void run_test (charT, const char *cname)
|
||||
{
|
||||
if (0) {
|
||||
// do a compile time only test on use_facet and has_facet
|
||||
_STD_HAS_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
_STD_USE_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
}
|
||||
|
||||
// exercise the behavior of the libc-based C++ locale implementation
|
||||
test_libc (charT (), cname);
|
||||
|
||||
// exercise the behavior of our own C++ locale implementation
|
||||
test_libstd (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// set the global locale_list pointer to point to the array
|
||||
// of NUL-separated locale names set on the command line via
|
||||
// the --locales=... option, if specified, or to 0 (in which
|
||||
// case we'll generate our own list)
|
||||
locale_list = rw_opt_locales;
|
||||
|
||||
run_test (char (), "char");
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
run_test (wchar_t (), "wchar_t");
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.category.ctype",
|
||||
"narrow and widen",
|
||||
run_test,
|
||||
"|-locales= ",
|
||||
&rw_opt_setlocales,
|
||||
(void*)0 /* sentinel */);
|
||||
}
|
||||
863
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.scan.cpp
vendored
Normal file
863
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.scan.cpp
vendored
Normal file
@@ -0,0 +1,863 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.ctype.scan.cpp - Tests exercising the scan() of ctype facet
|
||||
*
|
||||
* $Id: 22.locale.ctype.scan.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.
|
||||
*
|
||||
* Copyright 2001-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// DESCRIPTION: test iterates over the locales installed on a machine,
|
||||
// calling the C character classification functions and
|
||||
// their C++ counterpart(s), comparing the results of
|
||||
// the calls against one another.
|
||||
|
||||
|
||||
#include <rw/_defs.h>
|
||||
|
||||
#if defined __linux__
|
||||
// on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
|
||||
# define _XOPEN_SOURCE 500 /* Single Unix conformance */
|
||||
// bring __int32_t into scope (otherwise <wctype.h> fails to compile)
|
||||
# include <sys/types.h>
|
||||
#endif // __linux__
|
||||
|
||||
// see Onyx PR #28150
|
||||
#if defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
# include <wchar.h>
|
||||
#endif // defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cwchar> // for WEOF, btowc(), wctob()
|
||||
#include <cwctype> // for iswxxx()
|
||||
|
||||
|
||||
#if !defined (_MSC_VER)
|
||||
# if !defined (LC_MESSAGES)
|
||||
# define LC_MESSAGES _RWSTD_LC_MESSAGES
|
||||
# endif // LC_MESSAGES
|
||||
# include <langinfo.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <driver.h>
|
||||
#include <file.h> // for SLASH
|
||||
#include <rw_locale.h> // for rw_locale_query()
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// the root of the locale directory (RWSTD_LOCALE_ROOT)
|
||||
// not set here to avoid Solaris 7 putenv() bug (PR #30017)
|
||||
const char* locale_root;
|
||||
|
||||
#define NLOOPS 25
|
||||
#define MAX_STR_SIZE 16
|
||||
|
||||
#define LOCALES "{{en-US,de-DE,fr-FR,es-ES}-*-{ISO-8859-*,UTF-8,CP125?}," \
|
||||
"{ja-JP-*-{EUC-JP,SHIFT_JIS,UTF-8,CP125?}}," \
|
||||
"{zh-CN-*-{GB*,UTF-8,CP125?}}," \
|
||||
"{ru-RU-*-{KOI*,UTF-8,CP125?}}}"
|
||||
|
||||
const char* locale_list = 0;
|
||||
|
||||
#define BEGIN_LOCALE_LOOP(num, locname, loop_cntrl) \
|
||||
if (!locale_list) locale_list = rw_locale_query (LC_CTYPE, LOCALES); \
|
||||
for (const char* locname = locale_list; \
|
||||
locname && *locname; locname += std::strlen (locname) + 1) { \
|
||||
_TRY { \
|
||||
const std::locale loc (locname); \
|
||||
const std::ctype<char> &ctc = \
|
||||
_STD_USE_FACET (std::ctype<char>, loc); \
|
||||
_RWSTD_UNUSED (ctc); \
|
||||
const std::ctype<charT> &ctp = \
|
||||
_STD_USE_FACET (std::ctype<charT>, loc); \
|
||||
for (int loop_cntrl = 0; loop_cntrl < int (num); loop_cntrl++)
|
||||
|
||||
#define END_LOCALE_LOOP(locname) \
|
||||
} \
|
||||
_CATCH (...) { \
|
||||
rw_assert (0, 0, __LINE__, \
|
||||
"locale (\"%s\") threw an exception", locname); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// for notational convenience
|
||||
typedef unsigned char UChar;
|
||||
|
||||
#define ALPHA std::ctype_base::alpha
|
||||
#define UPPER std::ctype_base::upper
|
||||
#define LOWER std::ctype_base::lower
|
||||
#define DIGIT std::ctype_base::digit
|
||||
#define SPACE std::ctype_base::space
|
||||
#define CNTRL std::ctype_base::cntrl
|
||||
#define PUNCT std::ctype_base::punct
|
||||
#define XDIGIT std::ctype_base::xdigit
|
||||
#define GRAPH std::ctype_base::graph
|
||||
#define PRINT std::ctype_base::print
|
||||
|
||||
|
||||
// wrapper functions for the c library char and wchar_t functions
|
||||
int libc_isalpha (char ch)
|
||||
{
|
||||
return (std::isalpha)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isspace (char ch)
|
||||
{
|
||||
return (std::isspace)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isprint (char ch)
|
||||
{
|
||||
return (std::isprint)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_iscntrl (char ch)
|
||||
{
|
||||
return (std::iscntrl)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isupper (char ch)
|
||||
{
|
||||
return (std::isupper)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_islower (char ch)
|
||||
{
|
||||
return (std::islower)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isdigit (char ch)
|
||||
{
|
||||
return (std::isdigit)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_ispunct (char ch)
|
||||
{
|
||||
return (std::ispunct)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isxdigit (char ch)
|
||||
{
|
||||
return (std::isxdigit)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isalnum (char ch)
|
||||
{
|
||||
return (std::isalnum)(UChar (ch));
|
||||
}
|
||||
|
||||
int libc_isgraph (char ch)
|
||||
{
|
||||
return (std::isgraph)(UChar (ch));
|
||||
}
|
||||
|
||||
std::ctype_base::mask libc_mask (int mask, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
|
||||
if (locname) {
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return std::ctype_base::mask ();
|
||||
}
|
||||
|
||||
const int c = UChar (ch);
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (mask & ALPHA && (std::isalpha)(c))
|
||||
result |= ALPHA;
|
||||
if (mask & CNTRL && (std::iscntrl)(c))
|
||||
result |= CNTRL;
|
||||
if (mask & DIGIT && (std::isdigit)(c))
|
||||
result |= DIGIT;
|
||||
if (mask & GRAPH && (std::isgraph)(c))
|
||||
result |= GRAPH;
|
||||
if (mask & LOWER && (std::islower)(c))
|
||||
result |= LOWER;
|
||||
if (mask & PRINT && (std::isprint)(c))
|
||||
result |= PRINT;
|
||||
if (mask & PUNCT && (std::ispunct)(c))
|
||||
result |= PUNCT;
|
||||
if (mask & SPACE && (std::isspace)(c))
|
||||
result |= SPACE;
|
||||
if (mask & UPPER && (std::isupper)(c))
|
||||
result |= UPPER;
|
||||
if (mask & XDIGIT && (std::isxdigit)(c))
|
||||
result |= XDIGIT;
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return std::ctype_base::mask (result);
|
||||
}
|
||||
|
||||
inline bool libc_is (std::ctype_base::mask mask, char ch, const char *locname)
|
||||
{
|
||||
const std::ctype_base::mask m = libc_mask (mask, ch, locname);
|
||||
|
||||
return 0 != (m & mask);
|
||||
}
|
||||
|
||||
std::size_t c_strlen (const char *s1)
|
||||
{
|
||||
return std::strlen (s1);
|
||||
}
|
||||
|
||||
const char* widen (char *dst, const char *src)
|
||||
{
|
||||
if (src == dst || !src || !dst)
|
||||
return src;
|
||||
|
||||
std::memcpy (dst, src, std::strlen (src) + 1);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
char widen (char, char ch, const char*)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
int libc_isalpha (wchar_t ch)
|
||||
{
|
||||
return (std::iswalpha)(ch);
|
||||
}
|
||||
|
||||
int libc_isspace (wchar_t ch)
|
||||
{
|
||||
return (std::iswspace)(ch);
|
||||
}
|
||||
|
||||
int libc_isprint (wchar_t ch)
|
||||
{
|
||||
return (std::iswprint)(ch);
|
||||
}
|
||||
|
||||
int libc_iscntrl (wchar_t ch)
|
||||
{
|
||||
return (std::iswcntrl)(ch);
|
||||
}
|
||||
|
||||
int libc_isupper (wchar_t ch)
|
||||
{
|
||||
return (std::iswupper)(ch);
|
||||
}
|
||||
|
||||
int libc_islower (wchar_t ch)
|
||||
{
|
||||
return (std::iswlower)(ch);
|
||||
}
|
||||
|
||||
int libc_isdigit (wchar_t ch)
|
||||
{
|
||||
return (std::iswdigit)(ch);
|
||||
}
|
||||
|
||||
int libc_ispunct (wchar_t ch)
|
||||
{
|
||||
return (std::iswpunct)(ch);
|
||||
}
|
||||
|
||||
int libc_isxdigit (wchar_t ch)
|
||||
{
|
||||
return (std::iswxdigit)(ch);
|
||||
}
|
||||
|
||||
int libc_isalnum (wchar_t ch)
|
||||
{
|
||||
return (std::iswalnum)(ch);
|
||||
}
|
||||
|
||||
int libc_isgraph (wchar_t ch)
|
||||
{
|
||||
return (std::iswgraph)(ch);
|
||||
}
|
||||
|
||||
wchar_t libc_tolower (wchar_t ch)
|
||||
{
|
||||
return (std::towlower)(ch);
|
||||
}
|
||||
|
||||
wchar_t libc_toupper (wchar_t ch)
|
||||
{
|
||||
return (std::towupper)(ch);
|
||||
}
|
||||
|
||||
std::size_t c_strlen (const wchar_t *s1)
|
||||
{
|
||||
return std::wcslen (s1);
|
||||
}
|
||||
|
||||
|
||||
const wchar_t* widen (wchar_t *dst, const char *src)
|
||||
{
|
||||
static wchar_t buf [4096];
|
||||
|
||||
if (!src)
|
||||
return 0;
|
||||
|
||||
if (!dst)
|
||||
dst = buf;
|
||||
|
||||
std::size_t len = std::strlen (src);
|
||||
|
||||
_RWSTD_ASSERT (len < sizeof buf /sizeof *buf);
|
||||
|
||||
len = std::mbstowcs (dst, src, sizeof buf / sizeof *buf);
|
||||
|
||||
if (std::size_t (-1) == len)
|
||||
*dst = 0;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
std::ctype_base::mask libc_mask (int mask, wchar_t ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
|
||||
if (locname) {
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return std::ctype_base::mask ();
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (mask & ALPHA && (std::iswalpha)(ch))
|
||||
result |= ALPHA;
|
||||
if (mask & CNTRL && (std::iswcntrl)(ch))
|
||||
result |= CNTRL;
|
||||
if (mask & DIGIT && (std::iswdigit)(ch))
|
||||
result |= DIGIT;
|
||||
if (mask & GRAPH && (std::iswgraph)(ch))
|
||||
result |= GRAPH;
|
||||
if (mask & LOWER && (std::iswlower)(ch))
|
||||
result |= LOWER;
|
||||
if (mask & PRINT && (std::iswprint)(ch))
|
||||
result |= PRINT;
|
||||
if (mask & PUNCT && (std::iswpunct)(ch))
|
||||
result |= PUNCT;
|
||||
if (mask & SPACE && (std::iswspace)(ch))
|
||||
result |= SPACE;
|
||||
if (mask & UPPER && (std::iswupper)(ch))
|
||||
result |= UPPER;
|
||||
if (mask & XDIGIT && (std::iswxdigit)(ch))
|
||||
result |= XDIGIT;
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return std::ctype_base::mask (result);
|
||||
}
|
||||
|
||||
bool libc_is (std::ctype_base::mask mask, wchar_t ch, const char *locname)
|
||||
{
|
||||
const std::ctype_base::mask m = libc_mask (mask, ch, locname);
|
||||
|
||||
return 0 != (m & mask);
|
||||
}
|
||||
|
||||
wchar_t widen (wchar_t, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return UChar (ch);
|
||||
|
||||
wchar_t result;
|
||||
|
||||
#ifndef _RWSTD_NO_BTOWC
|
||||
|
||||
result = std::btowc (UChar (ch));
|
||||
|
||||
#elif !defined (_RWSTD_NO_MBTOWC)
|
||||
|
||||
if (1 != std::mbtowc (&result, &ch, 1))
|
||||
result = wchar_t (WEOF);
|
||||
|
||||
#else
|
||||
|
||||
result = UChar (ch);
|
||||
|
||||
#endif // _RWSTD_NO_BTOWC, _RWSTD_NO_MBTOWC
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
|
||||
template <class charT>
|
||||
void gen_str (charT *str, std::size_t size)
|
||||
{
|
||||
// generate a random string with the given size
|
||||
// we do not attempt to check that the size is within the
|
||||
// valid range for the string.
|
||||
|
||||
for (std::size_t i = 0; i < size; i++){
|
||||
str [i] = UChar (std::rand () % UCHAR_MAX);
|
||||
// only increment if we are not going to roll over
|
||||
if (str [i] != charT (UCHAR_MAX - 1U))
|
||||
++str [i];
|
||||
}
|
||||
|
||||
str [size] = charT ();
|
||||
|
||||
_RWSTD_ASSERT (c_strlen (str) == size);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_scan (charT, const char *cname)
|
||||
{
|
||||
rw_info (0, 0, __LINE__, "std::ctype<%s>::scan_is(), scan_not()", cname);
|
||||
|
||||
charT str [MAX_STR_SIZE + 1];
|
||||
|
||||
BEGIN_LOCALE_LOOP (NLOOPS, locname, j) {
|
||||
|
||||
const std::size_t size = std::size_t (j % MAX_STR_SIZE);
|
||||
|
||||
// generate a random string
|
||||
gen_str (str, size);
|
||||
|
||||
// set the global C locale to default to make sure
|
||||
// the C++ library does not asume a set value
|
||||
std::setlocale (LC_CTYPE, "");
|
||||
|
||||
// call scan_is and scan_not using each mask and compare it to
|
||||
// the results found when using the c library
|
||||
|
||||
const charT* alpha_is = ctp.scan_is (ALPHA, str, str + size);
|
||||
const charT* alpha_not = ctp.scan_not (ALPHA, str, str + size);
|
||||
const charT* space_is = ctp.scan_is (SPACE, str, str + size);
|
||||
const charT* space_not = ctp.scan_not (SPACE, str, str + size);
|
||||
const charT* print_is = ctp.scan_is (PRINT, str, str + size);
|
||||
const charT* print_not = ctp.scan_not (PRINT, str, str + size);
|
||||
const charT* cntrl_is = ctp.scan_is (CNTRL, str, str + size);
|
||||
const charT* cntrl_not = ctp.scan_not (CNTRL, str, str + size);
|
||||
const charT* upper_is = ctp.scan_is (UPPER, str, str + size);
|
||||
const charT* upper_not = ctp.scan_not (UPPER, str, str + size);
|
||||
const charT* lower_is = ctp.scan_is (LOWER, str, str + size);
|
||||
const charT* lower_not = ctp.scan_not (LOWER, str, str + size);
|
||||
const charT* digit_is = ctp.scan_is (DIGIT, str, str + size);
|
||||
const charT* digit_not = ctp.scan_not (DIGIT, str, str + size);
|
||||
const charT* punct_is = ctp.scan_is (PUNCT, str, str + size);
|
||||
const charT* punct_not = ctp.scan_not (PUNCT, str, str + size);
|
||||
const charT* xdigit_is = ctp.scan_is (XDIGIT, str, str + size);
|
||||
const charT* xdigit_not = ctp.scan_not (XDIGIT, str, str + size);
|
||||
|
||||
// set the global C locale to locname for the C library call
|
||||
std::setlocale (LC_CTYPE, locname);
|
||||
|
||||
// find the first character in the string that is of the specified
|
||||
// type
|
||||
charT first = 0;
|
||||
charT first_not = 0;
|
||||
_RWSTD_SIZE_T i;
|
||||
int success;
|
||||
|
||||
#define SCAN(what) \
|
||||
for (i = 0; i < size; i++) { \
|
||||
if (libc_is##what (str [i])) { \
|
||||
first = (str [i]); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
success = what##_is != (str + size) || 0 == first \
|
||||
|| *what##_is != first; \
|
||||
rw_assert (success, 0, __LINE__, \
|
||||
"ctype<%s>::scan_is(" #what ", %{#lc}) " \
|
||||
"== %{*Ac}, got %{*Ac} in locale (%#s)", \
|
||||
cname, int (sizeof *str), first, \
|
||||
int (sizeof *what##_is), what##_is, \
|
||||
locname); \
|
||||
\
|
||||
first = 0; \
|
||||
for (i = 0; i < size; i++) { \
|
||||
if (!libc_is##what (str[i])) { \
|
||||
first_not = (str[i]); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
success = what##_not != (str + size) || 0 == first_not \
|
||||
|| *what##_not == first_not; \
|
||||
rw_assert (success, 0, __LINE__, \
|
||||
"ctype<%s>::scan_not(" #what ", %{#lc}) " \
|
||||
"== %{*Ac}, got %{*Ac} in locale (%#s)", \
|
||||
cname, int (sizeof *str), first, \
|
||||
int (sizeof *what##_not), what##_not, \
|
||||
locname); \
|
||||
\
|
||||
first_not = 0
|
||||
|
||||
// test all classes of characters
|
||||
SCAN (alpha);
|
||||
SCAN (space);
|
||||
SCAN (print);
|
||||
SCAN (cntrl);
|
||||
SCAN (upper);
|
||||
SCAN (lower);
|
||||
SCAN (digit);
|
||||
SCAN (punct);
|
||||
SCAN (xdigit);
|
||||
|
||||
} END_LOCALE_LOOP (locname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libc (charT, const char *cname)
|
||||
{
|
||||
test_scan (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd_scan_is (charT, const char *cname,
|
||||
const std::ctype<charT> &ct,
|
||||
const char* str, std::ctype_base::mask mask,
|
||||
int expected_idx, int fwiden = 0)
|
||||
{
|
||||
// convert narrow string to a (possibly) wide representation
|
||||
charT wstrbuf [256];
|
||||
charT* wstr = wstrbuf;
|
||||
|
||||
// If instructed to use the facet widen method, do so, otherwise
|
||||
// use widen helper function that in turn uses C lib mbstowcs
|
||||
if (fwiden == 0)
|
||||
widen (wstrbuf, str);
|
||||
else
|
||||
ct.widen (str, str + std::strlen (str), wstrbuf);
|
||||
|
||||
const int success =
|
||||
&wstr [expected_idx] == ct.scan_is (mask, wstr, wstr + c_strlen (wstr));
|
||||
|
||||
rw_assert (success, 0, __LINE__,
|
||||
"ctype<%s>::scan_is() returned an unexpected value",
|
||||
cname);
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd_scan_not (charT, const char *cname,
|
||||
const std::ctype<charT> &ct,
|
||||
const char* str, std::ctype_base::mask mask,
|
||||
int expected_idx, int fwiden = 0)
|
||||
{
|
||||
// convert narrow string to a (possibly) wide representation
|
||||
charT wstrbuf [256];
|
||||
charT* wstr = wstrbuf;
|
||||
|
||||
// If instructed to use the facet widen method, do so, otherwise
|
||||
// use widen helper function that in turn uses C lib mbstowcs
|
||||
if (fwiden == 0)
|
||||
widen (wstrbuf, str);
|
||||
else
|
||||
ct.widen (str, str + std::strlen (str), wstrbuf);
|
||||
|
||||
const int success =
|
||||
&wstr[expected_idx] == ct.scan_not (mask, wstr, wstr + c_strlen (wstr));
|
||||
|
||||
rw_assert (success, 0, __LINE__,
|
||||
"ctype<%s>::scan_not() returned an unexpected value",
|
||||
cname);
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd (charT, const char *cname)
|
||||
{
|
||||
const char cmap_1[] = {
|
||||
"<code_set_name> \"ANSI_X3.4-1968\"\n"
|
||||
"<mb_cur_max> 1\n"
|
||||
"<mb_cur_min> 1\n"
|
||||
"CHARMAP\n"
|
||||
"<U0000> \\x00\n"
|
||||
"<U0001> \\x01\n"
|
||||
"<U0002> \\x02\n"
|
||||
"<U0003> \\x03\n"
|
||||
"<U0004> \\x04\n"
|
||||
"<U0005> \\x05\n"
|
||||
"<U0006> \\x06\n"
|
||||
"<U0007> \\x07\n"
|
||||
"<U0008> \\x08\n"
|
||||
"<U0009> \\x09\n"
|
||||
"<U000a> \\x0a\n"
|
||||
"<U000b> \\x0b\n"
|
||||
"<U000c> \\x0c\n"
|
||||
"<U000d> \\x0d\n"
|
||||
"<U000e> \\x0e\n"
|
||||
"<U000f> \\x0f\n"
|
||||
"<U0010> \\x10\n"
|
||||
"<U0011> \\x11\n"
|
||||
"<U0012> \\x12\n"
|
||||
"<U0013> \\x13\n"
|
||||
"<U0014> \\x14\n"
|
||||
"<U0015> \\x15\n"
|
||||
"<U0016> \\x16\n"
|
||||
"<U0017> \\x17\n"
|
||||
"<U0018> \\x18\n"
|
||||
"<U0019> \\x19\n"
|
||||
"<U001a> \\x1a\n"
|
||||
"<U001b> \\x1b\n"
|
||||
"<U001c> \\x1c\n"
|
||||
"<U001d> \\x1d\n"
|
||||
"<U001e> \\x1e\n"
|
||||
"<U001f> \\x1f\n"
|
||||
"<U0020> \\x20\n"
|
||||
"<U0021> \\x21\n"
|
||||
"<U0022> \\x22\n"
|
||||
"<U0023> \\x23\n"
|
||||
"<U0024> \\x24\n"
|
||||
"<U0025> \\x25\n"
|
||||
"<U0026> \\x26\n"
|
||||
"<U0027> \\x27\n"
|
||||
"<U0028> \\x28\n"
|
||||
"<U0029> \\x29\n"
|
||||
"<U002a> \\x2a\n"
|
||||
"<U002b> \\x2b\n"
|
||||
"<U002c> \\x2c\n"
|
||||
"<U002d> \\x2d\n"
|
||||
"<U002e> \\x2e\n"
|
||||
"<U002f> \\x2f\n"
|
||||
"<U0030> \\x30\n"
|
||||
"<U0031> \\x31\n"
|
||||
"<U0032> \\x32\n"
|
||||
"<U0033> \\x33\n"
|
||||
"<U0034> \\x34\n"
|
||||
"<U0035> \\x35\n"
|
||||
"<U0036> \\x36\n"
|
||||
"<U0037> \\x37\n"
|
||||
"<U0038> \\x38\n"
|
||||
"<U0039> \\x39\n"
|
||||
"<U003a> \\x3a\n"
|
||||
"<U003b> \\x3b\n"
|
||||
"<U003c> \\x3c\n"
|
||||
"<U003d> \\x3d\n"
|
||||
"<U003e> \\x3e\n"
|
||||
"<U003f> \\x3f\n"
|
||||
"<U0040> \\x40\n"
|
||||
"<U0041> \\x41\n"
|
||||
"<U0042> \\x42\n"
|
||||
"<U0043> \\x43\n"
|
||||
"<U0044> \\x44\n"
|
||||
"<U0045> \\x45\n"
|
||||
"<U0046> \\x46\n"
|
||||
"<U0047> \\x47\n"
|
||||
"<U0048> \\x48\n"
|
||||
"<U0049> \\x49\n"
|
||||
"<U004a> \\x4a\n"
|
||||
"<U004b> \\x4b\n"
|
||||
"<U004c> \\x4c\n"
|
||||
"<U004d> \\x4d\n"
|
||||
"<U004e> \\x4e\n"
|
||||
"<U004f> \\x4f\n"
|
||||
"<U0050> \\x50\n"
|
||||
"<U0051> \\x51\n"
|
||||
"<U0052> \\x52\n"
|
||||
"<U0053> \\x53\n"
|
||||
"<U0054> \\x54\n"
|
||||
"<U0055> \\x55\n"
|
||||
"<U0056> \\x56\n"
|
||||
"<U0057> \\x57\n"
|
||||
"<U0058> \\x58\n"
|
||||
"<U0059> \\x59\n"
|
||||
"<U005a> \\x5a\n"
|
||||
"<U005b> \\x5b\n"
|
||||
"<U005c> \\x5c\n"
|
||||
"<U005d> \\x5d\n"
|
||||
"<U005e> \\x5e\n"
|
||||
"<U005f> \\x5f\n"
|
||||
"<U0060> \\x60\n"
|
||||
"<U0061> \\x61\n"
|
||||
"<U0062> \\x62\n"
|
||||
"<U0063> \\x63\n"
|
||||
"<U0064> \\x64\n"
|
||||
"<U0065> \\x65\n"
|
||||
"<U0066> \\x66\n"
|
||||
"<U0067> \\x67\n"
|
||||
"<U0068> \\x68\n"
|
||||
"<U0069> \\x69\n"
|
||||
"<U006a> \\x6a\n"
|
||||
"<U006b> \\x6b\n"
|
||||
"<U006c> \\x6c\n"
|
||||
"<U006d> \\x6d\n"
|
||||
"<U006e> \\x6e\n"
|
||||
"<U006f> \\x6f\n"
|
||||
"<U0070> \\x70\n"
|
||||
"<U0071> \\x71\n"
|
||||
"<U0072> \\x72\n"
|
||||
"<U0073> \\x73\n"
|
||||
"<U0074> \\x74\n"
|
||||
"<U0075> \\x75\n"
|
||||
"<U0076> \\x76\n"
|
||||
"<U0077> \\x77\n"
|
||||
"<U0078> \\x78\n"
|
||||
"<U0079> \\x79\n"
|
||||
"<U007a> \\x7a\n"
|
||||
"<U007b> \\x7b\n"
|
||||
"<U007c> \\x7c\n"
|
||||
"<U007d> \\x7d\n"
|
||||
"<U007e> \\x7e\n"
|
||||
"<U007f> \\x7f\n"
|
||||
"<U1000> \\xa0\n"
|
||||
"<U1001> \\xa1\n"
|
||||
"<U1002> \\xa2\n"
|
||||
"END CHARMAP\n"
|
||||
};
|
||||
|
||||
const char loc_1[] = {
|
||||
"escape_char /\n"
|
||||
"LC_CTYPE\n"
|
||||
"# <A> <B> <C> MYANMAR LETTER KHA\n"
|
||||
"upper <U0041>;<U0042>;<U0043>;<U1001>\n"
|
||||
" <a> <b> <c> MYANMAR LETTER KA\n"
|
||||
"lower <U0061>;<U0062>;<U0063>;<U1000>\n"
|
||||
"alpha <U0061>;<U0062>;<U0063>;<U0041>;"
|
||||
"<U0042>;<U0043>;<U1000>;<U1001>\n"
|
||||
"digit <U0031>;<U0032>;<U0033>;<U1002>\n"
|
||||
"space <U0020>\n"
|
||||
"cntrl <U0000>\n"
|
||||
" <!> <\">\n"
|
||||
"punct <U0021>; <U0022>\n"
|
||||
"graph <U0041>;<U0042>;<U0043>;<U0061>;<U0062>;<U0063>;"
|
||||
"<U1000>;<U1001>;<U1002>;<U1003>;<U1004>;<U1005>;"
|
||||
"<U0031>;<U0032>;<U0033>;<U0020>;<U0021>;<U0022>\n"
|
||||
"print <U0041>;<U0042>;<U0043>;"
|
||||
"<U0061>;<U0062>;<U0063>;"
|
||||
"<U1000>;<U1001>;<U1002>;<U1003>;<U1004>;<U1005>;"
|
||||
"<U0031>;<U0032>;<U0033>;<U0020>;<U0021>;<U0022>\n"
|
||||
"xdigit <U0041>;<U0042>;<U0043>;<U0061>;<U0062>;"
|
||||
"<U0063>;<U0031>;<U0032>;<U0033>\n"
|
||||
"END LC_CTYPE\n"
|
||||
};
|
||||
|
||||
//invoke rw_create_locale to build a locale to test with
|
||||
const char* const locname = rw_create_locale (cmap_1, loc_1);
|
||||
|
||||
if (!rw_error (0 != locname, 0, __LINE__,
|
||||
"failed to create a locale in %s", locale_root))
|
||||
return;
|
||||
|
||||
const std::locale loc (locname);
|
||||
|
||||
const std::ctype<charT> &ct =
|
||||
_STD_USE_FACET (std::ctype<charT>, loc);
|
||||
|
||||
ct._C_opts |= ct._C_use_libstd;
|
||||
ct._C_opts &= ~ct._C_use_libc;
|
||||
|
||||
// now check the scan functions
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::ctype<%s>::scan_is(const %1$s*, const %1$s, mask*) "
|
||||
"in locale(%#s)", cname, locname);
|
||||
|
||||
test_libstd_scan_is (charT (), cname, ct, "abc1BC", DIGIT, 3);
|
||||
test_libstd_scan_is (charT (), cname, ct, "abc123B ", SPACE, 7);
|
||||
test_libstd_scan_is (charT (), cname, ct, "abc123", LOWER, 0);
|
||||
test_libstd_scan_is (charT (), cname, ct, "abc123", UPPER, 6);
|
||||
test_libstd_scan_is (charT (), cname, ct, "abc1ABC", DIGIT | UPPER, 3);
|
||||
test_libstd_scan_is (charT (), cname, ct, "abcA2BC", DIGIT | UPPER, 3);
|
||||
|
||||
if (sizeof(charT) > 1) {
|
||||
test_libstd_scan_is (charT (), cname, ct, "ABC\xa0xyz", LOWER, 3, 1);
|
||||
test_libstd_scan_is (charT (), cname, ct, "abcx\xa1yz", UPPER, 4, 1);
|
||||
}
|
||||
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::ctype<%s>::scan_not(const %1$s*, const %1$s, mask*) "
|
||||
"in locale(%#s)", cname, locname);
|
||||
|
||||
test_libstd_scan_not (charT (), cname, ct, "abc1BC", ALPHA, 3);
|
||||
test_libstd_scan_not (charT (), cname, ct, "aaBBcc", LOWER, 2);
|
||||
test_libstd_scan_not (charT (), cname, ct, "abc1BC", DIGIT, 0);
|
||||
test_libstd_scan_not (charT (), cname, ct, "abc1BC", PRINT, 6);
|
||||
|
||||
if (sizeof(charT) > 1) {
|
||||
test_libstd_scan_not (charT (), cname, ct, "abc\xa2xyz", ALPHA, 3, 1);
|
||||
test_libstd_scan_not (charT (), cname, ct, "123\xa1yz ", DIGIT, 3, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void run_test (charT, const char *cname)
|
||||
{
|
||||
if (0) {
|
||||
// do a compile time only test on use_facet and has_facet
|
||||
_STD_HAS_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
_STD_USE_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
}
|
||||
|
||||
test_libc (charT (), cname);
|
||||
test_libstd (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
run_test (char (), "char");
|
||||
run_test (wchar_t (), "wchar_t");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.category.ctype",
|
||||
0 /* no comment */,
|
||||
run_test,
|
||||
"",
|
||||
(void*)0 /* sentinel */);
|
||||
}
|
||||
496
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.tolower.cpp
vendored
Normal file
496
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.tolower.cpp
vendored
Normal file
@@ -0,0 +1,496 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.ctype.tolower.cpp - Tests exercising the tolower() of ctype facet
|
||||
*
|
||||
* $Id: 22.locale.ctype.tolower.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.
|
||||
*
|
||||
* Copyright 2001-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// DESCRIPTION: test iterates over the locales installed on a machine,
|
||||
// calling the C character classification functions and
|
||||
// their C++ counterpart(s), comparing the results of
|
||||
// the calls against one another.
|
||||
|
||||
|
||||
#include <rw/_defs.h>
|
||||
|
||||
#if defined __linux__
|
||||
// on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
|
||||
# define _XOPEN_SOURCE 500 /* Single Unix conformance */
|
||||
// bring __int32_t into scope (otherwise <wctype.h> fails to compile)
|
||||
# include <sys/types.h>
|
||||
#endif // __linux__
|
||||
|
||||
// see Onyx PR #28150
|
||||
#if defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
# include <wchar.h>
|
||||
#endif // defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cwchar> // for WEOF, btowc(), wctob()
|
||||
#include <cwctype> // for iswxxx()
|
||||
|
||||
|
||||
#if !defined (_MSC_VER)
|
||||
# if !defined (LC_MESSAGES)
|
||||
# define LC_MESSAGES _RWSTD_LC_MESSAGES
|
||||
# endif // LC_MESSAGES
|
||||
# include <langinfo.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <driver.h>
|
||||
#include <file.h> // for SLASH
|
||||
#include <rw_locale.h> // for rw_locale_query()
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// the root of the locale directory (RWSTD_LOCALE_ROOT)
|
||||
// not set here to avoid Solaris 7 putenv() bug (PR #30017)
|
||||
const char* locale_root;
|
||||
|
||||
#define NLOOPS 25
|
||||
#define MAX_STR_SIZE 16
|
||||
|
||||
#define LOCALES "{{en-US,de-DE,fr-FR,es-ES}-*-{ISO-8859-*,UTF-8,CP125?}," \
|
||||
"{ja-JP-*-{EUC-JP,SHIFT_JIS,UTF-8,CP125?}}," \
|
||||
"{zh-CN-*-{GB*,UTF-8,CP125?}}," \
|
||||
"{ru-RU-*-{KOI*,UTF-8,CP125?}}}"
|
||||
|
||||
const char* locale_list = 0;
|
||||
|
||||
#define BEGIN_LOCALE_LOOP(num, locname, loop_cntrl) \
|
||||
const char* locale_list = rw_locale_query (LC_CTYPE, LOCALES); \
|
||||
for (const char* locname = locale_list; \
|
||||
locname && *locname; locname += std::strlen (locname) + 1) { \
|
||||
_TRY { \
|
||||
const std::locale loc (locname); \
|
||||
const std::ctype<char> &ctc = \
|
||||
_STD_USE_FACET (std::ctype<char>, loc); \
|
||||
_RWSTD_UNUSED (ctc); \
|
||||
const std::ctype<charT> &ctp = \
|
||||
_STD_USE_FACET (std::ctype<charT>, loc); \
|
||||
for (int loop_cntrl = 0; loop_cntrl < int (num); loop_cntrl++)
|
||||
|
||||
#define END_LOCALE_LOOP(locname) \
|
||||
} \
|
||||
_CATCH (...) { \
|
||||
rw_assert (0, 0, __LINE__, \
|
||||
"locale (\"%s\") threw an exception", locname); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// for notational convenience
|
||||
typedef unsigned char UChar;
|
||||
|
||||
#define ALPHA std::ctype_base::alpha
|
||||
#define UPPER std::ctype_base::upper
|
||||
#define LOWER std::ctype_base::lower
|
||||
#define DIGIT std::ctype_base::digit
|
||||
#define SPACE std::ctype_base::space
|
||||
#define CNTRL std::ctype_base::cntrl
|
||||
#define PUNCT std::ctype_base::punct
|
||||
#define XDIGIT std::ctype_base::xdigit
|
||||
#define GRAPH std::ctype_base::graph
|
||||
#define PRINT std::ctype_base::print
|
||||
|
||||
|
||||
// wrapper functions for the c library char and wchar_t functions
|
||||
char libc_tolower (char ch)
|
||||
{
|
||||
return std::tolower (UChar (ch));
|
||||
}
|
||||
|
||||
char libc_toupper (char ch)
|
||||
{
|
||||
return (std::toupper)(UChar (ch));
|
||||
}
|
||||
|
||||
const char* widen (char *dst, const char *src)
|
||||
{
|
||||
if (src == dst || !src || !dst)
|
||||
return src;
|
||||
|
||||
std::memcpy (dst, src, std::strlen (src) + 1);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char widen (char, char ch, const char*)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t libc_tolower (wchar_t ch)
|
||||
{
|
||||
return (std::towlower)(ch);
|
||||
}
|
||||
|
||||
wchar_t libc_toupper (wchar_t ch)
|
||||
{
|
||||
return (std::towupper)(ch);
|
||||
}
|
||||
|
||||
const wchar_t* widen (wchar_t *dst, const char *src)
|
||||
{
|
||||
static wchar_t buf [4096];
|
||||
|
||||
if (!src)
|
||||
return 0;
|
||||
|
||||
if (!dst)
|
||||
dst = buf;
|
||||
|
||||
std::size_t len = std::strlen (src);
|
||||
|
||||
_RWSTD_ASSERT (len < sizeof buf /sizeof *buf);
|
||||
|
||||
len = std::mbstowcs (dst, src, sizeof buf / sizeof *buf);
|
||||
|
||||
if (std::size_t (-1) == len)
|
||||
*dst = 0;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
wchar_t widen (wchar_t, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return UChar (ch);
|
||||
|
||||
wchar_t result;
|
||||
|
||||
#ifndef _RWSTD_NO_BTOWC
|
||||
|
||||
result = std::btowc (UChar (ch));
|
||||
|
||||
#elif !defined (_RWSTD_NO_MBTOWC)
|
||||
|
||||
if (1 != std::mbtowc (&result, &ch, 1))
|
||||
result = wchar_t (WEOF);
|
||||
|
||||
#else
|
||||
|
||||
result = UChar (ch);
|
||||
|
||||
#endif // _RWSTD_NO_BTOWC, _RWSTD_NO_MBTOWC
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_tolower (charT, const char *cname)
|
||||
{
|
||||
rw_info (0, 0, __LINE__, "std::ctype<%s>::tolower(%1$s)", cname);
|
||||
|
||||
BEGIN_LOCALE_LOOP (UCHAR_MAX, locname, i) {
|
||||
|
||||
const charT ch = charT (i);
|
||||
|
||||
// set the global C locale to locname for the C library call
|
||||
std::setlocale (LC_CTYPE, locname);
|
||||
|
||||
const charT lch = libc_tolower (ch);
|
||||
|
||||
// set the global C locale to default to make sure
|
||||
// the C++ library does not asume a set value
|
||||
std::setlocale (LC_CTYPE, "");
|
||||
|
||||
// exercise tolower using ctype<>::tolower ()
|
||||
rw_assert (lch == (ctp.tolower)(ch), 0, __LINE__,
|
||||
"ctype<%s>::tolower(%{#lc}) == %{#lc}, got %{#lc} "
|
||||
"in locale(%#s)",
|
||||
cname, ch, lch, (ctp.tolower)(ch), locname);
|
||||
|
||||
// exercise tolower using tolower (char, locale)
|
||||
rw_assert (lch == (charT)(std::tolower)(ch, loc), 0, __LINE__,
|
||||
"tolower<%s>(%{#lc}, locale(%#s)) == %{#lc}, got %{#lc}",
|
||||
cname, ch, locname, lch, (std::tolower)(ch, loc));
|
||||
} END_LOCALE_LOOP (locname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libc (charT, const char *cname)
|
||||
{
|
||||
test_tolower (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd_tolower (charT, const char *cname,
|
||||
const std::ctype<charT> &ct,
|
||||
const char *locname)
|
||||
{
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::ctype<%s>::tolower(%1$s) in locale(%#s)",
|
||||
cname, locname);
|
||||
|
||||
int success;
|
||||
|
||||
#undef TEST
|
||||
#define TEST(lower, upper) \
|
||||
success = ct.widen (lower) == ct.tolower (ct.widen (upper)); \
|
||||
rw_assert (success, 0, __LINE__, \
|
||||
"ctype<%s>::tolower(%d) == %d, got %d", \
|
||||
cname, upper, lower, ct.tolower((charT)upper))
|
||||
|
||||
TEST ('a', 'A');
|
||||
TEST ('b', 'B');
|
||||
TEST ('c', 'C');
|
||||
|
||||
if (sizeof(charT) > 1)
|
||||
TEST ('\xa0', '\xa1');
|
||||
|
||||
#undef TEST
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd (charT, const char *cname)
|
||||
{
|
||||
const char cmap_1[] = {
|
||||
"<code_set_name> \"ANSI_X3.4-1968\"\n"
|
||||
"<mb_cur_max> 1\n"
|
||||
"<mb_cur_min> 1\n"
|
||||
"CHARMAP\n"
|
||||
"<U0000> \\x00\n"
|
||||
"<U0001> \\x01\n"
|
||||
"<U0002> \\x02\n"
|
||||
"<U0003> \\x03\n"
|
||||
"<U0004> \\x04\n"
|
||||
"<U0005> \\x05\n"
|
||||
"<U0006> \\x06\n"
|
||||
"<U0007> \\x07\n"
|
||||
"<U0008> \\x08\n"
|
||||
"<U0009> \\x09\n"
|
||||
"<U000a> \\x0a\n"
|
||||
"<U000b> \\x0b\n"
|
||||
"<U000c> \\x0c\n"
|
||||
"<U000d> \\x0d\n"
|
||||
"<U000e> \\x0e\n"
|
||||
"<U000f> \\x0f\n"
|
||||
"<U0010> \\x10\n"
|
||||
"<U0011> \\x11\n"
|
||||
"<U0012> \\x12\n"
|
||||
"<U0013> \\x13\n"
|
||||
"<U0014> \\x14\n"
|
||||
"<U0015> \\x15\n"
|
||||
"<U0016> \\x16\n"
|
||||
"<U0017> \\x17\n"
|
||||
"<U0018> \\x18\n"
|
||||
"<U0019> \\x19\n"
|
||||
"<U001a> \\x1a\n"
|
||||
"<U001b> \\x1b\n"
|
||||
"<U001c> \\x1c\n"
|
||||
"<U001d> \\x1d\n"
|
||||
"<U001e> \\x1e\n"
|
||||
"<U001f> \\x1f\n"
|
||||
"<U0020> \\x20\n"
|
||||
"<U0021> \\x21\n"
|
||||
"<U0022> \\x22\n"
|
||||
"<U0023> \\x23\n"
|
||||
"<U0024> \\x24\n"
|
||||
"<U0025> \\x25\n"
|
||||
"<U0026> \\x26\n"
|
||||
"<U0027> \\x27\n"
|
||||
"<U0028> \\x28\n"
|
||||
"<U0029> \\x29\n"
|
||||
"<U002a> \\x2a\n"
|
||||
"<U002b> \\x2b\n"
|
||||
"<U002c> \\x2c\n"
|
||||
"<U002d> \\x2d\n"
|
||||
"<U002e> \\x2e\n"
|
||||
"<U002f> \\x2f\n"
|
||||
"<U0030> \\x30\n"
|
||||
"<U0031> \\x31\n"
|
||||
"<U0032> \\x32\n"
|
||||
"<U0033> \\x33\n"
|
||||
"<U0034> \\x34\n"
|
||||
"<U0035> \\x35\n"
|
||||
"<U0036> \\x36\n"
|
||||
"<U0037> \\x37\n"
|
||||
"<U0038> \\x38\n"
|
||||
"<U0039> \\x39\n"
|
||||
"<U003a> \\x3a\n"
|
||||
"<U003b> \\x3b\n"
|
||||
"<U003c> \\x3c\n"
|
||||
"<U003d> \\x3d\n"
|
||||
"<U003e> \\x3e\n"
|
||||
"<U003f> \\x3f\n"
|
||||
"<U0040> \\x40\n"
|
||||
"<U0041> \\x41\n"
|
||||
"<U0042> \\x42\n"
|
||||
"<U0043> \\x43\n"
|
||||
"<U0044> \\x44\n"
|
||||
"<U0045> \\x45\n"
|
||||
"<U0046> \\x46\n"
|
||||
"<U0047> \\x47\n"
|
||||
"<U0048> \\x48\n"
|
||||
"<U0049> \\x49\n"
|
||||
"<U004a> \\x4a\n"
|
||||
"<U004b> \\x4b\n"
|
||||
"<U004c> \\x4c\n"
|
||||
"<U004d> \\x4d\n"
|
||||
"<U004e> \\x4e\n"
|
||||
"<U004f> \\x4f\n"
|
||||
"<U0050> \\x50\n"
|
||||
"<U0051> \\x51\n"
|
||||
"<U0052> \\x52\n"
|
||||
"<U0053> \\x53\n"
|
||||
"<U0054> \\x54\n"
|
||||
"<U0055> \\x55\n"
|
||||
"<U0056> \\x56\n"
|
||||
"<U0057> \\x57\n"
|
||||
"<U0058> \\x58\n"
|
||||
"<U0059> \\x59\n"
|
||||
"<U005a> \\x5a\n"
|
||||
"<U005b> \\x5b\n"
|
||||
"<U005c> \\x5c\n"
|
||||
"<U005d> \\x5d\n"
|
||||
"<U005e> \\x5e\n"
|
||||
"<U005f> \\x5f\n"
|
||||
"<U0060> \\x60\n"
|
||||
"<U0061> \\x61\n"
|
||||
"<U0062> \\x62\n"
|
||||
"<U0063> \\x63\n"
|
||||
"<U0064> \\x64\n"
|
||||
"<U0065> \\x65\n"
|
||||
"<U0066> \\x66\n"
|
||||
"<U0067> \\x67\n"
|
||||
"<U0068> \\x68\n"
|
||||
"<U0069> \\x69\n"
|
||||
"<U006a> \\x6a\n"
|
||||
"<U006b> \\x6b\n"
|
||||
"<U006c> \\x6c\n"
|
||||
"<U006d> \\x6d\n"
|
||||
"<U006e> \\x6e\n"
|
||||
"<U006f> \\x6f\n"
|
||||
"<U0070> \\x70\n"
|
||||
"<U0071> \\x71\n"
|
||||
"<U0072> \\x72\n"
|
||||
"<U0073> \\x73\n"
|
||||
"<U0074> \\x74\n"
|
||||
"<U0075> \\x75\n"
|
||||
"<U0076> \\x76\n"
|
||||
"<U0077> \\x77\n"
|
||||
"<U0078> \\x78\n"
|
||||
"<U0079> \\x79\n"
|
||||
"<U007a> \\x7a\n"
|
||||
"<U007b> \\x7b\n"
|
||||
"<U007c> \\x7c\n"
|
||||
"<U007d> \\x7d\n"
|
||||
"<U007e> \\x7e\n"
|
||||
"<U007f> \\x7f\n"
|
||||
"<U1000> \\xa0\n"
|
||||
"<U1001> \\xa1\n"
|
||||
"<U1002> \\xa2\n"
|
||||
"END CHARMAP\n"
|
||||
};
|
||||
|
||||
const char loc_1[] = {
|
||||
"escape_char /\n"
|
||||
"LC_CTYPE\n"
|
||||
"toupper (<U0061>,<U0041>);(<U0062>,<U0042>);"
|
||||
"(<U0063>,<U0043>);(<U1000>,<U1001>)\n"
|
||||
"tolower (<U0041>,<U0061>);(<U0042>,<U0062>);"
|
||||
"(<U0043>,<U0063>);(<U1001>,<U1000>)\n"
|
||||
"END LC_CTYPE\n"
|
||||
};
|
||||
|
||||
//invoke rw_create_locale to build a locale to test with
|
||||
const char* const locname = rw_create_locale (cmap_1, loc_1);
|
||||
|
||||
if (!rw_error (0 != locname, 0, __LINE__,
|
||||
"failed to create a locale in %s", locale_root))
|
||||
return;
|
||||
|
||||
const std::locale loc (locname);
|
||||
|
||||
const std::ctype<charT> &ct =
|
||||
_STD_USE_FACET (std::ctype<charT>, loc);
|
||||
|
||||
ct._C_opts |= ct._C_use_libstd;
|
||||
ct._C_opts &= ~ct._C_use_libc;
|
||||
|
||||
test_libstd_tolower (charT (), cname, ct, locname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void run_test (charT, const char *cname)
|
||||
{
|
||||
if (0) {
|
||||
// do a compile time only test on use_facet and has_facet
|
||||
_STD_HAS_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
_STD_USE_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
}
|
||||
|
||||
test_libc (charT (), cname);
|
||||
test_libstd (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
run_test (char (), "char");
|
||||
run_test (wchar_t (), "wchar_t");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.category.ctype",
|
||||
0 /* no comment */,
|
||||
run_test,
|
||||
"",
|
||||
(void*)0 /* sentinel */);
|
||||
}
|
||||
497
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.toupper.cpp
vendored
Normal file
497
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.toupper.cpp
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.ctype.toupper.cpp - Tests exercising the toupper() of ctype facet
|
||||
*
|
||||
* $Id: 22.locale.ctype.toupper.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.
|
||||
*
|
||||
* Copyright 2001-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// DESCRIPTION: test iterates over the locales installed on a machine,
|
||||
// calling the C character classification functions and
|
||||
// their C++ counterpart(s), comparing the results of
|
||||
// the calls against one another.
|
||||
|
||||
|
||||
#include <rw/_defs.h>
|
||||
|
||||
#if defined __linux__
|
||||
// on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
|
||||
# define _XOPEN_SOURCE 500 /* Single Unix conformance */
|
||||
// bring __int32_t into scope (otherwise <wctype.h> fails to compile)
|
||||
# include <sys/types.h>
|
||||
#endif // __linux__
|
||||
|
||||
// see Onyx PR #28150
|
||||
#if defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
# include <wchar.h>
|
||||
#endif // defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <climits>
|
||||
#include <clocale>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cwchar> // for WEOF, btowc(), wctob()
|
||||
#include <cwctype> // for iswxxx()
|
||||
|
||||
|
||||
#if !defined (_MSC_VER)
|
||||
# if !defined (LC_MESSAGES)
|
||||
# define LC_MESSAGES _RWSTD_LC_MESSAGES
|
||||
# endif // LC_MESSAGES
|
||||
# include <langinfo.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <driver.h>
|
||||
#include <file.h> // for SLASH
|
||||
#include <rw_locale.h> // for rw_locale_query()
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// the root of the locale directory (RWSTD_LOCALE_ROOT)
|
||||
// not set here to avoid Solaris 7 putenv() bug (PR #30017)
|
||||
const char* locale_root;
|
||||
|
||||
#define NLOOPS 25
|
||||
#define MAX_STR_SIZE 16
|
||||
|
||||
#define LOCALES "{{en-US,de-DE,fr-FR,es-ES}-*-{ISO-8859-*,UTF-8,CP125?}," \
|
||||
"{ja-JP-*-{EUC-JP,SHIFT_JIS,UTF-8,CP125?}}," \
|
||||
"{zh-CN-*-{GB*,UTF-8,CP125?}}," \
|
||||
"{ru-RU-*-{KOI*,UTF-8,CP125?}}}"
|
||||
|
||||
const char* locale_list = 0;
|
||||
|
||||
#define BEGIN_LOCALE_LOOP(num, locname, loop_cntrl) \
|
||||
if (!locale_list) locale_list = rw_locale_query (LC_CTYPE, LOCALES); \
|
||||
for (const char* locname = locale_list; \
|
||||
locname && *locname; locname += std::strlen (locname) + 1) { \
|
||||
_TRY { \
|
||||
const std::locale loc (locname); \
|
||||
const std::ctype<char> &ctc = \
|
||||
_STD_USE_FACET (std::ctype<char>, loc); \
|
||||
_RWSTD_UNUSED (ctc); \
|
||||
const std::ctype<charT> &ctp = \
|
||||
_STD_USE_FACET (std::ctype<charT>, loc); \
|
||||
for (int loop_cntrl = 0; loop_cntrl < int (num); loop_cntrl++)
|
||||
|
||||
#define END_LOCALE_LOOP(locname) \
|
||||
} \
|
||||
_CATCH (...) { \
|
||||
rw_assert (0, 0, __LINE__, \
|
||||
"locale (\"%s\") threw an exception", locname); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
// for notational convenience
|
||||
typedef unsigned char UChar;
|
||||
|
||||
#define ALPHA std::ctype_base::alpha
|
||||
#define UPPER std::ctype_base::upper
|
||||
#define LOWER std::ctype_base::lower
|
||||
#define DIGIT std::ctype_base::digit
|
||||
#define SPACE std::ctype_base::space
|
||||
#define CNTRL std::ctype_base::cntrl
|
||||
#define PUNCT std::ctype_base::punct
|
||||
#define XDIGIT std::ctype_base::xdigit
|
||||
#define GRAPH std::ctype_base::graph
|
||||
#define PRINT std::ctype_base::print
|
||||
|
||||
|
||||
// wrapper functions for the c library char and wchar_t functions
|
||||
char libc_tolower (char ch)
|
||||
{
|
||||
return std::tolower (UChar (ch));
|
||||
}
|
||||
|
||||
char libc_toupper (char ch)
|
||||
{
|
||||
return (std::toupper)(UChar (ch));
|
||||
}
|
||||
|
||||
const char* widen (char *dst, const char *src)
|
||||
{
|
||||
if (src == dst || !src || !dst)
|
||||
return src;
|
||||
|
||||
std::memcpy (dst, src, std::strlen (src) + 1);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
char widen (char, char ch, const char*)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t libc_tolower (wchar_t ch)
|
||||
{
|
||||
return (std::towlower)(ch);
|
||||
}
|
||||
|
||||
wchar_t libc_toupper (wchar_t ch)
|
||||
{
|
||||
return (std::towupper)(ch);
|
||||
}
|
||||
|
||||
const wchar_t* widen (wchar_t *dst, const char *src)
|
||||
{
|
||||
static wchar_t buf [4096];
|
||||
|
||||
if (!src)
|
||||
return 0;
|
||||
|
||||
if (!dst)
|
||||
dst = buf;
|
||||
|
||||
std::size_t len = std::strlen (src);
|
||||
|
||||
_RWSTD_ASSERT (len < sizeof buf /sizeof *buf);
|
||||
|
||||
len = std::mbstowcs (dst, src, sizeof buf / sizeof *buf);
|
||||
|
||||
if (std::size_t (-1) == len)
|
||||
*dst = 0;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
wchar_t widen (wchar_t, char ch, const char *locname)
|
||||
{
|
||||
char curlocname [256];
|
||||
std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0));
|
||||
|
||||
if (0 == std::setlocale (LC_CTYPE, locname))
|
||||
return UChar (ch);
|
||||
|
||||
wchar_t result;
|
||||
|
||||
#ifndef _RWSTD_NO_BTOWC
|
||||
|
||||
result = std::btowc (UChar (ch));
|
||||
|
||||
#elif !defined (_RWSTD_NO_MBTOWC)
|
||||
|
||||
if (1 != std::mbtowc (&result, &ch, 1))
|
||||
result = wchar_t (WEOF);
|
||||
|
||||
#else
|
||||
|
||||
result = UChar (ch);
|
||||
|
||||
#endif // _RWSTD_NO_BTOWC, _RWSTD_NO_MBTOWC
|
||||
|
||||
if (locname)
|
||||
std::setlocale (LC_CTYPE, curlocname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_toupper (charT, const char *cname)
|
||||
{
|
||||
rw_info (0, 0, __LINE__, "std::ctype<%s>::toupper(%1$s)", cname);
|
||||
|
||||
BEGIN_LOCALE_LOOP (UCHAR_MAX, locname2, i) {
|
||||
|
||||
const charT ch = charT (i);
|
||||
|
||||
// set the global C locale to the locale name for the C library call
|
||||
std::setlocale (LC_CTYPE, locname2);
|
||||
|
||||
const charT uch = libc_toupper (ch);
|
||||
|
||||
// set the global C locale to default to make sure
|
||||
// the C++ library does not asume a set value
|
||||
std::setlocale (LC_CTYPE, "");
|
||||
|
||||
// exercise toupper using ctype<>::toupper ()
|
||||
rw_assert (uch == (ctp.toupper)(ch), 0, __LINE__,
|
||||
"ctype<%s>::toupper(%{#lc}) == %{#lc}, got %{#lc} "
|
||||
"in locale(%#s)",
|
||||
cname, ch, uch, (ctp.toupper)(ch), locname2);
|
||||
|
||||
// exercise toupper using toupper (char, locale)
|
||||
rw_assert (uch == (charT)(std::toupper)(ch, loc), 0, __LINE__,
|
||||
"toupper<%s>(%{#lc}, locale(%#s)) == %{#lc}, got %{#lc}",
|
||||
cname, ch, locname2, uch, (std::toupper)(ch, loc));
|
||||
} END_LOCALE_LOOP (locname2);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libc (charT, const char *cname)
|
||||
{
|
||||
test_toupper (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd_toupper (charT, const char *cname,
|
||||
const std::ctype<charT> &ct,
|
||||
const char *locname)
|
||||
{
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::ctype<%s>::toupper(%1$s) in locale(%#s)",
|
||||
cname, locname);
|
||||
|
||||
int success;
|
||||
|
||||
#undef TEST
|
||||
#define TEST(lower, upper) \
|
||||
success = ct.widen (upper) == ct.toupper (ct.widen (lower)); \
|
||||
rw_assert (success, 0, __LINE__, \
|
||||
"ctype<%s>::toupper(%d) == %d, got %d", cname, \
|
||||
lower, upper, ct.toupper((charT)lower));
|
||||
|
||||
TEST ('a', 'A');
|
||||
TEST ('b', 'B');
|
||||
TEST ('c', 'C');
|
||||
|
||||
if (sizeof(charT) > 1)
|
||||
TEST ('\xa0', '\xa1');
|
||||
|
||||
#undef TEST
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_libstd (charT, const char *cname)
|
||||
{
|
||||
const char cmap_1[] = {
|
||||
"<code_set_name> \"ANSI_X3.4-1968\"\n"
|
||||
"<mb_cur_max> 1\n"
|
||||
"<mb_cur_min> 1\n"
|
||||
"CHARMAP\n"
|
||||
"<U0000> \\x00\n"
|
||||
"<U0001> \\x01\n"
|
||||
"<U0002> \\x02\n"
|
||||
"<U0003> \\x03\n"
|
||||
"<U0004> \\x04\n"
|
||||
"<U0005> \\x05\n"
|
||||
"<U0006> \\x06\n"
|
||||
"<U0007> \\x07\n"
|
||||
"<U0008> \\x08\n"
|
||||
"<U0009> \\x09\n"
|
||||
"<U000a> \\x0a\n"
|
||||
"<U000b> \\x0b\n"
|
||||
"<U000c> \\x0c\n"
|
||||
"<U000d> \\x0d\n"
|
||||
"<U000e> \\x0e\n"
|
||||
"<U000f> \\x0f\n"
|
||||
"<U0010> \\x10\n"
|
||||
"<U0011> \\x11\n"
|
||||
"<U0012> \\x12\n"
|
||||
"<U0013> \\x13\n"
|
||||
"<U0014> \\x14\n"
|
||||
"<U0015> \\x15\n"
|
||||
"<U0016> \\x16\n"
|
||||
"<U0017> \\x17\n"
|
||||
"<U0018> \\x18\n"
|
||||
"<U0019> \\x19\n"
|
||||
"<U001a> \\x1a\n"
|
||||
"<U001b> \\x1b\n"
|
||||
"<U001c> \\x1c\n"
|
||||
"<U001d> \\x1d\n"
|
||||
"<U001e> \\x1e\n"
|
||||
"<U001f> \\x1f\n"
|
||||
"<U0020> \\x20\n"
|
||||
"<U0021> \\x21\n"
|
||||
"<U0022> \\x22\n"
|
||||
"<U0023> \\x23\n"
|
||||
"<U0024> \\x24\n"
|
||||
"<U0025> \\x25\n"
|
||||
"<U0026> \\x26\n"
|
||||
"<U0027> \\x27\n"
|
||||
"<U0028> \\x28\n"
|
||||
"<U0029> \\x29\n"
|
||||
"<U002a> \\x2a\n"
|
||||
"<U002b> \\x2b\n"
|
||||
"<U002c> \\x2c\n"
|
||||
"<U002d> \\x2d\n"
|
||||
"<U002e> \\x2e\n"
|
||||
"<U002f> \\x2f\n"
|
||||
"<U0030> \\x30\n"
|
||||
"<U0031> \\x31\n"
|
||||
"<U0032> \\x32\n"
|
||||
"<U0033> \\x33\n"
|
||||
"<U0034> \\x34\n"
|
||||
"<U0035> \\x35\n"
|
||||
"<U0036> \\x36\n"
|
||||
"<U0037> \\x37\n"
|
||||
"<U0038> \\x38\n"
|
||||
"<U0039> \\x39\n"
|
||||
"<U003a> \\x3a\n"
|
||||
"<U003b> \\x3b\n"
|
||||
"<U003c> \\x3c\n"
|
||||
"<U003d> \\x3d\n"
|
||||
"<U003e> \\x3e\n"
|
||||
"<U003f> \\x3f\n"
|
||||
"<U0040> \\x40\n"
|
||||
"<U0041> \\x41\n"
|
||||
"<U0042> \\x42\n"
|
||||
"<U0043> \\x43\n"
|
||||
"<U0044> \\x44\n"
|
||||
"<U0045> \\x45\n"
|
||||
"<U0046> \\x46\n"
|
||||
"<U0047> \\x47\n"
|
||||
"<U0048> \\x48\n"
|
||||
"<U0049> \\x49\n"
|
||||
"<U004a> \\x4a\n"
|
||||
"<U004b> \\x4b\n"
|
||||
"<U004c> \\x4c\n"
|
||||
"<U004d> \\x4d\n"
|
||||
"<U004e> \\x4e\n"
|
||||
"<U004f> \\x4f\n"
|
||||
"<U0050> \\x50\n"
|
||||
"<U0051> \\x51\n"
|
||||
"<U0052> \\x52\n"
|
||||
"<U0053> \\x53\n"
|
||||
"<U0054> \\x54\n"
|
||||
"<U0055> \\x55\n"
|
||||
"<U0056> \\x56\n"
|
||||
"<U0057> \\x57\n"
|
||||
"<U0058> \\x58\n"
|
||||
"<U0059> \\x59\n"
|
||||
"<U005a> \\x5a\n"
|
||||
"<U005b> \\x5b\n"
|
||||
"<U005c> \\x5c\n"
|
||||
"<U005d> \\x5d\n"
|
||||
"<U005e> \\x5e\n"
|
||||
"<U005f> \\x5f\n"
|
||||
"<U0060> \\x60\n"
|
||||
"<U0061> \\x61\n"
|
||||
"<U0062> \\x62\n"
|
||||
"<U0063> \\x63\n"
|
||||
"<U0064> \\x64\n"
|
||||
"<U0065> \\x65\n"
|
||||
"<U0066> \\x66\n"
|
||||
"<U0067> \\x67\n"
|
||||
"<U0068> \\x68\n"
|
||||
"<U0069> \\x69\n"
|
||||
"<U006a> \\x6a\n"
|
||||
"<U006b> \\x6b\n"
|
||||
"<U006c> \\x6c\n"
|
||||
"<U006d> \\x6d\n"
|
||||
"<U006e> \\x6e\n"
|
||||
"<U006f> \\x6f\n"
|
||||
"<U0070> \\x70\n"
|
||||
"<U0071> \\x71\n"
|
||||
"<U0072> \\x72\n"
|
||||
"<U0073> \\x73\n"
|
||||
"<U0074> \\x74\n"
|
||||
"<U0075> \\x75\n"
|
||||
"<U0076> \\x76\n"
|
||||
"<U0077> \\x77\n"
|
||||
"<U0078> \\x78\n"
|
||||
"<U0079> \\x79\n"
|
||||
"<U007a> \\x7a\n"
|
||||
"<U007b> \\x7b\n"
|
||||
"<U007c> \\x7c\n"
|
||||
"<U007d> \\x7d\n"
|
||||
"<U007e> \\x7e\n"
|
||||
"<U007f> \\x7f\n"
|
||||
"<U1000> \\xa0\n"
|
||||
"<U1001> \\xa1\n"
|
||||
"<U1002> \\xa2\n"
|
||||
"END CHARMAP\n"
|
||||
};
|
||||
|
||||
const char loc_1[] = {
|
||||
"escape_char /\n"
|
||||
"LC_CTYPE\n"
|
||||
"toupper (<U0061>,<U0041>);(<U0062>,<U0042>);"
|
||||
"(<U0063>,<U0043>);(<U1000>,<U1001>)\n"
|
||||
"tolower (<U0041>,<U0061>);(<U0042>,<U0062>);"
|
||||
"(<U0043>,<U0063>);(<U1001>,<U1000>)\n"
|
||||
"END LC_CTYPE\n"
|
||||
};
|
||||
|
||||
//invoke rw_create_locale to build a locale to test with
|
||||
const char* const locname = rw_create_locale (cmap_1, loc_1);
|
||||
|
||||
if (!rw_error (0 != locname, 0, __LINE__,
|
||||
"failed to create a locale in %s", locale_root))
|
||||
return;
|
||||
|
||||
const std::locale loc (locname);
|
||||
|
||||
const std::ctype<charT> &ct =
|
||||
_STD_USE_FACET (std::ctype<charT>, loc);
|
||||
|
||||
ct._C_opts |= ct._C_use_libstd;
|
||||
ct._C_opts &= ~ct._C_use_libc;
|
||||
|
||||
test_libstd_toupper (charT (), cname, ct, locname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void run_test (charT, const char *cname)
|
||||
{
|
||||
if (0) {
|
||||
// do a compile time only test on use_facet and has_facet
|
||||
_STD_HAS_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
_STD_USE_FACET (std::ctype_byname<charT>, std::locale ());
|
||||
}
|
||||
|
||||
test_libc (charT (), cname);
|
||||
test_libstd (charT (), cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
run_test (char (), "char");
|
||||
run_test (wchar_t (), "wchar_t");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.category.ctype",
|
||||
0 /* no comment */,
|
||||
run_test,
|
||||
"",
|
||||
(void*)0 /* sentinel */);
|
||||
}
|
||||
152
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.widen.cpp
vendored
Normal file
152
extern/stdcxx/4.2.1/tests/localization/22.locale.ctype.widen.cpp
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.ctype.widen.cpp - tests exercising std::ctype<charT>::widen()
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 1994-2008 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <driver.h>
|
||||
|
||||
typedef unsigned char UChar;
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
typedef std::ctype<wchar_t> WCtype;
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static void
|
||||
test_char ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "std::ctype<char>::widen(char)");
|
||||
|
||||
const std::locale loc;
|
||||
|
||||
const WCtype& ctp = std::use_facet<WCtype> (loc);
|
||||
|
||||
for (int i = 0; i != int (_RWSTD_UCHAR_MAX) + 1; ++i) {
|
||||
|
||||
// compute the argument, and the expected and actual results
|
||||
const char narrow = char (i);
|
||||
const char expect = narrow;
|
||||
const char wide = ctp.widen (narrow);
|
||||
|
||||
rw_assert (expect == wide, __FILE__, __LINE__,
|
||||
"std::ctype<char>::widen(%#c) == %#c, got %#c",
|
||||
narrow, expect, wide);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// will leave this here for now since it appears to be a placeholder
|
||||
// for further testing
|
||||
|
||||
static void
|
||||
test_byname_char ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__,
|
||||
"std::ctype_byname<char>::widen(char)");
|
||||
|
||||
rw_warn (false, __FILE__, __LINE__,
|
||||
"ctype_byname<char>::widen() not exercised");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static void
|
||||
test_wchar_t ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__,
|
||||
"std::ctype<wchar_t>::widen(char)");
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::locale loc;
|
||||
|
||||
const WCtype& ctp = std::use_facet<WCtype> (loc);
|
||||
|
||||
for (int i = 0; i != int (_RWSTD_UCHAR_MAX) + 1; ++i) {
|
||||
|
||||
// compute the argument, and the expected and actual results
|
||||
const char narrow = char (i);
|
||||
const wchar_t expect = wchar_t (UChar (narrow));
|
||||
const wchar_t wide = ctp.widen (narrow);
|
||||
|
||||
rw_assert (expect == wide, __FILE__, __LINE__,
|
||||
"std::ctype<wchar_t>::widen(%#c) == %#Lc, got %#Lc",
|
||||
narrow, expect, wide);
|
||||
}
|
||||
|
||||
#else // if defined (_RWSTD_NO_WCHAR_T)
|
||||
|
||||
rw_warn (false, __FILE__, __LINE__,
|
||||
"ctype<wchar_t>::widen() not exercised: "
|
||||
"macro _RWSTD_NO_WCHAR_T defined");
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// another placeholder for further testing?
|
||||
|
||||
static void
|
||||
test_byname_wchar_t ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__,
|
||||
"std::ctype_byname<wchar_t>::widen(char)");
|
||||
|
||||
rw_warn (false, __FILE__, __LINE__,
|
||||
"ctype_byname<wchar_t>::widen() not exercised");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int /*unused*/, char* /*unused*/ [])
|
||||
{
|
||||
test_char ();
|
||||
test_byname_char ();
|
||||
|
||||
test_wchar_t ();
|
||||
test_byname_wchar_t ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*extern*/ int
|
||||
main (int argc, char* argv [])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.ctype.widen",
|
||||
0, // no comment
|
||||
run_test, "", 0);
|
||||
}
|
||||
|
||||
626
extern/stdcxx/4.2.1/tests/localization/22.locale.globals.mt.cpp
vendored
Normal file
626
extern/stdcxx/4.2.1/tests/localization/22.locale.globals.mt.cpp
vendored
Normal file
@@ -0,0 +1,626 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.globals.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of [locale.global.templates]
|
||||
*
|
||||
* $Id: 22.locale.globals.mt.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 <locale> // for locale
|
||||
|
||||
#include <cwchar> // for mbstate_t
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h> // for rw_locales()
|
||||
#include <rw_thread.h> // for rw_get_processors(), rw_thread_pool()
|
||||
#include <driver.h> // for rw_test()
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 16
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int opt_nloops = 20000;
|
||||
|
||||
enum {
|
||||
opt_inx_codecvt,
|
||||
opt_inx_collate,
|
||||
opt_inx_ctype,
|
||||
opt_inx_messages,
|
||||
opt_inx_moneypunct,
|
||||
opt_inx_moneypunct_intl,
|
||||
opt_inx_numpunct,
|
||||
opt_inx_money_get,
|
||||
opt_inx_money_put,
|
||||
opt_inx_num_get,
|
||||
opt_inx_num_put,
|
||||
opt_inx_time_get,
|
||||
opt_inx_time_put,
|
||||
opt_nfacets
|
||||
};
|
||||
|
||||
// tri-state options to enable/disable individual facets
|
||||
// opt_facets [i] < 0: facet is initially explicitly disabled
|
||||
// opt_facets [i] == 0: option not specified on the command line
|
||||
// opt_facets [i] > 0: facet is initially explicitly enabled
|
||||
int opt_facets [opt_nfacets];
|
||||
|
||||
// disable exceptions?
|
||||
int opt_no_exceptions;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// convenience typedefs for all required specializations of standard facets
|
||||
typedef std::codecvt<char, char, std::mbstate_t> Codecvt;
|
||||
typedef std::collate<char> Collate;
|
||||
typedef std::ctype<char> Ctype;
|
||||
typedef std::messages<char> Messages;
|
||||
typedef std::moneypunct<char, false> Moneypunct0;
|
||||
typedef std::moneypunct<char, true> Moneypunct1;
|
||||
typedef std::numpunct<char> Numpunct;
|
||||
typedef std::money_get<char> MoneyGet;
|
||||
typedef std::money_put<char> MoneyPut;
|
||||
typedef std::num_get<char> NumGet;
|
||||
typedef std::num_put<char> NumPut;
|
||||
typedef std::time_get<char> TimeGet;
|
||||
typedef std::time_put<char> TimePut;
|
||||
|
||||
typedef std::collate_byname<char> CollateByname;
|
||||
typedef std::ctype_byname<char> CtypeByname;
|
||||
typedef std::codecvt_byname<char, char, std::mbstate_t> CodecvtByname;
|
||||
typedef std::messages_byname<char> MessagesByname;
|
||||
typedef std::moneypunct_byname<char, false> Moneypunct0Byname;
|
||||
typedef std::moneypunct_byname<char, true> Moneypunct1Byname;
|
||||
typedef std::numpunct_byname<char> NumpunctByname;
|
||||
typedef std::time_get_byname<char> TimeGetByname;
|
||||
typedef std::time_put_byname<char> TimePutByname;
|
||||
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
typedef std::collate<wchar_t> WCollate;
|
||||
typedef std::ctype<wchar_t> WCtype;
|
||||
typedef std::codecvt<wchar_t, char, std::mbstate_t> WCodecvt;
|
||||
typedef std::messages<wchar_t> WMessages;
|
||||
typedef std::moneypunct<wchar_t, false> WMoneypunct0;
|
||||
typedef std::moneypunct<wchar_t, true> WMoneypunct1;
|
||||
typedef std::numpunct<wchar_t> WNumpunct;
|
||||
typedef std::money_get<wchar_t> WMoneyGet;
|
||||
typedef std::money_put<wchar_t> WMoneyPut;
|
||||
typedef std::num_get<wchar_t> WNumGet;
|
||||
typedef std::num_put<wchar_t> WNumPut;
|
||||
typedef std::time_get<wchar_t> WTimeGet;
|
||||
typedef std::time_put<wchar_t> WTimePut;
|
||||
|
||||
typedef std::collate_byname<wchar_t> WCollateByname;
|
||||
typedef std::ctype_byname<wchar_t> WCtypeByname;
|
||||
typedef std::codecvt_byname<wchar_t, char, std::mbstate_t> WCodecvtByname;
|
||||
typedef std::messages_byname<wchar_t> WMessagesByname;
|
||||
typedef std::moneypunct_byname<wchar_t, false> WMoneypunct0Byname;
|
||||
typedef std::moneypunct_byname<wchar_t, true> WMoneypunct1Byname;
|
||||
typedef std::numpunct_byname<wchar_t> WNumpunctByname;
|
||||
typedef std::time_get_byname<wchar_t> WTimeGetByname;
|
||||
typedef std::time_put_byname<wchar_t> WTimePutByname;
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void*
|
||||
test_has_facet (void*)
|
||||
{
|
||||
const std::locale classic (std::locale::classic ());
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
// save the name of the locale
|
||||
const char* const locale_name = locales [i % nlocales];
|
||||
|
||||
// construct a named locale and imbue it in the ios object
|
||||
// so that the locale is used not only by the num_put facet
|
||||
// but also by the numpunct facet
|
||||
const std::locale loc (locale_name);
|
||||
|
||||
const bool byname = loc != classic;
|
||||
|
||||
// call has_facet for each base facet only of it's enabled
|
||||
#define HAS(Facet, opt) \
|
||||
(0 <= opt_facets [opt_inx_ ## opt] ? std::has_facet<Facet>(loc) : true)
|
||||
|
||||
HAS (Codecvt, codecvt);
|
||||
HAS (Collate, collate);
|
||||
HAS (Ctype, ctype);
|
||||
HAS (Messages, messages);
|
||||
HAS (Moneypunct0, moneypunct);
|
||||
HAS (Moneypunct1, moneypunct_intl);
|
||||
HAS (MoneyGet, money_get);
|
||||
HAS (MoneyPut, money_put);
|
||||
HAS (Numpunct, numpunct);
|
||||
HAS (NumGet, num_get);
|
||||
HAS (NumPut, num_put);
|
||||
HAS (TimeGet, time_get);
|
||||
HAS (TimePut, time_put);
|
||||
|
||||
// call has_facet for each _byname facet only of it's enabled
|
||||
#define HAS_BYNAME(Facet, opt) \
|
||||
(0 <= opt_facets [opt_inx_ ## opt] ? \
|
||||
byname == std::has_facet<Facet>(loc) : true)
|
||||
|
||||
HAS_BYNAME (CodecvtByname, codecvt);
|
||||
HAS_BYNAME (CollateByname, collate);
|
||||
HAS_BYNAME (CtypeByname, ctype);
|
||||
HAS_BYNAME (MessagesByname, messages);
|
||||
HAS_BYNAME (Moneypunct0Byname, moneypunct);
|
||||
HAS_BYNAME (Moneypunct1Byname, moneypunct_intl);
|
||||
HAS_BYNAME (TimeGetByname, time_get);
|
||||
HAS_BYNAME (TimePutByname, time_put);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
HAS (WCodecvt, codecvt);
|
||||
HAS (WCollate, collate);
|
||||
HAS (WCtype, ctype);
|
||||
HAS (WMessages, messages);
|
||||
HAS (WMoneypunct0, moneypunct);
|
||||
HAS (WMoneypunct1, moneypunct_intl);
|
||||
HAS (WMoneyGet, money_get);
|
||||
HAS (WMoneyPut, money_put);
|
||||
HAS (WNumpunct, numpunct);
|
||||
HAS (WNumGet, num_get);
|
||||
HAS (WNumPut, num_put);
|
||||
HAS (WTimeGet, time_get);
|
||||
HAS (WTimePut, time_put);
|
||||
|
||||
HAS_BYNAME (WCodecvtByname, codecvt);
|
||||
HAS_BYNAME (WCollateByname, collate);
|
||||
HAS_BYNAME (WCtypeByname, ctype);
|
||||
HAS_BYNAME (WMessagesByname, messages);
|
||||
HAS_BYNAME (WMoneypunct0Byname, moneypunct);
|
||||
HAS_BYNAME (WMoneypunct1Byname, moneypunct_intl);
|
||||
HAS_BYNAME (WTimeGetByname, time_get);
|
||||
HAS_BYNAME (WTimePutByname, time_put);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
static void
|
||||
use_facet_loop (const std::locale &classic, int i)
|
||||
{
|
||||
static const std::locale::facet* const dummy =
|
||||
(std::locale::facet*)1;
|
||||
|
||||
// save the name of the locale
|
||||
const char* const locale_name = locales [i % nlocales];
|
||||
|
||||
// construct a named locale and imbue it in the ios object
|
||||
// so that the locale is used not only by the num_put facet
|
||||
// but also by the numpunct facet
|
||||
const std::locale loc (locale_name);
|
||||
|
||||
const bool byname = loc != classic;
|
||||
|
||||
{
|
||||
|
||||
#define USE(Facet, opt) \
|
||||
(0 <= opt_facets [opt_inx_ ## opt] ? &std::use_facet<Facet>(loc) : dummy)
|
||||
|
||||
const std::locale::facet* const bases[] = {
|
||||
// get pointers to the char specializations of facets
|
||||
USE (Collate, collate),
|
||||
USE (Ctype, ctype),
|
||||
USE (Codecvt, codecvt),
|
||||
USE (Messages, messages),
|
||||
USE (Moneypunct0, moneypunct),
|
||||
USE (Moneypunct1, moneypunct_intl),
|
||||
USE (MoneyGet, money_get),
|
||||
USE (MoneyPut, money_put),
|
||||
USE (Numpunct, numpunct),
|
||||
USE (NumGet, num_get),
|
||||
USE (NumPut, num_put),
|
||||
USE (TimeGet, time_get),
|
||||
USE (TimePut, time_put)
|
||||
};
|
||||
|
||||
if (byname) {
|
||||
|
||||
// get pointers to the char specializations
|
||||
// of byname facets
|
||||
const std::locale::facet* const derived[] = {
|
||||
USE (CollateByname, collate),
|
||||
USE (CtypeByname, ctype),
|
||||
USE (CodecvtByname, codecvt),
|
||||
USE (MessagesByname, messages),
|
||||
USE (Moneypunct0Byname, moneypunct),
|
||||
USE (Moneypunct1Byname, moneypunct_intl),
|
||||
// no money_get_byname or money_put_byname
|
||||
USE (MoneyGet, money_get),
|
||||
USE (MoneyPut, money_put),
|
||||
USE (NumpunctByname, numpunct),
|
||||
// no num_get_byname or num_put_byname
|
||||
USE (NumGet, num_get),
|
||||
USE (NumPut, num_put),
|
||||
USE (TimeGetByname, time_get),
|
||||
USE (TimePutByname, time_put)
|
||||
};
|
||||
|
||||
const std::size_t nbases = sizeof bases / sizeof *bases;
|
||||
|
||||
for (std::size_t j = 0; j != nbases; ++j) {
|
||||
RW_ASSERT (bases [j] != 0);
|
||||
RW_ASSERT (bases [j] == derived [j]);
|
||||
}
|
||||
}
|
||||
else if (0 == opt_no_exceptions) {
|
||||
|
||||
bool threw;
|
||||
|
||||
#define TEST_USE_FACET(Facet, opt) \
|
||||
try { \
|
||||
threw = false; \
|
||||
if (0 <= opt_facets [opt_inx_ ## opt]) \
|
||||
std::use_facet<Facet>(loc); \
|
||||
} \
|
||||
catch (...) { threw = true; } \
|
||||
RW_ASSERT (threw || opt_facets [opt_inx_ ## opt] < 0)
|
||||
|
||||
TEST_USE_FACET (CollateByname, collate);
|
||||
TEST_USE_FACET (CtypeByname, ctype);
|
||||
TEST_USE_FACET (CodecvtByname, codecvt);
|
||||
TEST_USE_FACET (MessagesByname, messages);
|
||||
TEST_USE_FACET (Moneypunct0Byname, moneypunct);
|
||||
TEST_USE_FACET (Moneypunct1Byname, moneypunct_intl);
|
||||
TEST_USE_FACET (NumpunctByname, numpunct);
|
||||
TEST_USE_FACET (TimeGetByname, time_get);
|
||||
TEST_USE_FACET (TimePutByname, time_put);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
{
|
||||
const std::locale::facet* const bases[] = {
|
||||
// get pointers to the char specializations of facets
|
||||
USE (WCollate, collate),
|
||||
USE (WCtype, ctype),
|
||||
USE (WCodecvt, codecvt),
|
||||
USE (WMessages, messages),
|
||||
USE (WMoneypunct0, moneypunct),
|
||||
USE (WMoneypunct1, moneypunct_intl),
|
||||
USE (WMoneyGet, money_get),
|
||||
USE (WMoneyPut, money_put),
|
||||
USE (WNumpunct, numpunct),
|
||||
USE (WNumGet, num_get),
|
||||
USE (WNumPut, num_put),
|
||||
USE (WTimeGet, time_get),
|
||||
USE (WTimePut, time_put)
|
||||
};
|
||||
|
||||
if (byname) {
|
||||
// get pointers to the char specializations
|
||||
// of byname facets
|
||||
const std::locale::facet* const derived[] = {
|
||||
USE (WCollateByname, collate),
|
||||
USE (WCtypeByname, ctype),
|
||||
USE (WCodecvtByname, codecvt),
|
||||
USE (WMessagesByname, messages),
|
||||
USE (WMoneypunct0Byname, moneypunct),
|
||||
USE (WMoneypunct1Byname, moneypunct_intl),
|
||||
// no money_get_byname or money_put_byname
|
||||
USE (WMoneyGet, money_get),
|
||||
USE (WMoneyPut, money_put),
|
||||
USE (WNumpunctByname, numpunct),
|
||||
// no num_get_byname or num_put_byname
|
||||
USE (WNumGet, num_get),
|
||||
USE (WNumPut, num_put),
|
||||
USE (WTimeGetByname, time_get),
|
||||
USE (WTimePutByname, time_put)
|
||||
};
|
||||
|
||||
const std::size_t nbases = sizeof bases / sizeof *bases;
|
||||
|
||||
for (std::size_t j = 0; j != nbases; ++j) {
|
||||
RW_ASSERT (bases [j] != 0);
|
||||
RW_ASSERT (bases [j] == derived [j]);
|
||||
}
|
||||
}
|
||||
else if (0 == opt_no_exceptions) {
|
||||
|
||||
bool threw;
|
||||
|
||||
TEST_USE_FACET (WCollateByname, collate);
|
||||
TEST_USE_FACET (WCtypeByname, ctype);
|
||||
TEST_USE_FACET (WCodecvtByname, codecvt);
|
||||
TEST_USE_FACET (WMessagesByname, messages);
|
||||
TEST_USE_FACET (WMoneypunct0Byname, moneypunct);
|
||||
TEST_USE_FACET (WMoneypunct1Byname, moneypunct_intl);
|
||||
TEST_USE_FACET (WNumpunctByname, numpunct);
|
||||
TEST_USE_FACET (WTimeGetByname, time_get);
|
||||
TEST_USE_FACET (WTimePutByname, time_put);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void*
|
||||
test_use_facet (void*)
|
||||
{
|
||||
const std::locale classic (std::locale::classic ());
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
try {
|
||||
use_facet_loop (classic, i);
|
||||
}
|
||||
catch (...) {
|
||||
// what to do here?
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int opt_has_facet; // exercise std::has_facet?
|
||||
int opt_use_facet; // exercise std::use_facet?
|
||||
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
for (std::size_t i = 0; i != opt_nfacets; ++i) {
|
||||
if (0 < opt_facets [i]) {
|
||||
for (std::size_t j = 0; j != opt_nfacets; ++j) {
|
||||
if (opt_facets [j] == 0)
|
||||
opt_facets [j] = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_codecvt], 0, __LINE__,
|
||||
"std::codecvt tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_collate], 0, __LINE__,
|
||||
"std::collate tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_ctype], 0, __LINE__,
|
||||
"std::ctype tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_messages], 0, __LINE__,
|
||||
"std::messages tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_moneypunct], 0, __LINE__,
|
||||
"std::moneypunct<charT, false> tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_moneypunct_intl], 0, __LINE__,
|
||||
"std::moneypunct<charT, true> tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_money_get], 0, __LINE__,
|
||||
"std::money_get tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_money_put], 0, __LINE__,
|
||||
"std::money_put tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_numpunct], 0, __LINE__,
|
||||
"std::numpunct tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_num_get], 0, __LINE__,
|
||||
"std::num_get tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_num_put], 0, __LINE__,
|
||||
"std::num_put tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_time_get], 0, __LINE__,
|
||||
"std::time_get tests disabled");
|
||||
|
||||
rw_note (0 <= opt_facets [opt_inx_time_put], 0, __LINE__,
|
||||
"std::time_put tests disabled");
|
||||
|
||||
rw_note (0 == opt_no_exceptions, 0, __LINE__,
|
||||
"tests involving exceptions disabled");
|
||||
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = sizeof locales / sizeof *locales;
|
||||
|
||||
// set to true if the classic "C" locale is on the lost
|
||||
bool has_classic = false;
|
||||
|
||||
for (const char *name = locale_list; *name; name += std::strlen (name) +1) {
|
||||
|
||||
locales [nlocales++] = name;
|
||||
|
||||
if (!has_classic && 0 == std::strcmp ("C", name))
|
||||
has_classic = true;
|
||||
|
||||
if (nlocales == maxinx)
|
||||
break;
|
||||
}
|
||||
|
||||
// when the classic "C" locale isn't on the list put it there
|
||||
// unless the list was explicitly specified on the command line
|
||||
if (1 < nlocales && !has_classic && 0 == rw_opt_locales)
|
||||
locales [0] = "C";
|
||||
|
||||
int result;
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::locale globals with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
if (opt_has_facet >= 0) {
|
||||
rw_info (0, 0, 0,
|
||||
"template <class T> bool std::has_facet (const locale&)");
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
|
||||
test_has_facet, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, test_has_facet);
|
||||
}
|
||||
else {
|
||||
rw_note (0, 0, 0, "std::has_facet test disabled");
|
||||
}
|
||||
|
||||
if (opt_use_facet >= 0) {
|
||||
rw_info (0, 0, 0,
|
||||
"template <class T> const T& std::use_facet (const locale&)");
|
||||
|
||||
#ifdef _RWSTD_NO_DYNAMIC_CAST
|
||||
|
||||
// if dynamic_cast isn't supported, then [has,use]_facet()
|
||||
// can't reliably detect if a facet is installed or not.
|
||||
rw_warn (0 != opt_no_exceptions, 0, __LINE__,
|
||||
"dynamic_cast not supported "
|
||||
"(macro _RWSTD_NO_DYNAMIC_CAST is #defined), "
|
||||
"disabling exceptions tests");
|
||||
|
||||
opt_no_exceptions = 1;
|
||||
|
||||
#endif // _RWSTD_NO_DYNAMIC_CAST
|
||||
|
||||
|
||||
#ifdef _RWSTD_NO_THREAD_SAFE_EXCEPTIONS
|
||||
|
||||
// avoid exercising exceptions (triggered by use_facet) if
|
||||
// their implementation in the runtime isn't thread-safe
|
||||
rw_warn (0, 0, 0,
|
||||
"exceptions not thread safe (macro "
|
||||
"_RWSTD_NO_THREAD_SAFE_EXCEPTIONS is #defined), "
|
||||
"disabling exceptions tests");
|
||||
|
||||
opt_no_exceptions = 1;
|
||||
|
||||
#endif // _RWSTD_NO_THREAD_SAFE_EXCEPTIONS
|
||||
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
|
||||
test_use_facet, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, test_use_facet);
|
||||
}
|
||||
else {
|
||||
rw_note (0, 0, 0, "std::use_facet test disabled");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.global.templates",
|
||||
"thread safety", run_test,
|
||||
"|-has_facet~ "
|
||||
"|-use_facet~ "
|
||||
"|-nloops#0 " // arg must be non-negative
|
||||
"|-nthreads#0-* " // arg must be in [0, MAX_THREADS]
|
||||
"|-locales= " // argument must be provided
|
||||
"|-no-exceptions# " // disable exceptions
|
||||
"|-codecvt~ " // enable/disable individual facets
|
||||
"|-collate~ "
|
||||
"|-ctype~ "
|
||||
"|-messages~ "
|
||||
"|-moneypunct~ "
|
||||
"|-moneypunct_intl~ "
|
||||
"|-money_get~ "
|
||||
"|-money_put~ "
|
||||
"|-numpunct~ "
|
||||
"|-num_get~ "
|
||||
"|-num_put~ "
|
||||
"|-time_get~ "
|
||||
"|-time_put~ ",
|
||||
&opt_has_facet,
|
||||
&opt_use_facet,
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&rw_opt_setlocales,
|
||||
&opt_no_exceptions,
|
||||
opt_facets + opt_inx_codecvt,
|
||||
opt_facets + opt_inx_collate,
|
||||
opt_facets + opt_inx_ctype,
|
||||
opt_facets + opt_inx_messages,
|
||||
opt_facets + opt_inx_moneypunct,
|
||||
opt_facets + opt_inx_moneypunct_intl,
|
||||
opt_facets + opt_inx_money_get,
|
||||
opt_facets + opt_inx_money_put,
|
||||
opt_facets + opt_inx_numpunct,
|
||||
opt_facets + opt_inx_num_get,
|
||||
opt_facets + opt_inx_num_put,
|
||||
opt_facets + opt_inx_time_get,
|
||||
opt_facets + opt_inx_time_put);
|
||||
}
|
||||
888
extern/stdcxx/4.2.1/tests/localization/22.locale.messages.cpp
vendored
Normal file
888
extern/stdcxx/4.2.1/tests/localization/22.locale.messages.cpp
vendored
Normal file
@@ -0,0 +1,888 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.messages.cpp - tests exercising the std::messages facet
|
||||
*
|
||||
* $Id: 22.locale.messages.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.
|
||||
*
|
||||
* Copyright 2001-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <driver.h> // for rw_test()
|
||||
#include <environ.h> // for rw_putenv()
|
||||
#include <file.h> // for rw_nextfd()
|
||||
#include <rw_locale.h> // for rw_locales(), rw_create_catalog()
|
||||
#include <rw_process.h> // for rw_system()
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
#include <cstdlib> // for getenv()
|
||||
#include <cstdio> // for remove()
|
||||
#include <clocale> // for LC_ALL
|
||||
|
||||
#include <cwchar> // for mbsinit()
|
||||
|
||||
#ifndef _RWSTD_NO_NEW_HEADER
|
||||
# if defined (_MSC_VER)
|
||||
# include <io.h> // for _open()
|
||||
# include <direct.h> // for getcwd()
|
||||
# else
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h> // for getcwd()
|
||||
# endif
|
||||
# include <fcntl.h> // for mode flags for _open
|
||||
#endif // _RWSTD_NO_NEW_HEADER
|
||||
|
||||
#undef open
|
||||
#undef close
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# define open(f,m) _open (f, _##m)
|
||||
# define close(f) _close (f)
|
||||
#else
|
||||
# define open(f,m) open (f, m)
|
||||
# define close(f) close (f)
|
||||
#endif // defined (_MSC_VER)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
struct CodeCvt: std::codecvt<charT, char, std::mbstate_t>
|
||||
{
|
||||
typedef std::codecvt<charT, char, std::mbstate_t> Base;
|
||||
typedef typename Base::extern_type extern_type;
|
||||
typedef typename Base::intern_type intern_type;
|
||||
typedef typename Base::state_type state_type;
|
||||
typedef typename Base::result result;
|
||||
|
||||
static bool used_;
|
||||
static bool partial_;
|
||||
static bool noconv_;
|
||||
static bool check_state_;
|
||||
|
||||
static bool valid_state_;
|
||||
|
||||
CodeCvt (std::size_t ref = 1U)
|
||||
: Base (ref) {
|
||||
used_ = partial_ = noconv_ = check_state_ = valid_state_ = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// override base class virtual function to make the messages
|
||||
// facet use codecvt<char, char>::in() (the base returns true)
|
||||
bool do_always_noconv () const _THROWS (()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result
|
||||
do_in (state_type &state,
|
||||
const extern_type *from,
|
||||
const extern_type *from_end,
|
||||
const extern_type *&from_next,
|
||||
intern_type *to,
|
||||
intern_type *to_end,
|
||||
intern_type *&to_next) const {
|
||||
|
||||
used_ = true;
|
||||
|
||||
#ifndef _RWSTD_NO_MBSINIT
|
||||
|
||||
if (check_state_)
|
||||
valid_state_ = std::mbsinit (&state) != 0;
|
||||
|
||||
#else // if (_RWSTD_NO_MBSINIT)
|
||||
|
||||
if (check_state_)
|
||||
valid_state_ = true;
|
||||
|
||||
#endif // _RWSTD_NO_MBSINIT
|
||||
|
||||
const result res =
|
||||
Base::do_in (state, from, from_end, from_next,
|
||||
to, to_end, to_next);
|
||||
|
||||
if (partial_)
|
||||
return std::codecvt_base::partial;
|
||||
|
||||
if (noconv_)
|
||||
return std::codecvt_base::noconv;
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT>
|
||||
bool CodeCvt<charT>::used_;
|
||||
template <class charT>
|
||||
bool CodeCvt<charT>::partial_;
|
||||
template <class charT>
|
||||
bool CodeCvt<charT>::noconv_;
|
||||
template <class charT>
|
||||
bool CodeCvt<charT>::check_state_;
|
||||
template <class charT>
|
||||
bool CodeCvt<charT>::valid_state_;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// finds the first named locale other than "C" or "POSIX"; returns
|
||||
// a pointer to the name of the locale on success, 0 on failure
|
||||
const char*
|
||||
find_named_locale ()
|
||||
{
|
||||
const char *name = rw_locales (LC_ALL, "");
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
char namebuf [256];
|
||||
|
||||
// get the full name of the "C" locale for comparison with aliases
|
||||
const char* const classic_name =
|
||||
std::strcpy (namebuf, std::setlocale (LC_ALL, "C"));
|
||||
|
||||
do {
|
||||
if (std::strcmp (name, "C") && std::strcmp (name, "POSIX")) {
|
||||
|
||||
// skip over any aliases of the "C" and "POSIX" locales
|
||||
const char* const fullname = std::setlocale (LC_ALL, name);
|
||||
if (std::strcmp (fullname, classic_name)) {
|
||||
|
||||
// skip over the C and POSIX locales
|
||||
_TRY {
|
||||
const std::locale loc (name);
|
||||
_RWSTD_UNUSED (loc);
|
||||
|
||||
std::setlocale (LC_ALL, "C");
|
||||
return name;
|
||||
}
|
||||
_CATCH (...) { }
|
||||
}
|
||||
}
|
||||
name += std::strlen (name) + 1;
|
||||
|
||||
} while (*name);
|
||||
|
||||
std::setlocale (LC_ALL, "C");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifndef _WIN32
|
||||
# define CAT_NAME "./rwstdmessages.cat"
|
||||
# define MSG_NAME "rwstdmessages.msg"
|
||||
#else
|
||||
# define CAT_NAME "rwstdmessages.dll"
|
||||
# define MSG_NAME "rwstdmessages.rc"
|
||||
#endif
|
||||
|
||||
#define NLS_CAT_NAME "rwstdmessages"
|
||||
|
||||
#define MAX_SETS 5
|
||||
#define MAX_MESSAGES 5
|
||||
|
||||
|
||||
int msg_id (int set, int id)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
return (set - 1) * 5 + id;
|
||||
|
||||
#else
|
||||
|
||||
_RWSTD_UNUSED (set);
|
||||
return id;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static const char* const
|
||||
messages [MAX_SETS][MAX_MESSAGES] = {
|
||||
{ "First set, first message",
|
||||
"First set, second message",
|
||||
"First set, third message",
|
||||
"First set, fourth message",
|
||||
"First set, fifth message"
|
||||
},
|
||||
{ "Second set, first message",
|
||||
"Second set, second message",
|
||||
"Second set, third message",
|
||||
"Second set, fourth message",
|
||||
"Second set, fifth message"
|
||||
},
|
||||
{ "Third set, first message",
|
||||
"Third set, second message",
|
||||
"Third set, third message",
|
||||
"Third set, fourth message",
|
||||
"Third set, fifth message"
|
||||
},
|
||||
{ "Fourth set, first message",
|
||||
"Fourth set, second message",
|
||||
"Fourth set, third message",
|
||||
"Fourth set, fourth message",
|
||||
"Fourth set, fifth message"
|
||||
},
|
||||
{ "Fifth set, first message",
|
||||
"Fifth set, second message",
|
||||
"Fifth set, third message",
|
||||
"Fifth set, fourth message",
|
||||
"Fifth set, fifth message"
|
||||
}
|
||||
};
|
||||
|
||||
static std::string catalog;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
template <class charT>
|
||||
std::basic_string<charT> widen (std::string message)
|
||||
{
|
||||
std::basic_string<charT> result;
|
||||
for (std::size_t i = 0; i < message.length(); i++) {
|
||||
result.push_back ((charT)message[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// Test that the message facet exists in the locale and that
|
||||
// we can get a reference to it.
|
||||
template <class charT>
|
||||
void test_has_facet (const char *loc_name, const char *cname)
|
||||
{
|
||||
// construct a copy of the named locale or default
|
||||
// when no name is specified
|
||||
const std::locale loc =
|
||||
loc_name ? std::locale (loc_name) : std::locale ();
|
||||
|
||||
typedef std::messages<charT> Messages;
|
||||
|
||||
// verify that the facet exists in the locale
|
||||
bool facet_exists = std::has_facet<Messages>(loc);
|
||||
|
||||
rw_assert (facet_exists, 0, __LINE__,
|
||||
"has_facet<messages<%s> >(locale(%{?}%#s%{;})) == true",
|
||||
cname, 0 != loc_name, loc_name);
|
||||
|
||||
try {
|
||||
// verify that use facet doesn't throw an exception
|
||||
std::use_facet<Messages>(loc);
|
||||
}
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (std::exception &ex) {
|
||||
rw_assert (0, 0, __LINE__,
|
||||
"use_fact<messages<%s> >(locale(%{?}%#s%{;})) "
|
||||
"unexpectedly threw exception(%#s)",
|
||||
cname, 0 != loc_name, loc_name, ex.what ());
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (0, 0, __LINE__,
|
||||
"use_fact<messages<%s> >(locale(%{?}%#s%{;})) "
|
||||
"unexpectedly threw an unknown exception",
|
||||
cname, 0 != loc_name, loc_name);
|
||||
}
|
||||
|
||||
typedef std::messages_byname<charT> MessagesByname;
|
||||
|
||||
const bool byname = loc_name
|
||||
&& std::strcmp (loc_name, "C") && std::strcmp (loc_name, "POSIX");
|
||||
|
||||
facet_exists = std::has_facet<MessagesByname>(loc);
|
||||
|
||||
rw_assert (byname == facet_exists, 0, __LINE__,
|
||||
"has_fact<messages_byname<%s> >(locale(%{?}%#s%{;})) == %b",
|
||||
cname, 0 != loc_name, loc_name);
|
||||
|
||||
try {
|
||||
// verify that use facet throws an exception only
|
||||
// for the default and "C" locales
|
||||
std::use_facet<MessagesByname>(loc);
|
||||
|
||||
rw_assert (byname, 0, __LINE__,
|
||||
"use_fact<messages_byname<%s> >(locale(%{?}%#s%{;})) "
|
||||
"failed to throw",
|
||||
cname, 0 != loc_name, loc_name);
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
rw_assert (!byname, 0, __LINE__,
|
||||
"use_fact<messages_byname<%s> >(locale(%{?}%#s%{;})) "
|
||||
"unexpectedly threw exception(%#s)",
|
||||
cname, 0 != loc_name, loc_name, ex.what ());
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (0, 0, __LINE__,
|
||||
"use_fact<messages<%s> >(locale(%{?}%#s%{;})) "
|
||||
"unexpectedly threw an unknown exception",
|
||||
cname, 0 != loc_name, loc_name);
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
std::messages_base::catalog
|
||||
open_catalog (const std::messages<charT> &msgs,
|
||||
const char *cat_name, const std::locale &loc,
|
||||
int expect, const char *cname, int line)
|
||||
{
|
||||
std::messages_base::catalog cat = -1;
|
||||
|
||||
// expect is set to:
|
||||
// * 0 (or greater) when the caller expects the call to open()
|
||||
// to succeed
|
||||
// * -1 when the caller expects the call to open() to fail
|
||||
// by returning -1
|
||||
// * -2 (or less) when the caller expects the call to open()
|
||||
// to exit by throwing an exception
|
||||
const bool expect_success = expect >= 0;
|
||||
const bool expect_failure = expect == -1;
|
||||
const bool expect_exception = expect < -1;
|
||||
|
||||
const char* const nlspath = std::getenv ("NLSPATH");
|
||||
|
||||
try {
|
||||
// an already closed cat should throw an exception
|
||||
cat = (msgs.open)(cat_name, loc);
|
||||
|
||||
const bool success =
|
||||
expect_success && -1 < cat || expect_failure && cat < 0;
|
||||
|
||||
rw_assert (success, 0, line,
|
||||
"messages<%s>::open(%#s, locale(%#s))"
|
||||
"%{?} > -1%{:}%{?} == -1 %{;}%{;}, got %d"
|
||||
"%{?}; failed to throw an exception%{;}; NLSPATH=%s",
|
||||
cname, cat_name, loc.name ().c_str (),
|
||||
expect_success, expect_failure, cat,
|
||||
expect_exception, nlspath);
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (std::exception &ex) {
|
||||
rw_assert (expect_exception, 0, line,
|
||||
"messages<%s>::open(%#s, locale(%#s)) unexpectedly "
|
||||
"threw exception(%#s); NLSPATH=%s",
|
||||
cname, cat_name, loc.name ().c_str (), ex.what (), nlspath);
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (expect_exception, 0, line,
|
||||
"messages<%s>::open(%#s, locale(%#s)) unexpectedly "
|
||||
"threw an unknown exception; NLSPATH=%s",
|
||||
cname, cat_name, loc.name ().c_str (), nlspath);
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
return cat;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void
|
||||
close_catalog (const std::messages<charT> &msgs,
|
||||
std::messages_base::catalog cat,
|
||||
bool expect_exception,
|
||||
const char *cname, int line)
|
||||
{
|
||||
try {
|
||||
// an already closed cat should throw an exception
|
||||
(msgs.close)(cat);
|
||||
|
||||
rw_assert (!expect_exception, 0, line,
|
||||
"messages<%s>::close(%d) failed "
|
||||
"to throw an expected exception",
|
||||
cname, cat);
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (std::exception &ex) {
|
||||
rw_assert (expect_exception, 0, line,
|
||||
"messages<%s>::close(%d) unexpectedly "
|
||||
"threw exception(%#s)",
|
||||
cname, cat, ex.what ());
|
||||
}
|
||||
catch (...) {
|
||||
rw_assert (expect_exception, 0, line,
|
||||
"messages<%s>::close(%d) unexpectedly "
|
||||
"threw an unknown exception",
|
||||
cname, cat);
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_open_close (const char *loc_name, const char *cname)
|
||||
{
|
||||
int fdcount [2];
|
||||
int next_fd [2];
|
||||
|
||||
#ifndef _WIN32
|
||||
next_fd [0] = rw_nextfd (fdcount + 0);
|
||||
#else
|
||||
// don't test file descriptor leaking on Win32 to avoid
|
||||
// invalid parameter error
|
||||
// catalog functions not uses file descriptors
|
||||
next_fd [0] = fdcount [0] = 0;
|
||||
#endif
|
||||
|
||||
rw_info (0, 0, __LINE__,
|
||||
"std::messages<%s>::open() and close() in locale(#%s)",
|
||||
cname, loc_name);
|
||||
|
||||
// construct a copy of the named locale or default
|
||||
// when no name is specified
|
||||
const std::locale loc =
|
||||
loc_name ? std::locale (loc_name) : std::locale ();
|
||||
|
||||
const std::messages<charT>& msgs =
|
||||
std::use_facet<std::messages<charT> >(loc);
|
||||
|
||||
const std::messages_base::catalog cat =
|
||||
open_catalog (msgs, CAT_NAME, loc, 0, cname, __LINE__);
|
||||
|
||||
// close a (presumably successfully) opened catalog
|
||||
close_catalog (msgs, cat, cat < 0, cname, __LINE__);
|
||||
|
||||
// an already closed cat should throw an exception
|
||||
close_catalog (msgs, cat, true, cname, __LINE__);
|
||||
|
||||
// verify that no file descriptor has leaked
|
||||
#ifndef _WIN32
|
||||
next_fd [1] = rw_nextfd (fdcount + 1);
|
||||
#else
|
||||
next_fd [1] = fdcount [1] = 0;
|
||||
#endif
|
||||
|
||||
rw_assert (next_fd [1] == next_fd [0] && fdcount [0] == fdcount [1],
|
||||
0, __LINE__,
|
||||
"std::messages<%s>::close() leaked %d file descriptor(s) "
|
||||
"(or descriptor mismatch)",
|
||||
cname, fdcount [1] - fdcount [0]);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_get (const char *loc_name,
|
||||
const char* const text[5][5],
|
||||
const char *cname)
|
||||
{
|
||||
// construct a copy of the named locale or default
|
||||
// when no name is specified
|
||||
const std::locale loc =
|
||||
loc_name ? std::locale (loc_name) : std::locale ();
|
||||
|
||||
const std::messages<charT>& msgs =
|
||||
std::use_facet<std::messages<charT> > (loc);
|
||||
|
||||
const charT def[] = {
|
||||
'N', 'o', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', '.', '\0'
|
||||
};
|
||||
|
||||
std::messages_base::catalog cat = -1;
|
||||
|
||||
cat = open_catalog (msgs, CAT_NAME, loc, 0, cname, __LINE__);
|
||||
|
||||
if (cat < 0)
|
||||
return;
|
||||
|
||||
typedef std::char_traits<charT> Traits;
|
||||
typedef std::allocator<charT> Allocator;
|
||||
typedef std::basic_string<charT, Traits, Allocator> String;
|
||||
|
||||
for (int setId = 1; setId <= MAX_SETS; ++setId) {
|
||||
|
||||
for (int msgId = 1; msgId <= MAX_MESSAGES; ++msgId) {
|
||||
|
||||
const int id = msg_id (setId, msgId);
|
||||
const String got = msgs.get (cat, setId, id, def);
|
||||
|
||||
rw_assert (got == widen<charT>(text [setId - 1][msgId - 1]),
|
||||
0, __LINE__,
|
||||
"messages<%s>::get(%d, %d, %d, %{*Ac}) == %#s, "
|
||||
"got %{#*S}",
|
||||
cname, cat, setId, id,
|
||||
int (sizeof *def), def,
|
||||
text [setId - 1][msgId - 1],
|
||||
int (sizeof (charT)), &got);
|
||||
}
|
||||
}
|
||||
|
||||
// bad catalog id
|
||||
const std::messages_base::catalog bad_cat = 777;
|
||||
|
||||
try {
|
||||
// get() will either throw or return `def'
|
||||
// when passed a bad catalog id
|
||||
const String got = msgs.get (bad_cat, 1, 1, def);
|
||||
|
||||
rw_assert (def == got, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 1, 1, %{*Ac}) == %{*Ac}, got %{#*S}",
|
||||
cname, bad_cat, int (sizeof *def), def,
|
||||
int (sizeof *def), def, int (sizeof (charT)), &got);
|
||||
}
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (std::exception &ex) {
|
||||
rw_assert (true, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 1, 1, %{*Ac}) unexpectedly threw "
|
||||
"exception(%#s)", cname, bad_cat, int (sizeof *def), def,
|
||||
ex.what ());
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
// Bad set id
|
||||
#if !defined (_WIN32) && !defined (_WIN64)
|
||||
// When we use resource files for the message catalogs
|
||||
// the set ids are ignored.
|
||||
rw_assert (msgs.get (cat, 777, 1, def) == def, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 777, 1, %{#*Ac}) == %{#*Ac}",
|
||||
cname, cat, int (sizeof *def), def, int (sizeof *def), def);
|
||||
#endif // !defined (_WIN32) && !defined (_WIN64)
|
||||
|
||||
// Bad message id
|
||||
rw_assert (msgs.get (cat, 1, 777, def) == def, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 777, 1) == \"\"", cname);
|
||||
|
||||
close_catalog (msgs, cat, false, cname, __LINE__);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void test_use_codecvt (const char *cname)
|
||||
{
|
||||
CodeCvt<charT> cvt (1);
|
||||
|
||||
const std::locale loc (std::locale::classic (), &cvt);
|
||||
|
||||
const charT def[] = {
|
||||
'N', 'o', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', '.', '\0'
|
||||
};
|
||||
|
||||
const std::messages<charT>& msgs =
|
||||
std::use_facet <std::messages<charT> >(loc);
|
||||
|
||||
cvt.used_ = false;
|
||||
|
||||
std::messages_base::catalog cat = -1;
|
||||
|
||||
cat = open_catalog (msgs, CAT_NAME, loc, 0, cname, __LINE__);
|
||||
|
||||
if (cat < 0)
|
||||
return;
|
||||
|
||||
cvt.check_state_ = true;
|
||||
|
||||
const int msgid = msg_id (1, 1);
|
||||
std::basic_string<charT> got = msgs.get (cat, 1, msgid, def);
|
||||
rw_assert (cvt.used_, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 1, %d, const char_type*) "
|
||||
"uses codecvt<%1$s, char>", cname, cat, msgid);
|
||||
|
||||
rw_assert (cvt.valid_state_, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 1, %d, const char_type*) "
|
||||
"initializes mbstate_t argument", cname, cat, msgid);
|
||||
|
||||
cvt.check_state_ = false;
|
||||
cvt.partial_ = true;
|
||||
|
||||
got = msgs.get (cat, 1, msgid, def);
|
||||
rw_assert (got == def, 0, __LINE__,
|
||||
"messages<%s>::get(%d, 1, %d, %{*Ac}) == %{*Ac}",
|
||||
cname, cat, msgid, int (sizeof *def), def,
|
||||
int (sizeof *def), def);
|
||||
|
||||
cvt.partial_ = false;
|
||||
cvt.noconv_ = true;
|
||||
|
||||
got = msgs.get (cat, 1, msgid, def);
|
||||
rw_assert (got == widen<charT>(std::string(messages[0][0])), 0, __LINE__,
|
||||
"messages<%s>::get(%d, 1, %d, %{*Ac}) == %#s, got %{#*S}",
|
||||
cname, cat, msgid, int (sizeof *def), def,
|
||||
messages [0][0], int (sizeof (charT)), &got);
|
||||
|
||||
cvt.noconv_ = false;
|
||||
|
||||
close_catalog (msgs, cat, false, cname, __LINE__);
|
||||
|
||||
cvt.used_ = false;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
template <class charT>
|
||||
void test_use_nls_path (const char *cname)
|
||||
{
|
||||
// get working directory
|
||||
char cwd [2048];
|
||||
cwd [0] = '\0';
|
||||
if (!rw_error (0 != getcwd (cwd, 2048), 0, __LINE__,
|
||||
"getcwd(%#p, %u) failed: %{#m} (%m)", cwd, 2048))
|
||||
return;
|
||||
|
||||
char* const nlspath = new char [std::strlen (cwd) + 512];
|
||||
|
||||
// create NLSPATH string
|
||||
std::sprintf (nlspath, "NLSPATH=%s/%%N.cat", cwd);
|
||||
rw_putenv (nlspath);
|
||||
|
||||
const std::locale loc;
|
||||
|
||||
const std::messages<charT>& msgs =
|
||||
std::use_facet <std::messages<charT> >(loc);
|
||||
|
||||
const std::messages_base::catalog cat =
|
||||
open_catalog (msgs, NLS_CAT_NAME, loc, 0, "char", __LINE__);
|
||||
|
||||
if (-1 < cat)
|
||||
close_catalog (msgs, cat, false, cname, __LINE__);
|
||||
|
||||
delete[] nlspath;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
template <class charT>
|
||||
void stress_test (const char *cname)
|
||||
{
|
||||
// NLSPATH must be defined
|
||||
RW_ASSERT (0 != std::getenv ("NLSPATH"));
|
||||
|
||||
char catalog_names [24][24];
|
||||
const std::size_t NCATS = sizeof catalog_names / sizeof *catalog_names;
|
||||
|
||||
std::messages_base::catalog cats [NCATS];
|
||||
|
||||
// detect descriptor leaks
|
||||
const int fd1 = open (__FILE__, O_RDONLY);
|
||||
|
||||
const std::locale loc = std::locale::classic ();
|
||||
|
||||
const std::messages<charT>& msgs =
|
||||
std::use_facet<std::messages<charT> > (loc);
|
||||
|
||||
std::size_t i;
|
||||
|
||||
for (i = 0; i < NCATS; i++) {
|
||||
|
||||
char msg_name [NCATS];
|
||||
|
||||
#ifndef _WIN32
|
||||
std::sprintf (msg_name, "rwstdmessages_%d.msg", int (i));
|
||||
#else
|
||||
std::sprintf (msg_name, "rwstdmessages_%d.rc", int (i));
|
||||
#endif
|
||||
|
||||
rw_create_catalog (msg_name, catalog.c_str ());
|
||||
|
||||
const char* const dot = std::strrchr (msg_name, '.');
|
||||
std::strncpy (catalog_names[i], msg_name, dot - msg_name);
|
||||
*(catalog_names[i] + (dot - msg_name)) = '\0';
|
||||
|
||||
// open each catalog (expect success)
|
||||
cats [i] = open_catalog (msgs, catalog_names [i],
|
||||
loc, 0, cname, __LINE__);
|
||||
}
|
||||
|
||||
// close smallest first and check for descriptor leaks
|
||||
for (i = 0; i < NCATS; ++i) {
|
||||
if (-1 != cats [i])
|
||||
close_catalog (msgs, cats [i], false, cname, __LINE__);
|
||||
}
|
||||
|
||||
int fd2 = open (__FILE__, O_RDONLY);
|
||||
rw_assert (fd2 - fd1 == 1, 0, __LINE__,
|
||||
"messages<%s>::close() leaked %d file descriptors",
|
||||
cname, fd2 - fd1 - 1);
|
||||
|
||||
// open again, close largest first and check for descriptor leaks
|
||||
for (i = 0; i < NCATS; ++i) {
|
||||
cats [i] = open_catalog (msgs, catalog_names [i],
|
||||
loc, 0, cname, __LINE__);
|
||||
}
|
||||
|
||||
for (i = NCATS; i-- > 0; ) {
|
||||
if (-1 != cats [i])
|
||||
close_catalog (msgs, cats [i], false, cname, __LINE__);
|
||||
}
|
||||
|
||||
// close again fd2
|
||||
close (fd2);
|
||||
|
||||
fd2 = open (__FILE__, O_RDONLY);
|
||||
rw_assert (fd2 - fd1 == 1, 0, __LINE__,
|
||||
"messages<%s>::close() leaked %d file descriptors",
|
||||
cname, fd2 - fd1 - 1);
|
||||
|
||||
close (fd1);
|
||||
close (fd2);
|
||||
|
||||
rw_system (SHELL_RM_F "rwstdmessages_*");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int opt_has_facet;
|
||||
int opt_open_close;
|
||||
int opt_get;
|
||||
int opt_codecvt;
|
||||
int opt_nlspath;
|
||||
int opt_stress_test;
|
||||
|
||||
|
||||
template <class charT>
|
||||
void test_messages (charT, const char *cname, const char *locname)
|
||||
{
|
||||
if (rw_note (0 <= opt_has_facet, 0, __LINE__,
|
||||
"has_facet<messages<%s> > tests disabled", cname)) {
|
||||
|
||||
// exercise has_facet and use_facet in the default locale
|
||||
test_has_facet<charT>(0, cname);
|
||||
|
||||
// exercise has_facet and use_facet in locale("C")
|
||||
test_has_facet<charT>("C", cname);
|
||||
|
||||
// exercise has_facet and use_facet in a named locale
|
||||
test_has_facet<charT>(locname, cname);
|
||||
}
|
||||
|
||||
if (rw_note (0 <= opt_open_close, 0, __LINE__,
|
||||
"messages<%s>::open() and close() tests disabled", cname)) {
|
||||
test_open_close<charT>("C", cname);
|
||||
test_open_close<charT>(locname, cname);
|
||||
}
|
||||
|
||||
if (rw_note (0 <= opt_has_facet, 0, __LINE__,
|
||||
"messages<%s>::get() tests disabled", cname)) {
|
||||
test_get<charT>("C", messages, cname);
|
||||
test_get<charT>(locname, messages, cname);
|
||||
}
|
||||
|
||||
if (rw_note (0 <= opt_has_facet, 0, __LINE__,
|
||||
"messages<%s> codecvt tests disabled", cname))
|
||||
test_use_codecvt<charT>(cname);
|
||||
|
||||
if (rw_note (0 <= opt_nlspath, 0, __LINE__,
|
||||
"messages<%s> NLSPATH tests disabled", cname))
|
||||
test_use_nls_path<charT>(cname);
|
||||
|
||||
if (rw_note (0 <= opt_has_facet, 0, __LINE__,
|
||||
"messages<%s> codecvt tests disabled", cname))
|
||||
stress_test<charT>(cname);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char*[])
|
||||
{
|
||||
|
||||
#ifdef _RWSTD_OS_AIX
|
||||
|
||||
// must do this so that NLSPATH lookup works correctly for both
|
||||
// the C and POSIX locales.
|
||||
const int p = rw_putenv ("LC__FASTMSG=false");
|
||||
rw_note (!p, 0, __LINE__, "failed to set LC__FASTMSG");
|
||||
|
||||
#endif // _RWSTD_OS_AIX
|
||||
|
||||
#ifdef _RWSTD_NO_DYNAMIC_CAST
|
||||
|
||||
// if dynamic_cast isn't supported then has_facet() can't
|
||||
// reliably detect if a facet is installed or not.
|
||||
rw_warn (0 != opt_has_facet, 0, __LINE__,
|
||||
"dynamic_cast not supported, disabling has_facet tests");
|
||||
|
||||
opt_has_facet = -1;
|
||||
|
||||
#endif // _RWSTD_NO_DYNAMIC_CAST
|
||||
|
||||
|
||||
for (int i = 0; i < MAX_SETS; ++i) {
|
||||
for (int j = 0; j < MAX_MESSAGES; ++j)
|
||||
catalog.append (messages [i][j], std::strlen (messages [i][j]) + 1);
|
||||
|
||||
catalog.append (1, '\0');
|
||||
}
|
||||
|
||||
const char* const locname = find_named_locale ();
|
||||
|
||||
rw_create_catalog (MSG_NAME, catalog.c_str ());
|
||||
|
||||
test_messages (char (), "char", locname);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
test_messages (wchar_t (), "wchar_t", locname);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
std::remove (CAT_NAME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.category.messages",
|
||||
0 /* no comment */,
|
||||
run_test,
|
||||
"|-has_facet~ "
|
||||
"|-open_close~ "
|
||||
"|-get~ "
|
||||
"|-codecvt~ "
|
||||
"|-nlspath~ "
|
||||
"|-stress-test~ ",
|
||||
&opt_has_facet,
|
||||
&opt_open_close,
|
||||
&opt_get,
|
||||
&opt_codecvt,
|
||||
&opt_nlspath,
|
||||
&opt_stress_test,
|
||||
(void*)0 /* sentinel */);
|
||||
}
|
||||
340
extern/stdcxx/4.2.1/tests/localization/22.locale.messages.mt.cpp
vendored
Normal file
340
extern/stdcxx/4.2.1/tests/localization/22.locale.messages.mt.cpp
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.messages.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the messages facet
|
||||
*
|
||||
* $Id: 22.locale.messages.mt.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 <locale>
|
||||
|
||||
#include <driver.h> // for rw_test()
|
||||
#include <rw_locale.h> // for rw_create_catalog()
|
||||
#include <rw_thread.h>
|
||||
#include <valcmp.h> // for rw_strncmp ()
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
#include <cstdio> // for remove()
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int rw_opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int rw_opt_nloops = 100000;
|
||||
|
||||
// locale for threads to share
|
||||
static const
|
||||
std::locale locale;
|
||||
|
||||
// message catalog for threads to share
|
||||
static
|
||||
std::messages_base::catalog catalog;
|
||||
|
||||
static
|
||||
std::messages_base::catalog wcatalog;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef _WIN32
|
||||
# define CAT_NAME "./rwstdmessages.cat"
|
||||
# define MSG_NAME "rwstdmessages.msg"
|
||||
#else
|
||||
# define CAT_NAME "rwstdmessages.dll"
|
||||
# define MSG_NAME "rwstdmessages.rc"
|
||||
#endif
|
||||
|
||||
#define MAX_SETS 5
|
||||
#define MAX_MESSAGES 5
|
||||
|
||||
|
||||
int msg_id (int set, int id)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
return (set - 1) * 5 + id;
|
||||
|
||||
#else
|
||||
|
||||
_RWSTD_UNUSED (set);
|
||||
return id;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static const char* const
|
||||
messages [MAX_SETS][MAX_MESSAGES] = {
|
||||
{ "First set, first message",
|
||||
"First set, second message",
|
||||
"First set, third message",
|
||||
"First set, fourth message",
|
||||
"First set, fifth message"
|
||||
},
|
||||
{ "Second set, first message",
|
||||
"Second set, second message",
|
||||
"Second set, third message",
|
||||
"Second set, fourth message",
|
||||
"Second set, fifth message"
|
||||
},
|
||||
{ "Third set, first message",
|
||||
"Third set, second message",
|
||||
"Third set, third message",
|
||||
"Third set, fourth message",
|
||||
"Third set, fifth message"
|
||||
},
|
||||
{ "Fourth set, first message",
|
||||
"Fourth set, second message",
|
||||
"Fourth set, third message",
|
||||
"Fourth set, fourth message",
|
||||
"Fourth set, fifth message"
|
||||
},
|
||||
{ "Fifth set, first message",
|
||||
"Fifth set, second message",
|
||||
"Fifth set, third message",
|
||||
"Fifth set, fourth message",
|
||||
"Fifth set, fifth message"
|
||||
}
|
||||
};
|
||||
|
||||
static std::string str_messages;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class T>
|
||||
void test_open_close (const std::locale& loc,
|
||||
const std::messages<T>& msgs,
|
||||
const std::string& name)
|
||||
{
|
||||
std::messages_base::catalog cat =
|
||||
(msgs.open) (name, loc);
|
||||
|
||||
RW_ASSERT (! (cat < 0));
|
||||
|
||||
(msgs.close) (cat);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_get (const std::messages<T>& msgs,
|
||||
const std::messages_base::catalog cat,
|
||||
int set, int msgid,
|
||||
const std::basic_string<T>& dflt)
|
||||
{
|
||||
// the msg_id() thing seems like a bug to me. if anything, the user
|
||||
// should never need to write or call msg_id().
|
||||
|
||||
const typename std::messages<T>::string_type res =
|
||||
msgs.get (cat, set, msg_id (set, msgid), dflt);
|
||||
|
||||
RW_ASSERT (!rw_strncmp (messages [set-1][msgid-1], res.c_str ()));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise messages<char>
|
||||
bool test_wchar; // exercise messages<wchar_t>
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
const std::string name (CAT_NAME);
|
||||
|
||||
const std::messages<char>& nmsgs =
|
||||
std::use_facet<std::messages<char> >(locale);
|
||||
|
||||
const std::string ndflt ("\1\2\3\4");
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
const std::messages<wchar_t>& wmsgs =
|
||||
std::use_facet<std::messages<wchar_t> >(locale);
|
||||
|
||||
const std::wstring wdflt (L"\1\2\3\4");
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
for (int i = 0; i != rw_opt_nloops; ++i) {
|
||||
|
||||
int set = 1 + i % MAX_SETS;
|
||||
int msgid = 1 + i % MAX_MESSAGES;
|
||||
|
||||
if (test_char) {
|
||||
if (i & 1) {
|
||||
test_get<char>(nmsgs, catalog, set, msgid, ndflt);
|
||||
}
|
||||
else {
|
||||
test_open_close<char>(locale, nmsgs, name);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_wchar) {
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (i & 1) {
|
||||
test_get<wchar_t>(wmsgs, wcatalog, set, msgid, wdflt);
|
||||
}
|
||||
else {
|
||||
test_open_close<wchar_t>(locale, wmsgs, name);
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
for (int i = 0; i < MAX_SETS; ++i) {
|
||||
for (int j = 0; j < MAX_MESSAGES; ++j)
|
||||
str_messages.append (messages [i][j], std::strlen (messages [i][j]) + 1);
|
||||
|
||||
str_messages.append (1, '\0');
|
||||
}
|
||||
|
||||
// generate a message catalog
|
||||
rw_create_catalog (MSG_NAME, str_messages.c_str ());
|
||||
const std::string name (CAT_NAME);
|
||||
|
||||
const std::messages<char>& nmsgs =
|
||||
std::use_facet<std::messages<char> >(locale);
|
||||
|
||||
catalog = (nmsgs.open) (name, locale);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::messages<wchar_t>& wmsgs =
|
||||
std::use_facet<std::messages<wchar_t> >(locale);
|
||||
|
||||
wcatalog = (wmsgs.open) (name, locale);
|
||||
|
||||
#endif
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::messages<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each",
|
||||
rw_opt_nthreads, 1 != rw_opt_nthreads,
|
||||
rw_opt_nloops, 1 != rw_opt_nloops);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::messages<char>");
|
||||
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
|
||||
thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::messages<wchar_t>");
|
||||
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
|
||||
thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::messages<char> and "
|
||||
"std::messages<wchar_t>");
|
||||
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
|
||||
thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
(nmsgs.close) (catalog);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
(wmsgs.close) (wcatalog);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
std::remove (CAT_NAME);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
rw_opt_nthreads = rw_get_cpus ();
|
||||
if (rw_opt_nthreads < 2)
|
||||
rw_opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.messages",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* ", // must be in [0, MAX_THREADS]
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&rw_opt_nthreads);
|
||||
}
|
||||
1064
extern/stdcxx/4.2.1/tests/localization/22.locale.money.get.cpp
vendored
Normal file
1064
extern/stdcxx/4.2.1/tests/localization/22.locale.money.get.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
478
extern/stdcxx/4.2.1/tests/localization/22.locale.money.get.mt.cpp
vendored
Normal file
478
extern/stdcxx/4.2.1/tests/localization/22.locale.money.get.mt.cpp
vendored
Normal file
@@ -0,0 +1,478 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.money.get.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the money_get facet
|
||||
*
|
||||
* $Id: 22.locale.money.get.mt.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 <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, money_get
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h>
|
||||
#include <valcmp.h> // for rw_strncmp ()
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int opt_nloops = 100000;
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around a small cache size on HP-UX in LP64 mode
|
||||
// in LP64 mode (see STDCXX-812)
|
||||
int opt_nlocales = 9;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
//
|
||||
struct MyMoneyData
|
||||
{
|
||||
enum { BufferSize = 16 };
|
||||
|
||||
enum GetId {
|
||||
get_ldbl,
|
||||
get_string,
|
||||
get_max
|
||||
};
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// international or domestic format flag
|
||||
bool intl_;
|
||||
|
||||
//
|
||||
long double units_;
|
||||
|
||||
// narrow locale specific representations of units_
|
||||
char ncs_ [BufferSize];
|
||||
std::string ncs_digits_;
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
// wide locale specific representations of units_
|
||||
wchar_t wcs_ [BufferSize];
|
||||
std::wstring wcs_digits_;
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} my_money_data [MAX_THREADS];
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyIos: std::basic_ios<charT, Traits>
|
||||
{
|
||||
MyIos () {
|
||||
this->init (0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyStreambuf: std::basic_streambuf<charT, Traits>
|
||||
{
|
||||
typedef std::basic_streambuf<charT, Traits> Base;
|
||||
|
||||
MyStreambuf ()
|
||||
: Base () {
|
||||
}
|
||||
|
||||
void pubsetg (const charT *gbeg, std::streamsize n) {
|
||||
this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
|
||||
_RWSTD_CONST_CAST (charT*, gbeg),
|
||||
_RWSTD_CONST_CAST (charT*, gbeg) + n);
|
||||
}
|
||||
|
||||
void pubsetp (charT *pbeg, std::streamsize n) {
|
||||
this->setp (pbeg, pbeg + n);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise money_get<char>
|
||||
bool test_wchar; // exercise money_get<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
std::basic_string<char, std::char_traits<char> > str;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
std::basic_string<wchar_t, std::char_traits<wchar_t> > wstr;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
std::ios_base::iostate state = std::ios_base::goodbit;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_DOUBLE
|
||||
long double ldbl = 0.;
|
||||
#endif // _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
// save the name of the locale
|
||||
const MyMoneyData& data = my_money_data [i % nlocales];
|
||||
|
||||
// construct a named locale, get a reference to the money_get
|
||||
// facet from it and use it to format a random money value
|
||||
const std::locale loc =
|
||||
opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::money_get<char> &ng =
|
||||
std::use_facet<std::money_get<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
if (i & 1) {
|
||||
ng.get (std::istreambuf_iterator<char>(&nsb),
|
||||
std::istreambuf_iterator<char>(),
|
||||
data.intl_, nio, state, ldbl);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (! rw_ldblcmp (ldbl, data.units_));
|
||||
}
|
||||
else {
|
||||
ng.get (std::istreambuf_iterator<char>(&nsb),
|
||||
std::istreambuf_iterator<char>(),
|
||||
data.intl_, nio, state, str);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (! rw_strncmp (str.c_str (),
|
||||
data.ncs_digits_.c_str ()));
|
||||
}
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::money_get<wchar_t> &wg =
|
||||
std::use_facet<std::money_get<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
if (i & 1) {
|
||||
wg.get (std::istreambuf_iterator<wchar_t>(&wsb),
|
||||
std::istreambuf_iterator<wchar_t>(),
|
||||
data.intl_, wio, state, ldbl);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (! rw_ldblcmp (ldbl, data.units_));
|
||||
}
|
||||
else {
|
||||
wg.get (std::istreambuf_iterator<wchar_t>(&wsb),
|
||||
std::istreambuf_iterator<wchar_t>(),
|
||||
data.intl_, wio, state, wstr);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (! rw_strncmp(wstr.c_str (),
|
||||
data.wcs_digits_.c_str ()));
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
// find all installed locales for which setlocale (LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
for (const char* name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the money and results for this locale
|
||||
MyMoneyData& data = my_money_data [inx];
|
||||
data.locale_name_ = name;
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
// exercise domestic formats every other iteration
|
||||
// and international formats the rest
|
||||
data.intl_ = 0 == (inx & 5);
|
||||
|
||||
// initialize with random but valid values
|
||||
long double units = 1.f + inx;
|
||||
|
||||
// exercise postive and negative values
|
||||
if (inx & 1)
|
||||
units += (units * 3.14159);
|
||||
else
|
||||
units -= (units * 2.71828);
|
||||
|
||||
// local scope
|
||||
{
|
||||
const std::money_put<char> &np =
|
||||
std::use_facet<std::money_put<char> >(loc);
|
||||
|
||||
const std::money_get<char> &ng =
|
||||
std::use_facet<std::money_get<char> >(loc);
|
||||
|
||||
std::ios::iostate state = std::ios::goodbit;
|
||||
|
||||
nio.imbue (loc);
|
||||
|
||||
// write the value to buffer from long double
|
||||
nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
data.intl_, nio, ' ', units) = '\0';
|
||||
|
||||
rw_fatal (!nio.fail (), __FILE__, __LINE__,
|
||||
"money_put<char>::put(...) "
|
||||
"failed for locale(%#s)", data.locale_name_);
|
||||
|
||||
// read the value back so threads know what to expect
|
||||
nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
ng.get (std::istreambuf_iterator<char>(&nsb),
|
||||
std::istreambuf_iterator<char>(),
|
||||
data.intl_, nio, state, data.units_);
|
||||
|
||||
// read back as string, again for threads
|
||||
nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
ng.get (std::istreambuf_iterator<char>(&nsb),
|
||||
std::istreambuf_iterator<char>(),
|
||||
data.intl_, nio, state, data.ncs_digits_);
|
||||
|
||||
if (state & std::ios_base::failbit)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
// local scope
|
||||
{
|
||||
const std::money_put<wchar_t> &wp =
|
||||
std::use_facet<std::money_put<wchar_t> >(loc);
|
||||
|
||||
const std::money_get<wchar_t> &wg =
|
||||
std::use_facet<std::money_get<wchar_t> >(loc);
|
||||
|
||||
std::ios::iostate state = std::ios::goodbit;
|
||||
|
||||
wio.imbue (loc);
|
||||
|
||||
// write the value to buffer from long double
|
||||
wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
data.intl_, wio, L' ', units) = L'\0';
|
||||
|
||||
rw_fatal (!nio.fail (), __FILE__, __LINE__,
|
||||
"money_put<wchar_t>::put(...) "
|
||||
"failed for locale(%#s)", data.locale_name_);
|
||||
|
||||
// read back as string, again for threads
|
||||
wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
wg.get (std::istreambuf_iterator<wchar_t>(&wsb),
|
||||
std::istreambuf_iterator<wchar_t>(),
|
||||
data.intl_, wio, state, data.wcs_digits_);
|
||||
|
||||
if (state & std::ios_base::failbit)
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::money_get<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::money_get<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::money_get<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::money_get<char> "
|
||||
"and std::money_get<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.money.get",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&opt_shared_locale);
|
||||
}
|
||||
870
extern/stdcxx/4.2.1/tests/localization/22.locale.money.put.cpp
vendored
Normal file
870
extern/stdcxx/4.2.1/tests/localization/22.locale.money.put.cpp
vendored
Normal file
@@ -0,0 +1,870 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.money.put.cpp - tests exercising the std::money_put facet
|
||||
*
|
||||
* $Id: 22.locale.money.put.cpp 651095 2008-04-23 22:50:27Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2001-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <cstdio> // for sprintf()
|
||||
|
||||
#include <cmdopt.h> // for rw_enabled()
|
||||
#include <driver.h> // for rw_assert(), rw_test(), ...
|
||||
#include <valcmp.h> // for rw_strncmp()
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// set to non-zero value when grouping shouldn't be exercised
|
||||
static int no_grouping;
|
||||
|
||||
// set to non-zero value when the basic_string overloads
|
||||
// of moneY-put::put() shouldn't be exercised
|
||||
static int no_basic_string;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT, bool Intl>
|
||||
struct Punct: std::moneypunct<charT, Intl>
|
||||
{
|
||||
typedef typename std::moneypunct<charT>::char_type char_type;
|
||||
typedef typename std::moneypunct<charT>::string_type string_type;
|
||||
|
||||
static char_type decimal_point_;
|
||||
static char_type thousands_sep_;
|
||||
static const char *grouping_;
|
||||
static const char_type *curr_symbol_;
|
||||
static const char_type *positive_sign_;
|
||||
static const char_type *negative_sign_;
|
||||
static std::money_base::pattern pos_format_;
|
||||
static std::money_base::pattern neg_format_;
|
||||
static int frac_digits_;
|
||||
|
||||
static int n_thousands_sep_; // number of calls to do_thousands_sep()
|
||||
|
||||
Punct (): std::moneypunct<charT>(1) { }
|
||||
|
||||
char_type do_decimal_point () const {
|
||||
return decimal_point_;
|
||||
}
|
||||
|
||||
int do_frac_digits () const {
|
||||
return frac_digits_;
|
||||
}
|
||||
|
||||
virtual string_type do_curr_symbol () const {
|
||||
return curr_symbol_ ? curr_symbol_ : string_type ();
|
||||
}
|
||||
|
||||
virtual std::string do_grouping () const {
|
||||
return grouping_;
|
||||
}
|
||||
|
||||
virtual char_type do_thousands_sep () const {
|
||||
++n_thousands_sep_;
|
||||
return thousands_sep_;
|
||||
}
|
||||
|
||||
virtual string_type do_positive_sign () const {
|
||||
return positive_sign_ ? positive_sign_ : string_type ();
|
||||
}
|
||||
|
||||
virtual string_type do_negative_sign () const {
|
||||
return negative_sign_ ? negative_sign_ : string_type ();
|
||||
}
|
||||
|
||||
virtual std::money_base::pattern do_pos_format () const {
|
||||
return pos_format_;
|
||||
}
|
||||
|
||||
virtual std::money_base::pattern do_neg_format () const {
|
||||
return neg_format_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT, bool Intl>
|
||||
const char*
|
||||
Punct<charT, Intl>::grouping_ = "";
|
||||
|
||||
template <class charT, bool Intl>
|
||||
typename Punct<charT, Intl>::char_type
|
||||
Punct<charT, Intl>::decimal_point_ = ':';
|
||||
|
||||
template <class charT, bool Intl>
|
||||
typename Punct<charT, Intl>::char_type
|
||||
Punct<charT, Intl>::thousands_sep_ = ';';
|
||||
|
||||
template <class charT, bool Intl>
|
||||
const typename Punct<charT, Intl>::char_type*
|
||||
Punct<charT, Intl>::curr_symbol_;
|
||||
|
||||
template <class charT, bool Intl>
|
||||
const typename Punct<charT, Intl>::char_type*
|
||||
Punct<charT, Intl>::positive_sign_;
|
||||
|
||||
template <class charT, bool Intl>
|
||||
const typename Punct<charT, Intl>::char_type*
|
||||
Punct<charT, Intl>::negative_sign_;
|
||||
|
||||
template <class charT, bool Intl>
|
||||
std::money_base::pattern
|
||||
Punct<charT, Intl>::pos_format_ = { {
|
||||
std::money_base::symbol,
|
||||
std::money_base::sign,
|
||||
std::money_base::none,
|
||||
std::money_base::value
|
||||
} };
|
||||
|
||||
template <class charT, bool Intl>
|
||||
std::money_base::pattern
|
||||
Punct<charT, Intl>::neg_format_ = { {
|
||||
std::money_base::symbol,
|
||||
std::money_base::sign,
|
||||
std::money_base::none,
|
||||
std::money_base::value
|
||||
} };
|
||||
|
||||
template <class charT, bool Intl>
|
||||
int
|
||||
Punct<charT, Intl>::n_thousands_sep_;
|
||||
|
||||
template <class charT, bool Intl>
|
||||
int
|
||||
Punct<charT, Intl>::frac_digits_;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
struct Ios: std::basic_ios<charT>
|
||||
{
|
||||
Ios () { this->init (0); }
|
||||
};
|
||||
|
||||
template <class charT>
|
||||
struct MoneyPut: std::money_put<charT, charT*>
|
||||
{
|
||||
// default ctor defined in order to make it possible
|
||||
// to define const objects of the type w/o explictly
|
||||
// initializing them
|
||||
typedef std::money_put<charT, charT*> Base;
|
||||
MoneyPut (): Base () { /* no-op */ }
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
bool test_neg_zero;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
std::money_base::pattern
|
||||
set_pattern (const char *format)
|
||||
{
|
||||
std::money_base::pattern pat;
|
||||
|
||||
for (unsigned i = 0; i != sizeof pat.field / sizeof *pat.field; ++i) {
|
||||
switch (format [i]) {
|
||||
case '\0': case '@': pat.field [i] = std::money_base::none; break;
|
||||
case '\1': case ' ': pat.field [i] = std::money_base::space; break;
|
||||
case '\2': case '$': pat.field [i] = std::money_base::symbol; break;
|
||||
case '\3': case '-': pat.field [i] = std::money_base::sign; break;
|
||||
case '\4': case '1': pat.field [i] = std::money_base::value; break;
|
||||
default:
|
||||
_RWSTD_ASSERT (!!"bad format specifier");
|
||||
}
|
||||
}
|
||||
|
||||
return pat;
|
||||
}
|
||||
|
||||
|
||||
template <class charT>
|
||||
int type_test (int lineno,
|
||||
charT /* unused */,
|
||||
long double val /* value to format */,
|
||||
const char *str /* expected result */,
|
||||
char fill = ' ',
|
||||
int flags = 0,
|
||||
int frac_digits = 0,
|
||||
int width = 0,
|
||||
const char *format = 0 /* pattern or printf() format */,
|
||||
const char *grouping = 0)
|
||||
{
|
||||
if (!rw_enabled (lineno)) {
|
||||
rw_note (0, __FILE__, __LINE__, "test on line %d disabled", lineno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const cname = 1 < sizeof (charT) ? "wchar_t" : "char";
|
||||
|
||||
static int i = 0; // assertion number per specialization of type_test()
|
||||
|
||||
if (!i) {
|
||||
rw_info (0, 0, 0, "std::money_put<%s>::put(ostreambuf_iterator"
|
||||
"<%s>, bool, ios_base, %s, long double)",
|
||||
cname, cname, cname);
|
||||
|
||||
rw_info (0, 0, 0, "std::money_put<%s>::put(ostreambuf_iterator"
|
||||
"<%s>, bool, ios_base, %s, "
|
||||
"const basic_string<%s>&))",
|
||||
cname, cname, cname, cname);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise put (..., long double) overload
|
||||
|
||||
int nfail = 0; // number of failed assertions
|
||||
|
||||
// unless 0, or unless it starts with '%', the `format' argument
|
||||
// is treated as a money_base::pattern string; otherwise the
|
||||
// default pattern is used
|
||||
|
||||
// default format as in locale ("C")
|
||||
const char *fmt_pat = !format || *format == '%' ? "\2\3\4\0" : format;
|
||||
|
||||
if (!grouping) {
|
||||
// default grouping as in locale ("C")
|
||||
grouping = "";
|
||||
}
|
||||
|
||||
const Punct<charT, false> pun;
|
||||
|
||||
// take care to initialize Punct static data before installing
|
||||
// the facet in case locale or the base facet calls the overridden
|
||||
// virtuals early to cache the results
|
||||
pun.grouping_ = grouping;
|
||||
pun.frac_digits_ = frac_digits;
|
||||
|
||||
if (val < 0.0) {
|
||||
pun.neg_format_ = set_pattern (fmt_pat);
|
||||
pun.pos_format_ = std::money_base::pattern ();
|
||||
}
|
||||
else if (val > 0.0) {
|
||||
pun.neg_format_ = std::money_base::pattern ();
|
||||
pun.pos_format_ = set_pattern (fmt_pat);
|
||||
}
|
||||
else {
|
||||
// 0.0 and -0.0
|
||||
pun.neg_format_ = set_pattern (fmt_pat);
|
||||
pun.pos_format_ = pun.neg_format_;
|
||||
}
|
||||
|
||||
// ios-derived object to pass to the facet
|
||||
Ios<charT> ios;
|
||||
|
||||
// money_put-derived object
|
||||
const MoneyPut<charT> mp;
|
||||
|
||||
// install the moneypunct facet in a locale and imbue the latter
|
||||
// in the ios-derived object used by money_put
|
||||
std::locale loc (ios.getloc (), (const std::moneypunct<charT>*)&pun);
|
||||
ios.imbue (loc);
|
||||
|
||||
// set the formatting flags and the width
|
||||
ios.flags (std::ios_base::fmtflags (flags));
|
||||
ios.width (std::streamsize (width));
|
||||
|
||||
bool success;
|
||||
|
||||
charT buf [256] = { 0 };
|
||||
|
||||
if (rw_enabled ("long double")) {
|
||||
|
||||
// exercise 22.2.6.2.1, long double overload
|
||||
*mp.put (buf, false, ios, charT (fill), val) = charT ();
|
||||
|
||||
rw_assert (0 == ios.width (), __FILE__, lineno,
|
||||
"money_put<%s>::put (%#p, false, const ios_base&, "
|
||||
"%{#c}, %LfL) reset width from %d",
|
||||
cname, buf, fill, val, width);
|
||||
|
||||
success = 0 == rw_strncmp (buf, str);
|
||||
|
||||
if (!success)
|
||||
++nfail;
|
||||
|
||||
rw_assert (success, __FILE__, lineno,
|
||||
"money_put<%s>::put (%#p, false, "
|
||||
"const ios_base&, %{#c}, %LfL) == %{#s} got %{#s}; "
|
||||
"flags = %{If}, grouping = %{#s}",
|
||||
cname, buf,
|
||||
fill, val, str, buf,
|
||||
flags, grouping);
|
||||
}
|
||||
else {
|
||||
static int msg_issued;
|
||||
|
||||
rw_note (msg_issued++, __FILE__, 0, "long double test disabled");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// exercise put (..., const basic_string&) overload
|
||||
|
||||
if (frac_digits < 0) {
|
||||
// do not perform string test(s) for negative values of frac_digits
|
||||
// (extension implemented only for the long double overload of put())
|
||||
++i;
|
||||
return nfail;
|
||||
}
|
||||
|
||||
if (no_basic_string) {
|
||||
rw_note (0, __FILE__, __LINE__,
|
||||
"basic_string<%s> test on line %d disabled", lineno, cname);
|
||||
return nfail;
|
||||
}
|
||||
|
||||
// zero out buffer
|
||||
std::char_traits<charT>::assign (buf, sizeof buf / sizeof *buf, charT ());
|
||||
|
||||
// if the format string starts with a '%',
|
||||
// use it to format the floating point value
|
||||
if (!format || *format != '%')
|
||||
format = "%.0" _RWSTD_LDBL_PRINTF_PREFIX "f";
|
||||
|
||||
char valbuf [256] = "";
|
||||
const int valbuflen = std::sprintf (valbuf, format, val);
|
||||
|
||||
RW_ASSERT (0 < valbuflen && valbuflen < int (sizeof valbuf));
|
||||
|
||||
typedef std::char_traits<charT> Traits;
|
||||
typedef std::allocator<charT> Allocator;
|
||||
|
||||
const std::basic_string<charT, Traits, Allocator>
|
||||
valstr (valbuf, valbuf + valbuflen);
|
||||
|
||||
// set width (reset by a previous call)
|
||||
ios.width (std::streamsize (width));
|
||||
|
||||
// exercise 22.2.6.2.1, basic_string overload
|
||||
*mp.put (buf, false, ios, charT (fill), valstr) = charT ();
|
||||
|
||||
success = 0 == rw_strncmp (buf, str);
|
||||
|
||||
if (!success)
|
||||
++nfail;
|
||||
|
||||
rw_assert (success, __FILE__, lineno,
|
||||
"money_put<%s>::put (%#p, false, "
|
||||
"const ios_base&, %{#S}) == %{#s} got %{#s}; "
|
||||
"flags = %{If}, grouping = %{#s}",
|
||||
cname, fill, &valstr, buf, str,
|
||||
flags, grouping);
|
||||
|
||||
++i;
|
||||
|
||||
return nfail;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// for convenience
|
||||
#define Boolalpha std::ios_base::boolalpha
|
||||
#define Dec std::ios_base::dec
|
||||
#define Fixed std::ios_base::fixed
|
||||
#define Hex std::ios_base::hex
|
||||
#define Internal std::ios_base::internal
|
||||
#define Left std::ios_base::left
|
||||
#define Oct std::ios_base::oct
|
||||
#define Right std::ios_base::right
|
||||
#define Scientific std::ios_base::scientific
|
||||
#define Showbase std::ios_base::showbase
|
||||
#define Showpoint std::ios_base::showpoint
|
||||
#define Showpos std::ios_base::showpos
|
||||
#define Skipws std::ios_base::skipws
|
||||
#define Unitbuf std::ios_base::unitbuf
|
||||
#define Uppercase std::ios_base::uppercase
|
||||
#define Bin std::ios_base::bin
|
||||
#define Adjustfield std::ios_base::adjustfield
|
||||
#define Basefield std::ios_base::basefield
|
||||
#define Floatfield std::ios_base::floatfield
|
||||
#define Nolock std::ios_base::nolock
|
||||
#define Nolockbuf std::ios_base::nolockbuf
|
||||
|
||||
#define Eofbit std::ios_base::eofbit
|
||||
#define Failbit std::ios_base::failbit
|
||||
#define Goodbit std::ios_base::goodbit
|
||||
|
||||
|
||||
template <class charT>
|
||||
void ldbl_test (charT)
|
||||
{
|
||||
static const charT curr_symbol1 [8] = { '$', '\0' };
|
||||
Punct<charT, false>::curr_symbol_ = curr_symbol1;
|
||||
|
||||
Punct<charT, false>::decimal_point_ = ':';
|
||||
Punct<charT, false>::thousands_sep_ = ';';
|
||||
|
||||
static const charT signs1[][4] = {
|
||||
// negative positive
|
||||
{ '~', '\0' }, { '\0', },
|
||||
};
|
||||
|
||||
Punct<charT, false>::negative_sign_ = signs1 [0];
|
||||
Punct<charT, false>::positive_sign_ = signs1 [1];
|
||||
|
||||
int ntried = 0;
|
||||
int nfailed = 0;
|
||||
|
||||
#define T __LINE__, charT ()
|
||||
#define TEST ++ntried, nfailed += type_test
|
||||
|
||||
// enum part { none, space, symbol, sign, value };
|
||||
|
||||
// no symbol, empty sign, default format
|
||||
TEST (T, 0., "0", ' ');
|
||||
TEST (T, 1., "1", ' ');
|
||||
TEST (T, 12., "12", ' ');
|
||||
TEST (T, 123., "123", ' ');
|
||||
TEST (T, 1234., "1234", ' ');
|
||||
TEST (T, 12345., "12345", ' ');
|
||||
TEST (T, 123456., "123456", ' ');
|
||||
TEST (T, 1234567., "1234567", ' ');
|
||||
TEST (T, 12345678., "12345678", ' ');
|
||||
TEST (T, 123456789., "123456789", ' ');
|
||||
|
||||
TEST (T, 12345678.9, "12345679", ' ');
|
||||
TEST (T, 1234567.89, "1234568", ' ');
|
||||
TEST (T, 123456.789, "123457", ' ');
|
||||
TEST (T, 12345.6789, "12346", ' ');
|
||||
TEST (T, 1234.56789, "1235", ' ');
|
||||
TEST (T, 123.456789, "123", ' ');
|
||||
TEST (T, 12.3456789, "12", ' ');
|
||||
TEST (T, 1.23456789, "1", ' ');
|
||||
TEST (T, .123456789, "0", ' ');
|
||||
|
||||
// exercise correct handling of frac_digits
|
||||
TEST (T, 9876543210., "987654321:0", ' ', 0, 1);
|
||||
TEST (T, 876543210., "8765432:10", ' ', 0, 2);
|
||||
TEST (T, 76543210., "76543:210", ' ', 0, 3);
|
||||
TEST (T, 6543210., "654:3210", ' ', 0, 4);
|
||||
TEST (T, 543210., "5:43210", ' ', 0, 5);
|
||||
TEST (T, 43210., "0:043210", ' ', 0, 6);
|
||||
TEST (T, 3210., "0:0003210", ' ', 0, 7);
|
||||
TEST (T, 210., "0:00000210", ' ', 0, 8);
|
||||
TEST (T, 10., "0:000000010", ' ', 0, 9);
|
||||
TEST (T, 1., "0:000000001", ' ', 0, 9);
|
||||
TEST (T, 0., "0:000000000", ' ', 0, 9);
|
||||
TEST (T, 200., "0:000000200", ' ', 0, 9);
|
||||
TEST (T, 3000., "0:000003000", ' ', 0, 9);
|
||||
TEST (T, 40000., "0:000040000", ' ', 0, 9);
|
||||
TEST (T, 500000., "0:000500000", ' ', 0, 9);
|
||||
TEST (T, 6000000., "0:006000000", ' ', 0, 9);
|
||||
TEST (T, 70000000., "0:070000000", ' ', 0, 9);
|
||||
TEST (T, 800000000., "0:800000000", ' ', 0, 9);
|
||||
TEST (T, -900000000., "~0:900000000", ' ', 0, 9);
|
||||
TEST (T, -80000000., "~0:080000000", ' ', 0, 9);
|
||||
TEST (T, -7000000., "~0:007000000", ' ', 0, 9);
|
||||
TEST (T, -600000., "~0:000600000", ' ', 0, 9);
|
||||
TEST (T, -50000., "~0:000050000", ' ', 0, 9);
|
||||
TEST (T, -4000., "~0:000004000", ' ', 0, 9);
|
||||
TEST (T, -300., "~0:000000300", ' ', 0, 9);
|
||||
TEST (T, -20., "~0:000000020", ' ', 0, 9);
|
||||
TEST (T, -1., "~0:000000001", ' ', 0, 9);
|
||||
|
||||
if (test_neg_zero)
|
||||
TEST (T, -0., "~0:000000000", ' ', 0, 9);
|
||||
|
||||
// extension: fixed and negative frac_digits
|
||||
TEST (T, 1.0, "1:0", ' ', Fixed, -1);
|
||||
TEST (T, 2.0, "2:00", ' ', Fixed, -2);
|
||||
TEST (T, 3.0, "3:000", ' ', Fixed, -3);
|
||||
TEST (T, 4.1, "4:1000", ' ', Fixed, -4);
|
||||
TEST (T, 52.34, "52:34000", ' ', Fixed, -5);
|
||||
TEST (T, 634.56789, "634:5679", ' ', Fixed, -4);
|
||||
|
||||
|
||||
// exhaustively exercise valid permutations of format patterns
|
||||
// (`none' allowed in all but the first position by 22.2.6.3, p1)
|
||||
TEST (T, 12, "12", '\0', 0, 0, 0, "\3\0\4\2", "");
|
||||
TEST (T, 123, "123", '\0', 0, 0, 0, "\3\0\2\4", "");
|
||||
TEST (T, 1234, "1234", '\0', 0, 0, 0, "\3\2\4\0", "");
|
||||
TEST (T, 2345, "2345", '\0', 0, 0, 0, "\3\4\2\0", "");
|
||||
TEST (T, 3456, "3456", '\0', 0, 0, 0, "\3\4\0\2", "");
|
||||
TEST (T, 4567, "4567", '\0', 0, 0, 0, "\4\0\2\3", "");
|
||||
TEST (T, 5678, "5678", '\0', 0, 0, 0, "\4\2\0\3", "");
|
||||
TEST (T, 6789, "6789", '\0', 0, 0, 0, "\4\2\3\0", "");
|
||||
TEST (T, 7890, "7890", '\0', 0, 0, 0, "\4\0\3\2", "");
|
||||
TEST (T, 8901, "8901", '\0', 0, 0, 0, "\2\4\0\3", "");
|
||||
TEST (T, 9012, "9012", '\0', 0, 0, 0, "\2\0\4\3", "");
|
||||
TEST (T, 123, "123", '\0', 0, 0, 0, "\2\0\3\4", "");
|
||||
|
||||
// format using `space' in valid positions (all but
|
||||
// the first and last as specified by 22.2.6.3, p1)
|
||||
// the actual space character (not the fill char)
|
||||
// is required
|
||||
TEST (T, 9, " 9", '*', 0, 0, 0, "\3\1\4\2", "");
|
||||
TEST (T, 98, " 98", '*', 0, 0, 0, "\3\1\2\4", "");
|
||||
TEST (T, 987, "987 ", '*', 0, 0, 0, "\3\4\1\2", "");
|
||||
TEST (T, 876, "876 ", '*', 0, 0, 0, "\4\1\2\3", "");
|
||||
TEST (T, 765, "765 ", '*', 0, 0, 0, "\4\2\1\3", "");
|
||||
TEST (T, 654, "654 ", '*', 0, 0, 0, "\4\1\3\2", "");
|
||||
TEST (T, 543, "543 ", '*', 0, 0, 0, "\2\4\1\3", "");
|
||||
TEST (T, 432, " 432", '*', 0, 0, 0, "\2\1\4\3", "");
|
||||
TEST (T, 321, " 321", '*', 0, 0, 0, "\2\1\3\4", "");
|
||||
|
||||
TEST (T, 0, "$0", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 1, "$1", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 12, "$12", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 123, "$123", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 1234, "$1234", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 12345, "$12345", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 123456, "$123456", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 1234567, "$1234567", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
TEST (T, 12345678, "$12345678", '\0', Showbase, 0, 0, "\2\3\4\0", "");
|
||||
|
||||
TEST (T, 0, "$0", '\0', Showbase, 0, 0, 0, "\2");
|
||||
TEST (T, 1, "$1", '\0', Showbase, 0, 0, 0, "\2\2");
|
||||
TEST (T, 12, "$12", '\0', Showbase, 0, 0, 0, "\2");
|
||||
TEST (T, 123, "$1;23", '\0', Showbase, 0, 0, 0, "\2\2");
|
||||
TEST (T, 1234, "$12;34", '\0', Showbase, 0, 0, 0, "\2");
|
||||
TEST (T, 12345, "$1;23;45", '\0', Showbase, 0, 0, 0, "\2\2");
|
||||
TEST (T, 123456, "$12;34;56", '\0', Showbase, 0, 0, 0, "\2");
|
||||
TEST (T, 1234567, "$1;23;45;67", '\0', Showbase, 0, 0, 0, "\2\2");
|
||||
TEST (T, 12345678, "$12;34;56;78", '\0', Showbase, 0, 0, 0, "\2");
|
||||
TEST (T, 123456789, "$1;23;45;67;89", '\0', Showbase, 0, 0, 0, "\2\2");
|
||||
|
||||
if (test_neg_zero)
|
||||
TEST (T, -0.0, "$~0", '\0', Showbase, 0, 0, 0, "\3\3");
|
||||
|
||||
TEST (T, -1, "$~1", '\0', Showbase, 0, 0, 0, "\3");
|
||||
TEST (T, -12, "$~12", '\0', Showbase, 0, 0, 0, "\3\3");
|
||||
TEST (T, -123, "$~123", '\0', Showbase, 0, 0, 0, "\3");
|
||||
TEST (T, -1234, "$~1;234", '\0', Showbase, 0, 0, 0, "\3\3");
|
||||
TEST (T, -12345, "$~12;345", '\0', Showbase, 0, 0, 0, "\3");
|
||||
TEST (T, -123456, "$~123;456", '\0', Showbase, 0, 0, 0, "\3\3");
|
||||
TEST (T, -1234567, "$~1;234;567", '\0', Showbase, 0, 0, 0, "\3");
|
||||
TEST (T, -12345678, "$~12;345;678", '\0', Showbase, 0, 0, 0, "\3\3");
|
||||
TEST (T, -123456789, "$~123;456;789", '\0', Showbase, 0, 0, 0, "\3");
|
||||
|
||||
// for convenience
|
||||
const char *f = "\3\2\4\0"; // { sign, symbol, value, none }
|
||||
|
||||
TEST (T, -321, "~$32;1", '\0', Showbase, 0, 0, f, "\1\2");
|
||||
TEST (T, -4322, "~$432;2", '\0', Showbase, 0, 0, f, "\1\3");
|
||||
TEST (T, -54323, "~$5;4;3;2;3", '\0', Showbase, 0, 0, f, "\1\1");
|
||||
TEST (T, -654324, "~$6;5;4;3;2;4", '\0', Showbase, 0, 0, f, "\1\1");
|
||||
TEST (T, -7654325, "~$765;432;5", '\0', Showbase, 0, 0, f, "\1\3");
|
||||
TEST (T, -87654326, "~$8;7;6;5;4;3;26", '\0', Showbase, 0, 0, f, "\2\1");
|
||||
TEST (T, -987654327, "~$98;76;54;32;7", '\0', Showbase, 0, 0, f, "\1\2");
|
||||
|
||||
static const charT curr_symbol2 [8] = { 'X', 'Y', '\0' };
|
||||
Punct<charT, false>::curr_symbol_ = curr_symbol2;
|
||||
|
||||
static const charT signs2[][8] = {
|
||||
// negative positive
|
||||
{ '(', ')', '\0' }, { '{', '}', '\0' }
|
||||
};
|
||||
|
||||
Punct<charT, false>::negative_sign_ = signs2 [0];
|
||||
Punct<charT, false>::positive_sign_ = signs2 [1];
|
||||
Punct<charT, false>::thousands_sep_ = '.';
|
||||
Punct<charT, false>::decimal_point_ = '.';
|
||||
|
||||
f = "\3\4\1\2"; // { sign, value, space, symbol }
|
||||
|
||||
TEST (T, -1357911, "(1.3.5.7.9.1.1 XY)", '*', Showbase, 0, 0, f, "\1");
|
||||
TEST (T, -2468012, "(2.46.80.12 XY)", '-', Showbase, 0, 0, f, "\2");
|
||||
TEST (T, -3692513, "(3.692.513 XY)", ' ', Showbase, 0, 0, f, "\3");
|
||||
TEST (T, -9999914, "(999.9914 XY)", '@', Showbase, 0, 0, f, "\4");
|
||||
TEST (T, -1000015, "(10.00015 XY)", '#', Showbase, 0, 0, f, "\5");
|
||||
TEST (T, -16, "(16 XY)", ')', Showbase, 0, 0, f, "\6");
|
||||
|
||||
TEST (T, +1357917, "{1.3.5.7.9.1.7 XY}", ',', Showbase, 0, 0, f, "\1");
|
||||
TEST (T, +2468018, "{2.46.80.18 XY}", '+', Showbase, 0, 0, f, "\2");
|
||||
TEST (T, +3692519, "{3.692.519 XY}", '0', Showbase, 0, 0, f, "\3");
|
||||
TEST (T, +9999920, "{999.9920 XY}", '1', Showbase, 0, 0, f, "\4");
|
||||
TEST (T, +1000021, "{10.00021 XY}", '\0', Showbase, 0, 0, f, "\5");
|
||||
TEST (T, +22, "{22 XY}", '{', Showbase, 0, 0, f, "\6");
|
||||
TEST (T, +123, "{123 }", '_', 0, 0, 0, f, "\6");
|
||||
TEST (T, -224, "(224 )", '_', 0, 0, 0, f, "\7");
|
||||
|
||||
TEST (T, +325, "{ XY325}", ' ', Showbase, 0, 0, "\3\1\2\4", "\xa");
|
||||
TEST (T, -426, "( XY426)", ' ', Showbase, 0, 0, "\3\1\2\4", "\xb");
|
||||
TEST (T, +527, "{XY 527}", ' ', Showbase, 0, 0, "\3\2\1\4", "\xc");
|
||||
TEST (T, -628, "(XY 628)", ' ', Showbase, 0, 0, "\3\2\1\4", "\xd");
|
||||
TEST (T, +729, "{XY729}", ' ', Showbase, 0, 0, "\3\2\0\4", "\xe");
|
||||
TEST (T, -830, "(XY830)", ' ', Showbase, 0, 0, "\3\2\0\4", "\xf");
|
||||
TEST (T, +931, "{XY931}", ' ', Showbase, 0, 0, "\3\0\2\4", "\x10");
|
||||
TEST (T, -1032, "(XY1032)", ' ', Showbase, 0, 0, "\3\0\2\4");
|
||||
TEST (T, +1133, "1133{XY}", ' ', Showbase, 0, 0, "\4\3\2\0");
|
||||
TEST (T, -1234, "1234XY()", ' ', Showbase, 0, 0, "\4\2\3\0");
|
||||
TEST (T, +1335, "1335XY{}", ' ', Showbase, 0, 0, "\4\2\0\3");
|
||||
TEST (T, -1436, "1436XY ()", ' ', Showbase, 0, 0, "\4\2\1\3");
|
||||
TEST (T, +1537, "1537XY{}", ' ', Showbase, 0, 0, "\4\0\2\3");
|
||||
TEST (T, -1638, "1638 XY()", ' ', Showbase, 0, 0, "\4\1\2\3");
|
||||
TEST (T, +1739, "XY1739{}", ' ', Showbase, 0, 0, "\2\4\0\3");
|
||||
TEST (T, -1840, "XY1840 ()", ' ', Showbase, 0, 0, "\2\4\1\3");
|
||||
TEST (T, +1941, "XY1941{}", ' ', Showbase, 0, 0, "\2\0\4\3");
|
||||
TEST (T, -2042, "XY 2042()", ' ', Showbase, 0, 0, "\2\1\4\3");
|
||||
TEST (T, +2143, "XY{2143}", ' ', Showbase, 0, 0, "\2\3\4\0");
|
||||
TEST (T, -2244, "XY(2244)", ' ', Showbase, 0, 0, "\2\3\0\4");
|
||||
TEST (T, +2345, "XY{ 2345}", ' ', Showbase, 0, 0, "\2\3\1\4");
|
||||
|
||||
// 22.2.6.2, p2:
|
||||
// ...copies of `fill' are inserted as necessary to pad to the
|
||||
// specified width. For the value `af' equal to (str.flags()
|
||||
// & str.adjustfield), if (af == str.internal) is true, the fill
|
||||
// characters are placed where `none' or `space' appears in the
|
||||
// formatting pattern; otherwise if (af == str.left) is true, they
|
||||
// are placed after the other characters; otherwise, they are
|
||||
// placed before the other characters.
|
||||
|
||||
TEST (T, -2446, "___XY( 2446)", '_', Showbase, 0, 12, "\2\3\1\4");
|
||||
TEST (T, +2547, "____XY{2547}", '_', Showbase, 0, 12, "\2\3\0\4");
|
||||
|
||||
TEST (T, -2648, "___XY( 2648)", '_', Showbase | Right, 0, 12, "\2\3\1\4");
|
||||
TEST (T, +2749, "____XY{2749}", '_', Showbase | Right, 0, 12, "\2\3\0\4");
|
||||
|
||||
TEST (T, -2850, "XY( 2850)___", '_', Showbase | Left, 0, 12, "\2\3\1\4");
|
||||
TEST (T, +2951, "XY{2951}____", '_', Showbase | Left, 0, 12, "\2\3\0\4");
|
||||
|
||||
TEST (T, -3052, "___XY( 3052)", '_',
|
||||
Showbase | Left | Right, 0, 12, "\2\3\1\4");
|
||||
|
||||
TEST (T, +3153, "____XY{3153}", '_',
|
||||
Showbase | Left | Right, 0, 12, "\2\3\0\4");
|
||||
|
||||
TEST (T, -3254, "___XY( 3254)", '_',
|
||||
Showbase | Left | Right | Internal, 0, 12, "\2\3\1\4");
|
||||
|
||||
TEST (T, +3355, "____XY{3355}", '_',
|
||||
Showbase | Left | Right | Internal, 0, 12, "\2\3\0\4");
|
||||
|
||||
TEST (T, -3456, "XY( ___3456)", '_',
|
||||
Showbase | Internal, 0, 12, "\2\3\1\4");
|
||||
|
||||
TEST (T, +3557, "XY{____3557}", '_',
|
||||
Showbase | Internal, 0, 12, "\2\3\0\4");
|
||||
|
||||
TEST (T, -3658, "XY____(3658)", '_',
|
||||
Showbase | Internal, 0, 12, "\2\0\3\4");
|
||||
|
||||
TEST (T, +3759, "XY{3759____}", '_',
|
||||
Showbase | Internal, 0, 12, "\2\3\4\0");
|
||||
|
||||
TEST (T, 3759, "XY{37.59}", '_',
|
||||
Showbase | Internal, 0, 8, "\2\3\4\0", "\2");
|
||||
|
||||
TEST (T, 3760, "XY{ 37.60}", '_',
|
||||
Showbase | Internal, 0, 8, "\2\3\1\4", "\2");
|
||||
|
||||
TEST (T, 12345678900000000000.0, "XY{ ........1.23.45678.9000.00.000.0.00}",
|
||||
'.', Showbase | Internal, 0, 40, "\2\3\1\4", "\2\1\3\2\4\5\2");
|
||||
|
||||
TEST (T, 1234567890000000000.0, "{ ...........1234.56789.0000.000.00.0XY}",
|
||||
'.', Showbase | Internal, 0, 40, "\3\1\4\2", "\1\2\3\4\5\6");
|
||||
|
||||
// exercise justification with non-zero frac_digits
|
||||
TEST (T, 1, "_____{0.1}", '_', 0, 1, 10, "-@1$");
|
||||
TEST (T, 12, "_____{1.2}", '_', 0, 1, 10, "-@1$");
|
||||
TEST (T, 123, "____{1.23}", '_', 0, 2, 10, "-@1$");
|
||||
TEST (T, 1234, "_{12.34XY}", '_', Showbase, 2, 10, "-@1$");
|
||||
TEST (T, 1235, "_{ 12.35XY}", '_', Showbase, 2, 11, "- 1$");
|
||||
|
||||
TEST (T, 2, "******{0.2}", '*', Right, 1, 11, "-@1$");
|
||||
TEST (T, 23, "******{2.3}", '*', Right, 1, 11, "-@1$");
|
||||
TEST (T, 234, "*****{2.34}", '*', Right, 2, 11, "-@1$");
|
||||
TEST (T, 2345, "**{23.45XY}", '*', Right | Showbase, 2, 11, "-@1$");
|
||||
TEST (T, 2346, "**{ 23.46XY}", '*', Right | Showbase, 2, 12, "- 1$");
|
||||
|
||||
TEST (T, 3, "{0.3}#######", '#', Left, 1, 12, "-@1$");
|
||||
TEST (T, 34, "{3.4}#######", '#', Left, 1, 12, "-@1$");
|
||||
TEST (T, 345, "{3.45}######", '#', Left, 2, 12, "-@1$");
|
||||
TEST (T, 3456, "{34.56XY}###", '#', Left | Showbase, 2, 12, "-@1$");
|
||||
TEST (T, 3457, "{ 34.57XY}###", '#', Left | Showbase, 2, 13, "- 1$");
|
||||
|
||||
TEST (T, 4, "{=====0.4}", '=', Internal, 1, 10, "-@1$");
|
||||
TEST (T, 45, "{=====4.5}", '=', Internal, 1, 10, "-@1$");
|
||||
TEST (T, 456, "{====4.56}", '=', Internal, 2, 10, "-@1$");
|
||||
TEST (T, 4567, "{=45.67XY}", '=', Internal | Showbase, 2, 10, "-@1$");
|
||||
TEST (T, 4568, "{ =45.68XY}", '=', Internal | Showbase, 2, 11, "- 1$");
|
||||
|
||||
Punct<charT, false>::thousands_sep_ = ',';
|
||||
Punct<charT, false>::decimal_point_ = '.';
|
||||
|
||||
// justification with grouping
|
||||
TEST (T, 105, "====={1,0.5}", '=', 0, 1, 12, "-@1$", "\1");
|
||||
TEST (T, 1056, "===={1,05.6}", '=', 0, 1, 12, "-@1$", "\2");
|
||||
TEST (T, 10567, "==={1,05.67}", '=', 0, 2, 12, "-@1$", "\2");
|
||||
TEST (T, 105678, "=={10,56.78XY}", '=', Showbase, 2, 14, "-@1$", "\2");
|
||||
TEST (T, 105679, "={ 10,56.79XY}", '=', Showbase, 2, 14, "- 1$", "\2");
|
||||
TEST (T, 105680, "={ 1,056,80XY}", '=', Showbase, 0, 14, "- 1$", "\2\3");
|
||||
|
||||
int flags = Right | Showbase;
|
||||
TEST (T, 106, ">>>>>{1,0.6}", '>', Right, 1, 12, "-@1$", "\1");
|
||||
TEST (T, 1057, ">>>>{1,05.7}", '>', Right, 1, 12, "-@1$", "\2");
|
||||
TEST (T, 10568, ">>>{1,05.68}", '>', Right, 2, 12, "-@1$", "\2");
|
||||
TEST (T, 105679, ">>{10,56.79XY}", '>', flags, 2, 14, "-@1$", "\2");
|
||||
TEST (T, 105680, ">{ 10,56.80XY}", '>', flags, 2, 14, "- 1$", "\2");
|
||||
TEST (T, 105681, ">{ 1,056,81XY}", '>', flags, 0, 14, "- 1$", "\2\3");
|
||||
|
||||
flags = Left | Showbase;
|
||||
TEST (T, 107, "{1,0.7}<<<<<", '<', Left, 1, 12, "-@1$", "\1");
|
||||
TEST (T, 1058, "{1,05.8}<<<<", '<', Left, 1, 12, "-@1$", "\2");
|
||||
TEST (T, 10569, "{1,05.69}<<<", '<', Left, 2, 12, "-@1$", "\2");
|
||||
TEST (T, 105680, "{10,56.80XY}<<", '<', flags, 2, 14, "-@1$", "\2");
|
||||
TEST (T, 105681, "{ 10,56.81XY}<", '<', flags, 2, 14, "- 1$", "\2");
|
||||
TEST (T, 105682, "{ 1,056,82XY}<", '<', flags, 0, 14, "- 1$", "\2\3");
|
||||
|
||||
flags = Internal | Showbase;
|
||||
TEST (T, 108, "{^^^^^1,0.8}", '^', Internal, 1, 12, "-@1$", "\1");
|
||||
TEST (T, 1059, "{^^^^1,05.9}", '^', Internal, 1, 12, "-@1$", "\2");
|
||||
TEST (T, 10570, "{^^^1,05.70}", '^', Internal, 2, 12, "-@1$", "\2");
|
||||
TEST (T, 105681, "{^^10,56.81XY}", '^', flags, 2, 14, "-@1$", "\2");
|
||||
TEST (T, 105682, "{ ^10,56.82XY}", '^', flags, 2, 14, "- 1$", "\2");
|
||||
TEST (T, 105683, "{ ^1,056,83XY}", '^', flags, 0, 14, "- 1$", "\2\3");
|
||||
|
||||
flags = Left | Right | Showbase;
|
||||
TEST (T, 109, "#####{1,0.9}", '#', Left | Right, 1, 12, "-@1$", "\1");
|
||||
TEST (T, 1060, "####{1,06.0}", '#', Left | Right, 1, 12, "-@1$", "\2");
|
||||
TEST (T, 10571, "###{1,05.71}", '#', Left | Right, 2, 12, "-@1$", "\2");
|
||||
TEST (T, 105682, "##{10,56.82XY}", '#', flags, 2, 14, "-@1$", "\2");
|
||||
TEST (T, 105683, "#{ 10,56.83XY}", '#', flags, 2, 14, "- 1$", "\2");
|
||||
TEST (T, 105684, "#{ 10,56,84XY}", '#', flags, 0, 14, "- 1$", "\2");
|
||||
|
||||
|
||||
// verify that mon_put (..., const basic_string&) ignores the part
|
||||
// of the string starting with the first non-numeric character
|
||||
#undef FMT
|
||||
#define FMT(fmt) "%.0" _RWSTD_LDBL_PRINTF_PREFIX "f" fmt
|
||||
|
||||
// using default format "\2\3\4\0": {symbol, sign, value, none}
|
||||
TEST (T, 10, "{1.0}", ' ', 0, 1, -1, FMT (" "));
|
||||
TEST (T, 10, "{1.0}", ' ', 0, 1, -1, FMT ("."));
|
||||
|
||||
TEST (T, -11, "(1.1)", ' ', 0, 1, -1, FMT (" "));
|
||||
TEST (T, -11, "(1.1)", ' ', 0, 1, -1, FMT ("."));
|
||||
|
||||
TEST (T, 101, "{1.01}", ' ', 0, 2, -1, FMT (" "));
|
||||
TEST (T, 101, "{1.01}", ' ', 0, 2, -1, FMT ("."));
|
||||
|
||||
Punct<charT, false>::negative_sign_ = signs1 [0];
|
||||
Punct<charT, false>::positive_sign_ = signs1 [1];
|
||||
|
||||
TEST (T, 1012, "1,0.12", ' ', 0, 2, -1, FMT (" 0"), "\1");
|
||||
TEST (T, 1013, "1,0.13", ' ', 0, 2, -1, FMT (".1"), "\1");
|
||||
|
||||
TEST (T, -1014, "~1,01.4", ' ', 0, 1, -1, FMT ("~2"), "\2");
|
||||
TEST (T, -1015, "~1,01.5", ' ', 0, 1, -1, FMT (",3"), "\2");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
void grouping_test ()
|
||||
{
|
||||
if (!rw_enabled ("char")) {
|
||||
rw_note (0, __FILE__, __LINE__, "char test disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
rw_info (0, 0, 0, "std::money_put<%s>::put(ostreambuf_iterator"
|
||||
"<%s>, bool, ios_base, %s, long double); correct use of "
|
||||
"moneypunct<%s, false>::grouping() and thousands_sep()",
|
||||
"char", "char", "char", "char");
|
||||
|
||||
typedef Punct<char, false> PunctT;
|
||||
|
||||
// construct a "replacement" moneypunct-derived facet
|
||||
const PunctT pun;
|
||||
|
||||
// group after every digit
|
||||
PunctT::grouping_ = "\1";
|
||||
|
||||
// reset the do_thousands_sep()-call counter
|
||||
PunctT::thousands_sep_ = ';';
|
||||
PunctT::decimal_point_ = ':';
|
||||
PunctT::n_thousands_sep_ = 0;
|
||||
|
||||
// construct and initialize a basic_ios-derived object
|
||||
struct Ios: std::basic_ios<char> { Ios () { this->init (0); } } ios;
|
||||
|
||||
// construct a money_put-derived facet to exercise
|
||||
struct MoneyPut: std::money_put<char, char*> { } mp;
|
||||
|
||||
// imbue a stream object with a custom locale
|
||||
// containing the replacement punctuation facet
|
||||
std::locale l;
|
||||
std::locale loc (l, (const std::moneypunct<char>*)&pun);
|
||||
ios.imbue (loc);
|
||||
|
||||
// decimal output, no special formatting
|
||||
ios.setf (std::ios::fmtflags ());
|
||||
|
||||
char buf [40] = "";
|
||||
|
||||
*mp.put (buf, false, ios, '\0', 123456789.0L) = '\0';
|
||||
|
||||
// verify that the number was formatted correctly
|
||||
rw_assert (0 == rw_strncmp (buf, "1;2;3;4;5;6;7;8;9"), __FILE__, __LINE__,
|
||||
"money_put<char, char*>::do_put(..., 123456789.0L) "
|
||||
"== %#s, got %#s", "1;2;3;4;5;6;7;8;9", buf);
|
||||
|
||||
// verify that do_thousands_sep() was called at least once
|
||||
// (but not necessarily for each thousands separator inserted
|
||||
// into the output, since the value is allowed to be cached)
|
||||
rw_assert (0 != PunctT::n_thousands_sep_, __FILE__, __LINE__,
|
||||
"money_put<char, char*>::do_put(..., 123456789.0L) "
|
||||
"called moneypunct<char>::do_thousands_sep()");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char*[])
|
||||
{
|
||||
// check to see if we can test -0.0
|
||||
static volatile double d = -0.0;
|
||||
test_neg_zero = 1.0 / d < d;
|
||||
|
||||
if (no_grouping)
|
||||
rw_note (0, __FILE__, __LINE__, "grouping test disabled");
|
||||
else
|
||||
grouping_test ();
|
||||
|
||||
if (rw_enabled ("char"))
|
||||
ldbl_test (char ());
|
||||
else
|
||||
rw_note (0, __FILE__, __LINE__, "char test disabled");
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (rw_enabled ("wchar_t"))
|
||||
ldbl_test (wchar_t ());
|
||||
else
|
||||
rw_note (0, __FILE__, __LINE__, "wchar_t test disabled");
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.money.put",
|
||||
0 /* no comment */, run_test,
|
||||
"|-no-grouping# |-no-basic_string#",
|
||||
&no_grouping, &no_basic_string);
|
||||
}
|
||||
484
extern/stdcxx/4.2.1/tests/localization/22.locale.money.put.mt.cpp
vendored
Normal file
484
extern/stdcxx/4.2.1/tests/localization/22.locale.money.put.mt.cpp
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.money.put.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the money_put facet
|
||||
*
|
||||
* $Id: 22.locale.money.put.mt.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 <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, money_put
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h>
|
||||
#include <valcmp.h> // for rw_strncmp ()
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int opt_nloops = 100000;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around a small locale cache on HP-UX in LP64 mode
|
||||
// (see STDCXX-812)
|
||||
int opt_nlocales = 9;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static const char n_money_vals[][20] = {
|
||||
"1", "12", "123", "1234", "12345", "123456", "1234567", "12345678",
|
||||
"-9", "-98", "-987", "-9876", "-98765", "-987654", "-9876543",
|
||||
"1.9", "-12.89", "123.789", "-1234.6789", "-12345.56789"
|
||||
};
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
static const wchar_t w_money_vals[][20] = {
|
||||
L"1", L"12", L"123", L"1234", L"12345", L"123456", L"1234567",
|
||||
L"-9", L"-98", L"-987", L"-9876", L"-98765", L"-987654", L"-9876543",
|
||||
L"1.9", L"-12.89", L"123.789", L"-1234.6789", L"-12345.56789"
|
||||
};
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
//
|
||||
struct MyMoneyData
|
||||
{
|
||||
enum { BufferSize = 16 };
|
||||
|
||||
enum PutId {
|
||||
put_ldbl,
|
||||
put_string,
|
||||
put_max
|
||||
};
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// international or domestic format flag
|
||||
bool intl_;
|
||||
|
||||
// the time struct used to generate strings below
|
||||
double money_value_;
|
||||
|
||||
// type of the data we created string from
|
||||
PutId type_;
|
||||
|
||||
// index into string array [n,w]_money_vals
|
||||
unsigned money_index_;
|
||||
|
||||
// narrow representations of money_
|
||||
char ncs_ [BufferSize];
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
// wide representations of money_
|
||||
wchar_t wcs_ [BufferSize];
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} my_money_data [MAX_THREADS];
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyIos: std::basic_ios<charT, Traits>
|
||||
{
|
||||
MyIos () {
|
||||
this->init (0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyStreambuf: std::basic_streambuf<charT, Traits>
|
||||
{
|
||||
typedef std::basic_streambuf<charT, Traits> Base;
|
||||
|
||||
MyStreambuf ()
|
||||
: Base () {
|
||||
}
|
||||
|
||||
void pubsetp (charT *pbeg, std::streamsize n) {
|
||||
this->setp (pbeg, pbeg + n);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise money_put<char>
|
||||
bool test_wchar; // exercise money_put<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
char ncs [MyMoneyData::BufferSize];
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
wchar_t wcs [MyMoneyData::BufferSize];
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
// save the name of the locale
|
||||
const MyMoneyData& data = my_money_data [i % nlocales];
|
||||
|
||||
// construct a named locale, get a reference to the money_put
|
||||
// facet from it and use it to format a random money value
|
||||
const std::locale loc =
|
||||
opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::money_put<char> &np =
|
||||
std::use_facet<std::money_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
|
||||
|
||||
switch (data.type_) {
|
||||
case MyMoneyData::put_ldbl:
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
data.intl_, nio, ' ', data.money_value_) = '\0';
|
||||
break;
|
||||
case MyMoneyData::put_string:
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
data.intl_, nio, ' ',
|
||||
n_money_vals [data.money_index_]) = '\0';
|
||||
break;
|
||||
case MyMoneyData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
RW_ASSERT (!nio.fail ());
|
||||
RW_ASSERT (!rw_strncmp (ncs, data.ncs_));
|
||||
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::money_put<wchar_t> &wp =
|
||||
std::use_facet<std::money_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
|
||||
|
||||
switch (data.type_) {
|
||||
case MyMoneyData::put_ldbl:
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
data.intl_, wio, ' ', data.money_value_) = L'\0';
|
||||
break;
|
||||
case MyMoneyData::put_string:
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
data.intl_, wio, ' ',
|
||||
w_money_vals [data.money_index_]) = L'\0';
|
||||
break;
|
||||
case MyMoneyData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
RW_ASSERT (!wio.fail ());
|
||||
RW_ASSERT (!rw_strncmp (wcs, data.wcs_));
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
// find all installed locales for which setlocale (LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
for (const char* name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the money and results for this locale
|
||||
MyMoneyData& data = my_money_data [inx];
|
||||
data.locale_name_ = name;
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
// initialize with random but valid values
|
||||
|
||||
data.money_value_ = inx;
|
||||
data.type_ = MyMoneyData::PutId (nlocales % MyMoneyData::put_max);
|
||||
data.money_index_ = inx % RW_COUNT_OF (n_money_vals);
|
||||
|
||||
// exercise domestic formats every other iteration
|
||||
// and international formats the rest
|
||||
data.intl_ = 0 == (inx & 1);
|
||||
|
||||
// exercise postive and negative values
|
||||
if (inx & 1)
|
||||
data.money_value_ *= -1.;
|
||||
|
||||
// add some random fractional digits
|
||||
if (inx & 2)
|
||||
data.money_value_ += data.money_value_ / 3.14;
|
||||
|
||||
const std::money_put<char> &np =
|
||||
std::use_facet<std::money_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
switch (data.type_) {
|
||||
case MyMoneyData::put_ldbl:
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
data.intl_, nio, ' ', data.money_value_) = '\0';
|
||||
break;
|
||||
case MyMoneyData::put_string:
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
data.intl_, nio, ' ',
|
||||
n_money_vals [data.money_index_]) = '\0';
|
||||
break;
|
||||
case MyMoneyData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
rw_assert (!nio.fail (), __FILE__, __LINE__,
|
||||
"money_put<char>::put(...) "
|
||||
"failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::money_put<wchar_t> &wp =
|
||||
std::use_facet<std::money_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
switch (data.type_) {
|
||||
case MyMoneyData::put_ldbl:
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
data.intl_, wio, L' ', data.money_value_) = '\0';
|
||||
break;
|
||||
case MyMoneyData::put_string:
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
data.intl_, wio, L' ',
|
||||
w_money_vals [data.money_index_]) = L'\0';
|
||||
break;
|
||||
case MyMoneyData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
rw_assert (!nio.fail (), __FILE__, __LINE__,
|
||||
"money_put<wchar_t>::put(...) "
|
||||
"failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::money_put<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::money_put<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::money_put<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::money_put<char> "
|
||||
"and std::money_put<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.money.put",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&opt_shared_locale);
|
||||
}
|
||||
857
extern/stdcxx/4.2.1/tests/localization/22.locale.moneypunct.cpp
vendored
Normal file
857
extern/stdcxx/4.2.1/tests/localization/22.locale.moneypunct.cpp
vendored
Normal file
@@ -0,0 +1,857 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 22.locale.moneypunct.cpp - tests for the moneypunct facet
|
||||
*
|
||||
* $Id: 22.locale.moneypunct.cpp 651095 2008-04-23 22:50:27Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 1998-2008 Rogue Wave Software, Inc.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <locale>
|
||||
|
||||
#include <cassert>
|
||||
#include <clocale> // for LC_ALL, setlocale()
|
||||
#include <cstdio> // for fprintf(), stderr
|
||||
#include <cstdlib> // for getenv()
|
||||
#include <cstring> // for memcmp(), strerror()
|
||||
|
||||
#include <driver.h> // for rw_test()
|
||||
#include <environ.h> // for rw_putenv()
|
||||
#include <rw_locale.h> // for rw_locales()
|
||||
#include <rw_printf.h> // for rw_fprintf()
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
typedef unsigned char UChar;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// does a deep copy of struct lconv
|
||||
std::lconv* lconvdup (const std::lconv *plconv)
|
||||
{
|
||||
if (!plconv)
|
||||
return 0;
|
||||
|
||||
const std::size_t
|
||||
decimal_point_sz = std::strlen (plconv->decimal_point) + 1,
|
||||
thousands_sep_sz = std::strlen (plconv->thousands_sep) + 1,
|
||||
grouping_sz = std::strlen (plconv->grouping) + 1,
|
||||
int_curr_symbol_sz = std::strlen (plconv->int_curr_symbol) + 1,
|
||||
currency_symbol_sz = std::strlen (plconv->currency_symbol) + 1,
|
||||
mon_decimal_point_sz = std::strlen (plconv->mon_decimal_point) + 1,
|
||||
mon_thousands_sep_sz = std::strlen (plconv->mon_thousands_sep) + 1,
|
||||
mon_grouping_sz = std::strlen (plconv->mon_grouping) + 1,
|
||||
positive_sign_sz = std::strlen (plconv->positive_sign) + 1,
|
||||
negative_sign_sz = std::strlen (plconv->negative_sign) + 1;
|
||||
|
||||
const std::size_t total_sz =
|
||||
decimal_point_sz
|
||||
+ thousands_sep_sz
|
||||
+ grouping_sz
|
||||
+ int_curr_symbol_sz
|
||||
+ currency_symbol_sz
|
||||
+ mon_decimal_point_sz
|
||||
+ mon_thousands_sep_sz
|
||||
+ mon_grouping_sz
|
||||
+ positive_sign_sz
|
||||
+ negative_sign_sz;
|
||||
|
||||
const std::size_t bufsize = sizeof (std::lconv) + total_sz;
|
||||
|
||||
char *pbuf = _RWSTD_STATIC_CAST (char*, operator new (bufsize));
|
||||
|
||||
std::lconv *plconv2 = _RWSTD_REINTERPRET_CAST (std::lconv*, pbuf);
|
||||
|
||||
plconv2->decimal_point = (pbuf += sizeof (std::lconv));
|
||||
std::memcpy (pbuf, plconv->decimal_point, decimal_point_sz);
|
||||
|
||||
plconv2->thousands_sep = (pbuf += decimal_point_sz);
|
||||
std::memcpy (pbuf, plconv->thousands_sep, thousands_sep_sz);
|
||||
|
||||
plconv2->grouping = (pbuf += thousands_sep_sz);
|
||||
std::memcpy (pbuf, plconv->grouping, grouping_sz);
|
||||
|
||||
plconv2->int_curr_symbol = (pbuf += grouping_sz);
|
||||
std::memcpy (pbuf, plconv->int_curr_symbol, int_curr_symbol_sz);
|
||||
|
||||
plconv2->currency_symbol = (pbuf += int_curr_symbol_sz);
|
||||
std::memcpy (pbuf, plconv->currency_symbol, currency_symbol_sz);
|
||||
|
||||
plconv2->mon_decimal_point = (pbuf += currency_symbol_sz);
|
||||
std::memcpy (pbuf, plconv->mon_decimal_point, mon_decimal_point_sz);
|
||||
|
||||
plconv2->mon_thousands_sep = (pbuf += mon_decimal_point_sz);
|
||||
std::memcpy (pbuf, plconv->mon_thousands_sep, mon_thousands_sep_sz);
|
||||
|
||||
plconv2->mon_grouping = (pbuf += mon_thousands_sep_sz);
|
||||
std::memcpy (pbuf, plconv->mon_grouping, mon_grouping_sz);
|
||||
|
||||
plconv2->positive_sign = (pbuf += mon_grouping_sz);
|
||||
std::memcpy (pbuf, plconv->positive_sign, positive_sign_sz);
|
||||
|
||||
plconv2->negative_sign = (pbuf += positive_sign_sz);
|
||||
std::memcpy (pbuf, plconv->negative_sign, negative_sign_sz);
|
||||
|
||||
plconv2->int_frac_digits = plconv->int_frac_digits;
|
||||
plconv2->frac_digits = plconv->frac_digits;
|
||||
plconv2->p_cs_precedes = plconv->p_cs_precedes;
|
||||
plconv2->p_sep_by_space = plconv->p_sep_by_space;
|
||||
plconv2->n_cs_precedes = plconv->n_cs_precedes;
|
||||
plconv2->n_sep_by_space = plconv->n_sep_by_space;
|
||||
plconv2->p_sign_posn = plconv->p_sign_posn;
|
||||
plconv2->n_sign_posn = plconv->n_sign_posn;
|
||||
|
||||
#ifndef _RWSTD_NO_LCONV_INT_FMAT
|
||||
|
||||
plconv2->int_p_cs_precedes = plconv->int_p_cs_precedes;
|
||||
plconv2->int_p_sep_by_space = plconv->int_p_sep_by_space;
|
||||
plconv2->int_n_cs_precedes = plconv->int_n_cs_precedes;
|
||||
plconv2->int_n_sep_by_space = plconv->int_n_sep_by_space;
|
||||
plconv2->int_p_sign_posn = plconv->int_p_sign_posn;
|
||||
plconv2->int_n_sign_posn = plconv->int_n_sign_posn;
|
||||
|
||||
#endif // _RWSTD_NO_LCONV_INT_FMAT
|
||||
|
||||
return plconv2;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
class Test
|
||||
{
|
||||
std::locale loc_;
|
||||
bool intl_; // international?
|
||||
const char *char_name_; // charT name ("char" or "wchar_t")
|
||||
const char *locname_;
|
||||
const char *lang_;
|
||||
const char *lc_all_;
|
||||
const char *lc_monetary_;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::moneypunct<charT, false> Punct;
|
||||
typedef std::moneypunct<charT, true> IntlPunct;
|
||||
|
||||
Test (const char *cname, bool intl)
|
||||
: loc_ (), intl_ (intl),
|
||||
char_name_ (cname),
|
||||
locname_ (0), lang_ (0), lc_all_ (0), lc_monetary_ (0) { }
|
||||
|
||||
void runTest ();
|
||||
|
||||
void check_decimal_point (charT);
|
||||
void check_thousands_sep (charT);
|
||||
void check_frac_digits (int);
|
||||
void check_grouping (const std::string&);
|
||||
|
||||
typedef std::char_traits<charT> Traits;
|
||||
typedef std::allocator<charT> Allocator;
|
||||
typedef std::basic_string<charT, Traits, Allocator> String;
|
||||
|
||||
void check_curr_symbol (const String&);
|
||||
void check_positive_sign (const String&);
|
||||
void check_negative_sign (const String&);
|
||||
|
||||
void check_format (const std::lconv&);
|
||||
void check_format (bool, std::money_base::pattern, const UChar [3]);
|
||||
|
||||
bool check_moneypunct (const char*);
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
runTest()
|
||||
{
|
||||
// create a copy of the classic C locale
|
||||
loc_ = std::locale::classic ();
|
||||
|
||||
// verify (at compile time) that _bynam facets can be used
|
||||
// to specialize use_facet() and has_facet()
|
||||
typedef std::moneypunct_byname<charT, false> MoneyPunctByname;
|
||||
typedef std::moneypunct_byname<charT, true> MoneyPunctIntlByname;
|
||||
|
||||
if (1) {
|
||||
if (_STD_HAS_FACET (MoneyPunctByname, loc_))
|
||||
_RWSTD_USE_FACET (MoneyPunctByname, loc_);
|
||||
|
||||
if (_STD_HAS_FACET (MoneyPunctIntlByname, loc_))
|
||||
_RWSTD_USE_FACET (MoneyPunctIntlByname, loc_);
|
||||
}
|
||||
|
||||
// note that values in 7.4 of C89, and 7.11, p2 of C99, respectively,
|
||||
// or '\0' and '\0' for decimal_point and thousands_sep, are specified
|
||||
// in 22.2.3.1.2, p1 and p2 of C++98 to be '.', and ',' in the C locale
|
||||
//
|
||||
check_decimal_point (charT ('.'));
|
||||
check_thousands_sep (charT (','));
|
||||
check_frac_digits (0 /* i.e., not available, or same as CHAR_MAX in C */);
|
||||
check_grouping ("");
|
||||
|
||||
const charT empty[] = { '\0' };
|
||||
check_curr_symbol (empty);
|
||||
check_positive_sign (empty);
|
||||
check_negative_sign (empty);
|
||||
|
||||
// verify 22.2.6.3.2, p7:
|
||||
// moneypunct<char>, moneypunct<wchar_t>, moneypunct<char,true>, and
|
||||
// moneypunct<wchar_t,true>, return an object of type pattern initialized
|
||||
// to { symbol, sign, none, value }
|
||||
std::money_base::pattern fmat = {
|
||||
// initializer must be properly bracketed to prevent g++ warnings
|
||||
{
|
||||
std::money_base::symbol,
|
||||
std::money_base::sign,
|
||||
std::money_base::none,
|
||||
std::money_base::value
|
||||
}
|
||||
};
|
||||
|
||||
const UChar cpat [4] = { '?', '?', '?', 0 };
|
||||
check_format (false /* negative */, fmat, cpat);
|
||||
check_format (true /* positive */, fmat, cpat);
|
||||
|
||||
// exercise the native locale (affected by the environment
|
||||
// variables LANG, LC_ALL, LC_MONETARY, etc.)
|
||||
check_moneypunct (""); // 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; s += std::strlen (s) + 1) {
|
||||
if (check_moneypunct (s))
|
||||
if ( !first_non_c
|
||||
&& std::strcmp ("C", s)
|
||||
&& std::strcmp ("POSIX", s)) {
|
||||
first_non_c = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (!first_non_c)
|
||||
return;
|
||||
|
||||
// verify that moneypunct behaves correctly when LC_ALL is set
|
||||
// to the name of the (non-C, non-POSIX) locale
|
||||
char envvar [80];
|
||||
|
||||
// make sure buffer doesn't overflow
|
||||
assert (std::strlen(first_non_c) + sizeof "LC_ALL=" <= sizeof envvar);
|
||||
|
||||
std::sprintf (envvar, "LC_ALL=%s", first_non_c);
|
||||
rw_putenv (envvar);
|
||||
check_moneypunct ("");
|
||||
|
||||
// remove LC_ALL from the environment
|
||||
rw_putenv ("LC_ALL=");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
std::string convert (const char*, const char *s, const char*)
|
||||
{
|
||||
return std::string (s);
|
||||
}
|
||||
|
||||
|
||||
// convert a multibyte character string in an external representation
|
||||
// to wstring object in an internal representation
|
||||
std::wstring
|
||||
convert (const char *locname, const char *s, const wchar_t*)
|
||||
{
|
||||
// save the name of the original locale
|
||||
std::string saved_loc;
|
||||
|
||||
if (const char *savename = std::setlocale (LC_ALL, 0))
|
||||
saved_loc = savename;
|
||||
|
||||
// switch to (named) locale
|
||||
const char *loc = std::setlocale (LC_ALL, locname);
|
||||
if (!loc) {
|
||||
rw_fprintf (rw_stderr,
|
||||
"%s:%d: setlocale (LC_ALL, %s) = 0: %m\n",
|
||||
locname);
|
||||
return std::wstring ();
|
||||
}
|
||||
|
||||
// use an extension: allocate but do not initialize
|
||||
std::wstring res ((wchar_t*)0, 64);
|
||||
|
||||
for ( ; ; ) {
|
||||
// try to convert, resizing buffer if necessary
|
||||
std::size_t n =
|
||||
std::mbstowcs (&res [0], s, res.capacity ());
|
||||
|
||||
if (res.capacity () == n)
|
||||
// increase capacity
|
||||
res.reserve (res.capacity () * 2);
|
||||
else if (std::size_t (-1) == n) {
|
||||
|
||||
// restore the original locale before printing out
|
||||
// the error message (we don't want it localized)
|
||||
std::setlocale (LC_ALL, saved_loc.c_str ());
|
||||
|
||||
rw_fprintf (rw_stderr,
|
||||
"%s:%d: mbstowcs(..., %#s, %zu) "
|
||||
"= -1: %m\n", __FILE__, __LINE__,
|
||||
s, res.capacity ());
|
||||
res = std::wstring (); // mbstowcs() error
|
||||
|
||||
return res;
|
||||
}
|
||||
else {
|
||||
// shrink if necessary
|
||||
res.resize (n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// restore original locale
|
||||
std::setlocale (LC_ALL, saved_loc.c_str ());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
bool Test<charT>::
|
||||
check_moneypunct (const char *locname)
|
||||
{
|
||||
// (try to) set the global C locale
|
||||
char locnamebuf [256];
|
||||
const char *loc = std::setlocale (LC_ALL, locname);
|
||||
if (!loc)
|
||||
return false;
|
||||
|
||||
loc = std::strcpy (locnamebuf, loc);
|
||||
|
||||
locname_ = loc;
|
||||
|
||||
// the values of the environment variables LANG, LC_ALL,
|
||||
// and LC_MONETARY (and others) affect the native locale
|
||||
lang_ = std::getenv ("LANG");
|
||||
lc_all_ = std::getenv ("LC_ALL");
|
||||
lc_monetary_ = std::getenv ("LC_MONETARY");
|
||||
|
||||
if (!lang_)
|
||||
lang_ = "(null)";
|
||||
if (!lc_all_)
|
||||
lc_all_ = "(null)";
|
||||
if (!lc_monetary_)
|
||||
lc_monetary_ = "(null)";
|
||||
|
||||
_TRY {
|
||||
|
||||
// get a pointer to lconv and copy data to a temporray buffer
|
||||
const std::lconv* const plconv = lconvdup (std::localeconv ());
|
||||
|
||||
if (!plconv)
|
||||
return false;
|
||||
|
||||
// reset to default locale given by LC_LANG
|
||||
std::setlocale (LC_ALL, "");
|
||||
|
||||
// create a new C++ locale object
|
||||
loc_ = std::locale (locname);
|
||||
|
||||
// check that newly constructed locale matches
|
||||
|
||||
// the MBCS mon_decimal_point and mon_thousands_sep must
|
||||
// be properly converted (i.e., *mon_decimal_point may not
|
||||
// the same as s [0] after the conversion)
|
||||
String s;
|
||||
|
||||
// `locname' may be the empty string, in which case `loc'
|
||||
// will be set to the actual name of the locale
|
||||
if ( std::strcmp ("C", locname)
|
||||
&& std::strcmp ("C", loc)) {
|
||||
|
||||
// named locale other than "C" or "POISX"
|
||||
s = ::convert (locname, plconv->mon_decimal_point, (charT*)0);
|
||||
check_decimal_point (s.size () ? s [0] : charT ());
|
||||
|
||||
s = ::convert (locname, plconv->mon_thousands_sep, (charT*)0);
|
||||
check_thousands_sep (s.size () ? s [0] : charT ());
|
||||
|
||||
check_frac_digits (plconv->int_frac_digits);
|
||||
}
|
||||
else {
|
||||
// note that values in 7.4 of C89, and 7.11, p2 of C99,
|
||||
// respectively, or '\0' and '\0' for decimal_point and
|
||||
// thousands_sep, are specified in 22.2.3.1.2, p1 and p2
|
||||
// of C++98 to be '.', and ',' in the C locale
|
||||
check_decimal_point (charT ('.'));
|
||||
check_thousands_sep (charT (','));
|
||||
|
||||
// frac_digits is specified as CHAR_MAX (i.e., not available) by C99
|
||||
// verify that the C++ value is NOT CHAR_MAX, but rather 0 (it could
|
||||
// be negative with the same result)
|
||||
check_frac_digits (0);
|
||||
}
|
||||
|
||||
check_grouping (plconv->mon_grouping);
|
||||
|
||||
// convert a (possibly) multibyte string in external
|
||||
// representation to one in internal representation
|
||||
s = intl_ ? ::convert (locname, plconv->int_curr_symbol, (charT*)0)
|
||||
: ::convert (locname, plconv->currency_symbol, (charT*)0);
|
||||
|
||||
check_curr_symbol (s);
|
||||
|
||||
s = ::convert (locname, plconv->positive_sign, (charT*)0);
|
||||
|
||||
check_positive_sign (s);
|
||||
|
||||
s = ::convert (locname, plconv->negative_sign, (charT*)0);
|
||||
|
||||
check_negative_sign (s);
|
||||
|
||||
check_format (*plconv);
|
||||
|
||||
// cast away constness to work around compiler bugs (e.g., MSVC 6)
|
||||
operator delete (_RWSTD_CONST_CAST (std::lconv*, plconv));
|
||||
}
|
||||
_CATCH (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_decimal_point (charT result)
|
||||
{
|
||||
const charT c = intl_ ? _RWSTD_USE_FACET (IntlPunct, loc_).decimal_point ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).decimal_point ();
|
||||
|
||||
rw_assert (std::char_traits<charT>::eq (c, result), 0, __LINE__,
|
||||
"moneypunct<%s, %b>::decimal_point() == %#lc, got %#lc "
|
||||
"in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
|
||||
char_name_, intl_, result, c,
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_thousands_sep (charT result)
|
||||
{
|
||||
const charT c = intl_ ? _RWSTD_USE_FACET (IntlPunct, loc_).thousands_sep ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).thousands_sep ();
|
||||
|
||||
rw_assert (std::char_traits<charT>::eq (c, result), 0, __LINE__,
|
||||
"moneypunct<%s, %b>::thousands_sep() == %#lc, got %#lc "
|
||||
"in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
|
||||
char_name_, intl_, result, c,
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_frac_digits (int result)
|
||||
{
|
||||
const int i = intl_ ? _RWSTD_USE_FACET (IntlPunct, loc_).frac_digits ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).frac_digits ();
|
||||
|
||||
rw_assert (i == result, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::frac_digits() == %d, got %d "
|
||||
"in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
|
||||
char_name_, intl_, result, i,
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_grouping (const std::string &result)
|
||||
{
|
||||
const std::string s = intl_ ?
|
||||
_RWSTD_USE_FACET (IntlPunct, loc_).grouping ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).grouping ();
|
||||
|
||||
if ( s != result
|
||||
&& s.size () != result.size () && s.size () && result.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 () > result.size () ? &result : &s;
|
||||
const std::string *shrt = s.size () < result.size () ? &result : &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, %b>::grouping() equivalent to %#s, got %#s "
|
||||
"in locale (%#s) with LANG=%s, LC_ALL=%s, "
|
||||
"LC_MONETARY=%s",
|
||||
char_name_, intl_, result.c_str (), s.c_str (),
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
else
|
||||
rw_assert (s == result, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::grouping() == %#s, got %#s "
|
||||
"in locale (%#s) with LANG=%s, LC_ALL=%s, "
|
||||
"LC_MONETARY=%s",
|
||||
char_name_, intl_, result.c_str (), s.c_str (),
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
|
||||
#if 0
|
||||
|
||||
// Test disabled: what's meant here is that the pattern, NOT the value,
|
||||
// is defined identically as that of numpunct<charT>::do_grouping().
|
||||
// The values are often going to be different since one uses
|
||||
// lconv::grouping, and the other lconv::mon_grouping.
|
||||
|
||||
// 22.2.6.3.2, p3: do_grouping() returns a pattern defined identically
|
||||
// as the result of numpunct<charT>::do_grouping().
|
||||
|
||||
const std::string grp =
|
||||
_RWSTD_USE_FACET (std::numpunct<charT>, loc_).grouping ();
|
||||
|
||||
rw_assert (s == grp, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::grouping() == numpunct<>::grouping() == "
|
||||
"%{*Ac}, got %{*Ac} in locale (\"%s\") with LANG=%s, LC_ALL=%s, "
|
||||
"LC_MONETARY=%s",
|
||||
char_name_, intl_,
|
||||
int (sizeof (charT)), result.c_str (),
|
||||
int (sizeof (charT)), s.c_str (),
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
|
||||
#endif // 0
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_curr_symbol (const String &result)
|
||||
{
|
||||
const String s = intl_ ? _RWSTD_USE_FACET (IntlPunct, loc_).curr_symbol ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).curr_symbol ();
|
||||
|
||||
rw_assert (s == result, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::curr_symbol() == %{*Ac}, got %{*Ac} "
|
||||
"in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
|
||||
char_name_, intl_,
|
||||
int (sizeof (charT)), result.c_str (),
|
||||
int (sizeof (charT)), s.c_str (),
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_positive_sign (const String &result)
|
||||
{
|
||||
const String s = intl_ ?
|
||||
_RWSTD_USE_FACET (IntlPunct, loc_).positive_sign ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).positive_sign ();
|
||||
|
||||
rw_assert (s == result, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::positive_sign() == %{*Ac}, got %{*Ac} "
|
||||
"in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
|
||||
char_name_, intl_,
|
||||
int (sizeof (charT)), result.c_str (),
|
||||
int (sizeof (charT)), s.c_str (),
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_negative_sign (const String &result)
|
||||
{
|
||||
const String s = intl_ ?
|
||||
_RWSTD_USE_FACET (IntlPunct, loc_).negative_sign ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).negative_sign ();
|
||||
|
||||
rw_assert (s == result, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::negative_sign() == %{*Ac}, got %{*Ac} "
|
||||
"in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
|
||||
char_name_, intl_,
|
||||
int (sizeof (charT)), result.c_str (),
|
||||
int (sizeof (charT)), s.c_str (),
|
||||
locname_, lang_, lc_all_, lc_monetary_);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_format (const std::lconv &lc)
|
||||
{
|
||||
const UChar cpat [2][2][3] = {
|
||||
// ^ ^ ^
|
||||
// | | |
|
||||
// | | +--- cs_precedes, sep_by_space, sign_posn
|
||||
// | +------ positive, negative
|
||||
// +--------- local, international
|
||||
|
||||
{
|
||||
// C90 positive local format
|
||||
{ lc.p_cs_precedes, lc.p_sep_by_space, lc.p_sign_posn },
|
||||
|
||||
// C90 negative local format
|
||||
{ lc.n_cs_precedes, lc.n_sep_by_space, lc.n_sign_posn }
|
||||
},
|
||||
|
||||
#ifndef _RWSTD_NO_LCONV_INT_FMAT
|
||||
|
||||
{ // C99 positive international format
|
||||
{ lc.int_p_cs_precedes, lc.int_p_sep_by_space, lc.int_p_sign_posn},
|
||||
|
||||
// C99 negative international format
|
||||
{ lc.int_n_cs_precedes, lc.int_n_sep_by_space, lc.int_n_sign_posn }
|
||||
}
|
||||
|
||||
#else // if defined (_RWSTD_NO_LCONV_INT_FMAT)
|
||||
|
||||
{
|
||||
{ lc.p_cs_precedes, lc.p_sep_by_space, lc.p_sign_posn },
|
||||
{ lc.n_cs_precedes, lc.n_sep_by_space, lc.n_sign_posn }
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_LCONV_INT_FMAT
|
||||
};
|
||||
|
||||
// cs_precedes [0..1]:
|
||||
//
|
||||
// An integer set to 1 if the currency_symbol precedes the value
|
||||
// for a monetary value, and set to 0 if the symbol succeeds
|
||||
// the value.
|
||||
|
||||
// sep_by_space [0..2]:
|
||||
//
|
||||
// 0 No space separates the currency_symbol from the value for
|
||||
// a monetary value.
|
||||
// 1 If the currency symbol and sign string are adjacent, a space
|
||||
// separates them from the value; otherwise, a space separates
|
||||
// the currency symbol from the value.
|
||||
// 2 If the currency symbol and sign string are adjacent, a space
|
||||
// separates them; otherwise, a space separates the sign string
|
||||
// from the value.
|
||||
|
||||
// sign_posn [0..4]:
|
||||
//
|
||||
// An integer set to a value indicating the positioning of the
|
||||
// positive_sign for a monetary value. The following integer
|
||||
// values shall be recognized:
|
||||
//
|
||||
// 0 Parentheses enclose the value and the currency_symbol.
|
||||
// 1 The sign string precedes the value and the currency_symbol.
|
||||
// 2 The sign string succeeds the value and the currency_symbol.
|
||||
// 3 The sign string immediately precedes the currency_symbol.
|
||||
// 4 The sign string immediately succeeds the currency_symbol.
|
||||
|
||||
enum {
|
||||
none = std::money_base::none,
|
||||
space = std::money_base::space,
|
||||
symbol = std::money_base::symbol,
|
||||
sign = std::money_base::sign,
|
||||
value = std::money_base::value
|
||||
};
|
||||
|
||||
static const std::money_base::pattern patterns[] = {
|
||||
|
||||
/* 000: -1$. */ { { sign, value, symbol, none } }, // "\3\4\2\0"
|
||||
/* 001: -1$. */ { { sign, value, symbol, none } }, // "\3\4\2\0"
|
||||
/* 002: 1$-. */ { { value, symbol, sign, none } }, // "\4\2\3\0"
|
||||
/* 003: 1-$. */ { { value, sign, symbol, none } }, // "\4\3\2\0"
|
||||
/* 004: 1$-. */ { { value, symbol, sign, none } }, // "\4\2\3\0"
|
||||
|
||||
/* 010: -1 $ */ { { sign, value, space, symbol } }, // "\3\4\1\2"
|
||||
/* 011: -1 $ */ { { sign, value, space, symbol } }, // "\3\4\1\2"
|
||||
/* 012: 1 $- */ { { value, space, symbol, sign } }, // "\4\1\2\3"
|
||||
/* 013: 1 -$ */ { { value, space, sign, symbol } }, // "\4\3\3\2"
|
||||
/* 014: 1 $- */ { { value, space, symbol, sign } }, // "\4\1\2\3"
|
||||
|
||||
/* 020: - 1$ */ { { sign, space, value, symbol } }, // "\3\1\4\2"
|
||||
/* 021: - 1$ */ { { sign, space, value, symbol } }, // "\3\\14\2"
|
||||
/* 022: 1$ - */ { { value, symbol, space, sign } }, // "\4\2\1\3"
|
||||
/* 023: 1- $ */ { { value, sign, space, symbol } }, // "\4\3\1\2"
|
||||
/* 024: 1$ - */ { { value, symbol, space, sign } }, // "\4\2\1\3"
|
||||
|
||||
/* 100: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
|
||||
/* 101: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
|
||||
/* 102: $1-. */ { { symbol, value, sign, none } }, // "\2\4\3\0"
|
||||
/* 103: -$1. */ { { sign, symbol, value, none } }, // "\3\2\4\0"
|
||||
/* 104: $-1. */ { { symbol, sign, value, none } }, // "\2\3\4\0"
|
||||
|
||||
/* 110: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
|
||||
/* 111: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
|
||||
/* 112: $ 1- */ { { symbol, space, value, sign } }, // "\2\1\4\3"
|
||||
/* 113: -$ 1 */ { { sign, symbol, space, value } }, // "\3\2\1\4"
|
||||
/* 114: $- 1 */ { { symbol, sign, space, value } }, // "\2\3\1\4"
|
||||
|
||||
/* 120: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
|
||||
/* 121: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
|
||||
/* 122: $1 - */ { { symbol, value, space, sign } }, // "\2\4\1\3"
|
||||
/* 123: - $1 */ { { sign, space, symbol, value } }, // "\3\1\2\4"
|
||||
/* 124: $ -1 */ { { symbol, space, sign, value } } // "\2\1\3\4"
|
||||
};
|
||||
|
||||
for (int neg = 0; neg != 2; ++neg) {
|
||||
|
||||
enum { cs_precedes, sep_by_space, sign_posn };
|
||||
|
||||
// ignore unspecified formats (-1)
|
||||
if ( cpat [intl_][neg][cs_precedes] > 1
|
||||
|| cpat [intl_][neg][sep_by_space] > 2
|
||||
|| cpat [intl_][neg][sign_posn] > 4)
|
||||
continue;
|
||||
|
||||
const int inx =
|
||||
cpat [intl_][neg][cs_precedes] * 3 * 5
|
||||
+ cpat [intl_][neg][sep_by_space] * 5
|
||||
+ cpat [intl_][neg][sign_posn];
|
||||
|
||||
check_format (!neg, patterns [inx], cpat [intl_][neg]);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT>
|
||||
void Test<charT>::
|
||||
check_format (bool pos, std::money_base::pattern result, const UChar cpat [3])
|
||||
{
|
||||
const std::money_base::pattern pat =
|
||||
intl_ ? pos ? _RWSTD_USE_FACET (IntlPunct, loc_).pos_format ()
|
||||
: _RWSTD_USE_FACET (IntlPunct, loc_).neg_format ()
|
||||
: pos ? _RWSTD_USE_FACET (Punct, loc_).pos_format ()
|
||||
: _RWSTD_USE_FACET (Punct, loc_).neg_format ();
|
||||
|
||||
// number of times each symbol appears in pattern
|
||||
int counts [5] = { 0 };
|
||||
|
||||
for (unsigned i = 0; i != sizeof pat.field / sizeof *pat.field; i++) {
|
||||
|
||||
if (UChar (pat.field [i] < char (sizeof counts / sizeof *counts)))
|
||||
++counts [UChar (pat.field [i])];
|
||||
|
||||
// verify 22.2.6.3, p1
|
||||
if (std::money_base::none == pat.field [i] && !i)
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::%s_format() == %{LM}, "
|
||||
"none must not appear first",
|
||||
char_name_, intl_, pos ? "pos" : "neg",
|
||||
pat.field);
|
||||
|
||||
if ( std::money_base::space == pat.field [i]
|
||||
&& !i && i != sizeof pat.field / sizeof *pat.field - 1)
|
||||
rw_assert (false, 0, __LINE__,
|
||||
"moneypunct<%s, %b>::%s_format() == %{LM}, "
|
||||
"space must not appear first or last",
|
||||
char_name_, intl_, pos ? "pos" : "neg",
|
||||
pat.field);
|
||||
}
|
||||
|
||||
// verify that the actual pattern matches the expected one
|
||||
rw_assert (0 == std::memcmp (&pat, &result, sizeof pat), 0, __LINE__,
|
||||
"moneypunct<%s, %b>::%s_format() == %{LM}, got %{LM}; "
|
||||
"(cs_precedes = '\\%o', sep_by_space = '\\%o', "
|
||||
"sign_posn = '\\%o')",
|
||||
char_name_, intl_, pos ? "pos" : "neg",
|
||||
pat.field, result.field, cpat [0], cpat [1], cpat [2]);
|
||||
|
||||
// verify 22.2.6.3, p1
|
||||
rw_assert (1 == counts [std::money_base::symbol], 0, __LINE__,
|
||||
"money_base::symbol must apear exactly once, did %d times",
|
||||
counts [std::money_base::symbol]);
|
||||
|
||||
rw_assert (1 == counts [std::money_base::sign], 0, __LINE__,
|
||||
"money_base::sign must apear exactly once, did %d times",
|
||||
counts [std::money_base::sign]);
|
||||
|
||||
rw_assert (1 == counts [std::money_base::value], 0, __LINE__,
|
||||
"money_base::value must apear exactly once, did %d times",
|
||||
counts [std::money_base::value]);
|
||||
|
||||
rw_assert (1 == counts [std::money_base::space]
|
||||
+ counts [std::money_base::none], 0, __LINE__,
|
||||
"money_base::space or money_base::none must appear "
|
||||
"exactly once, did %d times",
|
||||
counts [std::money_base::space]
|
||||
+ counts [std::money_base::none]);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
{
|
||||
Test<char> t ("char", false);
|
||||
t.runTest ();
|
||||
}
|
||||
|
||||
{
|
||||
Test<char> t ("char", true);
|
||||
t.runTest ();
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
{
|
||||
Test<wchar_t> t ("wchar_t", false);
|
||||
t.runTest ();
|
||||
}
|
||||
|
||||
{
|
||||
Test<wchar_t> t ("wchar_t", true);
|
||||
t.runTest ();
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.moneypunct",
|
||||
0 /* no comment */,
|
||||
run_test,
|
||||
"",
|
||||
(void*)0 /* sentinel */);
|
||||
}
|
||||
485
extern/stdcxx/4.2.1/tests/localization/22.locale.moneypunct.mt.cpp
vendored
Normal file
485
extern/stdcxx/4.2.1/tests/localization/22.locale.moneypunct.mt.cpp
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.moneypunct.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the moneypunct facet
|
||||
*
|
||||
* $Id: 22.locale.moneypunct.mt.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 <ios> // for ios
|
||||
#include <locale> // for locale, moneypunct
|
||||
|
||||
#include <cstdlib> // for mbstowcs(), size_t
|
||||
#include <cstring> // for strcpy()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h>
|
||||
#include <valcmp.h>
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int rw_opt_nthreads = 1;
|
||||
|
||||
// the default number of times for each thread to iterate
|
||||
#define DFLT_LOOPS 10000
|
||||
|
||||
// the number of times each thread should iterate (will be set to
|
||||
// DFLT_LOOPS unless explicitly specified on the command line)
|
||||
int rw_opt_nloops = -1;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// number of locales to test
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
struct MoneypunctData
|
||||
{
|
||||
// the name of the locale the data goes with
|
||||
const char* locale_name_;
|
||||
|
||||
char decimal_point_;
|
||||
char thousands_sep_;
|
||||
char grouping_ [32];
|
||||
char curr_symbol_ [32];
|
||||
char positive_sign_ [32];
|
||||
char negative_sign_ [32];
|
||||
int frac_digits_;
|
||||
char pos_format_ [32];
|
||||
char neg_format_ [32];
|
||||
|
||||
char int_curr_symbol_ [32];
|
||||
|
||||
int int_frac_digits_;
|
||||
char int_pos_format_ [32];
|
||||
char int_neg_format_ [32];
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t wdecimal_point_;
|
||||
wchar_t wthousands_sep_;
|
||||
wchar_t wcurr_symbol_ [32];
|
||||
wchar_t wpositive_sign_ [32];
|
||||
wchar_t wnegative_sign_ [32];
|
||||
|
||||
wchar_t wint_curr_symbol_ [32];
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} punct_data [MAX_THREADS];
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
bool test_char; // exercise num_put<char>
|
||||
bool test_wchar; // exercise num_put<wchar_t>
|
||||
|
||||
static void
|
||||
thread_loop_body (std::size_t i)
|
||||
{
|
||||
const std::size_t inx = std::size_t (i) % (nlocales ? nlocales : 1);
|
||||
|
||||
const MoneypunctData* const data = punct_data + inx;
|
||||
|
||||
// construct a named locale
|
||||
const std::locale loc (data->locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char, local specialization of the facet
|
||||
|
||||
typedef std::moneypunct<char, false> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const char dp = mp.decimal_point ();
|
||||
const char ts = mp.thousands_sep ();
|
||||
const std::string grp = mp.grouping ();
|
||||
const std::string cur = mp.curr_symbol ();
|
||||
const std::string pos = mp.positive_sign ();
|
||||
const std::string neg = mp.negative_sign ();
|
||||
const int fd = mp.frac_digits ();
|
||||
const Punct::pattern pfm = mp.pos_format ();
|
||||
const Punct::pattern nfm = mp.neg_format ();
|
||||
|
||||
RW_ASSERT (dp == data->decimal_point_);
|
||||
RW_ASSERT (ts == data->thousands_sep_);
|
||||
RW_ASSERT (fd == data->frac_digits_);
|
||||
RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
|
||||
RW_ASSERT (!rw_strncmp (cur.c_str (), data->curr_symbol_));
|
||||
RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
|
||||
RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
|
||||
|
||||
RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
|
||||
RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
|
||||
}
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char, international specialization
|
||||
|
||||
typedef std::moneypunct<char, true> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const char dp = mp.decimal_point ();
|
||||
const char ts = mp.thousands_sep ();
|
||||
const std::string grp = mp.grouping ();
|
||||
const std::string cur = mp.curr_symbol ();
|
||||
const std::string pos = mp.positive_sign ();
|
||||
const std::string neg = mp.negative_sign ();
|
||||
const int fd = mp.frac_digits ();
|
||||
const Punct::pattern pfm = mp.pos_format ();
|
||||
const Punct::pattern nfm = mp.neg_format ();
|
||||
|
||||
RW_ASSERT (dp == data->decimal_point_);
|
||||
RW_ASSERT (ts == data->thousands_sep_);
|
||||
RW_ASSERT (fd == data->frac_digits_);
|
||||
RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
|
||||
RW_ASSERT (!rw_strncmp (cur.c_str (), data->int_curr_symbol_));
|
||||
RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
|
||||
RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
|
||||
|
||||
RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
|
||||
RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char, local specialization of the facet
|
||||
|
||||
typedef std::moneypunct<wchar_t, false> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const wchar_t dp = mp.decimal_point ();
|
||||
const wchar_t ts = mp.thousands_sep ();
|
||||
const std::string grp = mp.grouping ();
|
||||
const std::wstring cur = mp.curr_symbol ();
|
||||
const std::wstring pos = mp.positive_sign ();
|
||||
const std::wstring neg = mp.negative_sign ();
|
||||
const int fd = mp.frac_digits ();
|
||||
const Punct::pattern pfm = mp.pos_format ();
|
||||
const Punct::pattern nfm = mp.neg_format ();
|
||||
|
||||
RW_ASSERT (dp == data->wdecimal_point_);
|
||||
RW_ASSERT (ts == data->wthousands_sep_);
|
||||
RW_ASSERT (fd == data->frac_digits_);
|
||||
RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
|
||||
RW_ASSERT (!rw_strncmp (cur.c_str (), data->wcurr_symbol_));
|
||||
RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
|
||||
RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
|
||||
|
||||
RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
|
||||
RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
|
||||
}
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char, international specialization
|
||||
|
||||
typedef std::moneypunct<wchar_t, true> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const wchar_t dp = mp.decimal_point ();
|
||||
const wchar_t ts = mp.thousands_sep ();
|
||||
const std::string grp = mp.grouping ();
|
||||
const std::wstring cur = mp.curr_symbol ();
|
||||
const std::wstring pos = mp.positive_sign ();
|
||||
const std::wstring neg = mp.negative_sign ();
|
||||
const int fd = mp.frac_digits ();
|
||||
const Punct::pattern pfm = mp.pos_format ();
|
||||
const Punct::pattern nfm = mp.neg_format ();
|
||||
|
||||
RW_ASSERT (dp == data->wdecimal_point_);
|
||||
RW_ASSERT (ts == data->wthousands_sep_);
|
||||
RW_ASSERT (fd == data->frac_digits_);
|
||||
RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
|
||||
RW_ASSERT (!rw_strncmp (cur.c_str (), data->wint_curr_symbol_));
|
||||
RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
|
||||
RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
|
||||
|
||||
RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
|
||||
RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
for (int i = 0; i != rw_opt_nloops; ++i) {
|
||||
|
||||
thread_loop_body (std::size_t (i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
// array of locale names to use for testing
|
||||
const char* locales [sizeof punct_data / sizeof *punct_data];
|
||||
|
||||
const std::size_t maxinx = sizeof locales / sizeof *locales;
|
||||
|
||||
// iterate over locales, initializing a global punct_data array
|
||||
for (const char *name = locale_list; *name; name += std::strlen (name) +1) {
|
||||
|
||||
std::locale loc;
|
||||
|
||||
MoneypunctData* const pdata = punct_data + nlocales;
|
||||
|
||||
pdata->locale_name_ = name;
|
||||
locales [nlocales] = name;
|
||||
|
||||
try {
|
||||
loc = std::locale (name);
|
||||
|
||||
typedef std::moneypunct<char, false> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const char dp = mp.decimal_point ();
|
||||
const char ts = mp.thousands_sep ();
|
||||
const std::string grp = mp.grouping ();
|
||||
const std::string cur = mp.curr_symbol ();
|
||||
const std::string pos = mp.positive_sign ();
|
||||
const std::string neg = mp.negative_sign ();
|
||||
const int fd = mp.frac_digits ();
|
||||
const Punct::pattern pfm = mp.pos_format ();
|
||||
const Punct::pattern nfm = mp.neg_format ();
|
||||
|
||||
pdata->decimal_point_ = dp;
|
||||
pdata->thousands_sep_ = ts;
|
||||
pdata->frac_digits_ = fd;
|
||||
|
||||
std::strcpy (pdata->grouping_, grp.c_str ());
|
||||
std::strcpy (pdata->curr_symbol_, cur.c_str ());
|
||||
std::strcpy (pdata->positive_sign_, pos.c_str ());
|
||||
std::strcpy (pdata->negative_sign_, neg.c_str ());
|
||||
std::memcpy (pdata->pos_format_, &pfm, sizeof pfm);
|
||||
std::memcpy (pdata->neg_format_, &nfm, sizeof nfm);
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (0, 0, __LINE__,
|
||||
"std::locale(%#s) threw an exception, skipping", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
typedef std::moneypunct<char, true> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const std::string cur = mp.curr_symbol ();
|
||||
const int fd = mp.frac_digits ();
|
||||
const Punct::pattern pfm = mp.pos_format ();
|
||||
const Punct::pattern nfm = mp.neg_format ();
|
||||
|
||||
pdata->int_frac_digits_ = fd;
|
||||
|
||||
std::strcpy (pdata->int_curr_symbol_, cur.c_str ());
|
||||
std::memcpy (pdata->int_pos_format_, &pfm, sizeof pfm);
|
||||
std::memcpy (pdata->int_neg_format_, &nfm, sizeof nfm);
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (0, 0, __LINE__,
|
||||
"std::locale(%#s) threw an exception, skipping", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
try {
|
||||
typedef std::moneypunct<wchar_t, false> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const wchar_t dp = mp.decimal_point ();
|
||||
const wchar_t ts = mp.thousands_sep ();
|
||||
const std::wstring cur = mp.curr_symbol ();
|
||||
const std::wstring pos = mp.positive_sign ();
|
||||
const std::wstring neg = mp.negative_sign ();
|
||||
|
||||
pdata->wdecimal_point_ = dp;
|
||||
pdata->wthousands_sep_ = ts;
|
||||
|
||||
typedef std::wstring::traits_type Traits;
|
||||
|
||||
Traits::copy (pdata->wcurr_symbol_, cur.data (), cur.size ());
|
||||
Traits::copy (pdata->wpositive_sign_, pos.data (), pos.size ());
|
||||
Traits::copy (pdata->wnegative_sign_, neg.data (), neg.size ());
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (0, 0, __LINE__,
|
||||
"std::locale(%#s) threw an exception, skipping", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
typedef std::moneypunct<wchar_t, true> Punct;
|
||||
|
||||
const Punct &mp = std::use_facet<Punct>(loc);
|
||||
|
||||
const std::wstring cur = mp.curr_symbol ();
|
||||
const std::wstring pos = mp.positive_sign ();
|
||||
const std::wstring neg = mp.negative_sign ();
|
||||
|
||||
typedef std::wstring::traits_type Traits;
|
||||
|
||||
Traits::copy (pdata->wint_curr_symbol_, cur.data (), cur.size ());
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (0, 0, __LINE__,
|
||||
"std::locale(%#s) threw an exception, skipping", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
++nlocales;
|
||||
|
||||
if (nlocales == maxinx)
|
||||
break;
|
||||
}
|
||||
|
||||
// unless the number of iterations was explicitly specified
|
||||
// on the command line, decrease the number to equal the number
|
||||
// of excericsed locales when only one thread is being tested
|
||||
if (1 == rw_opt_nthreads && rw_opt_nloops < 0)
|
||||
rw_opt_nloops = int (nlocales);
|
||||
|
||||
// when the number of iterations wasn't explicitly specified
|
||||
// on the command line set it to the default value
|
||||
if (rw_opt_nloops < 0)
|
||||
rw_opt_nloops = DFLT_LOOPS;
|
||||
|
||||
rw_fatal (0 < nlocales, 0, __LINE__,
|
||||
"must have at least one valid locale to test");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::moneypunct<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
rw_opt_nthreads, 1 != rw_opt_nthreads,
|
||||
rw_opt_nloops, 1 != rw_opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::moneypunct<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::moneypunct<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise the thread safety
|
||||
// of the wchar_t specialization
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::moneypunct<char> "
|
||||
"and std::moneypunct<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
rw_opt_nthreads = rw_get_cpus ();
|
||||
if (rw_opt_nthreads < 2)
|
||||
rw_opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.moneypunct",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-locales=", // must be provided
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&rw_opt_nthreads,
|
||||
&rw_opt_setlocales);
|
||||
}
|
||||
3000
extern/stdcxx/4.2.1/tests/localization/22.locale.num.get.cpp
vendored
Normal file
3000
extern/stdcxx/4.2.1/tests/localization/22.locale.num.get.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
572
extern/stdcxx/4.2.1/tests/localization/22.locale.num.get.mt.cpp
vendored
Normal file
572
extern/stdcxx/4.2.1/tests/localization/22.locale.num.get.mt.cpp
vendored
Normal file
@@ -0,0 +1,572 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.num.get.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the num_get facet
|
||||
*
|
||||
* $Id: 22.locale.num.get.mt.cpp 650350 2008-04-22 01:35:17Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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 <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, num_get
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h> // for rw_get_processors (), rw_thread_pool()
|
||||
#include <driver.h>
|
||||
#include <valcmp.h>
|
||||
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int rw_opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate
|
||||
int rw_opt_nloops = MAX_LOOPS;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around an inefficiency (small cache size?) on HP-UX
|
||||
// in LP64 mode (see STDCXX-812)
|
||||
int opt_nlocales = 10;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int rw_opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
|
||||
struct MyNumData {
|
||||
|
||||
enum { BufferSize = 32 };
|
||||
|
||||
enum PutId {
|
||||
put_bool,
|
||||
put_long,
|
||||
put_ulong,
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_LONG
|
||||
|
||||
put_llong,
|
||||
put_ullong,
|
||||
|
||||
#endif // _RWSTD_NO_LONG_LONG
|
||||
|
||||
put_dbl,
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
put_ldbl,
|
||||
|
||||
#endif // _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
put_ptr,
|
||||
put_max
|
||||
};
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// the value that we will be formatting
|
||||
double value_;
|
||||
|
||||
// the type of the data we get
|
||||
PutId type_;
|
||||
|
||||
// holds the narrow/wide character representation of value_ and
|
||||
// the number of used 'charT' in each buffer.
|
||||
char ncs_ [BufferSize];
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t wcs_ [BufferSize];
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} my_num_data [MAX_THREADS];
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyIos: std::basic_ios<charT, Traits>
|
||||
{
|
||||
MyIos () {
|
||||
this->init (0);
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyStreambuf: std::basic_streambuf<charT, Traits>
|
||||
{
|
||||
typedef std::basic_streambuf<charT, Traits> Base;
|
||||
|
||||
MyStreambuf ()
|
||||
: Base () {
|
||||
}
|
||||
|
||||
void pubsetg (const charT *gbeg, std::streamsize n) {
|
||||
this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
|
||||
_RWSTD_CONST_CAST (charT*, gbeg),
|
||||
_RWSTD_CONST_CAST (charT*, gbeg) + n);
|
||||
}
|
||||
|
||||
void pubsetp (charT *pbeg, std::streamsize n) {
|
||||
this->setp (pbeg, pbeg + n);
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT, class Traits>
|
||||
void
|
||||
test_put_data (const MyNumData &data,
|
||||
const std::num_put<charT> &np,
|
||||
const std::ostreambuf_iterator<charT, Traits> &iter,
|
||||
std::basic_ios<charT, Traits> &io,
|
||||
charT fill,
|
||||
charT term)
|
||||
{
|
||||
switch (data.type_) {
|
||||
case MyNumData::put_bool:
|
||||
*np.put (iter, io, fill,
|
||||
data.value_ < 1.f) = term;
|
||||
break;
|
||||
case MyNumData::put_long:
|
||||
*np.put (iter, io, fill,
|
||||
(long)data.value_) = term;
|
||||
break;
|
||||
case MyNumData::put_ulong:
|
||||
*np.put (iter, io, fill,
|
||||
(unsigned long)data.value_) = term;
|
||||
break;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_LONG
|
||||
|
||||
case MyNumData::put_llong:
|
||||
*np.put (iter, io, fill,
|
||||
(_RWSTD_LONG_LONG)data.value_) = term;
|
||||
break;
|
||||
case MyNumData::put_ullong:
|
||||
*np.put (iter, io, fill,
|
||||
(unsigned _RWSTD_LONG_LONG)data.value_) = term;
|
||||
break;
|
||||
|
||||
#endif // _RWSTD_NO_LONG_LONG
|
||||
|
||||
case MyNumData::put_dbl:
|
||||
*np.put (iter, io, fill,
|
||||
(double)data.value_) = term;
|
||||
|
||||
break;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
case MyNumData::put_ldbl:
|
||||
*np.put (iter, io, fill,
|
||||
(long double)data.value_) = term;
|
||||
break;
|
||||
|
||||
#endif // _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
case MyNumData::put_ptr:
|
||||
*np.put (iter, io, fill,
|
||||
(const void*)&data.value_) = term;
|
||||
break;
|
||||
|
||||
case MyNumData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
void
|
||||
test_get_data (const MyNumData &data,
|
||||
const std::num_get<charT> &ng,
|
||||
const std::istreambuf_iterator<charT, Traits> &iter,
|
||||
const std::istreambuf_iterator<charT, Traits> &end,
|
||||
std::basic_ios<charT, Traits> &io)
|
||||
{
|
||||
std::ios_base::iostate state = std::ios_base::goodbit;
|
||||
|
||||
switch (data.type_) {
|
||||
case MyNumData::put_bool: {
|
||||
const bool expected = data.value_ < 1.f;
|
||||
bool checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
case MyNumData::put_long: {
|
||||
const long expected = (long)data.value_;
|
||||
long checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
case MyNumData::put_ulong: {
|
||||
const unsigned long expected = (unsigned long)data.value_;
|
||||
unsigned long checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_LONG
|
||||
|
||||
case MyNumData::put_llong: {
|
||||
const _RWSTD_LONG_LONG expected = (_RWSTD_LONG_LONG)data.value_;
|
||||
_RWSTD_LONG_LONG checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
case MyNumData::put_ullong: {
|
||||
const unsigned _RWSTD_LONG_LONG expected
|
||||
= (unsigned _RWSTD_LONG_LONG)data.value_;
|
||||
unsigned _RWSTD_LONG_LONG checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif // _RWSTD_NO_LONG_LONG
|
||||
|
||||
case MyNumData::put_dbl: {
|
||||
const double expected = (double)data.value_;
|
||||
double checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
case MyNumData::put_ldbl: {
|
||||
const long double expected = (long double)data.value_;
|
||||
long double checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif // _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
case MyNumData::put_ptr: {
|
||||
const void* expected = (const void*)&data.value_;
|
||||
void* checked;
|
||||
ng.get (iter, end, io, state, checked);
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT (checked == expected);
|
||||
}
|
||||
break;
|
||||
|
||||
case MyNumData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise num_get<char>
|
||||
bool test_wchar; // exercise num_get<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
typedef std::char_traits<char> Traits;
|
||||
MyIos<char, Traits> nio;
|
||||
MyStreambuf<char, Traits> nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
typedef std::char_traits<wchar_t> WTraits;
|
||||
MyIos<wchar_t, WTraits> wio;
|
||||
MyStreambuf<wchar_t, WTraits> wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
for (int i = 0; i != rw_opt_nloops; ++i) {
|
||||
|
||||
// fill in the value and results for this locale
|
||||
const MyNumData& data = my_num_data [i % nlocales];
|
||||
|
||||
// construct a named locale and imbue it in the ios object
|
||||
// so that the locale is used not only by the num_put facet
|
||||
const std::locale loc =
|
||||
rw_opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::num_get<char> &ng =
|
||||
std::use_facet<std::num_get<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetg (data.ncs_, Traits::length (data.ncs_));
|
||||
|
||||
test_get_data (data, ng,
|
||||
std::istreambuf_iterator<char>(&nsb),
|
||||
std::istreambuf_iterator<char>(),
|
||||
nio);
|
||||
|
||||
RW_ASSERT (!nio.fail ());
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::num_get<wchar_t> &wp =
|
||||
std::use_facet<std::num_get<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetg (data.wcs_, WTraits::length (data.wcs_));
|
||||
|
||||
test_get_data (data, wp,
|
||||
std::istreambuf_iterator<wchar_t>(&wsb),
|
||||
std::istreambuf_iterator<wchar_t>(),
|
||||
wio);
|
||||
|
||||
RW_ASSERT (!wio.fail ());
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
for (const char *name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the value and results for this locale
|
||||
MyNumData& data = my_num_data [nlocales];
|
||||
data.locale_name_ = name;
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
data.value_ = nlocales & 1 ? -1.f * nlocales : 1.f * nlocales;
|
||||
data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max);
|
||||
|
||||
// format data into buffers
|
||||
const std::num_put<char> &np =
|
||||
std::use_facet<std::num_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
test_put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
|
||||
nio, ' ', '\0');
|
||||
|
||||
rw_fatal (!nio.fail (), __FILE__, __LINE__,
|
||||
"num_put<char>::put(...) failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::num_put<wchar_t> &wp =
|
||||
std::use_facet<std::num_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
test_put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
wio, L' ', L'\0');
|
||||
|
||||
rw_fatal (!wio.fail (), __FILE__, __LINE__,
|
||||
"num_put<wchar_t>::put(...) failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (rw_opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::num_get<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
rw_opt_nthreads, 1 != rw_opt_nthreads,
|
||||
rw_opt_nloops, 1 != rw_opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::num_get<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::num_get<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::num_get<char> and std::num_get<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv [])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
rw_opt_nthreads = rw_get_cpus ();
|
||||
if (rw_opt_nthreads < 2)
|
||||
rw_opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.num.get",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&rw_opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&rw_opt_shared_locale);
|
||||
}
|
||||
2454
extern/stdcxx/4.2.1/tests/localization/22.locale.num.put.cpp
vendored
Normal file
2454
extern/stdcxx/4.2.1/tests/localization/22.locale.num.put.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
468
extern/stdcxx/4.2.1/tests/localization/22.locale.num.put.mt.cpp
vendored
Normal file
468
extern/stdcxx/4.2.1/tests/localization/22.locale.num.put.mt.cpp
vendored
Normal file
@@ -0,0 +1,468 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.num.put.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the num_put facet
|
||||
*
|
||||
* $Id: 22.locale.num.put.mt.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 <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, num_put
|
||||
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h> // for rw_get_processors (), rw_thread_pool()
|
||||
#include <driver.h>
|
||||
#include <valcmp.h>
|
||||
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate
|
||||
int opt_nloops = MAX_LOOPS;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around an inefficiency (small cache size?) on HP-UX
|
||||
// in LP64 mode (see STDCXX-812)
|
||||
int opt_nlocales = 10;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
|
||||
struct MyNumData {
|
||||
|
||||
enum { BufferSize = 32 };
|
||||
|
||||
enum PutId {
|
||||
put_bool,
|
||||
put_long,
|
||||
put_ulong,
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_LONG
|
||||
|
||||
put_llong,
|
||||
put_ullong,
|
||||
|
||||
#endif // _RWSTD_NO_LONG_LONG
|
||||
|
||||
put_dbl,
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
put_ldbl,
|
||||
|
||||
#endif // _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
put_ptr,
|
||||
put_max
|
||||
};
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// the value that we will be formatting
|
||||
double value_;
|
||||
|
||||
// the type of the data we put
|
||||
PutId type_;
|
||||
|
||||
// holds the narrow/wide character representation of value_ and
|
||||
// the number of used 'charT' in each buffer.
|
||||
char ncs_ [BufferSize];
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t wcs_ [BufferSize];
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} my_num_data [MAX_THREADS];
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyIos: std::basic_ios<charT, Traits>
|
||||
{
|
||||
MyIos () {
|
||||
this->init (0);
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyStreambuf: std::basic_streambuf<charT, Traits>
|
||||
{
|
||||
typedef std::basic_streambuf<charT, Traits> Base;
|
||||
|
||||
MyStreambuf ()
|
||||
: Base () {
|
||||
}
|
||||
|
||||
void pubsetp (charT *pbeg, std::streamsize n) {
|
||||
this->setp (pbeg, pbeg + n);
|
||||
}
|
||||
};
|
||||
|
||||
template <class charT, class Traits>
|
||||
void
|
||||
put_data (const MyNumData &data,
|
||||
const std::num_put<charT> &np,
|
||||
const std::ostreambuf_iterator<charT, Traits> &iter,
|
||||
std::basic_ios<charT, Traits> &io,
|
||||
charT fill,
|
||||
charT term)
|
||||
{
|
||||
switch (data.type_) {
|
||||
case MyNumData::put_bool:
|
||||
*np.put (iter, io, fill,
|
||||
data.value_ < 1.f) = term;
|
||||
break;
|
||||
case MyNumData::put_long:
|
||||
*np.put (iter, io, fill,
|
||||
(long)data.value_) = term;
|
||||
break;
|
||||
case MyNumData::put_ulong:
|
||||
*np.put (iter, io, fill,
|
||||
(unsigned long)data.value_) = term;
|
||||
break;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_LONG
|
||||
|
||||
case MyNumData::put_llong:
|
||||
*np.put (iter, io, fill,
|
||||
(_RWSTD_LONG_LONG)data.value_) = term;
|
||||
break;
|
||||
case MyNumData::put_ullong:
|
||||
*np.put (iter, io, fill,
|
||||
(unsigned _RWSTD_LONG_LONG)data.value_) = term;
|
||||
break;
|
||||
|
||||
#endif // _RWSTD_NO_LONG_LONG
|
||||
|
||||
case MyNumData::put_dbl:
|
||||
*np.put (iter, io, fill,
|
||||
(double)data.value_) = term;
|
||||
|
||||
break;
|
||||
|
||||
#ifndef _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
case MyNumData::put_ldbl:
|
||||
*np.put (iter, io, fill,
|
||||
(long double)data.value_) = term;
|
||||
break;
|
||||
|
||||
#endif // _RWSTD_NO_LONG_DOUBLE
|
||||
|
||||
case MyNumData::put_ptr:
|
||||
*np.put (iter, io, fill,
|
||||
(const void*)&data.value_) = term;
|
||||
break;
|
||||
|
||||
case MyNumData::put_max:
|
||||
// avoid enumeration value `put_max' not handled in switch
|
||||
// this case should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise num_put<char>
|
||||
bool test_wchar; // exercise num_put<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
char ncs [MyNumData::BufferSize];
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
wchar_t wcs [MyNumData::BufferSize];
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
// fill in the value and results for this locale
|
||||
const MyNumData& data = my_num_data [i % nlocales];
|
||||
|
||||
// construct a named locale and imbue it in the ios object
|
||||
// so that the locale is used not only by the num_put facet
|
||||
const std::locale loc =
|
||||
opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::num_put<char> &np =
|
||||
std::use_facet<std::num_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
|
||||
|
||||
put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
|
||||
nio, ' ', '\0');
|
||||
|
||||
RW_ASSERT (!nio.fail ());
|
||||
RW_ASSERT (!rw_strncmp (ncs, data.ncs_));
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::num_put<wchar_t> &wp =
|
||||
std::use_facet<std::num_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
|
||||
|
||||
put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
wio, L' ', L'\0');
|
||||
|
||||
RW_ASSERT (!wio.fail ());
|
||||
RW_ASSERT (!rw_strncmp (wcs, data.wcs_));
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
for (const char *name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the value and results for this locale
|
||||
MyNumData& data = my_num_data [nlocales];
|
||||
data.locale_name_ = name;
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
data.value_ = nlocales & 1 ? -1 * nlocales : nlocales;
|
||||
data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max);
|
||||
|
||||
// format data into buffers
|
||||
const std::num_put<char> &np =
|
||||
std::use_facet<std::num_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
|
||||
nio, ' ', '\0');
|
||||
|
||||
rw_fatal (!nio.fail (), __FILE__, __LINE__,
|
||||
"num_put<char>::put(...) failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::num_put<wchar_t> &wp =
|
||||
std::use_facet<std::num_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
wio, L' ', L'\0');
|
||||
|
||||
rw_fatal (!wio.fail (), __FILE__, __LINE__,
|
||||
"num_put<wchar_t>::put(...) failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::num_put<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::num_put<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::num_put<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::num_put<char> and std::num_put<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.num.put",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&opt_shared_locale);
|
||||
}
|
||||
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);
|
||||
}
|
||||
335
extern/stdcxx/4.2.1/tests/localization/22.locale.numpunct.mt.cpp
vendored
Normal file
335
extern/stdcxx/4.2.1/tests/localization/22.locale.numpunct.mt.cpp
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.numpunct.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the numpunct facet
|
||||
*
|
||||
* $Id: 22.locale.numpunct.mt.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 <locale> // for locale, numpunct
|
||||
|
||||
#include <clocale> // for lconv, localeconv()
|
||||
#include <cstdlib> // for mbstowcs()
|
||||
#include <cstring> // for size_t, strcpy()
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h>
|
||||
#include <valcmp.h>
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 32
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int rw_opt_nloops = 200000;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around an inefficiency (small cache size?) on HP-UX
|
||||
// in LP64 mode (see STDCXX-812)
|
||||
int opt_nlocales = 10;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
struct NumPunctData
|
||||
{
|
||||
const char* locale_name_;
|
||||
std::locale locale_;
|
||||
|
||||
std::string grouping_;
|
||||
|
||||
char decimal_point_;
|
||||
char thousands_sep_;
|
||||
std::string truename_;
|
||||
std::string falsename_;
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
wchar_t wdecimal_point_;
|
||||
wchar_t wthousands_sep_;
|
||||
std::wstring wtruename_;
|
||||
std::wstring wfalsename_;
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} punct_data [MAX_THREADS];
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise num_put<char>
|
||||
bool test_wchar; // exercise num_put<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
for (int i = 0; i != rw_opt_nloops; ++i) {
|
||||
|
||||
const std::size_t inx = std::size_t (i) % nlocales;
|
||||
|
||||
const NumPunctData& data = punct_data[inx];
|
||||
|
||||
// construct a named locale
|
||||
const std::locale loc =
|
||||
opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::numpunct<char> &np =
|
||||
std::use_facet<std::numpunct<char> >(loc);
|
||||
|
||||
const char dp = np.decimal_point ();
|
||||
const char ts = np.thousands_sep ();
|
||||
const std::string grp = np.grouping ();
|
||||
const std::string tn = np.truename ();
|
||||
const std::string fn = np.falsename ();
|
||||
|
||||
RW_ASSERT (dp == data.decimal_point_);
|
||||
RW_ASSERT (ts == data.thousands_sep_);
|
||||
RW_ASSERT (0 == rw_strncmp (grp.c_str (),
|
||||
data.grouping_.c_str ()));
|
||||
RW_ASSERT (0 == rw_strncmp (tn.c_str (),
|
||||
data.truename_.c_str ()));
|
||||
RW_ASSERT (0 == rw_strncmp (fn.c_str (),
|
||||
data.falsename_.c_str ()));
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::numpunct<wchar_t> &wp =
|
||||
std::use_facet<std::numpunct<wchar_t> >(loc);
|
||||
|
||||
const wchar_t dp = wp.decimal_point ();
|
||||
const wchar_t ts = wp.thousands_sep ();
|
||||
const std::string grp = wp.grouping ();
|
||||
const std::wstring tn = wp.truename ();
|
||||
const std::wstring fn = wp.falsename ();
|
||||
|
||||
RW_ASSERT (dp == data.wdecimal_point_);
|
||||
RW_ASSERT (ts == data.wthousands_sep_);
|
||||
RW_ASSERT (0 == rw_strncmp (grp.c_str (),
|
||||
data.grouping_.c_str ()));
|
||||
RW_ASSERT (0 == rw_strncmp (tn.c_str (),
|
||||
data.wtruename_.c_str ()));
|
||||
RW_ASSERT (0 == rw_strncmp (fn.c_str (),
|
||||
data.wfalsename_.c_str ()));
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = sizeof punct_data / sizeof *punct_data;
|
||||
|
||||
// iterate over locales, initializing a global punct_data array
|
||||
for (const char *name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) +1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
NumPunctData& data = punct_data [inx];
|
||||
|
||||
try {
|
||||
std::locale loc(name);
|
||||
data.locale_name_ = name;
|
||||
|
||||
const std::numpunct<char> &np =
|
||||
std::use_facet<std::numpunct<char> >(loc);
|
||||
|
||||
data.grouping_ = np.grouping ();
|
||||
|
||||
data.decimal_point_ = np.decimal_point ();
|
||||
data.thousands_sep_ = np.thousands_sep ();
|
||||
|
||||
data.truename_ = np.truename ();
|
||||
data.falsename_ = np.falsename ();
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::numpunct<wchar_t> &wp =
|
||||
std::use_facet<std::numpunct<wchar_t> >(loc);
|
||||
|
||||
data.wdecimal_point_ = wp.decimal_point ();
|
||||
data.wthousands_sep_ = wp.thousands_sep ();
|
||||
|
||||
data.wtruename_ = wp.truename ();
|
||||
data.wfalsename_ = wp.falsename ();
|
||||
|
||||
#endif
|
||||
|
||||
if (opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::numpunct<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
rw_opt_nloops, 1 != rw_opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::numpunct<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::numpunct<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise the thread safety
|
||||
// of the wchar_t specialization
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::numpunct<char> and std::numpunct<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.numpunct",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&opt_shared_locale);
|
||||
}
|
||||
199
extern/stdcxx/4.2.1/tests/localization/22.locale.statics.mt.cpp
vendored
Normal file
199
extern/stdcxx/4.2.1/tests/localization/22.locale.statics.mt.cpp
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.statics.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of [lib.locale.statics]
|
||||
*
|
||||
* $Id: 22.locale.statics.mt.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.
|
||||
*
|
||||
* Copyright 2007 Rogue Wave Software, Inc.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <locale> // for locale
|
||||
#include <cstring> // for strlen()
|
||||
|
||||
#include <rw_locale.h> // for rw_locales()
|
||||
#include <rw_thread.h> // for rw_get_processors(), rw_thread_pool()
|
||||
#include <driver.h> // for rw_test()
|
||||
|
||||
|
||||
// maximum number of threads allowed by the command line interface
|
||||
#define MAX_THREADS 16
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate (unless specified
|
||||
// otherwise on the command line)
|
||||
int opt_nloops = 20000;
|
||||
|
||||
int opt_classic;
|
||||
int opt_global;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale objects to use for testing
|
||||
static std::locale
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void*
|
||||
test_classic (void*)
|
||||
{
|
||||
static volatile int nthreads;
|
||||
|
||||
// cast nthreads to int& (see STDCXX-792)
|
||||
// casting should be removed after fixing STDCXX-794
|
||||
_RWSTD_ATOMIC_PREINCREMENT (_RWSTD_CONST_CAST (int&, nthreads), false);
|
||||
|
||||
// spin until all threads have been created in order to icrease
|
||||
// the odds that at least two of them will hit the tested function
|
||||
// (and the lazy one-time initialization done by it) at the same
|
||||
// time
|
||||
while (nthreads < opt_nthreads);
|
||||
|
||||
const std::locale classic (std::locale::classic ());
|
||||
|
||||
_RWSTD_UNUSED (classic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void*
|
||||
test_global (void*)
|
||||
{
|
||||
for (std::size_t i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
const std::size_t inx = i % nlocales;
|
||||
|
||||
const std::locale last (std::locale::global (locales [inx]));
|
||||
|
||||
_RWSTD_UNUSED (last);
|
||||
|
||||
// FIXME: verify the consistency of the returned locale
|
||||
// by making sure that it matches the locale passed to
|
||||
// global() made by the last call to the function by
|
||||
// the last thread
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (rw_note (0 <= opt_classic, 0, __LINE__,
|
||||
"std::locale::classic() test disabled")) {
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::locale::classic() with %d thread%{?}s%{;}",
|
||||
opt_nthreads, 1 != opt_nthreads);
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
|
||||
test_classic, 0);
|
||||
}
|
||||
|
||||
if (rw_note (0 <= opt_global, 0, __LINE__,
|
||||
"std::locale::global(const std::locale&) test disabled")) {
|
||||
|
||||
|
||||
// find all installed locales for which setlocale(LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = sizeof locales / sizeof *locales;
|
||||
|
||||
const char* locale_names [MAX_THREADS];
|
||||
|
||||
for (const char *name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
locale_names [nlocales] = name;
|
||||
locales [nlocales++] = std::locale (name);
|
||||
|
||||
if (nlocales == maxinx)
|
||||
break;
|
||||
}
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::locale::global(const std::locale&) with "
|
||||
"%d thread%{?}s%{;}, %d iteration%{?}s%{;} each, in "
|
||||
"%zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locale_names);
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
|
||||
test_global, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.statics",
|
||||
"thread safety",
|
||||
run_test,
|
||||
"|-classic~ "
|
||||
"|-global~ "
|
||||
"|-nloops#0 " // arg must be non-negative
|
||||
"|-nthreads#0-* " // arg must be in [0, MAX_THREADS]
|
||||
"|-locales= ", // argument must be provided
|
||||
&opt_classic,
|
||||
&opt_global,
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&rw_opt_setlocales);
|
||||
}
|
||||
1680
extern/stdcxx/4.2.1/tests/localization/22.locale.time.get.cpp
vendored
Normal file
1680
extern/stdcxx/4.2.1/tests/localization/22.locale.time.get.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
527
extern/stdcxx/4.2.1/tests/localization/22.locale.time.get.mt.cpp
vendored
Normal file
527
extern/stdcxx/4.2.1/tests/localization/22.locale.time.get.mt.cpp
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.time.get.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the time_get facet
|
||||
*
|
||||
* $Id: 22.locale.time.get.mt.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.
|
||||
*
|
||||
* Copyright 2002-2007 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
#include <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, time_put
|
||||
#include <cstring> // for strlen ()
|
||||
#include <ctime> // for tm
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h> // for rw_assert ()
|
||||
#include <valcmp.h> // for rw_strncmp ()
|
||||
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int rw_opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate
|
||||
int rw_opt_nloops = 50000;
|
||||
|
||||
// number of locales to use
|
||||
int rw_opt_nlocales = MAX_THREADS;
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int rw_opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
//
|
||||
struct MyTimeData
|
||||
{
|
||||
enum { BufferSize = 64 };
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// the time struct used to generate strings below
|
||||
std::tm time_;
|
||||
|
||||
// the type specifier
|
||||
char format_;
|
||||
|
||||
// narrow representations of time_ given the
|
||||
// locale_name_ and the format_
|
||||
char ncs_ [BufferSize];
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
// wide representations of time_
|
||||
wchar_t wcs_ [BufferSize];
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} my_time_data [MAX_THREADS];
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyIos: std::basic_ios<charT, Traits>
|
||||
{
|
||||
MyIos () {
|
||||
this->init (0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyStreambuf: std::basic_streambuf<charT, Traits>
|
||||
{
|
||||
typedef std::basic_streambuf<charT, Traits> Base;
|
||||
|
||||
MyStreambuf ()
|
||||
: Base () {
|
||||
}
|
||||
|
||||
void pubsetg (const charT *gbeg, std::streamsize n) {
|
||||
this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
|
||||
_RWSTD_CONST_CAST (charT*, gbeg),
|
||||
_RWSTD_CONST_CAST (charT*, gbeg) + n);
|
||||
}
|
||||
|
||||
void pubsetp (charT *pbeg, std::streamsize n) {
|
||||
this->setp (pbeg, pbeg + n);
|
||||
}
|
||||
};
|
||||
|
||||
void verify_fields (const std::tm& a, const std::tm& b)
|
||||
{
|
||||
RW_ASSERT (a.tm_sec == b.tm_sec);
|
||||
RW_ASSERT (a.tm_min == b.tm_min);
|
||||
RW_ASSERT (a.tm_hour == b.tm_hour);
|
||||
RW_ASSERT (a.tm_mday == b.tm_mday);
|
||||
RW_ASSERT (a.tm_mon == b.tm_mon);
|
||||
RW_ASSERT (a.tm_year == b.tm_year);
|
||||
RW_ASSERT (a.tm_wday == b.tm_wday);
|
||||
RW_ASSERT (a.tm_yday == b.tm_yday);
|
||||
}
|
||||
#define RW_ASSERT_FIELDS(a,b) verify_fields(a,b)
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise time_get<char>
|
||||
bool test_wchar; // exercise time_get<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
std::ios_base::iostate state = std::ios_base::goodbit;
|
||||
|
||||
std::tm local;
|
||||
for (int i = 0; i != rw_opt_nloops; ++i) {
|
||||
|
||||
// save the name of the locale
|
||||
const MyTimeData& data = my_time_data [i % nlocales];
|
||||
|
||||
// construct a named locale, get a reference to the time_put
|
||||
// facet from it and use it to format a random time value
|
||||
// using a random conversion specifier
|
||||
const std::locale loc =
|
||||
rw_opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::time_get<char> &ng =
|
||||
std::use_facet<std::time_get<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
const std::istreambuf_iterator<char> iter (&nsb);
|
||||
const std::istreambuf_iterator<char> end;
|
||||
|
||||
std::memset (&local, 0, sizeof local);
|
||||
|
||||
switch (data.format_) {
|
||||
case 'X':
|
||||
ng.get_time (iter, end, nio, state, &local);
|
||||
break;
|
||||
case 'x':
|
||||
ng.get_date (iter, end, nio, state, &local);
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
ng.get_weekday (iter, end, nio, state, &local);
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
ng.get_monthname (iter, end, nio, state, &local);
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
ng.get_year (iter, end, nio, state, &local);
|
||||
break;
|
||||
default:
|
||||
|
||||
#ifndef _RWSTD_NO_EXT_TIME_GET
|
||||
ng.get (iter, end, nio, state, &local, data.format_);
|
||||
#endif // _RWSTD_NO_EXT_TIME_GET
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT_FIELDS (local, data.time_);
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::time_get<wchar_t> &wg =
|
||||
std::use_facet<std::time_get<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
const std::istreambuf_iterator<wchar_t> iter (&wsb);
|
||||
const std::istreambuf_iterator<wchar_t> end;
|
||||
|
||||
std::memset (&local, 0, sizeof local);
|
||||
|
||||
switch (data.format_) {
|
||||
case 'X':
|
||||
wg.get_time (iter, end, wio, state, &local);
|
||||
break;
|
||||
case 'x':
|
||||
wg.get_date (iter, end, wio, state, &local);
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
wg.get_weekday (iter, end, wio, state, &local);
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
wg.get_monthname (iter, end, wio, state, &local);
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
wg.get_year (iter, end, wio, state, &local);
|
||||
break;
|
||||
default:
|
||||
|
||||
#ifndef _RWSTD_NO_EXT_TIME_GET
|
||||
wg.get (iter, end, wio, state, &local, data.format_);
|
||||
#endif // _RWSTD_NO_EXT_TIME_GET
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
RW_ASSERT (! (state & std::ios_base::failbit));
|
||||
RW_ASSERT_FIELDS (local, data.time_);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
// find all installed locales for which setlocale (LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
int j = 0;
|
||||
for (const char* name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the time and results for this locale
|
||||
MyTimeData& data = my_time_data [inx];
|
||||
data.locale_name_ = name;
|
||||
|
||||
// initialize tm with random but valid values
|
||||
std::memset (&data.time_, 0, sizeof data.time_);
|
||||
data.time_.tm_sec = ++j % 61;
|
||||
data.time_.tm_min = ++j % 60;
|
||||
data.time_.tm_hour = ++j % 12;
|
||||
data.time_.tm_wday = ++j % 7;
|
||||
data.time_.tm_mon = ++j % 12;
|
||||
data.time_.tm_mday = ++j % 31;
|
||||
data.time_.tm_yday = ++j % 366;
|
||||
data.time_.tm_year = ++j;
|
||||
|
||||
#ifndef _RWSTD_NO_EXT_TIME_GET
|
||||
// format specifiers that we can reliably parse
|
||||
// get_weekday, get_monthname, get_date, get_time,
|
||||
// get_year and the extension get.
|
||||
const char formats [] = "aAbBCdhHjmMnRStTwxXyY";
|
||||
#else
|
||||
// formats that generate strings compatible with
|
||||
// get_weekday, get_monthname, get_date, get_time
|
||||
// and get_year.
|
||||
const char formats [] = "aAbBxXyY";
|
||||
#endif
|
||||
|
||||
// get the "random" data type used to generate representation
|
||||
data.format_ = formats [nlocales % (sizeof formats - 1)];
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
const std::time_put<char> &np =
|
||||
std::use_facet<std::time_put<char> >(loc);
|
||||
|
||||
const std::time_get<char> &ng =
|
||||
std::use_facet<std::time_get<char> >(loc);
|
||||
|
||||
std::ios::iostate state = std::ios::goodbit;
|
||||
|
||||
nio.imbue (loc);
|
||||
|
||||
// put the time representation on the stream
|
||||
nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb), nio, ' ',
|
||||
&data.time_, data.format_) = '\0';
|
||||
|
||||
rw_fatal (!nio.fail (), __FILE__, __LINE__,
|
||||
"time_put<char>::put(...) failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
// read the data back out. this is what the thread
|
||||
// is expected to do, and the result it should get.
|
||||
|
||||
nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
const std::istreambuf_iterator<char> iter (&nsb);
|
||||
const std::istreambuf_iterator<char> end;
|
||||
|
||||
std::memset (&data.time_, 0, sizeof data.time_);
|
||||
|
||||
switch (data.format_) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
ng.get_weekday (iter, end, nio, state, &data.time_);
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'h':
|
||||
ng.get_monthname (iter, end, nio, state, &data.time_);
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
ng.get_year (iter, end, nio, state, &data.time_);
|
||||
break;
|
||||
case 'x':
|
||||
ng.get_date (iter, end, nio, state, &data.time_);
|
||||
break;
|
||||
case 'X':
|
||||
ng.get_time (iter, end, nio, state, &data.time_);
|
||||
break;
|
||||
default:
|
||||
|
||||
#ifndef _RWSTD_NO_EXT_TIME_GET
|
||||
ng.get (iter, end, nio, state, &data.time_, data.format_);
|
||||
#endif // _RWSTD_NO_EXT_TIME_GET
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// we couldn't read the data back, so don't use this locale
|
||||
if (state & std::ios_base::failbit)
|
||||
continue;
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::time_put<wchar_t> &wp =
|
||||
std::use_facet<std::time_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
wio, L' ', &data.time_, data.format_) = L'\0';
|
||||
|
||||
rw_fatal (!wio.fail (), __FILE__, __LINE__,
|
||||
"time_put<wchar_t>::put(...) failed for locale(%#s)",
|
||||
data.locale_name_);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (rw_opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::time_get<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
rw_opt_nthreads, 1 != rw_opt_nthreads,
|
||||
rw_opt_nloops, 1 != rw_opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::time_get<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::time_get<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::time_get<char> and std::time_get<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
rw_opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
rw_opt_nthreads = rw_get_cpus ();
|
||||
if (rw_opt_nthreads < 2)
|
||||
rw_opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.time.get",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&rw_opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&rw_opt_nthreads,
|
||||
&rw_opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&rw_opt_shared_locale);
|
||||
}
|
||||
2060
extern/stdcxx/4.2.1/tests/localization/22.locale.time.put.cpp
vendored
Normal file
2060
extern/stdcxx/4.2.1/tests/localization/22.locale.time.put.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
405
extern/stdcxx/4.2.1/tests/localization/22.locale.time.put.mt.cpp
vendored
Normal file
405
extern/stdcxx/4.2.1/tests/localization/22.locale.time.put.mt.cpp
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 22.locale.time.put.mt.cpp
|
||||
*
|
||||
* test exercising the thread safety of the time_put facet
|
||||
*
|
||||
* $Id: 22.locale.time.put.mt.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.
|
||||
*
|
||||
* Copyright 2002-2007 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <ios> // for ios
|
||||
#include <iterator> // for ostreambuf_iterator
|
||||
#include <locale> // for locale, time_put
|
||||
|
||||
#include <cstring> // for strlen ()
|
||||
#include <ctime> // for tm
|
||||
|
||||
#include <rw_locale.h>
|
||||
#include <rw_thread.h>
|
||||
#include <driver.h> // for rw_assert ()
|
||||
#include <valcmp.h> // for rw_strncmp ()
|
||||
|
||||
#define MAX_THREADS 32
|
||||
#define MAX_LOOPS 100000
|
||||
|
||||
// default number of threads (will be adjusted to the number
|
||||
// of processors/cores later)
|
||||
int opt_nthreads = 1;
|
||||
|
||||
// the number of times each thread should iterate
|
||||
int opt_nloops = MAX_LOOPS;
|
||||
|
||||
#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
|
||||
|
||||
// number of locales to use
|
||||
int opt_nlocales = MAX_THREADS;
|
||||
|
||||
#else // HP-UX in LP64 mode
|
||||
|
||||
// work around an inefficiency (small cache size?) on HP-UX
|
||||
// in LP64 mode (see STDCXX-812)
|
||||
int opt_nlocales = 10;
|
||||
|
||||
#endif // HP-UX 32/64 bit mode
|
||||
|
||||
// should all threads share the same set of locale objects instead
|
||||
// of creating their own?
|
||||
int opt_shared_locale;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// array of locale names to use for testing
|
||||
static const char*
|
||||
locales [MAX_THREADS];
|
||||
|
||||
// number of locale names in the array
|
||||
static std::size_t
|
||||
nlocales;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
//
|
||||
struct MyTimeData
|
||||
{
|
||||
enum { BufferSize = 64 };
|
||||
|
||||
// name of the locale the data corresponds to
|
||||
const char* locale_name_;
|
||||
|
||||
// optionally set to the named locale for threads to share
|
||||
std::locale locale_;
|
||||
|
||||
// the time struct used to generate strings below
|
||||
std::tm time_;
|
||||
|
||||
// the format specifier
|
||||
char format_;
|
||||
|
||||
// narrow representations of time_ given the
|
||||
// locale_name_ and the format_
|
||||
char ncs_ [BufferSize];
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
// wide representations of time_
|
||||
wchar_t wcs_ [BufferSize];
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
} my_time_data [MAX_THREADS];
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyIos: std::basic_ios<charT, Traits>
|
||||
{
|
||||
MyIos () {
|
||||
this->init (0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class charT, class Traits>
|
||||
struct MyStreambuf: std::basic_streambuf<charT, Traits>
|
||||
{
|
||||
typedef std::basic_streambuf<charT, Traits> Base;
|
||||
|
||||
MyStreambuf ()
|
||||
: Base () {
|
||||
}
|
||||
|
||||
void pubsetp (charT *pbeg, std::streamsize n) {
|
||||
this->setp (pbeg, pbeg + n);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool test_char; // exercise time_put<char>
|
||||
bool test_wchar; // exercise time_put<wchar_t>
|
||||
|
||||
|
||||
static void*
|
||||
thread_func (void*)
|
||||
{
|
||||
char ncs [MyTimeData::BufferSize];
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
wchar_t wcs [MyTimeData::BufferSize];
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
for (int i = 0; i != opt_nloops; ++i) {
|
||||
|
||||
// save the name of the locale
|
||||
const MyTimeData& data = my_time_data [i % nlocales];
|
||||
|
||||
// construct a named locale, get a reference to the time_put
|
||||
// facet from it and use it to format a random time value
|
||||
// using a random conversion specifier
|
||||
const std::locale loc =
|
||||
opt_shared_locale ? data.locale_
|
||||
: std::locale (data.locale_name_);
|
||||
|
||||
if (test_char) {
|
||||
// exercise the narrow char specialization of the facet
|
||||
|
||||
const std::time_put<char> &tp =
|
||||
std::use_facet<std::time_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
|
||||
|
||||
// format time using provided format specifier
|
||||
*tp.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
nio, ' ', &data.time_, data.format_) = '\0';
|
||||
|
||||
RW_ASSERT (!nio.fail ());
|
||||
RW_ASSERT (!rw_strncmp(ncs, data.ncs_));
|
||||
|
||||
}
|
||||
|
||||
// both specializations may be tested at the same time
|
||||
|
||||
if (test_wchar) {
|
||||
// exercise the wide char specialization of the facet
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::time_put<wchar_t> &wp =
|
||||
std::use_facet<std::time_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
|
||||
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
wio, L' ', &data.time_, data.format_) = L'\0';
|
||||
|
||||
RW_ASSERT (!wio.fail ());
|
||||
RW_ASSERT (!rw_strncmp(wcs, data.wcs_));
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int, char**)
|
||||
{
|
||||
MyIos<char, std::char_traits<char> > nio;
|
||||
MyStreambuf<char, std::char_traits<char> > nsb;
|
||||
nio.rdbuf (&nsb);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
MyIos<wchar_t, std::char_traits<wchar_t> > wio;
|
||||
MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
|
||||
wio.rdbuf (&wsb);
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
// find all installed locales for which setlocale (LC_ALL) succeeds
|
||||
const char* const locale_list =
|
||||
rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
|
||||
|
||||
const std::size_t maxinx = RW_COUNT_OF (locales);
|
||||
|
||||
int j = 0;
|
||||
for (const char* name = locale_list;
|
||||
*name;
|
||||
name += std::strlen (name) + 1) {
|
||||
|
||||
const std::size_t inx = nlocales;
|
||||
locales [inx] = name;
|
||||
|
||||
// fill in the time and results for this locale
|
||||
MyTimeData& data = my_time_data [inx];
|
||||
data.locale_name_ = name;
|
||||
|
||||
// initialize tm with random but valid values
|
||||
data.time_.tm_sec = ++j % 61;
|
||||
data.time_.tm_min = ++j % 60;
|
||||
data.time_.tm_hour = ++j % 12;
|
||||
data.time_.tm_wday = ++j % 7;
|
||||
data.time_.tm_mon = ++j % 12;
|
||||
data.time_.tm_mday = ++j % 31;
|
||||
data.time_.tm_yday = ++j % 366;
|
||||
data.time_.tm_year = ++j;
|
||||
|
||||
const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%";
|
||||
|
||||
// get the "random" conversion specifier used to generate
|
||||
// the result string
|
||||
data.format_ = cvtspecs [nlocales % (sizeof cvtspecs - 1)];
|
||||
|
||||
try {
|
||||
const std::locale loc (data.locale_name_);
|
||||
|
||||
const std::time_put<char> &np =
|
||||
std::use_facet<std::time_put<char> >(loc);
|
||||
|
||||
nio.imbue (loc);
|
||||
nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
|
||||
|
||||
*np.put (std::ostreambuf_iterator<char>(&nsb),
|
||||
nio, ' ', &data.time_, data.format_) = '\0';
|
||||
|
||||
rw_fatal (!nio.fail (), __FILE__, __LINE__,
|
||||
"time_put<char>::put(..., %c) "
|
||||
"failed for locale(%#s)",
|
||||
data.format_, data.locale_name_);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
const std::time_put<wchar_t> &wp =
|
||||
std::use_facet<std::time_put<wchar_t> >(loc);
|
||||
|
||||
wio.imbue (loc);
|
||||
wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
|
||||
|
||||
*wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
|
||||
wio, L' ', &data.time_, data.format_) = L'\0';
|
||||
|
||||
rw_fatal (!wio.fail (), __FILE__, __LINE__,
|
||||
"time_put<wchar_t>::put(..., %c) "
|
||||
"failed for locale(%#s)",
|
||||
data.format_, data.locale_name_);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
if (opt_shared_locale)
|
||||
data.locale_ = loc;
|
||||
|
||||
nlocales += 1;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
rw_warn (!rw_opt_locales, 0, __LINE__,
|
||||
"failed to create locale(%#s)", name);
|
||||
}
|
||||
|
||||
if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid divide by zero in thread if there are no locales to test
|
||||
rw_fatal (nlocales != 0, 0, __LINE__,
|
||||
"failed to create one or more usable locales!");
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"testing std::time_put<charT> with %d thread%{?}s%{;}, "
|
||||
"%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
|
||||
opt_nthreads, 1 != opt_nthreads,
|
||||
opt_nloops, 1 != opt_nloops,
|
||||
nlocales, int (nlocales), "%#s", locales);
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::time_put<char>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = false;
|
||||
|
||||
// create and start a pool of threads and wait for them to finish
|
||||
int result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#ifndef _RWSTD_NO_WCHAR_T
|
||||
|
||||
rw_info (0, 0, 0, "exercising std::time_put<wchar_t>");
|
||||
|
||||
test_char = false;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
// exercise both the char and the wchar_t specializations
|
||||
// at the same time
|
||||
|
||||
rw_info (0, 0, 0,
|
||||
"exercising both std::time_put<char> and std::time_put<wchar_t>");
|
||||
|
||||
test_char = true;
|
||||
test_wchar = true;
|
||||
|
||||
// start a pool of threads to exercise wstring thread safety
|
||||
result =
|
||||
rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
|
||||
|
||||
rw_error (result == 0, 0, __LINE__,
|
||||
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
|
||||
opt_nthreads, thread_func);
|
||||
|
||||
#endif // _RWSTD_NO_WCHAR_T
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef _RWSTD_REENTRANT
|
||||
|
||||
// set nthreads to the greater of the number of processors
|
||||
// and 2 (for uniprocessor systems) by default
|
||||
opt_nthreads = rw_get_cpus ();
|
||||
if (opt_nthreads < 2)
|
||||
opt_nthreads = 2;
|
||||
|
||||
#endif // _RWSTD_REENTRANT
|
||||
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.locale.time.put",
|
||||
"thread safety", run_test,
|
||||
"|-nloops#0 " // must be non-negative
|
||||
"|-nthreads#0-* " // must be in [0, MAX_THREADS]
|
||||
"|-nlocales#0 " // arg must be non-negative
|
||||
"|-locales= " // must be provided
|
||||
"|-shared-locale# ",
|
||||
&opt_nloops,
|
||||
int (MAX_THREADS),
|
||||
&opt_nthreads,
|
||||
&opt_nlocales,
|
||||
&rw_opt_setlocales,
|
||||
&opt_shared_locale);
|
||||
}
|
||||
Reference in New Issue
Block a user