#include "utf8.h" #define UTF8_ONE_BYTE_MASK 0b10000000 #define UTF8_ONE_BYTE_COUNT 0 #define UTF8_TWO_BYTE_MASK 0b11100000 #define UTF8_TWO_BYTE_COUNT 0b11000000 #define UTF8_THREE_BYTE_MASK 0b11110000 #define UTF8_THREE_BYTE_COUNT 0b11100000 #define UTF8_FOUR_BYTE_MASK 0b11111000 #define UTF8_FOUR_BYTE_COUNT 0b11110000 // This one could use a better name, I just don't know a better one (yet?) #define UTF8_OTHER_MASK 0b00111111 size_t utf8_codepoint_size(uint8_t text) { if((text & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_COUNT) { return 1; } if((text & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_COUNT) { return 2; } if((text & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_COUNT) { return 3; } return 4; } /* Compute the size (number of visible chars) of an UTF-8 string. For each character, the check function is called. If it returns false, utf8_scan end and return -1. Normally, returns the number of characters in the string. It also validate that UTF-8 character of size 2, 3 and 4 contains confirming content. It returns -1 if not confirming. So it performs basic validation of an UTF-8 string plus custom validation of ASCII chars. */ int utf8_scan (std::string_view s, std::function check) { int ret = 0; size_t s_size = s.size(); auto pt = s.begin(); for (unsigned i=0; i 1){ size--; i += size; pt++; for (unsigned j=0; j= 0xc0){ ret = -1; break; } } if (ret == -1) break; pt--; } } }else{ // Incomplete UTF-8 character ret = -1; break; } } return ret; } #ifdef TEST #include #include #include #include #include #include using namespace std; int main (int argc, char *argv[]) { glocal int ret = -1; glocal.ret = (argc,argv); setproginfo ("","0.0","..."); int ret = -1; for (int i=0; i 1){ ret = true; } return ret; }); printf ("accept only alpha + multi character UTF-8len = %d\n",len); } return ret; return glocal.ret; } #endif