Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yumetodo/b672a8b8c5ad4ecdb5af705b003b7965 to your computer and use it in GitHub Desktop.
Save yumetodo/b672a8b8c5ad4ecdb5af705b003b7965 to your computer and use it in GitHub Desktop.
literal operator templateを文字列リテラルに適用できると勘違いして作った産物
inline constexpr int get_u8_byte_count(char ch) {
if (0 <= uint8_t(ch) && uint8_t(ch) < 0x80) {
return 1;
}
if (0xC2 <= uint8_t(ch) && uint8_t(ch) < 0xE0) {
return 2;
}
if (0xE0 <= uint8_t(ch) && uint8_t(ch) < 0xF0) {
return 3;
}
if (0xF0 <= uint8_t(ch) && uint8_t(ch) < 0xF8) {
return 4;
}
return 0;
}
inline constexpr bool is_u8_later_byte(char ch) {
return 0x80 <= uint8_t(ch) && uint8_t(ch) < 0xC0;
}
inline constexpr bool is_u8_later_byte(std::initializer_list<char> chars){
for(auto&& c: chars) if(!is_u8_later_byte(c)) return false;
return true;
}
namespace detail{
template<std::size_t l, std::size_t pc, char ...chars>
struct codepoint_count;
template<std::size_t l, char c1, char ...chars>
struct codepoint_count<l, 0, c1, chars...> : codepoint_count<l, get_u8_byte_count(c1), c1, chars...> {};
template<std::size_t l, char c1>
struct codepoint_count<l, 1, c1> : std::integral_constant<std::size_t, l + 1> {};
template<std::size_t l, char c1, char c2, char ...chars>
struct codepoint_count<l, 1, c1, c2, chars...> : codepoint_count<l + 1, get_u8_byte_count(c2), c2, chars...> {};
template<std::size_t l, char c1, char c2>
struct codepoint_count<l, 2, c1, c2> : std::enable_if_t<
is_u8_later_byte(c2),
std::integral_constant<std::size_t, l + 2>
> {};
template<std::size_t l, char c1, char c2, char c3, char ...chars>
struct codepoint_count<l, 2, c1, c2, c3, chars...> : std::enable_if_t<
is_u8_later_byte(c2),
codepoint_count<l + 2, get_u8_byte_count(c3), c3, chars...>
> {};
template<std::size_t l, char c1, char c2, char c3>
struct codepoint_count<l, 3, c1, c2, c3> : std::enable_if_t<
is_u8_later_byte({c2, c3}),
std::integral_constant<std::size_t, l + 3>
> {};
template<std::size_t l, char c1, char c2, char c3, char c4, char ...chars>
struct codepoint_count<l, 3, c1, c2, c3, c4, chars...> : std::enable_if_t<
is_u8_later_byte({c2, c3}),
codepoint_count<l + 3, get_u8_byte_count(c4), c4, chars...>
> {};
template<std::size_t l, char c1, char c2, char c3, char c4>
struct codepoint_count<l, 4, c1, c2, c3, c4> : std::enable_if_t<
is_u8_later_byte({c2, c3, c4}),
std::integral_constant<std::size_t, l + 4>
> {};
template<std::size_t l, char c1, char c2, char c3, char c4, char c5, char ...chars>
struct codepoint_count<l, 4, c1, c2, c3, c4, c5, chars...> : std::enable_if_t<
is_u8_later_byte({c2, c3, c4}),
codepoint_count<l + 4, get_u8_byte_count(c5), c5, chars...>
> {};
}
template<char ...chars>
inline constexpr std::size_t codepoint_count(){ return detail::codepoint_count<0, 0, chars...>::value; }
static_assert(9u == codepoint_count<u8'a', u8'r', u8'i', u8'k', u8'i', u8't', u8'a', u8'r', u8'i'>());
@yumetodo
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment