Convert FX_Number to absl::variant<>.
Be stricter than is possible with just a union, and avoid tracking
the type of the value with two discrete booleans.
Change-Id: I71beb99c90a2c0fda42cb6d4ffbfeed29d8a2bf7
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114570
Commit-Queue: Thomas Sepez <tsepez@google.com>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/fx_number.cpp b/core/fxcrt/fx_number.cpp
index d577531..1d6c129 100644
--- a/core/fxcrt/fx_number.cpp
+++ b/core/fxcrt/fx_number.cpp
@@ -15,24 +15,18 @@
#include "core/fxcrt/fx_string.h"
#include "third_party/base/numerics/safe_conversions.h"
-FX_Number::FX_Number()
- : m_bIsInteger(true), m_bIsSigned(false), m_UnsignedValue(0) {}
+FX_Number::FX_Number() = default;
-FX_Number::FX_Number(int32_t value)
- : m_bIsInteger(true), m_bIsSigned(true), m_SignedValue(value) {}
+FX_Number::FX_Number(int32_t value) : value_(value) {}
-FX_Number::FX_Number(float value)
- : m_bIsInteger(false), m_bIsSigned(true), m_FloatValue(value) {}
+FX_Number::FX_Number(float value) : value_(value) {}
-FX_Number::FX_Number(ByteStringView strc)
- : m_bIsInteger(true), m_bIsSigned(false), m_UnsignedValue(0) {
+FX_Number::FX_Number(ByteStringView strc) {
if (strc.IsEmpty())
return;
if (strc.Contains('.')) {
- m_bIsInteger = false;
- m_bIsSigned = true;
- m_FloatValue = StringToFloat(strc);
+ value_ = StringToFloat(strc);
return;
}
@@ -42,14 +36,15 @@
// unsigned and then check for overflow if the user actually signed the value.
// The Permissions flag is listed in Table 3.20 PDF 1.7 spec.
FX_SAFE_UINT32 unsigned_val = 0;
+ bool bIsSigned = false;
bool bNegative = false;
size_t cc = 0;
if (strc[0] == '+') {
+ bIsSigned = true;
cc++;
- m_bIsSigned = true;
} else if (strc[0] == '-') {
+ bIsSigned = true;
bNegative = true;
- m_bIsSigned = true;
cc++;
}
@@ -61,8 +56,8 @@
}
uint32_t uValue = unsigned_val.ValueOrDefault(0);
- if (!m_bIsSigned) {
- m_UnsignedValue = uValue;
+ if (!bIsSigned) {
+ value_ = uValue;
return;
}
@@ -82,24 +77,38 @@
// becomes -2147483648. For this case, avoid undefined behavior, because
// an int32_t cannot represent 2147483648.
static constexpr int kMinInt = std::numeric_limits<int>::min();
- m_SignedValue = LIKELY(value != kMinInt) ? -value : kMinInt;
+ value_ = LIKELY(value != kMinInt) ? -value : kMinInt;
} else {
- m_SignedValue = value;
+ value_ = value;
}
}
+bool FX_Number::IsInteger() const {
+ return absl::holds_alternative<uint32_t>(value_) ||
+ absl::holds_alternative<int32_t>(value_);
+}
+
+bool FX_Number::IsSigned() const {
+ return absl::holds_alternative<int32_t>(value_) ||
+ absl::holds_alternative<float>(value_);
+}
+
int32_t FX_Number::GetSigned() const {
- if (m_bIsInteger) {
- return m_SignedValue;
+ if (absl::holds_alternative<uint32_t>(value_)) {
+ return static_cast<int32_t>(absl::get<uint32_t>(value_));
}
-
- return pdfium::base::saturated_cast<int32_t>(m_FloatValue);
+ if (absl::holds_alternative<int32_t>(value_)) {
+ return absl::get<int32_t>(value_);
+ }
+ return pdfium::base::saturated_cast<int32_t>(absl::get<float>(value_));
}
float FX_Number::GetFloat() const {
- if (!m_bIsInteger)
- return m_FloatValue;
-
- return m_bIsSigned ? static_cast<float>(m_SignedValue)
- : static_cast<float>(m_UnsignedValue);
+ if (absl::holds_alternative<uint32_t>(value_)) {
+ return static_cast<float>(absl::get<uint32_t>(value_));
+ }
+ if (absl::holds_alternative<int32_t>(value_)) {
+ return static_cast<float>(absl::get<int32_t>(value_));
+ }
+ return absl::get<float>(value_);
}
diff --git a/core/fxcrt/fx_number.h b/core/fxcrt/fx_number.h
index 3eda3eb..c943dec 100644
--- a/core/fxcrt/fx_number.h
+++ b/core/fxcrt/fx_number.h
@@ -10,29 +10,24 @@
#include <stdint.h>
#include "core/fxcrt/bytestring.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
class FX_Number {
public:
FX_Number();
- explicit FX_Number(uint32_t value) = delete;
+ explicit FX_Number(uint32_t value) = delete; // catch misuse.
explicit FX_Number(int32_t value);
explicit FX_Number(float value);
explicit FX_Number(ByteStringView str);
- bool IsInteger() const { return m_bIsInteger; }
- bool IsSigned() const { return m_bIsSigned; }
+ bool IsInteger() const;
+ bool IsSigned() const;
int32_t GetSigned() const; // Underflow/Overflow possible.
float GetFloat() const;
private:
- bool m_bIsInteger; // One of the two integers vs. float type.
- bool m_bIsSigned; // Only valid if |m_bInteger|.
- union {
- uint32_t m_UnsignedValue;
- int32_t m_SignedValue;
- float m_FloatValue;
- };
+ absl::variant<uint32_t, int32_t, float> value_ = 0u;
};
#endif // CORE_FXCRT_FX_NUMBER_H_