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