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.
This commit is contained in:
turboencabulator 2021-11-09 16:44:16 -06:00 committed by GitHub
parent 1b45b0d112
commit 591940b225
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 127 deletions

View File

@ -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<uint8_t>(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<uint8_t>(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<uint8_t>(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<double>(length);

View File

@ -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();
}