1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-01-19 04:02:09 +01:00

Improved FIT parser error handling

This commit is contained in:
Martin Tůma 2016-11-02 17:33:54 +01:00
parent 324ac2e0f4
commit 87a4398131
2 changed files with 54 additions and 16 deletions

View File

@ -5,6 +5,9 @@
const quint32 FIT_MAGIC = 0x5449462E; // .FIT const quint32 FIT_MAGIC = 0x5449462E; // .FIT
#define RECORD_MESSAGE 20
#define TIMESTAMP_FIELD 253
FITParser::FITParser(QList<TrackData> &tracks, QList<RouteData> &routes, FITParser::FITParser(QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Waypoint> &waypoints) : Parser(tracks, routes, waypoints) QList<Waypoint> &waypoints) : Parser(tracks, routes, waypoints)
@ -12,11 +15,21 @@ FITParser::FITParser(QList<TrackData> &tracks, QList<RouteData> &routes,
memset(_defs, 0, sizeof(_defs)); memset(_defs, 0, sizeof(_defs));
} }
FITParser::~FITParser() void FITParser::clearDefinitions()
{ {
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++) {
if (_defs[i].fields) if (_defs[i].fields) {
delete[] _defs[i].fields; delete[] _defs[i].fields;
_defs[i].fields = 0;
}
}
}
void FITParser::warning(const char *text) const
{
const QFile *file = static_cast<QFile *>(_device);
fprintf(stderr, "%s:%d: %s\n", qPrintable(file->fileName()),
_len, text);
} }
bool FITParser::readData(char *data, size_t size) bool FITParser::readData(char *data, size_t size)
@ -162,6 +175,11 @@ bool FITParser::parseData(MessageDefinition *def, quint8 offset)
int i; int i;
if (!def->fields) {
_errorString = "Undefined data message";
return false;
}
_endian = def->endian; _endian = def->endian;
for (i = 0; i < def->num_fields; i++) { for (i = 0; i < def->num_fields; i++) {
@ -169,9 +187,9 @@ bool FITParser::parseData(MessageDefinition *def, quint8 offset)
if (!readField(field, val)) if (!readField(field, val))
return false; return false;
if (field->id == 253) if (field->id == TIMESTAMP_FIELD)
_timestamp = timestamp = val; _timestamp = timestamp = val;
else if (def->global_id == 20) { else if (def->global_id == RECORD_MESSAGE) {
switch (field->id) { switch (field->id) {
case 0: case 0:
if (val != 0x7fffffff) if (val != 0x7fffffff)
@ -206,9 +224,19 @@ bool FITParser::parseData(MessageDefinition *def, quint8 offset)
} }
} }
if (def->global_id == 20 && trackpoint.coordinates().isValid()) { if (def->global_id == RECORD_MESSAGE) {
trackpoint.setTimestamp(QDateTime::fromTime_t(timestamp + 631065600)); if (trackpoint.coordinates().isValid()) {
trackpoint.setTimestamp(QDateTime::fromTime_t(timestamp
+ 631065600));
_tracks.last().append(trackpoint); _tracks.last().append(trackpoint);
} else {
if (trackpoint.coordinates().isNull())
warning("Missing coordinates");
else {
_errorString = "Invalid coordinates";
return false;
}
}
} }
return true; return true;
@ -216,7 +244,7 @@ bool FITParser::parseData(MessageDefinition *def, quint8 offset)
bool FITParser::parseDataMessage(quint8 header) bool FITParser::parseDataMessage(quint8 header)
{ {
int local_id = header & 0x1f; int local_id = header & 0xf;
MessageDefinition* def = &_defs[local_id]; MessageDefinition* def = &_defs[local_id];
return parseData(def, 0); return parseData(def, 0);
} }
@ -235,6 +263,11 @@ bool FITParser::parseRecord()
if (!readValue(header)) if (!readValue(header))
return false; return false;
if (header & 0x20) {
_errorString = "Developer data not supported";
return false;
}
if (header & 0x80) if (header & 0x80)
return parseCompressedMessage(header); return parseCompressedMessage(header);
else if (header & 0x40) else if (header & 0x40)
@ -261,7 +294,7 @@ bool FITParser::parseHeader()
_len = qFromLittleEndian(hdr.data_size); _len = qFromLittleEndian(hdr.data_size);
if (hdr.header_size > 12) if (hdr.header_size > sizeof(hdr))
if (!readData((char *)&crc, sizeof(crc))) if (!readData((char *)&crc, sizeof(crc)))
return false; return false;
@ -273,6 +306,7 @@ bool FITParser::loadFile(QFile *file)
_device = file; _device = file;
_endian = 0; _endian = 0;
_timestamp = 0; _timestamp = 0;
bool ret = true;
if (!parseHeader()) if (!parseHeader())
return false; return false;
@ -280,8 +314,10 @@ bool FITParser::loadFile(QFile *file)
_tracks.append(TrackData()); _tracks.append(TrackData());
while (_len) while (_len)
if (!parseRecord()) if ((ret = parseRecord()) == false)
return false; break;
return true; clearDefinitions();
return ret;
} }

View File

@ -8,7 +8,7 @@ class FITParser : public Parser
public: public:
FITParser(QList<TrackData> &tracks, QList<RouteData> &routes, FITParser(QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Waypoint> &waypoints); QList<Waypoint> &waypoints);
~FITParser(); ~FITParser() {}
bool loadFile(QFile *file); bool loadFile(QFile *file);
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
@ -37,6 +37,9 @@ private:
} MessageDefinition; } MessageDefinition;
void warning(const char *text) const;
void clearDefinitions();
bool readData(char *data, size_t size); bool readData(char *data, size_t size);
template<class T> bool readValue(T &val); template<class T> bool readValue(T &val);
bool skipValue(size_t size); bool skipValue(size_t size);
@ -49,7 +52,6 @@ private:
bool parseData(MessageDefinition *def, quint8 offset); bool parseData(MessageDefinition *def, quint8 offset);
bool readField(Field *f, quint32 &val); bool readField(Field *f, quint32 &val);
QIODevice *_device; QIODevice *_device;
QString _errorString; QString _errorString;