/Proj4/dmstor.c

http://github.com/route-me/route-me · C · 111 lines · 103 code · 3 blank · 5 comment · 16 complexity · 9f8c6074076af9b3e61479f73ce6ebd0 MD5 · raw file

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