Files
Upsilon/apps/code/script_store.cpp
Léa Saviot fbb5c70339 [code] Cleaned Script and ScriptStore classes, created accordion.h
A Script object now contains its AutoImport marker, its name and its
content. The ScripStore methods have better names and the optimization
is cleaner.

Change-Id: I1b21af2d23f1c9a34f984309512b0c01b2f1c320
2017-11-17 11:59:50 +01:00

187 lines
5.6 KiB
C++

#include "script_store.h"
#include "string.h"
#include <stddef.h>
namespace Code {
constexpr char ScriptStore::k_defaultScriptName[];
ScriptStore::ScriptStore() :
m_accordion(m_scriptData, k_scriptDataSize)
{
}
const Script ScriptStore::scriptAtIndex(int index, EditableZone zone) {
assert(index >= 0 && index < numberOfScripts());
size_t nameBufferSize = 0;
size_t contentBufferSize = 0;
int accordionIndex;
// Move the Free Space at the end of the correct string.
switch (zone) {
case EditableZone::None:
break;
case EditableZone::Name:
accordionIndex = accordionIndexOfNameOfScriptAtIndex(index);
nameBufferSize = m_accordion.sizeOfEditableBufferAtIndex(accordionIndex);
break;
case EditableZone::Content:
accordionIndex = accordionIndexOfContentOfScriptAtIndex(index);
contentBufferSize = m_accordion.sizeOfEditableBufferAtIndex(accordionIndex);
break;
}
// Compute the positions and lengths of the Script Marker, Name and Content.
const char * marker = m_accordion.bufferAtIndex(accordionIndexOfMarkersOfScriptAtIndex(index));
const char * name = m_accordion.bufferAtIndex(accordionIndexOfNameOfScriptAtIndex(index));
if (nameBufferSize == 0) {
nameBufferSize = strlen(name);
}
const char * content = m_accordion.bufferAtIndex(accordionIndexOfContentOfScriptAtIndex(index));
if (contentBufferSize == 0) {
contentBufferSize = strlen(content);
}
return Script(marker, name, nameBufferSize, content, contentBufferSize);
}
const Script ScriptStore::scriptNamed(const char * name) {
for (int i = 0; i < numberOfScripts(); i++) {
int accordionIndex = accordionIndexOfNameOfScriptAtIndex(i);
const char * currentScriptName = m_accordion.bufferAtIndex(accordionIndex);
if (strcmp(currentScriptName, name) == 0) {
return scriptAtIndex(i);
}
}
return Script();
}
int ScriptStore::numberOfScripts() {
return (m_accordion.numberOfBuffers())/Script::NumberOfStringsPerScript;
}
bool ScriptStore::addNewScript(DefaultScript defaultScript) {
const char autoImportationString[2] = {Script::DefaultAutoImportationMarker, 0};
if (!m_accordion.appendBuffer(autoImportationString)) {
return false;
}
const char * name = nullptr;
switch (defaultScript) {
case DefaultScript::Empty:
name = k_defaultScriptName;
break;
case DefaultScript::Mandelbrot:
name = "mandelbrot.py";
break;
case DefaultScript::Factorial:
name = "factorial.py";
break;
}
if (!m_accordion.appendBuffer(name)) {
// Delete the Auto Importation Marker
m_accordion.deleteLastBuffer();
return false;
}
bool didCopy = false;
switch (defaultScript) {
case DefaultScript::Empty:
didCopy = copyEmptyScriptOnFreeSpace();
break;
case DefaultScript::Mandelbrot:
didCopy = copyMandelbrotScriptOnFreeSpace();
break;
case DefaultScript::Factorial:
didCopy = copyFactorialScriptOnFreeSpace();
break;
}
if (didCopy) {
return true;
}
// Delete the Auto Importation Marker and the Name Of the Script
m_accordion.deleteLastBuffer();
m_accordion.deleteLastBuffer();
return false;
}
bool ScriptStore::renameScriptAtIndex(int index, const char * newName) {
assert (index >= 0 && index < numberOfScripts());
int accordionIndex = accordionIndexOfNameOfScriptAtIndex(index);
return m_accordion.replaceBufferAtIndex(accordionIndex, newName);
}
void ScriptStore::deleteScriptAtIndex(int index) {
assert (index >= 0 && index < numberOfScripts());
int accordionIndex = accordionIndexOfContentOfScriptAtIndex(index);
// We delete in reverse order because we want the indexes to stay true.
m_accordion.deleteBufferAtIndex(accordionIndex);
m_accordion.deleteBufferAtIndex(accordionIndex-1);
m_accordion.deleteBufferAtIndex(accordionIndex-2);
}
void ScriptStore::deleteAllScripts() {
m_accordion.deleteAll();
}
const char * ScriptStore::contentOfScript(const char * name) {
Script script = scriptNamed(name);
if (script.isNull()) {
return nullptr;
}
return script.content();
}
int ScriptStore::accordionIndexOfMarkersOfScriptAtIndex(int index) const {
return index * Script::NumberOfStringsPerScript;
}
int ScriptStore::accordionIndexOfNameOfScriptAtIndex(int index) const {
return index * Script::NumberOfStringsPerScript + 1;
}
int ScriptStore::accordionIndexOfContentOfScriptAtIndex(int index) const {
return index * Script::NumberOfStringsPerScript + 2;
}
bool ScriptStore::copyMandelbrotScriptOnFreeSpace() {
const char script[] = R"(# This script draws a Mandelbrot fractal set
# N_iteration: degree of precision
import kandinsky
N_iteration = 10
for x in range(320):
for y in range(240):
# Compute the mandelbrot sequence for the point c = (c_r, c_i) with start value z = (z_r, z_i)
z_r = 0
z_i = 0
# Rescale to fit the drawing screen 320x222
c_r = 2.7*x/319-2.1
c_i = -1.87*y/221+0.935
i = 0
while (i < N_iteration) and ((z_r * z_r) + (z_i * z_i) < 4):
i = i + 1
stock = z_r
z_r = z_r * z_r - z_i * z_i + c_r
z_i = 2 * stock * z_i + c_i
# Choose the color of the dot from the Mandelbrot sequence
rgb = int(255*i/N_iteration)
col = kandinsky.color(int(rgb),int(rgb*0.75),int(rgb*0.25))
# Draw a pixel colored in 'col' at position (x,y)
kandinsky.set_pixel(x,y,col))";
return m_accordion.appendBuffer(script);
}
bool ScriptStore::copyFactorialScriptOnFreeSpace() {
const char script[] = R"(def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1))";
return m_accordion.appendBuffer(script);
}
bool ScriptStore::copyEmptyScriptOnFreeSpace() {
const char script[] = "\0";
return m_accordion.appendBuffer(script);
}
}