LCOV - code coverage report
Current view: top level - include/flatcc/portable - pparsefp.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 4 50.0 %
Date: 2016-11-30 13:12:14 Functions: 0 0 -
Branches: 0 8 0.0 %

           Branch data     Line data    Source code
       1                 :            : #ifndef PPARSEFP_H
       2                 :            : #define PPARSEFP_H
       3                 :            : 
       4                 :            : /*
       5                 :            :  * Parses a float or double number and returns the length parsed if
       6                 :            :  * successful. The length argument is of limited value due to dependency
       7                 :            :  * on `strtod` - buf[len] must be accessible and must not be part of
       8                 :            :  * a valid number, including hex float numbers..
       9                 :            :  *
      10                 :            :  * Unlike strtod, whitespace is not parsed.
      11                 :            :  *
      12                 :            :  * May return:
      13                 :            :  * - null on error,
      14                 :            :  * - buffer start if first character does not start a number,
      15                 :            :  * - or end of parse on success.
      16                 :            :  *
      17                 :            :  */
      18                 :            : 
      19                 :            : #define PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION
      20                 :            : #include "pdiagnostic_push.h"
      21                 :            : 
      22                 :            : /*
      23                 :            :  * isinf is needed in order to stay compatible with strtod's
      24                 :            :  * over/underflow handling but isinf has some portability issues.
      25                 :            :  *
      26                 :            :  * Use the parse_double/float_is_range_error instead of isinf directly.
      27                 :            :  * This ensures optimizations can be added when not using strtod.
      28                 :            :  *
      29                 :            :  * On gcc, clang and msvc we can use isinf or equivalent directly.
      30                 :            :  * Other compilers such as xlc may require linking with -lm which may not
      31                 :            :  * be convienent so a default isinf is provided. If isinf is available
      32                 :            :  * and there is a noticable performance issue, define
      33                 :            :  * `PORTABLE_USE_ISINF`.
      34                 :            :  */
      35                 :            : #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || defined(PORTABLE_USE_ISINF)
      36                 :            : #include <math.h>
      37                 :            : #if defined(_MSC_VER) && !defined(isinf)
      38                 :            : #include <float.h>
      39                 :            : #define isnan _isnan
      40                 :            : #define isinf(x) (!_finite(x))
      41                 :            : #endif
      42                 :            : #define parse_double_isinf isinf
      43                 :            : #define parse_float_isinf isinf
      44                 :            : #else
      45                 :            : 
      46                 :            : #ifndef UINT8_MAX
      47                 :            : #include <stdint.h>
      48                 :            : #endif
      49                 :            : 
      50                 :            : /* Avoid linking with libmath but depends on float/double being IEEE754 */
      51                 :            : static inline int parse_double_isinf(double x)
      52                 :            : {
      53                 :            :     union { uint64_t u64; double f64; } v;
      54                 :            :     v.f64 = x;
      55                 :            :     return (v.u64 & 0x7fffffff00000000ULL) == 0x7ff0000000000000ULL;
      56                 :            : }
      57                 :            : 
      58                 :            : static inline int parse_float_isinf(float x)
      59                 :            : {
      60                 :            :     union { uint32_t u32; float f32; } v;
      61                 :            :     v.f32 = x;
      62                 :            :     return (v.u32 & 0x7fffffff) == 0x7f800000;
      63                 :            : }
      64                 :            : #endif
      65                 :            : 
      66                 :            : /* Returns 0 when in range, 1 on overflow, and -1 on underflow. */
      67                 :            : static inline int parse_double_is_range_error(double x)
      68                 :            : {
      69 [ #  # ][ #  # ]:          0 :     return parse_double_isinf(x) ? (x < 0.0 ? -1 : 1) : 0;
      70                 :            : }
      71                 :            : 
      72                 :            : static inline int parse_float_is_range_error(float x)
      73                 :            : {
      74 [ #  # ][ #  # ]:          0 :     return parse_float_isinf(x) ? (x < 0.0f ? -1 : 1) : 0;
      75                 :            : }
      76                 :            : 
      77                 :            : #ifndef PORTABLE_USE_GRISU3
      78                 :            : #define PORTABLE_USE_GRISU3 1
      79                 :            : #endif
      80                 :            : 
      81                 :            : #if PORTABLE_USE_GRISU3
      82                 :            : #include "grisu3_parse.h"
      83                 :            : #endif
      84                 :            : 
      85                 :            : #ifdef grisu3_parse_double_is_defined
      86                 :            : static inline const char *parse_double(const char *buf, int len, double *result)
      87                 :            : {
      88                 :          5 :     return grisu3_parse_double(buf, len, result);
      89                 :            : }
      90                 :            : #else
      91                 :            : #include <stdio.h>
      92                 :            : static inline const char *parse_double(const char *buf, int len, double *result)
      93                 :            : {
      94                 :            :     char *end;
      95                 :            : 
      96                 :            :     (void)len;
      97                 :            :     *result = strtod(buf, &end);
      98                 :            :     return end;
      99                 :            : }
     100                 :            : #endif
     101                 :            : 
     102                 :            : static inline const char *parse_float(const char *buf, int len, float *result)
     103                 :            : {
     104                 :            :     const char *end;
     105                 :            :     double v;
     106                 :            : 
     107                 :            :     end = parse_double(buf, len, &v);
     108                 :          3 :     *result = (float)v;
     109                 :            :     return end;
     110                 :            : }
     111                 :            : 
     112                 :            : #include "pdiagnostic_pop.h"
     113                 :            : #endif /* PPARSEFP_H */

Generated by: LCOV version 1.12