Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.codecvt.mt.cpp
Go to the documentation of this file.
1
29#include <ios> // for ios
30#include <iterator> // for ostreambuf_iterator
31#include <locale> // for locale, codecvt
32
33#include <cstring> // for strlen()
34#include <cwchar> // for codecvt
35
36#include <rw_locale.h>
37#include <rw_thread.h>
38#include <rw_driver.h>
39#include <rw_valcmp.h> // for rw_strncmp ()
40
41
42// maximum number of threads allowed by the command line interface
43#define MAX_THREADS 32
44#define MAX_LOOPS 100000
45
46// default number of threads (will be adjusted to the number
47// of processors/cores later)
49
50// the number of times each thread should iterate (unless specified
51// otherwise on the command line)
52int opt_nloops = 5000;
53
54// number of locales to use
56
57// should all threads share the same set of locale objects instead
58// of creating their own?
60
61// default timeout used by each threaded section of this test
62int opt_timeout = 60;
63
64
66// array of locale names to use for testing
67static const char*
69
70// number of locale names in the array
71static std::size_t
73
74
76//
77template <class internT> //, class externT = char, class stateT = std::mbstate_t>
79{
80 enum { BufferSize = 16 };
81
82 typedef char externT;
83 typedef std::mbstate_t stateT;
84 typedef std::codecvt_base::result resultT;
85 typedef std::size_t sizeT;
86
91
96
101};
102
103//
105{
106 // out, unshift, in, encoding, always_noconv, length, max_length
107 enum CvtId {
115 cvt_max
116 };
117
118 // name of the locale the data corresponds to
119 const char* locale_name_;
120
121 // optionally set to the named locale for threads to share
122 std::locale locale_;
123
126
128
129template <class charT>
130struct MyBuffer {
131 const charT* const str;
132 const int str_len;
133};
134
136 { "a\x80", 2 },
137 { "b", 1 },
138 { "c\0c", 3 },
139 { "ddd", 3 },
140 { "e\fce\0", 4 },
141 { "ff\0ffff", 5 },
142 { "gggg\0g", 6 },
143 { "hh\0hhhh", 7 },
144 { "i\ni\tiiii", 8 },
145 { "jjjjjjjjj", 9 },
146 { "kkkkkkkkkk", 10 }
147};
148
150 { L"\x0905\x0916", 2 },
151 { L"bb", 2 },
152 { L"\x106c", 2 },
153 { L"dddd", 4 },
154 { L"\xd800\xd801", 2 },
155 { L"ffffff", 6 },
156 { L"\xdfff\xffff", 2 },
157 { L"hhhhhhhh", 8 },
158 { L"i\0i\1i", 4 },
159 { L"jjjjjjjjjj", 10 },
160 { L"kkkkkkkkkkk", 11 }
161};
162
163
165template <typename T>
167{
168 enum { value = 0 };
169};
170
171template <>
172struct test_is_char<char>
173{
174 enum { value = 1 };
175};
176
177
179template <class internT>
180void test_codecvt (const std::locale& loc,
181 const MyBuffer<internT>& in,
182 const MyBuffer<char>& out,
184 const MyCodecvtData::CvtId id)
185{
186
187 typedef char externT;
188 typedef std::mbstate_t stateT;
189 typedef std::size_t sizeT;
190
191 typedef std::codecvt<internT, externT, stateT> code_cvt_type;
192
193 const code_cvt_type& cvt =
194 std::use_facet<code_cvt_type>(loc);
195
196 switch (id) {
198 {
199 externT out_buffer [MyCodecvtData_T<internT>::BufferSize];
200 out_buffer [0] = externT ();
201
202 const int out_len = RW_COUNT_OF (out_buffer);
203
204 const internT* from = in.str;
205 const internT* from_end = in.str + in.str_len;
206 const internT* from_next = 0;
207
208 externT* to = out_buffer;
209 externT* to_limit = out_buffer + out_len;
210 externT* to_next = 0;
211
212 std::mbstate_t state = std::mbstate_t ();
213
215 cvt.out (state, from, from_end, from_next,
216 to, to_limit, to_next);
217
218 const sizeT len = to_next - to;
219
220 RW_ASSERT (data.out_result_ == result);
221 RW_ASSERT (len == data.out_length_);
222 RW_ASSERT (!rw_strncmp (out_buffer, data.out_buffer_, len));
223 }
224 break;
226 {
227 externT out_buffer [MyCodecvtData_T<internT>::BufferSize];
228 out_buffer [0] = externT ();
229
230 const int out_len = RW_COUNT_OF (out_buffer);
231
232 externT* to = out_buffer;
233 externT* to_limit = out_buffer + out_len;
234 externT* to_next = 0;
235
236 std::mbstate_t state = std::mbstate_t ();
237
239 cvt.unshift (state, to, to_limit, to_next);
240
241 // 22.2.1.5.2 p5
242 RW_ASSERT (to == to_next);
243
244 // 22.2.1.5.2 p6 required only for codecvt<char, char, mbstate_t>
246 || result == std::codecvt_base::noconv);
247 }
248 break;
250 {
251 internT in_buffer [MyCodecvtData_T<internT>::BufferSize];
252 in_buffer [0] = internT ();
253
254 const int in_len = RW_COUNT_OF (in_buffer);
255 const int out_len = RW_COUNT_OF (data.out_buffer_);
256
257 const externT* from = data.out_buffer_;
258 const externT* from_end = data.out_buffer_ + out_len;
259 const externT* from_next = 0;
260
261 internT* to = in_buffer;
262 internT* to_limit = in_buffer + in_len;
263 internT* to_next = 0;
264
265 std::mbstate_t state = std::mbstate_t ();
266
268 cvt.in (state, from, from_end, from_next,
269 to, to_limit, to_next);
270
271 const sizeT len = to_next - to;
272
273 RW_ASSERT (data.in_result_ == result);
274 RW_ASSERT (len == data.in_length_);
275 RW_ASSERT (!rw_strncmp (in_buffer, data.in_buffer_, len));
276 }
277 break;
279 RW_ASSERT (data.encoding_ == cvt.encoding ());
280 break;
281
283 {
284 const externT* from = out.str;
285 const externT* from_end = out.str + out.str_len;
286 const size_t max = 32;
287
288 std::mbstate_t state = std::mbstate_t ();
289
290 const sizeT len = cvt.length (state, from, from_end, max);
291
292 RW_ASSERT (data.length_ == len);
293 }
294 break;
295
297 RW_ASSERT (data.max_length_ == cvt.max_length ());
298 break;
300 RW_ASSERT (data.always_noconv_ == cvt.always_noconv ());
301 break;
303 break;
304 }
305}
306
307
309extern "C" {
310
311bool test_char; // exercise codecvt<char,char>
312bool test_wchar; // exercise codecvt<wchar_t,char>
313
314static void*
315thread_func (void*)
316{
317 const int ni = RW_COUNT_OF (nsrc);
318 const int wi = RW_COUNT_OF (wsrc);
319
320 for (int i = 0; i != opt_nloops; ++i) {
321
323 break;
324
325 const std::size_t inx = i % nlocales;
327
328 // construct a named locale, get a reference to the codecvt
329 // facet from it and use it to format a random money value
330 const std::locale loc =
332 : std::locale (data.locale_name_);
333
334 const MyCodecvtData::CvtId op =
336
337 if (test_char) {
338 test_codecvt<char>(loc, nsrc [inx % ni], nsrc [inx % ni],
339 data.char_data_, op);
340 }
341
342 if (test_wchar) {
343 test_codecvt<wchar_t>(loc, wsrc [inx % wi], nsrc [inx % ni],
344 data.wchar_data_, op);
345 }
346 }
347
348 return 0;
349}
350
351} // extern "C"
352
353
355template <class internT>
356void run_test_fill (const std::locale& loc,
357 const MyBuffer<internT>& in,
358 const MyBuffer<char>& out,
360{
361
362 typedef char externT;
363 typedef std::mbstate_t stateT;
364
365 typedef std::codecvt<internT, externT, stateT> code_cvt_type;
366
367 const code_cvt_type& cvt =
368 std::use_facet<code_cvt_type>(loc);
369
370 //fill in the appropriate fields of data
371 data.encoding_ = cvt.encoding ();
372 data.max_length_ = cvt.max_length ();
373 data.always_noconv_ = cvt.always_noconv ();
374
375 // length
376 {
377 const externT* from = out.str;
378 const externT* from_end = out.str + out.str_len;
379 const size_t max = 32;
380
381 std::mbstate_t state = std::mbstate_t ();
382
383 data.length_ = cvt.length (state, from, from_end, max);
384 }
385
386 // out
387 {
388 const int out_len = RW_COUNT_OF (data.out_buffer_);
389
390 const internT* from = in.str;
391 const internT* from_end = in.str + in.str_len;
392 const internT* from_next = 0;
393
394 externT* to = data.out_buffer_;
395 externT* to_limit = data.out_buffer_ + out_len;
396 externT* to_next = 0;
397
398 data.out_result_ = cvt.out (data.out_state_,
399 from, from_end, from_next,
400 to, to_limit, to_next);
401
402 data.out_length_ = to_next - to;
403 }
404
406 //{
407 // externT* to = data.out_buffer_;
408 // externT* to_limit = data.out_buffer_ + RW_COUNT_OF (data.out_buffer_);
409 // externT* to_next = 0;
410
411 // std::mbstate_t state = std::mbstate_t ();
412
413 // data.shift_result_ = cvt.unshift (state, to, to_limit, to_next);
414 //}
415
416 // in
417 {
418 const int out_len = RW_COUNT_OF (data.out_buffer_);
419 const int in_len = RW_COUNT_OF (data.in_buffer_);
420
421 const externT* from = data.out_buffer_;
422 const externT* from_end = data.out_buffer_ + out_len;
423 const externT* from_next = 0;
424
425 internT* to = data.in_buffer_;
426 internT* to_limit = data.in_buffer_ + in_len;
427 internT* to_next = 0;
428
429 data.in_result_ = cvt.in (data.in_state_,
430 from, from_end, from_next,
431 to, to_limit, to_next);
432
433 data.in_length_ = to_next - to;
434 }
435}
436
437static int
438run_test (int, char**)
439{
440 // find all installed locales for which setlocale (LC_ALL) succeeds
441 const char* const locale_list =
442 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
443
444 const std::size_t maxinx = RW_COUNT_OF (locales);
445
446 const int ni = RW_COUNT_OF (nsrc);
447 const int wi = RW_COUNT_OF (wsrc);
448
449 for (const char* name = locale_list;
450 *name;
451 name += std::strlen (name) + 1) {
452
453 const std::size_t inx = nlocales;
454 locales [inx] = name;
455
456 // fill in the money and results for this locale
459
460 try {
461 const std::locale loc (data.locale_name_);
462
463 run_test_fill<char>
464 (loc, nsrc [inx % ni], nsrc [inx % ni], data.char_data_);
465
466 run_test_fill<wchar_t>
467 (loc, wsrc [inx % wi], nsrc [inx % ni], data.wchar_data_);
468
470 data.locale_ = loc;
471
472 nlocales += 1;
473
474 }
475 catch (...) {
476 rw_warn (!rw_opt_locales, 0, __LINE__,
477 "failed to create locale(%#s)", name);
478 }
479
480 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
481 break;
482 }
483
484 // avoid divide by zero in thread if there are no locales to test
485 rw_fatal (nlocales != 0, 0, __LINE__,
486 "failed to create one or more usable locales!");
487
488 rw_info (0, 0, 0,
489 "testing std::codecvt<charT> with %d thread%{?}s%{;}, "
490 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
493 nlocales, int (nlocales), "%#s", locales);
494
496
497 rw_info (0, 0, 0, "exercising std::codecvt<char, char>");
498
499 test_char = true;
500 test_wchar = false;
501
502 // create and start a pool of threads and wait for them to finish
503 int result =
504 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
505 thread_func, 0, std::size_t (opt_timeout));
506
507 rw_error (result == 0, 0, __LINE__,
508 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
509 opt_nthreads, thread_func);
510
512
513 rw_info (0, 0, 0, "exercising std::codecvt<wchar_t, char>");
514
515 test_char = false;
516 test_wchar = true;
517
518 result =
519 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
520 thread_func, 0, std::size_t (opt_timeout));
521
522 rw_error (result == 0, 0, __LINE__,
523 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
524 opt_nthreads, thread_func);
525
527
528 rw_info (0, 0, 0, "exercising std::codecvt<char, char> and "
529 "std::codecvt<wchar_t, char>");
530
531 test_char = true;
532 test_wchar = true;
533
534 result =
535 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
536 thread_func, 0, std::size_t (opt_timeout));
537
538 rw_error (result == 0, 0, __LINE__,
539 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
540 opt_nthreads, thread_func);
541
542 return result;
543}
544
545
547int main (int argc, char *argv[])
548{
549#ifdef _RWSTD_REENTRANT
550
551 // set nthreads to the greater of the number of processors
552 // and 2 (for uniprocessor systems) by default
554 if (opt_nthreads < 2)
555 opt_nthreads = 2;
556
557#endif // _RWSTD_REENTRANT
558
559 return rw_test (argc, argv, __FILE__,
560 "lib.locale.codecvt",
561 "thread safety", run_test,
562 "|-soft-timeout#0 " // must be non-negative
563 "|-nloops#0 " // must be non-negative
564 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
565 "|-nlocales#0 " // arg must be non-negative
566 "|-locales= " // must be provided
567 "|-shared-locale# ",
569 &opt_nloops,
570 int (MAX_THREADS),
575}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define charT
Definition 17.names.cpp:456
#define len
Definition 17.names.cpp:488
#define inx
Definition 17.names.cpp:484
volatile int result
const char *const data[]
int opt_timeout
void run_test_fill(const std::locale &loc, const MyBuffer< internT > &in, const MyBuffer< char > &out, MyCodecvtData_T< internT > &data)
int opt_nloops
int opt_shared_locale
int opt_nlocales
void test_codecvt(const std::locale &loc, const MyBuffer< internT > &in, const MyBuffer< char > &out, const MyCodecvtData_T< internT > &data, const MyCodecvtData::CvtId id)
struct MyCodecvtData my_codecvt_data[MAX_THREADS]
const MyBuffer< char > nsrc[]
#define MAX_THREADS
bool test_wchar
const MyBuffer< wchar_t > wsrc[]
int opt_nthreads
bool test_char
const char * locale_list
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const int out
const int in
#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)
#define RW_COUNT_OF(x)
_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)
const charT *const str
internT in_buffer_[BufferSize]
externT out_buffer_[BufferSize]
std::codecvt_base::result resultT
MyCodecvtData_T< char > char_data_
MyCodecvtData_T< wchar_t > wchar_data_
#define max(a, b)