Rewrite decoder

This commit is contained in:
Nathanaël Restori 2014-08-13 22:53:13 +02:00
parent e8ff5e0203
commit 368b7b42a8
3 changed files with 105 additions and 134 deletions

View File

@ -20,11 +20,11 @@ void QBrainfuck::on_encodeButton_clicked()
ui->debugTextEdit->setHtml(""); ui->debugTextEdit->setHtml("");
// First pass : find decades/steps // First pass : find decades/steps
QList<char> decades; // Store the decades for initial loop QList<unsigned char> decades; // Store the decades for initial loop
decades.append(0); decades.append(0);
QList<char> array; // Store the program's memory QList<unsigned char> memory; // Store the program's memory
array.append(0); memory.append(0);
QList<char> steps; // Store the steps to construct the program QList<unsigned char> steps; // Store the steps to construct the program
QString debugNumbers; QString debugNumbers;
QString debugChars; QString debugChars;
@ -32,25 +32,25 @@ void QBrainfuck::on_encodeButton_clicked()
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;
QList<char>::iterator index; QList<unsigned char>::iterator index;
// Find nearest memory's case and store it // Find nearest memory's case and store it
QList<char>::iterator arrayIterator; QList<unsigned char>::iterator memoryIterator;
for (arrayIterator = array.begin(); arrayIterator != array.end(); ++arrayIterator) { for (memoryIterator = memory.begin(); memoryIterator != memory.end(); ++memoryIterator) {
if (qAbs(*arrayIterator-*textIterator) < max_diff) { if (qAbs(*memoryIterator-*textIterator) < max_diff) {
max_diff = qAbs(*arrayIterator-*textIterator); max_diff = qAbs(*memoryIterator-*textIterator);
index = arrayIterator; index = memoryIterator;
} }
} }
// Add step and insert current value in the array, else add a decade if we don't find a case nearer than max_diff // Add step and insert current value in the memory, else add a decade if we don't find a case nearer than max_diff
if (max_diff <= ui->maxSignsSpinBox->value()) { if (max_diff <= ui->maxSignsSpinBox->value()) {
steps.append(*index); steps.append(*index);
*index = *textIterator; *index = *textIterator;
} else { } else {
steps.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value()); steps.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value());
decades.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value()); decades.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value());
array.append(*textIterator); memory.append(*textIterator);
} }
// Add current char to debug (with corresponding ASCII value) // Add current char to debug (with corresponding ASCII value)
@ -65,30 +65,30 @@ void QBrainfuck::on_encodeButton_clicked()
ui->debugTextEdit->insertHtml("# The message<br /><br />" + QString(text) + "<br /><br /># In ASCII<br /><br />" + debugNumbers + "<br />" + debugChars + "<br /><br /># The memory<br /><br />"); 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 += "+";
} }
program += "\["; program += "\[";
QList<char>::iterator decadesIterator; QList<unsigned char>::iterator decadesIterator;
for (decadesIterator = decades.begin()+1; decadesIterator != decades.end(); ++decadesIterator) { for (decadesIterator = decades.begin()+1; decadesIterator != decades.end(); ++decadesIterator) {
program += ">"; program += ">";
for(int i = 0; i < *decadesIterator; i+=ui->decadesSpinBox->value()) { for (int i = 0; i < *decadesIterator; i+=ui->decadesSpinBox->value()) {
program += "+"; program += "+";
} }
} }
for(int i = 0; i < decades.size()-1; ++i) { for (int i = 0; i < decades.size()-1; ++i) {
program += "<"; program += "<";
} }
program += "-]"; program += "-]";
// Print initial loop to debug // Print initial loop to debug
QString debugText; QString debugText;
for(int multiplier = 0; multiplier <= ui->decadesSpinBox->value(); ++multiplier) { for (int multiplier = 0; multiplier <= ui->decadesSpinBox->value(); ++multiplier) {
debugText += "&nbsp;&nbsp;<b>" + formatNumber(ui->decadesSpinBox->value()-multiplier) + "</b>"; debugText += "&nbsp;&nbsp;<b>" + formatNumber(ui->decadesSpinBox->value()-multiplier) + "</b>";
for(int i = 1; i < decades.length(); ++i) { for (int i = 1; i < decades.length(); ++i) {
debugText += formatNumber(decades[i]/ui->decadesSpinBox->value()*multiplier); debugText += formatNumber(decades[i]/ui->decadesSpinBox->value()*multiplier);
} }
@ -99,27 +99,27 @@ void QBrainfuck::on_encodeButton_clicked()
int prev_ptr = 0; int prev_ptr = 0;
QList<char>::const_iterator stepsIterator; QList<unsigned char>::const_iterator stepsIterator;
textIterator = text.constBegin(); textIterator = text.constBegin();
for (stepsIterator = steps.constBegin(); stepsIterator != steps.constEnd(); ++stepsIterator) { for (stepsIterator = steps.constBegin(); stepsIterator != steps.constEnd(); ++stepsIterator) {
int next_ptr = decades.indexOf(*stepsIterator); int next_ptr = decades.indexOf(*stepsIterator);
if(next_ptr > prev_ptr) { if (next_ptr > prev_ptr) {
for(int i = 0; i < next_ptr-prev_ptr; ++i) { for (int i = 0; i < next_ptr-prev_ptr; ++i) {
program += ">"; program += ">";
} }
} else { } else {
for(int i = 0; i < prev_ptr-next_ptr; ++i) { for (int i = 0; i < prev_ptr-next_ptr; ++i) {
program += "<"; program += "<";
} }
} }
if(*textIterator > *stepsIterator) { if (*textIterator > *stepsIterator) {
for(int i = 0; i < *textIterator-*stepsIterator; ++i) { for (int i = 0; i < *textIterator-*stepsIterator; ++i) {
program += "+"; program += "+";
} }
} else { } else {
for(int i = 0; i < *stepsIterator-*textIterator; ++i) { for (int i = 0; i < *stepsIterator-*textIterator; ++i) {
program += "-"; program += "-";
} }
} }
@ -129,7 +129,7 @@ void QBrainfuck::on_encodeButton_clicked()
decades[next_ptr] = *textIterator; decades[next_ptr] = *textIterator;
// Print current memory and current letter // Print current memory and current letter
printMemory(decades, decades.length(), next_ptr, "&nbsp;" + QString(*textIterator)); printMemory(decades, next_ptr, "&nbsp;" + QString(*textIterator));
++textIterator; ++textIterator;
} }
@ -143,68 +143,74 @@ void QBrainfuck::on_decodeButton_clicked()
ui->textTextEdit->setPlainText(""); ui->textTextEdit->setPlainText("");
ui->debugTextEdit->setHtml(""); ui->debugTextEdit->setHtml("");
bool exit = false;
int ptr = 0; int ptr = 0;
int maxPtr = 0; QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1();
QByteArray text = ui->programTextEdit->document()->toPlainText().toLatin1();
QByteArray array = QByteArray(ui->arraySpinBox->value(), (char)0);
QByteArray input = ui->inputLineEdit->text().toLatin1(); QByteArray input = ui->inputLineEdit->text().toLatin1();
QByteArray::const_iterator last_textIterator;
QByteArray::const_iterator inputIterator = input.constBegin(); QByteArray::const_iterator inputIterator = input.constBegin();
QByteArray::const_iterator textIterator; QList<unsigned char> memory;
int loopCounter = 0; QMap<int,int> correspondingBraces;
for (textIterator = text.constBegin(); textIterator != text.constEnd() && exit == false; ++textIterator) { QStack<int> loopStack;
switch (*textIterator) { 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 '>': case '>':
++ptr; ++ptr;
if (ptr >= ui->arraySpinBox->value()) { if(ptr == memory.size()) {
ptr = 0; memory.append(0);
}
if(maxPtr < ptr) {
maxPtr = ptr;
} }
break; break;
case '<': case '<':
--ptr; --ptr;
if (ptr < 0) { if (ptr < 0) {
ptr = ui->arraySpinBox->value()-1; QMessageBox::critical(this, "QBrainfuck error", "Error: Pointer went under 0");
maxPtr = ptr; return;
} }
break; break;
case '+': case '+':
array[ptr] = array.at(ptr) + 1; ++memory[ptr];
break; break;
case '-': case '-':
array[ptr] = array.at(ptr) - 1; --memory[ptr];
break; break;
case '.': case '.':
ui->textTextEdit->insertPlainText(QString(array.at(ptr))); ui->textTextEdit->insertPlainText(QString(memory.at(ptr)));
printMemory(array, maxPtr, ptr, "OUTPUT:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + QString(array.at(ptr)));
break; break;
case ',': case ',':
array[ptr] = *inputIterator; memory[ptr] = *inputIterator;
++inputIterator; ++inputIterator;
printMemory(array, maxPtr, ptr, "INPUT:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + QString(array.at(ptr)));
break; break;
case '[': case '[':
last_textIterator = textIterator; if (memory.at(ptr) == 0) {
loopCounter = 0; i = correspondingBraces.value(i);
printMemory(array, maxPtr, ptr, "LOOP BEG.&nbsp;&nbsp;&nbsp;&nbsp;"); }
break; break;
case ']': case ']':
if(array.at(ptr)!=0) { if (memory.at(ptr) != 0) {
textIterator = last_textIterator; i = correspondingBraces.value(i);
++loopCounter;
if (loopCounter >= ui->loopSpinBox->value()) {
QMessageBox::critical(this, "QBrainfuck", "Error: Loop too long");
exit = true;
}
printMemory(array, maxPtr, ptr, "LOOP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
} else {
printMemory(array, maxPtr, ptr, "LOOP END&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
} }
break; break;
} }
@ -217,7 +223,7 @@ void QBrainfuck::on_motifButton_clicked()
QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1(); QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1();
if (motif.contains(QRegExp(">|<|\\+|-|\\.|,|\\[|\\]"))) { if (motif.contains(QRegExp(">|<|\\+|-|\\.|,|\\[|\\]"))) {
QMessageBox::critical(this, "QBrainfuck", "Error: Motif contains Brainfuck characters"); QMessageBox::critical(this, "QBrainfuck error", "Error: Motif contains Brainfuck characters");
return; return;
} }
@ -280,7 +286,7 @@ void QBrainfuck::on_saveButton_clicked()
return; return;
} }
if(dialog.selectedNameFilter() == "Json Files (*.json)") { if (dialog.selectedNameFilter() == "Json Files (*.json)") {
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["text"] = ui->textTextEdit->document()->toPlainText(); jsonObject["text"] = ui->textTextEdit->document()->toPlainText();
@ -329,7 +335,7 @@ void QBrainfuck::on_loadButton_clicked()
QString QBrainfuck::formatNumber(int number) QString QBrainfuck::formatNumber(int number)
{ {
if(number < 10) { if (number < 10) {
return "&nbsp;&nbsp;&nbsp;" + QString().setNum(number); return "&nbsp;&nbsp;&nbsp;" + QString().setNum(number);
} else if (number < 100) { } else if (number < 100) {
return "&nbsp;&nbsp;" + QString().setNum(number); return "&nbsp;&nbsp;" + QString().setNum(number);
@ -338,27 +344,14 @@ QString QBrainfuck::formatNumber(int number)
} }
} }
void QBrainfuck::printMemory(QByteArray array, int maxPtr, int ptr, QString text) void QBrainfuck::printMemory(QList<unsigned char> memory, int ptr, QString text)
{ {
QString str; QString str;
for(int i = 0; i <= maxPtr; ++i) { for (int i = 0; i < memory.size(); ++i) {
if(i == ptr) { if (i == ptr) {
str += "<b>" + formatNumber(array[i]) + "</b>"; str += "<b>" + formatNumber(memory[i]) + "</b>";
} else { } else {
str += formatNumber(array[i]); str += formatNumber(memory[i]);
}
}
ui->debugTextEdit->insertHtml(text + str + "<br />");
}
void QBrainfuck::printMemory(QList<char> array, int maxPtr, int ptr, QString text)
{
QString str;
for(int i = 0; i < maxPtr; ++i) {
if(i == ptr) {
str += "<b>" + formatNumber(array[i]) + "</b>";
} else {
str += formatNumber(array[i]);
} }
} }
ui->debugTextEdit->insertHtml(text + str + "<br />"); ui->debugTextEdit->insertHtml(text + str + "<br />");

View File

@ -6,6 +6,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonDocument> #include <QJsonDocument>
#include <QStack>
namespace Ui { namespace Ui {
class QBrainfuck; class QBrainfuck;
@ -42,8 +43,7 @@ private:
Ui::QBrainfuck *ui; Ui::QBrainfuck *ui;
QString formatNumber(int number); QString formatNumber(int number);
void printMemory(QByteArray array, int maxPtr, int ptr, QString text); void printMemory(QList<unsigned char> memory, int ptr, QString text);
void printMemory(QList<char> array, int maxPtr, int ptr, QString text);
}; };
#endif // QBRAINFUCK_H #endif // QBRAINFUCK_H

View File

@ -176,50 +176,30 @@
<property name="fieldGrowthPolicy"> <property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum> <enum>QFormLayout::ExpandingFieldsGrow</enum>
</property> </property>
<item row="0" column="0">
<widget class="QLabel" name="loopLabel">
<property name="text">
<string>Max loop length</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="loopSpinBox">
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>500</number>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="arrayLabel">
<property name="text">
<string>Array size</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="arraySpinBox">
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="inputLabel"> <widget class="QLabel" name="inputLabel">
<property name="text"> <property name="text">
<string>Input</string> <string>Input</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="inputLineEdit"/> <widget class="QLineEdit" name="inputLineEdit"/>
</item> </item>
<item row="0" column="1">
<widget class="QLineEdit" name="regexLineEdit">
<property name="text">
<string>#</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="regexLabel">
<property name="text">
<string>Motif regex</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
@ -236,6 +216,12 @@
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QSpinBox" name="maxSignsSpinBox"> <widget class="QSpinBox" name="maxSignsSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value"> <property name="value">
<number>10</number> <number>10</number>
</property> </property>
@ -248,22 +234,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="regexLabel">
<property name="text">
<string>Motif regex</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="regexLineEdit">
<property name="text">
<string>#</string>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QSpinBox" name="decadesSpinBox"> <widget class="QSpinBox" name="decadesSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value"> <property name="value">
<number>10</number> <number>10</number>
</property> </property>