#include "qbrainfuck.h" #include "ui_qbrainfuck.h" QBrainfuck::QBrainfuck(QWidget *parent) : QMainWindow(parent), ui(new Ui::QBrainfuck) { ui->setupUi(this); } QBrainfuck::~QBrainfuck() { delete ui; } 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 decades.append(0); QList array; // Store the program's memory array.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; QList::iterator index; // Find nearest memory's case and store it QList::iterator arrayIterator; for (arrayIterator = array.begin(); arrayIterator != array.end(); ++arrayIterator) { if (qAbs(*arrayIterator-*textIterator) < max_diff) { max_diff = qAbs(*arrayIterator-*textIterator); index = arrayIterator; } } // Add step and insert current value in the array, else add a decade if we don't find a case nearer than max_diff if (max_diff <= ui->maxSignsSpinBox->value()) { steps.append(*index); *index = *textIterator; } else { steps.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value()); decades.append(qRound(*textIterator/(float)ui->decadesSpinBox->value())*ui->decadesSpinBox->value()); array.append(*textIterator); } // Add current char to debug (with corresponding ASCII value) debugNumbers += formatNumber(*textIterator); debugChars += "   " + QString(*textIterator); } qSort(decades); // 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 += "+"; } program += "\["; QList::iterator decadesIterator; for (decadesIterator = decades.begin()+1; decadesIterator != decades.end(); ++decadesIterator) { program += ">"; for(int i = 0; i < *decadesIterator; i+=ui->decadesSpinBox->value()) { program += "+"; } } for(int i = 0; i < decades.size()-1; ++i) { program += "<"; } 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; textIterator = text.constBegin(); for (stepsIterator = steps.constBegin(); stepsIterator != steps.constEnd(); ++stepsIterator) { int next_ptr = decades.indexOf(*stepsIterator); if(next_ptr > prev_ptr) { for(int i = 0; i < next_ptr-prev_ptr; ++i) { program += ">"; } } else { for(int i = 0; i < prev_ptr-next_ptr; ++i) { program += "<"; } } if(*textIterator > *stepsIterator) { for(int i = 0; i < *textIterator-*stepsIterator; ++i) { program += "+"; } } else { for(int i = 0; i < *stepsIterator-*textIterator; ++i) { program += "-"; } } program += "."; prev_ptr = next_ptr; decades[next_ptr] = *textIterator; // Print current memory and current letter printMemory(decades, decades.length(), 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(""); bool exit = false; int ptr = 0; int maxPtr = 0; QByteArray text = ui->programTextEdit->document()->toPlainText().toLatin1(); QByteArray array = QByteArray(ui->arraySpinBox->value(), (char)0); QByteArray input = ui->inputLineEdit->text().toLatin1(); QByteArray::const_iterator last_textIterator; QByteArray::const_iterator inputIterator = input.constBegin(); QByteArray::const_iterator textIterator; int loopCounter = 0; for (textIterator = text.constBegin(); textIterator != text.constEnd() && exit == false; ++textIterator) { switch (*textIterator) { case '>': ++ptr; if (ptr >= ui->arraySpinBox->value()) { ptr = 0; } if(maxPtr < ptr) { maxPtr = ptr; } break; case '<': --ptr; if (ptr < 0) { ptr = ui->arraySpinBox->value()-1; maxPtr = ptr; } break; case '+': array[ptr] = array.at(ptr) + 1; break; case '-': array[ptr] = array.at(ptr) - 1; break; case '.': ui->textTextEdit->insertPlainText(QString(array.at(ptr))); printMemory(array, maxPtr, ptr, "OUTPUT:     " + QString(array.at(ptr))); break; case ',': array[ptr] = *inputIterator; ++inputIterator; printMemory(array, maxPtr, ptr, "INPUT:      " + QString(array.at(ptr))); break; case '[': last_textIterator = textIterator; loopCounter = 0; printMemory(array, maxPtr, ptr, "LOOP BEG.    "); break; case ']': if(array.at(ptr)!=0) { textIterator = last_textIterator; ++loopCounter; if (loopCounter >= ui->loopSpinBox->value()) { QMessageBox::critical(this, "QBrainfuck", "Error: Loop too long"); exit = true; } printMemory(array, maxPtr, ptr, "LOOP         "); } else { printMemory(array, maxPtr, ptr, "LOOP END     "); } break; } } } void QBrainfuck::on_motifButton_clicked() { QString motif = ui->motifTextEdit->document()->toPlainText(); QByteArray program = ui->programTextEdit->document()->toPlainText().toLatin1(); if (motif.contains(QRegExp(">|<|\\+|-|\\.|,|\\[|\\]"))) { QMessageBox::critical(this, "QBrainfuck", "Error: Motif contains Brainfuck characters"); return; } QByteArray::const_iterator programIterator; for (programIterator = program.constBegin(); programIterator != program.constEnd(); ++programIterator) { switch (*programIterator) { case '>': case '<': case '+': case '-': case '.': case ',': case '[': case ']': int index = motif.indexOf(QRegExp(ui->regexLineEdit->text())); if (index==-1) { motif += *programIterator; } else { motif.replace(index, 1, *programIterator); } break; } } ui->resultTextEdit->setPlainText(motif); } void QBrainfuck::on_textTextEdit_textChanged() { ui->textLabel->setText("Text length: " + QString().setNum(ui->textTextEdit->document()->toPlainText().length())); } void QBrainfuck::on_programTextEdit_textChanged() { ui->programLabel->setText("Program length: " + QString().setNum(ui->programTextEdit->document()->toPlainText().count(QRegExp(">|<|\\+|-|\\.|,|\\[|\\]")))); } void QBrainfuck::on_motifTextEdit_textChanged() { ui->motifLabel->setText("Motif length: " + QString().setNum(ui->motifTextEdit->document()->toPlainText().count(QRegExp(ui->regexLineEdit->text())))); } void QBrainfuck::on_regexLineEdit_textChanged(const QString &arg1) { on_motifTextEdit_textChanged(); } void QBrainfuck::on_saveButton_clicked() { QFileDialog dialog(this); dialog.setFileMode(QFileDialog::AnyFile); dialog.setNameFilter("Json Files (*.json);;Txt Files (*.txt)"); dialog.setDefaultSuffix("json"); dialog.setAcceptMode(QFileDialog::AcceptSave); if (dialog.exec()) { QFile saveFile(dialog.selectedFiles().first()); if (!saveFile.open(QIODevice::WriteOnly)) { return; } if(dialog.selectedNameFilter() == "Json Files (*.json)") { QJsonObject jsonObject; jsonObject["text"] = ui->textTextEdit->document()->toPlainText(); jsonObject["program"] = ui->programTextEdit->document()->toPlainText(); jsonObject["motif"] = ui->motifTextEdit->document()->toPlainText(); jsonObject["result"] = ui->resultTextEdit->document()->toPlainText(); QJsonDocument jsonDoc(jsonObject); saveFile.write(jsonDoc.toJson()); } else { saveFile.write(ui->textTextEdit->document()->toPlainText().toUtf8() + "\n\n"); saveFile.write(ui->programTextEdit->document()->toPlainText().toUtf8() + "\n\n"); saveFile.write(ui->motifTextEdit->document()->toPlainText().toUtf8() + "\n\n"); saveFile.write(ui->resultTextEdit->document()->toPlainText().toUtf8() + "\n\n"); } } } void QBrainfuck::on_loadButton_clicked() { QFileDialog dialog(this); dialog.setFileMode(QFileDialog::AnyFile); dialog.setNameFilter("Json Files (*.json)"); dialog.setDefaultSuffix("json"); dialog.setAcceptMode(QFileDialog::AcceptOpen); if (dialog.exec()) { QFile loadFile(dialog.selectedFiles().first()); if (!loadFile.open(QIODevice::ReadOnly)) { return; } QByteArray saveData = loadFile.readAll(); QJsonDocument jsonDoc(QJsonDocument::fromJson(saveData)); QJsonObject jsonObject = jsonDoc.object(); ui->textTextEdit->setPlainText(jsonObject["text"].toString()); ui->programTextEdit->setPlainText(jsonObject["program"].toString()); ui->motifTextEdit->setPlainText(jsonObject["motif"].toString()); ui->resultTextEdit->setPlainText(jsonObject["result"].toString()); } } 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::printMemory(QByteArray array, int maxPtr, int ptr, QString text) { QString str; for(int i = 0; i <= maxPtr; ++i) { if(i == ptr) { str += "" + formatNumber(array[i]) + ""; } else { str += formatNumber(array[i]); } } ui->debugTextEdit->insertHtml(text + str + "
"); } void QBrainfuck::printMemory(QList array, int maxPtr, int ptr, QString text) { QString str; for(int i = 0; i < maxPtr; ++i) { if(i == ptr) { str += "" + formatNumber(array[i]) + ""; } else { str += formatNumber(array[i]); } } ui->debugTextEdit->insertHtml(text + str + "
"); }