Fix regression in ADIF parser that caused failure with missing header

Improved  robustness  of  the  ADIF parser  and  re-factored  to  more
idiomatic C++.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@8087 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2017-09-16 20:27:05 +00:00
parent 70675ca098
commit 41a60d4f0c
2 changed files with 52 additions and 28 deletions

View File

@ -18,17 +18,17 @@ void ADIF::init(QString const& filename)
}
QString ADIF::_extractField(QString const& line, QString const& fieldName) const
QString ADIF::extractField(QString const& record, QString const& fieldName) const
{
int fieldNameIndex = line.indexOf(fieldName,0,Qt::CaseInsensitive);
int fieldNameIndex = record.indexOf (fieldName + ':', 0, Qt::CaseInsensitive);
if (fieldNameIndex >=0)
{
int closingBracketIndex = line.indexOf('>',fieldNameIndex);
int fieldLengthIndex = line.indexOf(':',fieldNameIndex); // find the size delimiter
int closingBracketIndex = record.indexOf('>',fieldNameIndex);
int fieldLengthIndex = record.indexOf(':',fieldNameIndex); // find the size delimiter
int dataTypeIndex = -1;
if (fieldLengthIndex >= 0)
{
dataTypeIndex = line.indexOf(':',fieldLengthIndex+1); // check for a second : indicating there is a data type
dataTypeIndex = record.indexOf(':',fieldLengthIndex+1); // check for a second : indicating there is a data type
if (dataTypeIndex > closingBracketIndex)
dataTypeIndex = -1; // second : was found but it was beyond the closing >
}
@ -38,11 +38,11 @@ QString ADIF::_extractField(QString const& line, QString const& fieldName) const
int fieldLengthCharCount = closingBracketIndex - fieldLengthIndex -1;
if (dataTypeIndex >= 0)
fieldLengthCharCount -= 2; // data type indicator is always a colon followed by a single character
QString fieldLengthString = line.mid(fieldLengthIndex+1,fieldLengthCharCount);
QString fieldLengthString = record.mid(fieldLengthIndex+1,fieldLengthCharCount);
int fieldLength = fieldLengthString.toInt();
if (fieldLength > 0)
{
QString field = line.mid(closingBracketIndex+1,fieldLength);
QString field = record.mid(closingBracketIndex+1,fieldLength);
return field;
}
}
@ -59,27 +59,48 @@ void ADIF::load()
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
QString record;
QString buffer;
bool pre_read {false};
int end_position {-1};
// skip header record
while (!in.atEnd () && !record.contains ("<EOH>", Qt::CaseInsensitive))
// skip optional header record
do
{
record += in.readLine ();
buffer += in.readLine () + '\n';
if (buffer.startsWith (QChar {'<'})) // denotes no header
{
pre_read = true;
}
while ( !in.atEnd() )
else
{
record.clear ();
while (!in.atEnd () && !record.contains ("<EOR>", Qt::CaseInsensitive))
{
record += in.readLine ();
end_position = buffer.indexOf ("<EOH>", 0, Qt::CaseInsensitive);
}
QSO q;
q.call = _extractField(record,"CALL:");
q.band = _extractField(record,"BAND:");
q.mode = _extractField(record,"MODE:");
q.date = _extractField(record,"QSO_DATE:");
if (q.call != "")
_data.insert(q.call,q);
}
while (!in.atEnd () && !pre_read && end_position < 0);
if (!pre_read) // found header
{
buffer.remove (0, end_position + 5);
}
while (buffer.size () || !in.atEnd ())
{
do
{
end_position = buffer.indexOf ("<EOR>", 0, Qt::CaseInsensitive);
if (!in.atEnd () && end_position < 0)
{
buffer += in.readLine () + '\n';
}
}
while (!in.atEnd () && end_position < 0);
int record_length {end_position >= 0 ? end_position + 5 : -1};
auto record = buffer.left (record_length).trimmed ();
auto next_record = buffer.indexOf (QChar {'<'}, record_length);
buffer.remove (0, next_record >=0 ? next_record : buffer.size ());
record = record.mid (record.indexOf (QChar {'<'}));
add (extractField (record, "CALL")
, extractField (record, "BAND")
, extractField (record, "MODE")
, extractField (record, "QSO_DATE"));
}
inputFile.close ();
}
@ -93,9 +114,12 @@ void ADIF::add(QString const& call, QString const& band, QString const& mode, QS
q.band = band;
q.mode = mode;
q.date = date;
if (q.call.size ())
{
_data.insert(q.call,q);
// qDebug() << "Added as worked:" << call << band << mode << date;
}
}
// return true if in the log same band and mode (where JT65 == JT9)
bool ADIF::match(QString const& call, QString const& band, QString const& mode) const

View File

@ -43,7 +43,7 @@ class ADIF
QMultiHash<QString, QSO> _data;
QString _filename;
QString _extractField(QString const& line, QString const& fieldName) const;
QString extractField(QString const& line, QString const& fieldName) const;
};