Skip to content

Commit

Permalink
add fixed_string
Browse files Browse the repository at this point in the history
  • Loading branch information
actboy168 committed Jul 11, 2024
1 parent ed4ca21 commit 04f1b9c
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 20 deletions.
22 changes: 2 additions & 20 deletions bee/reflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,9 @@

#include <string_view>
#include <utility>
#include <bee/utility/fixed_string.h>

namespace bee::reflection {
template <unsigned short N>
struct cstring {
constexpr explicit cstring(std::string_view str) noexcept
: cstring { str, std::make_integer_sequence<unsigned short, N> {} } {}
constexpr const char* data() const noexcept { return chars_; }
constexpr unsigned short size() const noexcept { return N; }
constexpr operator std::string_view() const noexcept { return { data(), size() }; }
template <unsigned short... I>
constexpr cstring(std::string_view str, std::integer_sequence<unsigned short, I...>) noexcept
: chars_ { str[I]..., '\0' } {}
char chars_[static_cast<size_t>(N) + 1];
};
template <>
struct cstring<0> {
constexpr explicit cstring(std::string_view) noexcept {}
constexpr const char* data() const noexcept { return nullptr; }
constexpr unsigned short size() const noexcept { return 0; }
constexpr operator std::string_view() const noexcept { return {}; }
};
template <typename T>
constexpr auto name_raw() noexcept {
#if defined(__clang__) || defined(__GNUC__)
Expand All @@ -45,7 +27,7 @@ namespace bee::reflection {
template <typename T>
constexpr auto name() noexcept {
constexpr auto name = name_raw<T>();
return cstring<name.size()> { name };
return fixed_string<name.size()> { name };
}
template <typename T>
constexpr auto name_v = name<T>();
Expand Down
6 changes: 6 additions & 0 deletions bee/utility/assume.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@
# define BEE_ASSUME(cond) ((cond) ? (void)(0) : __builtin_unreachable())
# endif
#endif

#if defined(NDEBUG)
# define BEE_EXPECTS(cond) static_cast<void>(0)
#else
# define BEE_EXPECTS(cond) ((cond) ? static_cast<void>(0) : std::terminate())
#endif
148 changes: 148 additions & 0 deletions bee/utility/fixed_string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#pragma once

#include <cstddef>
#include <cstdlib>
#include <string_view>
#include <bee/utility/assume.h>

namespace bee {

template <typename CharT, std::size_t N, typename Traits = std::char_traits<CharT>>
class basic_fixed_string {
public:
CharT data_[N + 1] = {};

using traits_type = Traits;
using value_type = CharT;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using const_iterator = const value_type*;
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;

constexpr basic_fixed_string(const CharT (&txt)[N + 1]) noexcept {
BEE_EXPECTS(txt[N] == CharT {});
for (std::size_t i = 0; i < N; ++i) data_[i] = txt[i];
}
constexpr basic_fixed_string(const std::basic_string_view<CharT, Traits> txt) noexcept {
BEE_EXPECTS(txt.size() == N);
for (std::size_t i = 0; i < N; ++i) data_[i] = txt[i];
}

constexpr basic_fixed_string(const basic_fixed_string&) noexcept = default;
constexpr basic_fixed_string& operator=(const basic_fixed_string&) noexcept = default;

[[nodiscard]] constexpr const_iterator begin() const noexcept { return data(); }
[[nodiscard]] constexpr const_iterator end() const noexcept { return data() + size(); }
[[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
[[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
[[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
[[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
[[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
[[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }

static constexpr std::integral_constant<size_type, N> size {};
static constexpr std::integral_constant<size_type, N> length {};
static constexpr std::integral_constant<size_type, N> max_size {};
static constexpr std::bool_constant<N == 0> empty {};

[[nodiscard]] constexpr const_reference operator[](size_type pos) const {
BEE_EXPECTS(pos < N);
return data()[pos];
}

[[nodiscard]] constexpr const_reference front() const {
BEE_EXPECTS(!empty());
return (*this)[0];
}
[[nodiscard]] constexpr const_reference back() const {
BEE_EXPECTS(!empty());
return (*this)[N - 1];
}

constexpr void swap(basic_fixed_string& s) noexcept { swap_ranges(begin(), end(), s.begin()); }

[[nodiscard]] constexpr const_pointer c_str() const noexcept { return data(); }
[[nodiscard]] constexpr const_pointer data() const noexcept { return static_cast<const_pointer>(data_); }
[[nodiscard]] constexpr std::basic_string_view<CharT, Traits> view() const noexcept {
return std::basic_string_view<CharT, Traits>(cbegin(), cend());
}
[[nodiscard]] constexpr operator std::basic_string_view<CharT, Traits>() const noexcept {
return view();
}

template <std::size_t N2>
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + N2, Traits> operator+(
const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2, Traits>& rhs
) noexcept {
CharT txt[N + N2];
CharT* it = txt;
for (CharT c : lhs) *it++ = c;
for (CharT c : rhs) *it++ = c;
return basic_fixed_string<CharT, N + N2, Traits>(txt, it);
}

[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + 1, Traits> operator+(const basic_fixed_string& lhs, CharT rhs) noexcept {
CharT txt[N + 1];
CharT* it = txt;
for (CharT c : lhs) *it++ = c;
*it++ = rhs;
return basic_fixed_string<CharT, N + 1, Traits>(txt, it);
}

[[nodiscard]] constexpr friend basic_fixed_string<CharT, 1 + N, Traits> operator+(
const CharT lhs, const basic_fixed_string& rhs
) noexcept {
CharT txt[1 + N];
CharT* it = txt;
*it++ = lhs;
for (CharT c : rhs) *it++ = c;
return basic_fixed_string<CharT, 1 + N, Traits>(txt, it);
}

template <std::size_t N2>
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + N2 - 1, Traits> operator+(
const basic_fixed_string& lhs, const CharT (&rhs)[N2]
) noexcept {
BEE_EXPECTS(rhs[N2 - 1] == CharT {});
CharT txt[N + N2];
CharT* it = txt;
for (CharT c : lhs) *it++ = c;
for (CharT c : rhs) *it++ = c;
return txt;
}

template <std::size_t N1>
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N1 + N - 1, Traits> operator+(
const CharT (&lhs)[N1], const basic_fixed_string& rhs
) noexcept {
BEE_EXPECTS(lhs[N1 - 1] == CharT {});
CharT txt[N1 + N];
CharT* it = txt;
for (size_t i = 0; i != N1 - 1; ++i) *it++ = lhs[i];
for (CharT c : rhs) *it++ = c;
*it++ = CharT();
return txt;
}

template <size_t N2>
[[nodiscard]] friend constexpr bool operator==(const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2, Traits>& rhs) {
return lhs.view() == rhs.view();
}
template <size_t N2>
[[nodiscard]] friend constexpr bool operator==(const basic_fixed_string& lhs, const CharT (&rhs)[N2]) {
BEE_EXPECTS(rhs[N2 - 1] == CharT {});
return lhs.view() == std::basic_string_view<CharT, Traits>(std::cbegin(rhs), std::cend(rhs) - 1);
}
};

template <std::size_t N>
using fixed_string = basic_fixed_string<char, N>;
template <std::size_t N>
using fixed_wstring = basic_fixed_string<wchar_t, N>;
}

0 comments on commit 04f1b9c

Please sign in to comment.