homer512 icon

wide character to string

homer512 | PRO | 08/27/15 04:20:12 PM UTC | 0 ⭐ | 579 👁️ | Never ⏰ | []
C |

1.45 KB

|

None

|

0 👍

/

0 👎

#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