File: melder_atof.cpp

package info (click to toggle)
praat 5.3.16-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 40,728 kB
  • sloc: cpp: 333,759; ansic: 237,947; makefile: 731; python: 340
file content (117 lines) | stat: -rw-r--r-- 3,362 bytes parent folder | download | duplicates (2)
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 */