aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-03-06 12:49:31 +0100
committerGitHub <[email protected]>2024-03-06 12:49:31 +0100
commit151b0a7766a115103416e48a6c9e0bf5acc2a5aa (patch)
treef41cc33637185b68315bb1ee9198df2974d02fe4 /src
parentalso update validate to avoid code sign problems (diff)
downloadzen-151b0a7766a115103416e48a6c9e0bf5acc2a5aa.tar.xz
zen-151b0a7766a115103416e48a6c9e0bf5acc2a5aa.zip
Add WriteMeasuredVarUInt to avoid measuring ints twice before writing (#665)
Avoid double resize of buffer in CbWriter::SetName and CbWriter::AddBinary Add WriteMeasuredVarUInt to avoid measuring ints twice before writing
Diffstat (limited to 'src')
-rw-r--r--src/zencore/compactbinarybuilder.cpp33
-rw-r--r--src/zencore/include/zencore/varint.h46
2 files changed, 53 insertions, 26 deletions
diff --git a/src/zencore/compactbinarybuilder.cpp b/src/zencore/compactbinarybuilder.cpp
index 5c08d2e6e..3331291ce 100644
--- a/src/zencore/compactbinarybuilder.cpp
+++ b/src/zencore/compactbinarybuilder.cpp
@@ -221,12 +221,11 @@ CbWriter::SetName(const std::string_view Name)
State.Flags |= StateFlags::Name;
const uint32_t NameLenByteCount = MeasureVarUInt(uint32_t(Name.size()));
const int64_t NameLenOffset = Data.size();
- Data.resize(NameLenOffset + NameLenByteCount);
+ Data.resize(NameLenOffset + NameLenByteCount + Name.size());
- WriteVarUInt(uint64_t(Name.size()), Data.data() + NameLenOffset);
+ WriteMeasuredVarUInt(uint64_t(Name.size()), NameLenByteCount, Data.data() + NameLenOffset);
- const uint8_t* NamePtr = reinterpret_cast<const uint8_t*>(Name.data());
- Data.insert(Data.end(), NamePtr, NamePtr + Name.size());
+ memcpy(Data.data() + NameLenOffset + NameLenByteCount, Name.data(), Name.size());
return *this;
}
@@ -341,7 +340,7 @@ CbWriter::EndObject()
const uint64_t Size = uint64_t(Data.size() - PayloadOffset);
const uint32_t SizeByteCount = MeasureVarUInt(Size);
Data.insert(Data.begin() + PayloadOffset, SizeByteCount, 0);
- WriteVarUInt(Size, Data.data() + PayloadOffset);
+ WriteMeasuredVarUInt(Size, SizeByteCount, Data.data() + PayloadOffset);
EndField(bUniform ? CbFieldType::UniformObject : CbFieldType::Object);
}
@@ -400,8 +399,8 @@ CbWriter::EndArray()
const uint64_t Size = uint64_t(Data.size() - PayloadOffset) + CountByteCount;
const uint32_t SizeByteCount = MeasureVarUInt(Size);
Data.insert(Data.begin() + PayloadOffset, SizeByteCount + CountByteCount, 0);
- WriteVarUInt(Size, Data.data() + PayloadOffset);
- WriteVarUInt(Count, Data.data() + PayloadOffset + SizeByteCount);
+ WriteMeasuredVarUInt(Size, SizeByteCount, Data.data() + PayloadOffset);
+ WriteMeasuredVarUInt(Count, CountByteCount, Data.data() + PayloadOffset + SizeByteCount);
EndField(bUniform ? CbFieldType::UniformArray : CbFieldType::Array);
}
@@ -429,13 +428,13 @@ CbWriter::AddNull()
void
CbWriter::AddBinary(const void* const Value, const uint64_t Size)
{
- const size_t SizeByteCount = MeasureVarUInt(Size);
+ const uint32_t SizeByteCount = MeasureVarUInt(Size);
Data.reserve(Data.size() + 1 + SizeByteCount + Size);
BeginField();
const size_t SizeOffset = Data.size();
- Data.resize(Data.size() + SizeByteCount);
- WriteVarUInt(Size, Data.data() + SizeOffset);
- Data.insert(Data.end(), static_cast<const uint8_t*>(Value), static_cast<const uint8_t*>(Value) + Size);
+ Data.resize(Data.size() + SizeByteCount + Size);
+ WriteMeasuredVarUInt(Size, SizeByteCount, Data.data() + SizeOffset);
+ memcpy(Data.data() + SizeOffset + SizeByteCount, Value, Size);
EndField(CbFieldType::Binary);
}
@@ -468,7 +467,7 @@ CbWriter::AddString(const std::string_view Value)
Data.resize(Offset + SizeByteCount + Size);
uint8_t* StringData = Data.data() + Offset;
- WriteVarUInt(Size, StringData);
+ WriteMeasuredVarUInt(Size, SizeByteCount, StringData);
StringData += SizeByteCount;
if (Size > 0)
{
@@ -489,7 +488,7 @@ CbWriter::AddString(const std::wstring_view Value)
const int64_t Offset = Data.size();
Data.resize(Offset + SizeByteCount + Size);
uint8_t* StringData = Data.data() + Offset;
- WriteVarUInt(Size, StringData);
+ WriteMeasuredVarUInt(Size, SizeByteCount, StringData);
StringData += SizeByteCount;
if (Size > 0)
{
@@ -511,7 +510,7 @@ CbWriter::AddInteger(const int32_t Value)
const uint32_t MagnitudeByteCount = MeasureVarUInt(Magnitude);
const int64_t Offset = Data.size();
Data.resize(Offset + MagnitudeByteCount);
- WriteVarUInt(Magnitude, Data.data() + Offset);
+ WriteMeasuredVarUInt(Magnitude, MagnitudeByteCount, Data.data() + Offset);
EndField(CbFieldType::IntegerNegative);
}
@@ -526,7 +525,7 @@ CbWriter::AddInteger(const int64_t Value)
const uint64_t Magnitude = ~uint64_t(Value);
const uint32_t MagnitudeByteCount = MeasureVarUInt(Magnitude);
const uint64_t Offset = AddUninitialized(Data, MagnitudeByteCount);
- WriteVarUInt(Magnitude, Data.data() + Offset);
+ WriteMeasuredVarUInt(Magnitude, MagnitudeByteCount, Data.data() + Offset);
EndField(CbFieldType::IntegerNegative);
}
@@ -537,7 +536,7 @@ CbWriter::AddInteger(const uint32_t Value)
BeginField();
const uint32_t ValueByteCount = MeasureVarUInt(Value);
const uint64_t Offset = AddUninitialized(Data, ValueByteCount);
- WriteVarUInt(Value, Data.data() + Offset);
+ WriteMeasuredVarUInt(Value, ValueByteCount, Data.data() + Offset);
EndField(CbFieldType::IntegerPositive);
}
@@ -548,7 +547,7 @@ CbWriter::AddInteger(const uint64_t Value)
BeginField();
const uint32_t ValueByteCount = MeasureVarUInt(Value);
const uint64_t Offset = AddUninitialized(Data, ValueByteCount);
- WriteVarUInt(Value, Data.data() + Offset);
+ WriteMeasuredVarUInt(Value, ValueByteCount, Data.data() + Offset);
EndField(CbFieldType::IntegerPositive);
}
diff --git a/src/zencore/include/zencore/varint.h b/src/zencore/include/zencore/varint.h
index c0d63d814..ae9aceed6 100644
--- a/src/zencore/include/zencore/varint.h
+++ b/src/zencore/include/zencore/varint.h
@@ -181,17 +181,17 @@ ReadVarInt(const void* InData, uint32_t& OutByteCount)
}
/**
- * Write a variable-length unsigned integer.
+ * Write a pre-measured variable-length unsigned integer.
*
* @param InValue An unsigned integer to encode.
+ * @param ByteCount The number of bytes the integer requires to be encoded
* @param OutData A buffer of at least 5 bytes to write the output to.
* @return The number of bytes used in the output.
*/
-inline uint32_t
-WriteVarUInt(uint32_t InValue, void* OutData)
+inline void
+WriteMeasuredVarUInt(uint32_t InValue, uint32_t ByteCount, void* OutData)
{
- const uint32_t ByteCount = MeasureVarUInt(InValue);
- uint8_t* OutBytes = static_cast<uint8_t*>(OutData) + ByteCount - 1;
+ uint8_t* OutBytes = static_cast<uint8_t*>(OutData) + ByteCount - 1;
switch (ByteCount - 1)
{
case 4:
@@ -214,21 +214,35 @@ WriteVarUInt(uint32_t InValue, void* OutData)
break;
}
*OutBytes = uint8_t(0xff << (9 - ByteCount)) | uint8_t(InValue);
- return ByteCount;
}
/**
* Write a variable-length unsigned integer.
*
* @param InValue An unsigned integer to encode.
- * @param OutData A buffer of at least 9 bytes to write the output to.
+ * @param OutData A buffer of at least 5 bytes to write the output to.
* @return The number of bytes used in the output.
*/
inline uint32_t
-WriteVarUInt(uint64_t InValue, void* OutData)
+WriteVarUInt(uint32_t InValue, void* OutData)
{
const uint32_t ByteCount = MeasureVarUInt(InValue);
- uint8_t* OutBytes = static_cast<uint8_t*>(OutData) + ByteCount - 1;
+ WriteMeasuredVarUInt(InValue, MeasureVarUInt(InValue), OutData);
+ return ByteCount;
+}
+
+/**
+ * Write a pre-measured variable-length unsigned integer.
+ *
+ * @param InValue An unsigned integer to encode.
+ * @param ByteCount The number of bytes the integer requires to be encoded
+ * @param OutData A buffer of at least 9 bytes to write the output to.
+ * @return The number of bytes used in the output.
+ */
+inline void
+WriteMeasuredVarUInt(uint64_t InValue, uint32_t ByteCount, void* OutData)
+{
+ uint8_t* OutBytes = static_cast<uint8_t*>(OutData) + ByteCount - 1;
switch (ByteCount - 1)
{
case 8:
@@ -267,6 +281,20 @@ WriteVarUInt(uint64_t InValue, void* OutData)
break;
}
*OutBytes = uint8_t(0xff << (9 - ByteCount)) | uint8_t(InValue);
+}
+
+/**
+ * Write a variable-length unsigned integer.
+ *
+ * @param InValue An unsigned integer to encode.
+ * @param OutData A buffer of at least 9 bytes to write the output to.
+ * @return The number of bytes used in the output.
+ */
+inline uint32_t
+WriteVarUInt(uint64_t InValue, void* OutData)
+{
+ const uint32_t ByteCount = MeasureVarUInt(InValue);
+ WriteMeasuredVarUInt(InValue, ByteCount, OutData);
return ByteCount;
}