Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.codecvt.length.cpp
Go to the documentation of this file.
1
29#ifdef __SUNPRO_CC
30 // working around a SunPro/SunOS 5.8 bug (PR #26255)
31# include <time.h>
32#endif // __SUNPRO_CC
33
34#include <locale> // for codecvt
35
36#include <climits> // for MB_LEN_MAX
37#include <clocale> // for LC_CTYPE, setlocale()
38#include <cstdlib> // for MB_CUR_MAX, free(), size_t
39#include <cstring> // for strcpy(), strlen()
40#include <cwchar> // for mbstate_t
41
42#include <rw_any.h> // for rw_any
43#include <rw_cmdopt.h> // for rw_enabled()
44#include <rw_driver.h> // for rw_test()
45#include <rw_file.h> // for rw_fwrite()
46#include <rw_locale.h> // for rw_localedef(), rw_find_mb_locale()
47#include <rw_printf.h> // for rw_printf()
48
49
51typedef std::codecvt<char, char, std::mbstate_t> Codecvt;
52typedef std::codecvt_byname<char, char, std::mbstate_t> CodecvtByname;
53
54#ifndef _RWSTD_NO_WCHAR_T
55
56typedef std::codecvt<wchar_t, char, std::mbstate_t> WCodecvt;
57typedef std::codecvt_byname<wchar_t, char, std::mbstate_t> WCodecvtByname;
58
59#endif // _RWSTD_NO_WCHAR_T
60
61
63// the root of the locale directory (RWSTD_LOCALE_ROOT)
64// set in main() instead of here to avoid Solaris 7 putenv() bug (PR #30017)
65const char* locale_root /* = set in main() */;
66
67
68// creates a table-based multibyte locale
69const char* create_locale ()
70{
71 char cm_fname [1024];
72 if (rw_snprintf (cm_fname, sizeof cm_fname, "%s%c%s",
73 locale_root, _RWSTD_PATH_SEP, "charmap") < 0)
74 return 0;
75
76 static const char charmap[] = {
77 "<code_set_name> test_charmap\n"
78 "<comment_char> %\n"
79 "<escape_char> /\n"
80 "<mb_cur_min> 1\n"
81 "<mb_cur_max> 9\n"
82 "CHARMAP\n"
83 "<U0000> /x30 0 \n"
84 "<U0001> /x31 1 \n"
85 "<U0002> /x32/x32 22 \n"
86 "<U0003> /x33/x33/x33 333 \n"
87 "<U0004> /x34/x34/x34/x34 4444 \n"
88 "<U0005> /x35/x35/x35/x35/x35 55555 \n"
89 "<U0006> /x36/x36/x36/x36/x36/x36 666666 \n"
90 "<U0007> /x37/x37/x37/x37/x37/x37/x37 7777777 \n"
91 "<U0008> /x38/x38/x38/x38/x38/x38/x38/x38 88888888 \n"
92 "<U0009> /x39/x39/x39/x39/x39/x39/x39/x39/x39 999999999 \n"
93 "<U0010> /x41 A \n"
94 "<U0011> /x42 B \n"
95 "<U0012> /x43 C \n"
96 "END CHARMAP\n"
97 };
98
99 if (std::size_t (-1) == rw_fwrite (cm_fname, charmap))
100 return 0;
101
102 char src_fname [1024];
103 if (rw_snprintf (src_fname, sizeof src_fname, "%s%c%s",
104 locale_root, _RWSTD_PATH_SEP, "source") < 0)
105 return 0;
106
107 if (std::size_t (-1) == rw_fwrite (src_fname, "LC_CTYPE\nEND LC_CTYPE\n"))
108 return 0;
109
110 // invoke localedef to create the named locale
111 // silence the following warnings:
112 // 701: no compatible locale found
113 // 702: member of portable character set <x> not found
114 // in the character map
115 // 706: iconv_open() failed
116 const char* const locname =
117 rw_localedef ("-w701 -w702 -w706",
118 src_fname, cm_fname, "mb_cur_max-9");
119
120 return locname;
121}
122
123
125template <class internT>
126void test_length (internT /* dummy */,
127 int line,
128 const std::mbstate_t *pstate,
129 const std::codecvt<internT, char, std::mbstate_t> &cvt,
130 const char *from,
131 std::size_t nchars,
132 int maxi,
133 int result)
134{
135 static const std::mbstate_t initial_state = std::mbstate_t ();
136
137 const char* const tname = rw_any_t (internT ()).type_name ();
138
139 std::mbstate_t state = pstate ? *pstate : initial_state;
140
141 if (std::size_t (-1) == nchars)
142 nchars = std::strlen (from);
143
144 const int res = cvt.length (state, from, from + nchars, maxi);
145
146 rw_assert (res == result, 0, line,
147 "line %d: codecvt<%s, char, mbstate_t>::length("
148 "state, from=%{*s}, from + %zu, %d) == %d, got %d",
149 __LINE__, tname, sizeof *from, from, nchars, maxi, result, res);
150
151 rw_assert (!pstate || 0 == std::memcmp (pstate, &state, sizeof state),
152 0, line,
153 "line %d: codecvt<%s, char, mbstate_t>::length("
154 "state, from=%{*s}, from + %zu, %d) unexpected state",
155 __LINE__, tname, from, nchars, maxi);
156}
157
158
160void test_codecvt (const Codecvt *pcvt = 0)
161{
162 if (0 == pcvt)
163 rw_info (0, 0, 0,
164 "std::codecvt<char, char, mbstate_t>::length "
165 "(state_type&, const extern_type*, const "
166 "extern_type*, size_t)");
167
168 const std::locale classic = std::locale::classic ();
169
170 const Codecvt &cvt = pcvt ? *pcvt : std::use_facet<Codecvt>(classic);
171
172#undef TEST
173#define TEST(from, nchars, maxi, result) \
174 test_length (char (), __LINE__, 0, cvt, from, nchars, maxi, result)
175
176 // +--------------- source sequence of externT characters
177 // | +-------- size of sequence in externT characters
178 // | | +----- maximum number of internT characters
179 // | | | +-- expected result
180 // | | | |
181 // V V V V
182 TEST (0, 0, 0, 0);
183 TEST ("", 0, 0, 0);
184 TEST ("a", 1, 0, 0);
185 TEST ("ab", 2, 1, 1);
186 TEST ("ab", 2, 2, 2);
187 TEST ("ab", 2, 3, 2);
188 TEST ("abc", 3, 0, 0);
189 TEST ("abc", 3, 1, 1);
190 TEST ("abc", 3, 2, 2);
191 TEST ("abc", 3, 3, 3);
192 TEST ("abc", 3, 4, 3);
193}
194
195
197static void
198test_codecvt_byname ()
199{
200 rw_info (0, 0, 0,
201 "std::codecvt_byname<char, char, mbstate_t>::length "
202 "(state_type&, const extern_type*, const extern_type*, "
203 "size_t)");
204
205 const CodecvtByname cvt ("");
206
207 test_codecvt (&cvt);
208
209}
210
211
213static void
214test_wcodecvt ()
215{
216 rw_info (0, 0, 0,
217 "std::codecvt<wchar_t, char, mbstate_t>::length "
218 "(state_type&, const extern_type*, const extern_type*, "
219 "size_t)");
220
221#ifndef _RWSTD_NO_WCHAR_T
222
223 const std::locale classic = std::locale::classic ();
224
225 const WCodecvt &cvt = std::use_facet<WCodecvt>(classic);
226
227#undef TEST
228#define TEST(from, nchars, maxi, result) \
229 test_length (wchar_t (), __LINE__, 0, cvt, from, nchars, maxi, result)
230
231 // +--------------- source sequence of externT characters
232 // | +-------- size of sequence in externT characters
233 // | | +----- maximum number of internT characters
234 // | | | +-- expected result
235 // | | | |
236 // V V V V
237 TEST (0, 0, 0, 0);
238 TEST ("", 0, 0, 0);
239 TEST ("a", 1, 0, 0);
240 TEST ("ab", 2, 1, 1);
241 TEST ("ab", 2, 2, 2);
242 TEST ("ab", 2, 3, 2);
243 TEST ("abc", 3, 0, 0);
244 TEST ("abc", 3, 1, 1);
245 TEST ("abc", 3, 2, 2);
246 TEST ("abc", 3, 3, 3);
247 TEST ("abc", 3, 4, 3);
248
249#else // if defined (_RWSTD_NO_WCHAR_T)
250
251 rw_warn (0, 0, __LINE__, "_RWSTD_NO_WCHAR_T #defined, cannot test");
252
253#endif // _RWSTD_NO_WCHAR_T
254
255}
256
257
259#ifndef _RWSTD_NO_WCHAR_T
260
261// exercises an algorithmic multibyte encoding
262static void
263test_wcodecvt_byname_algorithmic ()
264{
265 rw_info (0, 0, 0, "locale (\"UTF-8@UCS\") [algorithmic encoding]");
266
267 // lowercase utf ==> relaxed checking (i.e., some, but not all,
268 // invalid UTF-8 sequence are accepted)
269 const WCodecvtByname cvt_relaxd ("utf-8@UCS");
270
271 // capital UTF ==> strict checking
272 const WCodecvtByname cvt_strict ("UTF-8@UCS");
273
274#undef STRICT
275#define STRICT(from, nc, maxi, res) \
276 test_length (wchar_t (), __LINE__, 0, cvt_strict, from, nc, maxi, res)
277
278#undef RELAXD
279#define RELAXD(from, nc, maxi, res) \
280 test_length (wchar_t (), __LINE__, 0, cvt_relaxd, from, nc, maxi, res)
281
282#undef TEST
283#define TEST(from, nc, maxi, res) \
284 STRICT (from, nc, maxi, res); \
285 RELAXD (from, nc, maxi, res)
286
287 // 22.2.1.5.2 [lib.locale.codecvt.virtuals]
288 // including the resolution of lwg issue 305
289 //
290 // -9- Preconditions: (from<=from_end) well-defined and true; state
291 // initialized, if at the beginning of a sequence, or else equal
292 // to the result of converting the preceding characters in the
293 // sequence.
294 //
295 // -9a- Effects: The effect on the state argument is "as if" it called
296 // do_in(state, from, from_end, from, to, to+max, to) for to pointing
297 // to a buffer of at least max elements.
298 //
299 // -10- Returns: (from_next-from) where from_next is the largest value
300 // in the range [from,from_end] such that the sequence of values
301 // in the range [from,from_next) represents max or fewer valid
302 // complete characters of type internT. The instantiation
303 // codecvt<char, char, mbstate_t> returns the lesser of max
304 // and (from_end-from).
305
306 // Note that the function returns the number of externT characters
307 // (i.e., those of type char for the required instantiations)
308
309 // +--------------- source sequence of externT characters
310 // | +-------- size of sequence in externT characters
311 // | | +----- maximum number of internT characters
312 // | | | +-- expected result in externT characters
313 // | | | |
314 // V V V V
315 TEST (0, 0, 0, 0);
316 TEST ("", 0, 0, 0);
317 TEST ("a", 1, 0, 0);
318 TEST ("ab", 2, 1, 1);
319 TEST ("ab", 2, 2, 2);
320 TEST ("ab", 2, 3, 2);
321 TEST ("abc", 3, 0, 0);
322 TEST ("abc", 3, 1, 1);
323 TEST ("abc", 3, 2, 2);
324 TEST ("abc", 3, 3, 3);
325 TEST ("abc", 3, 4, 3);
326
327 // invalid sequences rejected in both the strict and relaxed mode
328 TEST ("\x80", 1, 0, 0);
329 TEST ("\xc0", 1, 0, 0);
330 TEST ("\x80\x00", 2, 0, 0);
331 TEST ("\xc0\x00", 2, 0, 0);
332
333 // valid 2-byte UTF-8 sequences (except for overlong sequences)
334 // 110x xxxx 10xx xxxx
335 // i.e., first byte: c0-df
336 // second byte: 80-bf
337 TEST ("\xc2", 1, 0, 0);
338 TEST ("\xc2\x81", 1, 1, 0);
339 TEST ("\xc2\x82", 2, 1, 2);
340 TEST ("\xc2\x83", 2, 2, 2);
341
342 // the second byte doesn't follow the correct pattern
343 // and will be rejected in strict mode (but will be
344 // accepted in relaxed mode)
345 STRICT ("\xc2\x01", 2, 1, 0);
346 RELAXD ("\xc2\x01", 2, 1, 2);
347
348 TEST ("\xc2\x80\xc0", 3, 0, 0);
349 TEST ("\xc2\x80\xc0\x81", 3, 1, 2);
350 TEST ("\xc2\x80\xc0\x82", 3, 2, 2);
351
352 STRICT ("\xc2\x80\xc2\x01", 4, 2, 2);
353 RELAXD ("\xc2\x80\xc2\x01", 4, 2, 4);
354
355 TEST ("\xc2\x80\xc2\x81", 4, 0, 0);
356 TEST ("\xc2\x80\xc2\x82", 4, 1, 2);
357 TEST ("\xc2\x80\xc2\x83", 4, 2, 4);
358 TEST ("\xc2\x80\xc2\x84", 4, 3, 4);
359}
360
361
362// exercises a table-based multibyte encoding
363static void
364test_wcodecvt_byname_table_based ()
365{
366 const char* const locname = create_locale ();
367
368 if (!rw_error (0 != locname, 0, __LINE__,
369 "failed to create a locale database")) {
370 return;
371 }
372
373 std::locale loc;
374
375 _TRY {
376 loc = std::locale (locname);
377 }
378 _CATCH (...) {
379 rw_error (0, 0, __LINE__,
380 "locale(\"%s\") unexpectedly threw an exception", locname);
381 return;
382 }
383
384 const WCodecvt &cvt_table = std::use_facet<WCodecvt>(loc);
385
386 rw_info (0, 0, 0, "locale (\"%s\") [table-based encoding]", locname);
387
388#undef TEST
389#define TEST(from, nc, maxi, res) \
390 test_length (wchar_t (), __LINE__, 0, cvt_table, \
391 from, std::size_t (nc), maxi, res)
392
393 TEST (0, 0, 0, 0);
394 TEST ("", 0, 0, 0);
395 TEST ("A", 1, 0, 0);
396 TEST ("AB", 2, 1, 1);
397 TEST ("AB", 2, 2, 2);
398 TEST ("AB", 2, 3, 2);
399 TEST ("ABC", 3, 0, 0);
400 TEST ("ABC", 3, 1, 1);
401 TEST ("ABC", 3, 2, 2);
402 TEST ("ABC", 3, 3, 3);
403 TEST ("ABC", 3, 4, 3);
404
405 TEST ("22", 1, 1, 0); // "22" --> L'2'
406 TEST ("22", 2, 1, 2);
407 TEST ("22", 2, 2, 2);
408
409 TEST ("333", 1, 1, 0); // "333" --> L'3'
410 TEST ("333", 2, 1, 0);
411 TEST ("333", 3, 1, 3);
412 TEST ("333", 3, 2, 3);
413
414 TEST ("4444", 1, 1, 0); // "4444" --> L'4'
415 TEST ("4444", 2, 1, 0);
416 TEST ("4444", 3, 1, 0);
417 TEST ("4444", 4, 1, 4);
418 TEST ("4444", 4, 2, 4);
419
420 TEST ("122", 1, 0, 0); // "122" --> L"12"
421 TEST ("122", 1, 1, 1);
422 TEST ("122", 1, 2, 1);
423 TEST ("122", 2, 2, 1);
424 TEST ("122", 3, 2, 3);
425 TEST ("122", 3, 3, 3);
426
427 TEST ("122333", 1, 0, 0); // "122333" --> L"123"
428 TEST ("122333", 1, 1, 1);
429 TEST ("122333", 1, 2, 1);
430 TEST ("122333", 4, 1, 1);
431 TEST ("122333", 4, 2, 3);
432 TEST ("122333", 4, 3, 3);
433 TEST ("122333", 5, 1, 1);
434 TEST ("122333", 5, 2, 3);
435 TEST ("122333", 5, 3, 3);
436 TEST ("122333", 5, 1, 1);
437 TEST ("122333", 5, 2, 3);
438 TEST ("122333", 5, 3, 3);
439 TEST ("122333", 6, 1, 1);
440 TEST ("122333", 6, 2, 3);
441 TEST ("122333", 6, 3, 6);
442 TEST ("122333", 6, 4, 6);
443
444 // 0 12 3 45 67 89
445 // I: +---++----+------++------++--++- (intern_type characters)
446 // E: 0....:....1....:....2....:....3. (extern_type characters)
447 TEST ("4444A55555B666666C77777770333122", -1, 1, 4);
448 TEST ("4444A55555B666666C77777770333122", -1, 2, 5);
449 TEST ("4444A55555B666666C77777770333122", -1, 3, 10);
450 TEST ("4444A55555B666666C77777770333122", -1, 4, 11);
451 TEST ("4444A55555B666666C77777770333122", -1, 5, 17);
452 TEST ("4444A55555B666666C77777770333122", -1, 6, 18);
453 TEST ("4444A55555B666666C77777770333122", -1, 7, 25);
454 TEST ("4444A55555B666666C77777770333122", -1, 8, 26);
455 TEST ("4444A55555B666666C77777770333122", -1, 9, 29);
456 TEST ("4444A55555B666666C77777770333122", -1, 10, 30);
457 TEST ("4444A55555B666666C77777770333122", -1, 11, 32);
458
459 TEST ("4444.55555B666666C77777770333122", -1, 11, 4);
460 TEST ("4444A55555.666666C77777770333122", -1, 11, 10);
461 TEST ("4444A55555B666666.77777770333122", -1, 11, 17);
462 TEST ("4444A55555B666666C7777777.333122", -1, 11, 25);
463 TEST ("4444A55555B666666C77777770333.22", -1, 11, 29);
464}
465
466
467// exercises a libc-based multibyte encoding
468static void
469test_wcodecvt_byname_libc_based ()
470{
471 // compute `mb_cur_max' multibyte characters in increasing
472 // length from 1 to mb_cur_max bytes long
473
474 // i.e., initialize the first (N + 1) elements of mb_chars as follows:
475 // mb_chars [0] = "0"; // where "0" is a single byte character
476 // mb_chars [1] = "11"; // where "11" is a two-byte character
477 // mb_chars [2] = "222"; // where "222" is a three-byte character
478 // mb_chars [N] = "NNN...N"; // where "NNN...N" is an N-byte character
479
480 std::size_t mb_cur_max = 0;
481
482 rw_mbchar_array_t mb_chars;
483
484 const char* const locname = rw_find_mb_locale (&mb_cur_max, mb_chars);
485
486 if (!rw_warn (0 != locname, 0, __LINE__,
487 "failed to find a multibyte locale")) {
488 return;
489 }
490
491 std::locale loc;
492
493 _TRY {
494 loc = std::locale (locname);
495 }
496 _CATCH (...) {
497 rw_error (0, 0, __LINE__,
498 "locale(\"%s\") unexpectedly threw an exception", locname);
499 return;
500 }
501
502 const WCodecvt &cvt_libc = std::use_facet<WCodecvt>(loc);
503
504 rw_info (0, 0, 0, "locale (\"%s\") [libc-based encoding, "
505 "single-byte characters]", locname);
506
508 // exercise sequences containing single-byte characters
509
510#undef TEST
511#define TEST(from, nc, maxi, res) \
512 test_length (wchar_t (), __LINE__, 0, cvt_libc, \
513 from, std::size_t (nc), maxi, res)
514
515 TEST (0, 0, 0, 0);
516 TEST ("", 0, 0, 0);
517 TEST ("A", 1, 0, 0);
518 TEST ("AB", 2, 1, 1);
519 TEST ("AB", 2, 2, 2);
520 TEST ("AB", 2, 3, 2);
521 TEST ("ABC", 3, 0, 0);
522 TEST ("ABC", 3, 1, 1);
523 TEST ("ABC", 3, 2, 2);
524 TEST ("ABC", 3, 3, 3);
525 TEST ("ABC", 3, 4, 3);
526
527 // exercise embedded NULs
528 TEST ("\0BC", 3, 3, 3);
529 TEST ("A\0C", 3, 3, 3);
530 TEST ("AB\0", 3, 3, 3);
531 TEST ("\0\0C", 3, 3, 3);
532 TEST ("A\0\0", 3, 3, 3);
533 TEST ("\0B\0", 3, 3, 3);
534 TEST ("\0\0\0", 3, 3, 3);
535
537 // exercise sequences containing 2-byte characters
538
539 if (!rw_warn (2 <= mb_cur_max, 0, __LINE__,
540 "no multibyte characters found, skipping test")) {
541 return;
542 }
543
544 char* sequences = 0;
545
546 // verify the length of each character
547 for (std::size_t i = 0; i < mb_cur_max; ++i) {
548 const std::size_t mb_len = std::strlen (mb_chars [i]);
549
550 if (!rw_error (i + 1 == mb_len, 0, __LINE__,
551 "unexpected multibyte character length: "
552 "%zu, expected %zu", mb_len, i + 1)) {
553 return;
554 }
555
556 sequences = rw_sprintfa ("%s%s%#s",
557 sequences ? sequences : "",
558 i ? ", " : "", mb_chars [i]);
559 }
560
561 rw_info (0, 0, 0, "locale (\"%s\") [libc-based encoding, "
562 "MB_CUR_MAX = %zu, multi-byte characters: %s]",
563 locname, mb_cur_max, sequences);
564
565 std::free (sequences);
566
567#ifdef _RWSTD_OS_SUNOS
568
569 if (!rw_warn (std::strcmp ("5.7", _RWSTD_OS_RELEASE), 0, __LINE__,
570 "skipping tests due to a SunOS 5.7 libc bug")) {
571 return;
572 }
573
574#endif // _RWSTD_OS_SUNOS
575
576 char mb_string [256];
577
578 // create a sequence of two multibyte characters
579 rw_sprintf (mb_string, "%s%s", mb_chars [0], mb_chars [1]);
580
581 // +------------------- source sequence of multibyte externT characters
582 // | +-------- lenght of externT sequence in chars (bytes)
583 // | | +----- maximum number of internT characters
584 // | | | +-- expected result in externT characters (bytes)
585 // | | | |
586 // V V V V
587 TEST (mb_string, 0, 0, 0);
588 TEST (mb_string, 1, 1, 1);
589 TEST (mb_string, 1, 1, 1);
590 TEST (mb_string, 2, 1, 1);
591 TEST (mb_string, 2, 2, 1);
592 TEST (mb_string, 3, 1, 1);
593 TEST (mb_string, 3, 2, 3);
594 TEST (mb_string, 3, 3, 3);
595
596 TEST (mb_string, 3, -1, 3);
597
598 // exercise embedded NULs
599 rw_sprintf (mb_string, "%c%s%s", '\0', mb_chars [0], mb_chars [1]);
600 TEST (mb_string, 4, 3, 4);
601
602 rw_sprintf (mb_string, "%s%c%s", mb_chars [0], '\0', mb_chars [1]);
603 TEST (mb_string, 4, 3, 4);
604
605 rw_sprintf (mb_string, "%s%s%c", mb_chars [0], mb_chars [1], '\0');
606 TEST (mb_string, 4, 3, 4);
607
608 rw_sprintf (mb_string, "%c%c%s", '\0', '\0', mb_chars [0]);
609 TEST (mb_string, 3, 3, 3);
610
611 rw_sprintf (mb_string, "%c%c%s", '\0', '\0', mb_chars [1]);
612 TEST (mb_string, 4, 3, 4);
613
615 // exercise sequences containing 3-byte characters
616
617 if (mb_cur_max < 3)
618 return;
619
620 // create a sequence of three multibyte characters, 3, 2,
621 // and 1 byte long (and total length of (3+2+1)=6 bytes)
622 // with the following pattern: "<333><22><1>"
623 rw_sprintf (mb_string, "%s%s%s",
624 mb_chars [2], mb_chars [1], mb_chars [0]);
625
626 TEST (mb_string, 0, 3, 0); // ""
627 TEST (mb_string, 1, 3, 0); // "3"
628 TEST (mb_string, 2, 3, 0); // "33"
629 TEST (mb_string, 3, 3, 3); // "333" -> 1 complete internT
630 TEST (mb_string, 4, 3, 3); // "3332"
631 TEST (mb_string, 5, 3, 5); // "33322" -> 2 complete internT's
632 TEST (mb_string, 6, 3, 6); // "333221" -> 3 complete internT's
633 TEST (mb_string, 6, 4, 6);
634 TEST (mb_string, 6, -1, 6);
635
637 // exercise sequences containing 4-byte characters
638
639 if (mb_cur_max < 4)
640 return;
641
642 // create a sequence of four multibyte characters, 4, 3, 2,
643 // and 1 byte long (and total length of (4+3+2+1)=10 bytes)
644 // with the following pattern: "<4444><333><22><1>"
645 rw_sprintf (mb_string, "%s%s%s%s",
646 mb_chars [3], mb_chars [2], mb_chars [1], mb_chars [0]);
647
648 TEST (mb_string, 0, 4, 0); // ""
649 TEST (mb_string, 1, 4, 0); // "4"
650 TEST (mb_string, 2, 4, 0); // "44"
651 TEST (mb_string, 3, 4, 0); // "444"
652 TEST (mb_string, 4, 4, 4); // "4444" -> 1 complete internT
653 TEST (mb_string, 5, 4, 4); // "44443"
654 TEST (mb_string, 6, 4, 4); // "444433"
655 TEST (mb_string, 7, 4, 7); // "4444333" -> 2 complete internT's
656 TEST (mb_string, 8, 4, 7); // "44443332"
657 TEST (mb_string, 9, 4, 9); // "444433322" -> 3 complete internT's
658 TEST (mb_string, 10, 4, 10); // "4444333221" -> 4 complete internT's
659 TEST (mb_string, 10, 5, 10);
660 TEST (mb_string, 10, -1, 10);
661
663 // exercise sequences containing 5-byte characters
664
665 if (mb_cur_max < 5)
666 return;
667
668 // create a sequence of five multibyte characters, 5, 4, 3, 2,
669 // and 1 byte long (and total length of (5+4+3+2+1)=15 bytes)
670 // with the following pattern: "<55555><4444><333><22><1>"
671 rw_sprintf (mb_string, "%s%s%s%s%s",
672 mb_chars [4], mb_chars [3], mb_chars [2], mb_chars [1],
673 mb_chars [0]);
674
675 TEST (mb_string, 0, 5, 0); // ""
676 TEST (mb_string, 1, 5, 0); // "5"
677 TEST (mb_string, 2, 5, 0); // "55"
678 TEST (mb_string, 3, 5, 0); // "555"
679 TEST (mb_string, 4, 5, 0); // "5555"
680 TEST (mb_string, 5, 5, 5); // "55555"
681 TEST (mb_string, 6, 5, 5); // "555554"
682 TEST (mb_string, 7, 5, 5); // "5555544"
683 TEST (mb_string, 8, 5, 5); // "55555444"
684 TEST (mb_string, 9, 5, 9); // "555554444"
685 TEST (mb_string, 10, 5, 9); // "5555544443"
686 TEST (mb_string, 11, 5, 9); // "55555444433"
687 TEST (mb_string, 12, 5, 12); // "555554444333"
688 TEST (mb_string, 13, 5, 12); // "5555544443332"
689 TEST (mb_string, 14, 5, 14); // "55555444433322"
690 TEST (mb_string, 15, 5, 15); // "555554444333221"
691 TEST (mb_string, 15, 6, 15);
692 TEST (mb_string, 15, -1, 15);
693
694 // create a sequence of five multibyte characters, each 5 bytes long
695 // with the following pattern: "<55555><55555><55555><55555><55555>"
696 rw_sprintf (mb_string, "%s%s%s%s%s",
697 mb_chars [4], mb_chars [4], mb_chars [4], mb_chars [4],
698 mb_chars [4]);
699
700 TEST (mb_string, 5, 5, 5); // "<55555>"
701 TEST (mb_string, 6, 5, 5); // "<55555><5"
702 TEST (mb_string, 9, 5, 5); // "<55555><5555"
703 TEST (mb_string, 10, 1, 5); // "<55555><55555>"
704 TEST (mb_string, 10, 2, 10);
705 TEST (mb_string, 10, 5, 10);
706 TEST (mb_string, 11, 5, 10); // "<55555><55555><5"
707 TEST (mb_string, 14, 5, 10); // "<55555><55555><5555"
708 TEST (mb_string, 15, 5, 15); // "<55555><55555><55555>"
709
710 rw_sprintf (mb_string, "%s%s%s%s%s",
711 mb_chars [4], mb_chars [0], mb_chars [4], mb_chars [4],
712 mb_chars [4]);
713
714 // internT: 0 1 2 3 4 5
715 // externT: <-----><-><-----><-----><-----><
716 // "<55555><1><55555><55555><55555>"
717 TEST (mb_string, 5, 5, 5); // |-----> > > > >
718 TEST (mb_string, 6, 5, 6); // |--------> > > >
719 TEST (mb_string, 7, 5, 6); // |----------- > > >
720 TEST (mb_string, 8, 5, 6); // |------------ > > >
721 TEST (mb_string, 9, 5, 6); // |------------- > > >
722 TEST (mb_string, 10, 5, 6); // |-------------- > > >
723 TEST (mb_string, 11, 5, 11); // |---------------> > >
724 TEST (mb_string, 12, 5, 11); // |---------------- > >
725 TEST (mb_string, 15, 5, 11); // |--------------------- > >
726 TEST (mb_string, 16, 5, 16); // |----------------------> >
727 TEST (mb_string, 21, 5, 21); // |----------------------------->
728}
729
730#endif // _RWSTD_NO_WCHAR_T
731
732
733static void
734test_wcodecvt_byname ()
735{
736 rw_info (0, 0, 0,
737 "std::codecvt_byname<wchar_t, char, mbstate_t>::length "
738 "(state_type&, const extern_type*, const extern_type*, "
739 "size_t)");
740
741#ifndef _RWSTD_NO_WCHAR_T
742
743 test_wcodecvt_byname_algorithmic ();
744 test_wcodecvt_byname_table_based ();
745 test_wcodecvt_byname_libc_based ();
746
747#else // if defined (_RWSTD_NO_WCHAR_T)
748
749 rw_warn (0, 0, __LINE__, "_RWSTD_NO_WCHAR_T #defined, cannot test");
750
751#endif // _RWSTD_NO_WCHAR_T
752
753}
754
755
757static int no_codecvt;
758static int no_codecvt_byname;
759static int no_wcodecvt;
760static int no_wcodecvt_byname;
761
762static int
763run_test (int, char*[])
764{
765 // set up RWSTD_LOCALE_ROOT and other environment variables
766 // here as opposed to at program startup to work around a
767 // SunOS 5.7 bug in putenv() (PR #30017)
769
770#undef TEST
771#define TEST(what) \
772 if (no_ ## what) { \
773 rw_note (0, 0, __LINE__, "%s test disabled", #what); \
774 } \
775 else { \
776 test_ ## what (); \
777 } typedef void unused_typedef
778
779
780 if (rw_enabled ("char")) {
781 TEST (codecvt);
782 TEST (codecvt_byname);
783 }
784 else {
785 rw_note (0, 0, 0, "char tests disabled");
786 }
787
788 if (rw_enabled ("wchar_t")) {
789 TEST (wcodecvt);
790 TEST (wcodecvt_byname);
791 }
792 else {
793 rw_note (0, 0, 0, "wchar_t tests disabled");
794 }
795
796 return 0;
797}
798
799
801int main (int argc, char *argv[])
802{
803 return rw_test (argc, argv, __FILE__,
804 "lib.locale.codecvt.virtuals",
805 0 /* no comment */, run_test,
806 "|-no-codecvt# "
807 "|-no-codecvt_byname# "
808 "|-no-wcodecvt# "
809 "|-no-wcodecvt_byname# ",
810 &no_codecvt,
811 &no_codecvt_byname,
812 &no_wcodecvt,
813 &no_wcodecvt_byname);
814}
#define i
Definition 17.names.cpp:126
#define nchars
Definition 17.names.cpp:502
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define loc
Definition 17.names.cpp:492
volatile int result
std::codecvt< char, char, std::mbstate_t > Codecvt
std::codecvt< char, char, std::mbstate_t > Codecvt
std::codecvt< wchar_t, char, std::mbstate_t > WCodecvt
std::codecvt_byname< wchar_t, char, std::mbstate_t > WCodecvtByname
const char * create_locale()
#define STRICT(from, nc, maxi, res)
std::codecvt_byname< char, char, std::mbstate_t > CodecvtByname
void test_codecvt(const Codecvt *pcvt=0)
#define RELAXD(from, nc, maxi, res)
#define TEST(from, nchars, maxi, result)
const char * locale_root
void test_length(internT, 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)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
#define _RWSTD_PATH_SEP
Definition _config.h:297
#define _TRY
Definition _defs.h:850
#define _CATCH(ex)
Definition _defs.h:851
const char * type_name() const
Definition any.cpp:310
_TEST_EXPORT int rw_enabled(const char *name)
_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_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_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 _RWSTD_SIZE_T rw_fwrite(const char *, const void *, _RWSTD_SIZE_T=~0, const char *="w")
_TEST_EXPORT const char * rw_set_locale_root()
Definition locale.cpp:324
_TEST_EXPORT const char * rw_localedef(const char *, const char *, const char *, const char *)
Definition locale.cpp:154
char rw_mbchar_array_t[_RWSTD_MB_LEN_MAX][_RWSTD_MB_LEN_MAX]
Definition rw_locale.h:95
_TEST_EXPORT const char * rw_find_mb_locale(_RWSTD_SIZE_T *, rw_mbchar_array_t)
_TEST_EXPORT char * rw_sprintfa(const char *fmt,...)
Definition printf.cpp:3258
_TEST_EXPORT int rw_snprintf(char *, _RWSTD_SIZE_T, const char *,...)
_TEST_EXPORT int rw_sprintf(char *, const char *,...)
Definition printf.cpp:3284