1 /****************************************************************************
2 * Core Library Version 1.7, August 2004
3 * Copyright (c) 1995-2004 Exact Computation Project
4 * All rights reserved.
5 *
6 * file: GmpIO.cpp
7 * Adapted from multi-files under /cxx in GMP's source distribution
8 *
9 * Zilin Du, 2003
10 *
11 * $URL: https://github.com/CGAL/cgal/blob/v5.3/CGAL_Core/include/CGAL/CORE/Gmp_impl.h $
12 * $Id: Gmp_impl.h 12fd01d 2020-09-21T08:54:29+02:00 Ahmed Essam
13 * SPDX-License-Identifier: LGPL-3.0-only
14 ***************************************************************************/
15
16 /* Auxiliary functions for C++-style input of GMP types.
17
18 Copyright 2001 Free Software Foundation, Inc.
19
20 This file is part of the GNU MP Library.
21
22 */
23
24 #ifdef CGAL_HEADER_ONLY
25 #define CGAL_INLINE_FUNCTION inline
26 #else
27 #define CGAL_INLINE_FUNCTION
28 #endif
29
30 #include <CGAL/CORE/Gmp.h>
31 #include <cctype>
32 #include <iostream>
33 #include <string>
34 #include <cstdio>
35
36 namespace CORE {
37
38 CGAL_INLINE_FUNCTION
39 int
__gmp_istream_set_base(std::istream & i,char & c,bool & zero,bool & showbase)40 __gmp_istream_set_base (std::istream &i, char &c, bool &zero, bool &showbase)
41 {
42 int base;
43 using std::ios;
44
45 zero = showbase = false;
46 switch (i.flags() & ios::basefield)
47 {
48 case ios::dec:
49 base = 10;
50 break;
51 case ios::hex:
52 base = 16;
53 break;
54 case ios::oct:
55 base = 8;
56 break;
57 default:
58 showbase = true; // look for initial "0" or "0x" or "0X"
59 if (c == '0')
60 {
61 if (! i.get(c))
62 c = 0; // reset or we might loop indefinitely
63
64 if (c == 'x' || c == 'X')
65 {
66 base = 16;
67 i.get(c);
68 }
69 else
70 {
71 base = 8;
72 zero = true; // if no other digit is read, the "0" counts
73 }
74 }
75 else
76 base = 10;
77 break;
78 }
79
80 return base;
81 }
82
83 CGAL_INLINE_FUNCTION
84 void
__gmp_istream_set_digits(std::string & s,std::istream & i,char & c,bool & ok,int base)85 __gmp_istream_set_digits (std::string &s, std::istream &i, char &c, bool &ok, int base)
86 {
87 switch (base)
88 {
89 case 10:
90 while (isdigit(c))
91 {
92 ok = true; // at least a valid digit was read
93 s += c;
94 if (! i.get(c))
95 break;
96 }
97 break;
98 case 8:
99 while (isdigit(c) && c != '8' && c != '9')
100 {
101 ok = true; // at least a valid digit was read
102 s += c;
103 if (! i.get(c))
104 break;
105 }
106 break;
107 case 16:
108 while (isxdigit(c))
109 {
110 ok = true; // at least a valid digit was read
111 s += c;
112 if (! i.get(c))
113 break;
114 }
115 break;
116 }
117 }
118
119 CGAL_INLINE_FUNCTION
120 std::istream &
121 //operator>> (std::istream &i, mpz_ptr z)
io_read(std::istream & i,mpz_ptr z)122 io_read (std::istream &i, mpz_ptr z)
123 {
124 using namespace std;
125 int base;
126 char c = 0;
127 std::string s;
128 bool ok = false, zero, showbase;
129
130 i.get(c); // start reading
131
132 if (i.flags() & ios::skipws) // skip initial whitespace
133 while (isspace(c) && i.get(c))
134 ;
135
136 if (c == '-' || c == '+') // sign
137 {
138 if (c == '-') // mpz_set_str doesn't accept '+'
139 s = "-";
140 i.get(c);
141 }
142
143 while (isspace(c) && i.get(c)) // skip whitespace
144 ;
145
146 base = __gmp_istream_set_base(i, c, zero, showbase); // select the base
147 __gmp_istream_set_digits(s, i, c, ok, base); // read the number
148
149 if (i.good()) // last character read was non-numeric
150 i.putback(c);
151 else if (i.eof() && (ok || zero)) // stopped just before eof
152 i.clear();
153
154 if (ok)
155 mpz_set_str(z, s.c_str(), base); // extract the number
156 else if (zero)
157 mpz_set_ui(z, 0);
158 else
159 i.setstate(ios::failbit); // read failed
160
161 return i;
162 }
163
164 CGAL_INLINE_FUNCTION
165 std::istream &
166 //operator>> (std::istream &i, mpq_ptr q)
io_read(std::istream & i,mpq_ptr q)167 io_read (std::istream &i, mpq_ptr q)
168 {
169 using namespace std;
170 int base;
171 char c = 0;
172 std::string s;
173 bool ok = false, zero, showbase;
174
175 i.get(c); // start reading
176
177 if (i.flags() & ios::skipws) // skip initial whitespace
178 while (isspace(c) && i.get(c))
179 ;
180
181 if (c == '-' || c == '+') // sign
182 {
183 if (c == '-')
184 s = "-";
185 i.get(c);
186 }
187
188 while (isspace(c) && i.get(c)) // skip whitespace
189 ;
190
191 base = __gmp_istream_set_base(i, c, zero, showbase); // select the base
192 __gmp_istream_set_digits(s, i, c, ok, base); // read the numerator
193
194 if (! ok && zero) // the only digit read was "0"
195 {
196 base = 10;
197 s += '0';
198 ok = true;
199 }
200
201 if (c == '/') // there's a denominator
202 {
203 bool zero2 = false;
204 int base2 = base;
205
206 s += '/';
207 ok = false; // denominator is mandatory
208 i.get(c);
209
210 while (isspace(c) && i.get(c)) // skip whitespace
211 ;
212
213 if (showbase) // check base of denominator
214 base2 = __gmp_istream_set_base(i, c, zero2, showbase);
215
216 if (base2 == base || base2 == 10) // read the denominator
217 __gmp_istream_set_digits(s, i, c, ok, base);
218
219 if (! ok && zero2) // the only digit read was "0"
220 { // denominator is 0, but that's your business
221 s += '0';
222 ok = true;
223 }
224 }
225
226 if (i.good()) // last character read was non-numeric
227 i.putback(c);
228 else if (i.eof() && ok) // stopped just before eof
229 i.clear();
230
231 if (ok)
232 mpq_set_str(q, s.c_str(), base); // extract the number
233 else
234 i.setstate(ios::failbit); // read failed
235
236 return i;
237 }
238
239 CGAL_INLINE_FUNCTION
240 std::ostream&
241 //operator<< (std::ostream &o, mpz_srcptr z)
io_write(std::ostream & o,mpz_srcptr z)242 io_write (std::ostream &o, mpz_srcptr z)
243 {
244 char *str = new char [mpz_sizeinbase(z,10) + 2];
245 str = mpz_get_str(str, 10, z);
246 o << str ;
247 delete[] str;
248 return o;
249 }
250
251 CGAL_INLINE_FUNCTION
252 std::ostream&
253 //operator<< (std::ostream &o, mpq_srcptr q)
io_write(std::ostream & o,mpq_srcptr q)254 io_write (std::ostream &o, mpq_srcptr q)
255 {
256 // size according to GMP documentation
257 char *str = new char [mpz_sizeinbase(mpq_numref(q), 10) +
258 mpz_sizeinbase (mpq_denref(q), 10) + 3];
259 str = mpq_get_str(str, 10, q);
260 o << str ;
261 delete[] str;
262 return o;
263 }
264
265 } //namespace CORE
266