Skip to content

Commit

Permalink
strings, enum_to_strings, literals : Add char8_t support. (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
p-groarke authored Apr 14, 2024
1 parent 1357fd1 commit 2af8780
Show file tree
Hide file tree
Showing 7 changed files with 451 additions and 124 deletions.
105 changes: 105 additions & 0 deletions include_cpp17/fea/macros/literals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ Helpers for string literals.
#define FEA_WSTRINGIFY(x) FEA_PASTE(L, #x)
#define FEA_U16STRINGIFY(x) FEA_PASTE(u, #x)
#define FEA_U32STRINGIFY(x) FEA_PASTE(U, #x)
#if FEA_CPP20
#define FEA_U8STRINGIFY(x) FEA_PASTE(u8, #x)
#endif

// Stringify passed in text with appropriate prefix.
// Adds a comma after literal.
Expand All @@ -59,63 +62,108 @@ Helpers for string literals.
#define FEA_WSTRINGIFY_COMMA(x) FEA_WSTRINGIFY(x),
#define FEA_U16STRINGIFY_COMMA(x) FEA_U16STRINGIFY(x),
#define FEA_U32STRINGIFY_COMMA(x) FEA_U32STRINGIFY(x),
#if FEA_CPP20
#define FEA_U8STRINGIFY_COMMA(x) FEA_U8STRINGIFY(x),
#endif

// Prefix the literal with : nothing, L, u or U.
#define FEA_PREFIX(x) x
#define FEA_WPREFIX(x) L##x
#define FEA_U16PREFIX(x) u##x
#define FEA_U32PREFIX(x) U##x
#if FEA_CPP20
#define FEA_U8PREFIX(x) u8##x
#endif

// Prefix the literal and add trailing comma.
#define FEA_PREFIX_COMMA(x) x,
#define FEA_WPREFIX_COMMA(x) L##x,
#define FEA_U16PREFIX_COMMA(x) u##x,
#define FEA_U32PREFIX_COMMA(x) U##x,
#if FEA_CPP20
#define FEA_U8PREFIX_COMMA(x) u8##x,
#endif

// Prefixes the literals list with : nothing, L, u, or U.
#define FEA_VA_PREFIX(...) FEA_FOR_EACH(FEA_PREFIX_COMMA, __VA_ARGS__)
#define FEA_VA_WPREFIX(...) FEA_FOR_EACH(FEA_WPREFIX_COMMA, __VA_ARGS__)
#define FEA_VA_U16PREFIX(...) FEA_FOR_EACH(FEA_U16PREFIX_COMMA, __VA_ARGS__)
#define FEA_VA_U32PREFIX(...) FEA_FOR_EACH(FEA_U32PREFIX_COMMA, __VA_ARGS__)
#if FEA_CPP20
#define FEA_VA_U8PREFIX(...) FEA_FOR_EACH(FEA_U8PREFIX_COMMA, __VA_ARGS__)
#endif

// Creates string of literal, prefixed appropriately.
#define FEA_S(x) std::string(x)
#define FEA_WS(x) std::wstring(FEA_WPREFIX(x))
#define FEA_U16S(x) std::u16string(FEA_U16PREFIX(x))
#define FEA_U32S(x) std::u32string(FEA_U32PREFIX(x))
#if FEA_CPP20
#define FEA_U8S(x) std::u8string(FEA_U8PREFIX(x))
#endif

// Creates string of literal with trailing comma.
#define FEA_S_COMMA(x) std::string(x),
#define FEA_WS_COMMA(x) std::wstring(FEA_WPREFIX(x)),
#define FEA_U16S_COMMA(x) std::u16string(FEA_U16PREFIX(x)),
#define FEA_U32S_COMMA(x) std::u32string(FEA_U32PREFIX(x)),
#if FEA_CPP20
#define FEA_U8S_COMMA(x) std::u8string(FEA_U8PREFIX(x)),
#endif

// Creates string_views with literals.
#define FEA_VA_S(...) FEA_FOR_EACH(FEA_S_COMMA, __VA_ARGS__)
#define FEA_VA_WS(...) FEA_FOR_EACH(FEA_WS_COMMA, __VA_ARGS__)
#define FEA_VA_U16S(...) FEA_FOR_EACH(FEA_U16S_COMMA, __VA_ARGS__)
#define FEA_VA_U32S(...) FEA_FOR_EACH(FEA_U32S_COMMA, __VA_ARGS__)
#if FEA_CPP20
#define FEA_VA_U8S(...) FEA_FOR_EACH(FEA_U8S_COMMA, __VA_ARGS__)
#endif

#if FEA_CPP17
// Creates string_view of literal, prefixed appropriately.
#define FEA_SV(x) std::string_view(x)
#define FEA_WSV(x) std::wstring_view(FEA_WPREFIX(x))
#define FEA_U16SV(x) std::u16string_view(FEA_U16PREFIX(x))
#define FEA_U32SV(x) std::u32string_view(FEA_U32PREFIX(x))
#if FEA_CPP20
#define FEA_U8SV(x) std::u8string_view(FEA_U8PREFIX(x))
#endif

// Creates string_view of literal with trailing comma.
#define FEA_SV_COMMA(x) std::string_view(x),
#define FEA_WSV_COMMA(x) std::wstring_view(FEA_WPREFIX(x)),
#define FEA_U16SV_COMMA(x) std::u16string_view(FEA_U16PREFIX(x)),
#define FEA_U32SV_COMMA(x) std::u32string_view(FEA_U32PREFIX(x)),
#if FEA_CPP20
#define FEA_U8SV_COMMA(x) std::u8string_view(FEA_U8PREFIX(x)),
#endif

// Creates string_views with literals.
#define FEA_VA_SV(...) FEA_FOR_EACH(FEA_SV_COMMA, __VA_ARGS__)
#define FEA_VA_WSV(...) FEA_FOR_EACH(FEA_WSV_COMMA, __VA_ARGS__)
#define FEA_VA_U16SV(...) FEA_FOR_EACH(FEA_U16SV_COMMA, __VA_ARGS__)
#define FEA_VA_U32SV(...) FEA_FOR_EACH(FEA_U32SV_COMMA, __VA_ARGS__)
#if FEA_CPP20
#define FEA_VA_U8SV(...) FEA_FOR_EACH(FEA_U8SV_COMMA, __VA_ARGS__)
#endif


#if !FEA_CPP20
// Makes a string from literal of type CharType
#define FEA_MAKE_STRING_T(CharType, str) \
[]() { \
if constexpr (std::is_same_v<CharType, char>) { \
return std::string{ str }; \
} else if constexpr (std::is_same_v<CharType, wchar_t>) { \
return std::wstring{ L##str }; \
} else if constexpr (std::is_same_v<CharType, char16_t>) { \
return std::u16string{ u##str }; \
} else if constexpr (std::is_same_v<CharType, char32_t>) { \
return std::u32string{ U##str }; \
} \
}()
#else
// Makes a string from literal of type CharType
#define FEA_MAKE_STRING_T(CharType, str) \
[]() { \
Expand All @@ -127,13 +175,17 @@ Helpers for string literals.
return std::u16string{ u##str }; \
} else if constexpr (std::is_same_v<CharType, char32_t>) { \
return std::u32string{ U##str }; \
} else if constexpr (std::is_same_v<CharType, char8_t>) { \
return std::u8string{ u8##str }; \
} \
}()
#endif

// These are shortcuts if you use CharT as an alias or template.
#define FEA_MAKE_STRING(str) FEA_MAKE_STRING_T(CharT, str)
#define FEA_STR(str) FEA_MAKE_STRING_T(CharT, str)

#if !FEA_CPP20
// Makes a string_view from literal of type CharType
#define FEA_MAKE_STRING_VIEW_T(CharType, str) \
[]() { \
Expand All @@ -147,11 +199,29 @@ Helpers for string literals.
return std::u32string_view{ U##str }; \
} \
}()
#else
// Makes a string_view from literal of type CharType
#define FEA_MAKE_STRING_VIEW_T(CharType, str) \
[]() { \
if constexpr (std::is_same_v<CharType, char>) { \
return std::string_view{ str }; \
} else if constexpr (std::is_same_v<CharType, wchar_t>) { \
return std::wstring_view{ L##str }; \
} else if constexpr (std::is_same_v<CharType, char16_t>) { \
return std::u16string_view{ u##str }; \
} else if constexpr (std::is_same_v<CharType, char32_t>) { \
return std::u32string_view{ U##str }; \
} else if constexpr (std::is_same_v<CharType, char8_t>) { \
return std::u8string_view{ u8##str }; \
} \
}()
#endif

// These are shortcuts if you use CharT as an alias or template.
#define FEA_MAKE_STRING_VIEW(str) FEA_MAKE_STRING_VIEW_T(CharT, str)
#define FEA_STRV(str) FEA_MAKE_STRING_VIEW_T(CharT, str)

#if !FEA_CPP20
// Makes a string literal of type CharType
#define FEA_MAKE_LITERAL_T(CharType, str) \
[]() { \
Expand All @@ -165,12 +235,44 @@ Helpers for string literals.
return U##str; \
} \
}()
#else
// Makes a string literal of type CharType
#define FEA_MAKE_LITERAL_T(CharType, str) \
[]() { \
if constexpr (std::is_same_v<CharType, char>) { \
return str; \
} else if constexpr (std::is_same_v<CharType, wchar_t>) { \
return L##str; \
} else if constexpr (std::is_same_v<CharType, char16_t>) { \
return u##str; \
} else if constexpr (std::is_same_v<CharType, char32_t>) { \
return U##str; \
} else if constexpr (std::is_same_v<CharType, char8_t>) { \
return u8##str; \
} \
}()
#endif

// These are shortcuts if you use CharT as an alias or template.
#define FEA_MAKE_LITERAL(str) FEA_MAKE_LITERAL_T(CharT, str)
#define FEA_LIT(str) FEA_MAKE_LITERAL_T(CharT, str)


#if !FEA_CPP20
// Makes a character literal of type CharType
#define FEA_MAKE_CHAR_LITERAL_T(CharType, str) \
[]() { \
if constexpr (std::is_same_v<CharType, char>) { \
return str; \
} else if constexpr (std::is_same_v<CharType, wchar_t>) { \
return L##str; \
} else if constexpr (std::is_same_v<CharType, char16_t>) { \
return u##str; \
} else if constexpr (std::is_same_v<CharType, char32_t>) { \
return U##str; \
} \
}()
#else
// Makes a character literal of type CharType
#define FEA_MAKE_CHAR_LITERAL_T(CharType, str) \
[]() { \
Expand All @@ -182,8 +284,11 @@ Helpers for string literals.
return u##str; \
} else if constexpr (std::is_same_v<CharType, char32_t>) { \
return U##str; \
} else if constexpr (std::is_same_v<CharType, char8_t>) { \
return u8##str; \
} \
}()
#endif

// These are shortcuts if you use CharT as an alias or template.
#define FEA_MAKE_CHAR_LITERAL(str) FEA_MAKE_CHAR_LITERAL_T(CharT, str)
Expand Down
35 changes: 35 additions & 0 deletions include_cpp17/fea/string/conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@
#include <locale>
#include <string>

/*
TODO : Rewrite everything based on std::c8rtomb, std::mbrtoc8,std::c16rtomb,
std::mbrtoc16, etc
Use return type overloading.
wstring -> reinterpret_cast as char16_t on windows, reinterpret_cast as char32_t
on linux.
*/

// Define FEA_CODEPAGE_CONVERSIONS to get windows (only) codepage conversions.
// Those are, helper functions for your current codepage to std::wstring.
#if FEA_WINDOWS && defined(FEA_CODEPAGE_CONVERSIONS_DEF)
Expand Down Expand Up @@ -141,6 +152,22 @@ inline std::u32string utf8_to_utf32(const std::string& s) {
#endif
}

#if FEA_CPP20
// UTF-8 to UTF-32
inline std::u32string utf8_to_utf32(const std::u8string& s) {
#if FEA_MSVC_CODECVT_BUG
std::wstring_convert<std::codecvt_utf8<std::uint_least32_t>,
std::uint_least32_t>
conv;
u32string_hack str = conv.from_bytes(s);
return { reinterpret_cast<const char32_t*>(str.c_str()) };
#else
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
return conv.from_bytes(reinterpret_cast<const char*>(s.c_str()));
#endif
}
#endif


// From UTF-16

Expand Down Expand Up @@ -345,6 +372,10 @@ std::basic_string<CharT> utf8_to_any(const std::string& str) {
return utf8_to_utf16(str);
} else if constexpr (std::is_same_v<CharT, char32_t>) {
return utf8_to_utf32(str);
#if FEA_CPP20
} else if constexpr (std::is_same_v<CharT, char8_t>) {
return std::u8string{ reinterpret_cast<const char8_t*>(str.c_str()) };
#endif
} else {
fea::maybe_throw(__FUNCTION__, __LINE__, "unsupported string type");
}
Expand All @@ -360,6 +391,10 @@ std::u32string any_to_utf32(const std::basic_string<CharT>& str) {
return utf16_to_utf32(str);
} else if constexpr (std::is_same_v<CharT, char32_t>) {
return str;
#if FEA_CPP20
} else if constexpr (std::is_same_v<CharT, char8_t>) {
return utf8_to_utf32(str);
#endif
} else {
fea::maybe_throw(__FUNCTION__, __LINE__, "unsupported string type");
}
Expand Down
Loading

0 comments on commit 2af8780

Please sign in to comment.