mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[code] Avoid dynamic allocation and useless string copy by keeping the
importation status flag in the areaBuffer
This commit is contained in:
@@ -57,9 +57,10 @@ void App::Snapshot::setOpt(const char * name, char * value) {
|
||||
}
|
||||
*separator = 0;
|
||||
const char * scriptName = value;
|
||||
const char * scriptContent = separator+1;
|
||||
const char * scriptContent = separator;
|
||||
Code::ScriptTemplate script(scriptName, scriptContent);
|
||||
m_scriptStore.addScriptFromTemplate(&script);
|
||||
m_scriptStore.scriptNamed(scriptName).toggleImportationStatus(); // set Importation Status to 1
|
||||
return;
|
||||
}
|
||||
if (strcmp(name, "lock-on-console") == 0) {
|
||||
|
||||
@@ -11,33 +11,26 @@ namespace Code {
|
||||
EditorController::EditorController(MenuController * menuController) :
|
||||
ViewController(nullptr),
|
||||
m_editorView(this),
|
||||
m_areaBuffer(nullptr),
|
||||
m_script(Ion::Storage::Record()),
|
||||
m_menuController(menuController)
|
||||
{
|
||||
m_editorView.setTextAreaDelegate(this);
|
||||
}
|
||||
|
||||
EditorController::~EditorController() {
|
||||
delete m_areaBuffer;
|
||||
m_areaBuffer = nullptr;
|
||||
}
|
||||
|
||||
void EditorController::setScript(Script script) {
|
||||
m_script = script;
|
||||
const char * scriptBody = m_script.readContent();
|
||||
size_t scriptBodySize = strlen(scriptBody)+1;
|
||||
size_t availableScriptSize = scriptBodySize + Ion::Storage::sharedStorage()->availableSize();
|
||||
assert(m_areaBuffer == nullptr);
|
||||
m_areaBuffer = new char[availableScriptSize];
|
||||
strlcpy(m_areaBuffer, scriptBody, scriptBodySize);
|
||||
m_editorView.setText(m_areaBuffer, availableScriptSize);
|
||||
Script::Data scriptData = m_script.value();
|
||||
size_t availableScriptSize = scriptData.size + Ion::Storage::sharedStorage()->availableSize();
|
||||
assert(sizeof(m_areaBuffer) >= availableScriptSize);
|
||||
strlcpy(m_areaBuffer, (const char *)scriptData.buffer, scriptData.size);
|
||||
m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag
|
||||
}
|
||||
|
||||
// TODO: this should be done in textAreaDidFinishEditing maybe??
|
||||
bool EditorController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK || event == Ion::Events::Back || event == Ion::Events::Home) {
|
||||
Script::ErrorStatus err = m_script.writeContent(m_areaBuffer, strlen(m_areaBuffer)+1);
|
||||
size_t sizeOfValue = strlen(m_areaBuffer+1)+1+1; // size of scriptContent + size of importation status
|
||||
Script::ErrorStatus err = m_script.setValue({.buffer=m_areaBuffer, .size=sizeOfValue});
|
||||
if (err == Script::ErrorStatus::NotEnoughSpaceAvailable || err == Script::ErrorStatus::RecordDoesNotExist) {
|
||||
assert(false); // This should not happen as we set the text area according to the available space in the Kallax
|
||||
} else {
|
||||
@@ -59,8 +52,6 @@ void EditorController::viewWillAppear() {
|
||||
|
||||
void EditorController::viewDidDisappear() {
|
||||
m_menuController->scriptContentEditionDidFinish();
|
||||
delete[] m_areaBuffer;
|
||||
m_areaBuffer = nullptr;
|
||||
m_editorView.unloadSyntaxHighlighter();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ class ScriptParameterController;
|
||||
class EditorController : public ViewController, public TextAreaDelegate {
|
||||
public:
|
||||
EditorController(MenuController * menuController);
|
||||
~EditorController();
|
||||
void setScript(Script script);
|
||||
|
||||
/* ViewController */
|
||||
@@ -32,7 +31,10 @@ private:
|
||||
static constexpr int k_indentationSpacesNumber = 2;
|
||||
StackViewController * stackController();
|
||||
EditorView m_editorView;
|
||||
char * m_areaBuffer;
|
||||
/* m_areaBuffer first character is dedicated to the importation status.
|
||||
* Thereby, we avoid wasteful copy while adding the Script to the storage
|
||||
* (in order to add the importation status char before the areaBuffer). */
|
||||
char m_areaBuffer[Ion::Storage::k_storageSize]; // this could be slightly optimize
|
||||
Script m_script;
|
||||
MenuController * m_menuController;
|
||||
};
|
||||
|
||||
@@ -25,14 +25,4 @@ const char * Script::readContent() const {
|
||||
return (const char *)d.buffer+k_importationStatusSize;
|
||||
}
|
||||
|
||||
Ion::Storage::Record::ErrorStatus Script::writeContent(const char * data, size_t size) {
|
||||
// TODO: could we avoid this useless allocation?
|
||||
char * buffer = new char[size+k_importationStatusSize];
|
||||
strlcpy(buffer+1, data, size);
|
||||
buffer[0] = importationStatus() ? 1 : 0;
|
||||
ErrorStatus e = setValue({.buffer= buffer, .size = size+k_importationStatusSize});
|
||||
delete[] buffer;
|
||||
return e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
void toggleImportationStatus();
|
||||
|
||||
const char * readContent() const;
|
||||
ErrorStatus writeContent(const char * data, size_t size);
|
||||
|
||||
constexpr static size_t k_importationStatusSize = 1;
|
||||
};
|
||||
|
||||
@@ -120,13 +120,9 @@ const char * ScriptStore::contentOfScript(const char * name) {
|
||||
}
|
||||
|
||||
Script::ErrorStatus ScriptStore::addScriptFromTemplate(const ScriptTemplate * scriptTemplate) {
|
||||
size_t scriptSize = strlen(scriptTemplate->content())+1;
|
||||
char * body = new char[scriptSize+Script::k_importationStatusSize];
|
||||
body[0] = 1;
|
||||
strlcpy(body+Script::k_importationStatusSize, scriptTemplate->content(), scriptSize);
|
||||
Script::ErrorStatus err = Ion::Storage::sharedStorage()->createRecord(scriptTemplate->name(), body, scriptSize+Script::k_importationStatusSize);
|
||||
size_t valueSize = strlen(scriptTemplate->content())+1+1;// scriptcontent size + 1 char for the importation status
|
||||
Script::ErrorStatus err = Ion::Storage::sharedStorage()->createRecord(scriptTemplate->name(), scriptTemplate->value(), valueSize);
|
||||
assert(err != Script::ErrorStatus::NonCompliantName);
|
||||
delete[] body;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
constexpr ScriptTemplate emptyScriptTemplate(".py", R"(from math import *
|
||||
constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01" R"(from math import *
|
||||
)");
|
||||
|
||||
constexpr ScriptTemplate factorialScriptTemplate("factorial.py", R"(def factorial(n):
|
||||
constexpr ScriptTemplate factorialScriptTemplate("factorial.py", "\x01" R"(def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
else:
|
||||
return n * factorial(n-1))");
|
||||
|
||||
constexpr ScriptTemplate fibonacciScriptTemplate("fibonacci.py", R"(def fibo(n):
|
||||
constexpr ScriptTemplate fibonacciScriptTemplate("fibonacci.py", "\x01" R"(def fibo(n):
|
||||
a=0
|
||||
b=1
|
||||
for i in range(1,n+1):
|
||||
@@ -27,7 +27,7 @@ def fibo2(n):
|
||||
return 1
|
||||
return fibo2(n-1)+fibo2(n-2))");
|
||||
|
||||
constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", R"(# This script draws a Mandelbrot fractal set
|
||||
constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", "\x01" R"(# This script draws a Mandelbrot fractal set
|
||||
# N_iteration: degree of precision
|
||||
import kandinsky
|
||||
def mandelbrot(N_iteration):
|
||||
@@ -47,7 +47,7 @@ def mandelbrot(N_iteration):
|
||||
# Draw a pixel colored in 'col' at position (x,y)
|
||||
kandinsky.set_pixel(x,y,col))");
|
||||
|
||||
constexpr ScriptTemplate polynomialScriptTemplate("polynomial.py", R"(from math import *
|
||||
constexpr ScriptTemplate polynomialScriptTemplate("polynomial.py", "\x01" R"(from math import *
|
||||
# roots(a,b,c) computes the solutions of the equation a*x**2+b*x+c=0
|
||||
def roots(a,b,c):
|
||||
delta = b*b-4*a*c
|
||||
|
||||
@@ -5,17 +5,18 @@ namespace Code {
|
||||
|
||||
class ScriptTemplate {
|
||||
public:
|
||||
constexpr ScriptTemplate(const char * name, const char * content) : m_name(name), m_content(content) {}
|
||||
constexpr ScriptTemplate(const char * name, const char * value) : m_name(name), m_value(value) {}
|
||||
static const ScriptTemplate * Empty();
|
||||
static const ScriptTemplate * Factorial();
|
||||
static const ScriptTemplate * Fibonacci();
|
||||
static const ScriptTemplate * Mandelbrot();
|
||||
static const ScriptTemplate * Polynomial();
|
||||
const char * name() const { return m_name; }
|
||||
const char * content() const { return m_content; }
|
||||
const char * content() const { return m_value+1; }
|
||||
const char * value() const { return m_value; }
|
||||
private:
|
||||
const char * m_name;
|
||||
const char * m_content;
|
||||
const char * m_value; // hold the 'importation status' flag concatenate with the script content
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -63,9 +63,9 @@ public:
|
||||
Record recordWithExtensionAtIndex(const char * extension, int index);
|
||||
Record recordNamed(const char * name);
|
||||
typedef uint16_t record_size_t;
|
||||
constexpr static size_t k_storageSize = 4096;
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xEE0BDDBA;
|
||||
constexpr static size_t k_storageSize = 4096;
|
||||
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
|
||||
|
||||
/* Getters/Setters on recordID */
|
||||
|
||||
Reference in New Issue
Block a user