root / org.gvsig.jcrs / libjni-proj4 / src / dmstor.c @ 36
History | View | Annotate | Download (2.3 KB)
1 | 36 | jjdelcerro | /* 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 | } |