From 36a6956c79aff6ef61d48a0419d2c5ba097f50c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl=20Restori?= Date: Wed, 20 Aug 2014 13:38:44 +0200 Subject: [PATCH] Add DecoderThread --- QBrainfuck.pro | 6 ++- decoderthread.cpp | 112 ++++++++++++++++++++++++++++++++++++++++ decoderthread.h | 31 +++++++++++ qbrainfuck.cpp | 128 ++++------------------------------------------ qbrainfuck.h | 9 ++-- 5 files changed, 162 insertions(+), 124 deletions(-) create mode 100644 decoderthread.cpp create mode 100644 decoderthread.h diff --git a/QBrainfuck.pro b/QBrainfuck.pro index 2b28c89..c706a38 100644 --- a/QBrainfuck.pro +++ b/QBrainfuck.pro @@ -13,8 +13,10 @@ TEMPLATE = app SOURCES += main.cpp\ - qbrainfuck.cpp + qbrainfuck.cpp \ + decoderthread.cpp -HEADERS += qbrainfuck.h +HEADERS += qbrainfuck.h \ + decoderthread.h FORMS += qbrainfuck.ui diff --git a/decoderthread.cpp b/decoderthread.cpp new file mode 100644 index 0000000..dc6236f --- /dev/null +++ b/decoderthread.cpp @@ -0,0 +1,112 @@ +#include "decoderthread.h" + +DecoderThread::DecoderThread(QObject *parent) : + QThread(parent) +{ +} + +DecoderThread::~DecoderThread() +{ + wait(); +} + +void DecoderThread::decode(QByteArray program, QByteArray input) +{ + this->program = program; + this->input = input; + start(); +} + +void DecoderThread::run() +{ + char* program = new char[this->program.size() + 1]; + strcpy(program, this->program.data()); + int programLength = this->program.size(); + + char* input = new char[this->input.size() + 1]; + strcpy(input, this->input.data()); + int inputLength = this->program.size(); + + actualDecode(program, programLength, input, inputLength); + + delete program; + delete input; +} + +void DecoderThread::actualDecode(char* program, int programLength, char* input, int inputLength) +{ + // Don't use QList or QByteArray, it's too slow + char memory[65536]; + int ptr = 0; + + QString text; + QMap correspondingBraces; + QStack loopStack; + + int programIndex = 0; + int inputIndex = 0; + + for (programIndex = 0; programIndex < programLength; ++programIndex) { + switch (program[programIndex]) { + case '[': + loopStack.push(programIndex); + break; + case ']': + if(loopStack.isEmpty()) { + emit errorMessage("Unmatched end of loop"); + return; + } + int old_i = loopStack.pop(); + correspondingBraces.insert(programIndex, old_i); + correspondingBraces.insert(old_i, programIndex); + break; + } + } + if(!loopStack.isEmpty()) { + emit errorMessage("Unmatched begin of loop"); + return; + } + + for (programIndex = 0; programIndex < programLength; ++programIndex) { + switch (program[programIndex]) { + case '>': + ++ptr; + break; + case '<': + --ptr; + break; + case '+': + ++memory[ptr]; + break; + case '-': + --memory[ptr]; + break; + case '.': + text += (QString(memory[ptr])); + if (memory[ptr] == '\n') { + emit programDecoded(text); + } + break; + case ',': + if (inputIndex < inputLength) { + memory[ptr] = input[inputIndex]; + ++inputIndex; + } else { + memory[ptr] = 0; + } + break; + case '[': + if (memory[ptr] == 0) { + programIndex = correspondingBraces.value(programIndex); + } + break; + case ']': + if (memory[ptr] != 0) { + programIndex = correspondingBraces.value(programIndex); + } + break; + } + } + + emit programDecoded(text); +} diff --git a/decoderthread.h b/decoderthread.h new file mode 100644 index 0000000..3192a29 --- /dev/null +++ b/decoderthread.h @@ -0,0 +1,31 @@ +#ifndef DECODERTHREAD_H +#define DECODERTHREAD_H + +#include +#include +#include + +class DecoderThread : public QThread +{ + Q_OBJECT +public: + explicit DecoderThread(QObject *parent = 0); + ~DecoderThread(); + void decode(QByteArray program, QByteArray input); + +private: + QByteArray program; + QByteArray input; + + void run(); + void actualDecode(char* program, int programLength, char* input, int inputLength); + +signals: + void programDecoded(QString text); + void errorMessage(QString text); + +public slots: + +}; + +#endif // DECODERTHREAD_H diff --git a/qbrainfuck.cpp b/qbrainfuck.cpp index 19a2a67..59e8fce 100644 --- a/qbrainfuck.cpp +++ b/qbrainfuck.cpp @@ -6,6 +6,10 @@ QBrainfuck::QBrainfuck(QWidget *parent) : ui(new Ui::QBrainfuck) { ui->setupUi(this); + + decoder = new DecoderThread(); + QObject::connect(decoder, &DecoderThread::programDecoded, this, &QBrainfuck::setText); + QObject::connect(decoder, &DecoderThread::errorMessage, this, &QBrainfuck::errorMessage); } QBrainfuck::~QBrainfuck() @@ -17,7 +21,6 @@ void QBrainfuck::on_encodeButton_clicked() { QByteArray text = ui->textTextEdit->document()->toPlainText().toLatin1(); ui->programTextEdit->setPlainText(""); - ui->debugTextEdit->setHtml(""); // First pass : find decades/steps QList decades; // Store the decades for initial loop @@ -26,9 +29,6 @@ void QBrainfuck::on_encodeButton_clicked() memory.append(0); QList steps; // Store the steps to construct the program - QString debugNumbers; - QString debugChars; - QByteArray::const_iterator textIterator; for (textIterator = text.constBegin(); textIterator != text.constEnd(); ++textIterator) { int max_diff = ui->maxSignsSpinBox->value()+1; @@ -52,10 +52,6 @@ void QBrainfuck::on_encodeButton_clicked() decades.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value()); memory.append(*textIterator); } - - // Add current char to debug (with corresponding ASCII value) - debugNumbers += formatNumber(*textIterator); - debugChars += "   " + QString(*textIterator); } qSort(decades); @@ -63,8 +59,6 @@ void QBrainfuck::on_encodeButton_clicked() // Second pass : write program QString program = ""; - ui->debugTextEdit->insertHtml("# The message

" + QString(text) + "

# In ASCII

" + debugNumbers + "
" + debugChars + "

# The memory

"); - for (int i = 0; i < ui->decadesSpinBox->value(); ++i) { program += "+"; } @@ -83,20 +77,6 @@ void QBrainfuck::on_encodeButton_clicked() } program += "-]"; - // Print initial loop to debug - QString debugText; - for (int multiplier = 0; multiplier <= ui->decadesSpinBox->value(); ++multiplier) { - debugText += "  " + formatNumber(ui->decadesSpinBox->value()-multiplier) + ""; - - for (int i = 1; i < decades.length(); ++i) { - debugText += formatNumber(decades[i]/ui->decadesSpinBox->value()*multiplier); - } - - debugText += "
"; - } - debugText += "
"; - ui->debugTextEdit->insertHtml(debugText); - int prev_ptr = 0; QList::const_iterator stepsIterator; @@ -127,94 +107,20 @@ void QBrainfuck::on_encodeButton_clicked() program += "."; prev_ptr = next_ptr; decades[next_ptr] = *textIterator; - - // Print current memory and current letter - printMemory(decades, next_ptr, " " + QString(*textIterator)); - ++textIterator; } ui->programTextEdit->setPlainText(program); - ui->debugTextEdit->insertHtml("

# The program

" + program); } void QBrainfuck::on_decodeButton_clicked() { ui->textTextEdit->setPlainText(""); - ui->debugTextEdit->setHtml(""); - int ptr = 0; QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1(); QByteArray input = ui->inputLineEdit->text().toLatin1(); - QByteArray::const_iterator inputIterator = input.constBegin(); - QList memory; - QMap correspondingBraces; - QStack loopStack; - - memory.append(0); - - for (int i = 0; i < program.size(); ++i) { - switch (program.at(i)) { - case '[': - loopStack.push(i); - break; - case ']': - if(loopStack.isEmpty()) { - QMessageBox::critical(this, "QBrainfuck error", "Error: Unmatched end of loop"); - return; - } - int old_i = loopStack.pop(); - correspondingBraces.insert(i, old_i); - correspondingBraces.insert(old_i, i); - break; - } - } - if(!loopStack.isEmpty()) { - QMessageBox::critical(this, "QBrainfuck error", "Error: Unmatched begin of loop"); - return; - } - - for (int i = 0; i < program.size(); ++i) { - switch (program.at(i)) { - case '>': - ++ptr; - if(ptr == memory.size()) { - memory.append(0); - } - break; - case '<': - --ptr; - if (ptr < 0) { - QMessageBox::critical(this, "QBrainfuck error", "Error: Pointer went under 0"); - return; - } - break; - case '+': - ++memory[ptr]; - break; - case '-': - --memory[ptr]; - break; - case '.': - ui->textTextEdit->insertPlainText(QString(memory.at(ptr))); - break; - case ',': - memory[ptr] = *inputIterator; - ++inputIterator; - break; - case '[': - if (memory.at(ptr) == 0) { - i = correspondingBraces.value(i); - } - break; - case ']': - if (memory.at(ptr) != 0) { - i = correspondingBraces.value(i); - } - break; - } - } + decoder->decode(program, input); } void QBrainfuck::on_motifButton_clicked() @@ -333,26 +239,10 @@ void QBrainfuck::on_loadButton_clicked() } } -QString QBrainfuck::formatNumber(int number) -{ - if (number < 10) { - return "   " + QString().setNum(number); - } else if (number < 100) { - return "  " + QString().setNum(number); - } else { - return " " + QString().setNum(number); - } +void QBrainfuck::setText(QString text) { + ui->textTextEdit->setPlainText(text); } -void QBrainfuck::printMemory(QList memory, int ptr, QString text) -{ - QString str; - for (int i = 0; i < memory.size(); ++i) { - if (i == ptr) { - str += "" + formatNumber(memory[i]) + ""; - } else { - str += formatNumber(memory[i]); - } - } - ui->debugTextEdit->insertHtml(text + str + "
"); +void QBrainfuck::errorMessage(QString message) { + QMessageBox::critical(this, "QBrainfuck error", "Error: " + message); } diff --git a/qbrainfuck.h b/qbrainfuck.h index a978f41..ec2af0b 100644 --- a/qbrainfuck.h +++ b/qbrainfuck.h @@ -7,6 +7,7 @@ #include #include #include +#include "decoderthread.h" namespace Ui { class QBrainfuck; @@ -39,11 +40,13 @@ private slots: void on_loadButton_clicked(); + void setText(QString text); + + void errorMessage(QString message); + private: Ui::QBrainfuck *ui; - - QString formatNumber(int number); - void printMemory(QList memory, int ptr, QString text); + DecoderThread *decoder; }; #endif // QBRAINFUCK_H