Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.moneypunct.mt.cpp
Go to the documentation of this file.
1
29#include <ios> // for ios
30#include <locale> // for locale, moneypunct
31
32#include <cstdlib> // for mbstowcs(), size_t
33#include <cstring> // for strcpy()
34
35#include <rw_locale.h>
36#include <rw_thread.h>
37#include <rw_driver.h>
38#include <rw_valcmp.h>
39
40
41// maximum number of threads allowed by the command line interface
42#define MAX_THREADS 32
43
44// default number of threads (will be adjusted to the number
45// of processors/cores later)
47
48// the default number of times for each thread to iterate
49#define DFLT_LOOPS 10000
50
51// the number of times each thread should iterate (will be set to
52// DFLT_LOOPS unless explicitly specified on the command line)
53int opt_nloops = -1;
54
55// default timeout used by each threaded section of this test
56int opt_timeout = 60;
57
58
60// number of locales to test
61static std::size_t
63
64
67{
68 // the name of the locale the data goes with
69 const char* locale_name_;
70
73 char grouping_ [32];
74 char curr_symbol_ [32];
75 char positive_sign_ [32];
76 char negative_sign_ [32];
78 char pos_format_ [32];
79 char neg_format_ [32];
80
82
84 char int_pos_format_ [32];
85 char int_neg_format_ [32];
86
87#ifndef _RWSTD_NO_WCHAR_T
88
91 wchar_t wcurr_symbol_ [32];
92 wchar_t wpositive_sign_ [32];
93 wchar_t wnegative_sign_ [32];
94
95 wchar_t wint_curr_symbol_ [32];
96
97#endif // _RWSTD_NO_WCHAR_T
98
100
101
103bool test_char; // exercise num_put<char>
104bool test_wchar; // exercise num_put<wchar_t>
105
106static void
107thread_loop_body (std::size_t i)
108{
109 const std::size_t inx = std::size_t (i) % (nlocales ? nlocales : 1);
110
111 const MoneypunctData* const data = punct_data + inx;
112
113 // construct a named locale
114 const std::locale loc (data->locale_name_);
115
116 if (test_char) {
117 // exercise the narrow char, local specialization of the facet
118
119 typedef std::moneypunct<char, false> Punct;
120
121 const Punct &mp = std::use_facet<Punct>(loc);
122
123 const char dp = mp.decimal_point ();
124 const char ts = mp.thousands_sep ();
125 const std::string grp = mp.grouping ();
126 const std::string cur = mp.curr_symbol ();
127 const std::string pos = mp.positive_sign ();
128 const std::string neg = mp.negative_sign ();
129 const int fd = mp.frac_digits ();
130 const Punct::pattern pfm = mp.pos_format ();
131 const Punct::pattern nfm = mp.neg_format ();
132
133 RW_ASSERT (dp == data->decimal_point_);
134 RW_ASSERT (ts == data->thousands_sep_);
135 RW_ASSERT (fd == data->frac_digits_);
136 RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
137 RW_ASSERT (!rw_strncmp (cur.c_str (), data->curr_symbol_));
138 RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
139 RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
140
141 RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
142 RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
143 }
144
145 if (test_char) {
146 // exercise the narrow char, international specialization
147
148 typedef std::moneypunct<char, true> Punct;
149
150 const Punct &mp = std::use_facet<Punct>(loc);
151
152 const char dp = mp.decimal_point ();
153 const char ts = mp.thousands_sep ();
154 const std::string grp = mp.grouping ();
155 const std::string cur = mp.curr_symbol ();
156 const std::string pos = mp.positive_sign ();
157 const std::string neg = mp.negative_sign ();
158 const int fd = mp.frac_digits ();
159 const Punct::pattern pfm = mp.pos_format ();
160 const Punct::pattern nfm = mp.neg_format ();
161
162 RW_ASSERT (dp == data->decimal_point_);
163 RW_ASSERT (ts == data->thousands_sep_);
164 RW_ASSERT (fd == data->frac_digits_);
165 RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
166 RW_ASSERT (!rw_strncmp (cur.c_str (), data->int_curr_symbol_));
167 RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
168 RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
169
170 RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
171 RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
172 }
173
174 // both specializations may be tested at the same time
175
176#ifndef _RWSTD_NO_WCHAR_T
177
178 if (test_wchar) {
179 // exercise the wide char, local specialization of the facet
180
181 typedef std::moneypunct<wchar_t, false> Punct;
182
183 const Punct &mp = std::use_facet<Punct>(loc);
184
185 const wchar_t dp = mp.decimal_point ();
186 const wchar_t ts = mp.thousands_sep ();
187 const std::string grp = mp.grouping ();
188 const std::wstring cur = mp.curr_symbol ();
189 const std::wstring pos = mp.positive_sign ();
190 const std::wstring neg = mp.negative_sign ();
191 const int fd = mp.frac_digits ();
192 const Punct::pattern pfm = mp.pos_format ();
193 const Punct::pattern nfm = mp.neg_format ();
194
195 RW_ASSERT (dp == data->wdecimal_point_);
196 RW_ASSERT (ts == data->wthousands_sep_);
197 RW_ASSERT (fd == data->frac_digits_);
198 RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
199 RW_ASSERT (!rw_strncmp (cur.c_str (), data->wcurr_symbol_));
200 RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
201 RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
202
203 RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
204 RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
205 }
206
207 if (test_wchar) {
208 // exercise the wide char, international specialization
209
210 typedef std::moneypunct<wchar_t, true> Punct;
211
212 const Punct &mp = std::use_facet<Punct>(loc);
213
214 const wchar_t dp = mp.decimal_point ();
215 const wchar_t ts = mp.thousands_sep ();
216 const std::string grp = mp.grouping ();
217 const std::wstring cur = mp.curr_symbol ();
218 const std::wstring pos = mp.positive_sign ();
219 const std::wstring neg = mp.negative_sign ();
220 const int fd = mp.frac_digits ();
221 const Punct::pattern pfm = mp.pos_format ();
222 const Punct::pattern nfm = mp.neg_format ();
223
224 RW_ASSERT (dp == data->wdecimal_point_);
225 RW_ASSERT (ts == data->wthousands_sep_);
226 RW_ASSERT (fd == data->frac_digits_);
227 RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
228 RW_ASSERT (!rw_strncmp (cur.c_str (), data->wint_curr_symbol_));
229 RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
230 RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
231
232 RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
233 RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
234 }
235
236#endif // _RWSTD_NO_WCHAR_T
237
238}
239
240
241extern "C" {
242
243static void*
244thread_func (void*)
245{
246 for (int i = 0; i != opt_nloops; ++i) {
247
249 break;
250
251 thread_loop_body (std::size_t (i));
252 }
253
254 return 0;
255}
256
257} // extern "C"
258
259
261static int
262run_test (int, char**)
263{
264 // find all installed locales for which setlocale(LC_ALL) succeeds
265 const char* const locale_list =
266 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
267
268 // array of locale names to use for testing
269 const char* locales [sizeof punct_data / sizeof *punct_data];
270
271 const std::size_t maxinx = sizeof locales / sizeof *locales;
272
273 // iterate over locales, initializing a global punct_data array
274 for (const char *name = locale_list; *name; name += std::strlen (name) +1) {
275
276 std::locale loc;
277
278 MoneypunctData* const pdata = punct_data + nlocales;
279
280 pdata->locale_name_ = name;
282
283 try {
284 loc = std::locale (name);
285
286 typedef std::moneypunct<char, false> Punct;
287
288 const Punct &mp = std::use_facet<Punct>(loc);
289
290 const char dp = mp.decimal_point ();
291 const char ts = mp.thousands_sep ();
292 const std::string grp = mp.grouping ();
293 const std::string cur = mp.curr_symbol ();
294 const std::string pos = mp.positive_sign ();
295 const std::string neg = mp.negative_sign ();
296 const int fd = mp.frac_digits ();
297 const Punct::pattern pfm = mp.pos_format ();
298 const Punct::pattern nfm = mp.neg_format ();
299
300 pdata->decimal_point_ = dp;
301 pdata->thousands_sep_ = ts;
302 pdata->frac_digits_ = fd;
303
304 std::strcpy (pdata->grouping_, grp.c_str ());
305 std::strcpy (pdata->curr_symbol_, cur.c_str ());
306 std::strcpy (pdata->positive_sign_, pos.c_str ());
307 std::strcpy (pdata->negative_sign_, neg.c_str ());
308 std::memcpy (pdata->pos_format_, &pfm, sizeof pfm);
309 std::memcpy (pdata->neg_format_, &nfm, sizeof nfm);
310 }
311 catch (...) {
312 rw_warn (0, 0, __LINE__,
313 "std::locale(%#s) threw an exception, skipping", name);
314 continue;
315 }
316
317 try {
318 typedef std::moneypunct<char, true> Punct;
319
320 const Punct &mp = std::use_facet<Punct>(loc);
321
322 const std::string cur = mp.curr_symbol ();
323 const int fd = mp.frac_digits ();
324 const Punct::pattern pfm = mp.pos_format ();
325 const Punct::pattern nfm = mp.neg_format ();
326
327 pdata->int_frac_digits_ = fd;
328
329 std::strcpy (pdata->int_curr_symbol_, cur.c_str ());
330 std::memcpy (pdata->int_pos_format_, &pfm, sizeof pfm);
331 std::memcpy (pdata->int_neg_format_, &nfm, sizeof nfm);
332 }
333 catch (...) {
334 rw_warn (0, 0, __LINE__,
335 "std::locale(%#s) threw an exception, skipping", name);
336 continue;
337 }
338
339#ifndef _RWSTD_NO_WCHAR_T
340
341 try {
342 typedef std::moneypunct<wchar_t, false> Punct;
343
344 const Punct &mp = std::use_facet<Punct>(loc);
345
346 const wchar_t dp = mp.decimal_point ();
347 const wchar_t ts = mp.thousands_sep ();
348 const std::wstring cur = mp.curr_symbol ();
349 const std::wstring pos = mp.positive_sign ();
350 const std::wstring neg = mp.negative_sign ();
351
352 pdata->wdecimal_point_ = dp;
353 pdata->wthousands_sep_ = ts;
354
355 typedef std::wstring::traits_type Traits;
356
357 Traits::copy (pdata->wcurr_symbol_, cur.data (), cur.size ());
358 Traits::copy (pdata->wpositive_sign_, pos.data (), pos.size ());
359 Traits::copy (pdata->wnegative_sign_, neg.data (), neg.size ());
360 }
361 catch (...) {
362 rw_warn (0, 0, __LINE__,
363 "std::locale(%#s) threw an exception, skipping", name);
364 continue;
365 }
366
367 try {
368 typedef std::moneypunct<wchar_t, true> Punct;
369
370 const Punct &mp = std::use_facet<Punct>(loc);
371
372 const std::wstring cur = mp.curr_symbol ();
373 const std::wstring pos = mp.positive_sign ();
374 const std::wstring neg = mp.negative_sign ();
375
376 typedef std::wstring::traits_type Traits;
377
378 Traits::copy (pdata->wint_curr_symbol_, cur.data (), cur.size ());
379 }
380 catch (...) {
381 rw_warn (0, 0, __LINE__,
382 "std::locale(%#s) threw an exception, skipping", name);
383 continue;
384 }
385
386#endif // _RWSTD_NO_WCHAR_T
387
388 ++nlocales;
389
390 if (nlocales == maxinx)
391 break;
392 }
393
394 // unless the number of iterations was explicitly specified
395 // on the command line, decrease the number to equal the number
396 // of excericsed locales when only one thread is being tested
397 if (1 == opt_nthreads && opt_nloops < 0)
398 opt_nloops = int (nlocales);
399
400 // when the number of iterations wasn't explicitly specified
401 // on the command line set it to the default value
402 if (opt_nloops < 0)
404
405 rw_fatal (0 < nlocales, 0, __LINE__,
406 "must have at least one valid locale to test");
407
408 rw_info (0, 0, 0,
409 "testing std::moneypunct<charT> with %d thread%{?}s%{;}, "
410 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
413 nlocales, int (nlocales), "%#s", locales);
414
415 rw_info (0, 0, 0, "exercising std::moneypunct<char>");
416
417 test_char = true;
418 test_wchar = false;
419
420 // create and start a pool of threads and wait for them to finish
421 int result =
422 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
423 thread_func, 0, std::size_t (opt_timeout));
424
425 rw_error (result == 0, 0, __LINE__,
426 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
427 opt_nthreads, thread_func);
428
429#ifndef _RWSTD_NO_WCHAR_T
430
431 rw_info (0, 0, 0, "exercising std::moneypunct<wchar_t>");
432
433 test_char = false;
434 test_wchar = true;
435
436 // start a pool of threads to exercise the thread safety
437 // of the wchar_t specialization
438 result =
439 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
440 thread_func, 0, std::size_t (opt_timeout));
441
442 rw_error (result == 0, 0, __LINE__,
443 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
444 opt_nthreads, thread_func);
445
446 // exercise both the char and the wchar_t specializations
447 // at the same time
448
449 rw_info (0, 0, 0,
450 "exercising both std::moneypunct<char> "
451 "and std::moneypunct<wchar_t>");
452
453 test_char = true;
454 test_wchar = true;
455
456 // start a pool of threads to exercise wstring thread safety
457 result =
458 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
459 thread_func, 0, std::size_t (opt_timeout));
460
461 rw_error (result == 0, 0, __LINE__,
462 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
463 opt_nthreads, thread_func);
464
465#endif // _RWSTD_NO_WCHAR_T
466
467 return result;
468}
469
470
472int main (int argc, char *argv[])
473{
474#ifdef _RWSTD_REENTRANT
475
476 // set nthreads to the greater of the number of processors
477 // and 2 (for uniprocessor systems) by default
479 if (opt_nthreads < 2)
480 opt_nthreads = 2;
481
482#endif // _RWSTD_REENTRANT
483
484 return rw_test (argc, argv, __FILE__,
485 "lib.locale.moneypunct",
486 "thread safety", run_test,
487 "|-soft-timeout#0 " // must be non-negative
488 "|-nloops#0 " // must be non-negative
489 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
490 "|-locales=", // must be provided
492 &opt_nloops,
493 int (MAX_THREADS),
496}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define Traits
Definition 17.names.cpp:556
#define neg
Definition 17.names.cpp:503
#define inx
Definition 17.names.cpp:484
#define pos
Definition 17.names.cpp:518
volatile int result
const char *const data[]
const char * locale_list
#define DFLT_LOOPS
struct MoneypunctData punct_data[MAX_THREADS]
#define MAX_THREADS
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const int cur
#define main
const unsigned nlocales
const struct @19 locales[]
const char * name
Definition codecvt1.cpp:72
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_fatal(int expr, const char *filename, int line, const char *fmtspec,...)
Definition driver.cpp:1596
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647
_TEST_EXPORT int rw_opt_setlocales(int, char *[])
Definition locale.cpp:866
_TEST_EXPORT const char *const & rw_opt_locales
Definition locale.cpp:862
_TEST_EXPORT char * rw_locales(int=_UNUSED_CAT, const char *=0, bool=true)
Definition locale.cpp:368
#define RW_ASSERT(expr)
_TEST_EXPORT int rw_thread_pool(rw_thread_t *, _RWSTD_SIZE_T, rw_thread_attr_t *, rw_thread_proc *, void **, _RWSTD_SIZE_T=0)
_TEST_EXPORT int rw_get_cpus()
Definition thread.cpp:402
_TEST_EXPORT int rw_thread_pool_timeout_expired()
Definition thread.cpp:65
_TEST_EXPORT int rw_strncmp(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, int=CMP_NULTERM)