[sequence] Implement specific setExpressionContent for Sequence model

This commit is contained in:
Émilie Feral
2019-03-11 13:52:01 +01:00
parent 634972a724
commit 5b89c1caa9
4 changed files with 55 additions and 10 deletions

View File

@@ -200,6 +200,20 @@ Poincare::Layout Sequence::SequenceHandle::name(Sequence * sequence) {
return m_name;
}
void Sequence::SequenceHandle::updateNewDataWithExpression(Ion::Storage::Record * record, Expression & expressionToStore, void * expressionAddress, size_t newExpressionSize, size_t previousExpressionSize) {
Ion::Storage::Record::Data newData = record->value();
// Translate expressions located downstream
size_t sizeBeforeExpression = (char *)expressionAddress -(char *)newData.buffer;
size_t remainingSize = newData.size - sizeBeforeExpression - previousExpressionSize;
memmove((char *)expressionAddress + newExpressionSize, (char *)expressionAddress + previousExpressionSize, remainingSize);
// Copy the expression
if (!expressionToStore.isUninitialized()) {
memmove(expressionAddress, expressionToStore.addressInPool(), newExpressionSize);
}
// Update meta data
updateMetaData(record, newExpressionSize);
}
/* Definition Handle*/
void * Sequence::DefinitionHandle::expressionAddress(const Ion::Storage::Record * record) const {
@@ -243,6 +257,10 @@ size_t Sequence::FirstInitialConditionHandle::expressionSize(const Ion::Storage:
return static_cast<const Sequence *>(record)->recordData()->firstInitialConditionSize();
}
void Sequence::FirstInitialConditionHandle::updateMetaData(const Ion::Storage::Record * record, size_t newSize) {
static_cast<const Sequence *>(record)->recordData()->setFirstInitialConditionSize(newSize);
}
void Sequence::FirstInitialConditionHandle::buildName(Sequence * sequence) {
assert(sequence->type() == Type::SingleRecurrence || sequence->type() == Type::DoubleRecurrence);
char buffer[k_initialRankNumberOfDigits+1];
@@ -262,6 +280,10 @@ void * Sequence::SecondInitialConditionHandle::expressionAddress(const Ion::Stor
return (char *)data.buffer+offset;
}
void Sequence::SecondInitialConditionHandle::updateMetaData(const Ion::Storage::Record * record, size_t newSize) {
static_cast<const Sequence *>(record)->recordData()->setSecondInitialConditionSize(newSize);
}
size_t Sequence::SecondInitialConditionHandle::expressionSize(const Ion::Storage::Record * record) const {
return static_cast<const Sequence *>(record)->recordData()->secondInitialConditionSize();
}

View File

@@ -101,6 +101,9 @@ private:
protected:
virtual void buildName(Sequence * sequence) = 0;
Poincare::Layout m_name;
private:
void updateNewDataWithExpression(Ion::Storage::Record * record, Poincare::Expression & newExpression, void * expressionAddress, size_t newExpressionSize, size_t previousExpressionSize) override;
virtual void updateMetaData(const Ion::Storage::Record * record, size_t newSize) {}
};
class DefinitionHandle : public SequenceHandle {
@@ -115,6 +118,7 @@ private:
public:
void * expressionAddress(const Ion::Storage::Record * record) const override;
private:
void updateMetaData(const Ion::Storage::Record * record, size_t newSize) override;
size_t expressionSize(const Ion::Storage::Record * record) const override;
void buildName(Sequence * sequence) override;
};
@@ -123,6 +127,7 @@ private:
public:
void * expressionAddress(const Ion::Storage::Record * record) const override;
private:
void updateMetaData(const Ion::Storage::Record * record, size_t newSize) override;
size_t expressionSize(const Ion::Storage::Record * record) const override;
void buildName(Sequence * sequence) override;
};

View File

@@ -11,6 +11,8 @@ using namespace Poincare;
namespace Shared {
static inline int maxInt(int x, int y) { return x > y ? x : y; }
ExpressionModelHandle::ExpressionModelHandle() :
m_expression(),
m_layout(),
@@ -68,30 +70,45 @@ Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setContent(Ion::Storage
return setExpressionContent(record, e);
}
Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setExpressionContent(Ion::Storage::Record * record, Expression & expressionToStore) {
Ion::Storage::Record::ErrorStatus ExpressionModelHandle::setExpressionContent(Ion::Storage::Record * record, Expression & newExpression) {
assert(record->fullName() != nullptr);
// Prepare the new data to store
// Prepare the new data to be stored
Ion::Storage::Record::Data newData = record->value();
size_t expressionToStoreSize = expressionToStore.isUninitialized() ? 0 : expressionToStore.size();
newData.size = newData.size - expressionSize(record) + expressionToStoreSize;
// Set the data
size_t previousExpressionSize = expressionSize(record);
size_t newExpressionSize = newExpression.isUninitialized() ? 0 : newExpression.size();
size_t previousDataSize = newData.size;
size_t newDataSize = previousDataSize - previousExpressionSize + newExpressionSize;
void * expAddress = expressionAddress(record);
// Update size of record to maximal size between previous and new data
newData.size = maxInt(previousDataSize, newDataSize);
Ion::Storage::Record::ErrorStatus error = record->setValue(newData);
if (error != Ion::Storage::Record::ErrorStatus::None) {
assert(error == Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable);
return error;
}
// Prepare the new data content
/* WARNING: expressionAddress() cannot be used while the metadata is invalid
* (as it is sometimes computed from metadata). Thus, the expression address
* is given as a parameter to updateNewDataWithExpression. */
updateNewDataWithExpression(record, newExpression, expAddress, newExpressionSize, previousExpressionSize);
// Set the data with the right size
newData.size = newDataSize;
error = record->setValue(newData);
// Any error would have occured at the first call to setValue
assert(error == Ion::Storage::Record::ErrorStatus::None);
// Copy the expression if needed
if (!expressionToStore.isUninitialized()) {
memcpy(expressionAddress(record), expressionToStore.addressInPool(), expressionToStore.size());
}
/* Here we delete only the elements relative to the expression model kept in
* this handle. */
tidy();
return error;
}
void ExpressionModelHandle::updateNewDataWithExpression(Ion::Storage::Record * record, Expression & expressionToStore, void * expressionAddress, size_t expressionToStoreSize, size_t previousExpressionSize) {
if (!expressionToStore.isUninitialized()) {
memmove(expressionAddress, expressionToStore.addressInPool(), expressionToStoreSize);
}
}
void ExpressionModelHandle::tidy() const {
m_layout = Layout();
m_expression = Expression();

View File

@@ -34,6 +34,7 @@ protected:
mutable Poincare::Expression m_expression;
mutable Poincare::Layout m_layout;
private:
virtual void updateNewDataWithExpression(Ion::Storage::Record * record, Poincare::Expression & expressionToStore, void * expressionAddress, size_t expressionToStoreSize, size_t previousExpressionSize);
virtual size_t expressionSize(const Ion::Storage::Record * record) const = 0;
mutable int m_circular;
};