[apps/shared] Split ExpressionModelHandle into ExpressionModelHandle and

SingleExpressionModelHandle (in perspective of Sequence model who will
be composed of 3 ExpressionModelHandle)
This commit is contained in:
Émilie Feral
2019-02-25 14:22:34 +01:00
parent 6566b08400
commit 3088a4ee23
19 changed files with 216 additions and 136 deletions

View File

@@ -11,16 +11,15 @@ using namespace Poincare;
namespace Shared {
ExpressionModelHandle::ExpressionModelHandle(Storage::Record record) :
Storage::Record(record),
ExpressionModelHandle::ExpressionModelHandle() :
m_expression(),
m_layout(),
m_circular(-1)
{
}
void ExpressionModelHandle::text(char * buffer, size_t bufferSize) const {
Expression e = expressionClone();
void ExpressionModelHandle::text(const Storage::Record * record, char * buffer, size_t bufferSize) const {
Expression e = expressionClone(record);
if (e.isUninitialized() && bufferSize > 0) {
buffer[0] = 0;
} else {
@@ -28,37 +27,35 @@ void ExpressionModelHandle::text(char * buffer, size_t bufferSize) const {
}
}
bool ExpressionModelHandle::isCircularlyDefined(Poincare::Context * context) const {
bool ExpressionModelHandle::isCircularlyDefined(const Storage::Record * record, Poincare::Context * context) const {
if (m_circular == -1) {
m_circular = Expression::ExpressionWithoutSymbols(expressionClone(), *context).isUninitialized();
m_circular = Expression::ExpressionWithoutSymbols(expressionClone(record), *context).isUninitialized();
}
return m_circular;
}
Expression ExpressionModelHandle::expressionReduced(Poincare::Context * context) const {
Expression ExpressionModelHandle::expressionReduced(const Storage::Record * record, Poincare::Context * context) const {
if (m_expression.isUninitialized()) {
assert(!isNull());
Ion::Storage::Record::Data recordData = value();
m_expression = Expression::ExpressionFromAddress(expressionAddressForValue(recordData), expressionSizeForValue(recordData));
assert(record->fullName() != nullptr);
m_expression = Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
PoincareHelpers::Simplify(&m_expression, *context);
// simplify might return an uninitialized Expression if interrupted
if (m_expression.isUninitialized()) {
m_expression = Expression::ExpressionFromAddress(expressionAddressForValue(recordData), expressionSizeForValue(recordData));
m_expression = Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
}
}
return m_expression;
}
Expression ExpressionModelHandle::expressionClone() const {
assert(!isNull());
Ion::Storage::Record::Data recordData = value();
Expression ExpressionModelHandle::expressionClone(const Storage::Record * record) const {
assert(record->fullName() != nullptr);
/* A new Expression has to be created at each call (because it might be tempered with after calling) */
return Expression::ExpressionFromAddress(expressionAddressForValue(recordData), expressionSizeForValue(recordData));
return Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
}
Layout ExpressionModelHandle::layout() {
Layout ExpressionModelHandle::layout(const Storage::Record * record) const {
if (m_layout.isUninitialized()) {
m_layout = PoincareHelpers::CreateLayout(expressionClone());
m_layout = PoincareHelpers::CreateLayout(expressionClone(record));
if (m_layout.isUninitialized()) {
m_layout = HorizontalLayout::Builder();
}
@@ -66,46 +63,20 @@ Layout ExpressionModelHandle::layout() {
return m_layout;
}
bool ExpressionModelHandle::isDefined() {
return !isEmpty();
Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setContent(Ion::Storage::Record * record, const char * c, char symbol) {
Expression e = ExpressionModelHandle::BuildExpressionFromText(c, symbol);
return setExpressionContent(record, e);
}
bool ExpressionModelHandle::isEmpty() {
return value().size <= metaDataSize();
}
void ExpressionModelHandle::tidyExpressionModel() {
m_layout = Layout();
m_expression = Expression();
m_circular = 0;
}
void ExpressionModelHandle::tidy() {
tidyExpressionModel();
}
Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setContent(const char * c) {
Expression expressionToStore;
// if c = "", we want to reinit the Expression
if (c && *c != 0) {
// Compute the expression to store, without replacing symbols
expressionToStore = Expression::Parse(c);
if (!expressionToStore.isUninitialized() && symbol() != 0) {
expressionToStore = expressionToStore.replaceUnknown(Symbol::Builder(symbol()));
}
}
return setExpressionContent(expressionToStore);
}
Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setExpressionContent(Expression & expressionToStore) {
assert(!isNull());
Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setExpressionContent(Ion::Storage::Record * record, Expression & expressionToStore) {
assert(record->fullName() != nullptr);
// Prepare the new data to store
Ion::Storage::Record::Data newData = value();
Ion::Storage::Record::Data newData = record->value();
size_t expressionToStoreSize = expressionToStore.isUninitialized() ? 0 : expressionToStore.size();
newData.size = metaDataSize() + expressionToStoreSize;
newData.size = newData.size - expressionSize(record) + expressionToStoreSize;
// Set the data
Ion::Storage::Record::ErrorStatus error = setValue(newData);
Ion::Storage::Record::ErrorStatus error = record->setValue(newData);
if (error != Ion::Storage::Record::ErrorStatus::None) {
assert(error == Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable);
return error;
@@ -113,21 +84,31 @@ Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setExpressionContent(Ex
// Copy the expression if needed
if (!expressionToStore.isUninitialized()) {
memcpy(expressionAddressForValue(value()), expressionToStore.addressInPool(), expressionToStore.size());
memcpy(expressionAddress(record), 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 elements relative to the ExpressionModel. */
tidyExpressionModel();
/* Here we delete only the elements relative to the expression model kept in
* this handle. */
tidy();
return error;
}
void * ExpressionModelHandle::expressionAddressForValue(Ion::Storage::Record::Data recordData) const {
return (char *)recordData.buffer+metaDataSize();
void ExpressionModelHandle::tidy() const {
m_layout = Layout();
m_expression = Expression();
m_circular = 0;
}
size_t ExpressionModelHandle::expressionSizeForValue(Ion::Storage::Record::Data recordData) const {
return recordData.size-metaDataSize();
Poincare::Expression ExpressionModelHandle::BuildExpressionFromText(const char * c, char symbol) {
Expression expressionToStore;
// if c = "", we want to reinit the Expression
if (c && *c != 0) {
// Compute the expression to store, without replacing symbols
expressionToStore = Expression::Parse(c);
if (!expressionToStore.isUninitialized() && symbol != 0) {
expressionToStore = expressionToStore.replaceUnknown(Symbol::Builder(symbol));
}
}
return expressionToStore;
}
}