diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index 93aff8660..0c2e5f3c4 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -41,7 +41,7 @@ float GraphController::interestingXRange() { float characteristicRange = 0.0f; TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) { - StorageFunction * f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); + ExpiringPointer f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); float fRange = f->expression(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Poincare::Preferences::sharedPreferences()->angleUnit()); if (!std::isnan(fRange)) { characteristicRange = fRange > characteristicRange ? fRange : characteristicRange; @@ -56,7 +56,7 @@ int GraphController::estimatedBannerNumberOfLines() const { void GraphController::selectFunctionWithCursor(int functionIndex) { StorageFunctionGraphController::selectFunctionWithCursor(functionIndex); - StorageCartesianFunction * f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor())); + ExpiringPointer f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor())); m_cursorView.setColor(f->color()); } diff --git a/apps/graph/graph/graph_controller_helper.cpp b/apps/graph/graph/graph_controller_helper.cpp index 67f52f61d..41ca6250c 100644 --- a/apps/graph/graph/graph_controller_helper.cpp +++ b/apps/graph/graph/graph_controller_helper.cpp @@ -9,7 +9,7 @@ using namespace Poincare; namespace Graph { bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCursor * cursor, int direction, Shared::InteractiveCurveViewRange * range, int numberOfStepsInGradUnit, Ion::Storage::Record record, App * app, float cursorTopMarginRatio, float cursorRightMarginRatio, float cursorBottomMarginRatio, float cursorLeftMarginRatio) { - StorageCartesianFunction * function = app->functionStore()->modelForRecord(record); + ExpiringPointer function = app->functionStore()->modelForRecord(record); double xCursorPosition = cursor->x(); double x = direction > 0 ? xCursorPosition + range->xGridUnit()/numberOfStepsInGradUnit : xCursorPosition - range->xGridUnit()/numberOfStepsInGradUnit; double y = function->evaluateAtAbscissa(x, app->localContext()); @@ -19,7 +19,7 @@ bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCurso } void GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record, App * app) { - StorageCartesianFunction * function = app->functionStore()->modelForRecord(record); + ExpiringPointer function = app->functionStore()->modelForRecord(record); constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits); char buffer[bufferSize]; const char * space = " "; diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index 2d04cfb40..be44101ab 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -25,7 +25,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { StorageFunctionGraphView::drawRect(ctx, rect); for (int i = 0; i < m_functionStore->numberOfActiveFunctions(); i++) { Ion::Storage::Record record = m_functionStore->activeRecordAtIndex(i); - StorageCartesianFunction * f = m_functionStore->modelForRecord(record);; + ExpiringPointer f = m_functionStore->modelForRecord(record);; /* Draw function (color the area under curve of the selected function) */ if (record == m_selectedRecord) { @@ -33,13 +33,13 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { StorageCartesianFunction * f = (StorageCartesianFunction *)model; Poincare::Context * c = (Poincare::Context *)context; return f->evaluateAtAbscissa(t, c); - }, f, context(), f->color(), true, m_highlightedStart, m_highlightedEnd); + }, f.operator->(), context(), f->color(), true, m_highlightedStart, m_highlightedEnd); } else { drawCurve(ctx, rect, [](float t, void * model, void * context) { StorageCartesianFunction * f = (StorageCartesianFunction *)model; Poincare::Context * c = (Poincare::Context *)context; return f->evaluateAtAbscissa(t, c); - }, f, context(), f->color()); + }, f.operator->(), context(), f->color()); } /* Draw tangent */ diff --git a/apps/graph/graph/integral_graph_controller.cpp b/apps/graph/graph/integral_graph_controller.cpp index 2ce449b95..a2ff51402 100644 --- a/apps/graph/graph/integral_graph_controller.cpp +++ b/apps/graph/graph/integral_graph_controller.cpp @@ -36,7 +36,7 @@ double IntegralGraphController::cursorNextStep(double x, int direction) { return (direction > 0 ? x + m_graphRange->xGridUnit()/k_numberOfCursorStepsInGradUnit : x - m_graphRange->xGridUnit()/k_numberOfCursorStepsInGradUnit); } -Layout IntegralGraphController::createFunctionLayout(StorageFunction * function) { +Layout IntegralGraphController::createFunctionLayout(ExpiringPointer function) { constexpr size_t bufferSize = SymbolAbstract::k_maxNameSize+5; // f(x)dx char buffer[bufferSize]; const char * dx = "dx"; diff --git a/apps/graph/graph/integral_graph_controller.h b/apps/graph/graph/integral_graph_controller.h index 67f56fb00..cc0d6f663 100644 --- a/apps/graph/graph/integral_graph_controller.h +++ b/apps/graph/graph/integral_graph_controller.h @@ -14,7 +14,7 @@ public: private: I18n::Message legendMessageAtStep(Step step) override; double cursorNextStep(double position, int direction) override; - Poincare::Layout createFunctionLayout(Shared::StorageFunction * function) override; + Poincare::Layout createFunctionLayout(Shared::ExpiringPointer function) override; }; } diff --git a/apps/graph/graph/intersection_graph_controller.cpp b/apps/graph/graph/intersection_graph_controller.cpp index a39f7c7a3..3b2638510 100644 --- a/apps/graph/graph/intersection_graph_controller.cpp +++ b/apps/graph/graph/intersection_graph_controller.cpp @@ -24,11 +24,11 @@ void IntersectionGraphController::reloadBannerView() { const char * space = " "; const char * legend = "="; // 'f(x)=g(x)=', keep 2 chars for '=' - StorageCartesianFunction * f = functionStore()->modelForRecord(m_record); + ExpiringPointer f = functionStore()->modelForRecord(m_record); int numberOfChar = f->nameWithArgument(buffer, bufferSize-2, StorageCartesianFunctionStore::Symbol()); numberOfChar += strlcpy(buffer+numberOfChar, legend, bufferSize-numberOfChar); // keep 1 char for '='; - StorageCartesianFunction * g = functionStore()->modelForRecord(m_intersectedRecord); + ExpiringPointer g = functionStore()->modelForRecord(m_intersectedRecord); numberOfChar += g->nameWithArgument(buffer, bufferSize-numberOfChar-1, StorageCartesianFunctionStore::Symbol()); numberOfChar += strlcpy(buffer+numberOfChar, legend, bufferSize-numberOfChar); numberOfChar += PoincareHelpers::ConvertFloatToText(m_cursor->y(), buffer+numberOfChar, bufferSize-numberOfChar, Constant::MediumNumberOfSignificantDigits); diff --git a/apps/graph/graph/tangent_graph_controller.cpp b/apps/graph/graph/tangent_graph_controller.cpp index 9f6a01c1e..b3ab42e99 100644 --- a/apps/graph/graph/tangent_graph_controller.cpp +++ b/apps/graph/graph/tangent_graph_controller.cpp @@ -46,7 +46,7 @@ void TangentGraphController::reloadBannerView() { char buffer[bufferSize]; const char * legend = "a="; int legendLength = strlcpy(buffer, legend, bufferSize); - StorageCartesianFunction * function = myApp->functionStore()->modelForRecord(m_record); + ExpiringPointer function = myApp->functionStore()->modelForRecord(m_record); double y = function->approximateDerivative(m_cursor->x(), myApp->localContext()); PoincareHelpers::ConvertFloatToText(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); m_bannerView->setLegendAtIndex(buffer, 4); diff --git a/apps/graph/list/storage_list_controller.cpp b/apps/graph/list/storage_list_controller.cpp index 61b3cd080..7c747a2d1 100644 --- a/apps/graph/list/storage_list_controller.cpp +++ b/apps/graph/list/storage_list_controller.cpp @@ -92,7 +92,7 @@ bool StorageListController::textFieldDidFinishEditing(TextField * textField, con } bool StorageListController::textFieldDidAbortEditing(TextField * textField) { - StorageFunction * function = modelStore()->modelForRecord(modelStore()->recordAtIndex(selectedRow())); + ExpiringPointer function = modelStore()->modelForRecord(modelStore()->recordAtIndex(selectedRow())); setFunctionNameInTextField(function, textField); m_selectableTableView.selectedCell()->setHighlighted(true); app()->setFirstResponder(&m_selectableTableView); @@ -124,7 +124,7 @@ HighlightCell * StorageListController::expressionCells(int index) { void StorageListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { TextFieldFunctionTitleCell * titleCell = static_cast(cell); if (!titleCell->isEditing()) { - StorageFunction * function = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); + ExpiringPointer function = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); setFunctionNameInTextField(function, titleCell->textField()); KDColor functionNameColor = function->isActive() ? function->color() : Palette::GreyDark; titleCell->setColor(functionNameColor); @@ -134,12 +134,12 @@ void StorageListController::willDisplayTitleCellAtIndex(HighlightCell * cell, in void StorageListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { Shared::StorageFunctionListController::willDisplayExpressionCellAtIndex(cell, j); FunctionExpressionCell * myCell = (FunctionExpressionCell *)cell; - StorageFunction * f = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); + ExpiringPointer f = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); KDColor textColor = f->isActive() ? KDColorBlack : Palette::GreyDark; myCell->setTextColor(textColor); } -void StorageListController::setFunctionNameInTextField(StorageFunction * function, TextField * textField) { +void StorageListController::setFunctionNameInTextField(ExpiringPointer function, TextField * textField) { char bufferName[BufferTextView::k_maxNumberOfChar]; function->nameWithArgument(bufferName, BufferTextView::k_maxNumberOfChar, modelStore()->symbol()); textField->setText(bufferName); diff --git a/apps/graph/list/storage_list_controller.h b/apps/graph/list/storage_list_controller.h index 492d211d2..7ae7ef527 100644 --- a/apps/graph/list/storage_list_controller.h +++ b/apps/graph/list/storage_list_controller.h @@ -31,7 +31,7 @@ private: Shared::TextFieldDelegateApp * textFieldDelegateApp() override { return static_cast(app()); } - void setFunctionNameInTextField(Shared::StorageFunction * function, TextField * textField); + void setFunctionNameInTextField(Shared::ExpiringPointer function, TextField * textField); TextFieldFunctionTitleCell m_functionTitleCells[k_maxNumberOfDisplayableRows]; Shared::FunctionExpressionCell m_expressionCells[k_maxNumberOfDisplayableRows]; ListParameterController m_parameterController; diff --git a/apps/graph/storage_cartesian_function_store.h b/apps/graph/storage_cartesian_function_store.h index c23a8a129..449b17f9d 100644 --- a/apps/graph/storage_cartesian_function_store.h +++ b/apps/graph/storage_cartesian_function_store.h @@ -10,7 +10,7 @@ namespace Graph { class StorageCartesianFunctionStore : public Shared::StorageFunctionStore { public: - Shared::StorageCartesianFunction * modelForRecord(Ion::Storage::Record record) const override { return static_cast(Shared::StorageFunctionStore::modelForRecord(record)); } + Shared::ExpiringPointer modelForRecord(Ion::Storage::Record record) const { return Shared::ExpiringPointer(static_cast(privateModelForRecord(record))); } static char Symbol() { return 'x'; } char symbol() const override { return Symbol(); } private: diff --git a/apps/graph/values/storage_function_parameter_controller.cpp b/apps/graph/values/storage_function_parameter_controller.cpp index 767ab9fbe..667ab51a0 100644 --- a/apps/graph/values/storage_function_parameter_controller.cpp +++ b/apps/graph/values/storage_function_parameter_controller.cpp @@ -69,7 +69,7 @@ void StorageFunctionParameterController::willDisplayCellForIndex(HighlightCell * } } -StorageCartesianFunction * StorageFunctionParameterController::function() { +ExpiringPointer StorageFunctionParameterController::function() { App * a = static_cast(app()); return a->functionStore()->modelForRecord(m_record); } diff --git a/apps/graph/values/storage_function_parameter_controller.h b/apps/graph/values/storage_function_parameter_controller.h index c56e754af..205320927 100644 --- a/apps/graph/values/storage_function_parameter_controller.h +++ b/apps/graph/values/storage_function_parameter_controller.h @@ -1,6 +1,7 @@ #ifndef GRAPH_STORAGE_FUNCTION_PARAM_CONTROLLER_H #define GRAPH_STORAGE_FUNCTION_PARAM_CONTROLLER_H +#include "../../shared/expiring_pointer.h" #include "../../shared/storage_cartesian_function.h" #include "../../shared/storage_values_function_parameter_controller.h" @@ -18,7 +19,7 @@ public: void willDisplayCellForIndex(HighlightCell * cell, int index) override; void viewWillAppear() override; private: - Shared::StorageCartesianFunction * function(); + Shared::ExpiringPointer function(); #if COPY_COLUMN constexpr static int k_totalNumberOfCell = 2; #else diff --git a/apps/graph/values/storage_values_controller.cpp b/apps/graph/values/storage_values_controller.cpp index 988d14d10..fe8bcd302 100644 --- a/apps/graph/values/storage_values_controller.cpp +++ b/apps/graph/values/storage_values_controller.cpp @@ -41,7 +41,7 @@ void StorageValuesController::willDisplayCellAtLocation(HighlightCell * cell, in // The cell is a function title cell: if (j == 0 && i > 0) { Shared::BufferFunctionTitleCell * myFunctionCell = (Shared::BufferFunctionTitleCell *)cell; - Shared::StorageCartesianFunction * function = functionStore()->modelForRecord(recordAtColumn(i)); + Shared::ExpiringPointer function = functionStore()->modelForRecord(recordAtColumn(i)); const size_t bufferNameSize = Shared::StorageFunction::k_maxNameWithArgumentSize + 1; char bufferName[bufferNameSize]; if (isDerivativeColumn(i)) { @@ -70,7 +70,7 @@ Ion::Storage::Record StorageValuesController::recordAtColumn(int i) { int index = 1; for (int k = 0; k < functionStore()->numberOfDefinedModels(); k++) { Ion::Storage::Record record = functionStore()->definedRecordAtIndex(k); - StorageCartesianFunction * f = functionStore()->modelForRecord(record); + ExpiringPointer f = functionStore()->modelForRecord(record); if (f->isActive()) { if (i == index) { return record; @@ -92,7 +92,7 @@ bool StorageValuesController::isDerivativeColumn(int i) { assert(i >= 1); int index = 1; for (int k = 0; k < functionStore()->numberOfDefinedModels(); k++) { - StorageCartesianFunction * f = functionStore()->modelForRecord(functionStore()->definedRecordAtIndex(k)); + ExpiringPointer f = functionStore()->modelForRecord(functionStore()->definedRecordAtIndex(k)); if (f->isActive()) { if (i == index) { return false; @@ -139,7 +139,7 @@ StorageFunctionParameterController * StorageValuesController::functionParameterC } double StorageValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) { - Shared::StorageCartesianFunction * function = functionStore()->modelForRecord(recordAtColumn(columnIndex)); + Shared::ExpiringPointer function = functionStore()->modelForRecord(recordAtColumn(columnIndex)); TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); if (isDerivativeColumn(columnIndex)) { return function->approximateDerivative(abscissa, myApp->localContext()); @@ -150,7 +150,7 @@ double StorageValuesController::evaluationOfAbscissaAtColumn(double abscissa, in void StorageValuesController::updateNumberOfColumns() { int result = 1; for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) { - StorageCartesianFunction * f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); + ExpiringPointer f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); if (f->isActive()) { result += 1 + f->displayDerivative(); } diff --git a/apps/shared/Makefile b/apps/shared/Makefile index db1d6dd7f..28f6a1e12 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -9,6 +9,7 @@ app_objs += $(addprefix apps/shared/,\ curve_view_range.o\ double_pair_store.o\ editable_cell_table_view_controller.o\ + expiring_pointer.o\ expression_field_delegate_app.o\ expression_model.o\ expression_model_list_controller.o\ diff --git a/apps/shared/expiring_pointer.cpp b/apps/shared/expiring_pointer.cpp new file mode 100644 index 000000000..6f7096e24 --- /dev/null +++ b/apps/shared/expiring_pointer.cpp @@ -0,0 +1,17 @@ +#include "expiring_pointer.h" +#include "storage_expression_model.h" +#include "storage_cartesian_function.h" +#include "storage_function.h" + +namespace Shared { + +#if DEBUG +template<> +StorageExpressionModel * ExpiringPointer::s_global = nullptr; +template<> +StorageFunction * ExpiringPointer::s_global = nullptr; +template<> +StorageCartesianFunction * ExpiringPointer::s_global = nullptr; +#endif + +} diff --git a/apps/shared/expiring_pointer.h b/apps/shared/expiring_pointer.h new file mode 100644 index 000000000..75cdbe5c4 --- /dev/null +++ b/apps/shared/expiring_pointer.h @@ -0,0 +1,37 @@ +#ifndef SHARED_EXPIRING_POINTER_H +#define SHARED_EXPIRING_POINTER_H + +#include + +namespace Shared { + +template +class ExpiringPointer { +public: + ExpiringPointer(T * rawPointer, bool reinitGlobal = true) : m_rawPointer(rawPointer) { +#if DEBUG + s_global = rawPointer; +#endif + } + T *operator->() { +#if DEBUG + assert(m_rawPointer != nullptr && m_rawPointer == s_global); +#endif + return m_rawPointer; + } + T &operator*() { +#if DEBUG + assert(m_rawPointer != nullptr && m_rawPointer == s_global); +#endif + return *m_rawPointer; + } +private: +#if DEBUG + static T * s_global; +#endif + T * m_rawPointer; +}; + +} + +#endif diff --git a/apps/shared/storage_expression_model_list_controller.cpp b/apps/shared/storage_expression_model_list_controller.cpp index 24ace6951..36fe8b55c 100644 --- a/apps/shared/storage_expression_model_list_controller.cpp +++ b/apps/shared/storage_expression_model_list_controller.cpp @@ -19,7 +19,7 @@ KDCoordinate StorageExpressionModelListController::expressionRowHeight(int j) { if (isAddEmptyRow(j)) { return Metric::StoreRowHeight; } - StorageExpressionModel * m = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); + ExpiringPointer m = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); if (m->layout().isUninitialized()) { return Metric::StoreRowHeight; } @@ -30,7 +30,7 @@ KDCoordinate StorageExpressionModelListController::expressionRowHeight(int j) { void StorageExpressionModelListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { EvenOddExpressionCell * myCell = (EvenOddExpressionCell *)cell; - StorageExpressionModel * m = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); + ExpiringPointer m = modelStore()->modelForRecord(modelStore()->recordAtIndex(j)); myCell->setLayout(m->layout()); } @@ -50,7 +50,7 @@ bool StorageExpressionModelListController::handleEventOnExpression(Ion::Events:: } if (event == Ion::Events::Backspace && !isAddEmptyRow(selectedRow())) { Ion::Storage::Record record = modelStore()->recordAtIndex(modelIndexForRow(selectedRow())); - StorageExpressionModel * model = modelStore()->modelForRecord(record); + ExpiringPointer model = modelStore()->modelForRecord(record); if (model->shouldBeClearedBeforeRemove()) { reinitExpression(model); } else { @@ -81,7 +81,7 @@ void StorageExpressionModelListController::addEmptyModel() { editExpression(Ion::Events::OK); } -void StorageExpressionModelListController::reinitExpression(StorageExpressionModel * model) { +void StorageExpressionModelListController::reinitExpression(ExpiringPointer model) { model->setContent(""); selectableTableView()->reloadData(); } @@ -91,7 +91,7 @@ void StorageExpressionModelListController::editExpression(Ion::Events::Event eve char initialTextContent[TextField::maxBufferSize()]; if (event == Ion::Events::OK || event == Ion::Events::EXE) { Ion::Storage::Record record = modelStore()->recordAtIndex(modelIndexForRow(selectedRow())); - StorageExpressionModel * model = modelStore()->modelForRecord(record); + ExpiringPointer model = modelStore()->modelForRecord(record); model->text(initialTextContent, TextField::maxBufferSize()); initialText = initialTextContent; } @@ -108,7 +108,7 @@ void StorageExpressionModelListController::editExpression(Ion::Events::Event eve void StorageExpressionModelListController::editSelectedRecordWithText(const char * text) { Ion::Storage::Record record = modelStore()->recordAtIndex(modelIndexForRow(selectedRow())); - StorageExpressionModel * model = modelStore()->modelForRecord(record); + ExpiringPointer model = modelStore()->modelForRecord(record); model->setContent(text); } diff --git a/apps/shared/storage_expression_model_list_controller.h b/apps/shared/storage_expression_model_list_controller.h index 9e9043b24..5c6eaa806 100644 --- a/apps/shared/storage_expression_model_list_controller.h +++ b/apps/shared/storage_expression_model_list_controller.h @@ -20,7 +20,7 @@ protected: bool handleEventOnExpression(Ion::Events::Event event); virtual void addEmptyModel(); virtual void didChangeModelsList() {} - virtual void reinitExpression(StorageExpressionModel * model); + virtual void reinitExpression(ExpiringPointer model); virtual void editExpression(Ion::Events::Event event); virtual void editSelectedRecordWithText(const char * text); virtual bool removeModelRow(Ion::Storage::Record record); diff --git a/apps/shared/storage_expression_model_store.cpp b/apps/shared/storage_expression_model_store.cpp index 21c9cc867..ab7a75ad0 100644 --- a/apps/shared/storage_expression_model_store.cpp +++ b/apps/shared/storage_expression_model_store.cpp @@ -15,7 +15,7 @@ Ion::Storage::Record StorageExpressionModelStore::recordAtIndex(int i) const { return Ion::Storage::sharedStorage()->recordWithExtensionAtIndex(modelExtension(), i); } -StorageExpressionModel * StorageExpressionModelStore::modelForRecord(Ion::Storage::Record record) const { +StorageExpressionModel * StorageExpressionModelStore::privateModelForRecord(Ion::Storage::Record record) const { uint32_t currentStorageChecksum = Ion::Storage::sharedStorage()->checksum(); /* If the storage changed since last call to modelForRecord, we invalid all * memoized models. Indeed, if f(x) = A+x, and A changed, f(x) memoization @@ -55,12 +55,12 @@ void StorageExpressionModelStore::tidy() { int StorageExpressionModelStore::numberOfModelsSatisfyingTest(ModelTest test) const { int result = 0; int i = 0; - StorageExpressionModel * m = modelForRecord(recordAtIndex(i++)); + StorageExpressionModel * m = privateModelForRecord(recordAtIndex(i++)); while (!m->isNull()) { if (test(m)) { result++; } - m = modelForRecord(recordAtIndex(i++)); + m = privateModelForRecord(recordAtIndex(i++)); } return result; } @@ -70,7 +70,7 @@ Ion::Storage::Record StorageExpressionModelStore::recordStatifyingTestAtIndex(in int index = 0; int currentModelIndex = 0; Ion::Storage::Record r = recordAtIndex(currentModelIndex++); - StorageExpressionModel * m = modelForRecord(r); + StorageExpressionModel * m = privateModelForRecord(r); while (!m->isNull()) { assert(currentModelIndex <= numberOfModels()); if (test(m)) { @@ -80,7 +80,7 @@ Ion::Storage::Record StorageExpressionModelStore::recordStatifyingTestAtIndex(in index++; } r = recordAtIndex(currentModelIndex++); - m = modelForRecord(r); + m = privateModelForRecord(r); } assert(false); return Ion::Storage::Record(); diff --git a/apps/shared/storage_expression_model_store.h b/apps/shared/storage_expression_model_store.h index 9d711bc83..0749fbfe0 100644 --- a/apps/shared/storage_expression_model_store.h +++ b/apps/shared/storage_expression_model_store.h @@ -2,6 +2,7 @@ #define SHARED_STORAGE_EXPRESSION_MODEL_STORE_H #include "storage_expression_model.h" +#include "expiring_pointer.h" #include #include @@ -19,7 +20,7 @@ public: int numberOfDefinedModels() const { return numberOfModelsSatisfyingTest([](StorageExpressionModel * m) { return m->isDefined(); }); } Ion::Storage::Record recordAtIndex(int i) const; Ion::Storage::Record definedRecordAtIndex(int i) const { return recordStatifyingTestAtIndex(i, [](StorageExpressionModel * m) { return m->isDefined(); }); } - virtual StorageExpressionModel * modelForRecord(Ion::Storage::Record record) const; + ExpiringPointer modelForRecord(Ion::Storage::Record record) const { return ExpiringPointer(privateModelForRecord(record)); } // Add and Remove virtual Ion::Storage::Record::ErrorStatus addEmptyModel() = 0; @@ -33,6 +34,7 @@ protected: typedef bool (*ModelTest)(StorageExpressionModel * model); int numberOfModelsSatisfyingTest(ModelTest test) const; Ion::Storage::Record recordStatifyingTestAtIndex(int i, ModelTest test) const; + StorageExpressionModel * privateModelForRecord(Ion::Storage::Record record) const; private: void resetMemoizedModels() const; virtual void setMemoizedModelAtIndex(int cacheIndex, Ion::Storage::Record) const = 0; diff --git a/apps/shared/storage_function_banner_delegate.cpp b/apps/shared/storage_function_banner_delegate.cpp index c38359b7a..a59d2bd07 100644 --- a/apps/shared/storage_function_banner_delegate.cpp +++ b/apps/shared/storage_function_banner_delegate.cpp @@ -7,7 +7,7 @@ using namespace Poincare; namespace Shared { void StorageFunctionBannerDelegate::reloadBannerViewForCursorOnFunction(CurveViewCursor * cursor, Ion::Storage::Record record, StorageFunctionStore * functionStore, char symbol) { - StorageFunction * function = functionStore->modelForRecord(record); + ExpiringPointer function = functionStore->modelForRecord(record); constexpr int bufferSize = k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits); char buffer[bufferSize]; const char * space = " "; diff --git a/apps/shared/storage_function_go_to_parameter_controller.cpp b/apps/shared/storage_function_go_to_parameter_controller.cpp index 66728f009..622b3ccff 100644 --- a/apps/shared/storage_function_go_to_parameter_controller.cpp +++ b/apps/shared/storage_function_go_to_parameter_controller.cpp @@ -23,7 +23,7 @@ double StorageFunctionGoToParameterController::parameterAtIndex(int index) { bool StorageFunctionGoToParameterController::setParameterAtIndex(int parameterIndex, double f) { assert(parameterIndex == 0); StorageFunctionApp * myApp = (StorageFunctionApp *)app(); - StorageFunction * function = myApp->functionStore()->modelForRecord(m_record); + ExpiringPointer function = myApp->functionStore()->modelForRecord(m_record); float y = function->evaluateAtAbscissa(f, myApp->localContext()); if (std::fabs(f) > k_maxDisplayableFloat || std::fabs(y) > k_maxDisplayableFloat) { app()->displayWarning(I18n::Message::ForbiddenValue); diff --git a/apps/shared/storage_function_graph_controller.cpp b/apps/shared/storage_function_graph_controller.cpp index 591149fde..ede44c85e 100644 --- a/apps/shared/storage_function_graph_controller.cpp +++ b/apps/shared/storage_function_graph_controller.cpp @@ -89,7 +89,7 @@ InteractiveCurveViewRangeDelegate::Range StorageFunctionGraphController::compute return range; } for (int i=0; inumberOfActiveFunctions(); i++) { - StorageFunction * f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); + ExpiringPointer f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); float y = 0.0f; float res = curveView()->resolution(); /* Scan x-range from the middle to the extrema in order to get balanced @@ -125,7 +125,7 @@ void StorageFunctionGraphController::initCursorParameters() { int functionIndex = 0; double y = 0; do { - StorageFunction * firstFunction = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(functionIndex++)); + ExpiringPointer firstFunction = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(functionIndex++)); y = firstFunction->evaluateAtAbscissa(x, myApp->localContext()); } while ((std::isnan(y) || std::isinf(y)) && functionIndex < functionStore()->numberOfActiveFunctions()); m_cursor->moveTo(x, y); diff --git a/apps/shared/storage_function_store.h b/apps/shared/storage_function_store.h index 34c15d075..acccd4975 100644 --- a/apps/shared/storage_function_store.h +++ b/apps/shared/storage_function_store.h @@ -17,7 +17,7 @@ public: int numberOfActiveFunctions() const { return numberOfModelsSatisfyingTest([](StorageExpressionModel * m) { return m->isDefined() && static_cast(m)->isActive(); }); } Ion::Storage::Record activeRecordAtIndex(int i) const { return recordStatifyingTestAtIndex(i, [](StorageExpressionModel * m) { return m->isDefined() && static_cast(m)->isActive(); }); } - StorageFunction * modelForRecord(Ion::Storage::Record record) const override { return static_cast(StorageExpressionModelStore::modelForRecord(record)); } + ExpiringPointer modelForRecord(Ion::Storage::Record record) const { return ExpiringPointer(static_cast(privateModelForRecord(record))); } virtual char symbol() const = 0; }; diff --git a/apps/shared/storage_list_parameter_controller.cpp b/apps/shared/storage_list_parameter_controller.cpp index ea9a03aae..b518db47e 100644 --- a/apps/shared/storage_list_parameter_controller.cpp +++ b/apps/shared/storage_list_parameter_controller.cpp @@ -94,7 +94,7 @@ bool StorageListParameterController::handleEnterOnRow(int rowIndex) { } } -StorageFunction * StorageListParameterController::function() { +ExpiringPointer StorageListParameterController::function() { return functionStore()->modelForRecord(m_record); } diff --git a/apps/shared/storage_list_parameter_controller.h b/apps/shared/storage_list_parameter_controller.h index 4003b6670..46aeb8921 100644 --- a/apps/shared/storage_list_parameter_controller.h +++ b/apps/shared/storage_list_parameter_controller.h @@ -34,7 +34,7 @@ protected: SelectableTableView m_selectableTableView; Ion::Storage::Record m_record; private: - StorageFunction * function(); + ExpiringPointer function(); StorageFunctionStore * functionStore(); #if FUNCTION_COLOR_CHOICE MessageTableCellWithChevron m_colorCell; diff --git a/apps/shared/storage_sum_graph_controller.cpp b/apps/shared/storage_sum_graph_controller.cpp index 4b41aae33..6d2997718 100644 --- a/apps/shared/storage_sum_graph_controller.cpp +++ b/apps/shared/storage_sum_graph_controller.cpp @@ -103,7 +103,7 @@ bool StorageSumGraphController::handleEvent(Ion::Events::Event event) { bool StorageSumGraphController::moveCursorHorizontallyToPosition(double x) { StorageFunctionApp * myApp = static_cast(app()); assert(!m_record.isNull()); - StorageFunction * function = myApp->functionStore()->modelForRecord(m_record); + ExpiringPointer function = myApp->functionStore()->modelForRecord(m_record); double y = function->evaluateAtAbscissa(x, myApp->localContext()); m_cursor->moveTo(x, y); if (m_step == Step::FirstParameter) { @@ -191,7 +191,7 @@ bool StorageSumGraphController::handleEnter() { m_step = (Step)((int)m_step+1); StorageFunctionApp * myApp = static_cast(app()); assert(!m_record.isNull()); - StorageFunction * function = myApp->functionStore()->modelForRecord(m_record); + ExpiringPointer function = myApp->functionStore()->modelForRecord(m_record); double sum = function->sumBetweenBounds(m_startSum, m_endSum, myApp->localContext()); m_legendView.setSumSymbol(m_step, m_startSum, m_endSum, sum, createFunctionLayout(function)); m_legendView.setLegendMessage(I18n::Message::Default, m_step); diff --git a/apps/shared/storage_sum_graph_controller.h b/apps/shared/storage_sum_graph_controller.h index 85fece226..0f5189133 100644 --- a/apps/shared/storage_sum_graph_controller.h +++ b/apps/shared/storage_sum_graph_controller.h @@ -9,6 +9,7 @@ #include "simple_interactive_curve_view_controller.h" #include "storage_function.h" #include "text_field_delegate.h" +#include "expiring_pointer.h" namespace Shared { @@ -39,7 +40,7 @@ private: constexpr static float k_cursorBottomMarginRatio = 0.28f; // (cursorHeight/2+bannerHeigh)/graphViewHeight virtual I18n::Message legendMessageAtStep(Step step) = 0; virtual double cursorNextStep(double position, int direction) = 0; - virtual Poincare::Layout createFunctionLayout(StorageFunction * function) = 0; + virtual Poincare::Layout createFunctionLayout(ExpiringPointer function) = 0; Shared::InteractiveCurveViewRange * interactiveCurveViewRange() override { return m_graphRange; } Shared::CurveView * curveView() override { return m_graphView; } TextFieldDelegateApp * textFieldDelegateApp() override { diff --git a/apps/shared/storage_values_controller.cpp b/apps/shared/storage_values_controller.cpp index 38d14a041..99f4606dc 100644 --- a/apps/shared/storage_values_controller.cpp +++ b/apps/shared/storage_values_controller.cpp @@ -309,7 +309,7 @@ int StorageValuesController::maxNumberOfElements() const { } double StorageValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) { - StorageFunction * function = functionStore()->modelForRecord(recordAtColumn(columnIndex)); + ExpiringPointer function = functionStore()->modelForRecord(recordAtColumn(columnIndex)); TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); return function->evaluateAtAbscissa(abscissa, myApp->localContext()); }