about summary refs log tree commit diff
path: root/manual/examples/mbstouwcs.c
blob: c94e1fa7900f7782db0a7e10326c2abd55327cf0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>

/* Do not include the above headers in the example.
*/
wchar_t *
mbstouwcs (const char *s)
{
  /* Include the null terminator in the conversion.  */
  size_t len = strlen (s) + 1;
  wchar_t *result = reallocarray (NULL, len, sizeof (wchar_t));
  if (result == NULL)
    return NULL;

  wchar_t *wcp = result;
  mbstate_t state;
  memset (&state, '\0', sizeof (state));

  while (true)
    {
      wchar_t wc;
      size_t nbytes = mbrtowc (&wc, s, len, &state);
      if (nbytes == 0)
        {
          /* Terminate the result string.  */
          *wcp = L'\0';
          break;
        }
      else if (nbytes == (size_t) -2)
        {
          /* Truncated input string.  */
          errno = EILSEQ;
          free (result);
          return NULL;
        }
      else if (nbytes == (size_t) -1)
        {
          /* Some other error (including EILSEQ).  */
          free (result);
          return NULL;
        }
      else
        {
          /* A character was converted.  */
          *wcp++ = towupper (wc);
          len -= nbytes;
          s += nbytes;
        }
    }
  return result;
}