@@ -160,40 +160,269 @@ bool CheckRangeAndIfHexThenSignExtend(T value, const NumberType& type,
160
160
return true ;
161
161
}
162
162
163
+ #include < cstdlib>
164
+ #include < climits>
165
+
163
166
// Parses a numeric value of a given type from the given text. The number
164
167
// should take up the entire string, and should be within bounds for the target
165
168
// type. On success, returns true and populates the object referenced by
166
169
// value_pointer. On failure, returns false.
167
- template <typename T>
168
- bool ParseNumber (const char * text, T* value_pointer) {
169
- // C++11 doesn't define std::istringstream(int8_t&), so calling this method
170
- // with a single-byte type leads to implementation-defined behaviour.
171
- // Similarly for uint8_t.
172
- static_assert (sizeof (T) > 1 ,
173
- " Single-byte types are not supported in this parse method" );
170
+ // template <typename T>
171
+ // bool ParseNumber(const char* text, T* value_pointer) {
172
+ // // C++11 doesn't define std::istringstream(int8_t&), so calling this method
173
+ // // with a single-byte type leads to implementation-defined behaviour.
174
+ // // Similarly for uint8_t.
175
+ // static_assert(sizeof(T) > 1,
176
+ // "Single-byte types are not supported in this parse method");
177
+
178
+ // if (!text) return false;
179
+ // std::istringstream text_stream(text);
180
+ // // Allow both decimal and hex input for integers.
181
+ // // It also allows octal input, but we don't care about that case.
182
+ // text_stream >> std::setbase(0);
183
+ // text_stream >> *value_pointer;
184
+
185
+ // // We should have read something.
186
+ // bool ok = (text[0] != 0) && !text_stream.bad();
187
+ // // It should have been all the text.
188
+ // ok = ok && text_stream.eof();
189
+ // // It should have been in range.
190
+ // ok = ok && !text_stream.fail();
191
+
192
+ // // Work around a bug in the GNU C++11 library. It will happily parse
193
+ // // "-1" for uint16_t as 65535.
194
+ // if (ok && text[0] == '-')
195
+ // ok = !ClampToZeroIfUnsignedType<T>::Clamp(value_pointer);
196
+
197
+ // return ok;
198
+ // }
199
+
200
+ template <typename T, typename Traits>
201
+ inline bool ParseFloat (const char * text, HexFloat<T, Traits>* value);
202
+
203
+ inline bool ParseNormalFloat (const char * text, float * value_pointer) {
204
+ if (!text) return false ;
205
+
206
+ char * end = nullptr ;
207
+ errno = 0 ;
208
+ auto parsed = std::strtof (text, &end);
209
+
210
+ if ((errno == ERANGE && (parsed == HUGE_VALF || parsed == -HUGE_VALF)) || (errno != 0 && parsed == 0 )) {
211
+ return false ;
212
+ }
213
+
214
+ if (end == text || end[0 ] != 0 ) {
215
+ return false ;
216
+ }
217
+
218
+ *value_pointer = parsed;
219
+ return true ;
220
+ }
221
+
222
+ inline bool ParseNormalFloat (const char * text, double * value_pointer) {
223
+ if (!text) return false ;
224
+
225
+ char * end = nullptr ;
226
+ errno = 0 ;
227
+ auto parsed = std::strtod (text, &end);
228
+
229
+ if ((errno == ERANGE && (parsed == HUGE_VAL || parsed == -HUGE_VAL)) || (errno != 0 && parsed == 0 )) {
230
+ return false ;
231
+ }
232
+
233
+ if (end == text || end[0 ] != 0 ) {
234
+ return false ;
235
+ }
236
+
237
+ *value_pointer = parsed;
238
+ return true ;
239
+ }
240
+
241
+ template <>
242
+ inline bool ParseFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>(
243
+ const char * text,
244
+ HexFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>* value_pointer) {
245
+ float parsed;
246
+ if (!ParseNormalFloat (text, &parsed)) {
247
+ return false ;
248
+ }
249
+
250
+ HexFloat<FloatProxy<float >> float_val (parsed);
251
+ float_val.castTo (*value_pointer, round_direction::kToZero );
252
+
253
+ if (Float16::isInfinity (value_pointer->value ().getAsFloat ())) {
254
+ value_pointer->set_value (value_pointer->isNegative () ? Float16::lowest () : Float16::max ());
255
+ return false ;
256
+ }
257
+
258
+ return true ;
259
+ }
260
+
261
+ template <>
262
+ inline bool ParseFloat<FloatProxy<float >, HexFloatTraits<FloatProxy<float >>>(
263
+ const char * text,
264
+ HexFloat<FloatProxy<float >, HexFloatTraits<FloatProxy<float >>>* value_pointer) {
265
+ float parsed;
266
+ if (!ParseNormalFloat (text, &parsed)) {
267
+ return false ;
268
+ }
269
+
270
+ value_pointer->set_value (parsed);
271
+ return true ;
272
+ }
273
+
274
+ template <>
275
+ inline bool ParseFloat<FloatProxy<double >, HexFloatTraits<FloatProxy<double >>>(
276
+ const char * text,
277
+ HexFloat<FloatProxy<double >, HexFloatTraits<FloatProxy<double >>>* value_pointer) {
278
+ double parsed;
279
+ if (!ParseNormalFloat (text, &parsed)) {
280
+ return false ;
281
+ }
282
+
283
+ value_pointer->set_value (parsed);
284
+ return true ;
285
+ }
286
+
287
+ inline bool ParseInteger (const char * text, uint16_t * value_pointer) {
288
+ if (!text || text[0 ] == ' -' ) return false ;
289
+
290
+ char * end = nullptr ;
291
+ errno = 0 ;
292
+ auto parsed = std::strtoul (text, &end, 0 );
293
+
294
+ if ((errno == ERANGE && parsed == ULONG_MAX) || (errno != 0 && parsed == 0 )) {
295
+ return false ;
296
+ }
297
+
298
+ if (end == text || end[0 ] != 0 ) {
299
+ return false ;
300
+ }
301
+
302
+ if (parsed > std::numeric_limits<uint16_t >::max () || parsed < std::numeric_limits<uint16_t >::min ()) {
303
+ return false ;
304
+ }
305
+
306
+ *value_pointer = static_cast <uint16_t >(parsed);
307
+ return true ;
308
+ }
309
+
310
+ inline bool ParseInteger (const char * text, int16_t * value_pointer) {
311
+ if (!text) return false ;
174
312
313
+ char * end = nullptr ;
314
+ errno = 0 ;
315
+ auto parsed = std::strtol (text, &end, 0 );
316
+
317
+ if ((errno == ERANGE && (parsed == LONG_MAX || parsed == LONG_MIN)) || (errno != 0 && parsed == 0 )) {
318
+ return false ;
319
+ }
320
+
321
+ if (end == text || end[0 ] != 0 ) {
322
+ return false ;
323
+ }
324
+
325
+ if (parsed > std::numeric_limits<int16_t >::max () || parsed < std::numeric_limits<int16_t >::min ()) {
326
+ return false ;
327
+ }
328
+
329
+ *value_pointer = static_cast <int16_t >(parsed);
330
+ return true ;
331
+ }
332
+
333
+ inline bool ParseInteger (const char * text, uint32_t * value_pointer) {
334
+ if (!text || text[0 ] == ' -' ) return false ;
335
+
336
+ char * end = nullptr ;
337
+ errno = 0 ;
338
+ auto parsed = std::strtoul (text, &end, 0 );
339
+
340
+ if ((errno == ERANGE && parsed == ULONG_MAX) || (errno != 0 && parsed == 0 )) {
341
+ return false ;
342
+ }
343
+
344
+ if (end == text || end[0 ] != 0 ) {
345
+ return false ;
346
+ }
347
+
348
+ if (parsed > std::numeric_limits<uint32_t >::max () || parsed < std::numeric_limits<uint32_t >::min ()) {
349
+ return false ;
350
+ }
351
+
352
+ *value_pointer = static_cast <uint32_t >(parsed);
353
+ return true ;
354
+ }
355
+
356
+ inline bool ParseInteger (const char * text, int32_t * value_pointer) {
175
357
if (!text) return false ;
176
- std::istringstream text_stream (text);
177
- // Allow both decimal and hex input for integers.
178
- // It also allows octal input, but we don't care about that case.
179
- text_stream >> std::setbase (0 );
180
- text_stream >> *value_pointer;
181
-
182
- // We should have read something.
183
- bool ok = (text[0 ] != 0 ) && !text_stream.bad ();
184
- // It should have been all the text.
185
- ok = ok && text_stream.eof ();
186
- // It should have been in range.
187
- ok = ok && !text_stream.fail ();
188
-
189
- // Work around a bug in the GNU C++11 library. It will happily parse
190
- // "-1" for uint16_t as 65535.
191
- if (ok && text[0 ] == ' -' )
192
- ok = !ClampToZeroIfUnsignedType<T>::Clamp (value_pointer);
193
-
194
- return ok;
358
+
359
+ char * end = nullptr ;
360
+ errno = 0 ;
361
+ auto parsed = std::strtol (text, &end, 0 );
362
+
363
+ if ((errno == ERANGE && (parsed == LONG_MAX || parsed == LONG_MIN)) || (errno != 0 && parsed == 0 )) {
364
+ return false ;
365
+ }
366
+
367
+ if (end == text || end[0 ] != 0 ) {
368
+ return false ;
369
+ }
370
+
371
+ if (parsed > std::numeric_limits<int32_t >::max () || parsed < std::numeric_limits<int32_t >::min ()) {
372
+ return false ;
373
+ }
374
+
375
+ *value_pointer = static_cast <int32_t >(parsed);
376
+ return true ;
377
+ }
378
+
379
+ inline bool ParseInteger (const char * text, int64_t * value_pointer) {
380
+ if (!text) return false ;
381
+
382
+ char * end = nullptr ;
383
+ errno = 0 ;
384
+ auto parsed = std::strtoll (text, &end, 0 );
385
+
386
+ if ((errno == ERANGE && (parsed == LLONG_MAX || parsed == LLONG_MIN)) || (errno != 0 && parsed == 0 )) {
387
+ return false ;
388
+ }
389
+
390
+ if (end == text || end[0 ] != 0 ) {
391
+ return false ;
392
+ }
393
+
394
+ if (parsed > std::numeric_limits<int64_t >::max () || parsed < std::numeric_limits<int64_t >::min ()) {
395
+ return false ;
396
+ }
397
+
398
+ *value_pointer = static_cast <int64_t >(parsed);
399
+ return true ;
195
400
}
196
401
402
+ inline bool ParseInteger (const char * text, uint64_t * value_pointer) {
403
+ if (!text || text[0 ] == ' -' ) return false ;
404
+
405
+ char * end = nullptr ;
406
+ errno = 0 ;
407
+ auto parsed = std::strtoull (text, &end, 0 );
408
+
409
+ if ((errno == ERANGE && parsed == ULLONG_MAX) || (errno != 0 && parsed == 0 )) {
410
+ return false ;
411
+ }
412
+
413
+ if (end == text || end[0 ] != 0 ) {
414
+ return false ;
415
+ }
416
+
417
+ if (parsed > std::numeric_limits<uint64_t >::max () || parsed < std::numeric_limits<uint64_t >::min ()) {
418
+ return false ;
419
+ }
420
+
421
+ *value_pointer = static_cast <uint64_t >(parsed);
422
+ return true ;
423
+ }
424
+
425
+
197
426
// Enum to indicate the parsing and encoding status.
198
427
enum class EncodeNumberStatus {
199
428
kSuccess = 0 ,
0 commit comments