Program Listing for File string.hpp

Return to documentation for file (SeQuant/core/utility/string.hpp)

//
// Created by Robert Adam on 2023-10-10
//

#ifndef SEQUANT_CORE_UTILITY_STRING_HPP
#define SEQUANT_CORE_UTILITY_STRING_HPP

#include <SeQuant/core/meta.hpp>
#include <SeQuant/core/utility/macros.hpp>

#include <string>
#include <string_view>

namespace sequant {

namespace meta {

template <typename T>
constexpr inline bool is_string_or_view_v =
    std::is_same_v<std::remove_cvref_t<T>, std::string> ||
    std::is_same_v<std::remove_cvref_t<T>, std::string_view>;

template <typename T>
constexpr inline bool is_wstring_or_view_v =
    std::is_same_v<std::remove_cvref_t<T>, std::wstring> ||
    std::is_same_v<std::remove_cvref_t<T>, std::wstring_view>;

template <typename T>
constexpr inline bool is_string_convertible_v =
    is_string_or_view_v<T> || std::is_same_v<std::remove_cvref_t<T>, char[]> ||
    std::is_same_v<std::remove_all_extents_t<std::remove_cvref_t<T>>, char> ||
    std::is_same_v<std::remove_cvref_t<T>, char *> ||
    std::is_same_v<std::remove_cvref_t<T>, const char *> ||
    std::is_same_v<std::remove_cvref_t<T>, char>;

template <typename T>
constexpr inline bool is_wstring_convertible_v =
    is_wstring_or_view_v<T> ||
    std::is_same_v<std::remove_cvref_t<T>, wchar_t[]> ||
    std::is_same_v<std::remove_all_extents_t<std::remove_cvref_t<T>>,
                   wchar_t> ||
    std::is_same_v<std::remove_cvref_t<T>, wchar_t *> ||
    std::is_same_v<std::remove_cvref_t<T>, const wchar_t *> ||
    std::is_same_v<std::remove_cvref_t<T>, wchar_t>;

template <typename T>
constexpr inline bool is_basic_string_convertible_v =
    is_string_convertible_v<T> || is_wstring_convertible_v<T>;

template <typename T, typename Enabler = void>
struct char_type;

template <typename T>
struct char_type<T, std::enable_if_t<is_basic_string_convertible_v<T>>> {
  using type = std::conditional_t<is_string_convertible_v<T>, char, wchar_t>;
};

template <typename T>
using char_t = typename char_type<T>::type;

}  // namespace meta

template <typename T>
concept basic_string_convertible =
    meta::is_basic_string_convertible_v<std::remove_cvref_t<T>>;

std::string toUtf8(std::wstring_view str);

std::string toUtf8(std::string_view str);

inline std::string toUtf8(char c) { return toUtf8(std::string_view(&c, 1)); }

inline std::string toUtf8(wchar_t c) {
  return toUtf8(std::wstring_view(&c, 1));
}

std::wstring toUtf16(std::string_view str);

std::wstring toUtf16(std::wstring_view str);

inline std::wstring toUtf16(char c) { return toUtf16(std::string_view(&c, 1)); }

inline std::wstring toUtf16(wchar_t c) {
  return toUtf16(std::wstring_view(&c, 1));
}

template <basic_string_convertible S>
std::basic_string_view<meta::char_t<S>> to_basic_string_view(S &&str) {
  if constexpr (meta::is_char_v<std::remove_reference_t<S>>)
    return {&str, 1};
  else
    return str;
}

std::wstring to_wstring(meta::integral auto t) { return std::to_wstring(t); }

std::wstring to_wstring(std::floating_point auto t) {
  if (std::floor(t) == t)
    return std::to_wstring(static_cast<long long>(t));
  else
    return std::to_wstring(t);
}

namespace detail {

template <typename Char, std::size_t NChar, std::size_t NWChar,
          std::size_t NChar8, std::size_t NChar16, std::size_t NChar32>
constexpr decltype(auto) select_string_literal(
    const char (&str)[NChar], const wchar_t (&wstr)[NWChar],
    const char8_t (&u8str)[NChar8], const char16_t (&u16str)[NChar16],
    const char32_t (&u32str)[NChar32]) {
  if constexpr (std::is_same_v<Char, char>)
    return str;
  else if constexpr (std::is_same_v<Char, wchar_t>)
    return wstr;
  else if constexpr (std::is_same_v<Char, char8_t>)
    return u8str;
  else if constexpr (std::is_same_v<Char, char16_t>)
    return u16str;
  else if constexpr (std::is_same_v<Char, char32_t>)
    return u32str;

  SEQUANT_ABORT("Unhandled character type");
}
}  // namespace detail

#define SQ_STRLIT(code_unit, char_string_literal)                  \
  ::sequant::detail::select_string_literal<code_unit>(             \
      char_string_literal, SEQUANT_CONCAT(L, char_string_literal), \
      SEQUANT_CONCAT(u8, char_string_literal),                     \
      SEQUANT_CONCAT(u, char_string_literal),                      \
      SEQUANT_CONCAT(U, char_string_literal))

}  // namespace sequant

#endif  // SEQUANT_CORE_UTILITY_STRING_HPP