1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
/* melder_atof.cpp
*
* Copyright (C) 2003-2011 Paul Boersma
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* pb 2003/05/19 Melder_atof
* pb 2006/04/16 moved Melder_atof from melder.c
* pb 2006/04/16 moved Melder_isStringNumeric from Table.c
* pb 2006/12/08 guard against null strings
* pb 2011/04/05 C++
*/
#include "melder.h"
#include "NUM.h"
static const wchar_t *findEndOfNumericString_nothrow (const wchar_t *string) {
const wchar_t *p = & string [0];
/*
* Leading white space is OK.
*/
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
p ++;
/*
* Next we accept an optional leading plus or minus.
*/
if (*p == '+' || *p == '-') p ++;
/*
* The next character must be a decimal digit.
* So we don't allow things like ".5".
*/
if (*p < '0' || *p > '9') return NULL; /* String is not numeric. */
p ++;
/*
* Then we accept any number of decimal digits.
*/
while (*p >= '0' && *p <= '9') p ++;
/*
* Next we accept an optional decimal point.
*/
if (*p == '.') {
p ++;
/*
* We accept any number of (even zero) decimal digits after the decimal point.
*/
while (*p >= '0' && *p <= '9') p ++;
}
/*
* Next we accept an optional exponential E or e.
*/
if (*p == 'e' || *p == 'E') {
p ++;
/*
* In the exponent we accept an optional leading plus or minus.
*/
if (*p == '+' || *p == '-') p ++;
/*
* The exponent must contain a decimal digit.
* So we don't allow things like "+2.1E".
*/
if (*p < '0' || *p > '9') return NULL; /* String is not numeric. */
p ++;
/*
* Then we accept any number of decimal digits.
*/
while (*p >= '0' && *p <= '9') p ++;
}
/*
* Next we accept an optional percent sign.
*/
if (*p == '%') p ++;
/*
* We have found the end of the numeric string.
*/
return p;
}
int Melder_isStringNumeric_nothrow (const wchar_t *string) {
if (string == NULL) return false;
const wchar_t *p = findEndOfNumericString_nothrow (string);
if (p == NULL) return FALSE;
/*
* We accept only white space after the numeric string.
*/
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
p ++;
return *p == '\0';
}
double Melder_atof (const wchar_t *string) {
if (string == NULL) return NUMundefined;
const wchar_t *p = findEndOfNumericString_nothrow (string);
if (p == NULL) return NUMundefined;
Melder_assert (p - string > 0);
#if defined (macintosh)
/* strtod may be 100 times faster than wcstod: */
return p [-1] == '%' ? 0.01 * strtod (Melder_peekWcsToUtf8 (string), NULL) : strtod (Melder_peekWcsToUtf8 (string), NULL);
#else
return p [-1] == '%' ? 0.01 * wcstod (string, NULL) : wcstod (string, NULL);
#endif
}
/* End of file melder_atof.cpp */
|