summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--csv/csv.cpp131
-rw-r--r--csv/csv.h25
-rw-r--r--proto-ft/ftnoir_protocol_ft.cpp2
-rw-r--r--proto-wine/ftnoir_protocol_wine.cpp2
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)
diff --git a/csv/csv.h b/csv/csv.h
index 8beaeb54..15f279d6 100644
--- a/csv/csv.h
+++ b/csv/csv.h
@@ -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;
}