diff options
Diffstat (limited to 'source/blender/blenlib/intern/string_utf8.c')
-rw-r--r-- | source/blender/blenlib/intern/string_utf8.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index dc6cb0ef228..f331d13e580 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -31,6 +31,8 @@ */ #include <string.h> +#include <wchar.h> +#include <wctype.h> #include "BLI_string.h" @@ -183,6 +185,159 @@ char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) return dst_r; } + +/* --------------------------------------------------------------------------*/ +/* wchar_t / utf8 functions */ + +/* UTF-8 <-> wchar transformations */ +static size_t chtoutf8(const unsigned long c, char o[4]) +{ + // Variables and initialization +/* memset(o, 0, 4); */ + + // Create the utf-8 string + if (c < 0x80) { + o[0] = (char) c; + return 1; + } + else if (c < 0x800) { + o[0] = (0xC0 | (c>>6)); + o[1] = (0x80 | (c & 0x3f)); + return 2; + } + else if (c < 0x10000) { + o[0] = (0xe0 | (c >> 12)); + o[1] = (0x80 | (c >>6 & 0x3f)); + o[2] = (0x80 | (c & 0x3f)); + return 3; + } + else if (c < 0x200000) { + o[0] = (0xf0 | (c>>18)); + o[1] = (0x80 | (c >>12 & 0x3f)); + o[2] = (0x80 | (c >> 6 & 0x3f)); + o[3] = (0x80 | (c & 0x3f)); + return 4; + } + + /* should we assert here? */ + return 0; +} + +size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxcpy) +{ + size_t len = 0; + while(*src && len < maxcpy) { /* XXX can still run over the buffer because utf8 size isnt known :| */ + len += chtoutf8(*src++, dst+len); + } + + dst[len]= '\0'; + + return len; +} + +/* wchar len in utf8 */ +size_t BLI_wstrlen_utf8(const wchar_t *src) +{ + char ch_dummy[4]; + size_t len = 0; + + while(*src) { + len += chtoutf8(*src++, ch_dummy); + } + + return len; +} + +// utf8slen +size_t BLI_strlen_utf8(const char *strc) +{ + int len=0; + + while(*strc) { + if ((*strc & 0xe0) == 0xc0) { + if((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) + strc++; + } else if ((*strc & 0xf0) == 0xe0) { + if((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) + strc += 2; + } else if ((*strc & 0xf8) == 0xf0) { + if((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) + strc += 3; + } + + strc++; + len++; + } + + return len; +} + + +/* Converts Unicode to wchar + +According to RFC 3629 "UTF-8, a transformation format of ISO 10646" +(http://tools.ietf.org/html/rfc3629), the valid UTF-8 encoding are: + + Char. number range | UTF-8 octet sequence + (hexadecimal) | (binary) + --------------------+--------------------------------------------- + 0000 0000-0000 007F | 0xxxxxxx + 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +If the encoding incidated by the first character is incorrect (because the +1 to 3 following characters do not match 10xxxxxx), the output is a '?' and +only a single input character is consumed. + +*/ + +size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size_t maxcpy) +{ + int len=0; + + if(dst_w==NULL || src_c==NULL) return(0); + + while(*src_c && len < maxcpy) { + if ((*src_c & 0xe0) == 0xc0) { + if((src_c[1] & 0x80) && (src_c[1] & 0x40) == 0x00) { + *dst_w=((src_c[0] &0x1f)<<6) | (src_c[1]&0x3f); + src_c++; + } else { + *dst_w = '?'; + } + } else if ((*src_c & 0xf0) == 0xe0) { + if((src_c[1] & src_c[2] & 0x80) && ((src_c[1] | src_c[2]) & 0x40) == 0x00) { + *dst_w=((src_c[0] & 0x0f)<<12) | ((src_c[1]&0x3f)<<6) | (src_c[2]&0x3f); + src_c += 2; + } else { + *dst_w = '?'; + } + } else if ((*src_c & 0xf8) == 0xf0) { + if((src_c[1] & src_c[2] & src_c[3] & 0x80) && ((src_c[1] | src_c[2] | src_c[3]) & 0x40) == 0x00) { + *dst_w=((src_c[0] & 0x07)<<18) | ((src_c[1]&0x1f)<<12) | ((src_c[2]&0x3f)<<6) | (src_c[3]&0x3f); + src_c += 3; + } else { + *dst_w = '?'; + } + } else { + *dst_w=(src_c[0] & 0x7f); + } + + src_c++; + dst_w++; + len++; + } + return len; +} + +/* end wchar_t / utf8 functions */ +/* --------------------------------------------------------------------------*/ + + + + + /* copied from glib */ /** * g_utf8_find_prev_char: |