utempl/include/utempl/constexpr_string.hpp

96 lines
3.2 KiB
C++

#pragma once
#include <fmt/format.h>
#include <algorithm>
namespace utempl {
template <std::size_t>
struct ConstexprString;
} // namespace utempl
template <std::size_t Size>
struct fmt::formatter<utempl::ConstexprString<Size>> : public fmt::formatter<std::string_view> {
constexpr auto parse(format_parse_context& ctx) const {
return ctx.begin();
};
inline constexpr auto format(const utempl::ConstexprString<Size>& str, auto& ctx) const {
return fmt::formatter<std::string_view>::format({str.begin()}, ctx);
};
};
namespace utempl {
template <std::size_t Size>
struct ConstexprString {
std::array<char, Size> data;
inline constexpr auto begin() -> char* {
return this->data.begin();
};
inline constexpr auto begin() const -> const char* {
return this->data.begin();
};
inline constexpr auto end() -> char* {
return this->data.end();
};
inline constexpr auto end() const -> const char* {
return this->data.end();
};
static constexpr auto kSize = Size == 0 ? 0 : Size - 1;
inline constexpr ConstexprString() = default;
inline constexpr ConstexprString(const char (&data)[Size]) : data{} {
std::ranges::copy_n(data, Size, this->data.begin());
};
inline constexpr ConstexprString(std::string data) : data{} {
std::ranges::copy_n(data.begin(), Size, this->data.begin());
};
inline constexpr ConstexprString(std::array<char, Size> data) : data(std::move(data)) {};
inline constexpr auto size() const {
return Size == 0 ? 0 : Size - 1;
};
inline constexpr operator std::string_view() const & {
return {this->begin()};
};
inline constexpr bool operator==(std::string_view other) const {
return static_cast<std::string_view>(*this) == other;
};
inline constexpr bool operator==(const ConstexprString<Size>& other) const {
return static_cast<std::string_view>(*this) == static_cast<std::string_view>(other);
};
template <std::size_t SSize>
inline constexpr bool operator==(const ConstexprString<SSize>& other) const {
return false;
};
inline constexpr bool operator==(const std::string& other) const {
return static_cast<std::string_view>(*this) == other;
};
template <std::size_t SSize>
inline constexpr auto operator+(const ConstexprString<SSize>& other) -> ConstexprString<Size + SSize - 1> {
ConstexprString<Size + SSize - 1> response;
std::ranges::copy_n(this->begin(), Size - 1, response.begin());
std::ranges::copy_n(other.begin(), SSize, response.begin() + Size - 1);
return response;
};
inline constexpr ConstexprString(const ConstexprString&) = default;
inline constexpr ConstexprString(ConstexprString&&) = default;
};
template <std::size_t N>
inline constexpr auto operator<<(std::ostream& stream, const ConstexprString<N>& str) -> std::ostream& {
stream << static_cast<std::string_view>(str);
return stream;
};
template <std::size_t Count>
inline constexpr auto CreateStringWith(char c) {
ConstexprString<Count + 1> str = {};
for(std::size_t i = 0; i < Count; i++) {
str.data[i] = c;
};
str.data[Count] = '\0';
return str;
};
template <std::size_t Size>
ConstexprString(const char (&data)[Size]) -> ConstexprString<Size>;
} // namespace utempl