Files
Upsilon/poincare/src/opposite.cpp
Émilie Feral fa2ee9e624 [poincare] Never return nullptr when creating a expression to avoid
nullptr dereference

Change-Id: Ie7976a8ee86c82283ebcbffc28fe902ddfb7a952
2017-03-29 11:35:30 +02:00

103 lines
3.4 KiB
C++

#include <poincare/opposite.h>
extern "C" {
#include <assert.h>
#include <stdlib.h>
#include <math.h>
}
#include "layout/horizontal_layout.h"
#include "layout/parenthesis_layout.h"
#include "layout/string_layout.h"
namespace Poincare {
Opposite::Opposite(Expression * operand, bool cloneOperands) {
assert(operand != nullptr);
if (cloneOperands) {
m_operand = operand->clone();
} else {
m_operand = operand;
}
}
Opposite::~Opposite() {
delete m_operand;
}
const Expression * Opposite::operand(int i) const {
assert(i == 0);
return m_operand;
}
int Opposite::numberOfOperands() const {
return 1;
}
Expression * Opposite::clone() const {
return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true);
}
Expression * Opposite::privateEvaluate(Context& context, AngleUnit angleUnit) const {
assert(angleUnit != AngleUnit::Default);
Expression * operandEvalutation = m_operand->evaluate(context, angleUnit);
Expression * result = nullptr;
switch (operandEvalutation->type()) {
case Type::Complex:
result = new Complex(Complex::Cartesian(-((Complex *)operandEvalutation)->a(), -((Complex *)operandEvalutation)->b()));
break;
case Type::Matrix:
result = evaluateOnMatrix((Matrix *)operandEvalutation, context, angleUnit);
break;
default:
result = new Complex(Complex::Float(NAN));
break;
}
delete operandEvalutation;
return result;
}
ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const {
assert(floatDisplayMode != FloatDisplayMode::Default);
assert(complexFormat != ComplexFormat::Default);
ExpressionLayout * children_layouts[2];
char string[2] = {'-', '\0'};
children_layouts[0] = new StringLayout(string, 1);
children_layouts[1] = m_operand->type() == Type::Opposite ? new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)) : m_operand->createLayout(floatDisplayMode, complexFormat);
return new HorizontalLayout(children_layouts, 2);
}
float Opposite::privateApproximate(Context& context, AngleUnit angleUnit) const {
assert(angleUnit != AngleUnit::Default);
return -m_operand->approximate(context, angleUnit);
}
Expression::Type Opposite::type() const {
return Expression::Type::Opposite;
}
Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands) const {
assert(newOperands != nullptr);
assert(numberOfOperands == 1);
return new Opposite(newOperands[0], cloneOperands);
}
Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context, AngleUnit angleUnit) const {
Expression ** operands = (Expression **)malloc(m->numberOfRows() * m->numberOfColumns()*sizeof(Expression *));
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
Expression * evaluation = m->operand(i)->evaluate(context, angleUnit);
assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex);
if (evaluation->type() == Type::Matrix) {
operands[i] = new Complex(Complex::Float(NAN));
delete evaluation;
continue;
}
operands[i] = new Complex(Complex::Cartesian(-((Complex *)evaluation)->a(), -((Complex *)evaluation)->b()));
delete evaluation;
}
Expression * matrix = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
free(operands);
return matrix;
}
}