Add DecoderThread
This commit is contained in:
parent
368b7b42a8
commit
36a6956c79
@ -13,8 +13,10 @@ TEMPLATE = app
|
|||||||
|
|
||||||
|
|
||||||
SOURCES += main.cpp\
|
SOURCES += main.cpp\
|
||||||
qbrainfuck.cpp
|
qbrainfuck.cpp \
|
||||||
|
decoderthread.cpp
|
||||||
|
|
||||||
HEADERS += qbrainfuck.h
|
HEADERS += qbrainfuck.h \
|
||||||
|
decoderthread.h
|
||||||
|
|
||||||
FORMS += qbrainfuck.ui
|
FORMS += qbrainfuck.ui
|
||||||
|
112
decoderthread.cpp
Normal file
112
decoderthread.cpp
Normal file
@ -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<int,int> correspondingBraces;
|
||||||
|
QStack<int> 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);
|
||||||
|
}
|
31
decoderthread.h
Normal file
31
decoderthread.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef DECODERTHREAD_H
|
||||||
|
#define DECODERTHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QStack>
|
||||||
|
|
||||||
|
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
|
128
qbrainfuck.cpp
128
qbrainfuck.cpp
@ -6,6 +6,10 @@ QBrainfuck::QBrainfuck(QWidget *parent) :
|
|||||||
ui(new Ui::QBrainfuck)
|
ui(new Ui::QBrainfuck)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
decoder = new DecoderThread();
|
||||||
|
QObject::connect(decoder, &DecoderThread::programDecoded, this, &QBrainfuck::setText);
|
||||||
|
QObject::connect(decoder, &DecoderThread::errorMessage, this, &QBrainfuck::errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
QBrainfuck::~QBrainfuck()
|
QBrainfuck::~QBrainfuck()
|
||||||
@ -17,7 +21,6 @@ void QBrainfuck::on_encodeButton_clicked()
|
|||||||
{
|
{
|
||||||
QByteArray text = ui->textTextEdit->document()->toPlainText().toLatin1();
|
QByteArray text = ui->textTextEdit->document()->toPlainText().toLatin1();
|
||||||
ui->programTextEdit->setPlainText("");
|
ui->programTextEdit->setPlainText("");
|
||||||
ui->debugTextEdit->setHtml("");
|
|
||||||
|
|
||||||
// First pass : find decades/steps
|
// First pass : find decades/steps
|
||||||
QList<unsigned char> decades; // Store the decades for initial loop
|
QList<unsigned char> decades; // Store the decades for initial loop
|
||||||
@ -26,9 +29,6 @@ void QBrainfuck::on_encodeButton_clicked()
|
|||||||
memory.append(0);
|
memory.append(0);
|
||||||
QList<unsigned char> steps; // Store the steps to construct the program
|
QList<unsigned char> steps; // Store the steps to construct the program
|
||||||
|
|
||||||
QString debugNumbers;
|
|
||||||
QString debugChars;
|
|
||||||
|
|
||||||
QByteArray::const_iterator textIterator;
|
QByteArray::const_iterator textIterator;
|
||||||
for (textIterator = text.constBegin(); textIterator != text.constEnd(); ++textIterator) {
|
for (textIterator = text.constBegin(); textIterator != text.constEnd(); ++textIterator) {
|
||||||
int max_diff = ui->maxSignsSpinBox->value()+1;
|
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());
|
decades.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value());
|
||||||
memory.append(*textIterator);
|
memory.append(*textIterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add current char to debug (with corresponding ASCII value)
|
|
||||||
debugNumbers += formatNumber(*textIterator);
|
|
||||||
debugChars += " " + QString(*textIterator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qSort(decades);
|
qSort(decades);
|
||||||
@ -63,8 +59,6 @@ void QBrainfuck::on_encodeButton_clicked()
|
|||||||
// Second pass : write program
|
// Second pass : write program
|
||||||
QString program = "";
|
QString program = "";
|
||||||
|
|
||||||
ui->debugTextEdit->insertHtml("# The message<br /><br />" + QString(text) + "<br /><br /># In ASCII<br /><br />" + debugNumbers + "<br />" + debugChars + "<br /><br /># The memory<br /><br />");
|
|
||||||
|
|
||||||
for (int i = 0; i < ui->decadesSpinBox->value(); ++i) {
|
for (int i = 0; i < ui->decadesSpinBox->value(); ++i) {
|
||||||
program += "+";
|
program += "+";
|
||||||
}
|
}
|
||||||
@ -83,20 +77,6 @@ void QBrainfuck::on_encodeButton_clicked()
|
|||||||
}
|
}
|
||||||
program += "-]";
|
program += "-]";
|
||||||
|
|
||||||
// Print initial loop to debug
|
|
||||||
QString debugText;
|
|
||||||
for (int multiplier = 0; multiplier <= ui->decadesSpinBox->value(); ++multiplier) {
|
|
||||||
debugText += " <b>" + formatNumber(ui->decadesSpinBox->value()-multiplier) + "</b>";
|
|
||||||
|
|
||||||
for (int i = 1; i < decades.length(); ++i) {
|
|
||||||
debugText += formatNumber(decades[i]/ui->decadesSpinBox->value()*multiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
debugText += "<br />";
|
|
||||||
}
|
|
||||||
debugText += "<br />";
|
|
||||||
ui->debugTextEdit->insertHtml(debugText);
|
|
||||||
|
|
||||||
int prev_ptr = 0;
|
int prev_ptr = 0;
|
||||||
|
|
||||||
QList<unsigned char>::const_iterator stepsIterator;
|
QList<unsigned char>::const_iterator stepsIterator;
|
||||||
@ -127,94 +107,20 @@ void QBrainfuck::on_encodeButton_clicked()
|
|||||||
program += ".";
|
program += ".";
|
||||||
prev_ptr = next_ptr;
|
prev_ptr = next_ptr;
|
||||||
decades[next_ptr] = *textIterator;
|
decades[next_ptr] = *textIterator;
|
||||||
|
|
||||||
// Print current memory and current letter
|
|
||||||
printMemory(decades, next_ptr, " " + QString(*textIterator));
|
|
||||||
|
|
||||||
++textIterator;
|
++textIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->programTextEdit->setPlainText(program);
|
ui->programTextEdit->setPlainText(program);
|
||||||
ui->debugTextEdit->insertHtml("<br /><br /># The program<br /><br />" + program);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QBrainfuck::on_decodeButton_clicked()
|
void QBrainfuck::on_decodeButton_clicked()
|
||||||
{
|
{
|
||||||
ui->textTextEdit->setPlainText("");
|
ui->textTextEdit->setPlainText("");
|
||||||
ui->debugTextEdit->setHtml("");
|
|
||||||
|
|
||||||
int ptr = 0;
|
|
||||||
QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1();
|
QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1();
|
||||||
QByteArray input = ui->inputLineEdit->text().toLatin1();
|
QByteArray input = ui->inputLineEdit->text().toLatin1();
|
||||||
QByteArray::const_iterator inputIterator = input.constBegin();
|
|
||||||
|
|
||||||
QList<unsigned char> memory;
|
decoder->decode(program, input);
|
||||||
QMap<int,int> correspondingBraces;
|
|
||||||
QStack<int> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QBrainfuck::on_motifButton_clicked()
|
void QBrainfuck::on_motifButton_clicked()
|
||||||
@ -333,26 +239,10 @@ void QBrainfuck::on_loadButton_clicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QBrainfuck::formatNumber(int number)
|
void QBrainfuck::setText(QString text) {
|
||||||
{
|
ui->textTextEdit->setPlainText(text);
|
||||||
if (number < 10) {
|
|
||||||
return " " + QString().setNum(number);
|
|
||||||
} else if (number < 100) {
|
|
||||||
return " " + QString().setNum(number);
|
|
||||||
} else {
|
|
||||||
return " " + QString().setNum(number);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QBrainfuck::printMemory(QList<unsigned char> memory, int ptr, QString text)
|
void QBrainfuck::errorMessage(QString message) {
|
||||||
{
|
QMessageBox::critical(this, "QBrainfuck error", "Error: " + message);
|
||||||
QString str;
|
|
||||||
for (int i = 0; i < memory.size(); ++i) {
|
|
||||||
if (i == ptr) {
|
|
||||||
str += "<b>" + formatNumber(memory[i]) + "</b>";
|
|
||||||
} else {
|
|
||||||
str += formatNumber(memory[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui->debugTextEdit->insertHtml(text + str + "<br />");
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
|
#include "decoderthread.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class QBrainfuck;
|
class QBrainfuck;
|
||||||
@ -39,11 +40,13 @@ private slots:
|
|||||||
|
|
||||||
void on_loadButton_clicked();
|
void on_loadButton_clicked();
|
||||||
|
|
||||||
|
void setText(QString text);
|
||||||
|
|
||||||
|
void errorMessage(QString message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::QBrainfuck *ui;
|
Ui::QBrainfuck *ui;
|
||||||
|
DecoderThread *decoder;
|
||||||
QString formatNumber(int number);
|
|
||||||
void printMemory(QList<unsigned char> memory, int ptr, QString text);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QBRAINFUCK_H
|
#endif // QBRAINFUCK_H
|
||||||
|
Loading…
Reference in New Issue
Block a user