1 /* Checked_Number class implementation: non-inline template functions.
2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5 This file is part of the Parma Polyhedra Library (PPL).
6
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23
24 #ifndef PPL_Checked_Number_templates_hh
25 #define PPL_Checked_Number_templates_hh 1
26
27 #include "assertions.hh"
28 #include <iomanip>
29 #include <limits>
30
31 namespace Parma_Polyhedra_Library {
32
33 template <typename T>
34 typename Enable_If<Is_Native_Or_Checked<T>::value, void>::type
ascii_dump(std::ostream & s,const T & t)35 ascii_dump(std::ostream& s, const T& t) {
36 if (std::numeric_limits<T>::is_exact) {
37 // An exact data type: pretty printer is accurate.
38 s << t;
39 }
40 else {
41 // An inexact data type (probably floating point):
42 // first dump its hexadecimal representation ...
43 const std::ios::fmtflags old_flags = s.setf(std::ios::hex,
44 std::ios::basefield);
45 const unsigned char* p = reinterpret_cast<const unsigned char*>(&t);
46 for (unsigned i = 0; i < sizeof(T); ++i) {
47 s << std::setw(2) << std::setfill('0') << static_cast<unsigned>(p[i]);
48 }
49 s.flags(old_flags);
50 // ... and then pretty print it for readability.
51 s << " (" << t << ")";
52 }
53 }
54
55 template <typename T>
56 typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
ascii_load(std::istream & s,T & t)57 ascii_load(std::istream& s, T& t) {
58 if (std::numeric_limits<T>::is_exact) {
59 // An exact data type: input from pretty printed version is accurate.
60 s >> t;
61 return !s.fail();
62 }
63 else {
64 // An inexact data type (probably floating point):
65 // first load its hexadecimal representation ...
66 std::string str;
67 if (!(s >> str) || str.size() != 2*sizeof(T)) {
68 return false;
69 }
70 unsigned char* p = reinterpret_cast<unsigned char*>(&t);
71 // CHECKME: any (portable) simpler way?
72 for (unsigned i = 0; i < sizeof(T); ++i) {
73 unsigned byte_value = 0;
74 for (unsigned j = 0; j < 2; ++j) {
75 byte_value <<= 4;
76 unsigned half_byte_value;
77 // Interpret single hex character.
78 switch (str[2*i + j]) {
79 case '0':
80 half_byte_value = 0;
81 break;
82 case '1':
83 half_byte_value = 1;
84 break;
85 case '2':
86 half_byte_value = 2;
87 break;
88 case '3':
89 half_byte_value = 3;
90 break;
91 case '4':
92 half_byte_value = 4;
93 break;
94 case '5':
95 half_byte_value = 5;
96 break;
97 case '6':
98 half_byte_value = 6;
99 break;
100 case '7':
101 half_byte_value = 7;
102 break;
103 case '8':
104 half_byte_value = 8;
105 break;
106 case '9':
107 half_byte_value = 9;
108 break;
109 case 'A':
110 case 'a':
111 half_byte_value = 10;
112 break;
113 case 'B':
114 case 'b':
115 half_byte_value = 11;
116 break;
117 case 'C':
118 case 'c':
119 half_byte_value = 12;
120 break;
121 case 'D':
122 case 'd':
123 half_byte_value = 13;
124 break;
125 case 'E':
126 case 'e':
127 half_byte_value = 14;
128 break;
129 case 'F':
130 case 'f':
131 half_byte_value = 15;
132 break;
133 default:
134 return false;
135 }
136 byte_value += half_byte_value;
137 }
138 PPL_ASSERT(byte_value <= 255);
139 p[i] = static_cast<unsigned char>(byte_value);
140 }
141 // ... then read and discard pretty printed value.
142 if (!(s >> str)) {
143 return false;
144 }
145 const std::string::size_type sz = str.size();
146 return sz > 2 && str[0] == '(' && str[sz-1] == ')';
147 }
148 }
149
150 } // namespace Parma_Polyhedra_Library
151
152 #endif // !defined(PPL_Checked_Number_templates_hh)
153