From 0eb53fab52acdcca60a3a80d4d0d9e1e9fffb38b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 22 Feb 2013 16:18:39 -0800 Subject: Flesh out the UDDF xml parsing a bit more Commit 28aba5a2062c ("Flesh out the UDDF xml parsing a bit more") improved on parsing UDDF files by teaching "percent()" to also handle pure fractions like UDDF uses. So in a UDDF file, an o2 value of "1.0" means "100%". But it turns out that I have a few dives with "1% He", and the "Turn fractions into percent" logic also turns that into 100%. So this makes the 'percent()' function a bit smarter. If it actually finds a percentage-sign after the number, it knows it is already percent, not a fraction. That disambiguates the two cases: "1.0" is 100%, but "1.0%" (note the explicit percentage sign) is 1%. So now our native format cannot get confused, because it generally tries to avoid naked numbers. Good choice. Signed-off-by: Linus Torvalds Signed-off-by: Dirk Hohndel --- parse-xml.c | 54 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'parse-xml.c') diff --git a/parse-xml.c b/parse-xml.c index ddb3ba347..e23ebc0a9 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -195,28 +195,32 @@ static void divedatetime(char *buffer, void *_when) } } -union int_or_float { - double fp; -}; - enum number_type { NEITHER, FLOAT }; -static enum number_type integer_or_float(char *buffer, union int_or_float *res) +static enum number_type parse_float(char *buffer, double *res, char **endp) { - char *end; - double fp; + double val; errno = 0; - fp = g_ascii_strtod(buffer, &end); - if (!errno && end != buffer) { - res->fp = fp; - return FLOAT; - } + val = g_ascii_strtod(buffer, endp); + if (errno || *endp == buffer) + return NEITHER; + + *res = val; + return FLOAT; +} + +union int_or_float { + double fp; +}; - return NEITHER; +static enum number_type integer_or_float(char *buffer, union int_or_float *res) +{ + char *end; + return parse_float(buffer, &res->fp, &end); } static void pressure(char *buffer, void *_press) @@ -361,18 +365,24 @@ static void duration(char *buffer, void *_time) static void percent(char *buffer, void *_fraction) { fraction_t *fraction = _fraction; - union int_or_float val; + double val; + char *end; - switch (integer_or_float(buffer, &val)) { + switch (parse_float(buffer, &val, &end)) { case FLOAT: - /* Turn fractions into percent.. */ - if (val.fp <= 1.0) - val.fp *= 100; - /* Then turn percent into our integer permille format */ - if (val.fp <= 100.0) - fraction->permille = val.fp * 10 + 0.5; - break; + /* Turn fractions into percent unless explicit.. */ + if (val <= 1.0) { + while (isspace(*end)) + end++; + if (*end != '%') + val *= 100; + } + /* Then turn percent into our integer permille format */ + if (val >= 0 && val <= 100.0) { + fraction->permille = val * 10 + 0.5; + break; + } default: printf("Strange percentage reading %s\n", buffer); break; -- cgit v1.2.3-70-g09d2