[apps/code] Handle too many Script default names used

When adding to many scripts without naming them, one can overflow the
number of default generated script names, in which case we force the
user to enter a name.
This commit is contained in:
Léa Saviot
2018-11-05 17:58:42 +01:00
committed by Émilie Feral
parent 0f9d1db851
commit e74e15eaf7
5 changed files with 32 additions and 20 deletions

View File

@@ -302,15 +302,22 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char
static constexpr int bufferSize = Script::k_defaultScriptNameMaxSize + 1 + ScriptStore::k_scriptExtensionLength; //"script99" + "." + "py"
char numberedDefaultName[bufferSize];
if (strlen(text) <= 1 + strlen(ScriptStore::k_scriptExtension)) {
if (strlen(text) > 1 + strlen(ScriptStore::k_scriptExtension)) {
newName = text;
} else {
// The user entered an empty name. Use a numbered default script name.
Script::DefaultName(numberedDefaultName, Script::k_defaultScriptNameMaxSize);
bool foundDefaultName = Script::DefaultName(numberedDefaultName, Script::k_defaultScriptNameMaxSize);
int defaultNameLength = strlen(numberedDefaultName);
numberedDefaultName[defaultNameLength++] = '.';
strlcpy(&numberedDefaultName[defaultNameLength], ScriptStore::k_scriptExtension, bufferSize - defaultNameLength);
/* If there are already scripts named script1.py, script2.py,... until
* Script::k_maxNumberOfDefaultScriptNames, we want to write the last tried
* default name and let the user modify it. */
if (!foundDefaultName) {
textField->setText(numberedDefaultName);
textField->setCursorLocation(defaultNameLength);
}
newName = const_cast<const char *>(numberedDefaultName);
} else {
newName = text;
}
Script::ErrorStatus error = Script::nameCompliant(newName) ? m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()).setName(newName) : Script::ErrorStatus::NonCompliantName;
if (error == Script::ErrorStatus::None) {

View File

@@ -18,23 +18,23 @@ static inline void intToText(int i, char * buffer, int bufferSize) {
buffer[2] = 0;
}
void Script::DefaultName(char buffer[], size_t bufferSize) {
bool Script::DefaultName(char buffer[], size_t bufferSize) {
assert(bufferSize >= k_defaultScriptNameMaxSize);
static constexpr char defaultScriptName[] = "script";
static constexpr int defaultScriptNameLength = 6;
memcpy(buffer, defaultScriptName, bufferSize);
// We will only name scripts from script1.py to script99.py.
int currentScriptNumber = 1;
while (currentScriptNumber < 100) {
while (currentScriptNumber <= k_maxNumberOfDefaultScriptNames) {
// Change the number in the script name.
intToText(currentScriptNumber, &buffer[defaultScriptNameLength], bufferSize - defaultScriptNameLength );
if (ScriptStore::ScriptNameIsFree(buffer)) {
return;
return true;
}
currentScriptNumber++;
}
assert(false);
// We did not find a new script name
return false;
}
bool Script::nameCompliant(const char * name) {

View File

@@ -9,16 +9,18 @@ namespace Code {
* Script: | AutoImportationStatus | Content |*/
class Script : public Ion::Storage::Record {
private:
// Default script names are chosen between script1 and script99
static constexpr int k_maxNumberOfDefaultScriptNames = 99;
static constexpr int k_defaultScriptNameNumberMaxSize = 2; // Numbers from 1 to 99 have 2 digits max
public:
static constexpr size_t k_importationStatusSize = 1;
static constexpr int k_defaultScriptNameMaxSize = 6 + 2 + 1;
/* k_defaultScriptNameMaxSize is the length of a name between script1 and
* script99
* 6 = strlen("script")
* 2 = maxLength of integers between 1 and 99
static constexpr int k_defaultScriptNameMaxSize = 6 + k_defaultScriptNameNumberMaxSize + 1;
/* 6 = strlen("script")
* k_defaultScriptNameNumberMaxSize = maxLength of integers between 1 and 99
* 1 = null-terminating char */
static void DefaultName(char buffer[], size_t bufferSize);
static bool DefaultName(char buffer[], size_t bufferSize);
static bool nameCompliant(const char * name);
Script(Ion::Storage::Record r) : Record(r) {}

View File

@@ -47,10 +47,10 @@ private:
/* If the storage available space has a smaller size than
* k_fullFreeSpaceSizeLimit, we consider the script store as full.
* To be able to add a new empty record, the available space should at least
* stores a Script with default name "script99.py" (12 char), the importation
* status (1 char), the default content "from math import *\n" (20 char) and
* 10 char of free space. */
static constexpr int k_fullFreeSpaceSizeLimit = sizeof(Ion::Storage::record_size_t)+12+1+20+10;
* be able to store a Script with default name and its extension, the
* importation status (1 char), the default content "from math import *\n"
* (20 char) and 10 char of free space. */
static constexpr int k_fullFreeSpaceSizeLimit = sizeof(Ion::Storage::record_size_t)+Script::k_defaultScriptNameMaxSize+k_scriptExtensionLength+1+20+10;
static constexpr size_t k_fileInput2ParseNodeStructKind = 1;
static constexpr size_t k_functionDefinitionParseNodeStructKind = 3;
static constexpr size_t k_expressionStatementParseNodeStructKind = 5;

View File

@@ -57,12 +57,15 @@ size_t TextField::ContentView::editedTextLength() const {
void TextField::ContentView::setText(const char * text) {
reloadRectFromCursorPosition(0);
int textLength = strlen(text) >= m_textBufferSize ? m_textBufferSize-1 : strlen(text);
if (m_isEditing) {
strlcpy(m_draftTextBuffer, text, m_textBufferSize);
int textLength = strlen(text) >= m_textBufferSize ? m_textBufferSize-1 : strlen(text);
m_currentDraftTextLength = textLength;
} else {
strlcpy(m_textBuffer, text, m_textBufferSize);
if (m_textBuffer == m_draftTextBuffer) {
m_currentDraftTextLength = textLength;
}
}
reloadRectFromCursorPosition(0);
}