xref: /netbsd-src/external/lgpl3/gmp/dist/tests/cxx/t-locale.cc (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
1 /* Test locale support in C++ functions.
2 
3 Copyright 2001-2003, 2007 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <clocale>
21 #include <iostream>
22 #include <cstdlib>
23 
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 using namespace std;
28 
29 
30 extern "C" {
31   char point_string[2];
32 }
33 
34 #if HAVE_STD__LOCALE
35 // Like std::numpunct, but with decimal_point coming from point_string[].
36 class my_numpunct : public numpunct<char> {
37  public:
my_numpunct(size_t r=0)38   explicit my_numpunct (size_t r = 0) : numpunct<char>(r) { }
39  protected:
do_decimal_point() const40   char do_decimal_point() const { return point_string[0]; }
41 };
42 #endif
43 
44 void
set_point(char c)45 set_point (char c)
46 {
47   point_string[0] = c;
48 
49 #if HAVE_STD__LOCALE
50   locale loc (locale::classic(), new my_numpunct ());
51   locale::global (loc);
52 #endif
53 }
54 
55 
56 void
check_input(void)57 check_input (void)
58 {
59   static const struct {
60     const char  *str1;
61     const char  *str2;
62     double      want;
63   } data[] = {
64 
65     { "1","",   1.0 },
66     { "1","0",  1.0 },
67     { "1","00", 1.0 },
68 
69     { "","5",    0.5 },
70     { "0","5",   0.5 },
71     { "00","5",  0.5 },
72     { "00","50", 0.5 },
73 
74     { "1","5",    1.5 },
75     { "1","5e1", 15.0 },
76   };
77 
78   static char point[] = {
79     '.', ',', 'x', '\xFF'
80   };
81 
82   mpf_t  got;
83   mpf_init (got);
84 
85   for (size_t i = 0; i < numberof (point); i++)
86     {
87       set_point (point[i]);
88 
89       for (int neg = 0; neg <= 1; neg++)
90         {
91           for (size_t j = 0; j < numberof (data); j++)
92             {
93               string str = string(data[j].str1)+point[i]+string(data[j].str2);
94               if (neg)
95                 str = "-" + str;
96 
97               istringstream is (str.c_str());
98 
99               mpf_set_ui (got, 123);   // dummy initial value
100 
101               if (! (is >> got))
102                 {
103                   cout << "istream mpf_t operator>> error\n";
104                   cout << "  point " << point[i] << "\n";
105                   cout << "  str   \"" << str << "\"\n";
106                   cout << "  localeconv point \""
107                        << GMP_DECIMAL_POINT << "\"\n";
108                   abort ();
109                 }
110 
111               double want = data[j].want;
112               if (neg)
113                 want = -want;
114               if (mpf_cmp_d (got, want) != 0)
115                 {
116                   cout << "istream mpf_t operator>> wrong\n";
117                   cout << "  point " << point[i] << "\n";
118                   cout << "  str   \"" << str << "\"\n";
119                   cout << "  got   " << got << "\n";
120                   cout << "  want  " << want << "\n";
121                   cout << "  localeconv point \""
122                        << GMP_DECIMAL_POINT << "\"\n";
123                   abort ();
124                 }
125             }
126         }
127     }
128 
129   mpf_clear (got);
130 }
131 
132 void
check_output(void)133 check_output (void)
134 {
135   static char point[] = {
136     '.', ',', 'x', '\xFF'
137   };
138 
139   for (size_t i = 0; i < numberof (point); i++)
140     {
141       set_point (point[i]);
142       ostringstream  got;
143 
144       mpf_t  f;
145       mpf_init (f);
146       mpf_set_d (f, 1.5);
147       got << f;
148       mpf_clear (f);
149 
150       string  want = string("1") + point[i] + string("5");
151 
152       if (want.compare (got.str()) != 0)
153         {
154           cout << "ostream mpf_t operator<< doesn't respect locale\n";
155           cout << "  point " << point[i] << "\n";
156           cout << "  got   \"" << got.str() << "\"\n";
157           cout << "  want  \"" << want      << "\"\n";
158           abort ();
159         }
160     }
161 }
162 
163 int
replacement_works(void)164 replacement_works (void)
165 {
166   set_point ('x');
167   mpf_t  f;
168   mpf_init (f);
169   mpf_set_d (f, 1.5);
170   ostringstream s;
171   s << f;
172   mpf_clear (f);
173 
174   return (s.str().compare("1x5") == 0);
175 }
176 
177 int
main(void)178 main (void)
179 {
180   tests_start ();
181 
182   if (replacement_works())
183     {
184       check_input ();
185       check_output ();
186     }
187   else
188     {
189       cout << "Replacing decimal point didn't work, tests skipped\n";
190     }
191 
192   tests_end ();
193   return 0;
194 }
195