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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/* Convert DMS string to radians */
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "proj.h"
#include "proj_internal.h"
static double proj_strtod(char *nptr, char **endptr);
/* following should be sufficient for all but the ridiculous */
#define MAX_WORK 64
static const char
*sym = "NnEeSsWw";
static const double
vm[] = {
DEG_TO_RAD,
.0002908882086657216,
.0000048481368110953599
};
/* byte sequence for Degree Sign U+00B0 in UTF-8. */
static constexpr char
DEG_SIGN1 = '\xc2';
static constexpr char
DEG_SIGN2 = '\xb0';
double
dmstor(const char *is, char **rs) {
return dmstor_ctx( pj_get_default_ctx(), is, rs );
}
double
dmstor_ctx(PJ_CONTEXT *ctx, const char *is, char **rs) {
int n, nl;
char *s, work[MAX_WORK];
const char* p;
double v, tv;
if (rs)
*rs = (char *)is;
/* copy string into work space */
while (isspace(*is)) ++is;
n = MAX_WORK;
s = work;
p = (char *)is;
/*
* Copy characters into work until we hit a non-printable character or run
* out of space in the buffer. Make a special exception for the bytes of
* the Degree Sign in UTF-8.
*
* It is possible that a really odd input (like lots of leading zeros)
* could be truncated in copying into work. But ...
*/
while ((isgraph(*p) || *p == DEG_SIGN1 || *p == DEG_SIGN2) && --n)
*s++ = *p++;
*s = '\0';
int sign = *(s = work);
if (sign == '+' || sign == '-') s++;
else sign = '+';
v = 0.;
for (nl = 0 ; nl < 3 ; nl = n + 1) {
if (!(isdigit(*s) || *s == '.')) break;
if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
return tv;
int adv = 1;
if (*s == 'D' || *s == 'd' || *s == DEG_SIGN2) {
/*
* Accept \xb0 as a single-byte degree symbol. This byte is the
* degree symbol in various single-byte encodings: multiple ISO
* 8859 parts, several Windows code pages and others.
*/
n = 0;
} else if (*s == '\'') {
n = 1;
} else if (*s == '"') {
n = 2;
} else if (s[0] == DEG_SIGN1 && s[1] == DEG_SIGN2) {
/* degree symbol in UTF-8 */
n = 0;
adv = 2;
} else if (*s == 'r' || *s == 'R') {
if (nl) {
proj_context_errno_set( ctx, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE );
return HUGE_VAL;
}
++s;
v = tv;
n = 4;
continue;
} else {
v += tv * vm[nl];
n = 4;
continue;
}
if (n < nl) {
proj_context_errno_set( ctx, PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE );
return HUGE_VAL;
}
v += tv * vm[n];
s += adv;
}
/* postfix sign */
if (*s && (p = strchr(sym, *s))) {
sign = (p - sym) >= 4 ? '-' : '+';
++s;
}
if (sign == '-')
v = -v;
if (rs) /* return point of next char after valid string */
*rs = (char *)is + (s - work);
return v;
}
static double
proj_strtod(char *nptr, char **endptr)
{
char c, *cp = nptr;
double result;
/*
* Scan for characters which cause problems with VC++ strtod()
*/
while ((c = *cp) != '\0') {
if (c == 'd' || c == 'D') {
/*
* Found one, so NUL it out, call strtod(),
* then restore it and return
*/
*cp = '\0';
result = strtod(nptr, endptr);
*cp = c;
return result;
}
++cp;
}
/* no offending characters, just handle normally */
return pj_strtod(nptr, endptr);
}
|