parser: remove int_or_float union & other small float-parsing cleanups

Owing to bitrot, this union only contained a float and therefore
is pointless. Let's remove it.

That makes the function name "integer_or_float()" non-sensical.
Call it "parse_float()" instead.

Moreover, change the output-arguments of "parse_float()" from
pointers to references, as null-pointers are not supported.

Finally, remove the "errno" check after "ascii_strtod()". As far as
I can tell, errno is not set in "ascii_strtod()" and using a global
variable for error-reporting it is an incredibly silly interface
anyway.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-04-23 14:32:26 +08:00 committed by bstoeger
parent 38a0050ac3
commit 628e2fe933

View file

@ -10,7 +10,6 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include <libxml/parser.h> #include <libxml/parser.h>
@ -151,16 +150,15 @@ enum number_type {
FLOATVAL FLOATVAL
}; };
static enum number_type parse_float(const char *buffer, double *res, const char **endp) static enum number_type parse_float(const char *buffer, double &res, const char *&endp)
{ {
double val; double val;
static bool first_time = true; static bool first_time = true;
errno = 0; val = ascii_strtod(buffer, &endp);
val = ascii_strtod(buffer, endp); if (endp == buffer)
if (errno || *endp == buffer)
return NEITHER; return NEITHER;
if (**endp == ',') { if (*endp == ',') {
if (nearly_equal(val, rint(val))) { if (nearly_equal(val, rint(val))) {
/* we really want to send an error if this is a Subsurface native file /* we really want to send an error if this is a Subsurface native file
* as this is likely indication of a bug - but right now we don't have * as this is likely indication of a bug - but right now we don't have
@ -170,46 +168,42 @@ static enum number_type parse_float(const char *buffer, double *res, const char
first_time = false; first_time = false;
} }
/* Try again in permissive mode*/ /* Try again in permissive mode*/
val = strtod_flags(buffer, endp, 0); val = strtod_flags(buffer, &endp, 0);
} }
} }
*res = val; res = val;
return FLOATVAL; return FLOATVAL;
} }
union int_or_float { static enum number_type parse_float(const char *buffer, double &res)
double fp;
};
static enum number_type integer_or_float(const char *buffer, union int_or_float *res)
{ {
const char *end; const char *end;
return parse_float(buffer, &res->fp, &end); return parse_float(buffer, res, end);
} }
static void pressure(const char *buffer, pressure_t *pressure, struct parser_state *state) static void pressure(const char *buffer, pressure_t *pressure, struct parser_state *state)
{ {
double mbar = 0.0; double mbar = 0.0;
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
/* Just ignore zero values */ /* Just ignore zero values */
if (!val.fp) if (!val)
break; break;
switch (state->xml_parsing_units.pressure) { switch (state->xml_parsing_units.pressure) {
case units::PASCALS: case units::PASCALS:
mbar = val.fp / 100; mbar = val / 100;
break; break;
case units::BAR: case units::BAR:
/* Assume mbar, but if it's really small, it's bar */ /* Assume mbar, but if it's really small, it's bar */
mbar = val.fp; mbar = val;
if (fabs(mbar) < 5000) if (fabs(mbar) < 5000)
mbar = mbar * 1000; mbar = mbar * 1000;
break; break;
case units::PSI: case units::PSI:
mbar = psi_to_mbar(val.fp); mbar = psi_to_mbar(val);
break; break;
} }
if (fabs(mbar) > 5 && fabs(mbar) < 5000000) { if (fabs(mbar) > 5 && fabs(mbar) < 5000000) {
@ -247,10 +241,10 @@ static void cylinder_use(const char *buffer, enum cylinderuse *cyl_use, struct p
static void salinity(const char *buffer, int *salinity) static void salinity(const char *buffer, int *salinity)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
*salinity = lrint(val.fp * 10.0); *salinity = lrint(val * 10.0);
break; break;
default: default:
report_info("Strange salinity reading %s", buffer); report_info("Strange salinity reading %s", buffer);
@ -259,16 +253,16 @@ static void salinity(const char *buffer, int *salinity)
static void depth(const char *buffer, depth_t *depth, struct parser_state *state) static void depth(const char *buffer, depth_t *depth, struct parser_state *state)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
switch (state->xml_parsing_units.length) { switch (state->xml_parsing_units.length) {
case units::METERS: case units::METERS:
depth->mm = lrint(val.fp * 1000); depth->mm = lrint(val * 1000.0);
break; break;
case units::FEET: case units::FEET:
depth->mm = feet_to_mm(val.fp); depth->mm = feet_to_mm(val);
break; break;
} }
break; break;
@ -292,16 +286,16 @@ static void extra_data_end(struct parser_state *state)
static void weight(const char *buffer, weight_t *weight, struct parser_state *state) static void weight(const char *buffer, weight_t *weight, struct parser_state *state)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
switch (state->xml_parsing_units.weight) { switch (state->xml_parsing_units.weight) {
case units::KG: case units::KG:
weight->grams = lrint(val.fp * 1000); weight->grams = lrint(val * 1000.0);
break; break;
case units::LBS: case units::LBS:
weight->grams = lbs_to_grams(val.fp); weight->grams = lbs_to_grams(val);
break; break;
} }
break; break;
@ -312,19 +306,19 @@ static void weight(const char *buffer, weight_t *weight, struct parser_state *st
static void temperature(const char *buffer, temperature_t *temperature, struct parser_state *state) static void temperature(const char *buffer, temperature_t *temperature, struct parser_state *state)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
switch (state->xml_parsing_units.temperature) { switch (state->xml_parsing_units.temperature) {
case units::KELVIN: case units::KELVIN:
temperature->mkelvin = lrint(val.fp * 1000); temperature->mkelvin = lrint(val * 1000.0);
break; break;
case units::CELSIUS: case units::CELSIUS:
temperature->mkelvin = C_to_mkelvin(val.fp); temperature->mkelvin = C_to_mkelvin(val);
break; break;
case units::FAHRENHEIT: case units::FAHRENHEIT:
temperature->mkelvin = F_to_mkelvin(val.fp); temperature->mkelvin = F_to_mkelvin(val);
break; break;
} }
break; break;
@ -396,7 +390,7 @@ static void percent(const char *buffer, fraction_t *fraction)
double val; double val;
const char *end; const char *end;
switch (parse_float(buffer, &val, &end)) { switch (parse_float(buffer, val, end)) {
case FLOATVAL: case FLOATVAL:
/* Turn fractions into percent unless explicit.. */ /* Turn fractions into percent unless explicit.. */
if (val <= 1.0) { if (val <= 1.0) {
@ -432,11 +426,11 @@ static void gasmix_nitrogen(const char *, struct gasmix *)
static void cylindersize(const char *buffer, volume_t *volume) static void cylindersize(const char *buffer, volume_t *volume)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
volume->mliter = lrint(val.fp * 1000); volume->mliter = lrint(val * 1000.0);
break; break;
default: default:
@ -608,16 +602,16 @@ static void get_notrip(const char *buffer, bool *notrip)
*/ */
static void fahrenheit(const char *buffer, temperature_t *temperature) static void fahrenheit(const char *buffer, temperature_t *temperature)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
if (nearly_equal(val.fp, 32.0)) if (nearly_equal(val, 32.0))
break; break;
if (val.fp < 32.0) if (val < 32.0)
temperature->mkelvin = C_to_mkelvin(val.fp); temperature->mkelvin = C_to_mkelvin(val);
else else
temperature->mkelvin = F_to_mkelvin(val.fp); temperature->mkelvin = F_to_mkelvin(val);
break; break;
default: default:
report_info("Crazy Diving Log temperature reading %s", buffer); report_info("Crazy Diving Log temperature reading %s", buffer);
@ -646,14 +640,14 @@ static void fahrenheit(const char *buffer, temperature_t *temperature)
*/ */
static void psi_or_bar(const char *buffer, pressure_t *pressure) static void psi_or_bar(const char *buffer, pressure_t *pressure)
{ {
union int_or_float val; double val;
switch (integer_or_float(buffer, &val)) { switch (parse_float(buffer, val)) {
case FLOATVAL: case FLOATVAL:
if (val.fp > 400) if (val > 400)
pressure->mbar = psi_to_mbar(val.fp); pressure->mbar = psi_to_mbar(val);
else else
pressure->mbar = lrint(val.fp * 1000); pressure->mbar = lrint(val * 1000);
break; break;
default: default:
report_info("Crazy Diving Log PSI reading %s", buffer); report_info("Crazy Diving Log PSI reading %s", buffer);