Add get_next_codepoint_size

This commit is contained in:
louiz’
2016-06-15 00:38:43 +02:00
parent 80d0c19c5a
commit 6235fb2d03
2 changed files with 21 additions and 12 deletions
+16 -12
View File
@@ -23,6 +23,17 @@ namespace utils
/** /**
* Based on http://en.wikipedia.org/wiki/UTF-8#Description * Based on http://en.wikipedia.org/wiki/UTF-8#Description
*/ */
std::size_t get_next_codepoint_size(const unsigned char c)
{
if ((c & 0b11111000) == 0b11110000) // 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
return 4;
else if ((c & 0b11110000) == 0b11100000) // 3 bytes: 1110xxx 10xxxxxx 10xxxxxx
return 3;
else if ((c & 0b11100000) == 0b11000000) // 2 bytes: 110xxxxx 10xxxxxx
return 2;
return 1; // 1 byte: 0xxxxxxx
}
bool is_valid_utf8(const char* s) bool is_valid_utf8(const char* s)
{ {
if (!s) if (!s)
@@ -32,38 +43,31 @@ namespace utils
while (*str) while (*str)
{ {
// 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx const auto codepoint_size = get_next_codepoint_size(str[0]);
if ((str[0] & 0b11111000) == 0b11110000) if (codepoint_size == 4)
{ {
if (!str[1] || !str[2] || !str[3] if (!str[1] || !str[2] || !str[3]
|| ((str[1] & 0b11000000) != 0b10000000) || ((str[1] & 0b11000000) != 0b10000000)
|| ((str[2] & 0b11000000) != 0b10000000) || ((str[2] & 0b11000000) != 0b10000000)
|| ((str[3] & 0b11000000) != 0b10000000)) || ((str[3] & 0b11000000) != 0b10000000))
return false; return false;
str += 4;
} }
// 3 bytes: 1110xxx 10xxxxxx 10xxxxxx else if (codepoint_size == 3)
else if ((str[0] & 0b11110000) == 0b11100000)
{ {
if (!str[1] || !str[2] if (!str[1] || !str[2]
|| ((str[1] & 0b11000000) != 0b10000000) || ((str[1] & 0b11000000) != 0b10000000)
|| ((str[2] & 0b11000000) != 0b10000000)) || ((str[2] & 0b11000000) != 0b10000000))
return false; return false;
str += 3;
} }
// 2 bytes: 110xxxxx 10xxxxxx else if (codepoint_size == 2)
else if (((str[0]) & 0b11100000) == 0b11000000)
{ {
if (!str[1] || if (!str[1] ||
((str[1] & 0b11000000) != 0b10000000)) ((str[1] & 0b11000000) != 0b10000000))
return false; return false;
str += 2;
} }
// 1 byte: 0xxxxxxx
else if ((str[0] & 0b10000000) != 0) else if ((str[0] & 0b10000000) != 0)
return false; return false;
else str += codepoint_size;
str++;
} }
return true; return true;
} }
+5
View File
@@ -5,6 +5,11 @@
namespace utils namespace utils
{ {
/**
* Return the size, in bytes, of the next UTF-8 codepoint, based on
* the given char.
*/
std::size_t get_next_codepoint_size(const unsigned char c);
/** /**
* Returns true if the given null-terminated string is valid utf-8. * Returns true if the given null-terminated string is valid utf-8.
* *