From 591940b22593c9b6bf6f579db9bcee8a08fdd900 Mon Sep 17 00:00:00 2001 From: turboencabulator Date: Tue, 9 Nov 2021 16:44:16 -0600 Subject: [PATCH] Simplify the waveform reading code (#194) Combine the Android and non-Android implementations. Only difference now is the path to the waveform data. Remove arbitrarily-sized buffers and most C-style string handling function calls. Use native Qt string methods instead; this should improve memory safety. --- Desktop_Interface/functiongencontrol.cpp | 99 +++++-------------- .../ui_elements/espocombobox.cpp | 63 +++--------- 2 files changed, 35 insertions(+), 127 deletions(-) diff --git a/Desktop_Interface/functiongencontrol.cpp b/Desktop_Interface/functiongencontrol.cpp index 38963193..5ab08997 100644 --- a/Desktop_Interface/functiongencontrol.cpp +++ b/Desktop_Interface/functiongencontrol.cpp @@ -9,95 +9,40 @@ ChannelData const& SingleChannelController::getData() const { void SingleChannelController::waveformName(QString newName) { - qDebug() << "newName = " << newName; - newName.append(".tlw"); - - int length; - #ifdef PLATFORM_ANDROID - QString waveformFilePath("assets:/waveforms/"); - waveformFilePath.append(newName); - - QFile fptr(waveformFilePath); - bool success = fptr.open(QIODevice::ReadOnly); - - QByteArray line; - char lengthString[16]; - char divisibilityString[16]; - - line = fptr.readLine(); - strcpy(lengthString, line.data()); - sscanf(lengthString, "%d", &length); - qDebug() << "lengthString" << lengthString; - - line = fptr.readLine(); - strcpy(divisibilityString, line.data()); - sscanf(divisibilityString, "%d", &m_data.divisibility); - qDebug() << "divisibilityString" << divisibilityString; - - qDebug() << "Length = " << length; - qDebug() << "Divisibility = " << m_data.divisibility; - - QByteArray remainingData = fptr.readAll(); - char *dataString = remainingData.data(); - - m_data.samples.resize(length); - - int dummy; - char *dataStringCurrent = dataString; - for (int i = 0; i < length; i++) - { - sscanf(dataStringCurrent, "%d", &dummy); - dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1; - m_data.samples[i] = static_cast(dummy); - } - + QString path("assets:/waveforms/"); + QFile file(path.append(newName).append(".tlw")); #else + QString path = QCoreApplication::applicationDirPath(); + QFile file(path.append("/waveforms/").append(newName).append(".tlw")); +#endif - QByteArray filePath = QCoreApplication::applicationDirPath() - .append("/waveforms/").append(newName).toLocal8Bit(); + qDebug() << "opening" << file.fileName(); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + qFatal("could not open %s", qUtf8Printable(file.fileName())); - qDebug() << "opening" << filePath; - - FILE *fptr = fopen(filePath.constData(), "r"); - if (fptr == NULL) - qFatal("%s could not be opened!", filePath.constData()); - - char lengthString[16]; - fgets(lengthString, 5, fptr); - sscanf(lengthString, "%d", &length); - - char divisibilityString[16]; - //Bit of bullshit to deal with CRLF line endings on Mac. - do - { - fgets(divisibilityString, 5, fptr); - } - while ((divisibilityString[0] == '\r') || (divisibilityString[0] == '\n')); - - sscanf(divisibilityString, "%d", &m_data.divisibility); + int length = file.readLine().toInt(); + m_data.divisibility = file.readLine().toInt(); + QByteArray data = file.readLine().trimmed(); + file.close(); qDebug() << "Length = " << length; qDebug() << "Divisibility = " << m_data.divisibility; + // Length is redundant, could be derived from the sample list. + if (length != data.count('\t') + 1) + qFatal("%s: sample count mismatch", qUtf8Printable(file.fileName())); m_data.samples.resize(length); - char *dataString = (char *) malloc(length*5+1); - fgets(dataString, length*5+1, fptr); - - int dummy; - char *dataStringCurrent = dataString; - for (int i = 0; i < length; i++) - { - sscanf(dataStringCurrent, "%d", &dummy); - dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1; - m_data.samples[i] = static_cast(dummy); + data.replace('\t', '\0'); + const char *dataString = data.constData(); + QByteArray dataElem; + for (auto &sample : m_data.samples) { + dataElem.setRawData(dataString, strlen(dataString)); + sample = static_cast(dataElem.toInt()); + dataString += dataElem.size() + 1; } - free(dataString); - fclose(fptr); -#endif - double newMaxFreq = DAC_SPS / (length >> (m_data.divisibility - 1)); double newMinFreq = double(CLOCK_FREQ) / 1024.0 / 65535.0 / static_cast(length); diff --git a/Desktop_Interface/ui_elements/espocombobox.cpp b/Desktop_Interface/ui_elements/espocombobox.cpp index e5cc38a6..8832123c 100644 --- a/Desktop_Interface/ui_elements/espocombobox.cpp +++ b/Desktop_Interface/ui_elements/espocombobox.cpp @@ -5,59 +5,22 @@ espoComboBox::espoComboBox(QWidget *parent) : QComboBox(parent) } - void espoComboBox::readWaveformList(void) { - //This code gets the name of the current directory, regardless of platform. - //This is so the interface knows where to find the waveform data - //QDir *dir = new QDir(); - //qDebug() << dir->currentPath(); #ifdef PLATFORM_ANDROID - QFile qt_list("assets:/waveforms/_list.wfl"); - bool success = qt_list.open(QIODevice::ReadOnly | QIODevice::Text); - if(!success){ - qFatal("Could not load _list.wfl"); - } - - char nameBuffer[255]; - QStringList *newNames = new QStringList(); - - while (!qt_list.atEnd()) { - QByteArray line = qt_list.readLine(); - strcpy(nameBuffer, line.data()); - strtok(nameBuffer, "\n\r"); - newNames->append(nameBuffer); - qDebug() << nameBuffer; - } - this->addItems(*(newNames)); - delete newNames; - qt_list.close(); + QFile file("assets:/waveforms/_list.wfl"); #else - QString dirString = QCoreApplication::applicationDirPath(); - dirString.append("/waveforms/_list.wfl"); - QByteArray array = dirString.toLocal8Bit(); - char* buffer = array.data(); - //qDebug() << buffer; - - qDebug() << "Attempting to open" << dirString; - - FILE *listPtr = fopen(buffer, "r"); - QStringList *newNames = new QStringList(); - char nameBuffer[255]; - - if(listPtr == NULL){ - qFatal("Could not load _list.wfl"); - } - - while (fgets(nameBuffer, sizeof(nameBuffer), listPtr) != NULL){ - qDebug() << "nameBuffer = " << nameBuffer; - strtok(nameBuffer, "\n\r"); - newNames->append(nameBuffer); - } - this->addItems(*(newNames)); - delete newNames; - - fclose(listPtr); + QString path = QCoreApplication::applicationDirPath(); + QFile file(path.append("/waveforms/_list.wfl")); #endif - qDebug() << "List loaded!!"; + + qDebug() << "opening" << file.fileName(); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + qFatal("could not open %s", qUtf8Printable(file.fileName())); + + QStringList newNames; + while (!file.atEnd()) + newNames.append(file.readLine().trimmed()); + this->addItems(newNames); + file.close(); }