#include <wchar.h>
/* using wcsrtombs */
#include <stdlib.h>
/* using realloc, free */
#include <string.h>
/* using memset */
#include <stdio.h>
/* using fprintf */
#include <locale.h>
/* using setlocale */
char* s_wstring_to_string (const wchar_t* ws)
{
size_t buflen;
char* buffer;
char* resized;
size_t bufpos ;
mbstate_t mbstate;
memset(&mbstate, 0, sizeof(mbstate));
/* to avoid parsing the string twice, we allocate memory speculatively
* with exponential growth. Then we shrink it at the end
*
* Alternative: use
* const wchar_t* tmp = ws;
* size_t buflen = wcsrtombs(NULL, &tmp, 0, mbstate);
* buffer = malloc(buflen);
* wcsrtombs(buffer, &ws, 0, mbstate);
* return buffer;
*/
for(buflen = 4, buffer = NULL, bufpos = 0; ws; buflen *= 2) {
size_t converted;
if(! (resized = realloc(buffer, buflen)))
goto err;
buffer = resized;
if((converted = wcsrtombs(buffer + bufpos, &ws, buflen - bufpos, &mbstate))
== (size_t) -1)
goto err;
bufpos += converted;
}
/* shrink buffer to actually required size */
if(! (resized = realloc(buffer, bufpos + 1)))
goto err;
return resized;
err:
free(buffer);
return NULL;
}
int
main(void) {
setlocale(LC_ALL, "");
char * my_wstr = s_wstring_to_string (L"z\u00df\u6c34\U0001f34c");
if(my_wstr)
fprintf (stdout, "%s\n", my_wstr);
else
puts("Parse failed");
return 0;
}
Comments