Skip to content

Commit

Permalink
New IgcMetaData and ExtensionDefinition classes
Browse files Browse the repository at this point in the history
  • Loading branch information
PacketFiend committed Mar 29, 2023
1 parent c4eda71 commit f2a67b4
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 90 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/autom4te.cache/
/babelweb/
/bld
/build
/bld/
/build/
/compile_commands.json
/config.h
/config.log
Expand Down Expand Up @@ -45,4 +45,4 @@ CMakeFiles/
/empty
/gbversion.h
/qrc_gpsbabel.cpp
/.vscode
/.vscode/
2 changes: 1 addition & 1 deletion formspec.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ enum FsType {
kFsGmsd = 0x474d5344L, /* GMSD = Garmin specific data */
kFsQstarzBl1000 = 0x5173747aL,
kFsLowranceusr4 = 0x615f234cL,
kFsIGC = 0x587ce52aL,
kFsIGC = 69676308L, /* IGC format, amendment 8 (2023-02-08) */
};

struct FormatSpecificData {
Expand Down
99 changes: 25 additions & 74 deletions igc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#include <QTime> // for operator<, operator==, QTime
#include <Qt> // for UTC, SkipEmptyParts
#include <QtGlobal> // for foreach, qPrintable
#include <QStringRef> // for substring
#include <QStringView> // for QStringView
#include <QDebug> // DELETEME for debugging
#include <QRegularExpression> // for QRegularExpression
Expand Down Expand Up @@ -76,14 +75,6 @@ unsigned char IgcFormat::coords_match(double lat1, double lon1, double lat2, dou
return (fabs(lat1 - lat2) < 0.0001 && fabs(lon1 - lon2) < 0.0001) ? 1 : 0;
}

// https://gist.github.com/david7482/70924ba3cc2cbbbfb88e
// https://stackoverflow.com/questions/98153/whats-the-best-hashing-algorithm-to-use-on-a-stl-string-when-using-hash-map/107657#107657
constexpr unsigned long long int hash2stringint(const char *str, unsigned long long int hash = 0)
{
return (*str == 0) ? hash : 101 * hash2stringint(str + 1) + *str;
}


/*************************************************************************************************
* Input file processing
*/
Expand Down Expand Up @@ -160,7 +151,7 @@ void IgcFormat::TaskRecordReader::igc_task_rec(const char* rec)
&day, &month, &year,
&hour, &minute, &second,
flight_date, task_num, &num_tp, task_desc) < 9) {
fatal(MYNAME ": task id (C) record parse error\n'%s'", rec);
fatal(MYNAME ": task id (C) record parse error A. \n'%s'", rec);
}
task_num[4] = '\0';
if (year < 70) {
Expand Down Expand Up @@ -230,7 +221,7 @@ void IgcFormat::TaskRecordReader::igc_task_rec(const char* rec)
break;

default:
fatal(MYNAME ": task id (C) record internal error\n%s", rec);
fatal(MYNAME ": task id (C) record internal error B\n%s", rec);
break;
}

Expand Down Expand Up @@ -263,14 +254,11 @@ void IgcFormat::read()
char tmp_str[20];
char* hdr_data;
char trk_desc[kMaxDescLen + 1];
std::string s;
std::string s2;
TaskRecordReader task_record_reader;
int begin = 0;
int end = 0;
igc_fs_flags_t igc_fs_flags;
QStringView ext_data;
int current_line = 1; // line numbering is off by one for some reason
int current_line = 1; // For error reporting. Line numbering is off by one for some reason.
IgcMetaData igc_metadata;
ExtensionDefinition* extension;

strcpy(trk_desc, HDRMAGIC HDRDELIM);

Expand Down Expand Up @@ -326,6 +314,7 @@ void IgcFormat::read()
break;

case rec_fix:
{
// Date must appear in file before the first fix record
if (!date.isValid()) {
fatal(MYNAME ": bad date\n");
Expand Down Expand Up @@ -376,22 +365,24 @@ void IgcFormat::read()
* but possible in the case of homebrew flight recorders), then skip the
* whole thing.
*/
if (igc_fs_flags.has_exts) {

// TODO: Iterate over the ext_types_hash hash map and check all extension data
if (igc_metadata.flags.has_igc_exts) {
auto* fsdata = new igc_fsdata;
if (igc_fs_flags.enl){
if (igc_metadata.flags.enl){
bool int_ok;
int len = igc_fs_flags.enl_end - igc_fs_flags.enl_start+1; // The difference results in a fencepost error
ext_data = QStringView(ibuf_q).mid(igc_fs_flags.enl_start, len);
int len = igc_metadata.extension("ENL")->end - igc_metadata.extension("ENL")->start+1; // The difference results in a fencepost error
ext_data = QStringView(ibuf_q).mid(igc_metadata.extension("ENL")->start, len);
fsdata->enl = ext_data.toInt(&int_ok);
if (!int_ok) {
printf(MYNAME ": Fatal parsing error at line %i, character %i. Problem line:\n",current_line, igc_fs_flags.enl_start);
printf(MYNAME ": Fatal parsing error at line %i, character %i. Problem line:\n",current_line, igc_metadata.extension("ENL")->start);
printf(MYNAME ": %s\n",ibuf_q.toUtf8().constData());
printf(MYNAME ": Cannot convert engine noise data %s to integer value.\n", ext_data.toUtf8().constData());
fatal(MYNAME ": Fatal error processing IGC file.\n");
} else {
pres_wpt->fs.FsChainAdd(fsdata);
}
}

pres_wpt->fs.FsChainAdd(fsdata);
}

pres_wpt->SetCreationTime(QDateTime(date, tod, Qt::UTC));
Expand All @@ -417,7 +408,7 @@ void IgcFormat::read()
}
track_add_wpt(gnss_head, gnss_wpt);
break;

}
case rec_task:
// Create a route for each pre-flight declaration
task_record_reader.igc_task_rec(ibuf);
Expand Down Expand Up @@ -489,59 +480,19 @@ void IgcFormat::read()
* the hash and parse individual hash values.
*/
for (i = ext_types_hash.constBegin(); i != ext_types_hash.constEnd(); ++i) {
begin = QStringView(i.key().mid(0,2)).toInt();
end = QStringView(i.key().mid(2,2)).toInt();
short begin = QStringView(i.key().mid(0,2)).toInt();
short end = QStringView(i.key().mid(2,2)).toInt();
QStringView ext_record_type = QStringView(i.key().mid(4,3)).toString();
switch (ext_types_hash.value(i.key())) {
case ext_rec_enl:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.enl = true;
igc_fs_flags.enl_start = begin;
igc_fs_flags.enl_end = end;
break;
case ext_rec_tas:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.tas = true;
igc_fs_flags.tas_start = begin;
igc_fs_flags.tas_end = end;
break;
case ext_rec_vat:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.vat = true;
igc_fs_flags.vat_start = begin;
igc_fs_flags.vat_end = end;
break;
case ext_rec_oat:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.oat = true;
igc_fs_flags.oat_start = begin;
igc_fs_flags.oat_end = end;
break;
case ext_rec_trt:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.trt = true;
igc_fs_flags.trt_start = begin;
igc_fs_flags.trt_end = end;
break;
case ext_rec_gsp:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.gsp = true;
igc_fs_flags.gsp_start = begin;
igc_fs_flags.gsp_end = end;
break;
case ext_rec_fxa:
igc_fs_flags.has_exts = igc_fs_flags.has_exts || true;
igc_fs_flags.fxa = true;
igc_fs_flags.fxa_start = begin;
igc_fs_flags.fxa_end = end;
break;
default:
break;

}
extension = igc_metadata.extension(ext_record_type.toString());
extension->start = begin;
extension->end = end;
extension->name = ext_record_type.toString();
extension->exists = true;
}
}
// These record types are discarded

// These record types are discarded
case rec_diff_gps:
case rec_event:
case rec_constel:
Expand Down
111 changes: 101 additions & 10 deletions igc.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,113 @@ class IgcFormat : public Format
*/
struct igc_fs_flags_t {
igc_fs_flags_t() :
has_exts(0),
has_igc_exts(0),
enl(0),
tas(0),
vat(0),
oat(0),
trt(0),
gsp(0),
fxa(0),
fxa(0)

{}

bool has_igc_exts;
bool enl;
bool tas;
bool vat;
bool oat;
bool trt;
bool gsp;
bool fxa;
};

class ExtensionDefinition {
public:
bool exists; // Superfluous flag?
QString name; // Name of extension (ENL,FXA,TAS, etc)
short start; // Start character of this data in B records
short end; // End character of this data in B records
ExtensionDefinition (const QString name = "", short start=0, short end=0) :
exists(!name.isEmpty()),
name(name),
start(start),
end(end)
{}
};

class IgcMetaData {
private:
QMap<QString, ExtensionDefinition*> extensions;
public:
igc_fs_flags_t flags;
IgcMetaData() {
flags.has_igc_exts = false;
flags.enl = false;
flags.tas = false;
flags.vat = false;
flags.oat = false;
flags.trt = false;
flags.gsp = false;
flags.fxa = false;
}

ExtensionDefinition* extension(const QString& name) {
auto it = extensions.find(name);
if (it != extensions.end()) {
// Extension already exists, return it
return *it;
} else {
// Extension does not exist, create a new one and put it in the map
ExtensionDefinition* extension = new ExtensionDefinition();
extension->name = name;
extensions.insert(name, extension);
setHasIgcExtsFlag(); // Update flags
return extension;
}
}

void setHasIgcExtsFlag() {
for (auto& pair : extensions) {
if (pair->exists) {
flags.has_igc_exts = true;
break;
}
}
}

void dump() const {
printf("Flags:\n");
printf(" has_igc_exts = %d\n", flags.has_igc_exts);
printf(" enl = %d\n", flags.enl);
printf(" tas = %d\n", flags.tas);
printf(" vat = %d\n", flags.vat);
printf(" oat = %d\n", flags.oat);
printf(" trt = %d\n", flags.trt);
printf(" gsp = %d\n", flags.gsp);
printf(" fxa = %d\n", flags.fxa);

printf("Extensions:\n");
for (auto it = extensions.begin(); it != extensions.end(); ++it) {
const ExtensionDefinition* extension = it.value();
printf(" Extension %s:\n", extension->name.toStdString().c_str());
printf(" exists = %d\n", extension->exists);
printf(" start = %d\n", extension->start);
printf(" end = %d\n", extension->end);
}
}

~IgcMetaData() {
// Deallocate all ExtensionDefinition objects
for (auto& pair : extensions) {
delete pair;
}
}
};

struct igc_fsmetadata_t {

igc_fsmetadata_t() :
enl_start(0),
enl_end(0),
tas_start(0),
Expand All @@ -204,14 +303,6 @@ struct igc_fs_flags_t {

{}

bool has_exts;
bool enl;
bool tas;
bool vat;
bool oat;
bool trt;
bool gsp;
bool fxa;
short enl_start;
short enl_end;
short tas_start;
Expand Down
4 changes: 2 additions & 2 deletions kml.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1468,7 +1468,7 @@ void KmlFormat::kml_mt_simple_array(const route_head* header,
{
writer->writeStartElement(QStringLiteral("gx:SimpleArrayData"));
writer->writeAttribute(QStringLiteral("name"), name);

foreach (const Waypoint* wpt, header->waypoint_list) {

const auto* fs_igc = reinterpret_cast<igc_fsdata*>(wpt->fs.FsChainFind(kFsIGC));
Expand Down Expand Up @@ -1850,7 +1850,7 @@ void KmlFormat::write()
writer->writeEndElement(); // Close Folder tag
}
}

// Output trackpoints
if (track_waypt_count()) {
if (!realtime_positioning) {
Expand Down

0 comments on commit f2a67b4

Please sign in to comment.