From caa12ec49ec5a80aa6afd6473fc7bf8839856d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 3 Aug 2018 11:16:50 +0200 Subject: [PATCH] [poincare] Ghost nodes --- .../allocation_failed_expression_node.h | 16 ++--- .../poincare/allocation_failed_layout_node.h | 38 ++---------- poincare/include/poincare/evaluation.h | 5 ++ poincare/include/poincare/expression_node.h | 15 +++-- .../include/poincare/ghost_expression_node.h | 43 ++++++++++++++ poincare/include/poincare/ghost_layout_node.h | 58 +++++++++++++++++++ poincare/include/poincare/layout_node.h | 2 + poincare/include/poincare/tree_node.h | 6 +- poincare/include/poincare/tree_pool.h | 2 +- poincare/src/expression_node.cpp | 7 +++ poincare/src/layout_node.cpp | 7 +++ 11 files changed, 146 insertions(+), 53 deletions(-) create mode 100644 poincare/include/poincare/ghost_expression_node.h create mode 100644 poincare/include/poincare/ghost_layout_node.h diff --git a/poincare/include/poincare/allocation_failed_expression_node.h b/poincare/include/poincare/allocation_failed_expression_node.h index 53fb7a1f5..1635370bd 100644 --- a/poincare/include/poincare/allocation_failed_expression_node.h +++ b/poincare/include/poincare/allocation_failed_expression_node.h @@ -1,28 +1,22 @@ #ifndef POINCARE_ALLOCATION_FAILED_EXPRESSION_NODE_H #define POINCARE_ALLOCATION_FAILED_EXPRESSION_NODE_H -#include -#include -#include -#include +#include +#include namespace Poincare { -class AllocationFailedExpressionNode : public ExpressionNode { +class AllocationFailedExpressionNode : public GhostExpressionNode { public: // ExpressionNode Type type() const override { return Type::AllocationFailure; } - EvaluationReference approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference::Undefined(); } - EvaluationReference approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference::Undefined(); } - LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; - int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override; + LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return AllocationFailedLayoutRef(); } // TreeNode size_t size() const override { return sizeof(AllocationFailedExpressionNode); } #if TREE_LOG - const char * description() const override { return "Allocation Failed"; } + const char * description() const override { return "AllocationFailedExpression"; } #endif - int numberOfChildren() const override { return 0; } bool isAllocationFailure() const override { return true; } }; diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 64f6706ff..945b67df4 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -1,47 +1,19 @@ #ifndef POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H #define POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H -#include "layout_node.h" -#include "layout_reference.h" -#include "layout_cursor.h" +#include "ghost_layout_node.h" namespace Poincare { -class AllocationFailedLayoutNode : public LayoutNode { +class AllocationFailedLayoutNode : public GhostLayoutNode { public: - // LayoutNode - int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { - assert(false); - return 0; - } - void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} - void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} - LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); } - void deleteBeforeCursor(LayoutCursor * cursor) override {} - bool isAllocationFailure() const override { return true; } - + using GhostLayoutNode::GhostLayoutNode; // TreeNode - int numberOfChildren() const override { return 0; } + bool isAllocationFailure() const override { return true; } size_t size() const override { return sizeof(AllocationFailedLayoutNode); } #if TREE_LOG - const char * description() const override { return "Allocation Failed"; } + const char * description() const override { return "AllocationFailedLayout"; } #endif - -protected: - // LayoutNode - KDSize computeSize() override { return KDSizeZero; } - KDCoordinate computeBaseline() override { return 0; } - KDPoint positionOfChild(LayoutNode * child) override { - assert(false); - return KDPointZero; - } - -private: - bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; } - bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override { return false; } - bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override { return false; } - - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} }; class AllocationFailedLayoutRef : public LayoutReference { diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index 238da5b3d..e1c858155 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -35,6 +35,11 @@ public: virtual EvaluationReference transpose() const = 0; // TreeNode + TreeNode * ghostStaticNode() override { + assert(false); + return FailedAllocationStaticNode(); + } + static TreeNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index a3bd93c6a..4b23341f8 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -14,14 +14,15 @@ namespace Poincare { * ExpressionRef. */ class ExpressionNode : public SerializableNode { -friend class ApproximationEngine; -friend class SymbolNode; + friend class ApproximationEngine; + friend class SymbolNode; friend class NAryExpressionNode; public: enum class Type : uint8_t { - AllocationFailure = 0, - Undefined = 1, - Integer = 2, + Ghost = 0, + AllocationFailure = 1, + Undefined = 2, + Integer = 3, Rational, Decimal, Float, @@ -86,6 +87,10 @@ public: PredictionInterval, EmptyExpression }; + /* Ghost */ + static TreeNode * GhostStaticNode(); + TreeNode * ghostStaticNode() override { return GhostStaticNode(); } + /* Allocation failure */ static TreeNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } diff --git a/poincare/include/poincare/ghost_expression_node.h b/poincare/include/poincare/ghost_expression_node.h new file mode 100644 index 000000000..857859109 --- /dev/null +++ b/poincare/include/poincare/ghost_expression_node.h @@ -0,0 +1,43 @@ +#ifndef POINCARE_GHOST_EXPRESSION_NODE_H +#define POINCARE_GHOST_EXPRESSION_NODE_H + +#include +#include +#include +#include +#include + +namespace Poincare { + +class GhostExpressionNode : public ExpressionNode { +public: + // ExpressionNode + Type type() const override { return Type::Ghost; } + EvaluationReference approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference::Undefined(); } + EvaluationReference approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference::Undefined(); } + LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return GhostLayoutRef(); } + int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override { + int descriptionLength = strlen(description()) + 1; + return strlcpy(buffer, description(), bufferSize < descriptionLength ? bufferSize : descriptionLength); + } + + // TreeNode + size_t size() const override { return sizeof(GhostExpressionNode); } +#if TREE_LOG + const char * description() const override { return "GhostExpression"; } +#endif + int numberOfChildren() const override { return 0; } +}; + +class GhostExpressionRef : public ExpressionReference { +public: + GhostExpressionRef() : ExpressionReference() { + TreeNode * node = TreePool::sharedPool()->createTreeNode(); + m_identifier = node->identifier(); + } + GhostExpressionRef(TreeNode * n) : ExpressionReference(n) {} +}; + +} + +#endif diff --git a/poincare/include/poincare/ghost_layout_node.h b/poincare/include/poincare/ghost_layout_node.h new file mode 100644 index 000000000..73001d10d --- /dev/null +++ b/poincare/include/poincare/ghost_layout_node.h @@ -0,0 +1,58 @@ +#ifndef POINCARE_GHOST_LAYOUT_NODE_H +#define POINCARE_GHOST_LAYOUT_NODE_H + +#include "layout_node.h" +#include "layout_reference.h" +#include "layout_cursor.h" + +namespace Poincare { + +class GhostLayoutNode : public LayoutNode { +public: + // LayoutNode + int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { + assert(false); + int descriptionLength = strlen(description()) + 1; + return strlcpy(buffer, description(), bufferSize < descriptionLength ? bufferSize : descriptionLength); + } + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} + LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); } + void deleteBeforeCursor(LayoutCursor * cursor) override {} + + // TreeNode + int numberOfChildren() const override { return 0; } + size_t size() const override { return sizeof(GhostLayoutNode); } +#if TREE_LOG + const char * description() const override { return "GhostLayout"; } +#endif + +protected: + // LayoutNode + KDSize computeSize() override { return KDSizeZero; } + KDCoordinate computeBaseline() override { return 0; } + KDPoint positionOfChild(LayoutNode * child) override { + assert(false); + return KDPointZero; + } + +private: + bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; } + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override { return false; } + bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override { return false; } + + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} +}; + +class GhostLayoutRef : public LayoutReference { +public: + GhostLayoutRef() : LayoutReference() { + TreeNode * node = TreePool::sharedPool()->createTreeNode(); + m_identifier = node->identifier(); + } + GhostLayoutRef(TreeNode * n) : LayoutReference(n) {} +}; + +} + +#endif diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index a478f3460..d9b2c4f3c 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -50,6 +50,8 @@ public: virtual void invalidAllSizesPositionsAndBaselines(); // TreeNode + static TreeNode * GhostStaticNode(); + TreeNode * ghostStaticNode() override { return GhostStaticNode(); } static TreeNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 57ce418cf..8278ad6dd 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -46,9 +46,9 @@ public: // Allocation failure virtual bool isAllocationFailure() const { return false; } virtual TreeNode * failedAllocationStaticNode() = 0; - int allocationFailureNodeIdentifier() { - return failedAllocationStaticNode()->identifier(); - } + int allocationFailureNodeIdentifier() { return failedAllocationStaticNode()->identifier(); } + virtual TreeNode * ghostStaticNode() = 0; + int ghostNodeIdentifier() { return ghostStaticNode()->identifier(); } // Node operations void retain() { diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 15686c716..a6edf845d 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -85,7 +85,7 @@ public: private: constexpr static int BufferSize = 1024;//2048; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); - constexpr static int MaxNumberOfStaticNodes = 2; // ExpressionNode, LayoutNode + constexpr static int MaxNumberOfStaticNodes = 5; // GhostLayoutNode, AllocationFailedLayoutNode, GhostExpressionNode, AllocationFailedExpressionNode, AllocationFailedEvaluationNode // TreeNode void discardTreeNode(TreeNode * node) { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 66ba5d07e..36d1ff1fc 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -1,9 +1,16 @@ #include #include +#include #include namespace Poincare { +TreeNode * ExpressionNode::GhostStaticNode() { + static GhostExpressionNode GhostNode; + TreePool::sharedPool()->registerStaticNodeIfRequired(&GhostNode); + return &GhostNode; +} + TreeNode * ExpressionNode::FailedAllocationStaticNode() { static AllocationFailedExpressionNode FailureNode; TreePool::sharedPool()->registerStaticNodeIfRequired(&FailureNode); diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index d57e45d8a..fccac0e9a 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -67,6 +68,12 @@ void LayoutNode::invalidAllSizesPositionsAndBaselines() { // TreeNode +TreeNode * LayoutNode::GhostStaticNode() { + static GhostStaticNode GhostNode; + TreePool::sharedPool()->registerStaticNodeIfRequired(&GhostNode); + return &GhostNode; +} + TreeNode * LayoutNode::FailedAllocationStaticNode() { static AllocationFailedLayoutNode FailureNode; TreePool::sharedPool()->registerStaticNodeIfRequired(&FailureNode);