From 5d4a3f8726c421cfd3f8b25403c74b3b01da876c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Mar 2020 11:19:54 +0100 Subject: [PATCH] [apps/code] Add variables in alphabetical order in the var box --- apps/code/variable_box_controller.cpp | 73 ++++++++++++++++++++------- apps/code/variable_box_controller.h | 19 ++++++- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index d3f036831..20ae11258 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -242,11 +242,7 @@ void VariableBoxController::loadFunctionsAndVariables(int scriptIndex, const cha if (!alreadyInVarBox) { tokenInText -= 2; - if (defToken) { - addFunctionAtIndex(tokenInText, nameLength, scriptIndex); - } else { - addVariableAtIndex(tokenInText, nameLength, scriptIndex); - } + addNode(defToken ? NodeType::Function : NodeType::Variable, NodeOrigin::CurrentScript, tokenInText, nameLength, scriptIndex); } } defToken = lex->tok_kind == MP_TOKEN_KW_DEF; @@ -379,23 +375,50 @@ void VariableBoxController::insertTextInCaller(const char * text, int textLength sender()->handleEventWithText(commandBuffer); } -// TODO LEA remane method (index) -void VariableBoxController::addFunctionAtIndex(const char * functionName, int nameLength, int scriptIndex) { - // TODO LEA check if current script or imported - if (m_currentScriptNodesCount < k_maxScriptNodesCount) { - m_currentScriptNodes[m_currentScriptNodesCount] = ScriptNode::FunctionNode(functionName, nameLength, scriptIndex); - m_currentScriptNodesCount++; +void VariableBoxController::addNode(NodeType type, NodeOrigin origin, const char * name, int nameLength, int scriptIndex) { + assert(origin == NodeOrigin::CurrentScript || origin == NodeOrigin::Importation); + int * currentNodeCount = nodesCountForOrigin(origin); + if (*currentNodeCount >= MaxNodesCountForOrigin(origin)) { + // There is no room to add another node + return; } + /* We want to insert the node in alphabetical order, so we look for the + * insertion index. */ + ScriptNode * nodes = origin == NodeOrigin::CurrentScript ? m_currentScriptNodes : m_importedNodes; + int insertionIndex = 0; + while (insertionIndex < *currentNodeCount) { + ScriptNode * node = nodes + insertionIndex; + int nameComparison = NodeNameCompare(node, name, nameLength); + assert(nameComparison != 0); // We already checked that the name is not present already + if (nameComparison > 0) { + break; + } + insertionIndex++; + } + + // Shift all the following nodes + for (int i = *currentNodeCount; i >= insertionIndex; i--) { + nodes[i+1] = nodes[i]; + } + // Add the node + nodes[insertionIndex] = type == NodeType::Variable ? + ScriptNode::VariableNode(name, nameLength, scriptIndex) : + ScriptNode::FunctionNode(name, nameLength, scriptIndex); + // Increase the node count + *currentNodeCount = *currentNodeCount + 1; } -// TODO LEA remane method (index) -// + factorize with addFunctionAtIndex? -void VariableBoxController::addVariableAtIndex(const char * variableName, int nameLength, int scriptIndex) { - // TODO LEA check if current script or imported - if (m_currentScriptNodesCount < k_maxScriptNodesCount) { - m_currentScriptNodes[m_currentScriptNodesCount] = ScriptNode::VariableNode(variableName, nameLength, scriptIndex); - m_currentScriptNodesCount++; +int VariableBoxController::MaxNodesCountForOrigin(NodeOrigin origin) { + assert(origin == NodeOrigin::CurrentScript || origin == NodeOrigin::Importation); + return k_maxScriptNodesCount; +} + +int * VariableBoxController::nodesCountForOrigin(NodeOrigin origin) { + if (origin == NodeOrigin::CurrentScript) { + return &m_currentScriptNodesCount; } + assert(origin == NodeOrigin::Importation); + return &m_importedNodesCount; } ScriptNode * VariableBoxController::scriptNodeAtIndex(int index) { @@ -413,4 +436,18 @@ ScriptNode * VariableBoxController::scriptNodeAtIndex(int index) { return node; } +int VariableBoxController::NodeNameCompare(ScriptNode * node, const char * name, int nameLength) { + const char * nodeName = node->name(); + const int nodeNameLength = node->nameLength(); + const int comparisonLength = minInt(nameLength, nodeNameLength); + int result = strncmp(nodeName, name, comparisonLength); + if (result != 0) { + return result; + } + if (nodeNameLength == nameLength) { + return 0; + } + return comparisonLength == nodeNameLength ? -1 : 1; +} + } diff --git a/apps/code/variable_box_controller.h b/apps/code/variable_box_controller.h index 3c77772e9..aba71799b 100644 --- a/apps/code/variable_box_controller.h +++ b/apps/code/variable_box_controller.h @@ -37,8 +37,23 @@ private: HighlightCell * nodeCellAtIndex(int index) override { return nullptr; } bool selectLeaf(int rowIndex) override; void insertTextInCaller(const char * text, int textLength = -1); - void addFunctionAtIndex(const char * functionName, int nameLength, int scriptIndex); - void addVariableAtIndex(const char * variableName, int nameLength, int scriptIndex); + enum class NodeOrigin : uint8_t { + CurrentScript, + Builtins, + Importation + }; + enum class NodeType : uint8_t { + Variable, + Function + }; + void addNode(NodeType type, NodeOrigin origin, const char * name, int nameLength, int scriptIndex = 0); + static int MaxNodesCountForOrigin(NodeOrigin origin); + int * nodesCountForOrigin(NodeOrigin origin); + + /* Return a negative int if the node name is before name in alphabetical + * order, 0 if they are equal, a positive int if it is after in alphabetical + * order. */ + static int NodeNameCompare(ScriptNode * node, const char * name, int nameLength); ScriptNode * scriptNodeAtIndex(int index); ScriptNode m_currentScriptNodes[k_maxScriptNodesCount]; ScriptNode m_builtinNodes[k_builtinNodesCount];