svn-gvsig-desktop / trunk / libraries / libjni-proj4 / src / dmstor.c @ 7098
History | View | Annotate | Download (2.3 KB)
1 |
/* Convert DMS string to radians */
|
---|---|
2 |
#ifndef lint
|
3 |
static const char SCCSID[]="@(#)dmstor.c 4.4 93/06/16 GIE REL"; |
4 |
#endif
|
5 |
#include <projects.h> |
6 |
#include <string.h> |
7 |
#include <ctype.h> |
8 |
|
9 |
static double proj_strtod(char *nptr, char **endptr); |
10 |
|
11 |
/* following should be sufficient for all but the rediculous */
|
12 |
#define MAX_WORK 64 |
13 |
static const char |
14 |
*sym = "NnEeSsWw";
|
15 |
static const double |
16 |
vm[] = { |
17 |
.0174532925199433,
|
18 |
.0002908882086657216,
|
19 |
.0000048481368110953599
|
20 |
}; |
21 |
double
|
22 |
dmstor(const char *is, char **rs) { |
23 |
int sign, n, nl;
|
24 |
char *p, *s, work[MAX_WORK];
|
25 |
double v, tv;
|
26 |
|
27 |
if (rs)
|
28 |
*rs = (char *)is;
|
29 |
/* copy sting into work space */
|
30 |
while (isspace(sign = *is)) ++is;
|
31 |
for (n = MAX_WORK, s = work, p = (char *)is; isgraph(*p) && --n ; ) |
32 |
*s++ = *p++; |
33 |
*s = '\0';
|
34 |
/* it is possible that a really odd input (like lots of leading
|
35 |
zeros) could be truncated in copying into work. But ... */
|
36 |
sign = *(s = work); |
37 |
if (sign == '+' || sign == '-') s++; |
38 |
else sign = '+'; |
39 |
for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) { |
40 |
if (!(isdigit(*s) || *s == '.')) break; |
41 |
if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
|
42 |
return tv;
|
43 |
switch (*s) {
|
44 |
case 'D': case 'd': |
45 |
n = 0; break; |
46 |
case '\'': |
47 |
n = 1; break; |
48 |
case '"': |
49 |
n = 2; break; |
50 |
case 'r': case 'R': |
51 |
if (nl) {
|
52 |
pj_errno = -16;
|
53 |
return HUGE_VAL;
|
54 |
} |
55 |
++s; |
56 |
v = tv; |
57 |
goto skip;
|
58 |
default:
|
59 |
v += tv * vm[nl]; |
60 |
skip: n = 4; |
61 |
continue;
|
62 |
} |
63 |
if (n < nl) {
|
64 |
pj_errno = -16;
|
65 |
return HUGE_VAL;
|
66 |
} |
67 |
v += tv * vm[n]; |
68 |
++s; |
69 |
} |
70 |
/* postfix sign */
|
71 |
if (*s && (p = strchr(sym, *s))) {
|
72 |
sign = (p - sym) >= 4 ? '-' : '+'; |
73 |
++s; |
74 |
} |
75 |
if (sign == '-') |
76 |
v = -v; |
77 |
if (rs) /* return point of next char after valid string */ |
78 |
*rs = (char *)is + (s - work);
|
79 |
return v;
|
80 |
} |
81 |
|
82 |
static double |
83 |
proj_strtod(char *nptr, char **endptr) |
84 |
|
85 |
{ |
86 |
char c, *cp = nptr;
|
87 |
double result;
|
88 |
|
89 |
/*
|
90 |
* Scan for characters which cause problems with VC++ strtod()
|
91 |
*/
|
92 |
while ((c = *cp) != '\0') { |
93 |
if (c == 'd' || c == 'D') { |
94 |
|
95 |
/*
|
96 |
* Found one, so NUL it out, call strtod(),
|
97 |
* then restore it and return
|
98 |
*/
|
99 |
*cp = '\0';
|
100 |
result = strtod(nptr, endptr); |
101 |
*cp = c; |
102 |
return result;
|
103 |
} |
104 |
++cp; |
105 |
} |
106 |
|
107 |
/* no offending characters, just handle normally */
|
108 |
|
109 |
return strtod(nptr, endptr);
|
110 |
} |
111 |
|