From 25acbdf78c0f43a7c6d284736f5ca7249efe5a89 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Tue, 1 Mar 2022 06:40:32 -0700 Subject: [PATCH] Use PImpl idiom to hide Format and Filter headers from users of Vecs, FilterVecs. (#854) * use pimpl to hide vec implementation of formats. * use PIMPL for filter_vecs. * sort vecs and filter_vecs include files. * workaround memory leak issues with pimpl vecs, filter_vecs. with some compilers sanitize address and valgrind reported errors. The number of errors varied with compiler/platform. Valgrind and sanitize address found different errors as well. MacOS with clang 13 ran error free. Linux with gcc9 and clang 10 showed multiple errors. The errors detected were related to the destruction of the Format and Filter instances. * move ctors/dtors back to h files. * catch nuke_format up with vecs. --- filter_vecs.cc | 201 ++++++++-- filter_vecs.h | 198 ++-------- tools/nuke_format | 10 +- vecs.cc | 966 ++++++++++++++++++++++++++++++++++++++++++++-- vecs.h | 936 ++------------------------------------------ 5 files changed, 1174 insertions(+), 1137 deletions(-) diff --git a/filter_vecs.cc b/filter_vecs.cc index a8973e7dd..a83a04225 100644 --- a/filter_vecs.cc +++ b/filter_vecs.cc @@ -19,24 +19,179 @@ */ -#include // for QByteArray -#include // for QString -#include // for QStringList -#include // for QVector<>::iterator, QVector -#include // for CaseInsensitive -#include // for qPrintable - -#include // for sort -#include // for assert -#include // for printf - -#include "defs.h" #include "filter_vecs.h" -#include "filter.h" // for Filter -#include "gbversion.h" // for WEB_DOC_DIR -#include "inifile.h" // for inifile_readstr -#include "vecs.h" // for Vecs +#include // for QByteArray +#include // for QString +#include // for QStringList +#include // for QVector +#include // for CaseInsensitive +#include // for qPrintable + +#include // for sort +#include // for assert +#include // for printf + +#include "arcdist.h" // for ArcDistanceFilter +#include "bend.h" // for BendFilter +#include "defs.h" // for arglist_t, CSTR, xfree, ARGTYPE_HIDDEN, fatal, global_options, global_opts, ARGTYPE_REQUIRED +#include "discard.h" // for DiscardFilter +#include "duplicate.h" // for DuplicateFilter +#include "filter.h" // for Filter +#include "gbversion.h" // for WEB_DOC_DIR +#include "height.h" // for HeightFilter +#include "inifile.h" // for inifile_readstr +#include "interpolate.h" // for InterpolateFilter +#include "nukedata.h" // for NukeDataFilter +#include "polygon.h" // for PolygonFilter +#include "position.h" // for PositionFilter +#include "radius.h" // for RadiusFilter +#include "resample.h" // for ResampleFilter +#include "reverse_route.h" // for ReverseRouteFilter +#include "smplrout.h" // for SimplifyRouteFilter +#include "sort.h" // for SortFilter +#include "stackfilter.h" // for StackFilter +#include "swapdata.h" // for SwapDataFilter +#include "trackfilter.h" // for TrackFilter +#include "transform.h" // for TransformFilter +#include "validate.h" // for ValidateFilter +#include "vecs.h" // for Vecs + + +struct FilterVecs::Impl { + ArcDistanceFilter arcdist; + BendFilter bend; + DiscardFilter discard; + DuplicateFilter duplicate; + HeightFilter height; + InterpolateFilter interpolate; + NukeDataFilter nukedata; + PolygonFilter polygon; + PositionFilter position; + RadiusFilter radius; + ResampleFilter resample; + ReverseRouteFilter reverse_route; + SimplifyRouteFilter routesimple; + SortFilter sort; + StackFilter stackfilt; + SwapDataFilter swapdata; + TrackFilter trackfilter; + TransformFilter transform; + ValidateFilter validate; + + const QVector filter_vec_list = { +#if FILTERS_ENABLED + { + &arcdist, + "arc", + "Include Only Points Within Distance of Arc", + }, + { + &bend, + "bend", + "Add points before and after bends in routes" + }, + { + &discard, + "discard", + "Remove unreliable points with high hdop or vdop" + }, + { + &duplicate, + "duplicate", + "Remove Duplicates", + }, + { + &interpolate, + "interpolate", + "Interpolate between trackpoints" + }, + { + &nukedata, + "nuketypes", + "Remove all waypoints, tracks, or routes" + }, + { + &polygon, + "polygon", + "Include Only Points Inside Polygon", + }, + { + &position, + "position", + "Remove Points Within Distance", + }, + { + &radius, + "radius", + "Include Only Points Within Radius", + }, + { + &resample, + "resample", + "Resample Track", + }, + { + &routesimple, + "simplify", + "Simplify routes", + }, + { + &sort, + "sort", + "Rearrange waypoints, routes and/or tracks by resorting", + }, + { + &stackfilt, + "stack", + "Save and restore waypoint lists" + }, + { + &reverse_route, + "reverse", + "Reverse stops within routes", + }, + { + &trackfilter, + "track", + "Manipulate track lists" + }, + { + &transform, + "transform", + "Transform waypoints into a route, tracks into routes, ..." + }, + { + &height, + "height", + "Manipulate altitudes" + }, + { + &swapdata, + "swap", + "Swap latitude and longitude of all loaded points" + }, + { + &validate, + "validate", + "Validate internal data structures" + } +#elif defined (MINIMAL_FILTERS) + { + &trackfilter, + "track", + "Manipulate track lists" + } +#endif + }; +}; + +FilterVecs& FilterVecs::Instance() +{ + static Impl impl; + static FilterVecs instance(&impl); + return instance; +} Filter* FilterVecs::find_filter_vec(const QString& vecname) { @@ -46,7 +201,7 @@ Filter* FilterVecs::find_filter_vec(const QString& vecname) } const QString svecname = options.takeFirst(); - for (const auto& vec : filter_vec_list) { + for (const auto& vec : d_ptr_->filter_vec_list) { if (svecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } @@ -111,7 +266,7 @@ void FilterVecs::free_filter_vec(Filter* filter) void FilterVecs::init_filter_vecs() { - for (const auto& vec : filter_vec_list) { + for (const auto& vec : d_ptr_->filter_vec_list) { QVector* args = vec.vec->get_args(); if (args && !args->isEmpty()) { assert(args->isDetached()); @@ -124,7 +279,7 @@ void FilterVecs::init_filter_vecs() void FilterVecs::exit_filter_vecs() { - for (const auto& vec : filter_vec_list) { + for (const auto& vec : d_ptr_->filter_vec_list) { (vec.vec->exit)(); QVector* args = vec.vec->get_args(); if (args && !args->isEmpty()) { @@ -145,7 +300,7 @@ void FilterVecs::exit_filter_vecs() */ void FilterVecs::disp_filter_vecs() const { - for (const auto& vec : filter_vec_list) { + for (const auto& vec : d_ptr_->filter_vec_list) { printf(" %-20.20s %-50.50s\n", qPrintable(vec.name), qPrintable(vec.desc)); const QVector* args = vec.vec->get_args(); @@ -163,7 +318,7 @@ void FilterVecs::disp_filter_vecs() const void FilterVecs::disp_filter_vec(const QString& vecname) const { - for (const auto& vec : filter_vec_list) { + for (const auto& vec : d_ptr_->filter_vec_list) { if (vecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } @@ -220,7 +375,7 @@ void FilterVecs::disp_v1(const fl_vecs_t& vec) */ void FilterVecs::disp_filters(int version) const { - auto sorted_filter_vec_list = filter_vec_list; + auto sorted_filter_vec_list = d_ptr_->filter_vec_list; auto alpha = [](const fl_vecs_t& a, const fl_vecs_t& b)->bool { return QString::compare(a.desc, b.desc, Qt::CaseInsensitive) < 0; @@ -256,7 +411,7 @@ bool FilterVecs::validate_filters() const { bool ok = true; - for (const auto& vec : filter_vec_list) { + for (const auto& vec : d_ptr_->filter_vec_list) { ok = validate_filter_vec(vec) && ok; } diff --git a/filter_vecs.h b/filter_vecs.h index 5906d7781..91b250b34 100644 --- a/filter_vecs.h +++ b/filter_vecs.h @@ -21,197 +21,59 @@ #ifndef FILTER_VECS_H_INCLUDED_ #define FILTER_VECS_H_INCLUDED_ -#include // for QString -#include // for QVector<>::iterator, QVector +#include // for QString #include "defs.h" // for arglist_t -#include "arcdist.h" // for ArcDistanceFilter -#include "bend.h" // for BendFilter -#include "discard.h" // for DiscardFilter -#include "duplicate.h" // for DuplicateFilter #include "filter.h" // for Filter -#include "height.h" // for HeightFilter -#include "interpolate.h" // for InterpolateFilter -#include "nukedata.h" // for NukeDataFilter -#include "polygon.h" // for PolygonFilter -#include "position.h" // for PositionFilter -#include "radius.h" // for RadiusFilter -#include "resample.h" // for ResampleFilter -#include "reverse_route.h" // for ReverseRouteFilter -#include "smplrout.h" // for SimplifyRouteFilter -#include "sort.h" // for SortFilter -#include "stackfilter.h" // for StackFilter -#include "swapdata.h" // for SwapDataFilter -#include "trackfilter.h" // for TrackFilter -#include "transform.h" // for TransformFilter -#include "validate.h" // for ValidateFilter class FilterVecs { // Meyers Singleton public: - static FilterVecs& Instance() - { - static FilterVecs instance; - return instance; - } + /* Special Member Functions */ + + static FilterVecs& Instance(); FilterVecs(const FilterVecs&) = delete; FilterVecs& operator= (const FilterVecs&) = delete; FilterVecs(FilterVecs&&) = delete; FilterVecs& operator=(FilterVecs&&) = delete; -private: - FilterVecs() = default; - ~FilterVecs() = default; + /* Member Functions */ + + Filter* find_filter_vec(const QString& vecname); + static void free_filter_vec(Filter* filter); + void init_filter_vecs(); + void exit_filter_vecs(); + void disp_filter_vecs() const; + void disp_filter_vec(const QString& vecname) const; + void disp_filters(int version) const; + bool validate_filters() const; private: + /* Types */ + + struct Impl; // Not defined here + struct fl_vecs_t { Filter* vec; QString name; QString desc; }; -public: -Filter* find_filter_vec(const QString& vecname); -static void free_filter_vec(Filter* filter); -void init_filter_vecs(); -void exit_filter_vecs(); -void disp_filter_vecs() const; -void disp_filter_vec(const QString& vecname) const; -void disp_filters(int version) const; -bool validate_filters() const; + /* Special Member Functions */ -private: -static void disp_help_url(const fl_vecs_t& vec, const arglist_t* arg); -static void disp_v1(const fl_vecs_t& vec); -static bool validate_filter_vec(const fl_vecs_t& vec); + explicit FilterVecs(Impl* i) : d_ptr_(i) {} + ~FilterVecs() = default; -private: - ArcDistanceFilter arcdist; - BendFilter bend; - DiscardFilter discard; - DuplicateFilter duplicate; - HeightFilter height; - InterpolateFilter interpolate; - NukeDataFilter nukedata; - PolygonFilter polygon; - PositionFilter position; - RadiusFilter radius; - ResampleFilter resample; - ReverseRouteFilter reverse_route; - SimplifyRouteFilter routesimple; - SortFilter sort; - StackFilter stackfilt; - SwapDataFilter swapdata; - TrackFilter trackfilter; - TransformFilter transform; - ValidateFilter validate; - - const QVector filter_vec_list = { -#if FILTERS_ENABLED - { - &arcdist, - "arc", - "Include Only Points Within Distance of Arc", - }, - { - &bend, - "bend", - "Add points before and after bends in routes" - }, - { - &discard, - "discard", - "Remove unreliable points with high hdop or vdop" - }, - { - &duplicate, - "duplicate", - "Remove Duplicates", - }, - { - &interpolate, - "interpolate", - "Interpolate between trackpoints" - }, - { - &nukedata, - "nuketypes", - "Remove all waypoints, tracks, or routes" - }, - { - &polygon, - "polygon", - "Include Only Points Inside Polygon", - }, - { - &position, - "position", - "Remove Points Within Distance", - }, - { - &radius, - "radius", - "Include Only Points Within Radius", - }, - { - &resample, - "resample", - "Resample Track", - }, - { - &routesimple, - "simplify", - "Simplify routes", - }, - { - &sort, - "sort", - "Rearrange waypoints, routes and/or tracks by resorting", - }, - { - &stackfilt, - "stack", - "Save and restore waypoint lists" - }, - { - &reverse_route, - "reverse", - "Reverse stops within routes", - }, - { - &trackfilter, - "track", - "Manipulate track lists" - }, - { - &transform, - "transform", - "Transform waypoints into a route, tracks into routes, ..." - }, - { - &height, - "height", - "Manipulate altitudes" - }, - { - &swapdata, - "swap", - "Swap latitude and longitude of all loaded points" - }, - { - &validate, - "validate", - "Validate internal data structures" - } -#elif defined (MINIMAL_FILTERS) - { - &trackfilter, - "track", - "Manipulate track lists" - } -#endif - }; + /* Member Functions */ + + static void disp_help_url(const fl_vecs_t& vec, const arglist_t* arg); + static void disp_v1(const fl_vecs_t& vec); + static bool validate_filter_vec(const fl_vecs_t& vec); + + /* Data Members */ + + Impl* d_ptr_; // Opaque pointer }; #endif // FILTER_VECS_H_INCLUDED_ diff --git a/tools/nuke_format b/tools/nuke_format index e0d4c952a..a33fe2f20 100755 --- a/tools/nuke_format +++ b/tools/nuke_format @@ -33,12 +33,12 @@ remove_line $1.h GPSBabel.pro remove_manually $1 reference/help.txt remove_manually $1 reference/format3.txt -# Take out the boilerplate entries in vecs.h ... -remove_line_containing extern.*$1 vecs.h -remove_line_containing Format.*$1 vecs.h -remove_line_containing include.*$1 vecs.h +# Take out the boilerplate entries in vecs.cc ... +remove_line_containing extern.*$1 vecs.cc +remove_line_containing Format.*$1 vecs.cc +remove_line_containing include.*$1 vecs.cc # ... then let a human nerd snip the actual table entry away. -remove_manually $1 vecs.h +remove_manually $1 vecs.cc remove_line_containing $1 reference/format0.txt remove_line_containing $1 reference/format1.txt diff --git a/vecs.cc b/vecs.cc index 438f534ce..62e34d480 100644 --- a/vecs.cc +++ b/vecs.cc @@ -19,33 +19,925 @@ */ -#include // for QByteArray -#include // for QDir, QDir::Files, QDir::Name -#include // for QFileInfo -#include // for QFileInfoList -#include // for QString -#include // for QStringList -#include // for QVector<>::iterator, QVector -#include // for CaseInsensitive -#include // for qPrintable - -#include // for sort -#include // for assert -#include // for isdigit -#include // for printf, putchar, sscanf, size_t - -#include "defs.h" #include "vecs.h" -#include "format.h" -#include "gbversion.h" // for WEB_DOC_DIR -#include "inifile.h" // for inifile_readstr -#include "legacyformat.h" -#include "src/core/logging.h" // for Warning, FatalMsg -#include "xcsv.h" // for xcsv_setup_internal_style, XcsvStyle, xcsv_read_style +#include // for QByteArray +#include // for QDebug +#include // for QDir, QDir::Files, QDir::Name +#include // for QFileInfo +#include // for QFileInfoList +#include // for QString +#include // for QStringList +#include // for QVector +#include // for CaseInsensitive +#include // for qPrintable, qAsConst + +#include // for sort +#include // for assert +#include // for isdigit +#include // for printf, putchar, sscanf + +#include "defs.h" // for arglist_t, ff_vecs_t, ff_cap, fatal, CSTR, ARGTYPE_TYPEMASK, case_ignore_strcmp, global_options, global_opts, warning, xfree, ARGTYPE_BOOL, ff_cap_read, ff_cap_write, ARGTYPE_HIDDEN, ff_type_internal, xstrdup, ARGTYPE_INT, ARGTYPE_REQUIRED, ARGTYPE_FLOAT +#include "dg-100.h" // for Dg100FileFormat, Dg100SerialFormat, Dg200FileFormat, Dg200SerialFormat +#include "energympro.h" // for EnergymproFormat +#include "exif.h" // for ExifFormat +#include "f90g_track.h" // for F90gTrackFormat +#include "format.h" // for Format +#include "garmin_fit.h" // for GarminFitFormat +#include "garmin_gpi.h" // for GarminGPIFormat +#include "gbversion.h" // for WEB_DOC_DIR +#include "gdb.h" // for GdbFormat +#include "geojson.h" // for GeoJsonFormat +#include "ggv_bin.h" // for GgvBinFormat +#include "globalsat_sport.h" // for GlobalsatSportFormat +#include "gpx.h" // for GpxFormat +#include "gtrnctr.h" // for GtrnctrFormat +#include "html.h" // for HtmlFormat +#include "humminbird.h" // for HumminbirdFormat, HumminbirdHTFormat +#include "inifile.h" // for inifile_readstr +#include "kml.h" // for KmlFormat +#include "legacyformat.h" // for LegacyFormat +#include "lowranceusr.h" // for LowranceusrFormat +#include "mapbar_track.h" // for MapbarTrackFormat +#include "mapfactor.h" // for MapfactorFormat +#include "mynav.h" // for MyNavFormat +#include "nmea.h" // for NmeaFormat +#include "osm.h" // for OsmFormat +#include "qstarz_bl_1000.h" // for QstarzBL1000Format +#include "random.h" // for RandomFormat +#include "shape.h" // for ShapeFormat +#include "skytraq.h" // for MinihomerFormat, SkytraqFormat, SkytraqfileFormat +#include "src/core/logging.h" // for Warning, FatalMsg +#include "subrip.h" // for SubripFormat +#include "tef_xml.h" // for TefXMLFormat +#include "teletype.h" // for TeletypeFormat +#include "text.h" // for TextFormat +#include "unicsv.h" // for UnicsvFormat +#include "wintec_tes.h" // for WintecTesFormat +#include "xcsv.h" // for XcsvStyle, XcsvFormat + + +extern ff_vecs_t geo_vecs; +extern ff_vecs_t mag_svecs; +extern ff_vecs_t mag_fvecs; +extern ff_vecs_t magX_fvecs; +extern ff_vecs_t garmin_vecs; +extern ff_vecs_t ozi_vecs; +#if MAXIMAL_ENABLED +extern ff_vecs_t holux_vecs; +extern ff_vecs_t tpg_vecs; +extern ff_vecs_t tpo2_vecs; +extern ff_vecs_t tpo3_vecs; +extern ff_vecs_t easygps_vecs; +extern ff_vecs_t saroute_vecs; +extern ff_vecs_t gpl_vecs; +extern ff_vecs_t igc_vecs; +extern ff_vecs_t brauniger_iq_vecs; +extern ff_vecs_t mtk_vecs; +extern ff_vecs_t mtk_fvecs; +extern ff_vecs_t mtk_m241_vecs; +extern ff_vecs_t mtk_m241_fvecs; +extern ff_vecs_t mtk_locus_vecs; +#endif // MAXIMAL_ENABLED +extern ff_vecs_t wbt_svecs; +#if MAXIMAL_ENABLED +extern ff_vecs_t wbt_fvecs; +//extern ff_vecs_t wbt_fvecs; +extern ff_vecs_t hiketech_vecs; +extern ff_vecs_t glogbook_vecs; +extern ff_vecs_t vcf_vecs; +extern ff_vecs_t google_dir_vecs; +extern ff_vecs_t tomtom_vecs; +extern ff_vecs_t bcr_vecs; +extern ff_vecs_t ignr_vecs; +extern ff_vecs_t gtm_vecs; +extern ff_vecs_t gpssim_vecs; +#if CSVFMTS_ENABLED +extern ff_vecs_t garmin_txt_vecs; +#endif // CSVFMTS_ENABLED +extern ff_vecs_t dmtlog_vecs; +extern ff_vecs_t raymarine_vecs; +extern ff_vecs_t ggv_log_vecs; +extern ff_vecs_t lmx_vecs; +extern ff_vecs_t xol_vecs; +extern ff_vecs_t navilink_vecs; +extern ff_vecs_t ik3d_vecs; +extern ff_vecs_t destinator_poi_vecs; +extern ff_vecs_t destinator_itn_vecs; +extern ff_vecs_t destinator_trl_vecs; +extern ff_vecs_t igo8_vecs; +extern ff_vecs_t mapasia_tr7_vecs; +extern ff_vecs_t gnav_trl_vecs; +extern ff_vecs_t navitel_trk_vecs; +extern ff_vecs_t ggv_ovl_vecs; +#if CSVFMTS_ENABLED +#endif // CSVFMTS_ENABLED +extern ff_vecs_t itracku_vecs; +extern ff_vecs_t itracku_fvecs; +extern ff_vecs_t sbp_vecs; +extern ff_vecs_t sbn_vecs; +extern ff_vecs_t mmo_vecs; +extern ff_vecs_t v900_vecs; +extern ff_vecs_t enigma_vecs; +extern ff_vecs_t format_garmin_xt_vecs; +#endif // MAXIMAL_ENABLED #define MYNAME "vecs" +struct Vecs::Impl +{ + /* + * Having these LegacyFormat instances be non-static data members + * prevents the static initialization order fiasco because + * the static vec that is used to construct a legacy format + * instance is guaranteed to have already constructed when an instance + * of this class is constructed. + */ +#if CSVFMTS_ENABLED + XcsvFormat xcsv_fmt; +#endif // CSVFMTS_ENABLED + LegacyFormat geo_fmt {geo_vecs}; + GpxFormat gpx_fmt; + LegacyFormat mag_sfmt {mag_svecs}; + LegacyFormat mag_ffmt {mag_fvecs}; + LegacyFormat magX_ffmt {magX_fvecs}; + LegacyFormat garmin_fmt {garmin_vecs}; + GdbFormat gdb_fmt; + NmeaFormat nmea_fmt; + LegacyFormat ozi_fmt {ozi_vecs}; + KmlFormat kml_fmt; +#if MAXIMAL_ENABLED + LowranceusrFormat lowranceusr_fmt; + LegacyFormat holux_fmt {holux_vecs}; + LegacyFormat tpg_fmt {tpg_vecs}; + LegacyFormat tpo2_fmt {tpo2_vecs}; + LegacyFormat tpo3_fmt {tpo3_vecs}; + LegacyFormat easygps_fmt {easygps_vecs}; + LegacyFormat saroute_fmt {saroute_vecs}; +#if SHAPELIB_ENABLED + ShapeFormat shape_fmt; +#endif + LegacyFormat gpl_fmt {gpl_vecs}; + TextFormat text_fmt; + HtmlFormat html_fmt; + LegacyFormat igc_fmt {igc_vecs}; + LegacyFormat brauniger_iq_fmt {brauniger_iq_vecs}; + LegacyFormat mtk_fmt {mtk_vecs}; + LegacyFormat mtk_ffmt {mtk_fvecs}; + LegacyFormat mtk_m241_fmt {mtk_m241_vecs}; + LegacyFormat mtk_m241_ffmt {mtk_m241_fvecs}; + LegacyFormat mtk_locus_fmt {mtk_locus_vecs}; +#endif // MAXIMAL_ENABLED + LegacyFormat wbt_sfmt {wbt_svecs}; +#if MAXIMAL_ENABLED + LegacyFormat wbt_ffmt {wbt_fvecs}; +//LegacyFormat wbt_ffmt {wbt_fvecs}; + LegacyFormat hiketech_fmt {hiketech_vecs}; + LegacyFormat glogbook_fmt {glogbook_vecs}; + LegacyFormat vcf_fmt {vcf_vecs}; + LegacyFormat google_dir_fmt {google_dir_vecs}; + LegacyFormat tomtom_fmt {tomtom_vecs}; + TefXMLFormat tef_xml_fmt; + LegacyFormat bcr_fmt {bcr_vecs}; + LegacyFormat ignr_fmt {ignr_vecs}; + UnicsvFormat unicsv_fmt; + LegacyFormat gtm_fmt {gtm_vecs}; + LegacyFormat gpssim_fmt {gpssim_vecs}; +#if CSVFMTS_ENABLED + LegacyFormat garmin_txt_fmt {garmin_txt_vecs}; +#endif // CSVFMTS_ENABLED + GtrnctrFormat gtc_fmt; + LegacyFormat dmtlog_fmt {dmtlog_vecs}; + LegacyFormat raymarine_fmt {raymarine_vecs}; + LegacyFormat ggv_log_fmt {ggv_log_vecs}; + GarminGPIFormat garmin_gpi_fmt; + LegacyFormat lmx_fmt {lmx_vecs}; + RandomFormat random_fmt; + LegacyFormat xol_fmt {xol_vecs}; + Dg100SerialFormat dg100_fmt; + Dg100FileFormat dg100_ffmt; + Dg200SerialFormat dg200_fmt; + Dg200FileFormat dg200_ffmt; + LegacyFormat navilink_fmt {navilink_vecs}; + LegacyFormat ik3d_fmt {ik3d_vecs}; + OsmFormat osm_fmt; + LegacyFormat destinator_poi_fmt {destinator_poi_vecs}; + LegacyFormat destinator_itn_fmt {destinator_itn_vecs}; + LegacyFormat destinator_trl_fmt {destinator_trl_vecs}; + ExifFormat exif_fmt; + LegacyFormat igo8_fmt {igo8_vecs}; + HumminbirdFormat humminbird_fmt; + HumminbirdHTFormat humminbird_ht_fmt; + LegacyFormat mapasia_tr7_fmt {mapasia_tr7_vecs}; + LegacyFormat gnav_trl_fmt {gnav_trl_vecs}; + LegacyFormat navitel_trk_fmt {navitel_trk_vecs}; + LegacyFormat ggv_ovl_fmt {ggv_ovl_vecs}; + LegacyFormat itracku_fmt {itracku_vecs}; + LegacyFormat itracku_ffmt {itracku_fvecs}; + LegacyFormat sbp_fmt {sbp_vecs}; + LegacyFormat sbn_fmt {sbn_vecs}; + LegacyFormat mmo_fmt {mmo_vecs}; + LegacyFormat v900_fmt {v900_vecs}; + LegacyFormat enigma_fmt {enigma_vecs}; + SkytraqFormat skytraq_fmt; + TeletypeFormat teletype_fmt; + SkytraqfileFormat skytraq_ffmt; + MinihomerFormat miniHomer_fmt; + WintecTesFormat wintec_tes_fmt; + SubripFormat subrip_fmt; + LegacyFormat format_garmin_xt_fmt {format_garmin_xt_vecs}; + GarminFitFormat format_fit_fmt; + MapbarTrackFormat mapbar_track_fmt; + F90gTrackFormat f90g_track_fmt; + MapfactorFormat mapfactor_fmt; + EnergymproFormat energympro_fmt; + MyNavFormat mynav_fmt; + GeoJsonFormat geojson_fmt; + GgvBinFormat ggv_bin_fmt; + GlobalsatSportFormat globalsat_sport_fmt; + QstarzBL1000Format qstarz_bl_1000_fmt; +#endif // MAXIMAL_ENABLED + + const QVector vec_list { +#if CSVFMTS_ENABLED + /* XCSV must be the first entry in this table. */ + { + &xcsv_fmt, + "xcsv", + "? Character Separated Values", + nullptr, + nullptr, + }, +#endif + { + &geo_fmt, + "geo", + "Geocaching.com .loc", + "loc", + nullptr, + }, + { + &gpx_fmt, + "gpx", + "GPX XML", + "gpx", + nullptr, + }, + { + &mag_sfmt, + "magellan", + "Magellan serial protocol", + nullptr, + nullptr, + }, + { + &mag_ffmt, + "magellan", + "Magellan SD files (as for Meridian)", + nullptr, + nullptr, + }, + { + &magX_ffmt, + "magellanx", + "Magellan SD files (as for eXplorist)", + "upt", + nullptr, + }, + { + &garmin_fmt, + "garmin", + "Garmin serial/USB protocol", + nullptr, + nullptr, + }, + { + &gdb_fmt, + "gdb", + "Garmin MapSource - gdb", + "gdb", + nullptr, + }, + { + &nmea_fmt, + "nmea", + "NMEA 0183 sentences", + nullptr, + nullptr, + }, + { + &ozi_fmt, + "ozi", + "OziExplorer", + nullptr, + nullptr, + }, + { + &kml_fmt, + "kml", + "Google Earth (Keyhole) Markup Language", + "kml", + nullptr, + }, +#if MAXIMAL_ENABLED + { + &lowranceusr_fmt, + "lowranceusr", + "Lowrance USR", + "usr", + nullptr, + }, + { + &holux_fmt, + "holux", + "Holux (gm-100) .wpo Format", + "wpo", + nullptr, + }, + { + &tpg_fmt, + "tpg", + "National Geographic Topo .tpg (waypoints)", + "tpg", + nullptr, + }, + { + &tpo2_fmt, + "tpo2", + "National Geographic Topo 2.x .tpo", + "tpo", + nullptr, + }, + { + &tpo3_fmt, + "tpo3", + "National Geographic Topo 3.x/4.x .tpo", + "tpo", + nullptr, + }, + { + &easygps_fmt, + "easygps", + "EasyGPS binary format", + "loc", + nullptr, + }, + { + &saroute_fmt, + "saroute", + "DeLorme Street Atlas Route", + "anr", + nullptr, + }, +#if SHAPELIB_ENABLED + { + &shape_fmt, + "shape", + "ESRI shapefile", + "shp", + nullptr, + }, +#endif + { + &gpl_fmt, + "gpl", + "DeLorme GPL", + "gpl", + nullptr, + }, + { + &text_fmt, + "text", + "Textual Output", + "txt", + nullptr, + }, + { + &html_fmt, + "html", + "HTML Output", + "html", + nullptr, + }, + { + &igc_fmt, + "igc", + "FAI/IGC Flight Recorder Data Format", + nullptr, + nullptr, + }, + { + &brauniger_iq_fmt, + "baroiq", + "Brauniger IQ Series Barograph Download", + nullptr, + nullptr, + }, + { + &mtk_fmt, + "mtk", + "MTK Logger (iBlue 747,Qstarz BT-1000,...) download", + nullptr, + nullptr, + }, + { + &mtk_ffmt, + "mtk-bin", + "MTK Logger (iBlue 747,...) Binary File Format", + "bin", + nullptr, + }, + { + &mtk_m241_fmt, + "m241", + "Holux M-241 (MTK based) download", + nullptr, + nullptr, + }, + { + &mtk_m241_ffmt, + "m241-bin", + "Holux M-241 (MTK based) Binary File Format", + "bin", + nullptr, + }, + { + &mtk_locus_fmt, + "mtk_locus", + "MediaTek Locus", + nullptr, + nullptr, + }, +#endif // MAXIMAL_ENABLED + { + &wbt_sfmt, + "wbt", + "Wintec WBT-100/200 GPS Download", + nullptr, + nullptr, + }, +#if MAXIMAL_ENABLED + { + &wbt_ffmt, + "wbt-bin", + "Wintec WBT-100/200 Binary File Format", + "bin", + nullptr, + }, + { + &wbt_ffmt, + "wbt-tk1", + "Wintec WBT-201/G-Rays 2 Binary File Format", + "tk1", + nullptr, + }, + { + &hiketech_fmt, + "hiketech", + "HikeTech", + "gps", + nullptr, + }, + { + &glogbook_fmt, + "glogbook", + "Garmin Logbook XML", + "xml", + nullptr, + }, + { + &vcf_fmt, + "vcard", + "Vcard Output (for iPod)", + "vcf", + nullptr, + }, + { + &google_dir_fmt, + "googledir", + "Google Directions XML", + "xml", + nullptr, + }, + { + &tomtom_fmt, + "tomtom", + "TomTom POI file (.ov2)", + "ov2", + nullptr, + }, + { + &tef_xml_fmt, + "tef", + "Map&Guide 'TourExchangeFormat' XML", + "xml", + nullptr, + }, + { + &bcr_fmt, + "bcr", + "Motorrad Routenplaner (Map&Guide) .bcr files", + "bcr", + nullptr, + }, + { + &ignr_fmt, + "ignrando", + "IGN Rando track files", + "rdn", + nullptr, + }, + { + &unicsv_fmt, + "unicsv", + "Universal csv with field structure in first line", + nullptr, + nullptr, + }, + { + >m_fmt, + "gtm", + "GPS TrackMaker", + "gtm", + nullptr, + }, + { + &gpssim_fmt, + "gpssim", + "Franson GPSGate Simulation", + "gpssim", + nullptr, + }, +#if CSVFMTS_ENABLED + { + &garmin_txt_fmt, + "garmin_txt", + "Garmin MapSource - txt (tab delimited)", + "txt", + nullptr, + }, +#endif // CSVFMTS_ENABLED + { + >c_fmt, + "gtrnctr", + "Garmin Training Center (.tcx/.crs/.hst/.xml)", + "tcx/crs/hst/xml", + nullptr, + }, + { + &dmtlog_fmt, + "dmtlog", + "TrackLogs digital mapping (.trl)", + "trl", + nullptr, + }, + { + &raymarine_fmt, + "raymarine", + "Raymarine Waypoint File (.rwf)", + "rwf", + nullptr, + }, + { + &ggv_log_fmt, + "ggv_log", + "Geogrid-Viewer tracklogs (.log)", + "log", + nullptr, + }, + { + &garmin_gpi_fmt, + "garmin_gpi", + "Garmin Points of Interest (.gpi)", + "gpi", + nullptr, + }, + { + &lmx_fmt, + "lmx", + "Nokia Landmark Exchange", + nullptr, + nullptr, + }, + { + &random_fmt, + "random", + "Internal GPS data generator", + nullptr, + nullptr, + }, + { + &xol_fmt, + "xol", + "Swiss Map 25/50/100 (.xol)", + "xol", + nullptr, + }, + { + &dg100_fmt, + "dg-100", + "GlobalSat DG-100/BT-335 Download", + nullptr, + nullptr, + }, + { + &dg100_ffmt, + "dg-100-bin", + "GlobalSat DG-100/BT-335 Binary File", + nullptr, + nullptr, + }, + { + &dg200_fmt, + "dg-200", + "GlobalSat DG-200 Download", + nullptr, + nullptr, + }, + { + &dg200_ffmt, + "dg-200-bin", + "GlobalSat DG-200 Binary File", + nullptr, + nullptr, + }, + { + &navilink_fmt, + "navilink", + "NaviGPS GT-11/BGT-11 Download", + nullptr, + nullptr, + }, + { + &ik3d_fmt, + "ik3d", + "MagicMaps IK3D project file (.ikt)", + "ikt", + nullptr, + }, + { + &osm_fmt, + "osm", + "OpenStreetMap data files", + "osm", + nullptr, + }, + { + &destinator_poi_fmt, + "destinator_poi", + "Destinator Points of Interest (.dat)", + "dat", + nullptr, + }, + { + &destinator_itn_fmt, + "destinator_itn", + "Destinator Itineraries (.dat)", + "dat", + nullptr, + }, + { + &destinator_trl_fmt, + "destinator_trl", + "Destinator TrackLogs (.dat)", + "dat", + nullptr, + }, + { + &exif_fmt, + "exif", + "Embedded Exif-GPS data (.jpg)", + "jpg", + nullptr, + }, + { + &igo8_fmt, + "igo8", + "IGO8 .trk", + "trk", + nullptr, + }, + { + &humminbird_fmt, + "humminbird", + "Humminbird waypoints and routes (.hwr)", + "hwr", + nullptr, + }, + { + &humminbird_ht_fmt, + "humminbird_ht", + "Humminbird tracks (.ht)", + "ht", + nullptr, + }, + { + &mapasia_tr7_fmt, + "mapasia_tr7", + "MapAsia track file (.tr7)", + "tr7", + nullptr, + }, + { + &gnav_trl_fmt, + "gnav_trl", + "Google Navigator Tracklines (.trl)", + "trl", + nullptr, + }, + { + &navitel_trk_fmt, + "navitel_trk", + "Navitel binary track (.bin)", + "bin", + nullptr, + }, + { + &ggv_ovl_fmt, + "ggv_ovl", + "Geogrid-Viewer ascii overlay file (.ovl)", + "ovl", + nullptr, + }, + { + &itracku_fmt, + "itracku", + "XAiOX iTrackU Logger", + nullptr, + nullptr, + }, + { + &itracku_ffmt, + "itracku-bin", + "XAiOX iTrackU Logger Binary File Format", + "bin", + nullptr, + }, + { + &sbp_fmt, + "sbp", + "NaviGPS GT-31/BGT-31 datalogger (.sbp)", + "sbp", + nullptr, + }, + { + &sbn_fmt, + "sbn", + "NaviGPS GT-31/BGT-31 SiRF binary logfile (.sbn)", + "sbn", + nullptr, + }, + { + &mmo_fmt, + "mmo", + "Memory-Map Navigator overlay files (.mmo)", + "mmo", + nullptr, + }, + { + &v900_fmt, + "v900", + "Columbus/Visiontac V900 files (.csv)", + nullptr, + nullptr, + }, + { + &enigma_fmt, + "enigma", + "Enigma binary waypoint file (.ert)", + "ert", + nullptr, + }, + { + &skytraq_fmt, + "skytraq", + "SkyTraq Venus based loggers (download)", + nullptr, + nullptr, + }, + { + &teletype_fmt, + "teletype", + "Teletype [ Get Jonathon Johnson to describe", + nullptr, + nullptr, + }, + { + &skytraq_ffmt, + "skytraq-bin", + "SkyTraq Venus based loggers Binary File Format", + "bin", + nullptr, + }, + { + &miniHomer_fmt, + "miniHomer", + "MiniHomer, a skyTraq Venus 6 based logger (download tracks, waypoints and get/set POI)", + nullptr, + nullptr, + }, + { + &wintec_tes_fmt, + "wintec_tes", + "Wintec TES file", + "tes", + nullptr, + }, + { + &subrip_fmt, + "subrip", + "SubRip subtitles for video mapping (.srt)", + "srt", + nullptr, + }, + { + &format_garmin_xt_fmt, + "garmin_xt", + "Mobile Garmin XT Track files", + nullptr, + nullptr, + }, + { + &format_fit_fmt, + "garmin_fit", + "Flexible and Interoperable Data Transfer (FIT) Activity file", + "fit", + nullptr, + }, + { + &mapbar_track_fmt, + "mapbar", + "Mapbar (China) navigation track for Sonim Xp3300", + "trk", + nullptr, + }, + { + &f90g_track_fmt, + "f90g", + "F90G Automobile DVR GPS log file", + "map", + nullptr, + }, + { + &mapfactor_fmt, + "mapfactor", + "Mapfactor Navigator", + "xml", + nullptr, + }, + { + &energympro_fmt, + "energympro", + "Energympro GPS training watch", + "cpo", + nullptr, + }, + { + &mynav_fmt, + "mynav", + "MyNav TRC format", + "trc", + nullptr, + }, + { + &geojson_fmt, + "geojson", + "GeoJson", + "json", + nullptr, + }, + { + &ggv_bin_fmt, + "ggv_bin", + "Geogrid-Viewer binary overlay file (.ovl)", + "ovl", + nullptr, + }, + { + &globalsat_sport_fmt, + "globalsat", + "GlobalSat GH625XT GPS training watch", + nullptr, + nullptr, + }, + { + &qstarz_bl_1000_fmt, + "qstarz_bl-1000", + "Qstarz BL-1000", + nullptr, + nullptr, + } +#endif // MAXIMAL_ENABLED + }; +}; + +Vecs& Vecs::Instance() +{ + static Impl impl; + static Vecs instance(&impl); + return instance; +} + /* * When we modify an element on the list we need to be careful * that we are not modifying a Qt COW copy. @@ -65,7 +957,7 @@ void Vecs::init_vecs() { - for (const auto& vec : vec_list) { + for (const auto& vec : d_ptr_->vec_list) { QVector* args = vec.vec->get_args(); if (args && !args->isEmpty()) { assert(args->isDetached()); @@ -87,7 +979,7 @@ int Vecs::is_integer(const char* c) void Vecs::exit_vecs() { - for (const auto& vec : vec_list) { + for (const auto& vec : d_ptr_->vec_list) { (vec.vec->exit)(); QVector* args = vec.vec->get_args(); if (args && !args->isEmpty()) { @@ -236,7 +1128,7 @@ Format* Vecs::find_vec(const QString& vecname) } const QString svecname = options.takeFirst(); - for (const auto& vec : vec_list) { + for (const auto& vec : d_ptr_->vec_list) { if (svecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } @@ -277,7 +1169,7 @@ Format* Vecs::find_vec(const QString& vecname) * format that utilized an internal style file, then we need to let * xcsv know the internal style file is no longer in play. */ - xcsv_fmt.xcsv_setup_internal_style(nullptr); + d_ptr_->xcsv_fmt.xcsv_setup_internal_style(nullptr); #endif // CSVFMTS_ENABLED vec.vec->set_name(vec.name); /* needed for session information */ vec.vec->set_argstring(vecname); /* needed for positional parameters */ @@ -294,7 +1186,7 @@ Format* Vecs::find_vec(const QString& vecname) continue; } - QVector* xcsv_args = vec_list.at(0).vec->get_args(); + QVector* xcsv_args = d_ptr_->vec_list.at(0).vec->get_args(); validate_options(options, xcsv_args, svec.name); @@ -324,12 +1216,12 @@ Format* Vecs::find_vec(const QString& vecname) disp_vec_options(svec.name, xcsv_args); } #if CSVFMTS_ENABLED - xcsv_fmt.xcsv_setup_internal_style(svec.style_filename); + d_ptr_->xcsv_fmt.xcsv_setup_internal_style(svec.style_filename); #endif // CSVFMTS_ENABLED - vec_list[0].vec->set_name(svec.name); /* needed for session information */ - vec_list[0].vec->set_argstring(vecname); /* needed for positional parameters */ - return vec_list[0].vec; + d_ptr_->vec_list[0].vec->set_name(svec.name); /* needed for session information */ + d_ptr_->vec_list[0].vec->set_argstring(vecname); /* needed for positional parameters */ + return d_ptr_->vec_list[0].vec; } /* @@ -402,10 +1294,10 @@ QVector Vecs::create_style_vec() QVector Vecs::sort_and_unify_vecs() const { QVector svp; - svp.reserve(vec_list.size() + style_list.size()); + svp.reserve(d_ptr_->vec_list.size() + style_list.size()); /* Gather relevant information for normal formats. */ - for (const auto& vec : vec_list) { + for (const auto& vec : d_ptr_->vec_list) { vecinfo_t info; info.name = vec.name; info.desc = vec.desc; @@ -430,12 +1322,12 @@ QVector Vecs::sort_and_unify_vecs() const /* The style formats are based on the xcsv format, * Make sure we know which entry in the vector list that is. */ - assert(vec_list.at(0).name.compare("xcsv", Qt::CaseInsensitive) == 0); + assert(d_ptr_->vec_list.at(0).name.compare("xcsv", Qt::CaseInsensitive) == 0); /* The style formats use a modified xcsv argument list that doesn't include * the option to set the style file. Make sure we know which entry in * the argument list that is. */ - assert(case_ignore_strcmp(vec_list.at(0).vec->get_args()->at(0).helpstring, + assert(case_ignore_strcmp(d_ptr_->vec_list.at(0).vec->get_args()->at(0).helpstring, "Full path to XCSV style file") == 0); /* Gather the relevant info for the style based formats. */ @@ -467,7 +1359,7 @@ QVector Vecs::sort_and_unify_vecs() const * 'Full path to XCSV style file' argument to any * GUIs for an internal format. */ - const QVector* args = vec_list.at(0).vec->get_args(); + const QVector* args = d_ptr_->vec_list.at(0).vec->get_args(); if (args != nullptr) { bool first = true; for (const auto& arg : *args) { @@ -720,7 +1612,7 @@ bool Vecs::validate_formats() const { bool ok = true; - for (const auto& vec : vec_list) { + for (const auto& vec : d_ptr_->vec_list) { ok = validate_vec(vec) && ok; } diff --git a/vecs.h b/vecs.h index eb6e39b81..55b908ecb 100644 --- a/vecs.h +++ b/vecs.h @@ -21,132 +21,49 @@ #ifndef VECS_H_INCLUDED_ #define VECS_H_INCLUDED_ -#include +#include // for uint32_t #include // for QString #include // for QStringList #include // for QVector<>::iterator, QVector #include "defs.h" -#include "dg-100.h" -#include "energympro.h" -#include "f90g_track.h" -#include "exif.h" #include "format.h" -#include "garmin_fit.h" -#include "garmin_gpi.h" -#include "gdb.h" -#include "geojson.h" -#include "ggv_bin.h" -#include "globalsat_sport.h" -#include "gpx.h" -#include "humminbird.h" -#include "gtrnctr.h" -#include "html.h" -#include "kml.h" -#include "legacyformat.h" -#include "lowranceusr.h" -#include "mapbar_track.h" -#include "mapfactor.h" -#include "mynav.h" -#include "nmea.h" -#include "osm.h" -#include "qstarz_bl_1000.h" -#include "random.h" -#include "shape.h" -#include "skytraq.h" -#include "subrip.h" -#include "tef_xml.h" -#include "teletype.h" -#include "text.h" -#include "unicsv.h" -#include "wintec_tes.h" -#include "xcsv.h" -extern ff_vecs_t geo_vecs; -extern ff_vecs_t mag_svecs; -extern ff_vecs_t mag_fvecs; -extern ff_vecs_t magX_fvecs; -extern ff_vecs_t garmin_vecs; -extern ff_vecs_t ozi_vecs; -#if MAXIMAL_ENABLED -extern ff_vecs_t holux_vecs; -extern ff_vecs_t tpg_vecs; -extern ff_vecs_t tpo2_vecs; -extern ff_vecs_t tpo3_vecs; -extern ff_vecs_t easygps_vecs; -extern ff_vecs_t saroute_vecs; -extern ff_vecs_t gpl_vecs; -extern ff_vecs_t igc_vecs; -extern ff_vecs_t brauniger_iq_vecs; -extern ff_vecs_t mtk_vecs; -extern ff_vecs_t mtk_fvecs; -extern ff_vecs_t mtk_m241_vecs; -extern ff_vecs_t mtk_m241_fvecs; -extern ff_vecs_t mtk_locus_vecs; -#endif // MAXIMAL_ENABLED -extern ff_vecs_t wbt_svecs; -#if MAXIMAL_ENABLED -extern ff_vecs_t wbt_fvecs; -//extern ff_vecs_t wbt_fvecs; -extern ff_vecs_t hiketech_vecs; -extern ff_vecs_t glogbook_vecs; -extern ff_vecs_t vcf_vecs; -extern ff_vecs_t google_dir_vecs; -extern ff_vecs_t tomtom_vecs; -extern ff_vecs_t bcr_vecs; -extern ff_vecs_t ignr_vecs; -extern ff_vecs_t gtm_vecs; -extern ff_vecs_t gpssim_vecs; -#if CSVFMTS_ENABLED -extern ff_vecs_t garmin_txt_vecs; -#endif // CSVFMTS_ENABLED -extern ff_vecs_t dmtlog_vecs; -extern ff_vecs_t raymarine_vecs; -extern ff_vecs_t ggv_log_vecs; -extern ff_vecs_t lmx_vecs; -extern ff_vecs_t xol_vecs; -extern ff_vecs_t navilink_vecs; -extern ff_vecs_t ik3d_vecs; -extern ff_vecs_t destinator_poi_vecs; -extern ff_vecs_t destinator_itn_vecs; -extern ff_vecs_t destinator_trl_vecs; -extern ff_vecs_t igo8_vecs; -extern ff_vecs_t mapasia_tr7_vecs; -extern ff_vecs_t gnav_trl_vecs; -extern ff_vecs_t navitel_trk_vecs; -extern ff_vecs_t ggv_ovl_vecs; -#if CSVFMTS_ENABLED -#endif // CSVFMTS_ENABLED -extern ff_vecs_t itracku_vecs; -extern ff_vecs_t itracku_fvecs; -extern ff_vecs_t sbp_vecs; -extern ff_vecs_t sbn_vecs; -extern ff_vecs_t mmo_vecs; -extern ff_vecs_t v900_vecs; -extern ff_vecs_t enigma_vecs; -extern ff_vecs_t format_garmin_xt_vecs; -#endif // MAXIMAL_ENABLED class Vecs { // Meyers Singleton public: - static Vecs& Instance() - { - static Vecs instance; - return instance; - } + /* Special Member Functions */ + + static Vecs& Instance(); Vecs(const Vecs&) = delete; Vecs& operator= (const Vecs&) = delete; Vecs(Vecs&&) = delete; Vecs& operator=(Vecs&&) = delete; -private: - Vecs() = default; - ~Vecs() = default; + /* Member Functions */ + + void init_vecs(); + void exit_vecs(); + static void assign_option(const QString& module, arglist_t* arg, const char* val); + static void disp_vec_options(const QString& vecname, const QVector* args); + static void validate_options(const QStringList& options, const QVector* args, const QString& name); + static QString get_option(const QStringList& options, const char* argname); + Format* find_vec(const QString& vecname); + void disp_vecs() const; + void disp_vec(const QString& vecname) const; + static const char* name_option(uint32_t type); + void disp_formats(int version) const; + static bool validate_args(const QString& name, const QVector* args); + bool validate_formats() const; private: + /* Types */ + + struct Impl; // Not defined here + struct vecs_t { Format* vec; QString name; @@ -189,23 +106,13 @@ class Vecs QString style_filename; }; + /* Special Member Functions */ -public: - void init_vecs(); - void exit_vecs(); - static void assign_option(const QString& module, arglist_t* arg, const char* val); - static void disp_vec_options(const QString& vecname, const QVector* args); - static void validate_options(const QStringList& options, const QVector* args, const QString& name); - static QString get_option(const QStringList& options, const char* argname); - Format* find_vec(const QString& vecname); - void disp_vecs() const; - void disp_vec(const QString& vecname) const; - static const char* name_option(uint32_t type); - void disp_formats(int version) const; - static bool validate_args(const QString& name, const QVector* args); - bool validate_formats() const; + explicit Vecs(Impl* i) : d_ptr_(i) {} + ~Vecs() = default; + + /* Member Functions */ -private: static int is_integer(const char* c); static QVector create_style_vec(); QVector sort_and_unify_vecs() const; @@ -215,790 +122,11 @@ class Vecs static void disp_v3(const vecinfo_t& vec); static bool validate_vec(const vecs_t& vec); -private: + /* Data Members */ + + Impl* d_ptr_; // Opaque pointer + QVector style_list; - /* - * Having these LegacyFormat instances be non-static data members - * prevents the static initialization order fiasco because - * the static vec that is used to construct a legacy format - * instance is guaranteed to have already constructed when an instance - * of this class is constructed. - */ -#if CSVFMTS_ENABLED - XcsvFormat xcsv_fmt; -#endif // CSVFMTS_ENABLED - LegacyFormat geo_fmt {geo_vecs}; - GpxFormat gpx_fmt; - LegacyFormat mag_sfmt {mag_svecs}; - LegacyFormat mag_ffmt {mag_fvecs}; - LegacyFormat magX_ffmt {magX_fvecs}; - LegacyFormat garmin_fmt {garmin_vecs}; - GdbFormat gdb_fmt; - NmeaFormat nmea_fmt; - LegacyFormat ozi_fmt {ozi_vecs}; - KmlFormat kml_fmt; -#if MAXIMAL_ENABLED - LowranceusrFormat lowranceusr_fmt; - LegacyFormat holux_fmt {holux_vecs}; - LegacyFormat tpg_fmt {tpg_vecs}; - LegacyFormat tpo2_fmt {tpo2_vecs}; - LegacyFormat tpo3_fmt {tpo3_vecs}; - LegacyFormat easygps_fmt {easygps_vecs}; - LegacyFormat saroute_fmt {saroute_vecs}; -#if SHAPELIB_ENABLED - ShapeFormat shape_fmt; -#endif - LegacyFormat gpl_fmt {gpl_vecs}; - TextFormat text_fmt; - HtmlFormat html_fmt; - LegacyFormat igc_fmt {igc_vecs}; - LegacyFormat brauniger_iq_fmt {brauniger_iq_vecs}; - LegacyFormat mtk_fmt {mtk_vecs}; - LegacyFormat mtk_ffmt {mtk_fvecs}; - LegacyFormat mtk_m241_fmt {mtk_m241_vecs}; - LegacyFormat mtk_m241_ffmt {mtk_m241_fvecs}; - LegacyFormat mtk_locus_fmt {mtk_locus_vecs}; -#endif // MAXIMAL_ENABLED - LegacyFormat wbt_sfmt {wbt_svecs}; -#if MAXIMAL_ENABLED - LegacyFormat wbt_ffmt {wbt_fvecs}; -//LegacyFormat wbt_ffmt {wbt_fvecs}; - LegacyFormat hiketech_fmt {hiketech_vecs}; - LegacyFormat glogbook_fmt {glogbook_vecs}; - LegacyFormat vcf_fmt {vcf_vecs}; - LegacyFormat google_dir_fmt {google_dir_vecs}; - LegacyFormat tomtom_fmt {tomtom_vecs}; - TefXMLFormat tef_xml_fmt; - LegacyFormat bcr_fmt {bcr_vecs}; - LegacyFormat ignr_fmt {ignr_vecs}; - UnicsvFormat unicsv_fmt; - LegacyFormat gtm_fmt {gtm_vecs}; - LegacyFormat gpssim_fmt {gpssim_vecs}; -#if CSVFMTS_ENABLED - LegacyFormat garmin_txt_fmt {garmin_txt_vecs}; -#endif // CSVFMTS_ENABLED - GtrnctrFormat gtc_fmt; - LegacyFormat dmtlog_fmt {dmtlog_vecs}; - LegacyFormat raymarine_fmt {raymarine_vecs}; - LegacyFormat ggv_log_fmt {ggv_log_vecs}; - GarminGPIFormat garmin_gpi_fmt; - LegacyFormat lmx_fmt {lmx_vecs}; - RandomFormat random_fmt; - LegacyFormat xol_fmt {xol_vecs}; - Dg100SerialFormat dg100_fmt; - Dg100FileFormat dg100_ffmt; - Dg200SerialFormat dg200_fmt; - Dg200FileFormat dg200_ffmt; - LegacyFormat navilink_fmt {navilink_vecs}; - LegacyFormat ik3d_fmt {ik3d_vecs}; - OsmFormat osm_fmt; - LegacyFormat destinator_poi_fmt {destinator_poi_vecs}; - LegacyFormat destinator_itn_fmt {destinator_itn_vecs}; - LegacyFormat destinator_trl_fmt {destinator_trl_vecs}; - ExifFormat exif_fmt; - LegacyFormat igo8_fmt {igo8_vecs}; - HumminbirdFormat humminbird_fmt; - HumminbirdHTFormat humminbird_ht_fmt; - LegacyFormat mapasia_tr7_fmt {mapasia_tr7_vecs}; - LegacyFormat gnav_trl_fmt {gnav_trl_vecs}; - LegacyFormat navitel_trk_fmt {navitel_trk_vecs}; - LegacyFormat ggv_ovl_fmt {ggv_ovl_vecs}; - LegacyFormat itracku_fmt {itracku_vecs}; - LegacyFormat itracku_ffmt {itracku_fvecs}; - LegacyFormat sbp_fmt {sbp_vecs}; - LegacyFormat sbn_fmt {sbn_vecs}; - LegacyFormat mmo_fmt {mmo_vecs}; - LegacyFormat v900_fmt {v900_vecs}; - LegacyFormat enigma_fmt {enigma_vecs}; - SkytraqFormat skytraq_fmt; - TeletypeFormat teletype_fmt; - SkytraqfileFormat skytraq_ffmt; - MinihomerFormat miniHomer_fmt; - WintecTesFormat wintec_tes_fmt; - SubripFormat subrip_fmt; - LegacyFormat format_garmin_xt_fmt {format_garmin_xt_vecs}; - GarminFitFormat format_fit_fmt; - MapbarTrackFormat mapbar_track_fmt; - F90gTrackFormat f90g_track_fmt; - MapfactorFormat mapfactor_fmt; - EnergymproFormat energympro_fmt; - MyNavFormat mynav_fmt; - GeoJsonFormat geojson_fmt; - GgvBinFormat ggv_bin_fmt; - GlobalsatSportFormat globalsat_sport_fmt; - QstarzBL1000Format qstarz_bl_1000_fmt; -#endif // MAXIMAL_ENABLED - const QVector vec_list { -#if CSVFMTS_ENABLED - /* XCSV must be the first entry in this table. */ - { - &xcsv_fmt, - "xcsv", - "? Character Separated Values", - nullptr, - nullptr, - }, -#endif - { - &geo_fmt, - "geo", - "Geocaching.com .loc", - "loc", - nullptr, - }, - { - &gpx_fmt, - "gpx", - "GPX XML", - "gpx", - nullptr, - }, - { - &mag_sfmt, - "magellan", - "Magellan serial protocol", - nullptr, - nullptr, - }, - { - &mag_ffmt, - "magellan", - "Magellan SD files (as for Meridian)", - nullptr, - nullptr, - }, - { - &magX_ffmt, - "magellanx", - "Magellan SD files (as for eXplorist)", - "upt", - nullptr, - }, - { - &garmin_fmt, - "garmin", - "Garmin serial/USB protocol", - nullptr, - nullptr, - }, - { - &gdb_fmt, - "gdb", - "Garmin MapSource - gdb", - "gdb", - nullptr, - }, - { - &nmea_fmt, - "nmea", - "NMEA 0183 sentences", - nullptr, - nullptr, - }, - { - &ozi_fmt, - "ozi", - "OziExplorer", - nullptr, - nullptr, - }, - { - &kml_fmt, - "kml", - "Google Earth (Keyhole) Markup Language", - "kml", - nullptr, - }, -#if MAXIMAL_ENABLED - { - &lowranceusr_fmt, - "lowranceusr", - "Lowrance USR", - "usr", - nullptr, - }, - { - &holux_fmt, - "holux", - "Holux (gm-100) .wpo Format", - "wpo", - nullptr, - }, - { - &tpg_fmt, - "tpg", - "National Geographic Topo .tpg (waypoints)", - "tpg", - nullptr, - }, - { - &tpo2_fmt, - "tpo2", - "National Geographic Topo 2.x .tpo", - "tpo", - nullptr, - }, - { - &tpo3_fmt, - "tpo3", - "National Geographic Topo 3.x/4.x .tpo", - "tpo", - nullptr, - }, - { - &easygps_fmt, - "easygps", - "EasyGPS binary format", - "loc", - nullptr, - }, - { - &saroute_fmt, - "saroute", - "DeLorme Street Atlas Route", - "anr", - nullptr, - }, -#if SHAPELIB_ENABLED - { - &shape_fmt, - "shape", - "ESRI shapefile", - "shp", - nullptr, - }, -#endif - { - &gpl_fmt, - "gpl", - "DeLorme GPL", - "gpl", - nullptr, - }, - { - &text_fmt, - "text", - "Textual Output", - "txt", - nullptr, - }, - { - &html_fmt, - "html", - "HTML Output", - "html", - nullptr, - }, - { - &igc_fmt, - "igc", - "FAI/IGC Flight Recorder Data Format", - nullptr, - nullptr, - }, - { - &brauniger_iq_fmt, - "baroiq", - "Brauniger IQ Series Barograph Download", - nullptr, - nullptr, - }, - { - &mtk_fmt, - "mtk", - "MTK Logger (iBlue 747,Qstarz BT-1000,...) download", - nullptr, - nullptr, - }, - { - &mtk_ffmt, - "mtk-bin", - "MTK Logger (iBlue 747,...) Binary File Format", - "bin", - nullptr, - }, - { - &mtk_m241_fmt, - "m241", - "Holux M-241 (MTK based) download", - nullptr, - nullptr, - }, - { - &mtk_m241_ffmt, - "m241-bin", - "Holux M-241 (MTK based) Binary File Format", - "bin", - nullptr, - }, - { - &mtk_locus_fmt, - "mtk_locus", - "MediaTek Locus", - nullptr, - nullptr, - }, -#endif // MAXIMAL_ENABLED - { - &wbt_sfmt, - "wbt", - "Wintec WBT-100/200 GPS Download", - nullptr, - nullptr, - }, -#if MAXIMAL_ENABLED - { - &wbt_ffmt, - "wbt-bin", - "Wintec WBT-100/200 Binary File Format", - "bin", - nullptr, - }, - { - &wbt_ffmt, - "wbt-tk1", - "Wintec WBT-201/G-Rays 2 Binary File Format", - "tk1", - nullptr, - }, - { - &hiketech_fmt, - "hiketech", - "HikeTech", - "gps", - nullptr, - }, - { - &glogbook_fmt, - "glogbook", - "Garmin Logbook XML", - "xml", - nullptr, - }, - { - &vcf_fmt, - "vcard", - "Vcard Output (for iPod)", - "vcf", - nullptr, - }, - { - &google_dir_fmt, - "googledir", - "Google Directions XML", - "xml", - nullptr, - }, - { - &tomtom_fmt, - "tomtom", - "TomTom POI file (.ov2)", - "ov2", - nullptr, - }, - { - &tef_xml_fmt, - "tef", - "Map&Guide 'TourExchangeFormat' XML", - "xml", - nullptr, - }, - { - &bcr_fmt, - "bcr", - "Motorrad Routenplaner (Map&Guide) .bcr files", - "bcr", - nullptr, - }, - { - &ignr_fmt, - "ignrando", - "IGN Rando track files", - "rdn", - nullptr, - }, - { - &unicsv_fmt, - "unicsv", - "Universal csv with field structure in first line", - nullptr, - nullptr, - }, - { - >m_fmt, - "gtm", - "GPS TrackMaker", - "gtm", - nullptr, - }, - { - &gpssim_fmt, - "gpssim", - "Franson GPSGate Simulation", - "gpssim", - nullptr, - }, -#if CSVFMTS_ENABLED - { - &garmin_txt_fmt, - "garmin_txt", - "Garmin MapSource - txt (tab delimited)", - "txt", - nullptr, - }, -#endif // CSVFMTS_ENABLED - { - >c_fmt, - "gtrnctr", - "Garmin Training Center (.tcx/.crs/.hst/.xml)", - "tcx/crs/hst/xml", - nullptr, - }, - { - &dmtlog_fmt, - "dmtlog", - "TrackLogs digital mapping (.trl)", - "trl", - nullptr, - }, - { - &raymarine_fmt, - "raymarine", - "Raymarine Waypoint File (.rwf)", - "rwf", - nullptr, - }, - { - &ggv_log_fmt, - "ggv_log", - "Geogrid-Viewer tracklogs (.log)", - "log", - nullptr, - }, - { - &garmin_gpi_fmt, - "garmin_gpi", - "Garmin Points of Interest (.gpi)", - "gpi", - nullptr, - }, - { - &lmx_fmt, - "lmx", - "Nokia Landmark Exchange", - nullptr, - nullptr, - }, - { - &random_fmt, - "random", - "Internal GPS data generator", - nullptr, - nullptr, - }, - { - &xol_fmt, - "xol", - "Swiss Map 25/50/100 (.xol)", - "xol", - nullptr, - }, - { - &dg100_fmt, - "dg-100", - "GlobalSat DG-100/BT-335 Download", - nullptr, - nullptr, - }, - { - &dg100_ffmt, - "dg-100-bin", - "GlobalSat DG-100/BT-335 Binary File", - nullptr, - nullptr, - }, - { - &dg200_fmt, - "dg-200", - "GlobalSat DG-200 Download", - nullptr, - nullptr, - }, - { - &dg200_ffmt, - "dg-200-bin", - "GlobalSat DG-200 Binary File", - nullptr, - nullptr, - }, - { - &navilink_fmt, - "navilink", - "NaviGPS GT-11/BGT-11 Download", - nullptr, - nullptr, - }, - { - &ik3d_fmt, - "ik3d", - "MagicMaps IK3D project file (.ikt)", - "ikt", - nullptr, - }, - { - &osm_fmt, - "osm", - "OpenStreetMap data files", - "osm", - nullptr, - }, - { - &destinator_poi_fmt, - "destinator_poi", - "Destinator Points of Interest (.dat)", - "dat", - nullptr, - }, - { - &destinator_itn_fmt, - "destinator_itn", - "Destinator Itineraries (.dat)", - "dat", - nullptr, - }, - { - &destinator_trl_fmt, - "destinator_trl", - "Destinator TrackLogs (.dat)", - "dat", - nullptr, - }, - { - &exif_fmt, - "exif", - "Embedded Exif-GPS data (.jpg)", - "jpg", - nullptr, - }, - { - &igo8_fmt, - "igo8", - "IGO8 .trk", - "trk", - nullptr, - }, - { - &humminbird_fmt, - "humminbird", - "Humminbird waypoints and routes (.hwr)", - "hwr", - nullptr, - }, - { - &humminbird_ht_fmt, - "humminbird_ht", - "Humminbird tracks (.ht)", - "ht", - nullptr, - }, - { - &mapasia_tr7_fmt, - "mapasia_tr7", - "MapAsia track file (.tr7)", - "tr7", - nullptr, - }, - { - &gnav_trl_fmt, - "gnav_trl", - "Google Navigator Tracklines (.trl)", - "trl", - nullptr, - }, - { - &navitel_trk_fmt, - "navitel_trk", - "Navitel binary track (.bin)", - "bin", - nullptr, - }, - { - &ggv_ovl_fmt, - "ggv_ovl", - "Geogrid-Viewer ascii overlay file (.ovl)", - "ovl", - nullptr, - }, - { - &itracku_fmt, - "itracku", - "XAiOX iTrackU Logger", - nullptr, - nullptr, - }, - { - &itracku_ffmt, - "itracku-bin", - "XAiOX iTrackU Logger Binary File Format", - "bin", - nullptr, - }, - { - &sbp_fmt, - "sbp", - "NaviGPS GT-31/BGT-31 datalogger (.sbp)", - "sbp", - nullptr, - }, - { - &sbn_fmt, - "sbn", - "NaviGPS GT-31/BGT-31 SiRF binary logfile (.sbn)", - "sbn", - nullptr, - }, - { - &mmo_fmt, - "mmo", - "Memory-Map Navigator overlay files (.mmo)", - "mmo", - nullptr, - }, - { - &v900_fmt, - "v900", - "Columbus/Visiontac V900 files (.csv)", - nullptr, - nullptr, - }, - { - &enigma_fmt, - "enigma", - "Enigma binary waypoint file (.ert)", - "ert", - nullptr, - }, - { - &skytraq_fmt, - "skytraq", - "SkyTraq Venus based loggers (download)", - nullptr, - nullptr, - }, - { - &teletype_fmt, - "teletype", - "Teletype [ Get Jonathon Johnson to describe", - nullptr, - nullptr, - }, - { - &skytraq_ffmt, - "skytraq-bin", - "SkyTraq Venus based loggers Binary File Format", - "bin", - nullptr, - }, - { - &miniHomer_fmt, - "miniHomer", - "MiniHomer, a skyTraq Venus 6 based logger (download tracks, waypoints and get/set POI)", - nullptr, - nullptr, - }, - { - &wintec_tes_fmt, - "wintec_tes", - "Wintec TES file", - "tes", - nullptr, - }, - { - &subrip_fmt, - "subrip", - "SubRip subtitles for video mapping (.srt)", - "srt", - nullptr, - }, - { - &format_garmin_xt_fmt, - "garmin_xt", - "Mobile Garmin XT Track files", - nullptr, - nullptr, - }, - { - &format_fit_fmt, - "garmin_fit", - "Flexible and Interoperable Data Transfer (FIT) Activity file", - "fit", - nullptr, - }, - { - &mapbar_track_fmt, - "mapbar", - "Mapbar (China) navigation track for Sonim Xp3300", - "trk", - nullptr, - }, - { - &f90g_track_fmt, - "f90g", - "F90G Automobile DVR GPS log file", - "map", - nullptr, - }, - { - &mapfactor_fmt, - "mapfactor", - "Mapfactor Navigator", - "xml", - nullptr, - }, - { - &energympro_fmt, - "energympro", - "Energympro GPS training watch", - "cpo", - nullptr, - }, - { - &mynav_fmt, - "mynav", - "MyNav TRC format", - "trc", - nullptr, - }, - { - &geojson_fmt, - "geojson", - "GeoJson", - "json", - nullptr, - }, - { - &ggv_bin_fmt, - "ggv_bin", - "Geogrid-Viewer binary overlay file (.ovl)", - "ovl", - nullptr, - }, - { - &globalsat_sport_fmt, - "globalsat", - "GlobalSat GH625XT GPS training watch", - nullptr, - nullptr, - }, - { - &qstarz_bl_1000_fmt, - "qstarz_bl-1000", - "Qstarz BL-1000", - nullptr, - nullptr, - } -#endif // MAXIMAL_ENABLED - }; }; #endif // VECS_H_INCLUDED_