55 decimal_point_sz = std::strlen (plconv->decimal_point) + 1,
56 thousands_sep_sz = std::strlen (plconv->thousands_sep) + 1,
57 grouping_sz = std::strlen (plconv->grouping) + 1,
58 int_curr_symbol_sz = std::strlen (plconv->int_curr_symbol) + 1,
59 currency_symbol_sz = std::strlen (plconv->currency_symbol) + 1,
60 mon_decimal_point_sz = std::strlen (plconv->mon_decimal_point) + 1,
61 mon_thousands_sep_sz = std::strlen (plconv->mon_thousands_sep) + 1,
62 mon_grouping_sz = std::strlen (plconv->mon_grouping) + 1,
63 positive_sign_sz = std::strlen (plconv->positive_sign) + 1,
64 negative_sign_sz = std::strlen (plconv->negative_sign) + 1;
66 const std::size_t total_sz =
72 + mon_decimal_point_sz
73 + mon_thousands_sep_sz
78 const std::size_t bufsize =
sizeof (std::lconv) + total_sz;
84 plconv2->decimal_point = (pbuf +=
sizeof (std::lconv));
85 std::memcpy (pbuf, plconv->decimal_point, decimal_point_sz);
87 plconv2->thousands_sep = (pbuf += decimal_point_sz);
88 std::memcpy (pbuf, plconv->thousands_sep, thousands_sep_sz);
90 plconv2->grouping = (pbuf += thousands_sep_sz);
91 std::memcpy (pbuf, plconv->grouping, grouping_sz);
93 plconv2->int_curr_symbol = (pbuf += grouping_sz);
94 std::memcpy (pbuf, plconv->int_curr_symbol, int_curr_symbol_sz);
96 plconv2->currency_symbol = (pbuf += int_curr_symbol_sz);
97 std::memcpy (pbuf, plconv->currency_symbol, currency_symbol_sz);
99 plconv2->mon_decimal_point = (pbuf += currency_symbol_sz);
100 std::memcpy (pbuf, plconv->mon_decimal_point, mon_decimal_point_sz);
102 plconv2->mon_thousands_sep = (pbuf += mon_decimal_point_sz);
103 std::memcpy (pbuf, plconv->mon_thousands_sep, mon_thousands_sep_sz);
105 plconv2->mon_grouping = (pbuf += mon_thousands_sep_sz);
106 std::memcpy (pbuf, plconv->mon_grouping, mon_grouping_sz);
108 plconv2->positive_sign = (pbuf += mon_grouping_sz);
109 std::memcpy (pbuf, plconv->positive_sign, positive_sign_sz);
111 plconv2->negative_sign = (pbuf += positive_sign_sz);
112 std::memcpy (pbuf, plconv->negative_sign, negative_sign_sz);
114 plconv2->int_frac_digits = plconv->int_frac_digits;
115 plconv2->frac_digits = plconv->frac_digits;
116 plconv2->p_cs_precedes = plconv->p_cs_precedes;
117 plconv2->p_sep_by_space = plconv->p_sep_by_space;
118 plconv2->n_cs_precedes = plconv->n_cs_precedes;
119 plconv2->n_sep_by_space = plconv->n_sep_by_space;
120 plconv2->p_sign_posn = plconv->p_sign_posn;
121 plconv2->n_sign_posn = plconv->n_sign_posn;
123#ifndef _RWSTD_NO_LCONV_INT_FMAT
125 plconv2->int_p_cs_precedes = plconv->int_p_cs_precedes;
126 plconv2->int_p_sep_by_space = plconv->int_p_sep_by_space;
127 plconv2->int_n_cs_precedes = plconv->int_n_cs_precedes;
128 plconv2->int_n_sep_by_space = plconv->int_n_sep_by_space;
129 plconv2->int_p_sign_posn = plconv->int_p_sign_posn;
130 plconv2->int_n_sign_posn = plconv->int_n_sign_posn;
139template <
class charT>
144 const char *char_name_;
145 const char *locname_;
148 const char *lc_monetary_;
152 typedef std::moneypunct<charT, false>
Punct;
155 Test (
const char *cname,
bool intl)
156 : loc_ (), intl_ (intl),
158 locname_ (0), lang_ (0), lc_all_ (0), lc_monetary_ (0) { }
169 typedef std::basic_string<charT, Traits, Allocator>
String;
183template <
class charT>
188 loc_ = std::locale::classic ();
192 typedef std::moneypunct_byname<charT, false> MoneyPunctByname;
193 typedef std::moneypunct_byname<charT, true> MoneyPunctIntlByname;
209 check_frac_digits (0 );
212 const charT empty[] = {
'\0' };
213 check_curr_symbol (empty);
214 check_positive_sign (empty);
215 check_negative_sign (empty);
221 std::money_base::pattern fmat = {
224 std::money_base::symbol,
225 std::money_base::sign,
226 std::money_base::none,
227 std::money_base::value
231 const UChar cpat [4] = {
'?',
'?',
'?', 0 };
232 check_format (
false , fmat, cpat);
233 check_format (
true , fmat, cpat);
237 check_moneypunct (
"");
240 const char *first_non_c = 0;
243 for (
const char*
s =
rw_locales ();
s && *
s;
s += std::strlen (
s) + 1) {
244 if (check_moneypunct (
s))
246 && std::strcmp (
"C",
s)
247 && std::strcmp (
"POSIX",
s)) {
260 assert (std::strlen(first_non_c) +
sizeof "LC_ALL=" <=
sizeof envvar);
262 std::sprintf (envvar,
"LC_ALL=%s", first_non_c);
264 check_moneypunct (
"");
272std::string
convert (
const char*,
const char *
s,
const char*)
274 return std::string (
s);
281convert (
const char *locname,
const char *
s,
const wchar_t*)
284 std::string saved_loc;
286 if (
const char *savename = std::setlocale (
LC_ALL, 0))
287 saved_loc = savename;
290 const char *
loc = std::setlocale (
LC_ALL, locname);
293 "%s:%d: setlocale (LC_ALL, %s) = 0: %m\n",
295 return std::wstring ();
299 std::wstring
res ((
wchar_t*)0, 64);
304 std::mbstowcs (&
res [0],
s,
res.capacity ());
306 if (
res.capacity () ==
n)
308 res.reserve (
res.capacity () * 2);
309 else if (std::size_t (-1) ==
n) {
313 std::setlocale (
LC_ALL, saved_loc.c_str ());
316 "%s:%d: mbstowcs(..., %#s, %zu) "
317 "= -1: %m\n", __FILE__, __LINE__,
319 res = std::wstring ();
331 std::setlocale (
LC_ALL, saved_loc.c_str ());
338template <
class charT>
343 char locnamebuf [256];
344 const char *
loc = std::setlocale (
LC_ALL, locname);
348 loc = std::strcpy (locnamebuf,
loc);
354 lang_ = std::getenv (
"LANG");
355 lc_all_ = std::getenv (
"LC_ALL");
356 lc_monetary_ = std::getenv (
"LC_MONETARY");
363 lc_monetary_ =
"(null)";
368 const std::lconv*
const plconv =
lconvdup (std::localeconv ());
374 std::setlocale (
LC_ALL,
"");
377 loc_ = std::locale (locname);
388 if ( std::strcmp (
"C", locname)
389 && std::strcmp (
"C",
loc)) {
398 check_frac_digits (plconv->int_frac_digits);
411 check_frac_digits (0);
421 check_curr_symbol (
s);
425 check_positive_sign (
s);
429 check_negative_sign (
s);
431 check_format (*plconv);
444template <
class charT>
452 "moneypunct<%s, %b>::decimal_point() == %#lc, got %#lc "
453 "in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
455 locname_, lang_, lc_all_, lc_monetary_);
460template <
class charT>
468 "moneypunct<%s, %b>::thousands_sep() == %#lc, got %#lc "
469 "in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
471 locname_, lang_, lc_all_, lc_monetary_);
476template <
class charT>
484 "moneypunct<%s, %b>::frac_digits() == %d, got %d "
485 "in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
487 locname_, lang_, lc_all_, lc_monetary_);
492template <
class charT>
496 const std::string
s = intl_ ?
507 const std::string *lng =
s.size () >
result.size () ? &
result : &
s;
508 const std::string *shrt =
s.size () <
result.size () ? &
result : &
s;
510 std::size_t
i = shrt->size () - 1;
512 for ( ;
i != lng->size (); ++
i)
513 if ((*shrt) [shrt->size () - 1] != (*lng)[
i])
517 "numpunct<%s, %b>::grouping() equivalent to %#s, got %#s "
518 "in locale (%#s) with LANG=%s, LC_ALL=%s, "
520 char_name_, intl_,
result.c_str (),
s.c_str (),
521 locname_, lang_, lc_all_, lc_monetary_);
525 "moneypunct<%s, %b>::grouping() == %#s, got %#s "
526 "in locale (%#s) with LANG=%s, LC_ALL=%s, "
528 char_name_, intl_,
result.c_str (),
s.c_str (),
529 locname_, lang_, lc_all_, lc_monetary_);
541 const std::string grp =
545 "moneypunct<%s, %b>::grouping() == numpunct<>::grouping() == "
546 "%{*Ac}, got %{*Ac} in locale (\"%s\") with LANG=%s, LC_ALL=%s, "
550 int (
sizeof (
charT)),
s.c_str (),
551 locname_, lang_, lc_all_, lc_monetary_);
559template <
class charT>
567 "moneypunct<%s, %b>::curr_symbol() == %{*Ac}, got %{*Ac} "
568 "in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
571 int (
sizeof (
charT)),
s.c_str (),
572 locname_, lang_, lc_all_, lc_monetary_);
577template <
class charT>
586 "moneypunct<%s, %b>::positive_sign() == %{*Ac}, got %{*Ac} "
587 "in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
590 int (
sizeof (
charT)),
s.c_str (),
591 locname_, lang_, lc_all_, lc_monetary_);
596template <
class charT>
605 "moneypunct<%s, %b>::negative_sign() == %{*Ac}, got %{*Ac} "
606 "in locale (\"%s\") with LANG=%s, LC_ALL=%s, LC_MONETARY=%s",
609 int (
sizeof (
charT)),
s.c_str (),
610 locname_, lang_, lc_all_, lc_monetary_);
615template <
class charT>
619 const UChar cpat [2][2][3] = {
628 { lc.p_cs_precedes, lc.p_sep_by_space, lc.p_sign_posn },
631 { lc.n_cs_precedes, lc.n_sep_by_space, lc.n_sign_posn }
634#ifndef _RWSTD_NO_LCONV_INT_FMAT
637 { lc.int_p_cs_precedes, lc.int_p_sep_by_space, lc.int_p_sign_posn},
640 { lc.int_n_cs_precedes, lc.int_n_sep_by_space, lc.int_n_sign_posn }
646 { lc.p_cs_precedes, lc.p_sep_by_space, lc.p_sign_posn },
647 { lc.n_cs_precedes, lc.n_sep_by_space, lc.n_sign_posn }
683 none = std::money_base::none,
684 space = std::money_base::space,
685 symbol = std::money_base::symbol,
686 sign = std::money_base::sign,
687 value = std::money_base::value
690 static const std::money_base::pattern patterns[] = {
692 { { sign,
value, symbol, none } },
693 { { sign,
value, symbol, none } },
694 { {
value, symbol, sign, none } },
695 { {
value, sign, symbol, none } },
696 { {
value, symbol, sign, none } },
698 { { sign,
value, space, symbol } },
699 { { sign,
value, space, symbol } },
700 { {
value, space, symbol, sign } },
701 { {
value, space, sign, symbol } },
702 { {
value, space, symbol, sign } },
704 { { sign, space,
value, symbol } },
705 { { sign, space,
value, symbol } },
706 { {
value, symbol, space, sign } },
707 { {
value, sign, space, symbol } },
708 { {
value, symbol, space, sign } },
710 { { sign, symbol,
value, none } },
711 { { sign, symbol,
value, none } },
712 { { symbol,
value, sign, none } },
713 { { sign, symbol,
value, none } },
714 { { symbol, sign,
value, none } },
716 { { sign, symbol, space,
value } },
717 { { sign, symbol, space,
value } },
718 { { symbol, space,
value, sign } },
719 { { sign, symbol, space,
value } },
720 { { symbol, sign, space,
value } },
722 { { sign, space, symbol,
value } },
723 { { sign, space, symbol,
value } },
724 { { symbol,
value, space, sign } },
725 { { sign, space, symbol,
value } },
726 { { symbol, space, sign,
value } }
731 enum { cs_precedes, sep_by_space, sign_posn };
734 if ( cpat [intl_][
neg][cs_precedes] > 1
735 || cpat [intl_][
neg][sep_by_space] > 2
736 || cpat [intl_][
neg][sign_posn] > 4)
740 cpat [intl_][
neg][cs_precedes] * 3 * 5
741 + cpat [intl_][
neg][sep_by_space] * 5
742 + cpat [intl_][
neg][sign_posn];
744 check_format (!
neg, patterns [
inx], cpat [intl_][
neg]);
750template <
class charT>
754 const std::money_base::pattern pat =
761 int counts [5] = { 0 };
763 for (
unsigned i = 0;
i !=
sizeof pat.field /
sizeof *pat.field;
i++) {
765 if (
UChar (pat.field [
i] < char (
sizeof counts /
sizeof *counts)))
766 ++counts [
UChar (pat.field [
i])];
769 if (std::money_base::none == pat.field [
i] && !
i)
771 "moneypunct<%s, %b>::%s_format() == %{LM}, "
772 "none must not appear first",
773 char_name_, intl_,
pos ?
"pos" :
"neg",
776 if ( std::money_base::space == pat.field [
i]
777 && !
i &&
i !=
sizeof pat.field /
sizeof *pat.field - 1)
779 "moneypunct<%s, %b>::%s_format() == %{LM}, "
780 "space must not appear first or last",
781 char_name_, intl_,
pos ?
"pos" :
"neg",
787 "moneypunct<%s, %b>::%s_format() == %{LM}, got %{LM}; "
788 "(cs_precedes = '\\%o', sep_by_space = '\\%o', "
789 "sign_posn = '\\%o')",
790 char_name_, intl_,
pos ?
"pos" :
"neg",
791 pat.field,
result.field, cpat [0], cpat [1], cpat [2]);
794 rw_assert (1 == counts [std::money_base::symbol], 0, __LINE__,
795 "money_base::symbol must apear exactly once, did %d times",
796 counts [std::money_base::symbol]);
798 rw_assert (1 == counts [std::money_base::sign], 0, __LINE__,
799 "money_base::sign must apear exactly once, did %d times",
800 counts [std::money_base::sign]);
802 rw_assert (1 == counts [std::money_base::value], 0, __LINE__,
803 "money_base::value must apear exactly once, did %d times",
804 counts [std::money_base::value]);
806 rw_assert (1 == counts [std::money_base::space]
807 + counts [std::money_base::none], 0, __LINE__,
808 "money_base::space or money_base::none must appear "
809 "exactly once, did %d times",
810 counts [std::money_base::space]
811 + counts [std::money_base::none]);
829#ifndef _RWSTD_NO_WCHAR_T
849int main (
int argc,
char *argv[])
851 return rw_test (argc, argv, __FILE__,
852 "lib.locale.moneypunct",
std::string convert(const char *, const char *s, const char *)
std::lconv * lconvdup(const std::lconv *plconv)
void check_decimal_point(charT, const char *, const std::locale *)
void check_grouping(charT, const char *, const std::string &, const std::locale *)
void check_thousands_sep(charT, const char *, const std::locale *)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define _RWSTD_USE_FACET(type, arg)
#define _RWSTD_REINTERPRET_CAST(T, x)
#define _STD_HAS_FACET(type, arg)
#define _RWSTD_STATIC_CAST(T, x)
#define _RWSTD_CONST_CAST(T, x)
void check_format(const std::lconv &)
std::moneypunct< charT, true > IntlPunct
std::basic_string< charT, Traits, Allocator > String
void check_positive_sign(const String &)
void check_thousands_sep(charT)
void check_curr_symbol(const String &)
std::allocator< charT > Allocator
void check_negative_sign(const String &)
std::char_traits< charT > Traits
void check_grouping(const std::string &)
std::moneypunct< charT, false > Punct
Test(const char *cname, bool intl)
bool check_moneypunct(const char *)
void check_frac_digits(int)
void check_decimal_point(charT)
_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_assert(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_putenv(const char *, int=-1)
_TEST_EXPORT char * rw_locales(int=_UNUSED_CAT, const char *=0, bool=true)
_TEST_EXPORT rw_file *const rw_stderr
_TEST_EXPORT int rw_fprintf(rw_file *, const char *,...)