diff --git a/gpx.cc b/gpx.cc index 1439a5f0c..9c8f5bf8d 100644 --- a/gpx.cc +++ b/gpx.cc @@ -522,6 +522,7 @@ GpxFormat::gpx_end(QStringView /*unused*/) logpoint_ct = 0; cur_tag = nullptr; wpt_tmp = nullptr; + fs_ptr = nullptr; break; case tt_cache_name: wpt_tmp->notes = cdatastr; @@ -616,6 +617,7 @@ GpxFormat::gpx_end(QStringView /*unused*/) delete rh_link_; rh_link_ = nullptr; } + fs_ptr = nullptr; break; case tt_rte_rtept: if (link_) { @@ -631,6 +633,7 @@ GpxFormat::gpx_end(QStringView /*unused*/) } route_add_wpt(rte_head, wpt_tmp); wpt_tmp = nullptr; + fs_ptr = nullptr; break; case tt_rte_desc: rte_head->rte_desc = cdatastr; @@ -661,9 +664,11 @@ GpxFormat::gpx_end(QStringView /*unused*/) delete rh_link_; rh_link_ = nullptr; } + fs_ptr = nullptr; break; case tt_trk_trkseg: next_trkpt_is_new_seg = 1; + fs_ptr = nullptr; break; case tt_trk_trkseg_trkpt: if (link_) { @@ -679,6 +684,7 @@ GpxFormat::gpx_end(QStringView /*unused*/) } track_add_wpt(trk_head, wpt_tmp); wpt_tmp = nullptr; + fs_ptr = nullptr; break; case tt_trk_desc: trk_head->rte_desc = cdatastr; @@ -920,7 +926,7 @@ GpxFormat::wr_init(const QString& fname) // normalization makes them null. if (gpx_write_version.isNull() || (gpx_write_version < gpx_1_0)) { fatal(FatalMsg() << MYNAME ": gpx version number" - << gpx_write_version << "not valid."); + << gpx_write_version << "not valid."); } writer->setAutoFormatting(true); @@ -1092,9 +1098,9 @@ GpxFormat::read() if (reader->hasError()) { fatal(FatalMsg() << MYNAME << "Read error:" << reader->errorString() - << "File:" << iqfile->fileName() - << "Line:" << reader->lineNumber() - << "Column:" << reader->columnNumber()); + << "File:" << iqfile->fileName() + << "Line:" << reader->lineNumber() + << "Column:" << reader->columnNumber()); } } @@ -1369,7 +1375,7 @@ void GpxFormat::gpx_write_common_core(const Waypoint* waypointp, const gpx_point_type point_type) const { const auto* fs_gpxwpt = reinterpret_cast(waypointp->fs.FsChainFind(kFsGpxWpt)); - + gpx_write_common_position(waypointp, point_type, fs_gpxwpt); gpx_write_common_description(waypointp, point_type, fs_gpxwpt); gpx_write_common_acc(waypointp, fs_gpxwpt); @@ -1389,7 +1395,15 @@ GpxFormat::gpx_waypt_pr(const Waypoint* waypointp) const auto* gmsd = garmin_fs_t::find(waypointp); /* gARmIN sPECIAL dATA */ if (fs_gpx) { if (! gmsd) { - fprint_xml_chain(fs_gpx->tag); + if (fs_gpx->tag) { + if (gpx_write_version > gpx_1_0) { + writer->writeStartElement("extensions"); + } + fprint_xml_chain(fs_gpx->tag); + if (gpx_write_version > gpx_1_0) { + writer->writeEndElement(); + } + } } } if (gmsd && (gpx_write_version > gpx_1_0)) { @@ -1416,23 +1430,21 @@ GpxFormat::gpx_track_hdr(const route_head* rte) writer->writeTextElement(QStringLiteral("number"), QString::number(rte->rte_num)); } - if (gpx_write_version > gpx_1_0) { - if (!(opt_humminbirdext || opt_garminext)) { - const auto* fs_gpx = reinterpret_cast(rte->fs.FsChainFind(kFsGpx)); - if (fs_gpx) { - fprint_xml_chain(fs_gpx->tag); - } - } else if (opt_garminext) { - if (rte->line_color.bbggrr > unknown_color) { - int ci = gt_color_index_by_rgb(rte->line_color.bbggrr); - if (ci > 0) { - writer->writeStartElement(QStringLiteral("extensions")); - writer->writeStartElement(QStringLiteral("gpxx:TrackExtension")); - writer->writeTextElement(QStringLiteral("gpxx:DisplayColor"), QStringLiteral("%1") - .arg(gt_color_name(ci))); - writer->writeEndElement(); // Close gpxx:TrackExtension tag - writer->writeEndElement(); // Close extensions tag - } + if (!(opt_humminbirdext || opt_garminext)) { + const auto* fs_gpx = reinterpret_cast(rte->fs.FsChainFind(kFsGpx)); + if (fs_gpx) { + fprint_xml_chain(fs_gpx->tag); + } + } else if (opt_garminext && (gpx_write_version > gpx_1_0)) { + if (rte->line_color.bbggrr > unknown_color) { + int ci = gt_color_index_by_rgb(rte->line_color.bbggrr); + if (ci > 0) { + writer->writeStartElement(QStringLiteral("extensions")); + writer->writeStartElement(QStringLiteral("gpxx:TrackExtension")); + writer->writeTextElement(QStringLiteral("gpxx:DisplayColor"), QStringLiteral("%1") + .arg(gt_color_name(ci))); + writer->writeEndElement(); // Close gpxx:TrackExtension tag + writer->writeEndElement(); // Close extensions tag } } } @@ -1506,25 +1518,23 @@ GpxFormat::gpx_route_hdr(const route_head* rte) const writer->writeTextElement(QStringLiteral("number"), QString::number(rte->rte_num)); } - if (gpx_write_version > gpx_1_0) { - if (!(opt_humminbirdext || opt_garminext)) { - const auto* fs_gpx = reinterpret_cast(rte->fs.FsChainFind(kFsGpx)); - if (fs_gpx) { - fprint_xml_chain(fs_gpx->tag); - } - } else if (opt_garminext) { - if (rte->line_color.bbggrr > unknown_color) { - int ci = gt_color_index_by_rgb(rte->line_color.bbggrr); - if (ci > 0) { - writer->writeStartElement(QStringLiteral("extensions")); - writer->writeStartElement(QStringLiteral("gpxx:RouteExtension")); - // FIXME: the value to use for IsAutoNamed is questionable. - writer->writeTextElement(QStringLiteral("gpxx:IsAutoNamed"), rte->rte_name.isEmpty()? QStringLiteral("true") : QStringLiteral("false")); // Required element - writer->writeTextElement(QStringLiteral("gpxx:DisplayColor"), QStringLiteral("%1") - .arg(gt_color_name(ci))); - writer->writeEndElement(); // Close gpxx:RouteExtension tag - writer->writeEndElement(); // Close extensions tag - } + if (!(opt_humminbirdext || opt_garminext)) { + const auto* fs_gpx = reinterpret_cast(rte->fs.FsChainFind(kFsGpx)); + if (fs_gpx) { + fprint_xml_chain(fs_gpx->tag); + } + } else if (opt_garminext && (gpx_write_version > gpx_1_0)) { + if (rte->line_color.bbggrr > unknown_color) { + int ci = gt_color_index_by_rgb(rte->line_color.bbggrr); + if (ci > 0) { + writer->writeStartElement(QStringLiteral("extensions")); + writer->writeStartElement(QStringLiteral("gpxx:RouteExtension")); + // FIXME: the value to use for IsAutoNamed is questionable. + writer->writeTextElement(QStringLiteral("gpxx:IsAutoNamed"), rte->rte_name.isEmpty()? QStringLiteral("true") : QStringLiteral("false")); // Required element + writer->writeTextElement(QStringLiteral("gpxx:DisplayColor"), QStringLiteral("%1") + .arg(gt_color_name(ci))); + writer->writeEndElement(); // Close gpxx:RouteExtension tag + writer->writeEndElement(); // Close extensions tag } } } diff --git a/reference/gpxpassthrough10.gpx b/reference/gpxpassthrough10.gpx new file mode 100644 index 000000000..937a02276 --- /dev/null +++ b/reference/gpxpassthrough10.gpx @@ -0,0 +1,61 @@ + + + + + 479.300 + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + + + -55.600 + Turn right at Airport Rd + Turn right at Airport Rd + Turn right at Airport Rd + wpt + + + -67.300 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + + + Low Road + Generated from track Route + rte + + 479.300 + RPT001 + + + 624.300 + RPT005 + rtept + + + 663.700 + RPT011 + + + + meridian + trk + + + 1.000 + + + + 0.000 + + trkpt + + + 0.000 + + + + + eof + diff --git a/reference/gpxpassthrough10~gpx.gpx b/reference/gpxpassthrough10~gpx.gpx new file mode 100644 index 000000000..486481301 --- /dev/null +++ b/reference/gpxpassthrough10~gpx.gpx @@ -0,0 +1,61 @@ + + + + + + 479.300 + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + + + -55.600 + Turn right at Airport Rd + Turn right at Airport Rd + Turn right at Airport Rd + wpt + + + -67.300 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + + + Low Road + Generated from track Route + rte + + 479.300 + RPT001 + + + 624.300 + RPT005 + rtept + + + 663.700 + RPT011 + + + + meridian + trk + + + 1.000 + + + + 0.000 + + trkpt + + + 0.000 + + + + + diff --git a/reference/gpxpassthrough11.gpx b/reference/gpxpassthrough11.gpx new file mode 100644 index 000000000..5337507d5 --- /dev/null +++ b/reference/gpxpassthrough11.gpx @@ -0,0 +1,81 @@ + + + + + + metadata + + + + 479.300 + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + + + -55.600 + Turn right at Airport Rd + Turn right at Airport Rd + Turn right at Airport Rd + + wpt + + + + -67.300 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + + + Low Road + Generated from track Route + + rte + + + 479.300 + RPT001 + + + 624.300 + RPT005 + + rtept + + + + 663.700 + RPT011 + + + + meridian + + trk + + + + 1.000 + + + + 0.000 + + + trkpt + + + + 0.000 + + + + trkseg + + + + + eof + + diff --git a/reference/gpxpassthrough11~gpx.gpx b/reference/gpxpassthrough11~gpx.gpx new file mode 100644 index 000000000..9183f17ef --- /dev/null +++ b/reference/gpxpassthrough11~gpx.gpx @@ -0,0 +1,73 @@ + + + + + + + + 479.300 + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + Head east on CA-190 E/Nadeau Trail Continue to follow CA-190 E + + + -55.600 + Turn right at Airport Rd + Turn right at Airport Rd + Turn right at Airport Rd + + wpt + + + + -67.300 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + Arrive at: Furnace Creek Airport-L06, Death Valley National Park, Death Valley, CA 92328 + + + Low Road + Generated from track Route + + rte + + + 479.300 + RPT001 + + + 624.300 + RPT005 + + rtept + + + + 663.700 + RPT011 + + + + meridian + + trk + + + + 1.000 + + + + 0.000 + + + trkpt + + + + 0.000 + + + + + diff --git a/testo.d/gpx.test b/testo.d/gpx.test index f37fcf267..85581adf4 100644 --- a/testo.d/gpx.test +++ b/testo.d/gpx.test @@ -66,6 +66,19 @@ compare ${REFERENCE}/track/garminconnect.csv ${TMPDIR}/garminconnect.csv gpsbabel -i gpx -f ${REFERENCE}/wptsequence.gpx -o gpx -F ${TMPDIR}/wptsequence.gpx compare ${REFERENCE}/wptsequence.gpx ${TMPDIR}/wptsequence.gpx +# passthrough +# gpx 1.0 +# we lose any extensions at the end of file - we don't have a place to store them. +gpsbabel -i gpx -f ${REFERENCE}/gpxpassthrough10.gpx -o gpx -F ${TMPDIR}/gpxpassthrough10~gpx.gpx +compare ${REFERENCE}/gpxpassthrough10~gpx.gpx ${TMPDIR}/gpxpassthrough10~gpx.gpx + +# gpx 1.1 +# we lose the any extensions in metadata, but we are constructing metadata anyway +# we lose any extensions at the end of each trkseg - we don't have a place to store them. +# we lose any extensions at the end of file - we don't have a place to store them. +gpsbabel -i gpx -f ${REFERENCE}/gpxpassthrough11.gpx -o gpx -F ${TMPDIR}/gpxpassthrough11~gpx.gpx +compare ${REFERENCE}/gpxpassthrough11~gpx.gpx ${TMPDIR}/gpxpassthrough11~gpx.gpx + if [ -z "${VALGRIND}" ]; then set -e if command -v xmllint > /dev/null; diff --git a/tools/schema/gpx/master.xsd b/tools/schema/gpx/master.xsd index 7c767b4a4..7f159f325 100644 --- a/tools/schema/gpx/master.xsd +++ b/tools/schema/gpx/master.xsd @@ -11,5 +11,6 @@ + diff --git a/tools/schema/gpx/testonlyschema.xsd b/tools/schema/gpx/testonlyschema.xsd new file mode 100644 index 000000000..7bf28b1c1 --- /dev/null +++ b/tools/schema/gpx/testonlyschema.xsd @@ -0,0 +1,15 @@ + + + + + + This schema exist only for regression testing of gpsbabel. + + + + +