1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-20 22:33:02 +01:00

Use char_traits for length

This commit is contained in:
Matt
2020-12-31 15:57:36 +02:00
parent 2ef4dd23aa
commit c2fd7708ad
2 changed files with 23 additions and 10 deletions

View File

@@ -24,13 +24,14 @@
namespace OpenRCT2 namespace OpenRCT2
{ {
template<typename T, size_t (*LenFn)(const T*), size_t StackSize = 256> class FormatBufferBase template<typename T, size_t StackSize = 256, typename TTraits = std::char_traits<T>> class FormatBufferBase
{ {
T _storage[StackSize]; T _storage[StackSize];
T* _buffer; T* _buffer;
size_t _size; size_t _size;
// NOTE: Capacity is on purpose uint32_t to have a fixed position for the flag on each architecture. // NOTE: Capacity is on purpose uint32_t to have a fixed position for the flag on each architecture.
uint32_t _capacity; uint32_t _capacity;
TTraits _traits;
static constexpr uint32_t FlagLocalStorage = (1u << 31); static constexpr uint32_t FlagLocalStorage = (1u << 31);
@@ -39,7 +40,7 @@ namespace OpenRCT2
: _storage{} : _storage{}
, _buffer(_storage) , _buffer(_storage)
, _size{} , _size{}
, _capacity(FlagLocalStorage | static_cast<uint32_t>(std::size(_storage))) , _capacity(FlagLocalStorage | static_cast<uint32_t>(StackSize))
{ {
} }
@@ -76,12 +77,9 @@ namespace OpenRCT2
return _buffer; return _buffer;
} }
auto& operator<<(const T* v) template<size_t N> auto& operator<<(T const (&v)[N])
{ {
if (!v) append(v, N);
return *this;
append(v, LenFn(v));
return *this; return *this;
} }
@@ -91,13 +89,27 @@ namespace OpenRCT2
return *this; return *this;
} }
auto& operator<<(const T* v)
{
if (!v)
return *this;
append(v, _traits.length(v));
return *this;
}
auto& operator<<(const std::basic_string_view<T> v) auto& operator<<(const std::basic_string_view<T> v)
{ {
append(v.data(), v.size()); append(v.data(), v.size());
return *this; return *this;
} }
private: auto& operator<<(const std::basic_string<T>& v)
{
append(v.data(), v.size());
return *this;
}
void append(const T* buf, size_t len) void append(const T* buf, size_t len)
{ {
ensure_capacity(len); ensure_capacity(len);
@@ -108,6 +120,7 @@ namespace OpenRCT2
_buffer[_size] = T{}; _buffer[_size] = T{};
} }
private:
void ensure_capacity(size_t additionalSize) void ensure_capacity(size_t additionalSize)
{ {
const size_t curSize = size(); const size_t curSize = size();
@@ -130,7 +143,7 @@ namespace OpenRCT2
} }
}; };
using FormatBuffer = FormatBufferBase<char, strlen>; using FormatBuffer = FormatBufferBase<char>;
using FormatArg_t = std::variant<uint16_t, int32_t, const char*, std::string>; using FormatArg_t = std::variant<uint16_t, int32_t, const char*, std::string>;

View File

@@ -607,7 +607,7 @@ TEST_F(FormattingTests, format_number_comma2dp32_large_value_negative)
TEST_F(FormattingTests, buffer_storage_swap) TEST_F(FormattingTests, buffer_storage_swap)
{ {
FormatBufferBase<char, strlen, 16> ss; FormatBufferBase<char, 16> ss;
ss << "Hello World"; ss << "Hello World";
ASSERT_STREQ(ss.data(), "Hello World"); ASSERT_STREQ(ss.data(), "Hello World");
ss << ", Exceeding local storage"; ss << ", Exceeding local storage";