1 // Copyright (c) 1997-2020
2 //
3 // Utrecht University (The Netherlands),
4 // ETH Zurich (Switzerland),
5 // INRIA Sophia-Antipolis (France),
6 // Max-Planck-Institute Saarbruecken (Germany),
7 // and Tel-Aviv University (Israel).  All rights reserved.
8 //
9 // This file is part of CGAL (www.cgal.org)
10 //
11 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Stream_support/include/CGAL/IO/io.h $
12 // $Id: io.h 4e519a3 2021-05-05T13:15:37+02:00 Sébastien Loriot
13 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
14 //
15 //
16 // Author(s)     : Andreas Fabri
17 
18 #ifndef CGAL_IO_H
19 #define CGAL_IO_H
20 
21 #include <CGAL/disable_warnings.h>
22 
23 #include <CGAL/IO/io_tags.h>
24 #include <CGAL/IO/Color.h>
25 
26 #include <CGAL/assertions.h>
27 #include <CGAL/Fraction_traits.h>
28 #include <CGAL/tags.h>
29 
30 #include <cstdio>
31 #include <cctype>
32 #include <string>
33 #include <locale>
34 #include <iostream>
35 
36 namespace CGAL {
37 
38 namespace IO {
39 
40 class Static
41 {
42 public:
get_mode()43   static int get_mode()
44   {
45     static const int mode = std::ios::xalloc();
46     return mode;
47   }
48 };
49 
50 /*!
51 \ingroup PkgStreamSupportEnumRef
52 
53 All classes in the \cgal `Kernel` provide input and output operators for
54 IOStreams.  The basic task of such an operator is to produce a
55 representation of an object that can be written as a sequence of
56 characters on devices as a console, a file, or a pipe. The enum `Mode` distinguish between three different printing formats.
57 
58 In `ASCII` mode, numbers
59 e.g. the coordinates of a point or
60 the coefficients of a line, are written
61 in a machine independent format.
62 In <span class="textsc">BINARY</span> mode, data are written
63 in a binary format, e.g. a double is represented
64 as a sequence of four byte. The format depends on the machine.
65  The mode  <span class="textsc">PRETTY</span>
66 serves mainly for debugging as the type of the geometric
67 object is written, as well as the data defining the object. For example
68 for a point at the origin with %Cartesian double coordinates, the output
69 would be `PointC2(0.0, 0.0)`.  At the moment \cgal does not
70 provide input operations for pretty printed data. By default a stream
71 is in <span class="textsc">Ascii</span> mode.
72 
73 \sa `CGAL::IO::set_mode()`
74 \sa `CGAL::IO::set_ascii_mode()`
75 \sa `CGAL::IO::set_binary_mode()`
76 \sa `CGAL::IO::set_pretty_mode()`
77 \sa `CGAL::IO::get_mode()`
78 \sa `CGAL::IO::is_ascii()`
79 \sa `CGAL::IO::is_binary()`
80 \sa `CGAL::IO::is_pretty()`
81 */
82 enum Mode {ASCII = 0, PRETTY, BINARY};
83 
84 } // namespace IO
85 
86 #ifdef DOXYGEN_RUNNING
87 /*!
88 \ingroup IOstreamOperators
89 
90 \brief Inserts object `c` in the stream `os`. Returns `os`.
91 \cgal defines output operators for classes that are derived
92 from the class `ostream`. This allows to write to ostreams
93 as `cout` or `cerr`, as well as to `std::ostringstream`
94 and `std::ofstream`.
95 The output operator is defined for all classes in the \cgal `Kernel` and for the class `Color` as well.
96 
97 \sa `CGAL::IO::set_mode()`
98 \sa `CGAL::IO::set_ascii_mode()`
99 \sa `CGAL::IO::set_binary_mode()`
100 \sa `CGAL::IO::set_pretty_mode()`
101 \sa `CGAL::IO::get_mode()`
102 \sa `CGAL::IO::is_ascii()`
103 \sa `CGAL::IO::is_binary()`
104 \sa `CGAL::IO::is_pretty()`
105 */
106 ostream& operator<<(ostream& os, Class c);
107 
108 /*!
109 \ingroup IOstreamOperators
110 
111 \brief \cgal defines input operators for classes that are derived
112 from the class `istream`. This allows to read from istreams
113 as `std::cin`, as well as from `std::istringstream` and `std::ifstream`.
114 The input operator is defined for all classes in the \cgal `Kernel`.
115 
116 \sa `CGAL::IO::set_mode()`
117 \sa `CGAL::IO::set_ascii_mode()`
118 \sa `CGAL::IO::set_binary_mode()`
119 \sa `CGAL::IO::set_pretty_mode()`
120 \sa `CGAL::IO::get_mode()`
121 \sa `CGAL::IO::is_ascii()`
122 \sa `CGAL::IO::is_binary()`
123 \sa `CGAL::IO::is_pretty()`
124 */
125 istream& operator>>(istream& is, Class c);
126 #endif
127 
128 template <typename Dummy>
129 struct IO_rep_is_specialized_aux
130 {
131   static const bool is_specialized = true;
132 };
133 
134 template< class Dummy >
135 const bool IO_rep_is_specialized_aux<Dummy>::is_specialized;
136 
137 template <typename Dummy>
138 struct IO_rep_is_not_specialized_aux
139 {
140   static const bool is_specialized = false;
141 };
142 
143 template< class Dummy >
144 const bool IO_rep_is_not_specialized_aux<Dummy>::is_specialized;
145 
146 typedef IO_rep_is_specialized_aux<void> IO_rep_is_specialized;
147 typedef IO_rep_is_not_specialized_aux<void> IO_rep_is_not_specialized;
148 
149 /*!
150 \ingroup PkgStreamSupportRef
151 
152 The purpose of `Output_rep` is to provide a way to control output formatting that works independently of the object's stream output operator.
153 
154 If you dont specialize `Output_rep` for `T`, `T`'s stream output operator is called from within `Output_rep`, by default. If you want another behaviour for your type `T`, you have to provide a specialization for that type. Furthermore, you can provide specializations with a second template parameter (a formatting tag). The second template parameter defaults to `Null_tag` and means *default behaviour*.
155 
156 Specializations of `Output_rep` should provide the following features:
157 
158 \code{.cpp}
159 
160 template< class F >
161 struct Output_rep< Some_type, F > {
162   static const bool is_specialized = true;
163   Output_rep( const Some_type& t );
164   std::ostream& operator()( std::ostream& out ) const;
165 };
166 
167 \endcode
168 
169 You can also specialize for a formatting tag `F`.
170 
171 The constant `is_specialized` can be tested by meta-programming tools to
172 verify that a given type can be used with `oformat()`. Its value has to be
173 `true` in a specialization of `Output_rep`. When there is no specialization
174 for a type, the class template `Output_rep` defines `is_specialized` to the
175 default value `false`.
176 */
177 template <class T, class F = ::CGAL::Null_tag >
178 class Output_rep
179   : public IO_rep_is_not_specialized
180 {
181   const T& t;
182 
183 public:
184   //! initialize with a const reference to \a t.
Output_rep(const T & tt)185   Output_rep( const T& tt) : t(tt) {}
186   //! perform the output, calls \c operator\<\< by default.
operator()187   std::ostream& operator()( std::ostream& out) const { return (out << t); }
188 };
189 
190 /*!
191   \relates Output_rep
192   \brief stream output of the \c Output_rep calls its \c operator().
193 
194   \cgal defines output operators for classes that are derived from the class `ostream`.
195   This enables to write to ostreams as `cout` or `cerr`, as well as to `std::ostringstream`
196   and `std::ofstream`.
197   The output operator is defined for all classes in the \cgal `Kernel` and for the class `Color` as well.
198 */
199 template <class T, class F>
200 std::ostream& operator<<( std::ostream& out, Output_rep<T,F> rep) { return rep( out); }
201 
202 namespace IO {
203 
204 /*!
205 \ingroup PkgStreamSupportRef
206 
207 Convenience function to construct an output representation (`Output_rep`) for type `T`.
208 
209 Generic IO for type `T`.
210 */
211 template <class T>
oformat(const T & t)212 Output_rep<T> oformat(const T& t) { return Output_rep<T>(t); }
213 
214 /*!
215 \ingroup PkgStreamSupportRef
216 
217 Convenience function to construct an output representation (`Output_rep`) for type `T`.
218 
219 Generic IO for type `T` with formatting tag.
220 */
221 template <class T, class F>
oformat(const T & t,F)222 Output_rep<T,F> oformat( const T& t, F) { return Output_rep<T,F>(t); }
223 
224 } // namespace IO
225 
226 /*!
227 \ingroup PkgStreamSupportRef
228 
229 The definition of `Input_rep` is completely symmetric to `Output_rep`.
230 */
231 template <class T>
232 class Input_rep
233   : public IO_rep_is_not_specialized
234 {
235   T& t;
236 
237 public:
238   //! initialize with a reference to \a t.
Input_rep(T & tt)239   Input_rep( T& tt) : t(tt) {}
240 
241   //! perform the input, calls \c operator\>\> by default.
operator()242   std::istream& operator()( std::istream& in) const { return (in >> t); }
243 };
244 
245 #if CGAL_FORCE_IFORMAT_DOUBLE || \
246   ( ( _MSC_VER > 1600 ) && ( _MSC_VER < 1910 ) && (! defined( CGAL_NO_IFORMAT_DOUBLE )) )
247 
248 template <>
249 class Input_rep<double>
250   : public IO_rep_is_specialized
251 {
252   double& t;
253 
254 public:
255   //! initialize with a reference to \a t.
Input_rep(double & tt)256   Input_rep( double& tt) : t(tt) {}
257 
operator()258   std::istream& operator()( std::istream& is) const
259   {
260     typedef std::istream istream;
261     typedef istream::char_type char_type;
262     typedef istream::int_type int_type;
263     typedef istream::traits_type traits_type;
264 
265     std::string buffer;
266     buffer.reserve(32);
267 
268     char_type c;
269     do
270     {
271       const int_type i = is.get();
272       if(i == traits_type::eof())
273         return is;
274 
275       c = static_cast<char_type>(i);
276     }
277     while (std::isspace(c));
278 
279     if(c == '-')
280     {
281       buffer += '-';
282     }
283     else if(c != '+')
284     {
285       is.unget();
286     }
287 
288     for(;;)
289     {
290       const int_type i = is.get();
291       if(i == traits_type::eof())
292       {
293         is.clear(is.rdstate() & ~std::ios_base::failbit);
294         break;
295       }
296 
297       c = static_cast<char_type>(i);
298       if(std::isdigit(c) || (c =='.') || (c =='E') || (c =='e') || (c =='+') || (c =='-'))
299       {
300         buffer += c;
301       }
302       else
303       {
304         is.unget();
305         break;
306       }
307     }
308 
309     if(sscanf_s(buffer.c_str(), "%lf", &t) != 1)
310     {
311       // if a 'buffer' does not contain a double, set the fail bit.
312       is.setstate(std::ios_base::failbit);
313     }
314 
315     return is;
316   }
317 };
318 
319 template <>
320 class Input_rep<float>
321 {
322   float& t;
323 
324 public:
325   //! initialize with a reference to \a t.
Input_rep(float & tt)326   Input_rep( float& tt) : t(tt) {}
327 
operator()328   std::istream& operator()( std::istream& is) const
329   {
330     typedef std::istream istream;
331     typedef istream::char_type char_type;
332     typedef istream::int_type int_type;
333     typedef istream::traits_type traits_type;
334 
335     std::string buffer;
336     buffer.reserve(32);
337 
338     char_type c;
339     do
340     {
341       const int_type i = is.get();
342       if(i == traits_type::eof())
343         return is;
344 
345       c = static_cast<char_type>(i);
346     }
347     while (std::isspace(c));
348 
349     if(c == '-')
350     {
351       buffer += '-';
352     }
353     else if(c != '+')
354     {
355       is.unget();
356     }
357 
358     for(;;)
359     {
360       const int_type i = is.get();
361       if(i == traits_type::eof())
362       {
363         is.clear(is.rdstate() & ~std::ios_base::failbit);
364         break;
365       }
366 
367       c = static_cast<char_type>(i);
368       if(std::isdigit(c) || (c =='.') || (c =='E') || (c =='e') || (c =='+') || (c =='-'))
369       {
370         buffer += c;
371       }
372       else
373       {
374         is.unget();
375         break;
376       }
377     }
378 
379     if(sscanf_s(buffer.c_str(), "%f", &t) != 1)
380     {
381       // if a 'buffer' does not contain a double, set the fail bit.
382       is.setstate(std::ios_base::failbit);
383     }
384 
385     return is;
386   }
387 };
388 #endif
389 
390 /*! \relates Input_rep
391     \brief stream input to the \c Input_rep calls its \c operator().
392 
393 \brief \cgal defines input operators for classes that are derived
394 from the class `istream`. This allows to read from istreams
395 as `std::cin`, as well as from `std::istringstream` and `std::ifstream`.
396 The input operator is defined for all classes in the \cgal `Kernel`.
397 */
398 template <class T>
399 std::istream& operator>>( std::istream& in, Input_rep<T> rep) { return rep(in); }
400 
401 namespace IO {
402 
403 /*!
404 \ingroup PkgStreamSupportRef
405 
406 The definition of this function is completely symmetric to `oformat()`.
407 */
408 template <class T>
iformat(T & t)409 Input_rep<T> iformat( T& t) { return Input_rep<T>(t); }
410 
411 } // namespace IO
412 
413 template <class T, class F = Null_tag >
414 class Benchmark_rep
415 {
416   const T& t;
417 
418 public:
419   //! initialize with a const reference to \a t.
Benchmark_rep(const T & tt)420   Benchmark_rep( const T& tt) : t(tt) {}
421   //! perform the output, calls \c operator\<\< by default.
operator()422   std::ostream& operator()( std::ostream& out) const { return out << t; }
423 
424   // static function to get the benchmark name
get_benchmark_name()425   static std::string get_benchmark_name() { return ""; }
426 };
427 
428 template <class T, class F>
429 std::ostream& operator<<( std::ostream& out, Benchmark_rep<T,F> rep) { return rep( out); }
430 
431 namespace IO {
432 
433 template <class T>
bmformat(const T & t)434 Benchmark_rep<T> bmformat( const T& t) { return Benchmark_rep<T>(t); }
435 
436 template <class T, class F>
bmformat(const T & t,F)437 Benchmark_rep<T,F> bmformat( const T& t, F) { return Benchmark_rep<T,F>(t); }
438 
439 /*!
440 \ingroup PkgStreamSupportRef
441 
442 returns the printing mode of the %IO stream `s`.
443 
444 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
445 \sa `CGAL::IO::set_mode()`
446 \sa `CGAL::IO::set_ascii_mode()`
447 \sa `CGAL::IO::set_binary_mode()`
448 \sa `CGAL::IO::set_pretty_mode()`
449 \sa `CGAL::IO::is_ascii()`
450 \sa `CGAL::IO::is_binary()`
451 \sa `CGAL::IO::is_pretty()`
452 */
get_mode(std::ios & i)453 inline Mode get_mode(std::ios& i)
454 {
455   return static_cast<Mode>(i.iword(Static::get_mode()));
456 }
457 
458 /*!
459 \ingroup PkgStreamSupportRef
460 
461 sets the mode of the %IO stream `s` to be the `ASCII` mode.
462 Returns the previous mode of `s`.
463 
464 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
465 \sa `CGAL::IO::set_mode()`
466 \sa `CGAL::IO::set_binary_mode()`
467 \sa `CGAL::IO::set_pretty_mode()`
468 \sa `CGAL::IO::get_mode()`
469 \sa `CGAL::IO::is_ascii()`
470 \sa `CGAL::IO::is_binary()`
471 \sa `CGAL::IO::is_pretty()`
472 */
set_ascii_mode(std::ios & i)473 inline Mode set_ascii_mode(std::ios& i)
474 {
475   Mode m = get_mode(i);
476   i.iword(Static::get_mode()) = ASCII;
477   return m;
478 }
479 
480 /*!
481 \ingroup PkgStreamSupportRef
482 
483 sets the mode of the %IO stream `s` to be the `BINARY` mode.
484 Returns the previous mode of `s`.
485 
486 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
487 \sa `CGAL::IO::set_mode()`
488 \sa `CGAL::IO::set_ascii_mode()`
489 \sa `CGAL::IO::set_pretty_mode()`
490 \sa `CGAL::IO::get_mode()`
491 \sa `CGAL::IO::is_ascii()`
492 \sa `CGAL::IO::is_binary()`
493 \sa `CGAL::IO::is_pretty()`
494 */
set_binary_mode(std::ios & i)495 inline Mode set_binary_mode(std::ios& i)
496 {
497   Mode m = get_mode(i);
498   i.iword(Static::get_mode()) = BINARY;
499   return m;
500 }
501 
502 /*!
503 \ingroup PkgStreamSupportRef
504 
505 sets the mode of the %IO stream `s` to be the `PRETTY` mode.
506 Returns the previous mode of `s`.
507 
508 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
509 \sa `CGAL::IO::set_mode()`
510 \sa `CGAL::IO::set_ascii_mode()`
511 \sa `CGAL::IO::set_binary_mode()`
512 \sa `CGAL::IO::get_mode()`
513 \sa `CGAL::IO::is_ascii()`
514 \sa `CGAL::IO::is_binary()`
515 \sa `CGAL::IO::is_pretty()`
516 */
set_pretty_mode(std::ios & i)517 inline Mode set_pretty_mode(std::ios& i)
518 {
519   Mode m = get_mode(i);
520   i.iword(Static::get_mode()) = PRETTY;
521   return m;
522 }
523 
524 /*!
525 \ingroup PkgStreamSupportRef
526 
527 sets the printing mode of the %IO stream `s`.
528 
529 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
530 \sa `CGAL::IO::set_ascii_mode()`
531 \sa `CGAL::IO::set_binary_mode()`
532 \sa `CGAL::IO::set_pretty_mode()`
533 \sa `CGAL::IO::get_mode()`
534 \sa `CGAL::IO::is_ascii()`
535 \sa `CGAL::IO::is_binary()`
536 \sa `CGAL::IO::is_pretty()`
537 */
set_mode(std::ios & i,Mode m)538 inline Mode set_mode(std::ios& i, Mode m)
539 {
540   Mode old = get_mode(i);
541   i.iword(Static::get_mode()) = m;
542   return old;
543 }
544 
545 /*!
546 \ingroup PkgStreamSupportRef
547 
548 checks if the %IO stream `s` is in `PRETTY` mode.
549 
550 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
551 \sa `CGAL::IO::set_mode()`
552 \sa `CGAL::IO::set_ascii_mode()`
553 \sa `CGAL::IO::set_binary_mode()`
554 \sa `CGAL::IO::set_pretty_mode()`
555 \sa `CGAL::IO::get_mode()`
556 \sa `CGAL::IO::is_ascii()`
557 \sa `CGAL::IO::is_binary()`
558 */
is_pretty(std::ios & i)559 inline bool is_pretty(std::ios& i) { return i.iword(Static::get_mode()) == PRETTY; }
560 
561 /*!
562 \ingroup PkgStreamSupportRef
563 
564 checks if the %IO stream `s` is in `ASCII` mode.
565 
566 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
567 \sa `CGAL::IO::set_mode()`
568 \sa `CGAL::IO::set_ascii_mode()`
569 \sa `CGAL::IO::set_binary_mode()`
570 \sa `CGAL::IO::set_pretty_mode()`
571 \sa `CGAL::IO::get_mode()`
572 \sa `CGAL::IO::is_binary()`
573 \sa `CGAL::IO::is_pretty()`
574 */
is_ascii(std::ios & i)575 inline bool is_ascii(std::ios& i) { return i.iword(Static::get_mode()) == ASCII; }
576 
577 /*!
578 \ingroup PkgStreamSupportRef
579 
580 checks if the %IO stream `s` is in `BINARY` mode.
581 
582 \link PkgStreamSupportEnumRef `CGAL::IO::Mode`\endlink
583 \sa `CGAL::IO::set_mode()`
584 \sa `CGAL::IO::set_ascii_mode()`
585 \sa `CGAL::IO::set_binary_mode()`
586 \sa `CGAL::IO::set_pretty_mode()`
587 \sa `CGAL::IO::get_mode()`
588 \sa `CGAL::IO::is_ascii()`
589 \sa `CGAL::IO::is_pretty()`
590 */
is_binary(std::ios & i)591 inline bool is_binary(std::ios& i) { return i.iword(Static::get_mode()) == BINARY; }
592 
593 } // namespace IO
594 
595 template < class T >
write(std::ostream & os,const T & t,const io_Read_write &)596 inline void write(std::ostream& os, const T& t, const io_Read_write&)
597 {
598   os.write(reinterpret_cast<const char*>(&t), sizeof(t));
599 }
600 
601 template < class T >
write(std::ostream & os,const T & t,const io_Operator &)602 inline void write(std::ostream& os, const T& t, const io_Operator&)
603 {
604   os << IO::oformat(t);
605 }
606 
607 template < class T >
write(std::ostream & os,const T & t,const io_Extract_insert &)608 inline void write(std::ostream& os, const T& t, const io_Extract_insert&)
609 {
610   insert(os, t);
611 }
612 
613 template < class T >
write(std::ostream & os,const T & t)614 inline void write(std::ostream& os, const T& t)
615 {
616   write(os, t, typename Io_traits<T>::Io_tag());
617 }
618 
619 template < class T >
read(std::istream & is,T & t,const io_Read_write &)620 inline void read(std::istream& is, T& t, const io_Read_write&)
621 {
622   is.read(reinterpret_cast<char*>(&t), sizeof(t));
623 }
624 
625 template < class T >
read(std::istream & is,T & t,const io_Operator &)626 inline void read(std::istream& is, T& t, const io_Operator&)
627 {
628   is >> IO::iformat(t);
629 }
630 
631 template < class T >
read(std::istream & is,T & t,const io_Extract_insert &)632 inline void read(std::istream& is, T& t, const io_Extract_insert&)
633 {
634   extract(is, t);
635 }
636 
637 template < class T >
read(std::istream & is,T & t)638 inline void read(std::istream& is, T& t)
639 {
640   read(is, t, typename Io_traits<T>::Io_tag());
641 }
642 
643 namespace IO {
644 
645 inline std::ostream& operator<<( std::ostream& out, const Color& col)
646 {
647   switch(get_mode(out))
648   {
649     case ASCII :
650       return out << static_cast<int>(col.red())   << ' '
651                  << static_cast<int>(col.green()) << ' '
652                  << static_cast<int>(col.blue()) << ' '
653                  << static_cast<int>(col.alpha());
654     case BINARY :
655       out.write(reinterpret_cast<const char*>(col.to_rgba().data()), 4);
656       return out;
657     default:
658       return out << "Color(" << static_cast<int>(col.red()) << ", "
659                  << static_cast<int>(col.green()) << ", "
660                  << static_cast<int>(col.blue()) << ", "
661                  << static_cast<int>(col.alpha()) << ")";
662   }
663 }
664 
665 inline std::istream &operator>>(std::istream &is, Color& col)
666 {
667   unsigned char r = 0, g = 0, b = 0, a = 0;
668   int ir = 0, ig = 0, ib = 0, ia = 0;
669 
670   switch(get_mode(is))
671   {
672     case ASCII :
673       is >> ir >> ig >> ib >> ia;
674       r = (unsigned char)ir;
675       g = (unsigned char)ig;
676       b = (unsigned char)ib;
677       a = (unsigned char)ia;
678       break;
679     case BINARY :
680       read(is, r);
681       read(is, g);
682       read(is, b);
683       read(is, a);
684       break;
685     default:
686       std::cerr << "" << std::endl;
687       std::cerr << "Stream must be in ascii or binary mode" << std::endl;
688       break;
689   }
690 
691   col = Color(r,g,b,a);
692   return is;
693 }
694 
mode_name(IO::Mode m)695 inline const char* mode_name( IO::Mode m )
696 {
697   static const char* const names[] = {"ASCII", "PRETTY", "BINARY" };
698   CGAL_assertion( IO::ASCII <= m && m <= IO::BINARY );
699   return names[m];
700 }
701 
702 } // IO namespace
703 
704 #ifndef CGAL_NO_DEPRECATED_CODE
705 using IO::oformat;
706 using IO::iformat;
707 using IO::bmformat;
708 using IO::get_mode;
709 using IO::set_ascii_mode;
710 using IO::set_binary_mode;
711 using IO::set_pretty_mode;
712 using IO::set_mode;
713 using IO::is_pretty;
714 using IO::is_ascii;
715 using IO::is_binary;
716 using IO::mode_name;
717 #endif
718 
719 // From polynomial.h TODO: Where to put this?
swallow(std::istream & is,char d)720 inline void swallow(std::istream &is, char d)
721 {
722   char c;
723   do { is.get(c); } while(isspace(c));
724   if(c != d)
725   {
726     std::stringstream msg;
727     msg << "input error: expected '" << d << "' but got '" << c << "'";
728     CGAL_error_msg( msg.str().c_str() );
729   }
730 }
731 
swallow(std::istream & is,const std::string & s)732 inline void swallow(std::istream &is, const std::string& s)
733 {
734   std::string t;
735   is >> t;
736   if(s != t)
737   {
738     std::stringstream msg;
739     msg << "input error: expected '" << s << "' but got '" << t << "'";
740     CGAL_error_msg( msg.str().c_str() );
741   }
742 }
743 
744 namespace internal {
745 
eat_white_space(std::istream & is)746 inline void eat_white_space(std::istream &is)
747 {
748   std::istream::int_type c;
749   do
750   {
751     c = is.peek();
752     if(c == std::istream::traits_type::eof())
753     {
754       return;
755     }
756     else
757     {
758       std::istream::char_type cc= static_cast<std::istream::char_type>(c);
759       if(std::isspace(cc, std::locale::classic()))
760       {
761         is.get();
762         // since peek succeeded, this should too
763         CGAL_assertion(!is.fail());
764       }
765       else
766       {
767         return;
768       }
769     }
770   }
771   while (true);
772 }
773 
is_space(const std::istream &,std::istream::int_type c)774 inline bool is_space(const std::istream& /*is*/, std::istream::int_type c)
775 {
776   return (c == std::istream::traits_type::eof()) ||
777           std::isspace(static_cast<std::istream::char_type>(c),
778                        std::locale::classic() );
779 }
780 
is_eof(const std::istream &,std::istream::int_type c)781 inline bool is_eof(const std::istream& /*is*/, std::istream::int_type c)
782 {
783   return c == std::istream::traits_type::eof();
784 }
785 
is_digit(const std::istream &,std::istream::int_type c)786 inline bool is_digit(const std::istream& /*is*/, std::istream::int_type c)
787 {
788   CGAL_assertion(c != std::istream::traits_type::eof());
789   return std::isdigit(static_cast<std::istream::char_type>(c),
790                       std::locale::classic());
791 }
792 
peek(std::istream & is)793 inline std::istream::int_type peek(std::istream& is)
794 {
795   // Workaround for a bug in the version of libc++ that is shipped with
796   // Apple-clang-3.2. See the long comment in the function
797   // gmpz_new_read() in <CGAL/GMP/Gmpz_type.h>.
798 
799   if(is.eof())
800     return std::istream::traits_type::eof();
801   else
802     return is.peek();
803 }
804 
805 template <typename ET>
read_float_or_quotient(std::istream & is,ET & et)806 inline void read_float_or_quotient(std::istream & is, ET& et)
807 {
808   is >> et;
809 }
810 
811 template <typename Int, typename Rat>
read_float_or_quotient(std::istream & is,Rat & z)812 inline void read_float_or_quotient(std::istream& is, Rat &z)
813 {
814   // To build a rational from numerator and denominator. Hope that `Int`
815   // and `Fraction_traits::(Numerator|Denominator)_type` are consistent...
816   typename Fraction_traits<Rat>::Compose compose;
817 
818   // reads rational and floating point literals.
819   const std::istream::char_type zero = '0';
820   std::istream::int_type c;
821   std::ios::fmtflags old_flags = is.flags();
822 
823   is.unsetf(std::ios::skipws);
824   internal::eat_white_space(is);
825 
826   Int n(0); // unsigned number before '/' or '.'
827   Int d(1); // number after '/', or denominator (fp-case)
828   bool negative = false; // do we have a leading '-'?
829   bool digits = false;   // for fp-case: are there any digits at all?
830 
831   c = internal::peek(is);
832   if(c != '.')
833   {
834     // is there a sign?
835     if(c == '-' || c == '+')
836     {
837       is.get();
838       negative = (c == '-');
839       internal::eat_white_space(is);
840       c = internal::peek(is);
841     }
842 
843     // read n (could be empty)
844     while (!internal::is_eof(is, c) && internal::is_digit(is, c))
845     {
846       digits = true;
847       n = n*10 + (c-zero);
848       is.get();
849       c = internal::peek(is);
850     }
851 
852     // are we done?
853     if(internal::is_eof(is, c) || internal::is_space(is, c))
854     {
855       is.flags(old_flags);
856       if(digits && !is.fail())
857         z = negative? compose(-n,1): compose(n,1);
858       return;
859     }
860   }
861   else
862   {
863     n = 0;
864   }
865 
866   // now we have read n, we are not done, and c is the next character
867   // in the stream
868   if(c == '/' || c == '.')
869   {
870     is.get();
871     if(c == '/')
872     {
873       // rational case
874       is >> d;
875       is.flags(old_flags);
876       if(!is.fail())
877         z = negative? compose(-n,d) : compose(n,d);
878       return;
879     }
880 
881     // floating point case; read number after '.' (may be empty)
882     for(;;)
883     {
884       c = internal::peek(is);
885       if(internal::is_eof(is, c) || !internal::is_digit(is, c))
886         break;
887       // now we have a digit
888       is.get();
889       digits = true;
890       d *= 10;
891       n = n*10 + (c-zero);
892     }
893   }
894 
895   // now we have read all digits after '.', and c is the next character;
896   // read the exponential part (optional)
897   int e = 0;
898   if(c == 'e' || c == 'E')
899   {
900     is.get();
901     is >> e;
902   }
903 
904   // now construct the Gmpq
905   if(!digits)
906   {
907     // illegal floating-point number
908     is.setstate(std::ios_base::failbit);
909     is.flags(old_flags);
910     return;
911   }
912 
913   // handle e
914   if(e > 0)
915     while (e--) n *= 10;
916   else
917     while (e++) d *= 10;
918 
919   is.flags(old_flags);
920   if(!is.fail())
921     z = (negative ? compose(-n,d) : compose(n,d));
922 }
923 
924 } // namespace internal
925 
926 } // namespace CGAL
927 
928 #include <CGAL/enable_warnings.h>
929 
930 #endif // CGAL_IO_H
931