#pragma once #include #include #include #include #include namespace rublon { template < typename T, std::size_t N, std::size_t... Idx > constexpr std::array< T, N > toStdArray(T (&arr)[N], std::index_sequence< Idx... >) { return {arr[Idx]...}; } template < std::size_t NewSize, typename T, std::size_t OldSize, std::size_t... Indexes > constexpr std::array< T, NewSize > resize(const std::array< T, OldSize > & arr, std::index_sequence< Indexes... >) { return {arr[Indexes]...}; } template < std::size_t NewSize, typename T, std::size_t OldSize > constexpr std::array< T, NewSize > resize(const std::array< T, OldSize > & arr) { constexpr std::size_t minSize = std::min(OldSize, NewSize); return resize(arr, std::make_index_sequence< minSize >()); } namespace details { class StaticStringBase {}; } // namespace details // statically allocates a string buffer of (N+1) chars template < size_t N > class StaticString : public details::StaticStringBase { public: constexpr StaticString() = default; constexpr StaticString(const char (&chars)[N]) : m_str(toStdArray(chars)), _size{N} {} constexpr StaticString(std::array< const char, N > chars) : m_str(std::move(chars)), _size{N} {} constexpr StaticString(const char * str) { _size = std::min(strlen(str), N); std::memcpy(m_str.data(), str, _size); } void operator=(const char * str) { _size = std::min(strlen(str), N); std::memcpy(m_str.data(), str, _size); } void operator=(std::string_view str) { _size = std::min(str.size(), N); std::memcpy(m_str.data(), str.data(), _size); } const char * c_str() const noexcept { return m_str.data(); } const char * data() const noexcept { return m_str.data(); } char * data() noexcept { return m_str.data(); } constexpr char & operator[](size_t pos) { return m_str[pos]; } constexpr const char & operator[](size_t pos) const { return m_str[pos]; } std::size_t size() const { return _size; } constexpr std::size_t capacity() const noexcept { return N - 1; } // StaticString< N > & operator+=(const char * rhs) { // auto remaining = capacity() - _size; // auto rhs_len = std::strlen(rhs); // auto copy_len = std::min(rhs_len, remaining); // std::strncpy(data() + _size, rhs, copy_len); // _size += copy_len; // data()[_size] = '\0'; // null // return *this; // } template < std::size_t M > friend class StaticString; operator std::string_view() const { return {m_str.data(), size()}; } private: std::array< char, N + 1 > m_str{}; std::size_t _size; }; template < size_t N > bool operator==(const StaticString< N > & lhs, const char * rhs) { return strcmp(lhs.c_str(), rhs) == 0; } } // namespace rublon