Skip to content

Commit

Permalink
support optional start elements in xmlstreamwriter. (#1193)
Browse files Browse the repository at this point in the history
this adds methods to xmlstreamwriter to allow conditional writing
of a start element.  The conditional element will only be written to
the stream if it has children, which is deteremined when the condtional
element is ended.  This simplifies writing of such elements as the
writer does not need to know if it will subsequently write children or
not.
  • Loading branch information
tsteven4 authored Oct 27, 2023
1 parent e81ff8d commit c95e1cf
Show file tree
Hide file tree
Showing 5 changed files with 300 additions and 177 deletions.
148 changes: 55 additions & 93 deletions garmin_fs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
*/

#include <cstdio> // for snprintf, sscanf
#include <cstdlib> // for strtod
#include <cstdio> // for snprintf, sscanf
#include <cstdlib> // for strtod

#include <QString> // for QString, QStringLiteral
#include <QXmlStreamWriter> // for QXmlStreamWriter
#include <Qt> // for CaseInsensitive
#include <QString> // for QString, QStringLiteral
#include <Qt> // for CaseInsensitive

#include "defs.h"
#include "garmin_fs.h"
#include "garmin_tables.h" // for gt_switch_display_mode_value, gt_display_mode_symbol, gt_display_mode_symbol_and_comment, gt_display_mode_symbol_and_name
#include "inifile.h" // for inifile_readstr
#include "garmin_tables.h" // for gt_switch_display_mode_value, gt_display_mode_symbol, gt_display_mode_symbol_and_comment, gt_display_mode_symbol_and_name
#include "inifile.h" // for inifile_readstr
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter


#define MYNAME "garmin_fs"
Expand Down Expand Up @@ -80,113 +80,75 @@ garmin_fs_t::~garmin_fs_t()

void
garmin_fs_xml_fprint(const Waypoint* waypt,
QXmlStreamWriter* writer)
gpsbabel::XmlStreamWriter* writer)
{
garmin_fs_t* gmsd = garmin_fs_t::find(waypt);

if (gmsd == nullptr) {
return;
}
writer->stackOptionalStartElement(QStringLiteral("extensions"));
writer->stackOptionalStartElement(QStringLiteral("gpxx:WaypointExtension"));
writer->stackNamespace(QStringLiteral("http://www.garmin.com/xmlschemas/GpxExtensions/v3"),
"gpxx");

/* Find out if there is at least one field set */
QString addr = garmin_fs_t::get_addr(gmsd, "");
if (addr.isEmpty()) {
addr = garmin_fs_t::get_city(gmsd, "");
}
if (addr.isEmpty()) {
addr = garmin_fs_t::get_country(gmsd, "");
if (waypt->proximity_has_value()) {
writer->stackTextElement(QStringLiteral("gpxx:Proximity"), QString::number(waypt->proximity_value(), 'f', 6));
}
if (addr.isEmpty()) {
addr = garmin_fs_t::get_postal_code(gmsd, "");

if (waypt->temperature_has_value()) {
writer->stackTextElement(QStringLiteral("gpxx:Temperature"), QString::number(waypt->temperature_value(), 'f', 6));
}
if (addr.isEmpty()) {
addr = garmin_fs_t::get_state(gmsd, "");

if (waypt->depth_has_value()) {
writer->stackTextElement(QStringLiteral("gpxx:Depth"), QString::number(waypt->depth_value(), 'f', 6));
}

QString phone = garmin_fs_t::get_phone_nr(gmsd, "");

if (!addr.isEmpty() || !phone.isEmpty() ||
(gmsd->flags.category && gmsd->category) ||
waypt->depth_has_value() ||
waypt->proximity_has_value() ||
waypt->temperature_has_value() ||
gmsd->flags.display) {
writer->writeStartElement(QStringLiteral("extensions"));
writer->writeStartElement(QStringLiteral("gpxx:WaypointExtension"));
writer->writeNamespace(QStringLiteral("http://www.garmin.com/xmlschemas/GpxExtensions/v3"),
"gpxx");
if (waypt->proximity_has_value()) {
writer->writeTextElement(QStringLiteral("gpxx:Proximity"), QString::number(waypt->proximity_value(), 'f', 6));
}
if (waypt->temperature_has_value()) {
writer->writeTextElement(QStringLiteral("gpxx:Temperature"), QString::number(waypt->temperature_value(), 'f', 6));
}
if (waypt->depth_has_value()) {
writer->writeTextElement(QStringLiteral("gpxx:Depth"), QString::number(waypt->depth_value(), 'f', 6));
}
if (gmsd->flags.display) {
const char* cx;
switch (gmsd->display) {
case gt_display_mode_symbol:
cx = "SymbolOnly";
break;
case gt_display_mode_symbol_and_comment:
cx = "SymbolAndDescription";
break;
default:
cx = "SymbolAndName";
break;
}
writer->writeTextElement(QStringLiteral("gpxx:DisplayMode"), cx);
if (garmin_fs_t::has_display(gmsd)) {
const char* cx;
switch (gmsd->display) {
case gt_display_mode_symbol:
cx = "SymbolOnly";
break;
case gt_display_mode_symbol_and_comment:
cx = "SymbolAndDescription";
break;
default:
cx = "SymbolAndName";
break;
}
if (gmsd->flags.category && gmsd->category) {
uint16_t cx = gmsd->category;
writer->writeStartElement(QStringLiteral("gpxx:Categories"));
for (int i = 0; i < 16; i++) {
if (cx & 1) {
writer->writeTextElement(QStringLiteral("gpxx:Category"), QStringLiteral("Category %1").arg(i+1));
}
cx = cx >> 1;
}
writer->writeEndElement(); // gpxx:Categories
}
if (!addr.isEmpty()) {
QString str;
writer->writeStartElement(QStringLiteral("gpxx:Address"));
writer->stackTextElement(QStringLiteral("gpxx:DisplayMode"), cx);
}

if (!(str = garmin_fs_t::get_addr(gmsd, nullptr)).isEmpty()) {
writer->writeTextElement(QStringLiteral("gpxx:StreetAddress"), str);
}
if (!(str = garmin_fs_t::get_city(gmsd, nullptr)).isEmpty()) {
writer->writeTextElement(QStringLiteral("gpxx:City"), str);
}
if (!(str = garmin_fs_t::get_state(gmsd, nullptr)).isEmpty()) {
writer->writeTextElement(QStringLiteral("gpxx:State"), str);
}
if (!(str = garmin_fs_t::get_country(gmsd, nullptr)).isEmpty()) {
writer->writeTextElement(QStringLiteral("gpxx:Country"), str);
if (garmin_fs_t::has_category(gmsd)) {
uint16_t cx = gmsd->category;
writer->stackStartElement(QStringLiteral("gpxx:Categories"));
for (int i = 0; i < 16; i++) {
if (cx & 1) {
writer->stackTextElement(QStringLiteral("gpxx:Category"), QStringLiteral("Category %1").arg(i+1));
}
if (!(str = garmin_fs_t::get_postal_code(gmsd, nullptr)).isEmpty()) {
writer->writeTextElement(QStringLiteral("gpxx:PostalCode"), str);
}
writer->writeEndElement(); // /gpxx::Address
cx = cx >> 1;
}
writer->stackEndElement(); // gpxx:Categories
}

if (!phone.isEmpty()) {
writer->writeTextElement(QStringLiteral("gpxx:PhoneNumber"), phone);
}
writer->stackOptionalStartElement(QStringLiteral("gpxx:Address"));
writer->stackOptionalTextElement(QStringLiteral("gpxx:StreetAddress"), garmin_fs_t::get_addr(gmsd, nullptr));
writer->stackOptionalTextElement(QStringLiteral("gpxx:City"), garmin_fs_t::get_city(gmsd, nullptr));
writer->stackOptionalTextElement(QStringLiteral("gpxx:State"), garmin_fs_t::get_state(gmsd, nullptr));
writer->stackOptionalTextElement(QStringLiteral("gpxx:Country"), garmin_fs_t::get_country(gmsd, nullptr));
writer->stackOptionalTextElement(QStringLiteral("gpxx:PostalCode"), garmin_fs_t::get_postal_code(gmsd, nullptr));
writer->stackEndElement(); // gpxx:Address

writer->stackOptionalTextElement(QStringLiteral("gpxx:PhoneNumber"), garmin_fs_t::get_phone_nr(gmsd, nullptr));

writer->writeEndElement(); // /gpxx::WaypointExtension
writer->writeEndElement(); // /extensions.
}

writer->stackEndElement(); // gpxx:WaypointExtension
writer->stackEndElement(); // extensions
}

void
garmin_fs_xml_convert(const int base_tag, int tag, const QString& qstr, Waypoint* waypt)
{
// FIXME: eliminate C string copy/use here:
const char *cdatastr = xstrdup(qstr);
const char* cdatastr = xstrdup(qstr);
garmin_fs_t* gmsd = garmin_fs_t::find(waypt);
if (gmsd == nullptr) {
gmsd = garmin_fs_alloc(-1);
Expand Down
11 changes: 5 additions & 6 deletions garmin_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@
#ifndef GARMIN_FS_H
#define GARMIN_FS_H

#include <cstddef> // for size_t
#include <cstdint> // for int32_t, int16_t, uint16_t
#include <cstdint> // for int32_t, int16_t, uint16_t

#include <QString> // for QString
#include <QXmlStreamWriter> // for QXmlStreamWriter
#include <QString> // for QString

#include "defs.h"
#include "formspec.h" // for FsChainFind, kFsGmsd, FormatSpecificData
#include "formspec.h" // for FsChainFind, kFsGmsd, FormatSpecificData
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter


/* this order is used by most devices */
Expand Down Expand Up @@ -222,7 +221,7 @@ void garmin_fs_copy(void** dest, const void* src);

/* for GPX */
void garmin_fs_xml_convert(int base_tag, int tag, const QString& qstr, Waypoint* waypt);
void garmin_fs_xml_fprint(const Waypoint* waypt, QXmlStreamWriter*);
void garmin_fs_xml_fprint(const Waypoint* waypt, gpsbabel::XmlStreamWriter*);

/* common garmin_fs utilities */

Expand Down
Loading

0 comments on commit c95e1cf

Please sign in to comment.