diff options
| author | Brendan Jurd <direvus@gmail.com> | 2021-08-15 21:30:57 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-15 13:30:57 +0200 |
| commit | 17f83c6f122db849a8877ef0ca641d4743f352cd (patch) | |
| tree | 0a98295fa2877197a3d64f726a2d7098307693e1 /src/dmstor.cpp | |
| parent | a46df0f3a298060ee8322237c849a17ff34e0989 (diff) | |
| download | PROJ-17f83c6f122db849a8877ef0ca641d4743f352cd.tar.gz PROJ-17f83c6f122db849a8877ef0ca641d4743f352cd.zip | |
Add support for Degree Sign on input (#2791)
This commit adds support in dsmtor() for a Degree Sign (U+00B0), encoded
as UTF-8 (`\xc2\xb0`) or as a single byte (`\xb0`) (in ISO 8859 parts 1-4, 7-10,
13, 15, 16, and several Windows code pages), as an alternative symbol to
`D`/`d` to designate the degree unit.
Fixes #2712.
Diffstat (limited to 'src/dmstor.cpp')
| -rw-r--r-- | src/dmstor.cpp | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/src/dmstor.cpp b/src/dmstor.cpp index e65d4884..eeff1841 100644 --- a/src/dmstor.cpp +++ b/src/dmstor.cpp @@ -20,6 +20,12 @@ vm[] = { .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 ); @@ -29,57 +35,76 @@ dmstor(const char *is, char **rs) { dmstor_ctx(PJ_CONTEXT *ctx, const char *is, char **rs) { int n, nl; char *s, work[MAX_WORK]; - const char* p; + const char* p; double v, tv; if (rs) *rs = (char *)is; - /* copy sting into work space */ + /* copy string into work space */ while (isspace(*is)) ++is; n = MAX_WORK; s = work; p = (char *)is; - while (isgraph(*p) && --n) + + /* + * 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'; - /* it is possible that a really odd input (like lots of leading - zeros) could be truncated in copying into work. But ... */ int sign = *(s = work); if (sign == '+' || sign == '-') s++; else sign = '+'; v = 0.; - for (nl = 0 ; nl < 3 ; nl = n + 1 ) { + for (nl = 0 ; nl < 3 ; nl = n + 1) { if (!(isdigit(*s) || *s == '.')) break; if ((tv = proj_strtod(s, &s)) == HUGE_VAL) return tv; - switch (*s) { - case 'D': case 'd': - n = 0; break; - case '\'': - n = 1; break; - case '"': - n = 2; break; - case 'r': case 'R': + 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; - goto skip; - default: + n = 4; + continue; + } else { v += tv * vm[nl]; - skip: n = 4; + 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; + s += adv; } - /* postfix sign */ + /* postfix sign */ if (*s && (p = strchr(sym, *s))) { sign = (p - sym) >= 4 ? '-' : '+'; ++s; |
