]> git.street.me.uk Git - andy/viking.git/blame - src/misc/strtod.c
Read OSM Metatile capability and basic test with single example metatile.
[andy/viking.git] / src / misc / strtod.c
CommitLineData
241d0215
RN
1//
2// strtod.c
3//
4// Convert string to double
5//
6// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions
10// are met:
11//
12// 1. Redistributions of source code must retain the above copyright
13// notice, this list of conditions and the following disclaimer.
14// 2. Redistributions in binary form must reproduce the above copyright
15// notice, this list of conditions and the following disclaimer in the
16// documentation and/or other materials provided with the distribution.
17// 3. Neither the name of the project nor the names of its contributors
18// may be used to endorse or promote products derived from this software
19// without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
25// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31// SUCH DAMAGE.
32//
33
81687a73
RN
34// Tweaked version for Viking project to read in values containing ',' or '.' as the decimal separator
35// Modified functions to prevent clashing with the system ones
36
241d0215
RN
37#include <errno.h>
38#include <ctype.h>
39#include <math.h>
40#include <float.h>
41#include <stdlib.h>
42
81687a73 43double strtod_i8n(const char *str, char **endptr) {
241d0215
RN
44 double number;
45 int exponent;
46 int negative;
47 char *p = (char *) str;
48 double p10;
49 int n;
50 int num_digits;
51 int num_decimals;
52
53 // Skip leading whitespace
54 while (isspace(*p)) p++;
55
56 // Handle optional sign
57 negative = 0;
58 switch (*p) {
59 case '-': negative = 1; // Fall through to increment position
60 case '+': p++;
61 }
62
63 number = 0.;
64 exponent = 0;
65 num_digits = 0;
66 num_decimals = 0;
67
68 // Process string of digits
69 while (isdigit(*p)) {
70 number = number * 10. + (*p - '0');
71 p++;
72 num_digits++;
73 }
74
75 // Process decimal part
81687a73 76 if (*p == '.' || *p == ',') {
241d0215
RN
77 p++;
78
79 while (isdigit(*p)) {
80 number = number * 10. + (*p - '0');
81 p++;
82 num_digits++;
83 num_decimals++;
84 }
85
86 exponent -= num_decimals;
87 }
88
89 if (num_digits == 0) {
90 errno = ERANGE;
91 return 0.0;
92 }
93
94 // Correct for sign
95 if (negative) number = -number;
96
97 // Process an exponent string
98 if (*p == 'e' || *p == 'E') {
99 // Handle optional sign
100 negative = 0;
101 switch (*++p) {
102 case '-': negative = 1; // Fall through to increment pos
103 case '+': p++;
104 }
105
106 // Process string of digits
107 n = 0;
108 while (isdigit(*p)) {
109 n = n * 10 + (*p - '0');
110 p++;
111 }
112
113 if (negative) {
114 exponent -= n;
115 } else {
116 exponent += n;
117 }
118 }
119
120 if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP) {
121 errno = ERANGE;
122 return HUGE_VAL;
123 }
124
125 // Scale the result
126 p10 = 10.;
127 n = exponent;
128 if (n < 0) n = -n;
129 while (n) {
130 if (n & 1) {
131 if (exponent < 0) {
132 number /= p10;
133 } else {
134 number *= p10;
135 }
136 }
137 n >>= 1;
138 p10 *= p10;
139 }
140
141 if (number == HUGE_VAL) errno = ERANGE;
142 if (endptr) *endptr = p;
143
144 return number;
145}
146
81687a73
RN
147float strtof_i8n(const char *str, char **endptr) {
148 return (float) strtod_i8n(str, endptr);
241d0215
RN
149}
150
151
81687a73
RN
152long double strtold_i8n(const char *str, char **endptr) {
153 return strtod_i8n(str, endptr);
241d0215
RN
154}
155
81687a73
RN
156double atof_i8n(const char *str) {
157 return strtod_i8n(str, NULL);
241d0215 158}