1 /* error-checking interface to strtod-like functions 2 3 Copyright (C) 1996, 1999-2000, 2003-2006, 2009-2021 Free Software 4 Foundation, Inc. 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 18 19 /* Written by Jim Meyering. */ 20 21 #include <config.h> 22 23 #include "xstrtod.h" 24 25 #include <errno.h> 26 #include <limits.h> 27 #include <stdio.h> 28 29 #if LONG 30 # define XSTRTOD xstrtold 31 # define DOUBLE long double 32 #else 33 # define XSTRTOD xstrtod 34 # define DOUBLE double 35 #endif 36 37 /* An interface to a string-to-floating-point conversion function that 38 encapsulates all the error checking one should usually perform. 39 Like strtod/strtold, but stores the conversion in *RESULT, 40 and returns true upon successful conversion. 41 CONVERT specifies the conversion function, e.g., strtod itself. */ 42 43 bool 44 XSTRTOD (char const *str, char const **ptr, DOUBLE *result, /* */ 45 DOUBLE (*convert) (char const *, char **)) 46 { 47 DOUBLE val; 48 char *terminator; 49 bool ok = true; 50 51 errno = 0; 52 val = convert (str, &terminator); 53 54 /* Having a non-zero terminator is an error only when PTR is NULL. */ 55 if (terminator == str || (ptr == NULL && *terminator != '\0')) 56 ok = false; 57 else 58 { 59 /* Allow underflow (in which case CONVERT returns zero), 60 but flag overflow as an error. The user can decide 61 to use the limits in RESULT upon ERANGE. */ 62 if (val != 0 && errno == ERANGE) 63 ok = false; 64 } 65 66 if (ptr != NULL) 67 *ptr = terminator; 68 69 *result = val; 70 return ok; 71 }