From 0ccae9f587d8151017f88609f3d4fb02b7cdda06 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Mon, 2 Jan 2023 11:11:23 -0700 Subject: [PATCH] modernize units (#969) * modernize units fmt_* returns a std::pair of the value and the units. use structured binding to unpack the pair. use scoped enumeration for the units system. * make units formatter a class. * cleanup unitsformatter instance. --- kml.cc | 43 +++++++++++--------------- kml.h | 2 ++ units.cc | 93 +++++++++++++++++++++++++++++--------------------------- units.h | 39 +++++++++++++++--------- 4 files changed, 92 insertions(+), 85 deletions(-) diff --git a/kml.cc b/kml.cc index 0b8536038..5fe7bea28 100644 --- a/kml.cc +++ b/kml.cc @@ -39,6 +39,7 @@ #include // for QList #include // for QString, QStringLiteral, operator+, operator!= #include // for QStringList +#include // for qMakeStringPrivate, QStringLit... #include // for QVector #include // for QXmlStreamAttributes #include // for ISODate @@ -53,7 +54,7 @@ #include "src/core/logging.h" // for Warning, Fatal #include "src/core/xmlstreamwriter.h" // for XmlStreamWriter #include "src/core/xmltag.h" // for xml_findfirst, xml_tag, fs_xml, xml_attribute, xml_findnext -#include "units.h" // for fmt_setunits, fmt_speed, fmt_altitude, fmt_distance, units_aviation, units_metric, units_nautical, units_statute +#include "units.h" // for UnitsFormatter, UnitsFormatter... #include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping @@ -357,18 +358,19 @@ void KmlFormat::wr_init(const QString& fname) u = tolower(opt_units[0]); } + unitsformatter = new UnitsFormatter(); switch (u) { case 's': - fmt_setunits(units_statute); + unitsformatter->setunits(UnitsFormatter::units_t::statute); break; case 'm': - fmt_setunits(units_metric); + unitsformatter->setunits(UnitsFormatter::units_t::metric); break; case 'n': - fmt_setunits(units_nautical); + unitsformatter->setunits(UnitsFormatter::units_t::nautical); break; case 'a': - fmt_setunits(units_aviation); + unitsformatter->setunits(UnitsFormatter::units_t::aviation); break; default: fatal("Units argument '%s' should be 's' for statute units, 'm' for metric, 'n' for nautical or 'a' for aviation.\n", opt_units); @@ -404,6 +406,8 @@ void KmlFormat::wr_deinit() oqfile->close(); delete oqfile; oqfile = nullptr; + delete unitsformatter; + unitsformatter = nullptr; if (!posnfilenametmp.isEmpty()) { // QFile::rename() can't replace an existing file, so do a QFile::remove() @@ -572,34 +576,28 @@ void KmlFormat::kml_output_trkdescription(const route_head* header, const comput if (!header->rte_desc.isEmpty()) { kml_td(hwriter, QStringLiteral("Description"), QStringLiteral(" %1 ").arg(header->rte_desc)); } - const char* distance_units; - double distance = fmt_distance(td->distance_meters, &distance_units); + auto [distance, distance_units] = unitsformatter->fmt_distance(td->distance_meters); kml_td(hwriter, QStringLiteral("Distance"), QStringLiteral(" %1 %2 ").arg(QString::number(distance, 'f', 1), distance_units)); if (td->min_alt) { - const char* min_alt_units; - double min_alt = fmt_altitude(*td->min_alt, &min_alt_units); + auto [min_alt, min_alt_units] = unitsformatter->fmt_altitude(*td->min_alt); kml_td(hwriter, QStringLiteral("Min Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(min_alt, 'f', 3), min_alt_units)); } if (td->max_alt) { - const char* max_alt_units; - double max_alt = fmt_altitude(*td->max_alt, &max_alt_units); + auto [max_alt, max_alt_units] = unitsformatter->fmt_altitude(*td->max_alt); kml_td(hwriter, QStringLiteral("Max Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(max_alt, 'f', 3), max_alt_units)); } if (td->min_spd) { - const char* spd_units; - double spd = fmt_speed(*td->min_spd, &spd_units); + auto [spd, spd_units] = unitsformatter->fmt_speed(*td->min_spd); kml_td(hwriter, QStringLiteral("Min Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units)); } if (td->max_spd) { - const char* spd_units; - double spd = fmt_speed(*td->max_spd, &spd_units); + auto [spd, spd_units] = unitsformatter->fmt_speed(*td->max_spd); kml_td(hwriter, QStringLiteral("Max Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units)); } if (td->max_spd && td->start.isValid() && td->end.isValid()) { double elapsed = td->start.msecsTo(td->end)/1000.0; if (elapsed > 0.0) { - const char* spd_units; - double spd = fmt_speed(td->distance_meters / elapsed, &spd_units); + auto [spd, spd_units] = unitsformatter->fmt_speed(td->distance_meters / elapsed); if (spd > 1.0) { kml_td(hwriter, QStringLiteral("Avg Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units)); } @@ -723,8 +721,6 @@ void KmlFormat::kml_output_positioning(bool tessellate) const /* Output something interesting when we can for route and trackpoints */ void KmlFormat::kml_output_description(const Waypoint* pt) const { - const char* alt_units; - if (!trackdata) { return; } @@ -732,8 +728,6 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const QString hstring; gpsbabel::XmlStreamWriter hwriter(&hstring); - double alt = fmt_altitude(pt->altitude, &alt_units); - writer->writeStartElement(QStringLiteral("description")); hwriter.writeCharacters(QStringLiteral("\n")); hwriter.writeStartElement(QStringLiteral("table")); @@ -742,6 +736,7 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const kml_td(hwriter, QStringLiteral("Latitude: %1 ").arg(QString::number(pt->latitude, 'f', precision))); if (kml_altitude_known(pt)) { + auto [alt, alt_units] = unitsformatter->fmt_altitude(pt->altitude); kml_td(hwriter, QStringLiteral("Altitude: %1 %2 ").arg(QString::number(alt, 'f', 3), alt_units)); } @@ -763,14 +758,12 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const } if WAYPT_HAS(pt, depth) { - const char* depth_units; - double depth = fmt_distance(pt->depth, &depth_units); + auto [depth, depth_units] = unitsformatter->fmt_distance(pt->depth); kml_td(hwriter, QStringLiteral("Depth: %1 %2 ").arg(QString::number(depth, 'f', 1), depth_units)); } if WAYPT_HAS(pt, speed) { - const char* spd_units; - double spd = fmt_speed(pt->speed, &spd_units); + auto [spd, spd_units] = unitsformatter->fmt_speed(pt->speed); kml_td(hwriter, QStringLiteral("Speed: %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units)); } diff --git a/kml.h b/kml.h index 177e5df73..4d9b92296 100644 --- a/kml.h +++ b/kml.h @@ -34,6 +34,7 @@ #include "src/core/datetime.h" // for DateTime #include "src/core/file.h" // for File #include "src/core/xmlstreamwriter.h" // for XmlStreamWriter +#include "units.h" // for UnitsFormatter #include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping @@ -226,6 +227,7 @@ class KmlFormat : public Format QList* gx_trk_times{nullptr}; QList>* gx_trk_coords{nullptr}; + UnitsFormatter* unitsformatter{nullptr}; gpsbabel::File* oqfile{nullptr}; gpsbabel::XmlStreamWriter* writer{nullptr}; diff --git a/units.cc b/units.cc index aafdf90a6..74a51abe5 100644 --- a/units.cc +++ b/units.cc @@ -22,50 +22,51 @@ #include "defs.h" #include "units.h" -static int units = units_statute; -int -fmt_setunits(fmt_units u) +void +UnitsFormatter::setunits(units_t u) { switch (u) { - case units_statute: - case units_metric: - case units_nautical: - case units_aviation: + case units_t::statute: + case units_t::metric: + case units_t::nautical: + case units_t::aviation: units = u; - return 0; + break; default: - return 1; + fatal("not done yet"); + break; } } -double -fmt_distance(const double distance_meters, const char** tag) +std::pair +UnitsFormatter::fmt_distance(const double distance_meters) const { double d; + const char* tag; switch (units) { - case units_statute: + case units_t::statute: d = METERS_TO_FEET(distance_meters); if (d < 5280) { - *tag = "ft"; + tag = "ft"; } else { d = METERS_TO_MILES(distance_meters); - *tag = "mi"; + tag = "mi"; } break; - case units_nautical: - case units_aviation: + case units_t::nautical: + case units_t::aviation: d = METERS_TO_NMILES(distance_meters); - *tag = "NM"; + tag = "NM"; break; - case units_metric: + case units_t::metric: d = distance_meters; if (d < 1000) { - *tag = "meters"; + tag = "meters"; } else { d = d / 1000.0; - *tag = "km"; + tag = "km"; } break; @@ -74,27 +75,28 @@ fmt_distance(const double distance_meters, const char** tag) break; } - return d; + return {d, tag}; } -double -fmt_altitude(const double distance_meters, const char** tag) +std::pair +UnitsFormatter::fmt_altitude(const double distance_meters) const { double d; + const char* tag; switch (units) { - case units_statute: - case units_aviation: + case units_t::statute: + case units_t::aviation: d = METERS_TO_FEET(distance_meters); - *tag = "ft"; + tag = "ft"; break; - case units_nautical: + case units_t::nautical: d = METERS_TO_NMILES(distance_meters); - *tag = "NM"; + tag = "NM"; break; - case units_metric: + case units_t::metric: d = distance_meters; - *tag = "meters"; + tag = "meters"; break; default: @@ -102,35 +104,36 @@ fmt_altitude(const double distance_meters, const char** tag) break; } - return d; + return {d, tag}; } -double -fmt_speed(const double distance_meters_sec, const char** tag) +std::pair +UnitsFormatter::fmt_speed(const double speed_meters_per_sec) const { double d; + const char* tag; switch (units) { - case units_statute: - d = METERS_TO_MILES(distance_meters_sec) * SECONDS_PER_HOUR ; - *tag = "mph"; + case units_t::statute: + d = METERS_TO_MILES(speed_meters_per_sec) * SECONDS_PER_HOUR ; + tag = "mph"; break; - case units_nautical: - case units_aviation: - d = METERS_TO_NMILES(distance_meters_sec) * SECONDS_PER_HOUR ; - *tag = "knts"; + case units_t::nautical: + case units_t::aviation: + d = METERS_TO_NMILES(speed_meters_per_sec) * SECONDS_PER_HOUR ; + tag = "knts"; break; - case units_metric: - d = distance_meters_sec * SECONDS_PER_HOUR; - *tag = "meters/hour"; + case units_t::metric: + d = speed_meters_per_sec * SECONDS_PER_HOUR; + tag = "meters/hour"; if (d > 1000.0) { d /= 1000.0; - *tag = "km/hour"; + tag = "km/hour"; } break; default: fatal("not done yet"); } - return d; + return {d, tag}; } diff --git a/units.h b/units.h index fec3ff673..61c72a9e7 100644 --- a/units.h +++ b/units.h @@ -23,25 +23,34 @@ #ifndef GPSBABEL_UNITS_H #define GPSBABEL_UNITS_H -/* - * From units.c - */ -enum fmt_units { - units_unknown = 0, - units_statute = 1, - units_metric = 2, - units_nautical =3, - units_aviation =4 -}; +#include // for pair + +#include // for QString -int fmt_setunits(fmt_units); -double fmt_distance(double, const char** tag); +class UnitsFormatter +{ +public: -double fmt_altitude(double, const char** tag); + /* Types */ -double fmt_speed(double, const char** tag); + enum class units_t { + statute, + metric, + nautical, + aviation + }; -#include "defs.h" + /* Member Functions */ + void setunits(units_t u); + std::pair fmt_distance(double distance_meters) const; + std::pair fmt_altitude(double distance_meters) const; + std::pair fmt_speed(double speed_meters_per_sec) const; + + /* Data Members */ + + units_t units{units_t::statute}; + +}; #endif //GPSBABEL_UNITS_H