Skip to content

Commit 808a4b0

Browse files
committed
Merge branch 'master' of https://github.com/5e3/CompoundFs
2 parents 8a53408 + 8b2247b commit 808a4b0

17 files changed

Lines changed: 1482 additions & 326 deletions

Rfx/Blob.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
namespace Rfx
1515
{
1616

17+
///////////////////////////////////////////////////////////////////////////////
18+
/// Binary large object with a more agressively allocating grow() function and allocation
19+
/// that avoids the usual value initialization (see std::make_unique_for_overwrite())
1720
class Blob
1821
{
1922
std::unique_ptr<std::byte[]> m_storage;
@@ -39,8 +42,6 @@ class Blob
3942
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
4043
const_reverse_iterator crend() const noexcept { return rend(); }
4144

42-
43-
4445
public:
4546
Blob() = default;
4647
explicit Blob(size_t size);
@@ -67,6 +68,8 @@ class Blob
6768
void push_back(std::byte val) { *grow(1) = val; }
6869
};
6970

71+
///////////////////////////////////////////////////////////////////////////////
72+
7073
inline Blob::Blob(size_t size)
7174
: Blob()
7275
{
@@ -87,7 +90,6 @@ inline Blob::Blob(TString&& str)
8790
std::string_view sv(std::forward<TString>(str));
8891
for (auto ch: sv)
8992
push_back((std::byte) ch );
90-
9193
}
9294

9395
inline Blob::Blob(const Blob& other)

Rfx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set (Headers
2525
StreamRule.h
2626
PushBits.h
2727
Rfx.natvis
28+
TypeUtils.h
2829
)
2930

3031
if(WIN32)

Rfx/CompressedInteger.h

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,71 +3,83 @@
33
#pragma once
44

55
#include <concepts>
6-
#include <iterator>
6+
#include <cstddef>
77
#include <bit>
88
#include <limits>
9+
#include <stdexcept>
910

1011
namespace Rfx
1112
{
1213

1314
template <typename T>
1415
struct StreamRule;
1516

17+
///////////////////////////////////////////////////////////////////////////////
18+
1619
constexpr int compressedSize(size_t value)
1720
{
1821
value |= 0x1; // fix the 0 case
1922
return (std::bit_width(value) + 6) / 7;
2023
}
2124

25+
///////////////////////////////////////////////////////////////////////////////
2226

2327
template <std::integral Integer>
2428
struct CompressedInteger;
2529

26-
template <>
27-
struct CompressedInteger<size_t>
30+
///////////////////////////////////////////////////////////////////////////////
31+
32+
template <>
33+
struct CompressedInteger<size_t>
2834
{
29-
size_t m_value;
30-
operator size_t() const { return m_value; }
31-
};
35+
size_t m_value;
36+
operator size_t() const { return m_value; }
37+
};
3238

33-
template<>
39+
///////////////////////////////////////////////////////////////////////////////
40+
41+
template <>
3442
struct StreamRule<CompressedInteger<size_t>>
3543
{
44+
static constexpr std::byte MASK { 0b01111111 }; // Mask for extracting 7 bits
45+
static constexpr std::byte MORE { 0b10000000 }; // Indicator that more bytes are to follow
3646

3747
template <typename TStream>
38-
static void write(CompressedInteger<size_t> value, TStream& stream)
48+
static void write(CompressedInteger<size_t> value, TStream&& stream)
3949
{
40-
const std::byte mask { 0b01111111 };
41-
const std::byte more = ~mask;
42-
const int size = compressedSize(value.m_value);
43-
for (int i = 0; i < size - 1; i++)
50+
size_t temp = value.m_value;
51+
52+
// Write all the bytes except the last one
53+
while (temp >= 0b10000000) // While more than 7 bits remain
4454
{
45-
stream.write((std::byte(value.m_value) & mask ) | more);
46-
value.m_value >>= 7;
55+
stream.write(std::byte(temp) & MASK | MORE); // Write 7 bits with the continuation bit set
56+
temp >>= 7; // Shift to get the next 7 bits
4757
}
48-
49-
stream.write(std::byte(value.m_value) & mask);
58+
59+
// Write the last byte without the continuation bit
60+
stream.write(std::byte(temp) & MASK);
5061
}
5162

5263
template <typename TStream>
53-
static void read(CompressedInteger<size_t>& value, TStream& stream)
64+
static void read(CompressedInteger<size_t>& value, TStream&& stream)
5465
{
55-
const std::byte mask { 0b01111111 };
56-
const std::byte more = ~mask;
66+
size_t result = 0;
67+
int shift = 0;
5768
std::byte b;
58-
stream.read(b);
59-
value.m_value = size_t(b & mask);
60-
int count = 1;
61-
while ((b & more) != std::byte{0})
69+
70+
// Read bytes while the continuation bit is set
71+
do
6272
{
63-
if (count == compressedSize(std::numeric_limits<size_t>::max()))
73+
if (shift >= compressedSize(std::numeric_limits<size_t>::max()) * 7)
6474
throw std::runtime_error("read CompressedInteger out of bounds");
75+
6576
stream.read(b);
66-
value.m_value |= size_t(b & mask) << (7 * count);
67-
count++;
68-
}
77+
result |= (size_t(b & MASK) << shift); // Extract 7 bits and shift them into position
78+
shift += 7; // Move to the next 7-bit group
79+
} while (std::to_integer<uint8_t>(b & MORE)); // Continue if the continuation bit is set
80+
81+
value.m_value = result; // Set the result in the compressed integer
6982
}
7083
};
7184

72-
7385
}

Rfx/PushBits.h

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212

1313
namespace Rfx
1414
{
15+
16+
#ifdef _DEBUG
17+
constexpr bool debug_mode = true;
18+
#else
19+
constexpr bool debug_mode = false;
20+
#endif
21+
1522
template<typename T>
1623
concept BitStreamable = (std::is_arithmetic_v<T> || std::is_enum_v<T>);
1724

@@ -37,6 +44,9 @@ TIter copyBits(TRange first, TRange last, TIter pos)
3744
requires(BitStreamable<std::iter_value_t<TRange>> && std::same_as<std::iter_value_t<TIter>, std::byte>)
3845
{
3946
size_t size = last - first;
47+
if (debug_mode && size == 0)
48+
return pos;
49+
4050
const std::byte* ptr = reinterpret_cast<const std::byte*>(&(*first));
4151
return std::copy(ptr, ptr + (sizeof(std::iter_value_t<TRange>) * size), pos);
4252
}
@@ -67,6 +77,9 @@ TIter copyBits(TIter pos, TRange first, TRange last)
6777
requires(BitStreamable<std::iter_value_t<TRange>> && std::same_as<std::iter_value_t<TIter>, std::byte>)
6878
{
6979
size_t size = last - first;
80+
if (debug_mode && size == 0)
81+
return pos;
82+
7083
std::byte* ptr = reinterpret_cast<std::byte*>(&(*first));
7184
auto endPos = pos + (sizeof(std::iter_value_t<TRange>) * size);
7285
std::copy(pos, endPos, ptr);
@@ -91,16 +104,6 @@ void pushBits(const TRange& range, Blob& blob)
91104
copyBits(range.begin(), range.end(), it);
92105
}
93106

94-
template <std::ranges::range TRange>
95-
void pushBits(const TRange& range, Blob& blob)
96-
requires(BitStreamable<std::ranges::range_value_t<TRange>> && !std::ranges::sized_range<TRange>)
97-
{
98-
for (auto it = range.begin(); it != range.end(); ++it)
99-
{
100-
auto pos = blob.grow(sizeof(std::ranges::range_value_t<TRange>));
101-
copyBits(*it, pos);
102-
}
103-
}
104107

105108
///////////////////////////////////////////////////////////////////////////////
106109

@@ -124,8 +127,6 @@ T popBits(BlobRange& blobRange)
124127
return value;
125128
}
126129

127-
128-
129130
/// for containers of BitStreamable (like std::list<double>)
130131
template <std::ranges::sized_range TRange>
131132
auto popBits(TRange& valueRange, BlobRange blobRange)
@@ -136,16 +137,6 @@ auto popBits(TRange& valueRange, BlobRange blobRange)
136137
return copyBits(blobRange.begin(), valueRange.begin(), valueRange.end());
137138
}
138139

139-
/// for ranges of BitStreamables of unkown size (like std::ranges::subrange<std::list<double>::iterator>)
140-
template <std::ranges::range TRange>
141-
auto popBits(TRange& valueRange, BlobRange blobRange)
142-
requires(BitStreamable<std::ranges::range_value_t<TRange>> && !std::ranges::sized_range<TRange>)
143-
{
144-
Blob::const_iterator it = blobRange.begin();
145-
for (auto& value: valueRange)
146-
it = popBits(value, BlobRange(it, blobRange.end()));
147-
return it;
148-
}
149140

150141

151142

Rfx/Stream.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
namespace Rfx
1414
{
15-
15+
///////////////////////////////////////////////////////////////////////////////
16+
/// Stream into Blob with versioning.
1617
class StreamOut
1718
{
1819
Blob m_blob;
@@ -27,7 +28,7 @@ class StreamOut
2728
{
2829
if constexpr (BitStreamable<T>)
2930
pushBits(value, m_blob);
30-
else if constexpr (isVersioned<T>)
31+
else if constexpr (IsVersioned_v<T>)
3132
{
3233
size_t topIndex = m_fixups.size();
3334
auto fixup = m_fixups.nextFixup(m_blob.size());
@@ -78,8 +79,9 @@ class StreamOut
7879
}
7980
};
8081

81-
82-
class StreamIn
82+
///////////////////////////////////////////////////////////////////////////////
83+
/// Stream from Blob with versioning.
84+
class StreamIn
8385
{
8486
Blob::const_iterator m_first;
8587
Blob::const_iterator m_last;
@@ -114,7 +116,7 @@ class StreamIn
114116
{
115117
m_first = popBits(value, asRange());
116118
}
117-
else if constexpr (isVersioned<T>)
119+
else if constexpr (IsVersioned_v<T>)
118120
{
119121
auto last = m_last;
120122
auto currentFixup = m_currentFixup;
@@ -150,9 +152,11 @@ class StreamIn
150152
template<typename T>
151153
void operator()(T& value)
152154
{
153-
if (m_first < m_last)
155+
if (!empty())
154156
read(value);
155157
}
158+
159+
bool empty() const { return m_first == m_last; }
156160
};
157161

158162
}

0 commit comments

Comments
 (0)