diff options
Diffstat (limited to 'src/openvic-dataloader/detail/StringLiteral.hpp')
-rw-r--r-- | src/openvic-dataloader/detail/StringLiteral.hpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/openvic-dataloader/detail/StringLiteral.hpp b/src/openvic-dataloader/detail/StringLiteral.hpp new file mode 100644 index 0000000..985b087 --- /dev/null +++ b/src/openvic-dataloader/detail/StringLiteral.hpp @@ -0,0 +1,232 @@ +#pragma once + +#include <algorithm> +#include <array> +#include <cstddef> +#include <string> +#include <string_view> +#include <type_traits> + +#include <lexy/_detail/config.hpp> +#include <lexy/_detail/integer_sequence.hpp> +#include <lexy/dsl/identifier.hpp> + +namespace ovdl::detail { + + template<std::size_t N, typename CharT> + struct string_literal; + + struct _string_literal { + protected: + static constexpr auto _to_string(const auto& input) { return string_literal(input); } + static constexpr auto _concat(const auto&... input) { return string_literal(_to_string(input)...); } + }; + + template<std::size_t N, typename CharT = char> + struct string_literal : _string_literal { + 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 size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using traits_type = std::char_traits<value_type>; + + static constexpr size_type npos = size_type(-1); + + static constexpr auto size = std::integral_constant<std::size_t, N - 1> {}; + static constexpr auto length = size; + + value_type _data[N]; + + constexpr string_literal() noexcept = default; + + constexpr string_literal(const value_type (&literal)[N]) noexcept { + for (auto i = 0u; i != N; i++) + _data[i] = literal[i]; + } + + constexpr string_literal(value_type c) noexcept : _data {} { + _data[0] = c; + } + + constexpr auto begin() noexcept { return std::begin(_data); } + constexpr auto end() noexcept { return std::end(_data); } + constexpr auto cbegin() const noexcept { return std::cbegin(_data); } + constexpr auto cend() const noexcept { return std::cend(_data); } + constexpr auto rbegin() noexcept { return std::rbegin(_data); } + constexpr auto rend() noexcept { return std::rend(_data); } + constexpr auto crbegin() const noexcept { return std::crbegin(_data); } + constexpr auto crend() const noexcept { return std::crend(_data); } + + constexpr auto front() const noexcept { return as_string_view().front(); } + constexpr auto back() const noexcept { return as_string_view().back(); } + constexpr auto at(size_type pos) const { return as_string_view().at(pos); } + + constexpr auto operator[](size_type pos) const noexcept { return as_string_view()[pos]; } + + constexpr bool empty() const { return as_string_view().empty(); } + + template<size_type N2> + constexpr bool operator==(const string_literal<N2, value_type>& other) const { + return as_string_view() == other.as_string_view(); + } + + constexpr bool starts_with(std::basic_string_view<value_type> sv) const noexcept { return as_string_view().starts_with(sv); } + constexpr bool starts_with(value_type ch) const noexcept { return as_string_view().starts_with(ch); } + constexpr bool starts_with(const value_type* s) const { return as_string_view().starts_with(s); } + + template<size_type N2> + constexpr bool starts_with(const string_literal<N2, value_type>& other) const { + return starts_with(other.as_string_view()); + } + + constexpr bool ends_with(std::basic_string_view<value_type> sv) const noexcept { return as_string_view().ends_with(sv); } + constexpr bool ends_with(value_type ch) const noexcept { return as_string_view().ends_with(ch); } + constexpr bool ends_with(const value_type* s) const { return as_string_view().ends_with(s); } + + template<size_type N2> + constexpr bool ends_with(const string_literal<N2, value_type>& other) const { + return ends_with(other.as_string_view()); + } + + constexpr auto clear() const noexcept { + return string_literal<0, value_type> {}; + } + + constexpr auto push_back(value_type c) const noexcept { + return *this + string_literal { c }; + } + + constexpr auto pop_back() const noexcept { + string_literal<N - 1, value_type> result {}; + for (auto i = 0u; i != N - 2; i++) + result._data[i] = _data[i]; + return result; + } + + template<size_type count> + constexpr auto append(value_type ch) const noexcept { + string_literal<N + count, value_type> result {}; + for (auto i = 0u; i != N; i++) + result._data[i] = _data[i]; + + for (auto i = N; i != N + count; i++) + result._data[i] = ch; + + return result; + } + + template<size_type N2> + constexpr auto append(string_literal<N2, value_type> str) const noexcept { + return *this + str; + } + + template<size_type N2> + constexpr auto append(const value_type (&literal)[N2]) const noexcept { + return *this + literal; + } + + template<size_type pos = 0, size_type count = npos> + constexpr auto substr() const noexcept { + static_assert(pos <= N, "pos must be less than or equal to N"); + constexpr size_type result_size = std::min(count - pos, N - pos); + + string_literal<result_size, value_type> result {}; + for (size_type i = 0u, i2 = pos; i != result_size; i++, i2++) + result._data[i] = _data[i2]; + return result; + } + + constexpr auto substr() const noexcept { + return substr<>(); + } + + constexpr std::string_view substr(size_type pos, size_type count = npos) const noexcept { + return as_string_view().substr(pos, count); + } + + constexpr size_type find(std::string_view str, size_type pos = 0) const noexcept { + return as_string_view().find(str, pos); + } + + template<size_type N2> + constexpr size_type find(const value_type (&literal)[N2], size_type pos = 0) const noexcept { + return as_string_view().find(literal, pos, N2 - 2); + } + + constexpr size_type rfind(std::string_view str, size_type pos = 0) const noexcept { + return as_string_view().rfind(str, pos); + } + + template<size_type N2> + constexpr size_type rfind(const value_type (&literal)[N2], size_type pos = 0) const noexcept { + return as_string_view().find(literal, pos, N2 - 2); + } + + constexpr int compare(std::string_view str) const noexcept { + return as_string_view().compare(str); + } + + template<size_type N2> + constexpr int compare(const value_type (&literal)[N2]) const noexcept { + return as_string_view().compare(0, N, literal, N2 - 2); + } + + constexpr operator std::basic_string_view<value_type>() const& { return as_string_view(); } + constexpr operator std::basic_string_view<value_type>() const&& = delete; + + constexpr std::basic_string_view<value_type> as_string_view() const& { return std::basic_string_view<value_type>(_data, size() - 1); } + constexpr std::basic_string_view<value_type> as_string_view() const&& = delete; + + constexpr operator const value_type*() const& { return c_str(); } + constexpr operator const value_type*() const&& = delete; + + constexpr const value_type* c_str() const& { return _data; } + constexpr const value_type* c_str() const&& = delete; + + constexpr const value_type* data() const& { return _data; } + constexpr const value_type* data() const&& = delete; + + template<size_type N2> + constexpr auto operator+(const string_literal<N2, value_type>& other) const noexcept { + string_literal<N + N2 - 1, value_type> result {}; + for (size_type i = 0u; i != N; i++) + result._data[i] = _data[i]; + + for (size_type i = N - 1, i2 = 0; i2 != N2; i++, i2++) + result._data[i] = other._data[i2]; + return result; + } + + template<size_type N2> + constexpr auto operator+(const value_type (&rhs)[N2]) const noexcept { + return *this + _to_string(rhs); + } + + template<size_type N2> + friend constexpr auto operator+(const value_type (&lhs)[N2], string_literal<N, value_type> rhs) noexcept { + return _to_string(lhs) + rhs; + } + }; + template<std::size_t N, typename CharT = char> + string_literal(const CharT (&)[N]) -> string_literal<N, CharT>; + + template<typename CharT = char> + string_literal(CharT) -> string_literal<1, CharT>; + + template<template<typename C, C... Cs> typename T, string_literal Str, std::size_t... Idx> + auto _to_type_string(lexy::_detail::index_sequence<Idx...>) { + return T<typename decltype(Str)::value_type, Str._data[Idx]...> {}; + } + template<template<typename C, C... Cs> typename T, string_literal Str> + using to_type_string = decltype(ovdl::detail::_to_type_string<T, Str>(lexy::_detail::make_index_sequence<decltype(Str)::size()> {})); +} + +namespace ovdl::dsl { + template<ovdl::detail::string_literal Str, typename L, typename T, typename... R> + constexpr auto keyword(lexyd::_id<L, T, R...>) { + return ovdl::detail::to_type_string<lexyd::_keyword<lexyd::_id<L, T>>::template get, Str> {}; + } +}
\ No newline at end of file |