diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 8c6e91cc..aec7564f 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -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( diff --git a/yoga/Utils.h b/yoga/Utils.h index 311030e2..7190fd7f 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -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(value.value * parentSize * 0.01)}; + return YGFloatOptional( + static_cast(value.value * parentSize * 0.01)); } - return {true, 0}; + return YGFloatOptional(); } inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) { diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp new file mode 100644 index 00000000..af9a6fc4 --- /dev/null +++ b/yoga/YGFloatOptional.cpp @@ -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 +#include + +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_; +} diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h new file mode 100644 index 00000000..d82230be --- /dev/null +++ b/yoga/YGFloatOptional.h @@ -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; +}; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index df61b14a..5a33c6e8 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -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)); } diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index ab0666d0..ab3aa7c7 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -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()); } } diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 031443c8..437b682d 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -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) && diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 3abc4c08..7a7f519a 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -6,6 +6,7 @@ */ #pragma once +#include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index b21b23d2..570f7ab9 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -13,7 +13,6 @@ #include "YGNode.h" #include "YGNodePrint.h" #include "Yoga-internal.h" - #ifdef _MSC_VER #include @@ -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 { diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 83eefa02..2ec6a687 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -42,11 +42,6 @@ typedef struct YGValue { YGUnit unit; } YGValue; -struct YGFloatOptional { - bool isUndefined; - float value; -}; - extern const YGValue YGValueUndefined; extern const YGValue YGValueAuto;