From 2f33ea8cce30ccffa747f44c1e71b6f4e592f453 Mon Sep 17 00:00:00 2001 From: Scott Klum Date: Tue, 4 Mar 2014 15:46:28 -0500 Subject: [PATCH] Generalized EBTS support --- openbr/plugins/format.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------ 1 file changed, 108 insertions(+), 42 deletions(-) diff --git a/openbr/plugins/format.cpp b/openbr/plugins/format.cpp index 152aab6..ca2d6e1 100644 --- a/openbr/plugins/format.cpp +++ b/openbr/plugins/format.cpp @@ -780,22 +780,26 @@ BR_REGISTER(Format, scoresFormat) class ebtsFormat : public Format { Q_OBJECT -; - QString textFieldValue(const QByteArray &byteArray, const QString &fieldNumber, int from = 0) const - { - // Find the field, skip the number bytes, and account for the semicolon - int fieldPosition = byteArray.indexOf(fieldNumber, from) + fieldNumber.size() + 1; - int sepPosition = byteArray.indexOf(QChar(0x1D),fieldPosition); - return byteArray.mid(fieldPosition,sepPosition-fieldPosition); - } + struct Field { + float type; + QList data; + }; + + struct Record { + int type; + quint32 bytes; + int position; // Starting position of record - int recordBytes(const QByteArray &byteArray, const float fieldNumber, int from = 0) const + QList fields; + }; + + quint32 recordBytes(const QByteArray &byteArray, const float recordType, int from) const { bool ok; - int size; + quint32 size; - if (fieldNumber == 4 || fieldNumber == 7) { + if (recordType == 4 || recordType == 7) { // read first four bytes ok = true; size = qFromBigEndian((const uchar*)byteArray.mid(from,4).constData()); @@ -807,16 +811,47 @@ class ebtsFormat : public Format return ok ? size : -1; } - QList parseRecord(const QByteArray &byteArray, const int from, const int bytes) const + void parseRecord(const QByteArray &byteArray, Record &record) const { - return byteArray.mid(from,bytes).split(QChar(0x1D).toLatin1()); + if (record.type == 4 || record.type == 7) { + // Just a binary blob + // Read everything after the first four bytes + // Not current supported + } else { + // Continue reading fields until we get all the data + int position = record.position; + float dataField = .999; + while (position < record.position + record.bytes) { + int index = byteArray.indexOf(QChar(0x1D), position); + Field field = parseField(byteArray.mid(position, index-position),QChar(0x1F)); + if (field.type - dataField == record.type ) { + // Data begin after the field identifier and the colon + int dataBegin = byteArray.indexOf(':', position)+1; + field.data.clear(); + field.data.append(byteArray.mid(dataBegin, record.bytes-(dataBegin-record.position))); + + // Data fields are always last in the record + record.fields.append(field); + break; + } + // Advance the position accounting for the separator + position += index-position+1; + record.fields.append(field); + } + } } - QList parseField(const QByteArray &byteArray, const QChar &sep) const + Field parseField(const QByteArray &byteArray, const QChar &sep) const { - QByteArray data = byteArray.split(':').last(); + bool ok; + Field f; - return data.split(sep.toLatin1()); + QList data = byteArray.split(':'); + + f.type = data.first().toFloat(&ok); + f.data = data.last().split(sep.toLatin1()); + + return f; } Template read() const @@ -828,40 +863,73 @@ class ebtsFormat : public Format Mat m; + QList records; + // Read the type one record (every EBTS file will have one of these) - int recordOneBytes = recordBytes(byteArray,1); - QList recordOne = parseRecord(byteArray,0,recordOneBytes); + Record r1; + r1.type = 1; + r1.position = 0; + r1.bytes = recordBytes(byteArray,r1.type,r1.position); + + // The fields in a type 1 record are strictly defined + QList data = byteArray.mid(r1.position,r1.bytes).split(QChar(0x1D).toLatin1()); + foreach (const QByteArray &datum, data) { + Field f = parseField(datum,QChar(0x1F)); + r1.fields.append(f); + } - // The third field (1.03/1.003) will have record identifiers for the remaining - // portion of the transaction - QList recordOneFieldThree = parseField(recordOne.at(2),QChar(0x1F)); + records.append(r1); - QList recordTypes; + // Read the type two record (every EBTS file will have one of these) + Record r2; + r2.type = 2; + r2.position = r1.bytes; + r2.bytes = recordBytes(byteArray,r2.type,r2.position); - for (int i=2; i recordTwo = parseRecord(byteArray,recordOneBytes,recordTwoBytes); - - QList recordSizes; - int startingPosition = recordOneBytes + recordTwoBytes; - foreach(int i, recordTypes) { - // Maybe switch to position - int recordSize = recordBytes(byteArray,i,startingPosition); - qDebug() << i << recordSize; - recordSizes.append(recordSize); - startingPosition += recordSize; + + records.append(r2); + + // The third field of the first record contains informations about all the remaining records in the transaction + // We don't care about the first two and the final items + for (int i=2; i frontalIdxs; + int position = r1.bytes + r2.bytes; + for (int i=2; i