diff --git a/apps/shared/storage_cartesian_function.cpp b/apps/shared/storage_cartesian_function.cpp index 8c1c56e3c..f1fbe8d16 100644 --- a/apps/shared/storage_cartesian_function.cpp +++ b/apps/shared/storage_cartesian_function.cpp @@ -109,7 +109,7 @@ void * StorageCartesianFunction::expressionAddress() const { size_t StorageCartesianFunction::expressionSize() const { assert(!record().isNull()); Ion::Storage::Record::Data d = record().value(); - return d.size-sizeof(FunctionRecordData); + return d.size-sizeof(CartesianFunctionRecordData); } StorageCartesianFunction::CartesianFunctionRecordData * StorageCartesianFunction::recordData() const { diff --git a/apps/shared/storage_cartesian_function.h b/apps/shared/storage_cartesian_function.h index 10b23c4fb..53387e472 100644 --- a/apps/shared/storage_cartesian_function.h +++ b/apps/shared/storage_cartesian_function.h @@ -33,7 +33,6 @@ public: return x; } // StorageExpressionModel - void setContent(const char * c) override; void * expressionAddress() const override; size_t expressionSize() const override; //TODO protected: @@ -41,16 +40,16 @@ public: public: CartesianFunctionRecordData() : FunctionRecordData(), - m_displayDerivative(true) + m_displayDerivative(true) {} bool displayDerivative() const { return m_displayDerivative; } void setDisplayDerivative(bool display) { m_displayDerivative = display; } - void * expressionAddress() { return &m_expression; } private: bool m_displayDerivative; char m_expression[0]; }; private: + size_t metaDataSize() override { return sizeof(CartesianFunctionRecordData); } CartesianFunctionRecordData * recordData() const; }; diff --git a/apps/shared/storage_expression_model.cpp b/apps/shared/storage_expression_model.cpp index 928c22e24..62fa0d6f5 100644 --- a/apps/shared/storage_expression_model.cpp +++ b/apps/shared/storage_expression_model.cpp @@ -6,53 +6,39 @@ #include #include +using namespace Ion; using namespace Poincare; namespace Shared { -StorageExpressionModel::StorageExpressionModel(const char * name) : - m_name(name), +StorageExpressionModel::StorageExpressionModel(Storage::Record record) : + Storage::Record(record), m_expression(), - m_layout(), - m_record() + m_layout() { + assert(!isNull()); } -StorageExpressionModel::StorageExpressionModel(Ion::Storage::Record record) : - m_name(record.fullName()), - m_expression(), - m_layout(), - m_record(record) -{ -} - -void StorageExpressionModel::destroy() { - record().destroy(); -} - -void StorageExpressionModel::text(char * buffer, size_t bufferSize) const { +/*void StorageExpressionModel::text(char * buffer, size_t bufferSize) const { Expression e = expression(); if (e.isUninitialized() && bufferSize > 0) { buffer[0] = 0; } else { e.serialize(buffer, bufferSize); } -} +}*/ -Expression StorageExpressionModel::expression() const { - if (m_expression.isUninitialized() && !m_record.isNull()) { - m_expression = Expression::ExpressionFromAddress(expressionAddress(), expressionSize()); +Expression StorageExpressionModel::expression(Poincare::Context * context) const { + if (m_expression.isUninitialized()) { + m_expression = Expression::ExpressionFromAddress(expressionAddress(), expressionSize()).deepReduce(*context, Preferences::AngleUnit::Degree, true); } return m_expression; } -Expression StorageExpressionModel::reducedExpression(Poincare::Context * context) const { - return expression().clone().deepReduce(*context, Preferences::AngleUnit::Degree, true); -} Layout StorageExpressionModel::layout() { - if (m_layout.isUninitialized() && !m_record.isNull()) { - m_layout = PoincareHelpers::CreateLayout(expression()); + if (m_layout.isUninitialized()) { + m_layout = PoincareHelpers::CreateLayout(Expression::ExpressionFromAddress(expressionAddress(), expressionSize())); if (m_layout.isUninitialized()) { m_layout = HorizontalLayout(); } @@ -65,7 +51,7 @@ bool StorageExpressionModel::isDefined() { } bool StorageExpressionModel::isEmpty() { - return record().isNull() || (record().value().size == 0); + return record().value().size == 0; } void StorageExpressionModel::tidy() { @@ -73,7 +59,8 @@ void StorageExpressionModel::tidy() { m_expression = Expression(); } -Expression StorageExpressionModel::expressionToStoreFromString(const char * c) { +Ion::Storage::Record::ErrorStatus StorageExpressionModel::setContent(const char * c) { + // Compute the expression to store Expression expressionToStore = Expression::parse(c); if (!expressionToStore.isUninitialized()) { GlobalContext context; @@ -84,20 +71,41 @@ Expression StorageExpressionModel::expressionToStoreFromString(const char * c) { expressionToStore = expressionToStore.replaceSymbolWithExpression(Symbol("x", 1), xUnknown); } } - return expressionToStore; + return setExpressionContent(expressionToStore); } -void StorageExpressionModel::didSetContentData() { +Ion::Storage::Record::ErrorStatus StorageExpressionModel::setExpressionContent(Expression & expressionToStore) { + // Prepare the new data to store + Ion::Storage::Record::Data newData = value(); + size_t expressionToStoreSize = expressionToStore.isUninitialized() ? 0 : expressionToStore.size(); + newData.size = metaDataSize() + expressionToStoreSize; + + // Set the data + Ion::Storage::Record::ErrorStatus error = record().setValue(newData); + if (error != Ion::Storage::Record::ErrorStatus::None) { + assert(error == Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable); + return error; + } + + // Copy the expression if needed + if (!expressionToStore.isUninitialized()) { + memcpy(expressionAddress(), expressionToStore.addressInPool(), expressionToStore.size()); + } + /* We cannot call tidy here because tidy is a virtual function and does not + * do the same thing for all children class. And here we want to delete only + * the m_layout and m_expression. */ m_layout = Layout(); m_expression = Expression(); + return error; } +void * StorageExpressionModel::expressionAddress() const { + return (char *)value().buffer+metaDataSize(); +} -Ion::Storage::Record StorageExpressionModel::record() const { - if (m_record.isNull()) { - m_record = Ion::Storage::sharedStorage()->recordNamed(m_name); - } - return m_record; +size_t StorageExpressionModel::expressionSize() const { + assert(!isNull()); + return value().size-metaDataSize(); } } diff --git a/apps/shared/storage_expression_model.h b/apps/shared/storage_expression_model.h index 859fb128d..20da7bae6 100644 --- a/apps/shared/storage_expression_model.h +++ b/apps/shared/storage_expression_model.h @@ -8,16 +8,14 @@ namespace Shared { -class StorageExpressionModel { +// StorageExpressionModel is a handle to Ion::Record + +class StorageExpressionModel : public Ion::Storage::Record { // TODO find better name (once we remove ExpressionModel?) public: - StorageExpressionModel(const char * name); StorageExpressionModel(Ion::Storage::Record record); - void destroy(); - const char * name() const { return m_name; } - void text(char * buffer, size_t bufferSize) const; - Poincare::Expression expression() const; - Poincare::Expression reducedExpression(Poincare::Context * context) const; + //void text(char * buffer, size_t bufferSize) const; + Poincare::Expression expression(Poincare::Context * context) const; Poincare::Layout layout(); /* TODO This comment will be true when Sequence inherits from this class * Here, isDefined is the exact contrary of isEmpty. However, for Sequence @@ -27,19 +25,16 @@ public: virtual bool isDefined(); virtual bool isEmpty(); virtual bool shouldBeClearedBeforeRemove() { return !isEmpty(); } - virtual void setContent(const char * c) = 0; virtual void tidy(); - virtual void * expressionAddress() const = 0; - virtual size_t expressionSize() const = 0; + virtual Ion::Storage::Record::ErrorStatus setContent(const char * c); + Ion::Storage::Record::ErrorStatus setExpressionContent(Poincare::Expression & e); protected: - Poincare::Expression expressionToStoreFromString(const char * c); - void didSetContentData(); + void * expressionAddress() const; + size_t expressionSize() const;; + virtual size_t metaDataSize() const = 0; Ion::Storage::Record record() const; - const char * m_name; mutable Poincare::Expression m_expression; mutable Poincare::Layout m_layout; -private: - mutable Ion::Storage::Record m_record; }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 7eac460dc..02e362b7d 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -92,7 +92,7 @@ public: Expression() : TreeHandle() {} Expression clone() const; static Expression parse(char const * string); - static const Expression ExpressionFromAddress(const void * address, size_t size); + static Expression ExpressionFromAddress(const void * address, size_t size); /* Circuit breaker */ typedef bool (*CircuitBreaker)();