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