From c9fcce804cbe1b4178166544daf53c36c3cebadf Mon Sep 17 00:00:00 2001 From: Corentin Schreiber Date: Mon, 17 Oct 2022 08:42:20 +0100 Subject: [PATCH] Fix #2 --- include/snatch/snatch.hpp | 209 +++++++++++++++++--------------------- src/snatch.cpp | 20 ++-- 2 files changed, 103 insertions(+), 126 deletions(-) diff --git a/include/snatch/snatch.hpp b/include/snatch/snatch.hpp index f428062a..77b87341 100644 --- a/include/snatch/snatch.hpp +++ b/include/snatch/snatch.hpp @@ -118,14 +118,14 @@ struct test_case { [[noreturn]] void terminate_with(std::string_view msg) noexcept; template -class basic_small_vector { - ElemType* buffer_ptr = nullptr; - std::size_t buffer_size = 0; - std::size_t data_size = 0; +class small_vector_span { + ElemType* buffer_ptr = nullptr; + std::size_t buffer_size = 0; + std::size_t* data_size = nullptr; public: - constexpr explicit basic_small_vector(ElemType* b, std::size_t bl) noexcept : - buffer_ptr(b), buffer_size(bl) {} + constexpr explicit small_vector_span(ElemType* b, std::size_t bl, std::size_t* s) noexcept : + buffer_ptr(b), buffer_size(bl), data_size(s) {} constexpr std::size_t capacity() const noexcept { return buffer_size; @@ -134,66 +134,66 @@ class basic_small_vector { return capacity() - size(); } constexpr std::size_t size() const noexcept { - return data_size; + return *data_size; } constexpr bool empty() const noexcept { - return data_size == 0; + return *data_size == 0; } constexpr void clear() noexcept { - data_size = 0; + *data_size = 0; } constexpr void resize(std::size_t size) noexcept { if (size > buffer_size) { impl::terminate_with("small vector is full"); } - data_size = size; + *data_size = size; } constexpr void grow(std::size_t elem) noexcept { - if (data_size + elem > buffer_size) { + if (*data_size + elem > buffer_size) { impl::terminate_with("small vector is full"); } - data_size += elem; + *data_size += elem; } constexpr ElemType& push_back(const ElemType& t) noexcept(std::is_nothrow_copy_assignable_v) { - if (data_size == buffer_size) { + if (*data_size == buffer_size) { impl::terminate_with("small vector is full"); } - ++data_size; + ++*data_size; - ElemType& elem = buffer_ptr[data_size - 1]; + ElemType& elem = buffer_ptr[*data_size - 1]; elem = t; return elem; } constexpr ElemType& push_back(ElemType&& t) noexcept(std::is_nothrow_move_assignable_v) { - if (data_size == buffer_size) { + if (*data_size == buffer_size) { impl::terminate_with("small vector is full"); } - ++data_size; - ElemType& elem = buffer_ptr[data_size - 1]; + ++*data_size; + ElemType& elem = buffer_ptr[*data_size - 1]; elem = std::move(t); return elem; } constexpr ElemType& back() noexcept { - if (data_size == 0) { + if (*data_size == 0) { impl::terminate_with("back() called on empty vector"); } - return buffer_ptr[data_size - 1]; + return buffer_ptr[*data_size - 1]; } constexpr const ElemType& back() const noexcept { - if (data_size == 0) { + if (*data_size == 0) { impl::terminate_with("back() called on empty vector"); } - return buffer_ptr[data_size - 1]; + return buffer_ptr[*data_size - 1]; } constexpr ElemType* data() noexcept { return buffer_ptr; @@ -219,70 +219,67 @@ class basic_small_vector { constexpr const ElemType* cend() const noexcept { return begin() + size(); } + constexpr ElemType& operator[](std::size_t i) noexcept { + if (i >= size()) { + impl::terminate_with("operator[] called with incorrect index"); + } + return buffer_ptr[i]; + } + constexpr const ElemType& operator[](std::size_t i) const noexcept { + if (i >= size()) { + impl::terminate_with("operator[] called with incorrect index"); + } + return buffer_ptr[i]; + } }; template class small_vector { std::array data_buffer; - basic_small_vector vector = - basic_small_vector(data_buffer.data(), MaxLength); + std::size_t data_size = 0; public: - constexpr small_vector() noexcept = default; - constexpr small_vector(const small_vector& other) noexcept { - data_buffer = other.data_buffer; - vector.resize(other.vector.size()); - } - constexpr small_vector(small_vector&& other) noexcept { - data_buffer = other.data_buffer; - vector.resize(other.vector.size()); - } + constexpr small_vector() noexcept = default; + constexpr small_vector(const small_vector& other) noexcept = default; + constexpr small_vector(small_vector&& other) noexcept = default; constexpr small_vector(std::initializer_list list) noexcept( - noexcept(vector.push_back(std::declval()))) { + noexcept(span().push_back(std::declval()))) { for (const auto& e : list) { - push_back(e); + span().push_back(e); } } - constexpr small_vector& operator=(const small_vector& other) noexcept { - data_buffer = other.data_buffer; - vector.resize(other.vector.size()); - return *this; - } - constexpr small_vector& operator=(small_vector&& other) noexcept { - data_buffer = other.data_buffer; - vector.resize(other.vector.size()); - return *this; - } - constexpr std::size_t capacity() const noexcept { + constexpr small_vector& operator=(const small_vector& other) noexcept = default; + constexpr small_vector& operator=(small_vector&& other) noexcept = default; + constexpr std::size_t capacity() const noexcept { return MaxLength; } constexpr std::size_t available() const noexcept { - return vector.available(); + return MaxLength - data_size; } constexpr std::size_t size() const noexcept { - return vector.size(); + return data_size; } constexpr bool empty() const noexcept { - return vector.empty(); + return data_size == 0u; } constexpr void clear() noexcept { - vector.clear(); + span().clear(); } constexpr void resize(std::size_t size) noexcept { - vector.resize(size); + span().resize(size); } constexpr void grow(std::size_t elem) noexcept { - vector.grow(elem); + span().grow(elem); } template - constexpr ElemType& push_back(U&& t) noexcept(noexcept(vector.push_back(t))) { - return vector.push_back(t); + constexpr ElemType& push_back(U&& t) noexcept(noexcept(this->span().push_back(t))) { + return this->span().push_back(t); } constexpr ElemType& back() noexcept { - return vector.back(); + return span().back(); } constexpr const ElemType& back() const noexcept { - return vector.back(); + return const_cast(this)->span().back(); } constexpr ElemType* data() noexcept { return data_buffer.data(); @@ -308,59 +305,39 @@ class small_vector { constexpr const ElemType* cend() const noexcept { return begin() + size(); } - constexpr operator basic_small_vector &() noexcept { - return vector; + constexpr small_vector_span span() noexcept { + return small_vector_span(data_buffer.data(), MaxLength, &data_size); } - constexpr operator const basic_small_vector &() const noexcept { - return vector; + constexpr operator small_vector_span() noexcept { + return span(); } constexpr ElemType& operator[](std::size_t i) noexcept { - if (i >= size()) { - impl::terminate_with("operator[] called with incorrect index"); - } - return data()[i]; + return span()[i]; } constexpr const ElemType& operator[](std::size_t i) const noexcept { - if (i >= size()) { - impl::terminate_with("operator[] called with incorrect index"); - } - return data()[i]; + return const_cast(this)->span()[i]; } }; -using basic_small_string = basic_small_vector; +using small_string_span = small_vector_span; template class small_string { std::array data_buffer; - basic_small_string vector = basic_small_string(data_buffer.data(), MaxLength); + std::size_t data_size = 0u; public: - constexpr small_string() noexcept = default; - constexpr small_string(const small_string& other) noexcept { - vector.resize(other.vector.size()); - data_buffer = other.data_buffer; - } - constexpr small_string(small_string&& other) noexcept { - vector.resize(other.vector.size()); - data_buffer = other.data_buffer; - } + constexpr small_string() noexcept = default; + constexpr small_string(const small_string& other) noexcept = default; + constexpr small_string(small_string&& other) noexcept = default; constexpr small_string(std::string_view str) noexcept { - vector.resize(str.size()); + resize(str.size()); for (std::size_t i = 0; i < str.size(); ++i) { data_buffer[i] = str[i]; } } - constexpr small_string& operator=(const small_string& other) noexcept { - data_buffer = other.data_buffer; - vector.resize(other.vector.size()); - return *this; - } - constexpr small_string& operator=(small_string&& other) noexcept { - data_buffer = other.data_buffer; - vector.resize(other.vector.size()); - return *this; - } + constexpr small_string& operator=(const small_string& other) noexcept = default; + constexpr small_string& operator=(small_string&& other) noexcept = default; constexpr std::string_view str() const noexcept { return std::string_view(data(), length()); } @@ -368,34 +345,34 @@ class small_string { return MaxLength; } constexpr std::size_t available() const noexcept { - return vector.available(); + return MaxLength - data_size; } constexpr std::size_t size() const noexcept { - return vector.size(); + return data_size; } constexpr std::size_t length() const noexcept { - return vector.size(); + return data_size; } constexpr bool empty() const noexcept { - return vector.empty(); + return data_size == 0u; } constexpr void clear() noexcept { - vector.clear(); + span().clear(); } constexpr void resize(std::size_t length) noexcept { - vector.resize(length); + span().resize(length); } constexpr void grow(std::size_t chars) noexcept { - vector.grow(chars); + span().grow(chars); } constexpr char& push_back(char t) noexcept { - return vector.push_back(t); + return span().push_back(t); } constexpr char& back() noexcept { - return vector.back(); + return span().back(); } constexpr const char& back() const noexcept { - return vector.back(); + return span().back(); } constexpr char* data() noexcept { return data_buffer.data(); @@ -421,25 +398,25 @@ class small_string { constexpr const char* cend() const noexcept { return begin() + length(); } - constexpr operator basic_small_string&() noexcept { - return vector; + constexpr small_string_span span() noexcept { + return small_string_span(data_buffer.data(), MaxLength, &data_size); } - constexpr operator const basic_small_string&() const noexcept { - return vector; + constexpr operator small_string_span() noexcept { + return span(); } }; -[[nodiscard]] bool append(basic_small_string& ss, std::string_view value) noexcept; +[[nodiscard]] bool append(small_string_span ss, std::string_view value) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, const void* ptr) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, std::nullptr_t) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, std::size_t i) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, std::ptrdiff_t i) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, float f) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, double f) noexcept; -[[nodiscard]] bool append(basic_small_string& ss, bool value) noexcept; +[[nodiscard]] bool append(small_string_span ss, const void* ptr) noexcept; +[[nodiscard]] bool append(small_string_span ss, std::nullptr_t) noexcept; +[[nodiscard]] bool append(small_string_span ss, std::size_t i) noexcept; +[[nodiscard]] bool append(small_string_span ss, std::ptrdiff_t i) noexcept; +[[nodiscard]] bool append(small_string_span ss, float f) noexcept; +[[nodiscard]] bool append(small_string_span ss, double f) noexcept; +[[nodiscard]] bool append(small_string_span ss, bool value) noexcept; template -[[nodiscard]] bool append(basic_small_string& ss, T* ptr) noexcept { +[[nodiscard]] bool append(small_string_span ss, T* ptr) noexcept { if constexpr (std::is_same_v, char>) { return append(ss, std::string_view(ptr)); } else { @@ -447,19 +424,19 @@ template } } template -[[nodiscard]] bool append(basic_small_string& ss, const char str[N]) noexcept { +[[nodiscard]] bool append(small_string_span ss, const char str[N]) noexcept { return append(ss, std::string_view(str)); } template -[[nodiscard]] bool append(basic_small_string& ss, T&& t, U&& u, Args&&... args) noexcept { +[[nodiscard]] bool append(small_string_span ss, T&& t, U&& u, Args&&... args) noexcept { if (!append(ss, std::forward(t))) { return false; } return append(ss, std::forward(u), std::forward(args)...); } -void truncate_end(basic_small_string& ss) noexcept; +void truncate_end(small_string_span ss) noexcept; struct expression { small_string data; diff --git a/src/snatch.cpp b/src/snatch.cpp index 97d58bc9..b83d189a 100644 --- a/src/snatch.cpp +++ b/src/snatch.cpp @@ -136,7 +136,7 @@ constexpr const char* get_format_code() noexcept { } template -bool append_fmt(basic_small_string& ss, T value) noexcept { +bool append_fmt(small_string_span ss, T value) noexcept { const int return_code = std::snprintf(ss.end(), 0, get_format_code(), value); if (return_code < 0) { return false; @@ -164,7 +164,7 @@ namespace snatch::impl { std::terminate(); } -bool append(basic_small_string& ss, std::string_view str) noexcept { +bool append(small_string_span ss, std::string_view str) noexcept { const bool could_fit = str.size() <= ss.available(); const std::size_t copy_count = std::min(str.size(), ss.available()); @@ -175,35 +175,35 @@ bool append(basic_small_string& ss, std::string_view str) noexcept { return could_fit; } -bool append(basic_small_string& ss, const void* ptr) noexcept { +bool append(small_string_span ss, const void* ptr) noexcept { return append_fmt(ss, ptr); } -bool append(basic_small_string& ss, std::nullptr_t) noexcept { +bool append(small_string_span ss, std::nullptr_t) noexcept { return append(ss, "nullptr"); } -bool append(basic_small_string& ss, std::size_t i) noexcept { +bool append(small_string_span ss, std::size_t i) noexcept { return append_fmt(ss, i); } -bool append(basic_small_string& ss, std::ptrdiff_t i) noexcept { +bool append(small_string_span ss, std::ptrdiff_t i) noexcept { return append_fmt(ss, i); } -bool append(basic_small_string& ss, float f) noexcept { +bool append(small_string_span ss, float f) noexcept { return append_fmt(ss, f); } -bool append(basic_small_string& ss, double d) noexcept { +bool append(small_string_span ss, double d) noexcept { return append_fmt(ss, d); } -bool append(basic_small_string& ss, bool value) noexcept { +bool append(small_string_span ss, bool value) noexcept { return append(ss, value ? "true" : "false"); } -void truncate_end(basic_small_string& ss) noexcept { +void truncate_end(small_string_span ss) noexcept { std::size_t num_dots = 3; std::size_t final_length = std::min(ss.capacity(), ss.size() + num_dots); std::size_t offset = final_length >= num_dots ? final_length - num_dots : 0;