Util: Add socket helper classes

This commit is contained in:
Stenzek
2024-05-25 23:49:14 +10:00
parent 9eb18449a7
commit 4e905a63ec
14 changed files with 1502 additions and 2 deletions

View File

@ -2,6 +2,8 @@ add_library(common
align.h
assert.cpp
assert.h
binary_span_reader_writer.cpp
binary_span_reader_writer.h
bitfield.h
bitutils.h
build_timestamp.h

View File

@ -0,0 +1,110 @@
// SPDX-FileCopyrightText: 2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "binary_span_reader_writer.h"
#include "small_string.h"
BinarySpanReader::BinarySpanReader() = default;
BinarySpanReader::BinarySpanReader(std::span<const u8> buf) : m_buf(buf)
{
}
bool BinarySpanReader::PeekCString(std::string_view* dst)
{
size_t pos = m_pos;
size_t size = 0;
while (pos < m_buf.size())
{
if (m_buf[pos] == 0)
break;
pos++;
size++;
}
if (pos == m_buf.size())
return false;
*dst = std::string_view(reinterpret_cast<const char*>(&m_buf[m_pos]), size);
return true;
}
bool BinarySpanReader::ReadCString(std::string* dst)
{
std::string_view sv;
if (!PeekCString(&sv))
return false;
dst->assign(sv);
m_pos += sv.size() + 1;
return true;
}
bool BinarySpanReader::ReadCString(std::string_view* dst)
{
if (!PeekCString(dst))
return false;
m_pos += dst->size() + 1;
return true;
}
bool BinarySpanReader::ReadCString(SmallStringBase* dst)
{
std::string_view sv;
if (!PeekCString(&sv))
return false;
dst->assign(sv);
m_pos += sv.size() + 1;
return true;
}
std::string_view BinarySpanReader::ReadCString()
{
std::string_view ret;
if (PeekCString(&ret))
m_pos += ret.size() + 1;
return ret;
}
bool BinarySpanReader::PeekCString(std::string* dst)
{
std::string_view sv;
if (!PeekCString(&sv))
return false;
dst->assign(sv);
return true;
}
bool BinarySpanReader::PeekCString(SmallStringBase* dst)
{
std::string_view sv;
if (!PeekCString(&sv))
return false;
dst->assign(sv);
m_pos += sv.size() + 1;
return true;
}
BinarySpanWriter::BinarySpanWriter() = default;
BinarySpanWriter::BinarySpanWriter(std::span<u8> buf) : m_buf(buf)
{
}
bool BinarySpanWriter::WriteCString(std::string_view val)
{
if ((m_pos + val.size() + 1) > m_buf.size()) [[unlikely]]
return false;
if (!val.empty())
std::memcpy(&m_buf[m_pos], val.data(), val.size());
m_buf[m_pos + val.size()] = 0;
m_pos += val.size() + 1;
return true;
}

View File

@ -0,0 +1,135 @@
// SPDX-FileCopyrightText: 2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "types.h"
#include <optional>
#include <span>
#include <string>
#include <string_view>
class SmallStringBase;
class BinarySpanReader
{
public:
BinarySpanReader();
BinarySpanReader(std::span<const u8> buf);
ALWAYS_INLINE const std::span<const u8>& GetSpan() const { return m_buf; }
ALWAYS_INLINE bool IsValid() const { return !m_buf.empty(); }
ALWAYS_INLINE bool CheckRemaining(size_t size) { return ((m_pos + size) <= m_buf.size()); }
ALWAYS_INLINE size_t GetBufferRemaining() const { return (m_buf.size() - m_pos); }
ALWAYS_INLINE size_t GetBufferConsumed() const { return m_pos; }
// clang-format off
template<typename T> ALWAYS_INLINE bool ReadT(T* dst) { return Read(dst, sizeof(T)); }
ALWAYS_INLINE bool ReadU8(u8* dst) { return ReadT(dst); }
ALWAYS_INLINE bool ReadU16(u16* dst) { return ReadT(dst); }
ALWAYS_INLINE bool ReadU32(u32* dst) { return ReadT(dst); }
ALWAYS_INLINE bool ReadU64(u64* dst) { return ReadT(dst); }
ALWAYS_INLINE bool ReadFloat(float* dst) { return ReadT(dst); }
bool ReadCString(std::string* dst);
bool ReadCString(std::string_view* dst);
bool ReadCString(SmallStringBase* dst);
template<typename T> ALWAYS_INLINE T ReadT() { T ret; if (!Read(&ret, sizeof(ret))) [[unlikely]] { ret = {}; } return ret; }
ALWAYS_INLINE u8 ReadU8() { return ReadT<u8>(); }
ALWAYS_INLINE u16 ReadU16() { return ReadT<u16>(); }
ALWAYS_INLINE u32 ReadU32() { return ReadT<u32>(); }
ALWAYS_INLINE u64 ReadU64() { return ReadT<u64>(); }
ALWAYS_INLINE float ReadFloat() { return ReadT<float>(); }
std::string_view ReadCString();
template<typename T> ALWAYS_INLINE bool PeekT(T* dst) { return Peek(dst, sizeof(T)); }
ALWAYS_INLINE bool PeekU8(u8* dst) { return PeekT(dst); }
ALWAYS_INLINE bool PeekU16(u16* dst) { return PeekT(dst); }
ALWAYS_INLINE bool PeekU32(u32* dst) { return PeekT(dst); }
ALWAYS_INLINE bool PeekU64(u64* dst) { return PeekT(dst); }
ALWAYS_INLINE bool PeekFloat(float* dst) { return PeekT(dst); }
bool PeekCString(std::string* dst);
bool PeekCString(std::string_view* dst);
bool PeekCString(SmallStringBase* dst);
ALWAYS_INLINE BinarySpanReader& operator>>(u8& val) { val = ReadT<u8>(); return *this; }
ALWAYS_INLINE BinarySpanReader& operator>>(u16& val) { val = ReadT<u16>(); return *this; }
ALWAYS_INLINE BinarySpanReader& operator>>(u32& val) { val = ReadT<u32>(); return *this; }
ALWAYS_INLINE BinarySpanReader& operator>>(u64& val) { val = ReadT<u64>(); return *this; }
ALWAYS_INLINE BinarySpanReader& operator>>(float& val) { val = ReadT<float>(); return *this; }
ALWAYS_INLINE BinarySpanReader& operator>>(std::string_view val) { val = ReadCString(); return *this; }
// clang-format on
private:
ALWAYS_INLINE bool Read(void* buf, size_t size)
{
if ((m_pos + size) < m_buf.size()) [[likely]]
{
std::memcpy(buf, &m_buf[m_pos], size);
m_pos += size;
return true;
}
return false;
}
ALWAYS_INLINE bool Peek(void* buf, size_t size)
{
if ((m_pos + size) < m_buf.size()) [[likely]]
{
std::memcpy(buf, &m_buf[m_pos], size);
return true;
}
return false;
}
private:
std::span<const u8> m_buf;
size_t m_pos = 0;
};
class BinarySpanWriter
{
public:
BinarySpanWriter();
BinarySpanWriter(std::span<u8> buf);
ALWAYS_INLINE const std::span<u8>& GetSpan() const { return m_buf; }
ALWAYS_INLINE bool IsValid() const { return !m_buf.empty(); }
ALWAYS_INLINE size_t GetBufferRemaining() const { return (m_buf.size() - m_pos); }
ALWAYS_INLINE size_t GetBufferWritten() const { return m_pos; }
// clang-format off
template<typename T> ALWAYS_INLINE bool WriteT(T dst) { return Write(&dst, sizeof(T)); }
ALWAYS_INLINE bool WriteU8(u8 val) { return WriteT(val); }
ALWAYS_INLINE bool WriteU16(u16 val) { return WriteT(val); }
ALWAYS_INLINE bool WriteU32(u32 val) { return WriteT(val); }
ALWAYS_INLINE bool WriteU64(u64 val) { return WriteT(val); }
ALWAYS_INLINE bool WriteFloat(float val) { return WriteT(val); }
bool WriteCString(std::string_view val);
ALWAYS_INLINE BinarySpanWriter& operator<<(u8 val) { WriteU8(val); return *this; }
ALWAYS_INLINE BinarySpanWriter& operator<<(u16 val) { WriteU16(val); return *this; }
ALWAYS_INLINE BinarySpanWriter& operator<<(u32 val) { WriteU32(val); return *this; }
ALWAYS_INLINE BinarySpanWriter& operator<<(u64 val) { WriteU64(val); return *this; }
ALWAYS_INLINE BinarySpanWriter& operator<<(float val) { WriteFloat(val); return *this; }
ALWAYS_INLINE BinarySpanWriter& operator<<(std::string_view val) { WriteCString(val); return *this; }
// clang-format on
private:
ALWAYS_INLINE bool Write(void* buf, size_t size)
{
if ((m_pos + size) < m_buf.size()) [[likely]]
{
std::memcpy(&m_buf[m_pos], buf, size);
m_pos += size;
return true;
}
return false;
}
private:
std::span<u8> m_buf;
size_t m_pos = 0;
};

View File

@ -34,6 +34,7 @@
<ClInclude Include="sha1_digest.h" />
<ClInclude Include="small_string.h" />
<ClInclude Include="heterogeneous_containers.h" />
<ClInclude Include="binary_span_reader_writer.h" />
<ClInclude Include="string_util.h" />
<ClInclude Include="thirdparty\SmallVector.h" />
<ClInclude Include="thirdparty\StackWalker.h" />
@ -60,6 +61,7 @@
<ClCompile Include="progress_callback.cpp" />
<ClCompile Include="sha1_digest.cpp" />
<ClCompile Include="small_string.cpp" />
<ClCompile Include="binary_span_reader_writer.cpp" />
<ClCompile Include="string_util.cpp" />
<ClCompile Include="thirdparty\SmallVector.cpp" />
<ClCompile Include="thirdparty\StackWalker.cpp" />

View File

@ -45,6 +45,7 @@
<Filter>thirdparty</Filter>
</ClInclude>
<ClInclude Include="dynamic_library.h" />
<ClInclude Include="binary_span_reader_writer.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="small_string.cpp" />
@ -72,6 +73,7 @@
<Filter>thirdparty</Filter>
</ClCompile>
<ClCompile Include="dynamic_library.cpp" />
<ClCompile Include="binary_span_reader_writer.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include="bitfield.natvis" />