| 1938 | } |
| 1939 | |
| 1940 | CharString String::utf8(Vector<uint8_t> *r_ch_length_map) const { |
| 1941 | int l = length(); |
| 1942 | if (!l) { |
| 1943 | return CharString(); |
| 1944 | } |
| 1945 | |
| 1946 | uint8_t *map_ptr = nullptr; |
| 1947 | if (r_ch_length_map) { |
| 1948 | r_ch_length_map->resize_uninitialized(l); |
| 1949 | map_ptr = r_ch_length_map->ptrw(); |
| 1950 | } |
| 1951 | |
| 1952 | const char32_t *d = &operator[](0); |
| 1953 | int fl = 0; |
| 1954 | for (int i = 0; i < l; i++) { |
| 1955 | uint32_t c = d[i]; |
| 1956 | int ch_w = 1; |
| 1957 | if (c <= 0x7f) { // 7 bits. |
| 1958 | ch_w = 1; |
| 1959 | } else if (c <= 0x7ff) { // 11 bits |
| 1960 | ch_w = 2; |
| 1961 | } else if (c <= 0xffff) { // 16 bits |
| 1962 | ch_w = 3; |
| 1963 | } else if (c <= 0x001fffff) { // 21 bits |
| 1964 | ch_w = 4; |
| 1965 | } else if (c <= 0x03ffffff) { // 26 bits |
| 1966 | ch_w = 5; |
| 1967 | print_unicode_error(vformat("Invalid unicode codepoint (%x)", c)); |
| 1968 | } else if (c <= 0x7fffffff) { // 31 bits |
| 1969 | ch_w = 6; |
| 1970 | print_unicode_error(vformat("Invalid unicode codepoint (%x)", c)); |
| 1971 | } else { |
| 1972 | ch_w = 1; |
| 1973 | print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as UTF-8", c), true); |
| 1974 | } |
| 1975 | fl += ch_w; |
| 1976 | if (map_ptr) { |
| 1977 | map_ptr[i] = ch_w; |
| 1978 | } |
| 1979 | } |
| 1980 | |
| 1981 | CharString utf8s; |
| 1982 | if (fl == 0) { |
| 1983 | return utf8s; |
| 1984 | } |
| 1985 | |
| 1986 | utf8s.resize_uninitialized(fl + 1); |
| 1987 | uint8_t *cdst = (uint8_t *)utf8s.get_data(); |
| 1988 | |
| 1989 | #define APPEND_CHAR(m_c) *(cdst++) = m_c |
| 1990 | |
| 1991 | for (int i = 0; i < l; i++) { |
| 1992 | uint32_t c = d[i]; |
| 1993 | |
| 1994 | if (c <= 0x7f) { // 7 bits. |
| 1995 | APPEND_CHAR(c); |
| 1996 | } else if (c <= 0x7ff) { // 11 bits |
| 1997 | APPEND_CHAR(uint32_t(0xc0 | ((c >> 6) & 0x1f))); // Top 5 bits. |