Improved CSV parser.

This commit is contained in:
LoRd_MuldeR 2012-01-05 21:08:04 +01:00
parent f857054dda
commit 38ad322fbd
3 changed files with 60 additions and 34 deletions

View File

@ -29,8 +29,8 @@
#define VER_LAMEXP_MINOR_HI 0 #define VER_LAMEXP_MINOR_HI 0
#define VER_LAMEXP_MINOR_LO 4 #define VER_LAMEXP_MINOR_LO 4
#define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 13 #define VER_LAMEXP_PATCH 14
#define VER_LAMEXP_BUILD 870 #define VER_LAMEXP_BUILD 872
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!) // Tool versions (minimum expected versions!)

View File

@ -370,24 +370,41 @@ int FileListModel::importFromCsv(QWidget *parent, const QString &inFile)
stream.setAutoDetectUnicode(false); stream.setAutoDetectUnicode(false);
stream.setCodec(codec); stream.setCodec(codec);
QStringList header = stream.readLine().simplified().split(";", QString::KeepEmptyParts); QString headerLine = stream.readLine().simplified();
while(headerLine.isEmpty())
{
if(stream.atEnd())
{
qWarning("The file appears to be empty!");
return CsvError_FileRead;
}
qWarning("Skipping a blank line at beginning of CSV file!");
headerLine = stream.readLine().simplified();
}
QStringList header = headerLine.split(";", QString::KeepEmptyParts);
const int nCols = header.count(); const int nCols = header.count();
const int nFiles = m_fileList.count(); const int nFiles = m_fileList.count();
if(nCols < 1) if(nCols < 1)
{ {
qWarning("Header appears to be empty!");
return CsvError_FileRead; return CsvError_FileRead;
} }
for(int i = 0; i < nCols; i++)
{
header[i] = header[i].trimmed();
}
bool *ignore = new bool[nCols]; bool *ignore = new bool[nCols];
memset(ignore, 0, sizeof(bool) * nCols); memset(ignore, 0, sizeof(bool) * nCols);
for(int i = 0; i < nCols; i++)
{
if((header[i] = header[i].trimmed()).isEmpty())
{
ignore[i] = true;
}
}
//----------------------// //----------------------//
for(int i = 0; i < nFiles; i++) for(int i = 0; i < nFiles; i++)
@ -398,9 +415,17 @@ int FileListModel::importFromCsv(QWidget *parent, const QString &inFile)
return CsvError_Incomplete; return CsvError_Incomplete;
} }
QStringList line = stream.readLine().split(";", QString::KeepEmptyParts); QString line = stream.readLine().simplified();
if(line.isEmpty())
{
qWarning("Skipping a blank line in CSV file!");
continue;
}
QStringList data = line.split(";", QString::KeepEmptyParts);
if(line.count() < header.count()) if(data.count() < header.count())
{ {
qWarning("Skipping an incomplete line in CSV file!"); qWarning("Skipping an incomplete line in CSV file!");
continue; continue;
@ -415,63 +440,52 @@ int FileListModel::importFromCsv(QWidget *parent, const QString &inFile)
else if(CHECK_HDR(header.at(j), "POSITION")) else if(CHECK_HDR(header.at(j), "POSITION"))
{ {
bool ok = false; bool ok = false;
unsigned int temp = line.at(j).trimmed().toUInt(&ok); unsigned int temp = data.at(j).trimmed().toUInt(&ok);
if(ok) m_fileList[i].setFilePosition(temp); if(ok) m_fileList[i].setFilePosition(temp);
} }
else if(CHECK_HDR(header.at(j), "TITLE")) else if(CHECK_HDR(header.at(j), "TITLE"))
{ {
QString temp = line.at(j).trimmed(); QString temp = data.at(j).trimmed();
if(!temp.isEmpty()) m_fileList[i].setFileName(temp); if(!temp.isEmpty()) m_fileList[i].setFileName(temp);
} }
else if(CHECK_HDR(header.at(j), "ARTIST")) else if(CHECK_HDR(header.at(j), "ARTIST"))
{ {
QString temp = line.at(j).trimmed(); QString temp = data.at(j).trimmed();
if(!temp.isEmpty()) m_fileList[i].setFileArtist(temp); if(!temp.isEmpty()) m_fileList[i].setFileArtist(temp);
} }
else if(CHECK_HDR(header.at(j), "ALBUM")) else if(CHECK_HDR(header.at(j), "ALBUM"))
{ {
QString temp = line.at(j).trimmed(); QString temp = data.at(j).trimmed();
if(!temp.isEmpty()) m_fileList[i].setFileAlbum(temp); if(!temp.isEmpty()) m_fileList[i].setFileAlbum(temp);
} }
else if(CHECK_HDR(header.at(j), "GENRE")) else if(CHECK_HDR(header.at(j), "GENRE"))
{ {
QString temp = line.at(j).trimmed(); QString temp = data.at(j).trimmed();
if(!temp.isEmpty()) m_fileList[i].setFileGenre(temp); if(!temp.isEmpty()) m_fileList[i].setFileGenre(temp);
} }
else if(CHECK_HDR(header.at(j), "YEAR")) else if(CHECK_HDR(header.at(j), "YEAR"))
{ {
bool ok = false; bool ok = false;
unsigned int temp = line.at(j).trimmed().toUInt(&ok); unsigned int temp = data.at(j).trimmed().toUInt(&ok);
if(ok) m_fileList[i].setFileYear(temp); if(ok) m_fileList[i].setFileYear(temp);
} }
else if(CHECK_HDR(header.at(j), "COMMENT")) else if(CHECK_HDR(header.at(j), "COMMENT"))
{ {
QString temp = line.at(j).trimmed(); QString temp = data.at(j).trimmed();
if(!temp.isEmpty()) m_fileList[i].setFileComment(temp); if(!temp.isEmpty()) m_fileList[i].setFileComment(temp);
} }
else else
{ {
qWarning("Unkonw field '%s' will be ignored!", header.at(j).toUtf8().constData()); qWarning("Unkonw field '%s' will be ignored!", header.at(j).toUtf8().constData());
ignore[j] = true; ignore[j] = true;
if(!checkArray(ignore, false, nCols))
{
qWarning("No known fields left, aborting!");
return CsvError_NoTags;
}
} }
} }
bool noFieldsLeft = true;
for(int j = 0; j < nCols; j++)
{
if(!ignore[j])
{
noFieldsLeft = false;
break;
}
}
if(noFieldsLeft)
{
LAMEXP_DELETE_ARRAY(ignore);
return CsvError_NoTags;
}
} }
//----------------------// //----------------------//
@ -479,3 +493,13 @@ int FileListModel::importFromCsv(QWidget *parent, const QString &inFile)
LAMEXP_DELETE_ARRAY(ignore); LAMEXP_DELETE_ARRAY(ignore);
return CsvError_OK; return CsvError_OK;
} }
bool FileListModel::checkArray(const bool *a, const bool val, size_t len)
{
for(size_t i = 0; i < len; i++)
{
if(a[i] == val) return true;
}
return false;
}

View File

@ -72,4 +72,6 @@ public slots:
private: private:
QList<AudioFileModel> m_fileList; QList<AudioFileModel> m_fileList;
const QIcon m_fileIcon; const QIcon m_fileIcon;
static bool checkArray(const bool *a, const bool val, size_t len);
}; };