From 335224cec4bca1ce3552bee7d79eeaf520cf3bd3 Mon Sep 17 00:00:00 2001 From: Rainer Clasen Date: Fri, 17 Jun 2011 13:06:56 +0200 Subject: [PATCH] Fit: support big/little endian data ... on both, big and little endian machines. Fit reader only supported little endian data on little endian machines. All values read from FIT files are now swapped (if neccessary) according to file and system endianess. fixes #287 --- src/FitRideFile.cpp | 65 ++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/src/FitRideFile.cpp b/src/FitRideFile.cpp index 119d18112..c0bc7d022 100644 --- a/src/FitRideFile.cpp +++ b/src/FitRideFile.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ struct FitField { struct FitDefinition { int global_msg_num; + bool is_big_endian; std::vector fields; }; @@ -95,22 +97,26 @@ struct FitFileReaderState return 0xff & c; } - int read_short(int *count = NULL) { + int read_short(bool is_big_endian, int *count = NULL) { uint16_t s; if (file.read(reinterpret_cast(&s), 2) != 2) throw TruncatedRead(); if (count) (*count) += 2; - return 0xffff & s; + return 0xffff & ( is_big_endian + ? qFromBigEndian( s ) + : qFromLittleEndian( s ) ); } - int read_long(int *count = NULL) { + int read_long(bool is_big_endian, int *count = NULL) { uint32_t l; if (file.read(reinterpret_cast(&l), 4) != 4) throw TruncatedRead(); if (count) (*count) += 4; - return l; + return is_big_endian + ? qFromBigEndian( l ) + : qFromLittleEndian( l ); } void decodeFileId(const FitDefinition &def, int, const std::vector values) { @@ -318,42 +324,38 @@ struct FitFileReaderState if (!(header_byte & 0x80) && (header_byte & 0x40)) { // Definition record int local_msg_type = header_byte & 0xf; - int reserved = read_byte(&count); (void) reserved; // unused - int architecture = read_byte(&count); - int global_msg_num = read_short(&count); - /*printf("definition: local type %d\n", - local_msg_type);*/ - if (architecture != 0) { - errors << QString("unsupported architecture %1").arg(architecture); - stop = true; - return count; - } - int num_fields = read_byte(&count); - // printf(", %d num_fields:\n", num_fields); + local_msg_types.insert(local_msg_type, FitDefinition()); FitDefinition &def = local_msg_types[local_msg_type]; - def.global_msg_num = global_msg_num; + + int reserved = read_byte(&count); (void) reserved; // unused + def.is_big_endian = read_byte(&count); + def.global_msg_num = read_short(def.is_big_endian, &count); + int num_fields = read_byte(&count); + /*printf("definition: local type %d\n", + local_msg_type);*/ + // printf(", %d num_fields:\n", num_fields); + for (int i = 0; i < num_fields; ++i) { def.fields.push_back(FitField()); FitField &field = def.fields.back(); - int field_def_num = read_byte(&count); - int field_size = read_byte(&count); - field.size = field_size; + + field.num = read_byte(&count); + field.size = read_byte(&count); int base_type = read_byte(&count); - int base_type_num = base_type & 0x1f; - if (base_type_num >= base_type_names_size) { - errors << QString("unknown base type %1").arg(base_type_num); + field.type = base_type & 0x1f; + if (field.type >= base_type_names_size) { + errors << QString("unknown base type %1").arg(field.type); stop = true; return count; } - field.type = base_type_num; - field.num = field_def_num; /*printf(" field %d: %d bytes, num %d, type %s, %s endianness\n", i, field_size, field_def_num, base_type_names[base_type_num], (base_type & 0x80) ? "with" : "without");*/ } } else { + // Data record int local_msg_type = 0; int time_offset = 0; if (header_byte & 0x80) { @@ -376,8 +378,8 @@ struct FitFileReaderState int v; switch (field.size) { case 1: v = read_byte(&count); break; - case 2: v = read_short(&count); break; - case 4: v = read_long(&count); break; + case 2: v = read_short(def.is_big_endian, &count); break; + case 4: v = read_long(def.is_big_endian, &count); break; default: errors << QString("unsupported field size %1").arg(field.size); stop = true; @@ -435,9 +437,9 @@ struct FitFileReaderState } int protocol_version = read_byte(); (void) protocol_version; - int profile_version = read_short(); // not sure what to do with this - (void) profile_version; - int data_size = read_long(); // always little endian + int profile_version = read_short(false); // always littleEndian + (void) profile_version; // not sure what to do with this + int data_size = read_long(false); // always littleEndian char fit_str[5]; if (file.read(fit_str, 4) != 4) { errors << "truncated header"; @@ -466,7 +468,7 @@ struct FitFileReaderState return NULL; } else { - int crc = read_short(); + int crc = read_short( false ); // always littleEndian (void) crc; foreach(int num, unknown_global_msg_nums) { errors << QString("unknown global message number %1; ignoring it").arg(num); @@ -484,3 +486,4 @@ RideFile *FitFileReader::openRideFile(QFile &file, QStringList &errors) const return state->run(); } +// vi:expandtab tabstop=4 shiftwidth=4