125 lines
3.9 KiB
C++
125 lines
3.9 KiB
C++
//-----------------------------------------------------------------------------
|
|
// ___ __ _ _
|
|
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Author: Kurt Sassenrath
|
|
// Module: Utility
|
|
//
|
|
// Compile-time string class, which can be used as template parameters and
|
|
// enable compile-time hashing/lookup of literals and so forth.
|
|
//
|
|
// Copyright (c) 2023 Kurt Sassenrath.
|
|
//
|
|
// License TBD.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef ct_string_4fab12ca46f0d931
|
|
#define ct_string_4fab12ca46f0d931
|
|
|
|
#include <array>
|
|
#include <string_view>
|
|
|
|
namespace parselink {
|
|
namespace ct {
|
|
|
|
template <std::size_t N>
|
|
struct string {
|
|
using char_type = char; // Maybe allow templatization in the future?
|
|
using storage_type = std::array<char, N + 1>;
|
|
storage_type data_ = {};
|
|
|
|
static constexpr auto npos = std::string_view::npos;
|
|
|
|
constexpr string() noexcept = default;
|
|
|
|
constexpr string(storage_type const& str) noexcept {
|
|
std::copy(std::begin(str), std::end(str), std::begin(data_));
|
|
}
|
|
|
|
constexpr string(char const (&str)[N + 1]) noexcept {
|
|
std::copy(std::begin(str), std::end(str), std::begin(data_));
|
|
}
|
|
|
|
constexpr string(string const& other) noexcept {
|
|
std::copy(std::begin(other), std::end(other), std::begin(data_));
|
|
}
|
|
|
|
constexpr string& operator=(string const& other) noexcept {
|
|
std::copy(std::begin(other), std::end(other), std::begin(data_));
|
|
return *this;
|
|
}
|
|
|
|
constexpr operator std::string_view() const noexcept {
|
|
return std::string_view{data_.data(), N};
|
|
}
|
|
|
|
// We save ourselves some headache by forwarding std::array's methods here.
|
|
constexpr auto data() noexcept { return data_.data(); }
|
|
|
|
constexpr auto data() const noexcept { return data_.data(); }
|
|
|
|
constexpr auto size() const noexcept { return N; }
|
|
|
|
constexpr auto begin() noexcept { return data_.begin(); }
|
|
|
|
constexpr auto begin() const noexcept { return data_.begin(); }
|
|
|
|
constexpr auto end() noexcept { return data_.end() - 1; }
|
|
|
|
constexpr auto end() const noexcept { return data_.end() - 1; }
|
|
|
|
constexpr auto cbegin() const noexcept { return data_.cbegin(); }
|
|
|
|
constexpr auto cend() const noexcept { return data_.cend() - 1; }
|
|
|
|
constexpr auto find(char_type c) noexcept {
|
|
return std::string_view{*this}.find(c);
|
|
}
|
|
|
|
constexpr auto find(char_type c) const noexcept {
|
|
return std::string_view{*this}.find(c);
|
|
}
|
|
};
|
|
|
|
template <size_t N>
|
|
string(char const (&)[N]) -> string<N - 1>;
|
|
|
|
template <std::size_t N1, std::size_t N2>
|
|
constexpr bool operator==(string<N1> const& a, string<N2> const& b) noexcept {
|
|
if constexpr (N1 != N2) return false;
|
|
return std::string_view{a} == std::string_view{b};
|
|
}
|
|
|
|
template <std::size_t N>
|
|
constexpr bool operator==(string<N> const& a, std::string_view b) noexcept {
|
|
return std::string_view{a} == b;
|
|
}
|
|
|
|
template <std::size_t N>
|
|
constexpr bool operator==(std::string_view a, string<N> const& b) noexcept {
|
|
return b == a;
|
|
}
|
|
|
|
template <std::size_t N1, std::size_t N2>
|
|
consteval string<N1 + N2> operator+(
|
|
string<N1> const& a, string<N2> const& b) noexcept {
|
|
using char_type = typename std::decay_t<decltype(a)>::char_type;
|
|
char_type buff[N1 + N2 + 1]{};
|
|
std::copy(std::begin(a), std::end(a), std::begin(buff));
|
|
std::copy(
|
|
std::begin(b), std::end(b), std::next(std::begin(buff), a.size()));
|
|
return string<N1 + N2>(buff);
|
|
}
|
|
|
|
// Sanity test for construction and concatenation at compile time.
|
|
static_assert(string("hello") + string(" world") == string("hello world"));
|
|
|
|
} // namespace ct
|
|
} // namespace parselink
|
|
|
|
#endif // ct_string_4fab12ca46f0d931
|