这是WideCharToMultiByte 和MultiByteToWideChar 的C 实现。
在这两种情况下,我都会确保将null 字符添加到目标缓冲区的末尾。
如果显式指定输入字符串长度而不使用终止空字符,MultiByteToWideChar 不会以空值终止输出字符串。
和
如果输入字符串长度明确指定且没有终止空字符,WideCharToMultiByte 不会以空值终止输出字符串。
即使有人指定-1 并传入null 终止的字符串,我仍然为额外的null 字符分配足够的空间,因为对于我的用例来说这不是问题。
wchar_t* utf8_decode( const char* str, int nbytes ) {
int nchars = 0;
if ( ( nchars = MultiByteToWideChar( CP_UTF8,
MB_ERR_INVALID_CHARS, str, nbytes, NULL, 0 ) ) == 0 ) {
return NULL;
}
wchar_t* wstr = NULL;
if ( !( wstr = malloc( ( ( size_t )nchars + 1 ) * sizeof( wchar_t ) ) ) ) {
return NULL;
}
wstr[ nchars ] = L'\0';
if ( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS,
str, nbytes, wstr, ( size_t )nchars ) == 0 ) {
free( wstr );
return NULL;
}
return wstr;
}
char* utf8_encode( const wchar_t* wstr, int nchars ) {
int nbytes = 0;
if ( ( nbytes = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS,
wstr, nchars, NULL, 0, NULL, NULL ) ) == 0 ) {
return NULL;
}
char* str = NULL;
if ( !( str = malloc( ( size_t )nbytes + 1 ) ) ) {
return NULL;
}
str[ nbytes ] = '\0';
if ( WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS,
wstr, nchars, str, nbytes, NULL, NULL ) == 0 ) {
free( str );
return NULL;
}
return str;
}