namespace util {
+namespace {
+
+void
+assign_from_data(Bytes* bytes, const void* data, size_t size) noexcept
+{
+ bytes->resize(size);
+ if (size > 0) {
+ std::memcpy(bytes->data(), data, size);
+ }
+}
+
+} // namespace
+
Bytes::Bytes(const Bytes& other) noexcept
: m_data(std::make_unique<uint8_t[]>(other.m_size)),
m_size(other.m_size),
if (&other == this) {
return *this;
}
- m_data = std::make_unique<uint8_t[]>(other.m_size);
- m_size = other.m_size;
- m_capacity = other.m_size;
- if (m_size > 0) {
- std::memcpy(m_data.get(), other.m_data.get(), m_size);
- }
+ assign_from_data(this, other.m_data.get(), other.m_size);
return *this;
}
return *this;
}
+Bytes&
+Bytes::operator=(nonstd::span<const uint8_t> data) noexcept
+{
+ assign_from_data(this, data.data(), data.size());
+ return *this;
+}
+
+Bytes&
+Bytes::operator=(std::string_view data) noexcept
+{
+ assign_from_data(this, data.data(), data.size());
+ return *this;
+}
+
void
Bytes::reserve(size_t size) noexcept
{
#include <cstring>
#include <initializer_list>
#include <memory>
+#include <string_view>
namespace util {
explicit Bytes(size_t size) noexcept;
Bytes(const void* data, size_t size) noexcept;
+ Bytes(const void* first, const void* last) noexcept;
Bytes(nonstd::span<const uint8_t> data) noexcept;
+ Bytes(std::string_view data) noexcept;
Bytes(const Bytes& other) noexcept;
Bytes(Bytes&& other) noexcept;
Bytes& operator=(const Bytes& other) noexcept;
Bytes& operator=(Bytes&& other) noexcept;
+ Bytes& operator=(nonstd::span<const uint8_t> data) noexcept;
+ Bytes& operator=(std::string_view data) noexcept;
uint8_t operator[](size_t pos) const noexcept;
uint8_t& operator[](size_t pos) noexcept;
std::memcpy(m_data.get(), data, size);
}
+inline Bytes::Bytes(const void* first, const void* last) noexcept
+ : Bytes(first,
+ reinterpret_cast<const uint8_t*>(last)
+ - reinterpret_cast<const uint8_t*>(first))
+{
+}
+
inline Bytes::Bytes(nonstd::span<const uint8_t> data) noexcept
: Bytes(data.data(), data.size())
{
}
+inline Bytes::Bytes(std::string_view data) noexcept
+ : Bytes(data.data(), data.size())
+{
+}
+
inline Bytes::Bytes(std::initializer_list<uint8_t> init) noexcept
- : Bytes({init.begin(), init.end()})
+ : Bytes(init.begin(), init.end())
{
}
CHECK(bytes2[2] == 'c');
}
+ SUBCASE("Construction from string_view")
+ {
+ std::string s("abc");
+ Bytes bytes2(s);
+
+ CHECK(bytes2.data() != nullptr);
+ REQUIRE(bytes2.size() == 3);
+ CHECK(bytes2[0] == 'a');
+ CHECK(bytes2[1] == 'b');
+ CHECK(bytes2[2] == 'c');
+ }
+
SUBCASE("Copy construction")
{
const Bytes bytes2(bytes1);
CHECK(bytes2[2] == 'c');
}
+ SUBCASE("Assignment from span")
+ {
+ std::vector<uint8_t> vector{'a', 'b', 'c'};
+ Bytes bytes2;
+ bytes2 = vector;
+
+ CHECK(bytes2.data() != nullptr);
+ REQUIRE(bytes2.size() == 3);
+ CHECK(bytes2[0] == 'a');
+ CHECK(bytes2[1] == 'b');
+ CHECK(bytes2[2] == 'c');
+ }
+
+ SUBCASE("Assignment from string_view")
+ {
+ std::string s = "abc";
+ Bytes bytes2;
+ bytes2 = s;
+
+ CHECK(bytes2.data() != nullptr);
+ REQUIRE(bytes2.size() == 3);
+ CHECK(bytes2[0] == 'a');
+ CHECK(bytes2[1] == 'b');
+ CHECK(bytes2[2] == 'c');
+ }
+
SUBCASE("Assignment from initializer list")
{
Bytes bytes2;