[poincare] Redesign the text method of expression to avoid keeping a

buffer in all expressions

Change-Id: I2ca33be09a525adf429854e651beaa75e5605d7a
This commit is contained in:
Émilie Feral
2016-12-08 18:08:54 +01:00
parent 41ed0bf8da
commit 69e381d736
8 changed files with 68 additions and 44 deletions

View File

@@ -17,9 +17,9 @@ public:
ExpressionLayout * evaluationLayout();
void setContent(const char * c, Context * context);
bool isEmpty();
constexpr static int k_maximalExpressionTextLength = 255;
private:
constexpr static int k_bodyLength = 255;
char m_text[k_bodyLength];
char m_text[k_maximalExpressionTextLength];
Expression * m_expression;
ExpressionLayout * m_layout;
Expression * m_evaluation;

View File

@@ -1,6 +1,5 @@
#include "history_controller.h"
#include "app.h"
#include "../constant.h"
#include <assert.h>
namespace Calculation {
@@ -47,7 +46,8 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
if (subviewType == HistoryViewCell::SubviewType::PrettyPrint) {
editController->setTextBody(calculation->text());
} else {
char * resultText = calculation->evaluation()->text();
char resultText[Calculation::k_maximalExpressionTextLength];
calculation->evaluation()->writeTextInBuffer(resultText, Calculation::k_maximalExpressionTextLength);
editController->setTextBody(resultText);
}
m_selectableTableView.deselectTable();
@@ -64,7 +64,8 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
if (subviewType == HistoryViewCell::SubviewType::PrettyPrint) {
newCalculation = *calculation;
} else {
char * resultText = calculation->evaluation()->text();
char resultText[Calculation::k_maximalExpressionTextLength];
calculation->evaluation()->writeTextInBuffer(resultText, Calculation::k_maximalExpressionTextLength);
/* TODO: this will work when we will parse float */
//App * calculationApp = (App *)app();
//newCalculation.setContent(resultText, calculationApp->evaluateContext());

View File

@@ -69,11 +69,7 @@ class Expression {
* Do not forget to delete the new expression to avoid leaking. */
virtual Expression * evaluate(Context& context) const = 0;
virtual float approximate(Context& context) const = 0;
char * text();
protected:
virtual void setText();
constexpr static int k_maxLength = 255;
char m_text[k_maxLength];
virtual int writeTextInBuffer(char * buffer, int bufferSize);
private:
bool sequentialOperandsIdentity(const Expression * e) const;
bool commutativeOperandsIdentity(const Expression * e) const;

View File

@@ -20,10 +20,10 @@ public:
};
void setNumberOfDigitsInMantissa(int numberOfDigits);
/* The parameter 'DisplayMode' refers to the way to display float 'scientific' or
* 'decimal'. The code only handles 'scientific' so far. */
void convertFloatToText(char * buffer, int bufferSize, int numberOfDigitsInMantissa, DisplayMode mode = DisplayMode::Scientific) const;
protected:
void setText() override;
* 'decimal'. The code only handles 'scientific' so far. If the buffer size is
* small, the function does nothing. */
int convertFloatToText(char * buffer, int bufferSize, int numberOfDigitsInMantissa, DisplayMode mode = DisplayMode::Scientific) const;
int writeTextInBuffer(char * buffer, int bufferSize) override;
private:
constexpr static int k_maxBufferLength = 14;
/* This function prints the int i in the buffer with a '.' at the position

View File

@@ -21,8 +21,9 @@ class Matrix : public Expression {
int numberOfOperands, bool cloneOperands = true) const override;
int numberOfRows() const;
int numberOfColumns() const;
protected:
void setText() override;
/* If the buffer is too small, the function fills the buffer until reaching
* buffer size */
int writeTextInBuffer(char * buffer, int bufferSize) override;
private:
MatrixData * m_matrixData;
static Integer * defaultExpression();

View File

@@ -171,10 +171,6 @@ bool Expression::isCommutative() const {
return false;
}
void Expression::setText() {
}
char * Expression::text() {
setText();
return m_text;
int Expression::writeTextInBuffer(char * buffer, int bufferSize) {
return 0;
}

View File

@@ -49,8 +49,8 @@ bool Float::valueEquals(const Expression * e) const {
return m_float == ((Float *)e)->m_float;
}
void Float::setText() {
convertFloatToText(m_text, k_maxBufferLength, m_numberOfDigitsInMantissa);
int Float::writeTextInBuffer(char * buffer, int bufferSize) {
return convertFloatToText(buffer, bufferSize, m_numberOfDigitsInMantissa);
}
void Float::printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, int i, int decimalMarkerPosition) {
@@ -78,12 +78,15 @@ void Float::printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize,
} while (endChar >= startChar);
}
void Float::convertFloatToText(char * buffer, int bufferSize,
int Float::convertFloatToText(char * buffer, int bufferSize,
int numberOfDigitsInMantissa, DisplayMode mode) const {
/* We here assert that the buffer is long enough to display with the right
* number of digits in the mantissa. If numberOfDigitsInMantissa = 7, the
* worst case has the form -1.999999e-38 (7+6+1 char). */
assert(bufferSize > 6 + numberOfDigitsInMantissa);
if (bufferSize <= 6 + numberOfDigitsInMantissa) {
buffer[0] = 0;
return 0;
}
if (isinf(m_float)) {
buffer[0] = m_float > 0 ? '+' : '-';
@@ -91,7 +94,7 @@ void Float::convertFloatToText(char * buffer, int bufferSize,
buffer[2] = 'n';
buffer[3] = 'f';
buffer[4] = 0;
return;
return 5;
}
if (isnan(m_float)) {
@@ -99,7 +102,7 @@ void Float::convertFloatToText(char * buffer, int bufferSize,
buffer[1] = 'a';
buffer[2] = 'N';
buffer[3] = 0;
return;
return 4;
}
float logBase10 = m_float != 0.0f ? log10f(fabsf(m_float)) : 0;
@@ -154,4 +157,5 @@ void Float::convertFloatToText(char * buffer, int bufferSize,
buffer[availableCharsForMantissaWithSign] = 'e';
printBase10IntegerWithDecimalMarker(buffer+availableCharsForMantissaWithSign+1, numberOfCharExponent, exponentInBase10, -1);
buffer[availableCharsForMantissaWithSign+1+numberOfCharExponent] = 0;
return (availableCharsForMantissaWithSign+1+numberOfCharExponent);
}

View File

@@ -79,22 +79,48 @@ int Matrix::numberOfColumns() const {
return m_matrixData->numberOfColumns();
}
void Matrix::setText() {
int Matrix::writeTextInBuffer(char * buffer, int bufferSize) {
buffer[bufferSize] = 0;
int currentChar = 0;
m_text[currentChar++] = '[';
for (int i = 0; i < m_matrixData->numberOfRows(); i++) {
m_text[currentChar++] = '[';
char * operandText = m_matrixData->operands()[i*m_matrixData->numberOfColumns()]->text();
strlcpy(m_text+currentChar, operandText, strlen(operandText)+1);
for (int j = 1; j < numberOfColumns(); j++) {
currentChar += strlen(operandText);
m_text[currentChar++] = ',';
operandText = m_matrixData->operands()[i*m_matrixData->numberOfColumns()+j]->text();
strlcpy(m_text+currentChar, operandText, strlen(operandText)+1);
}
currentChar += strlen(operandText);
m_text[currentChar++] = ']';
if (currentChar >= bufferSize) {
return 0;
}
m_text[currentChar++] = ']';
m_text[currentChar] = 0;
buffer[currentChar++] = '[';
if (currentChar >= bufferSize) {
return currentChar;
}
for (int i = 0; i < m_matrixData->numberOfRows(); i++) {
buffer[currentChar++] = '[';
if (currentChar >= bufferSize) {
return currentChar;
}
currentChar += m_matrixData->operands()[i*m_matrixData->numberOfColumns()]->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar);
if (currentChar >= bufferSize) {
return currentChar;
}
for (int j = 1; j < numberOfColumns(); j++) {
buffer[currentChar++] = ',';
if (currentChar >= bufferSize) {
return currentChar;
}
currentChar += m_matrixData->operands()[i*m_matrixData->numberOfColumns()+j]->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar);
if (currentChar >= bufferSize) {
return currentChar;
}
}
currentChar = strlen(buffer);
if (currentChar >= bufferSize) {
return currentChar;
}
buffer[currentChar++] = ']';
if (currentChar >= bufferSize) {
return currentChar;
}
}
buffer[currentChar++] = ']';
if (currentChar >= bufferSize) {
return currentChar;
}
buffer[currentChar] = 0;
return currentChar;
}