diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2025-04-29 18:50:58 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2025-05-16 08:54:14 +0200 |
commit | f09e8fb819e4763e24d81e5edd0bb1c9afd44d3e (patch) | |
tree | 2b175f9e15090e7582faf04c57e2c605f78034cd | |
parent | bd0172a4255ad9a1af14ad75f8ff31371a46c11e (diff) |
switch csv parser to using non-deprecated qt6 api
-rw-r--r-- | csv/csv.cpp | 131 | ||||
-rw-r--r-- | csv/csv.h | 25 | ||||
-rw-r--r-- | proto-ft/ftnoir_protocol_ft.cpp | 2 | ||||
-rw-r--r-- | proto-wine/ftnoir_protocol_wine.cpp | 2 |
4 files changed, 44 insertions, 116 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) @@ -1,26 +1,5 @@ #pragma once -#include <QtGlobal> -#include <QObject> -#include <QStringList> -#include <QIODevice> -#include <QtCore5Compat/QTextCodec> -#include <QtCore5Compat/QRegExp> -#include <QtGlobal> -class CSV -{ -public: - QString readLine(); - bool parseLine(QStringList& ret); +#include <QString> - static bool getGameData(int gameID, unsigned char* table, QString& gamename); -private: - CSV(QIODevice* device); - - QIODevice* m_device; - QString m_string; - int m_pos; - - static QTextCodec const* const m_codec; - static const QRegExp m_rx, m_rx2; -}; +bool getGameData(int gameID, unsigned char* table, QString& gamename); diff --git a/proto-ft/ftnoir_protocol_ft.cpp b/proto-ft/ftnoir_protocol_ft.cpp index 7f710621..c7501262 100644 --- a/proto-ft/ftnoir_protocol_ft.cpp +++ b/proto-ft/ftnoir_protocol_ft.cpp @@ -112,7 +112,7 @@ void freetrack::pose(const double* headpose, const double* raw) t.ints[0] = 0; t.ints[1] = 0; - (void)CSV::getGameData(id, t.table, gamename); + (void)getGameData(id, t.table, gamename); { // FTHeap pMemData happens to be aligned on a page boundary by virtue of diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index bae02b06..66f7e0fb 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -51,7 +51,7 @@ void wine::pose(const double *headpose, const double*) QMutexLocker foo(&game_name_mutex); /* only EZCA for FSX requires dummy process, and FSX doesn't work on Linux */ /* memory-hacks DLL can't be loaded into a Linux process, either */ - CSV::getGameData(shm->gameid, shm->table, gamename); + getGameData(shm->gameid, shm->table, gamename); gameid = shm->gameid2 = shm->gameid; connected_game = gamename; } |