aboutsummaryrefslogtreecommitdiff
path: root/manual/examples/mbstouwcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'manual/examples/mbstouwcs.c')
-rw-r--r--manual/examples/mbstouwcs.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/manual/examples/mbstouwcs.c b/manual/examples/mbstouwcs.c
index 5d223da..c94e1fa 100644
--- a/manual/examples/mbstouwcs.c
+++ b/manual/examples/mbstouwcs.c
@@ -1,3 +1,4 @@
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
@@ -7,22 +8,46 @@
wchar_t *
mbstouwcs (const char *s)
{
- size_t len = strlen (s);
- wchar_t *result = malloc ((len + 1) * sizeof (wchar_t));
+ /* 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;
- wchar_t tmp[1];
mbstate_t state;
- size_t nbytes;
-
memset (&state, '\0', sizeof (state));
- while ((nbytes = mbrtowc (tmp, s, len, &state)) > 0)
+
+ while (true)
{
- if (nbytes >= (size_t) -2)
- /* Invalid input string. */
- return NULL;
- *wcp++ = towupper (tmp[0]);
- len -= nbytes;
- s += nbytes;
+ 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;
}