aboutsummaryrefslogtreecommitdiff
path: root/zencore/compactbinary.cpp
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-09-27 11:02:38 +0200
committerGitHub <[email protected]>2021-09-27 11:02:38 +0200
commitb34490abe0f19f22499fb9dafb9b7431ca5ecc95 (patch)
treebc16bece4710c612324318551dfd92fdbeb29232 /zencore/compactbinary.cpp
parentstats: Completed Meter implementation (diff)
downloadzen-b34490abe0f19f22499fb9dafb9b7431ca5ecc95.tar.xz
zen-b34490abe0f19f22499fb9dafb9b7431ca5ecc95.zip
Ported CbValue from Unreal to Zen (#10)
CompactBinary: Ported CbValue changes from UE5
Diffstat (limited to 'zencore/compactbinary.cpp')
-rw-r--r--zencore/compactbinary.cpp172
1 files changed, 84 insertions, 88 deletions
diff --git a/zencore/compactbinary.cpp b/zencore/compactbinary.cpp
index f4908aa9a..a68096c36 100644
--- a/zencore/compactbinary.cpp
+++ b/zencore/compactbinary.cpp
@@ -3,6 +3,7 @@
#include "zencore/compactbinary.h"
#include <zencore/compactbinaryvalidation.h>
+#include <zencore/compactbinaryvalue.h>
#include <zencore/compress.h>
#include <zencore/endian.h>
#include <zencore/stream.h>
@@ -66,21 +67,8 @@ TimeSpan::Set(int Days, int Hours, int Minutes, int Seconds, int FractionNano)
//////////////////////////////////////////////////////////////////////////
namespace CompactBinaryPrivate {
-
static constexpr const uint8_t GEmptyObjectPayload[] = {uint8_t(CbFieldType::Object), 0x00};
static constexpr const uint8_t GEmptyArrayPayload[] = {uint8_t(CbFieldType::Array), 0x01, 0x00};
-
- template<typename T>
- static constexpr inline T ReadUnaligned(const void* const Memory)
- {
-#if PLATFORM_SUPPORTS_UNALIGNED_LOADS
- return *static_cast<const T*>(Memory);
-#else
- T Value;
- memcpy(&Value, Memory, sizeof(Value));
- return Value;
-#endif
- }
} // namespace CompactBinaryPrivate
//////////////////////////////////////////////////////////////////////////
@@ -151,14 +139,10 @@ CbFieldView::AsArrayView()
MemoryView
CbFieldView::AsBinaryView(const MemoryView Default)
{
- if (CbFieldTypeOps::IsBinary(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsBinary(Accessor.GetType()))
{
- const uint8_t* const PayloadBytes = static_cast<const uint8_t*>(Payload);
- uint32_t ValueSizeByteCount;
- const uint64_t ValueSize = ReadVarUInt(PayloadBytes, ValueSizeByteCount);
-
Error = CbFieldError::None;
- return MemoryView(PayloadBytes + ValueSizeByteCount, ValueSize);
+ return Accessor.AsBinary();
}
else
{
@@ -170,20 +154,25 @@ CbFieldView::AsBinaryView(const MemoryView Default)
std::string_view
CbFieldView::AsString(const std::string_view Default)
{
- if (CbFieldTypeOps::IsString(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsString(Accessor.GetType()))
{
- const char* const PayloadChars = static_cast<const char*>(Payload);
- uint32_t ValueSizeByteCount;
- const uint64_t ValueSize = ReadVarUInt(PayloadChars, ValueSizeByteCount);
-
- if (ValueSize >= (uint64_t(1) << 31))
- {
- Error = CbFieldError::RangeError;
- return Default;
- }
+ Error = CbFieldError::None;
+ return Accessor.AsString();
+ }
+ else
+ {
+ Error = CbFieldError::TypeError;
+ return Default;
+ }
+}
+std::u8string_view
+CbFieldView::AsU8String(const std::u8string_view Default)
+{
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsString(Accessor.GetType()))
+ {
Error = CbFieldError::None;
- return std::string_view(PayloadChars + ValueSizeByteCount, ValueSize);
+ return Accessor.AsU8String();
}
else
{
@@ -193,23 +182,11 @@ CbFieldView::AsString(const std::string_view Default)
}
uint64_t
-CbFieldView::AsInteger(const uint64_t Default, const IntegerParams Params)
+CbFieldView::AsInteger(const uint64_t Default, const CompactBinaryPrivate::IntegerParams Params)
{
- if (CbFieldTypeOps::IsInteger(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsInteger(Accessor.GetType()))
{
- // A shift of a 64-bit value by 64 is undefined so shift by one less because magnitude is never zero.
- const uint64_t OutOfRangeMask = uint64_t(-2) << (Params.MagnitudeBits - 1);
- const uint64_t IsNegative = uint8_t(Type) & 1;
-
- uint32_t MagnitudeByteCount;
- const uint64_t Magnitude = ReadVarUInt(Payload, MagnitudeByteCount);
- const uint64_t Value = Magnitude ^ -int64_t(IsNegative);
-
- const uint64_t IsInRange = (!(Magnitude & OutOfRangeMask)) & ((!IsNegative) | Params.IsSigned);
- Error = IsInRange ? CbFieldError::None : CbFieldError::RangeError;
-
- const uint64_t UseValueMask = -int64_t(IsInRange);
- return (Value & UseValueMask) | (Default & ~UseValueMask);
+ return Accessor.AsInteger(Params, &Error, Default);
}
else
{
@@ -221,25 +198,24 @@ CbFieldView::AsInteger(const uint64_t Default, const IntegerParams Params)
float
CbFieldView::AsFloat(const float Default)
{
- switch (CbFieldTypeOps::GetType(Type))
+ switch (CbValue Accessor = GetValue(); Accessor.GetType())
{
case CbFieldType::IntegerPositive:
case CbFieldType::IntegerNegative:
{
- const uint64_t IsNegative = uint8_t(Type) & 1;
+ const uint64_t IsNegative = uint8_t(Accessor.GetType()) & 1;
constexpr uint64_t OutOfRangeMask = ~((uint64_t(1) << /*FLT_MANT_DIG*/ 24) - 1);
uint32_t MagnitudeByteCount;
- const int64_t Magnitude = ReadVarUInt(Payload, MagnitudeByteCount) + IsNegative;
+ const int64_t Magnitude = ReadVarUInt(Accessor.GetData(), MagnitudeByteCount) + IsNegative;
const uint64_t IsInRange = !(Magnitude & OutOfRangeMask);
Error = IsInRange ? CbFieldError::None : CbFieldError::RangeError;
return IsInRange ? float(IsNegative ? -Magnitude : Magnitude) : Default;
}
case CbFieldType::Float32:
{
- Error = CbFieldError::None;
- const uint32_t Value = FromNetworkOrder(CompactBinaryPrivate::ReadUnaligned<uint32_t>(Payload));
- return reinterpret_cast<const float&>(Value);
+ Error = CbFieldError::None;
+ return Accessor.AsFloat32();
}
case CbFieldType::Float64:
Error = CbFieldError::RangeError;
@@ -253,31 +229,29 @@ CbFieldView::AsFloat(const float Default)
double
CbFieldView::AsDouble(const double Default)
{
- switch (CbFieldTypeOps::GetType(Type))
+ switch (CbValue Accessor = GetValue(); Accessor.GetType())
{
case CbFieldType::IntegerPositive:
case CbFieldType::IntegerNegative:
{
- const uint64_t IsNegative = uint8_t(Type) & 1;
+ const uint64_t IsNegative = uint8_t(Accessor.GetType()) & 1;
constexpr uint64_t OutOfRangeMask = ~((uint64_t(1) << /*DBL_MANT_DIG*/ 53) - 1);
uint32_t MagnitudeByteCount;
- const int64_t Magnitude = ReadVarUInt(Payload, MagnitudeByteCount) + IsNegative;
+ const int64_t Magnitude = ReadVarUInt(Accessor.GetData(), MagnitudeByteCount) + IsNegative;
const uint64_t IsInRange = !(Magnitude & OutOfRangeMask);
Error = IsInRange ? CbFieldError::None : CbFieldError::RangeError;
return IsInRange ? double(IsNegative ? -Magnitude : Magnitude) : Default;
}
case CbFieldType::Float32:
{
- Error = CbFieldError::None;
- const uint32_t Value = FromNetworkOrder(CompactBinaryPrivate::ReadUnaligned<uint32_t>(Payload));
- return reinterpret_cast<const float&>(Value);
+ Error = CbFieldError::None;
+ return Accessor.AsFloat32();
}
case CbFieldType::Float64:
{
- Error = CbFieldError::None;
- const uint64_t Value = FromNetworkOrder(CompactBinaryPrivate::ReadUnaligned<uint64_t>(Payload));
- return reinterpret_cast<const double&>(Value);
+ Error = CbFieldError::None;
+ return Accessor.AsFloat64();
}
default:
Error = CbFieldError::TypeError;
@@ -288,19 +262,19 @@ CbFieldView::AsDouble(const double Default)
bool
CbFieldView::AsBool(const bool bDefault)
{
- const CbFieldType LocalType = Type;
- const bool bIsBool = CbFieldTypeOps::IsBool(LocalType);
- Error = bIsBool ? CbFieldError::None : CbFieldError::TypeError;
- return (uint8_t(bIsBool) & uint8_t(LocalType) & 1) | ((!bIsBool) & bDefault);
+ CbValue Accessor = GetValue();
+ const bool IsBool = CbFieldTypeOps::IsBool(Accessor.GetType());
+ Error = IsBool ? CbFieldError::None : CbFieldError::TypeError;
+ return (uint8_t(IsBool) & Accessor.AsBool()) | ((!IsBool) & bDefault);
}
IoHash
CbFieldView::AsObjectAttachment(const IoHash& Default)
{
- if (CbFieldTypeOps::IsObjectAttachment(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsObjectAttachment(Accessor.GetType()))
{
Error = CbFieldError::None;
- return IoHash::MakeFrom(Payload);
+ return Accessor.AsObjectAttachment();
}
else
{
@@ -312,10 +286,10 @@ CbFieldView::AsObjectAttachment(const IoHash& Default)
IoHash
CbFieldView::AsBinaryAttachment(const IoHash& Default)
{
- if (CbFieldTypeOps::IsBinaryAttachment(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsBinaryAttachment(Accessor.GetType()))
{
Error = CbFieldError::None;
- return IoHash::MakeFrom(Payload);
+ return Accessor.AsBinaryAttachment();
}
else
{
@@ -327,10 +301,10 @@ CbFieldView::AsBinaryAttachment(const IoHash& Default)
IoHash
CbFieldView::AsAttachment(const IoHash& Default)
{
- if (CbFieldTypeOps::IsAttachment(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsAttachment(Accessor.GetType()))
{
Error = CbFieldError::None;
- return IoHash::MakeFrom(Payload);
+ return Accessor.AsAttachment();
}
else
{
@@ -342,10 +316,10 @@ CbFieldView::AsAttachment(const IoHash& Default)
IoHash
CbFieldView::AsHash(const IoHash& Default)
{
- if (CbFieldTypeOps::IsHash(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsHash(Accessor.GetType()))
{
Error = CbFieldError::None;
- return IoHash::MakeFrom(Payload);
+ return Accessor.AsHash();
}
else
{
@@ -363,16 +337,10 @@ CbFieldView::AsUuid()
Guid
CbFieldView::AsUuid(const Guid& Default)
{
- if (CbFieldTypeOps::IsUuid(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsUuid(Accessor.GetType()))
{
Error = CbFieldError::None;
- Guid Value;
- memcpy(&Value, Payload, sizeof(Guid));
- Value.A = FromNetworkOrder(Value.A);
- Value.B = FromNetworkOrder(Value.B);
- Value.C = FromNetworkOrder(Value.C);
- Value.D = FromNetworkOrder(Value.D);
- return Value;
+ return Accessor.AsUuid();
}
else
{
@@ -390,12 +358,40 @@ CbFieldView::AsObjectId()
Oid
CbFieldView::AsObjectId(const Oid& Default)
{
- if (CbFieldTypeOps::IsObjectId(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsObjectId(Accessor.GetType()))
+ {
+ Error = CbFieldError::None;
+ return Accessor.AsObjectId();
+ }
+ else
+ {
+ Error = CbFieldError::TypeError;
+ return Default;
+ }
+}
+
+CbCustomById
+CbFieldView::AsCustomById(CbCustomById Default)
+{
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsCustomById(Accessor.GetType()))
+ {
+ Error = CbFieldError::None;
+ return Accessor.AsCustomById();
+ }
+ else
+ {
+ Error = CbFieldError::TypeError;
+ return Default;
+ }
+}
+
+CbCustomByName
+CbFieldView::AsCustomByName(CbCustomByName Default)
+{
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsCustomByName(Accessor.GetType()))
{
Error = CbFieldError::None;
- Oid Value;
- memcpy(&Value, Payload, sizeof(Oid));
- return Value;
+ return Accessor.AsCustomByName();
}
else
{
@@ -407,10 +403,10 @@ CbFieldView::AsObjectId(const Oid& Default)
int64_t
CbFieldView::AsDateTimeTicks(const int64_t Default)
{
- if (CbFieldTypeOps::IsDateTime(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsDateTime(Accessor.GetType()))
{
Error = CbFieldError::None;
- return FromNetworkOrder(CompactBinaryPrivate::ReadUnaligned<int64_t>(Payload));
+ return Accessor.AsDateTimeTicks();
}
else
{
@@ -434,10 +430,10 @@ CbFieldView::AsDateTime(DateTime Default)
int64_t
CbFieldView::AsTimeSpanTicks(const int64_t Default)
{
- if (CbFieldTypeOps::IsTimeSpan(Type))
+ if (CbValue Accessor = GetValue(); CbFieldTypeOps::IsTimeSpan(Accessor.GetType()))
{
Error = CbFieldError::None;
- return FromNetworkOrder(CompactBinaryPrivate::ReadUnaligned<int64_t>(Payload));
+ return Accessor.AsTimeSpanTicks();
}
else
{