From 9a1ff2bd33c1185a6417f61f613c5c9ae9bf0fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 5 Jun 2020 11:28:12 +0200 Subject: [PATCH] [apps/code] Status at the beginning of a script is one byte long This saves space + avoids clashes with the NumWorks Workshop when exchanging scripts --- apps/code/editor_controller.cpp | 4 ++-- apps/code/script.cpp | 16 ++++++++++------ apps/code/script.h | 19 ++++++++++++++----- apps/code/script_store.cpp | 2 +- apps/code/script_template.cpp | 10 +++++----- apps/code/script_template.h | 2 +- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/apps/code/editor_controller.cpp b/apps/code/editor_controller.cpp index 2c003df88..bee8bb5d9 100644 --- a/apps/code/editor_controller.cpp +++ b/apps/code/editor_controller.cpp @@ -37,7 +37,7 @@ void EditorController::setScript(Script script, int scriptIndex) { * */ size_t newScriptSize = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(m_script); - m_editorView.setText(const_cast(m_script.content()), newScriptSize - Script::InformationSize()); + m_editorView.setText(const_cast(m_script.content()), newScriptSize - Script::StatusSize()); } void EditorController::willExitApp() { @@ -156,7 +156,7 @@ void EditorController::cleanStorageEmptySpace() { Ion::Storage::Record::Data scriptValue = m_script.value(); Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord( m_script, - scriptValue.size - Script::InformationSize() - (strlen(m_script.content()) + 1)); // TODO optimize number of script fetches + scriptValue.size - Script::StatusSize() - (strlen(m_script.content()) + 1)); // TODO optimize number of script fetches } diff --git a/apps/code/script.cpp b/apps/code/script.cpp index 6615eed4a..bee1db59f 100644 --- a/apps/code/script.cpp +++ b/apps/code/script.cpp @@ -68,19 +68,19 @@ bool Script::nameCompliant(const char * name) { bool Script::autoImportationStatus() const { assert(!isNull()); Data d = value(); - return (((char *)d.buffer)[0] == 1); + return (*statusFromData(d) & k_autoImportationStatusMask) == 1; } void Script::toggleAutoimportationStatus() { assert(!isNull()); Data d = value(); - ((char *)d.buffer)[0] = (((char *)d.buffer)[0] == 1 ? 0 : 1); + *statusFromData(d) ^= k_autoImportationStatusMask; setValue(d); } const char * Script::content() const { Data d = value(); - return ((const char *)d.buffer) + InformationSize(); + return ((const char *)d.buffer) + StatusSize(); } bool Script::contentFetchedFromConsole() const { @@ -106,19 +106,23 @@ void Script::resetContentFetchedStatus() { Script::FetchedStatus Script::fetchedStatus() const { assert(!isNull()); Data d = value(); - uint8_t status = const_cast(static_cast(d.buffer))[k_autoImportationStatusSize]; + uint8_t status = (*statusFromData(d)) >> k_fetchedStatusOffset; assert(status == static_cast(FetchedStatus::None) || status == static_cast(FetchedStatus::FromConsole) || status == static_cast(FetchedStatus::ForVariableBox)); return static_cast(status); } -void Script::setFetchedStatus(FetchedStatus status) { +void Script::setFetchedStatus(FetchedStatus fetchedStatus) { assert(!isNull()); Data d = value(); - const_cast(static_cast(d.buffer))[k_autoImportationStatusSize] = static_cast(status); + uint8_t * status = statusFromData(d); + *status = ((*status) & ~k_fetchedStatusMask) | (static_cast(fetchedStatus) << k_fetchedStatusOffset); //TODO Create and use a bit operations library setValue(d); } +uint8_t * Script::statusFromData(Data d) const { + return const_cast(static_cast(d.buffer)); +} } diff --git a/apps/code/script.h b/apps/code/script.h index b5b1cadf6..fbbb66267 100644 --- a/apps/code/script.h +++ b/apps/code/script.h @@ -5,8 +5,12 @@ namespace Code { -/* Record: | Size | Name | Body | - * Script: | | | AutoImportationStatus | FetchedStatus | Content | +/* Record: | Size | Name | Body | + * Script: | | | Status | Content | + * + * Status is a byte long: xxxxxxxx + * ^^ ^ + * FetchedStatus AutoImportationStatus * * AutoImportationStatus is 1 if the script should be auto imported when the * console opens. @@ -27,8 +31,8 @@ private: static constexpr int k_maxNumberOfDefaultScriptNames = 99; static constexpr int k_defaultScriptNameNumberMaxSize = 2; // Numbers from 1 to 99 have 2 digits max - static constexpr size_t k_autoImportationStatusSize = 1; // TODO use only 1 byte for both status flags - static constexpr size_t k_currentImportationStatusSize = 1; + // See the comment at the beginning of the file + static constexpr size_t k_statusSize = 1; public: static constexpr int k_defaultScriptNameMaxSize = 6 + k_defaultScriptNameNumberMaxSize + 1; @@ -38,7 +42,7 @@ public: static bool DefaultName(char buffer[], size_t bufferSize); static bool nameCompliant(const char * name); - static constexpr size_t InformationSize() { return k_autoImportationStatusSize + k_currentImportationStatusSize; } + static constexpr size_t StatusSize() { return k_statusSize; } Script(Ion::Storage::Record r = Ion::Storage::Record()) : Record(r) {} @@ -51,6 +55,10 @@ public: void setContentFetchedForVariableBox(); void resetContentFetchedStatus(); private: + static constexpr uint8_t k_autoImportationStatusMask = 0b1; + static constexpr uint8_t k_fetchedStatusBits = 0b11; + static constexpr uint8_t k_fetchedStatusOffset = 6; + static constexpr uint8_t k_fetchedStatusMask = k_fetchedStatusBits << k_fetchedStatusOffset; /* Fetched status */ enum class FetchedStatus : uint8_t { None = 0, @@ -59,6 +67,7 @@ private: }; FetchedStatus fetchedStatus() const; void setFetchedStatus(FetchedStatus status); + uint8_t * statusFromData(Data d) const; }; } diff --git a/apps/code/script_store.cpp b/apps/code/script_store.cpp index c6b232f13..3062eb01c 100644 --- a/apps/code/script_store.cpp +++ b/apps/code/script_store.cpp @@ -45,7 +45,7 @@ void ScriptStore::clearFetchInformation() { } Script::ErrorStatus ScriptStore::addScriptFromTemplate(const ScriptTemplate * scriptTemplate) { - size_t valueSize = Script::InformationSize() + strlen(scriptTemplate->content()) + 1; // (auto importation status + content fetched status) + scriptcontent size + null-terminating char + size_t valueSize = Script::StatusSize() + strlen(scriptTemplate->content()) + 1; // (auto importation status + content fetched status) + scriptcontent size + null-terminating char assert(Script::nameCompliant(scriptTemplate->name())); Script::ErrorStatus err = Ion::Storage::sharedStorage()->createRecordWithFullName(scriptTemplate->name(), scriptTemplate->value(), valueSize); assert(err != Script::ErrorStatus::NonCompliantName); diff --git a/apps/code/script_template.cpp b/apps/code/script_template.cpp index d2d4c9d7a..971b44496 100644 --- a/apps/code/script_template.cpp +++ b/apps/code/script_template.cpp @@ -2,10 +2,10 @@ namespace Code { -constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01\x00" R"(from math import * +constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01" R"(from math import * )"); -constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01\x00" R"(from math import * +constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01" R"(from math import * from turtle import * def squares(angle=0.5): reset() @@ -20,7 +20,7 @@ def squares(angle=0.5): L=L-L*sin(angle*pi/180) hideturtle())"); -constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", "\x01\x00" 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): @@ -40,7 +40,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", "\x01\x00" 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 @@ -53,7 +53,7 @@ def roots(a,b,c): else: return None)"); -constexpr ScriptTemplate parabolaScriptTemplate("parabola.py", "\x01\x00" R"(from matplotlib.pyplot import * +constexpr ScriptTemplate parabolaScriptTemplate("parabola.py", "\x01" R"(from matplotlib.pyplot import * from math import * g=9.81 diff --git a/apps/code/script_template.h b/apps/code/script_template.h index 02a53f87d..ec32e7052 100644 --- a/apps/code/script_template.h +++ b/apps/code/script_template.h @@ -14,7 +14,7 @@ public: static const ScriptTemplate * Polynomial(); static const ScriptTemplate * Parabola(); const char * name() const { return m_name; } - const char * content() const { return m_value + Script::InformationSize(); } + const char * content() const { return m_value + Script::StatusSize(); } const char * value() const { return m_value; } private: const char * m_name;