44#ifndef _RWSTD_NO_NEW_HEADER
49# include <sys/types.h>
60# define open(f,m) _open (f, _##m)
61# define close(f) _close (f)
63# define open(f,m) open (f, m)
64# define close(f) close (f)
70struct CodeCvt: std::codecvt<charT, char, std::mbstate_t>
72 typedef std::codecvt<charT, char, std::mbstate_t>
Base;
76 typedef typename Base::result
result;
109#ifndef _RWSTD_NO_MBSINIT
122 Base::do_in (state, from, from_end, from_next,
123 to, to_end, to_next);
126 return std::codecvt_base::partial;
129 return std::codecvt_base::noconv;
135template <
class charT>
137template <
class charT>
139template <
class charT>
141template <
class charT>
143template <
class charT>
161 const char*
const classic_name =
162 std::strcpy (namebuf, std::setlocale (
LC_ALL,
"C"));
165 if (std::strcmp (
name,
"C") && std::strcmp (
name,
"POSIX")) {
168 const char*
const fullname = std::setlocale (
LC_ALL,
name);
169 if (std::strcmp (fullname, classic_name)) {
176 std::setlocale (
LC_ALL,
"C");
186 std::setlocale (
LC_ALL,
"C");
194# define CAT_NAME "./rwstdmessages.cat"
195# define MSG_NAME "rwstdmessages.msg"
197# define CAT_NAME "rwstdmessages.dll"
198# define MSG_NAME "rwstdmessages.rc"
201#define NLS_CAT_NAME "rwstdmessages"
204#define MAX_MESSAGES 5
211 return (set - 1) * 5 + id;
223static const char*
const
225 {
"First set, first message",
226 "First set, second message",
227 "First set, third message",
228 "First set, fourth message",
229 "First set, fifth message"
231 {
"Second set, first message",
232 "Second set, second message",
233 "Second set, third message",
234 "Second set, fourth message",
235 "Second set, fifth message"
237 {
"Third set, first message",
238 "Third set, second message",
239 "Third set, third message",
240 "Third set, fourth message",
241 "Third set, fifth message"
243 {
"Fourth set, first message",
244 "Fourth set, second message",
245 "Fourth set, third message",
246 "Fourth set, fourth message",
247 "Fourth set, fifth message"
249 {
"Fifth set, first message",
250 "Fifth set, second message",
251 "Fifth set, third message",
252 "Fifth set, fourth message",
253 "Fifth set, fifth message"
257static std::string catalog;
262template <
class charT>
263std::basic_string<charT>
widen (std::string message)
265 std::basic_string<charT>
result;
266 for (std::size_t
i = 0;
i < message.length();
i++) {
277template <
class charT>
282 const std::locale
loc =
283 loc_name ? std::locale (loc_name) : std::locale ();
285 typedef std::messages<charT>
Messages;
288 bool facet_exists = std::has_facet<Messages>(
loc);
291 "has_facet<messages<%s> >(locale(%{?}%#s%{;})) == true",
292 cname, 0 != loc_name, loc_name);
296 std::use_facet<Messages>(
loc);
298#ifndef _RWSTD_NO_EXCEPTIONS
302 "use_fact<messages<%s> >(locale(%{?}%#s%{;})) "
303 "unexpectedly threw exception(%#s)",
304 cname, 0 != loc_name, loc_name, ex.what ());
308 "use_fact<messages<%s> >(locale(%{?}%#s%{;})) "
309 "unexpectedly threw an unknown exception",
310 cname, 0 != loc_name, loc_name);
315 const bool byname = loc_name
316 && std::strcmp (loc_name,
"C") && std::strcmp (loc_name,
"POSIX");
318 facet_exists = std::has_facet<MessagesByname>(
loc);
320 rw_assert (byname == facet_exists, 0, __LINE__,
321 "has_fact<messages_byname<%s> >(locale(%{?}%#s%{;})) == %b",
322 cname, 0 != loc_name, loc_name);
327 std::use_facet<MessagesByname>(
loc);
330 "use_fact<messages_byname<%s> >(locale(%{?}%#s%{;})) "
332 cname, 0 != loc_name, loc_name);
336 "use_fact<messages_byname<%s> >(locale(%{?}%#s%{;})) "
337 "unexpectedly threw exception(%#s)",
338 cname, 0 != loc_name, loc_name, ex.what ());
342 "use_fact<messages<%s> >(locale(%{?}%#s%{;})) "
343 "unexpectedly threw an unknown exception",
344 cname, 0 != loc_name, loc_name);
353template <
class charT>
354std::messages_base::catalog
356 const char *cat_name,
const std::locale &
loc,
357 int expect,
const char *cname,
int line)
359 std::messages_base::catalog cat = -1;
368 const bool expect_success = expect >= 0;
369 const bool expect_failure = expect == -1;
370 const bool expect_exception = expect < -1;
372 const char*
const nlspath = std::getenv (
"NLSPATH");
376 cat = (msgs.open)(cat_name,
loc);
379 (expect_success && -1 < cat) || (expect_failure && cat < 0);
382 "messages<%s>::open(%#s, locale(%#s))"
383 "%{?} > -1%{:}%{?} == -1 %{;}%{;}, got %d"
384 "%{?}; failed to throw an exception%{;}; NLSPATH=%s",
385 cname, cat_name,
loc.name ().c_str (),
386 expect_success, expect_failure, cat,
387 expect_exception, nlspath);
390#ifndef _RWSTD_NO_EXCEPTIONS
394 "messages<%s>::open(%#s, locale(%#s)) unexpectedly "
395 "threw exception(%#s); NLSPATH=%s",
396 cname, cat_name,
loc.name ().c_str (), ex.what (), nlspath);
400 "messages<%s>::open(%#s, locale(%#s)) unexpectedly "
401 "threw an unknown exception; NLSPATH=%s",
402 cname, cat_name,
loc.name ().c_str (), nlspath);
412template <
class charT>
415 std::messages_base::catalog cat,
416 bool expect_exception,
417 const char *cname,
int line)
424 "messages<%s>::close(%d) failed "
425 "to throw an expected exception",
429#ifndef _RWSTD_NO_EXCEPTIONS
433 "messages<%s>::close(%d) unexpectedly "
434 "threw exception(%#s)",
435 cname, cat, ex.what ());
439 "messages<%s>::close(%d) unexpectedly "
440 "threw an unknown exception",
450template <
class charT>
462 next_fd [0] = fdcount [0] = 0;
466 "std::messages<%s>::open() and close() in locale(#%s)",
471 const std::locale
loc =
472 loc_name ? std::locale (loc_name) : std::locale ();
474 const std::messages<charT>& msgs =
475 std::use_facet<std::messages<charT> >(
loc);
477 const std::messages_base::catalog cat =
490 next_fd [1] = fdcount [1] = 0;
493 rw_assert (next_fd [1] == next_fd [0] && fdcount [0] == fdcount [1],
495 "std::messages<%s>::close() leaked %d file descriptor(s) "
496 "(or descriptor mismatch)",
497 cname, fdcount [1] - fdcount [0]);
502template <
class charT>
504 const char*
const text[5][5],
509 const std::locale
loc =
510 loc_name ? std::locale (loc_name) : std::locale ();
512 const std::messages<charT>& msgs =
513 std::use_facet<std::messages<charT> > (
loc);
515 const charT def[] = {
516 'N',
'o',
' ',
'm',
'e',
's',
's',
'a',
'g',
'e',
'.',
'\0'
519 std::messages_base::catalog cat = -1;
526 typedef std::char_traits<charT>
Traits;
528 typedef std::basic_string<charT, Traits, Allocator>
String;
530 for (
int setId = 1; setId <=
MAX_SETS; ++setId) {
534 const int id =
msg_id (setId, msgId);
535 const String got = msgs.get (cat, setId,
id, def);
537 rw_assert (got == widen<charT>(text [setId - 1][msgId - 1]),
539 "messages<%s>::get(%d, %d, %d, %{*Ac}) == %#s, "
541 cname, cat, setId,
id,
542 int (
sizeof *def), def,
543 text [setId - 1][msgId - 1],
544 int (
sizeof (
charT)), &got);
549 const std::messages_base::catalog bad_cat = 777;
554 const String got = msgs.get (bad_cat, 1, 1, def);
557 "messages<%s>::get(%d, 1, 1, %{*Ac}) == %{*Ac}, got %{#*S}",
558 cname, bad_cat,
int (
sizeof *def), def,
559 int (
sizeof *def), def,
int (
sizeof (
charT)), &got);
561#ifndef _RWSTD_NO_EXCEPTIONS
565 "messages<%s>::get(%d, 1, 1, %{*Ac}) unexpectedly threw "
566 "exception(%#s)", cname, bad_cat,
int (
sizeof *def), def,
576 rw_assert (msgs.get (cat, 777, 1, def) == def, 0, __LINE__,
577 "messages<%s>::get(%d, 777, 1, %{#*Ac}) == %{#*Ac}",
578 cname, cat, int (
sizeof *def), def,
int (
sizeof *def), def);
582 rw_assert (msgs.get (cat, 1, 777, def) == def, 0, __LINE__,
583 "messages<%s>::get(%d, 777, 1) == \"\"", cname);
590template <
class charT>
595 const std::locale
loc (std::locale::classic (), &
cvt);
597 const charT def[] = {
598 'N',
'o',
' ',
'm',
'e',
's',
's',
'a',
'g',
'e',
'.',
'\0'
601 const std::messages<charT>& msgs =
602 std::use_facet <std::messages<charT> >(
loc);
606 std::messages_base::catalog cat = -1;
613 cvt.check_state_ =
true;
615 const int msgid =
msg_id (1, 1);
616 std::basic_string<charT> got = msgs.get (cat, 1, msgid, def);
618 "messages<%s>::get(%d, 1, %d, const char_type*) "
619 "uses codecvt<%1$s, char>", cname, cat, msgid);
622 "messages<%s>::get(%d, 1, %d, const char_type*) "
623 "initializes mbstate_t argument", cname, cat, msgid);
625 cvt.check_state_ =
false;
628 got = msgs.get (cat, 1, msgid, def);
630 "messages<%s>::get(%d, 1, %d, %{*Ac}) == %{*Ac}",
631 cname, cat, msgid,
int (
sizeof *def), def,
632 int (
sizeof *def), def);
634 cvt.partial_ =
false;
637 got = msgs.get (cat, 1, msgid, def);
638 rw_assert (got == widen<charT>(std::string(messages[0][0])), 0, __LINE__,
639 "messages<%s>::get(%d, 1, %d, %{*Ac}) == %#s, got %{#*S}",
640 cname, cat, msgid,
int (
sizeof *def), def,
641 messages [0][0],
int (
sizeof (
charT)), &got);
653template <
class charT>
659 if (!
rw_error (0 != getcwd (cwd, 2048), 0, __LINE__,
660 "getcwd(%#p, %u) failed: %{#m} (%m)", cwd, 2048))
663 char*
const nlspath =
new char [std::strlen (cwd) + 512];
666 std::sprintf (nlspath,
"NLSPATH=%s/%%N.cat", cwd);
669 const std::locale
loc;
671 const std::messages<charT>& msgs =
672 std::use_facet <std::messages<charT> >(
loc);
674 const std::messages_base::catalog cat =
686template <
class charT>
690 RW_ASSERT (0 != std::getenv (
"NLSPATH"));
692 char catalog_names [24][24];
693 const std::size_t NCATS =
sizeof catalog_names /
sizeof *catalog_names;
695 std::messages_base::catalog cats [NCATS];
698 const int fd1 =
open (__FILE__, O_RDONLY);
700 const std::locale
loc = std::locale::classic ();
702 const std::messages<charT>& msgs =
703 std::use_facet<std::messages<charT> > (
loc);
707 for (
i = 0;
i < NCATS;
i++) {
709 char msg_name [NCATS];
712 std::sprintf (msg_name,
"rwstdmessages_%d.msg",
int (
i));
714 std::sprintf (msg_name,
"rwstdmessages_%d.rc",
int (
i));
719 const char*
const dot = std::strrchr (msg_name,
'.');
720 std::strncpy (catalog_names[
i], msg_name, dot - msg_name);
721 *(catalog_names[
i] + (dot - msg_name)) =
'\0';
725 loc, 0, cname, __LINE__);
729 for (
i = 0;
i < NCATS; ++
i) {
734 int fd2 =
open (__FILE__, O_RDONLY);
736 "messages<%s>::close() leaked %d file descriptors",
737 cname, fd2 - fd1 - 1);
740 for (
i = 0;
i < NCATS; ++
i) {
742 loc, 0, cname, __LINE__);
745 for (
i = NCATS;
i-- > 0; ) {
753 fd2 =
open (__FILE__, O_RDONLY);
755 "messages<%s>::close() leaked %d file descriptors",
756 cname, fd2 - fd1 - 1);
774template <
class charT>
778 "has_facet<messages<%s> > tests disabled", cname)) {
781 test_has_facet<charT>(0, cname);
784 test_has_facet<charT>(
"C", cname);
787 test_has_facet<charT>(locname, cname);
791 "messages<%s>::open() and close() tests disabled", cname)) {
792 test_open_close<charT>(
"C", cname);
793 test_open_close<charT>(locname, cname);
797 "messages<%s>::get() tests disabled", cname)) {
798 test_get<charT>(
"C", messages, cname);
799 test_get<charT>(locname, messages, cname);
803 "messages<%s> codecvt tests disabled", cname))
804 test_use_codecvt<charT>(cname);
807 "messages<%s> NLSPATH tests disabled", cname))
808 test_use_nls_path<charT>(cname);
811 "messages<%s> codecvt tests disabled", cname))
812 stress_test<charT>(cname);
825 const int p =
rw_putenv (
"LC__FASTMSG=false");
826 rw_note (!
p, 0, __LINE__,
"failed to set LC__FASTMSG");
830#ifdef _RWSTD_NO_DYNAMIC_CAST
835 "dynamic_cast not supported, disabling has_facet tests");
844 catalog.append (messages [
i][
j], std::strlen (messages [
i][
j]) + 1);
846 catalog.append (1,
'\0');
855#ifndef _RWSTD_NO_WCHAR_T
869int main (
int argc,
char *argv[])
871 return rw_test (argc, argv, __FILE__,
872 "lib.category.messages",
std::messages_byname< char > MessagesByname
std::messages< char > Messages
void test_use_nls_path(const char *cname)
const char * find_named_locale()
void test_use_codecvt(const char *cname)
void test_open_close(const char *loc_name, const char *cname)
int msg_id(int set, int id)
void test_has_facet(const char *loc_name, const char *cname)
void close_catalog(const std::messages< charT > &msgs, std::messages_base::catalog cat, bool expect_exception, const char *cname, int line)
void test_messages(charT, const char *cname, const char *locname)
std::basic_string< charT > widen(std::string message)
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)
void test_get(const char *loc_name, const char *const text[5][5], const char *cname)
void stress_test(const char *cname)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define _RWSTD_UNUSED(arg)
_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 *,...)
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_putenv(const char *, int=-1)
_TEST_EXPORT int rw_nextfd(int *)
_TEST_EXPORT char * rw_locales(int=_UNUSED_CAT, const char *=0, bool=true)
_TEST_EXPORT int rw_create_catalog(const char *, const char *)
_TEST_EXPORT int rw_system(const char *,...)
std::codecvt< charT, char, std::mbstate_t > Base
Base::intern_type intern_type
bool do_always_noconv() const _THROWS(())
Base::extern_type extern_type
CodeCvt(std::size_t ref=1U)
Base::state_type state_type
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