You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2007/06/28 00:19:31 UTC
svn commit: r551354 -
/incubator/stdcxx/trunk/tests/localization/22.locale.moneypunct.mt.cpp
Author: sebor
Date: Wed Jun 27 15:19:30 2007
New Revision: 551354
URL: http://svn.apache.org/viewvc?view=rev&rev=551354
Log:
2007-06-27 Martin Sebor <se...@roguewave.com>
* 22.locale.moneypunct.mt.cpp: Rewrote so as not to rely on localeconv
but retrieve the "master" data from the C++ locale instead instead.
(thread_loop_body): Factored out the body of thread_func here.
(get_format): Removed.
(rw_opt_nloops): Reduced from 2000000 to 10000 and set to the number
of tested locales in non-reentrant configurations to speed things up.
(rw_opt_setlocales): Callback function to process --locales option.
(main): Set rw_opt_nthreads to rw_get_cpus() in thread-safe configs.
(--locale=<arg>): New command line option to specify the names of
locales to test.
Modified:
incubator/stdcxx/trunk/tests/localization/22.locale.moneypunct.mt.cpp
Modified: incubator/stdcxx/trunk/tests/localization/22.locale.moneypunct.mt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.moneypunct.mt.cpp?view=diff&rev=551354&r1=551353&r2=551354
==============================================================================
--- incubator/stdcxx/trunk/tests/localization/22.locale.moneypunct.mt.cpp (original)
+++ incubator/stdcxx/trunk/tests/localization/22.locale.moneypunct.mt.cpp Wed Jun 27 15:19:30 2007
@@ -29,9 +29,8 @@
#include <ios> // for ios
#include <locale> // for locale, moneypunct
-#include <clocale> // for lconv, localeconv()
-#include <cstdlib> // for mbstowcs()
-#include <cstring> // for size_t, strcpy()
+#include <cstdlib> // for mbstowcs(), size_t
+#include <cstring> // for strcpy()
#include <rw_locale.h>
#include <rw_thread.h>
@@ -42,17 +41,16 @@
// maximum number of threads allowed by the command line interface
#define MAX_THREADS 32
-
-#ifdef _RWSTD_REENTRANT
-int rw_opt_nthreads = 4;
-#else // if !defined (_RWSTD_REENTRANT)
-// in non-threaded builds use just one thread
+// default number of threads (will be adjusted to the number
+// of processors/cores later)
int rw_opt_nthreads = 1;
-#endif // _RWSTD_REENTRANT
-// the number of times each thread should iterate (unless specified
-// otherwise on the command line)
-int rw_opt_nloops = 200000;
+// 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;
/**************************************************************************/
@@ -97,147 +95,154 @@
} 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*)
+static void
+thread_loop_body (std::size_t i)
{
- for (int i = 0; i != rw_opt_nloops; ++i) {
+ const std::size_t inx = std::size_t (i) % (nlocales ? nlocales : 1);
- const std::size_t inx = std::size_t (i) % nlocales;
+ const MoneypunctData* const data = punct_data + inx;
- const MoneypunctData* const data = punct_data + inx;
+ // construct a named locale
+ const std::locale loc (data->locale_name_);
- // 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_));
- 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));
+ }
- 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
- if (test_char) {
- // exercise the narrow char, international specialization
+ typedef std::moneypunct<char, true> Punct;
- typedef std::moneypunct<char, true> Punct;
+ const Punct &mp = std::use_facet<Punct>(loc);
- 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_));
- 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 (!std::memcmp (&pfm, data->int_pos_format_, 4));
+ RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
+ }
- 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_));
+ // both specializations may be tested at the same time
- RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
- RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
- }
+#ifndef _RWSTD_NO_WCHAR_T
- // both specializations may be tested at the same time
+ if (test_wchar) {
+ // exercise the wide char, local specialization of the facet
-#ifndef _RWSTD_NO_WCHAR_T
+ typedef std::moneypunct<wchar_t, false> Punct;
- if (test_wchar) {
- // exercise the wide char, local specialization of the facet
+ const Punct &mp = std::use_facet<Punct>(loc);
- typedef std::moneypunct<wchar_t, false> Punct;
+ const char dp = mp.decimal_point ();
+ const char 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_));
- const Punct &mp = std::use_facet<Punct>(loc);
+ RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
+ RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
+ }
- const char dp = mp.decimal_point ();
- const char 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 ();
+ if (test_wchar) {
+ // exercise the wide char, international specialization
- 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_));
+ typedef std::moneypunct<wchar_t, true> Punct;
- RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
- RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
- }
+ const Punct &mp = std::use_facet<Punct>(loc);
- if (test_wchar) {
- // exercise the wide char, international specialization
+ const char dp = mp.decimal_point ();
+ const char 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_));
- typedef std::moneypunct<wchar_t, true> Punct;
+ RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
+ RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
+ }
- const Punct &mp = std::use_facet<Punct>(loc);
+#endif // _RWSTD_NO_WCHAR_T
- const char dp = mp.decimal_point ();
- const char 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));
- }
+extern "C" {
-#endif // _RWSTD_NO_WCHAR_T
+static void*
+thread_func (void*)
+{
+ for (int i = 0; i != rw_opt_nloops; ++i) {
+ thread_loop_body (std::size_t (i));
}
return 0;
@@ -247,154 +252,16 @@
/**************************************************************************/
-static void
-get_format (MoneypunctData *pdata, const std::lconv *pconv)
-{
- // code copied from src/punct.cpp
-
- enum {
- // for syntactic convenience
- 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 pat[] = {
-
- // 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.
-
- // +-------- cs_precedes
- // |+----- sep_by_space
- // ||+-- sign_posn
- // |||
- // VVV .... - 1 $ . // pattern
- /* 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\1\4\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"
- };
-
- std::size_t inx;
-
- inx = std::size_t (pconv->p_cs_precedes) * (3U * 5U)
- + std::size_t (pconv->p_sep_by_space) * 5U
- + std::size_t (pconv->p_sign_posn);
-
- if (inx < sizeof pat / sizeof *pat)
- std::memcpy (pdata->pos_format_, pat + inx, sizeof *pat);
- else
- std::memset (pdata->pos_format_, none, sizeof *pat);
-
- inx = std::size_t (pconv->n_cs_precedes) * (3U * 5U)
- + std::size_t (pconv->n_sep_by_space) * 5U
- + std::size_t (pconv->n_sign_posn);
-
- if (inx < sizeof pat / sizeof *pat)
- std::memcpy (pdata->neg_format_, pat + inx, sizeof *pat);
- else
- std::memset (pdata->neg_format_, none, sizeof *pat);
-
-
-#ifndef _RWSTD_NO_LCONV_INT_FMAT
-
- inx = std::size_t (pconv->int_p_cs_precedes) * (3U * 5U)
- + std::size_t (pconv->int_p_sep_by_space) * 5U
- + std::size_t (pconv->int_p_sign_posn);
-
- if (inx < sizeof pat / sizeof *pat)
- std::memcpy (pdata->int_pos_format_, pat + inx, sizeof *pat);
- else
- std::memset (pdata->int_pos_format_, none, sizeof *pat);
-
- inx = std::size_t (pconv->int_n_cs_precedes) * (3U * 5U)
- + std::size_t (pconv->int_n_sep_by_space) * 5U
- + std::size_t (pconv->int_n_sign_posn);
-
- if (inx < sizeof pat / sizeof *pat)
- memcpy (pdata->int_neg_format_, pat + inx, sizeof *pat);
- else
- memset (pdata->int_neg_format_, none, sizeof *pat);
-
- std::strcpy (pdata->int_curr_symbol_, pconv->int_curr_symbol);
-
- pdata->int_frac_digits_ = pconv->int_frac_digits;
-
-#else // if defined (_RWSTD_NO_LCONV_INT_FMAT)
-
- std::strcpy (pdata->int_curr_symbol_, pconv->curr_symbol);
-
- pdata->int_frac_digits_ = pconv->frac_digits;
-
-#endif // _RWSTD_NO_LCONV_INT_FMAT
-
-}
+static char*
+rw_opt_locales;
static int
run_test (int, char**)
{
- // get a NUL-separated list of names of installed locales
- char* const locale_list = rw_locales ();
+ // find all installed locales for which setlocale(LC_ALL) succeeds
+ 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];
@@ -404,76 +271,144 @@
// iterate over locales, initializing a global punct_data array
for (char *name = locale_list; *name; name += std::strlen (name) + 1) {
- const std::size_t inx = nlocales;
+ std::locale loc;
- // set LC_NUMERIC and LC_CTYPE to be able to use mbstowcs()
- if (std::setlocale (LC_ALL, name)) {
+ MoneypunctData* const pdata = punct_data + nlocales;
- const std::lconv* const pconv = std::localeconv ();
- MoneypunctData* const pdata = punct_data + inx;
+ pdata->locale_name_ = name;
+ locales [nlocales] = name;
- locales [inx] = pdata->locale_name_ = name;
+ try {
+ loc = std::locale (name);
- // assign just the first character of the (potentially)
- // multibyte decimal_point and thousands_sep (C++ locale
- // can't deal with more)
- pdata->decimal_point_ = *pconv->mon_decimal_point;
- pdata->thousands_sep_ = *pconv->mon_thousands_sep;
+ typedef std::moneypunct<char, false> Punct;
+
+ const Punct &mp = std::use_facet<Punct>(loc);
- pdata->frac_digits_ = pconv->frac_digits;
+ 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 ();
- // simply copy the narrow grouping, currency symbols,
- // and signs
- std::strcpy (pdata->grouping_, pconv->mon_grouping);
- std::strcpy (pdata->curr_symbol_, pconv->currency_symbol);
- std::strcpy (pdata->negative_sign_, pconv->negative_sign);
- std::strcpy (pdata->positive_sign_, pconv->positive_sign);
- std::strcpy (pdata->grouping_, pconv->mon_grouping);
+ pdata->int_frac_digits_ = fd;
- get_format (pdata, pconv);
+ 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_WCHAR_T
+#ifndef _RWSTD_NO_WCHAR_T
- wchar_t tmp [2];
+ try {
+ typedef std::moneypunct<wchar_t, false> Punct;
- // convert multibyte decimal point and thousands separator
- // to wide characters (assumes they are single character
- // each -- C++ locale can't handle more)
- std::mbstowcs (tmp, pconv->mon_decimal_point, 2);
- pdata->wdecimal_point_ = tmp [0];
+ const Punct &mp = std::use_facet<Punct>(loc);
- std::mbstowcs (tmp, pconv->mon_thousands_sep, 2);
- pdata->wthousands_sep_ = tmp [0];
+ 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;
+ }
- const std::size_t n =
- sizeof pdata->wcurr_symbol_ / sizeof (wchar_t);
+ try {
+ typedef std::moneypunct<wchar_t, true> Punct;
- std::mbstowcs (pdata->wcurr_symbol_, pdata->curr_symbol_, n);
- std::mbstowcs (pdata->wnegative_sign_, pdata->negative_sign_, n);
- std::mbstowcs (pdata->wpositive_sign_, pdata->positive_sign_, n);
+ const Punct &mp = std::use_facet<Punct>(loc);
- std::mbstowcs (pdata->wint_curr_symbol_,
- pdata->int_curr_symbol_,
- n);
+ const std::wstring cur = mp.curr_symbol ();
+ const std::wstring pos = mp.positive_sign ();
+ const std::wstring neg = mp.negative_sign ();
-#endif // _RWSTD_WCHAR_T
+ typedef std::wstring::traits_type Traits;
- ++nlocales;
+ 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;
}
- // reset the global locale
- std::setlocale (LC_ALL, "C");
+ // 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%{;}, "
- "%zu iteration%{?}s%{;} each, in locales { %{ .*A@} }",
+ "%zu iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
rw_opt_nthreads, 1 != rw_opt_nthreads,
rw_opt_nloops, 1 != rw_opt_nloops,
- int (nlocales), "%#s", locales);
+ nlocales, int (nlocales), "%#s", locales);
rw_info (0, 0, 0, "exercising std::moneypunct<char>");
@@ -529,14 +464,54 @@
/**************************************************************************/
+static int
+rw_opt_setlocales (int argc, char* argv[])
+{
+ RW_ASSERT (0 < argc && argv [0]);
+
+ rw_opt_locales = std::strchr (argv [0], '=');
+
+ if (rw_opt_locales) {
+
+ const std::size_t len = std::strlen (++rw_opt_locales);
+ char* const locale_names = new char [len + 2];
+
+ locale_names [len + 1] = '\0';
+
+ std::memcpy (locale_names, rw_opt_locales, len);
+
+ rw_opt_locales = locale_names;
+
+ for (char *next = rw_opt_locales; ; ) {
+ next = std::strpbrk (next, ", ");
+ if (next)
+ *next++ = '\0';
+ else
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
int main (int argc, char *argv[])
{
+#ifdef _RWSTD_REENTRANT
+
+ // set nthreads to the number of processors by default
+ rw_opt_nthreads = rw_get_cpus ();
+
+#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]
+ "|-nthreads#0-*" // must be in [0, MAX_THREADS]
+ "|-locales=", // must be provided
&rw_opt_nloops,
int (MAX_THREADS),
- &rw_opt_nthreads);
+ &rw_opt_nthreads,
+ &rw_opt_setlocales);
}