Skip to content

Commit 4fdc8a9

Browse files
committed
tidy up Blob and UTs
1 parent 808a4b0 commit 4fdc8a9

2 files changed

Lines changed: 90 additions & 53 deletions

File tree

Rfx/Blob.h

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ namespace Rfx
1919
/// that avoids the usual value initialization (see std::make_unique_for_overwrite())
2020
class Blob
2121
{
22-
std::unique_ptr<std::byte[]> m_storage;
2322
size_t m_size = 0;
2423
size_t m_capacity = 0;
24+
std::unique_ptr<std::byte[]> m_storage;
2525

2626
public:
2727
using iterator = std::byte*;
@@ -48,11 +48,10 @@ class Blob
4848
template <std::input_iterator It> Blob(It begin, It end) requires std::is_same_v<std::iter_value_t<It>, std::byte>;
4949
template <std::convertible_to<std::string_view> TString> Blob(TString&& str);
5050
Blob(const Blob& other);
51-
Blob(Blob&& other) noexcept;
52-
~Blob() = default;
51+
Blob(Blob&& other) noexcept = default;
5352

5453
Blob& operator=(const Blob&);
55-
Blob& operator=(Blob&&) noexcept;
54+
Blob& operator=(Blob&&) noexcept = default;
5655

5756
auto operator<=>(const Blob& rhs) const noexcept;
5857
bool operator==(const Blob& rhs) const noexcept;
@@ -71,17 +70,18 @@ class Blob
7170
///////////////////////////////////////////////////////////////////////////////
7271

7372
inline Blob::Blob(size_t size)
74-
: Blob()
73+
: m_size(size)
74+
, m_capacity(std::max(std::bit_ceil(size), size_t(1024)))
75+
, m_storage(std::make_unique_for_overwrite<std::byte[]>(m_capacity))
7576
{
76-
grow(size);
7777
}
7878

7979
template <std::input_iterator It>
8080
inline Blob::Blob(It begin, It end)
8181
requires std::is_same_v<std::iter_value_t<It>, std::byte>
8282
{
8383
for (; begin != end; ++begin)
84-
*grow(1) = *begin;
84+
push_back(*begin);
8585
}
8686

8787
template <std::convertible_to<std::string_view> TString>
@@ -98,37 +98,20 @@ inline Blob::Blob(const Blob& other)
9898
std::copy(other.begin(), other.end(), begin());
9999
}
100100

101-
inline Blob::Blob(Blob&& other) noexcept
102-
: m_storage(std::move(other.m_storage))
103-
, m_size(other.m_size)
104-
, m_capacity(other.m_capacity)
101+
inline Blob& Blob::operator=(const Blob& other)
105102
{
106-
other.m_size = 0;
107-
other.m_capacity = 0;
108-
}
109-
110-
inline Blob& Blob::operator= (const Blob& other)
111-
{
112-
if (&other != this)
103+
if (!m_storage || other.m_size > m_capacity)
113104
{
114-
if (other.size() > m_size)
115-
grow(other.size() - m_size);
116-
117-
std::copy(other.begin(), other.end(), begin());
105+
Blob cpy { other };
106+
return operator=(std::move(cpy));
118107
}
119-
return *this;
120-
}
121108

122-
inline Blob& Blob::operator=(Blob&& other) noexcept
123-
{
124109
if (&other != this)
125110
{
126-
m_storage = std::move(other.m_storage);
111+
std::copy(other.begin(), other.end(), begin());
127112
m_size = other.m_size;
128-
m_capacity = other.m_capacity;
129-
other.m_size = 0;
130-
other.m_capacity = 0;
131113
}
114+
132115
return *this;
133116
}
134117

@@ -148,28 +131,25 @@ inline bool Blob::operator==(const Blob& rhs) const noexcept
148131

149132
inline Blob::iterator Blob::grow(size_t size)
150133
{
151-
auto newSize = size + m_size;
152-
auto start = m_size;
153-
reserve(newSize);
154-
m_size = newSize;
155-
return m_storage.get() + start;
134+
auto s = m_size;
135+
resize(m_size + size);
136+
return begin() + s;
156137
}
157138

158139
inline void Blob::resize(size_t size)
159140
{
160-
if (m_size < size)
161-
reserve(size);
141+
reserve(size);
162142
m_size = size;
163143
}
164144

165145
inline void Blob::reserve(size_t capacity)
166146
{
167147
if (m_capacity < capacity)
168148
{
169-
m_capacity = std::max(std::bit_ceil(capacity), size_t(1024));
170-
auto storage = std::move(m_storage);
171-
m_storage = std::make_unique_for_overwrite<std::byte[]>(m_capacity);
172-
std::copy(storage.get(), storage.get() + m_size, begin());
149+
Blob cpy(capacity);
150+
cpy.m_size = m_size;
151+
std::copy(begin(), end(), cpy.begin());
152+
operator=(std::move(cpy));
173153
}
174154
}
175155

TestRfx/TestBlob.cpp

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ TEST(Blob, initialize_list)
3131
ASSERT_EQ(ar[3], std::byte { 't' });
3232
}
3333

34+
TEST(Blob, CopyCtor)
35+
{
36+
Blob b1 = "dasisntest";
37+
auto b2 = b1;
38+
ASSERT_EQ(b1.size(), b2.size());
39+
ASSERT_TRUE(std::equal(b1.begin(), b1.end(), b2.begin()));
40+
ASSERT_NE(b1.begin(), b2.begin());
41+
}
42+
43+
TEST(Blob, Assignment)
44+
{
45+
Blob b1 = "dasisntest";
46+
Blob b2;
47+
b2 = b1;
48+
ASSERT_EQ(b1.size(), b2.size());
49+
ASSERT_TRUE(std::equal(b1.begin(), b1.end(), b2.begin()));
50+
ASSERT_NE(b1.begin(), b2.begin());
51+
52+
Blob b3 = "test";
53+
auto it = b3.begin();
54+
b3 = b1;
55+
ASSERT_EQ(b1.size(), b3.size());
56+
ASSERT_TRUE(std::equal(b1.begin(), b1.end(), b3.begin()));
57+
ASSERT_EQ(it, b3.begin());
58+
59+
Blob b4 = b1;
60+
b4 = b4;
61+
ASSERT_EQ(b1.size(), b4.size());
62+
ASSERT_TRUE(std::equal(b1.begin(), b1.end(), b4.begin()));
63+
}
64+
3465
TEST(Blob, comparison)
3566
{
3667
Blob b1 = "testlang";
@@ -51,7 +82,30 @@ TEST(Blob, comparison)
5182
ASSERT_NE(b4.capacity(), b2.capacity());
5283
}
5384

54-
TEST(Blob, Ctors)
85+
TEST(Blob, moveCtorAssignment)
86+
{
87+
Blob b1 = "dasisntest";
88+
{
89+
auto b2 = b1;
90+
auto it = b2.begin();
91+
auto b3 = std::move(b2);
92+
ASSERT_EQ(b3, b1);
93+
ASSERT_EQ(it, b3.begin());
94+
} // call moved-from d'tor
95+
96+
auto b2 = b1;
97+
auto b3 = std::move(b2);
98+
auto it = b1.begin();
99+
b2 = std::move(b1); // move assign to a moved-from object
100+
ASSERT_EQ(b2, b3);
101+
ASSERT_EQ(it, b2.begin());
102+
103+
b1 = b2; // assign to moved-from object
104+
ASSERT_EQ(b1, b2);
105+
ASSERT_NE(b1.begin(), b2.begin());
106+
}
107+
108+
TEST(Blob, OtherCtorVariants)
55109
{
56110
std::vector<std::byte> bv = { std::byte { 1 }, std::byte { 2 }, std::byte { 3 } };
57111
Blob b1(bv.begin(), bv.end());
@@ -60,17 +114,16 @@ TEST(Blob, Ctors)
60114
std::ranges::reverse(b1);
61115
ASSERT_EQ(b1, b2);
62116

63-
auto it = b2.begin();
64-
auto b3 = std::move(b2);
65-
ASSERT_EQ(it, b3.begin());
66-
ASSERT_TRUE(b2.empty());
67-
ASSERT_TRUE(b2.capacity() == 0);
68-
69-
b2 = b1;
70-
ASSERT_EQ(b2.size(), 3);
117+
auto b3 = b2;
118+
b2.push_back(std::byte { 4 });
119+
ASSERT_NE(b2, b3);
120+
}
71121

72-
b2 = std::move(b3);
73-
b3 = b1;
122+
TEST(Blob, clearResultsInZeroSize)
123+
{
124+
Blob b = "DasIsnTest";
125+
b.clear();
126+
ASSERT_EQ(b.size(), 0);
74127
}
75128

76129
TEST(Blob, capacityGrowsWhenNeeded)
@@ -96,10 +149,14 @@ TEST(Blob, clearDoesntChangeCapacity)
96149
ASSERT_EQ(oldCapacity, b.capacity());
97150
}
98151

99-
TEST(Blob, reserveDoesntChangeContents)
152+
TEST(Blob, reserveDoesntChangeContentsButChangesBuffer)
100153
{
101154
Blob b = "test";
102155
Blob b2 = b;
156+
auto it = b.begin();
103157
b.reserve(5000);
104158
ASSERT_EQ(b, b2);
159+
ASSERT_NE(it, b.begin());
105160
}
161+
162+

0 commit comments

Comments
 (0)