summaryrefslogtreecommitdiffhomepage
path: root/csv/csv.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2025-04-29 18:50:58 +0200
committerStanislaw Halik <sthalik@misaki.pl>2025-05-16 08:54:14 +0200
commitf09e8fb819e4763e24d81e5edd0bb1c9afd44d3e (patch)
tree2b175f9e15090e7582faf04c57e2c605f78034cd /csv/csv.cpp
parentbd0172a4255ad9a1af14ad75f8ff31371a46c11e (diff)
switch csv parser to using non-deprecated qt6 api
Diffstat (limited to 'csv/csv.cpp')
-rw-r--r--csv/csv.cpp131
1 files changed, 40 insertions, 91 deletions
diff --git a/csv/csv.cpp b/csv/csv.cpp
index 6b4d0bcd..7361fdd1 100644
--- a/csv/csv.cpp
+++ b/csv/csv.cpp
@@ -11,84 +11,41 @@
#include "csv.h"
#include "compat/library-path.hpp"
-#include <QTextDecoder>
-#include <QFile>
+#include <utility>
+#include <cstdio>
+#include <QByteArray>
#include <QString>
+#include <QStringDecoder>
+#include <QFile>
#include <QDebug>
-#include <utility>
-#include <algorithm>
-
-const QTextCodec* const CSV::m_codec = QTextCodec::codecForName("UTF-8");
-const QRegExp CSV::m_rx = QRegExp(QString("((?:(?:[^;\\n]*;?)|(?:\"[^\"]*\";?))*)?\\n?"));
-const QRegExp CSV::m_rx2 = QRegExp(QString("(?:\"([^\"]*)\";?)|(?:([^;]*);?)?"));
+namespace {
-CSV::CSV(QIODevice* device) :
- m_device(device),
- m_pos(0)
+void chomp(QString& str)
{
- if (m_device && m_device->isReadable())
+ if (!str.isEmpty() && str.back() == '\n')
{
- QTextDecoder dec(m_codec);
- m_string = dec.toUnicode(m_device->readAll());
+ str.chop(1);
+ if (!str.isEmpty() && str.back() == '\r')
+ str.chop(1);
}
}
-QString CSV::readLine()
+auto do_scanf(QLatin1StringView s, unsigned(&tmp)[8])
{
- QString line;
-
- if ((m_pos = m_rx.indexIn(m_string,m_pos)) != -1)
- {
- line = m_rx.cap(1);
- m_pos += m_rx.matchedLength();
- }
- else
- {
- const QChar lf(QChar::LineFeed);
+ unsigned fuzz[3];
+ return std::sscanf(s.constData(),
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ fuzz + 2,
+ fuzz + 0,
+ tmp + 3, tmp + 2, tmp + 1, tmp + 0,
+ tmp + 7, tmp + 6, tmp + 5, tmp + 4,
+ fuzz + 1);
+};
- while (m_pos < m_string.length())
- if (m_string[m_pos++] == lf)
- break;
- }
- return line;
}
-bool CSV::parseLine(QStringList& ret)
-{
- QString line(readLine());
-
- QStringList list;
- int pos2 = 0;
-
- if (line.size() == 0)
- {
- ret = QStringList();
- return m_device->size() > m_pos;
- }
- else
- {
- while (line.size() > pos2 && (pos2 = m_rx2.indexIn(line, pos2)) != -1)
- {
- QString col;
- if (m_rx2.cap(1).size() > 0)
- col = m_rx2.cap(1);
- else if (m_rx2.cap(2).size() > 0)
- col = m_rx2.cap(2);
-
- list << col;
-
- if (col.size())
- pos2 += m_rx2.matchedLength();
- else
- pos2++;
- }
- }
- ret = std::move(list);
- return true;
-}
-
-bool CSV::getGameData(int id, unsigned char* table, QString& gamename)
+bool getGameData(int id, unsigned char* table, QString& gamename)
{
for (int i = 0; i < 8; i++)
table[i] = 0;
@@ -96,28 +53,28 @@ bool CSV::getGameData(int id, unsigned char* table, QString& gamename)
if (id != 0)
qDebug() << "csv: lookup game id" << id;
- QString id_str(QString::number(id));
-
static const QString csv_path(OPENTRACK_BASE_PATH +
OPENTRACK_DOC_PATH "settings/facetracknoir supported games.csv");
+ auto id_str = QString::number(id);
QFile file(csv_path);
-
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ if (!file.open(QIODevice::ReadOnly))
{
qDebug() << "csv: can't open game list for freetrack protocol!";
return false;
}
+ QStringDecoder decoder{QStringConverter::Encoding::Utf8};
+ QByteArray lineʹ; lineʹ.reserve(255);
+ QStringList gameLine; gameLine.reserve(8);
+ unsigned lineno = 0;
- CSV csv(&file);
-
- unsigned tmp[8];
- unsigned fuzz[3];
+ while (file.readLineInto(&lineʹ))
+ {
+ QString line = decoder.decode(lineʹ);
+ chomp(line);
- QStringList gameLine;
+ gameLine = line.split(';', Qt::SplitBehaviorFlags::KeepEmptyParts);
- for (int lineno = 0; csv.parseLine(gameLine); lineno++)
- {
//qDebug() << "Column 0: " << gameLine.at(0); // No.
//qDebug() << "Column 1: " << gameLine.at(1); // Game Name
//qDebug() << "Column 2: " << gameLine.at(2); // Game Protocol
@@ -127,28 +84,18 @@ bool CSV::getGameData(int id, unsigned char* table, QString& gamename)
//qDebug() << "Column 6: " << gameLine.at(6); // International ID
//qDebug() << "Column 7: " << gameLine.at(7); // FaceTrackNoIR ID
- if (gameLine.count() == 8)
+ if (gameLine.size() == 8)
{
- if (gameLine.at(6).compare(id_str, Qt::CaseInsensitive) == 0)
+ if (gameLine[6] == id_str)
{
const QString& proto = gameLine[3];
QString& name = gameLine[1];
-
const QByteArray id_cstr = gameLine[7].toLatin1();
-
- auto do_scanf = [&]() {
- return sscanf(id_cstr.constData(),
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- fuzz + 2,
- fuzz + 0,
- tmp + 3, tmp + 2, tmp + 1, tmp + 0,
- tmp + 7, tmp + 6, tmp + 5, tmp + 4,
- fuzz + 1);
- };
+ unsigned tmp[8] {};
if (proto == QStringLiteral("V160") || id_cstr.length() != 22)
(void)0;
- else if (id_cstr.length() != 22 || do_scanf() != 11)
+ else if (id_cstr.length() != 22 || do_scanf(QLatin1StringView(id_cstr), tmp) != 11)
qDebug() << "scanf failed" << lineno;
else
{
@@ -161,7 +108,9 @@ bool CSV::getGameData(int id, unsigned char* table, QString& gamename)
}
}
else
- qDebug() << "malformed csv line" << lineno;
+ qDebug() << "csv wrong column count" << gameLine.size();
+
+ lineno++;
}
if (id)