aboutsummaryrefslogtreecommitdiff
path: root/src/dmstor.cpp
diff options
context:
space:
mode:
authorBrendan Jurd <direvus@gmail.com>2021-08-15 21:30:57 +1000
committerGitHub <noreply@github.com>2021-08-15 13:30:57 +0200
commit17f83c6f122db849a8877ef0ca641d4743f352cd (patch)
tree0a98295fa2877197a3d64f726a2d7098307693e1 /src/dmstor.cpp
parenta46df0f3a298060ee8322237c849a17ff34e0989 (diff)
downloadPROJ-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.cpp63
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;