|
15 | 15 | #include "Integral.hpp" |
16 | 16 | #include "../../meta/FunctionTraits.hpp" |
17 | 17 | #include "../../util/TypePun.hpp" |
| 18 | +#include "../../util/SignBit.hpp" |
18 | 19 |
|
19 | 20 | //SimianIgnore |
20 | 21 |
|
@@ -62,15 +63,22 @@ namespace libember { namespace ber |
62 | 63 | // 0x42 Indicates NaN |
63 | 64 | output.append(0x42); |
64 | 65 | } |
| 66 | + else if ( |
| 67 | + (value == static_cast<value_type>(0.0)) && |
| 68 | + util::signbit(value)) |
| 69 | + { |
| 70 | + // 0x43 Indicates -0.0 |
| 71 | + output.append(0x43); |
| 72 | + } |
65 | 73 | else |
66 | 74 | { |
67 | 75 | double const real = value; |
68 | 76 | unsigned long long const bits = util::type_pun<unsigned long long>(real); |
69 | 77 |
|
70 | 78 | if (bits != 0) |
71 | 79 | { |
72 | | - long long const exponent = ((0x7FF0000000000000LL & bits) >> 52) - 1023; |
73 | | - unsigned long long mantissa = 0x000FFFFFFFFFFFFFULL & bits; |
| 80 | + long long const exponent = ((0x7FF0000000000000LL & bits) >> 52) - 1023; |
| 81 | + unsigned long long mantissa = 0x000FFFFFFFFFFFFFULL & bits; |
74 | 82 | mantissa |= 0x0010000000000000ULL; |
75 | 83 |
|
76 | 84 | while((mantissa & 0xFF) == 0x00) |
@@ -109,8 +117,8 @@ namespace libember { namespace ber |
109 | 117 |
|
110 | 118 | if (bits != 0) |
111 | 119 | { |
112 | | - long long const exponent = ((0x7FF0000000000000LL & bits) >> 52) - 1023; |
113 | | - unsigned long long mantissa = 0x000FFFFFFFFFFFFFULL & bits; |
| 120 | + long long const exponent = ((0x7FF0000000000000LL & bits) >> 52) - 1023; |
| 121 | + unsigned long long mantissa = 0x000FFFFFFFFFFFFFULL & bits; |
114 | 122 | mantissa |= 0x0010000000000000ULL; |
115 | 123 |
|
116 | 124 | while((mantissa & 0xFF) == 0x00) |
@@ -152,38 +160,54 @@ namespace libember { namespace ber |
152 | 160 | static value_type decode(util::OctetStream& input, std::size_t encodedLength) |
153 | 161 | { |
154 | 162 | if (encodedLength == 0) |
| 163 | + { |
155 | 164 | return static_cast<value_type>(0.0); |
| 165 | + } |
| 166 | + |
| 167 | + if (encodedLength > input.size()) |
| 168 | + { |
| 169 | + throw std::runtime_error("Not enough data"); |
| 170 | + } |
156 | 171 |
|
157 | 172 | unsigned char const preamble = input.front(); |
158 | 173 | input.consume(); |
159 | 174 |
|
160 | | - if (encodedLength == 1 && preamble == 0x40) |
| 175 | + if ((encodedLength == 1) && (preamble == 0x40)) |
161 | 176 | { |
162 | 177 | return +std::numeric_limits<value_type>::infinity(); |
163 | 178 | } |
164 | | - else if (encodedLength == 1 && preamble == 0x41) |
| 179 | + else if ((encodedLength == 1) && (preamble == 0x41)) |
165 | 180 | { |
166 | 181 | return -std::numeric_limits<value_type>::infinity(); |
167 | 182 | } |
168 | | - else if (encodedLength == 1 && preamble == 0x42) |
| 183 | + else if ((encodedLength == 1) && (preamble == 0x42)) |
169 | 184 | { |
170 | 185 | return std::numeric_limits<value_type>::quiet_NaN(); |
171 | 186 | } |
| 187 | + else if ((encodedLength == 1) && (preamble == 0x43)) |
| 188 | + { |
| 189 | + return static_cast<value_type>(-0.0); |
| 190 | + } |
172 | 191 | else |
173 | 192 | { |
174 | 193 | unsigned long long bits = 0; |
175 | 194 | unsigned int const sign = (preamble & 0x40); |
176 | 195 | unsigned int const exponentLength = 1 + (preamble & 3); |
177 | 196 | unsigned int const mantissaShift = ((preamble >> 2) & 3); |
178 | 197 |
|
| 198 | + // Note: If (exponentLength > encodedLength - 1), the following call to decode will throw, |
| 199 | + // so there is no need to check this separately. |
179 | 200 | long long exponent = ber::decode<long long>(input, exponentLength); |
180 | 201 | unsigned long long mantissa = ber::decode<unsigned long long>(input, encodedLength - exponentLength - 1) << mantissaShift; |
181 | 202 |
|
182 | | - while((mantissa & 0x7FFFF00000000000ULL) == 0x00) |
183 | | - mantissa <<= 8; |
| 203 | + if (mantissa != 0) |
| 204 | + { |
| 205 | + while((mantissa & 0x7FFFF00000000000ULL) == 0x00) |
| 206 | + mantissa <<= 8; |
184 | 207 |
|
185 | | - while((mantissa & 0x7FF0000000000000ULL) == 0x00) |
186 | | - mantissa <<= 1; |
| 208 | + while((mantissa & 0x7FF0000000000000ULL) == 0x00) |
| 209 | + mantissa <<= 1; |
| 210 | + } |
187 | 211 |
|
188 | 212 | mantissa &= 0x0FFFFFFFFFFFFFULL; |
189 | 213 | bits = (static_cast<unsigned long long>(exponent + 1023) << 52) | mantissa; |
@@ -246,4 +270,3 @@ namespace libember { namespace ber |
246 | 270 | //EndSimianIgnore |
247 | 271 |
|
248 | 272 | #endif // __LIBEMBER_BER_TRAITS_REAL_HPP |
249 | | - |
|
0 commit comments