1 /* Copyright (c) 2009 Corinna Vinschen <corinna@vinschen.de> */
2 /*
3 FUNCTION
4 <<mbsrtowcs>>, <<mbsnrtowcs>>---convert a character string to a wide-character string
5 
6 INDEX
7 	mbsrtowcs
8 INDEX
9 	_mbsrtowcs_r
10 INDEX
11 	mbsnrtowcs
12 INDEX
13 	_mbsnrtowcs_r
14 
15 SYNOPSIS
16 	#include <wchar.h>
17 	size_t mbsrtowcs(wchar_t *__restrict <[dst]>,
18 			 const char **__restrict <[src]>,
19 			 size_t <[len]>,
20 			 mbstate_t *__restrict <[ps]>);
21 
22 	#include <wchar.h>
23 	size_t mbsnrtowcs(wchar_t *__ restrict <[dst]>,
24 			  const char **__restrict <[src]>, size_t <[nms]>,
25 			  size_t <[len]>, mbstate_t *__restrict <[ps]>);
26 
27 
28 DESCRIPTION
29 The <<mbsrtowcs>> function converts a sequence of multibyte characters
30 pointed to indirectly by <[src]> into a sequence of corresponding wide
31 characters and stores at most <[len]> of them in the wchar_t array pointed
32 to by <[dst]>, until it encounters a terminating null character ('\0').
33 
34 If <[dst]> is NULL, no characters are stored.
35 
36 If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point
37 to the character after the one that conversion stopped at.  If conversion
38 stops because a null character is encountered, *<[src]> is set to NULL.
39 
40 The mbstate_t argument, <[ps]>, is used to keep track of the shift state.  If
41 it is NULL, <<mbsrtowcs>> uses an internal, static mbstate_t object, which
42 is initialized to the initial conversion state at program startup.
43 
44 The <<mbsnrtowcs>> function behaves identically to <<mbsrtowcs>>, except that
45 conversion stops after reading at most <[nms]> bytes from the buffer pointed
46 to by <[src]>.
47 
48 RETURNS
49 The <<mbsrtowcs>> and <<mbsnrtowcs>> functions return the number of wide
50 characters stored in the array pointed to by <[dst]> if successful, otherwise
51 it returns (size_t)-1.
52 
53 PORTABILITY
54 <<mbsrtowcs>> is defined by the C99 standard.
55 <<mbsnrtowcs>> is defined by the POSIX.1-2008 standard.
56 */
57 
58 #include <newlib.h>
59 #include <wchar.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <errno.h>
63 
64 size_t
mbsnrtowcs(wchar_t * dst,const char ** src,size_t nms,size_t len,mbstate_t * ps)65 mbsnrtowcs (
66 	wchar_t *dst,
67 	const char **src,
68 	size_t nms,
69 	size_t len,
70 	mbstate_t *ps)
71 {
72   wchar_t *ptr = dst;
73   const char *tmp_src;
74   size_t max;
75   size_t count = 0;
76   int bytes;
77 
78 #ifdef _MB_CAPABLE
79   if (ps == NULL)
80     {
81       static NEWLIB_THREAD_LOCAL mbstate_t _mbsrtowcs_state;
82       ps = &_mbsrtowcs_state;
83     }
84 #endif
85 
86   if (dst == NULL)
87     {
88       /* Ignore original len value and do not alter src pointer if the
89          dst pointer is NULL.  */
90       len = (size_t)-1;
91       tmp_src = *src;
92       src = &tmp_src;
93     }
94 
95   max = len;
96   while (len > 0)
97     {
98       bytes = mbrtowc (ptr, *src, nms, ps);
99       if (bytes > 0)
100 	{
101 	  *src += bytes;
102 	  nms -= bytes;
103 	  ++count;
104 	  ptr = (dst == NULL) ? NULL : ptr + 1;
105 	  --len;
106 	}
107       else if (bytes == -2)
108 	{
109 	  *src += nms;
110 	  return count;
111 	}
112       else if (bytes == 0)
113 	{
114 	  *src = NULL;
115 	  return count;
116 	}
117       else
118 	{
119 	  ps->__count = 0;
120 	  _REENT_ERRNO(r) = EILSEQ;
121 	  return (size_t)-1;
122 	}
123     }
124 
125   return (size_t)max;
126 }
127