Moved YGFloatOptional from C struct to C++ struct

Summary:
Earlier `YGfloatOptional` was plain struct with no privacy around the variables. This diff adds privacy and also enforces checks when one tries to access value of an undefined `YGFloatOptional`

This diff also adds a behaviour in which when a value of an undefined YGFloatOptional is accessed, it will normally terminate(Several cleanup steps are performed).

Reviewed By: emilsjolander

Differential Revision: D7288555

fbshipit-source-id: f61cc92c8fd0d48d2fc1f4d0e6fcef155f19ff8a
This commit is contained in:
Pritesh Nandgaonkar
2018-03-15 12:29:02 -07:00
committed by Facebook Github Bot
parent ae86824636
commit 5d7b75a47a
10 changed files with 123 additions and 64 deletions

View File

@@ -55,7 +55,7 @@ float YGFloatSanitize(const float& val) {
}
float YGUnwrapFloatOptional(const YGFloatOptional& op) {
return op.isUndefined ? YGUndefined : op.value;
return op.isUndefined() ? YGUndefined : op.getValue();
}
bool YGFloatOptionalFloatEquals(

View File

@@ -113,13 +113,14 @@ inline YGFloatOptional YGResolveValue(const YGValue value, const float parentSiz
switch (value.unit) {
case YGUnitUndefined:
case YGUnitAuto:
return {true, 0};
return YGFloatOptional();
case YGUnitPoint:
return {false, value.value};
return YGFloatOptional(value.value);
case YGUnitPercent:
return {false, static_cast<float>(value.value * parentSize * 0.01)};
return YGFloatOptional(
static_cast<float>(value.value * parentSize * 0.01));
}
return {true, 0};
return YGFloatOptional();
}
inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) {

32
yoga/YGFloatOptional.cpp Normal file
View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "YGFloatOptional.h"
#include <cstdlib>
#include <iostream>
YGFloatOptional::YGFloatOptional(const float& value)
: value_(value), isUndefined_(false) {}
YGFloatOptional::YGFloatOptional() : value_(0), isUndefined_(true) {}
float YGFloatOptional::getValue() const {
if (isUndefined_) {
// Abort, accessing a value of an undefined float optional
std::cerr << "Tried to get value of an undefined YGFloatOptional\n";
std::exit(EXIT_FAILURE);
}
return value_;
}
void YGFloatOptional::setValue(const float& val) {
value_ = val;
isUndefined_ = false;
}
bool YGFloatOptional::isUndefined() const {
return isUndefined_;
}

26
yoga/YGFloatOptional.h Normal file
View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
struct YGFloatOptional {
private:
float value_;
bool isUndefined_;
public:
YGFloatOptional(const float& value);
YGFloatOptional();
// Program will terminate if the value of an undefined is accessed. Please
// make sure to check if the optional is defined before calling this function.
// To check if float optional is defined, use `isUndefined()`.
float getValue() const;
// Sets the value of float optional, and thus isUndefined is assigned false.
void setValue(const float& val);
bool isUndefined() const;
};

View File

@@ -500,7 +500,7 @@ YGValue YGNode::resolveFlexBasisPtr() const {
if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) {
return flexBasis;
}
if (!style_.flex.isUndefined && style_.flex.value > 0.0f) {
if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) {
return config_->useWebDefaults ? YGValueAuto : YGValueZero;
}
return YGValueAuto;
@@ -592,11 +592,11 @@ float YGNode::resolveFlexGrow() {
if (parent_ == nullptr) {
return 0.0;
}
if (!style_.flexGrow.isUndefined) {
return style_.flexGrow.value;
if (!style_.flexGrow.isUndefined()) {
return style_.flexGrow.getValue();
}
if (!style_.flex.isUndefined && style_.flex.value > 0.0f) {
return style_.flex.value;
if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) {
return style_.flex.getValue();
}
return kDefaultFlexGrow;
}
@@ -605,12 +605,12 @@ float YGNode::resolveFlexShrink() {
if (parent_ == nullptr) {
return 0.0;
}
if (!style_.flexShrink.isUndefined) {
return style_.flexShrink.value;
if (!style_.flexShrink.isUndefined()) {
return style_.flexShrink.getValue();
}
if (!config_->useWebDefaults && !style_.flex.isUndefined &&
style_.flex.value < 0.0f) {
return -style_.flex.value;
if (!config_->useWebDefaults && !style_.flex.isUndefined() &&
style_.flex.getValue() < 0.0f) {
return -style_.flex.getValue();
}
return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink;
}
@@ -653,8 +653,9 @@ float YGNode::getLeadingPadding(
const float widthSize) {
if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeStart].unit != YGUnitUndefined &&
!YGResolveValue(style_.padding[YGEdgeStart], widthSize).isUndefined &&
YGUnwrapFloatOptional(YGResolveValue(style_.padding[YGEdgeStart], widthSize)) > 0.0f) {
!YGResolveValue(style_.padding[YGEdgeStart], widthSize).isUndefined() &&
YGUnwrapFloatOptional(
YGResolveValue(style_.padding[YGEdgeStart], widthSize)) > 0.0f) {
return YGUnwrapFloatOptional(YGResolveValue(style_.padding[YGEdgeStart], widthSize));
}
@@ -669,8 +670,9 @@ float YGNode::getTrailingPadding(
const float widthSize) {
if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeEnd].unit != YGUnitUndefined &&
!YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined &&
YGUnwrapFloatOptional(YGResolveValue(style_.padding[YGEdgeEnd], widthSize)) >= 0.0f) {
!YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() &&
YGUnwrapFloatOptional(
YGResolveValue(style_.padding[YGEdgeEnd], widthSize)) >= 0.0f) {
return YGUnwrapFloatOptional(YGResolveValue(style_.padding[YGEdgeEnd], widthSize));
}

View File

@@ -43,8 +43,8 @@ static void appendFloatOptionalIfDefined(
string* base,
const string key,
const YGFloatOptional num) {
if (!num.isUndefined) {
appendFormatedString(base, "%s: %g; ", key.c_str(), num.value);
if (!num.isUndefined()) {
appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue());
}
}

View File

@@ -7,9 +7,6 @@
#include "YGStyle.h"
#define YGFloatOptionalUndefined \
{ true, 0 }
const YGValue kYGValueUndefined = {0, YGUnitUndefined};
const YGValue kYGValueAuto = {YGUndefined, YGUnitAuto};
@@ -42,9 +39,9 @@ YGStyle::YGStyle()
flexWrap(YGWrapNoWrap),
overflow(YGOverflowVisible),
display(YGDisplayFlex),
flex(YGFloatOptionalUndefined),
flexGrow(YGFloatOptionalUndefined),
flexShrink(YGFloatOptionalUndefined),
flex(YGFloatOptional()),
flexGrow(YGFloatOptional()),
flexShrink(YGFloatOptional()),
flexBasis({0, YGUnitAuto}),
margin(kYGDefaultEdgeValuesUnit),
position(kYGDefaultEdgeValuesUnit),
@@ -73,24 +70,25 @@ bool YGStyle::operator==(const YGStyle& style) {
YGValueArrayEqual(maxDimensions, style.maxDimensions);
areNonFloatValuesEqual =
areNonFloatValuesEqual && flex.isUndefined == style.flex.isUndefined;
if (areNonFloatValuesEqual && !flex.isUndefined && !style.flex.isUndefined) {
areNonFloatValuesEqual && flex.isUndefined() == style.flex.isUndefined();
if (areNonFloatValuesEqual && !flex.isUndefined() &&
!style.flex.isUndefined()) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && flex.value == style.flex.value;
areNonFloatValuesEqual && flex.getValue() == style.flex.getValue();
}
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexGrow.isUndefined == style.flexGrow.isUndefined;
if (areNonFloatValuesEqual && !flexGrow.isUndefined) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && flexGrow.value == style.flexGrow.value;
flexGrow.isUndefined() == style.flexGrow.isUndefined();
if (areNonFloatValuesEqual && !flexGrow.isUndefined()) {
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexGrow.getValue() == style.flexGrow.getValue();
}
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexShrink.isUndefined == style.flexShrink.isUndefined;
if (areNonFloatValuesEqual && !style.flexShrink.isUndefined) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && flexShrink.value == style.flexShrink.value;
flexShrink.isUndefined() == style.flexShrink.isUndefined();
if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) {
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexShrink.getValue() == style.flexShrink.getValue();
}
if (!(YGFloatIsUndefined(aspectRatio) &&

View File

@@ -6,6 +6,7 @@
*/
#pragma once
#include "YGFloatOptional.h"
#include "Yoga-internal.h"
#include "Yoga.h"

View File

@@ -13,7 +13,6 @@
#include "YGNode.h"
#include "YGNodePrint.h"
#include "Yoga-internal.h"
#ifdef _MSC_VER
#include <float.h>
@@ -511,16 +510,16 @@ void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) {
}
float YGNodeStyleGetFlexGrow(const YGNodeRef node) {
return node->getStyle().flexGrow.isUndefined
return node->getStyle().flexGrow.isUndefined()
? kDefaultFlexGrow
: node->getStyle().flexGrow.value;
: node->getStyle().flexGrow.getValue();
}
float YGNodeStyleGetFlexShrink(const YGNodeRef node) {
return node->getStyle().flexShrink.isUndefined
return node->getStyle().flexShrink.isUndefined()
? (node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink
: kDefaultFlexShrink)
: node->getStyle().flexShrink.value;
: node->getStyle().flexShrink.getValue();
}
#define YG_NODE_STYLE_PROPERTY_SETTER_IMPL( \
@@ -744,9 +743,9 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) {
if (!YGFloatOptionalFloatEquals(node->getStyle().flex, flex)) {
YGStyle style = node->getStyle();
if (YGFloatIsUndefined(flex)) {
style.flex = {true, 0};
style.flex = YGFloatOptional();
} else {
style.flex = {false, flex};
style.flex = YGFloatOptional(flex);
}
node->setStyle(style);
node->markDirtyAndPropogate();
@@ -755,8 +754,8 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) {
// TODO(T26792433): Change the API to accept YGFloatOptional.
float YGNodeStyleGetFlex(const YGNodeRef node) {
return node->getStyle().flex.isUndefined ? YGUndefined
: node->getStyle().flex.value;
return node->getStyle().flex.isUndefined() ? YGUndefined
: node->getStyle().flex.getValue();
}
// TODO(T26792433): Change the API to accept YGFloatOptional.
@@ -764,9 +763,9 @@ void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) {
if (!YGFloatOptionalFloatEquals(node->getStyle().flexGrow, flexGrow)) {
YGStyle style = node->getStyle();
if (YGFloatIsUndefined(flexGrow)) {
style.flexGrow = {true, 0};
style.flexGrow = YGFloatOptional();
} else {
style.flexGrow = {false, flexGrow};
style.flexGrow = YGFloatOptional(flexGrow);
}
node->setStyle(style);
node->markDirtyAndPropogate();
@@ -778,9 +777,9 @@ void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) {
if (!YGFloatOptionalFloatEquals(node->getStyle().flexShrink, flexShrink)) {
YGStyle style = node->getStyle();
if (YGFloatIsUndefined(flexShrink)) {
style.flexShrink = {true, 0};
style.flexShrink = YGFloatOptional();
} else {
style.flexShrink = {false, flexShrink};
style.flexShrink = YGFloatOptional(flexShrink);
}
node->setStyle(style);
node->markDirtyAndPropogate();
@@ -1669,13 +1668,15 @@ static float YGNodeCalculateAvailableInnerDim(
// We want to make sure our available height does not violate min and max
// constraints
const YGFloatOptional minDimensionOptional = YGResolveValue(node->getStyle().minDimensions[dimension], parentDim);
const float minInnerDim = minDimensionOptional.isUndefined
const float minInnerDim = minDimensionOptional.isUndefined()
? 0.0f
: minDimensionOptional.value - paddingAndBorder;
: minDimensionOptional.getValue() - paddingAndBorder;
const YGFloatOptional maxDimensionOptional = YGResolveValue(node->getStyle().maxDimensions[dimension], parentDim) ;
const float maxInnerDim = maxDimensionOptional.isUndefined ? FLT_MAX : maxDimensionOptional.value - paddingAndBorder;
const float maxInnerDim = maxDimensionOptional.isUndefined()
? FLT_MAX
: maxDimensionOptional.getValue() - paddingAndBorder;
availableInnerDim =
YGFloatMax(YGFloatMin(availableInnerDim, maxInnerDim), minInnerDim);
}
@@ -2207,7 +2208,8 @@ static void YGJustifyMainAxis(
if (measureModeMainDim == YGMeasureModeAtMost &&
collectedFlexItemsValues.remainingFreeSpace > 0) {
if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined &&
!YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisParentSize).isUndefined) {
!YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisParentSize)
.isUndefined()) {
collectedFlexItemsValues.remainingFreeSpace = YGFloatMax(
0,
YGUnwrapFloatOptional(YGResolveValue(
@@ -3713,8 +3715,8 @@ void YGNodeCalculateLayout(
node->getMarginForAxis(YGFlexDirectionRow, parentWidth);
widthMeasureMode = YGMeasureModeExactly;
} else if (!YGResolveValue(
node->getStyle().maxDimensions[YGDimensionWidth],
parentWidth).isUndefined) {
node->getStyle().maxDimensions[YGDimensionWidth], parentWidth)
.isUndefined()) {
width = YGUnwrapFloatOptional(YGResolveValue(
node->getStyle().maxDimensions[YGDimensionWidth], parentWidth));
widthMeasureMode = YGMeasureModeAtMost;
@@ -3732,8 +3734,10 @@ void YGNodeCalculateLayout(
parentHeight)) +
node->getMarginForAxis(YGFlexDirectionColumn, parentWidth);
heightMeasureMode = YGMeasureModeExactly;
} else if (!YGResolveValue(node->getStyle().maxDimensions[YGDimensionHeight],
parentHeight).isUndefined) {
} else if (!YGResolveValue(
node->getStyle().maxDimensions[YGDimensionHeight],
parentHeight)
.isUndefined()) {
height = YGUnwrapFloatOptional(YGResolveValue(node->getStyle().maxDimensions[YGDimensionHeight], parentHeight));
heightMeasureMode = YGMeasureModeAtMost;
} else {

View File

@@ -42,11 +42,6 @@ typedef struct YGValue {
YGUnit unit;
} YGValue;
struct YGFloatOptional {
bool isUndefined;
float value;
};
extern const YGValue YGValueUndefined;
extern const YGValue YGValueAuto;