1/* Test locale support in C++ functions. 2 3Copyright 2001-2003, 2007 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the 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 27using namespace std; 28 29 30extern "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[]. 36class my_numpunct : public numpunct<char> { 37 public: 38 explicit my_numpunct (size_t r = 0) : numpunct<char>(r) { } 39 protected: 40 char do_decimal_point() const { return point_string[0]; } 41}; 42#endif 43 44void 45set_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 56void 57check_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 132void 133check_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 163int 164replacement_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 177int 178main (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