diff options
Diffstat (limited to 'csv')
-rw-r--r-- | csv/csv.cpp | 136 | ||||
-rw-r--r-- | csv/csv.h | 25 | ||||
-rw-r--r-- | csv/lang/de_DE.ts | 4 | ||||
-rw-r--r-- | csv/lang/zh_CN.ts | 2 |
4 files changed, 53 insertions, 114 deletions
diff --git a/csv/csv.cpp b/csv/csv.cpp index a1f62dc0..79841bea 100644 --- a/csv/csv.cpp +++ b/csv/csv.cpp @@ -11,84 +11,42 @@ #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 <QByteArrayView> #include <QDebug> -#include <utility> -#include <algorithm> - -const QTextCodec* const CSV::m_codec = QTextCodec::codecForName("System"); -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); - - 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; + 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); +}; - 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 +54,34 @@ 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}; + QStringList gameLine; gameLine.reserve(8); + unsigned lineno = 0; + // TODO QIODevice::readLineInto() is Qt 6.9 - sh 20250515 + char buf[256]; - CSV csv(&file); + while (auto sz = file.readLine(buf, sizeof(buf))) + { + QString line = decoder.decode(QByteArrayView{buf, sz}); - unsigned tmp[8]; - unsigned fuzz[3]; + if (line.isEmpty()) + break; + chomp(line); + if (line.isEmpty()) + continue; - 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 +91,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 +115,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 <QTextCodec> -#include <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/csv/lang/de_DE.ts b/csv/lang/de_DE.ts new file mode 100644 index 00000000..1552582e --- /dev/null +++ b/csv/lang/de_DE.ts @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="de_DE"> +</TS> diff --git a/csv/lang/zh_CN.ts b/csv/lang/zh_CN.ts index 6401616d..e5ca8aa9 100644 --- a/csv/lang/zh_CN.ts +++ b/csv/lang/zh_CN.ts @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> -<TS version="2.1"> +<TS version="2.1" language="zh_CN"> </TS> |