1 /* Copyright (c) 2009 Corinna Vinschen <corinna@vinschen.de> */
2 /*
3 FUNCTION
4 <<wcsrtombs>>, <<wcsnrtombs>>---convert a wide-character string to a character string
5 
6 INDEX
7 	wcsrtombs
8 INDEX
9 	_wcsrtombs_r
10 INDEX
11 	wcsnrtombs
12 INDEX
13 	_wcsnrtombs_r
14 
15 SYNOPSIS
16 	#include <wchar.h>
17 	size_t wcsrtombs(char *__restrict <[dst]>,
18 			 const wchar_t **__restrict <[src]>, size_t <[len]>,
19 			 mbstate_t *__restrict <[ps]>);
20 
21 	#include <wchar.h>
22 	size_t _wcsrtombs_r(struct _reent *<[ptr]>, char *<[dst]>,
23 			    const wchar_t **<[src]>, size_t <[len]>,
24 			    mbstate_t *<[ps]>);
25 
26 	#include <wchar.h>
27 	size_t wcsnrtombs(char *__restrict <[dst]>,
28 			  const wchar_t **__restrict <[src]>,
29 			  size_t <[nwc]>, size_t <[len]>,
30 			  mbstate_t *__restrict <[ps]>);
31 
32 	#include <wchar.h>
33 	size_t _wcsnrtombs_r(struct _reent *<[ptr]>, char *<[dst]>,
34 			     const wchar_t **<[src]>, size_t <[nwc]>,
35 			     size_t <[len]>, mbstate_t *<[ps]>);
36 
37 DESCRIPTION
38 The <<wcsrtombs>> function converts a string of wide characters indirectly
39 pointed to by <[src]> to a corresponding multibyte character string stored in
40 the array pointed to by <[dst]>.  No more than <[len]> bytes are written to
41 <[dst]>.
42 
43 If <[dst]> is NULL, no characters are stored.
44 
45 If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point
46 to the character after the one that conversion stopped at.  If conversion
47 stops because a null character is encountered, *<[src]> is set to NULL.
48 
49 The mbstate_t argument, <[ps]>, is used to keep track of the shift state.  If
50 it is NULL, <<wcsrtombs>> uses an internal, static mbstate_t object, which
51 is initialized to the initial conversion state at program startup.
52 
53 The <<wcsnrtombs>> function behaves identically to <<wcsrtombs>>, except that
54 conversion stops after reading at most <[nwc]> characters from the buffer
55 pointed to by <[src]>.
56 
57 RETURNS
58 The <<wcsrtombs>> and <<wcsnrtombs>> functions return the number of bytes
59 stored in the array pointed to by <[dst]> (not including any terminating
60 null), if successful, otherwise it returns (size_t)-1.
61 
62 PORTABILITY
63 <<wcsrtombs>> is defined by C99 standard.
64 <<wcsnrtombs>> is defined by the POSIX.1-2008 standard.
65 */
66 
67 #include <newlib.h>
68 #include <wchar.h>
69 #include <stdlib.h>
70 #include <stdio.h>
71 #include <errno.h>
72 #include "local.h"
73 #include "../locale/setlocale.h"
74 
75 size_t
_wcsnrtombs_l(char * dst,const wchar_t ** src,size_t nwc,size_t len,mbstate_t * ps,struct __locale_t * loc)76 _wcsnrtombs_l (char *dst, const wchar_t **src, size_t nwc,
77 	       size_t len, mbstate_t *ps, struct __locale_t *loc)
78 {
79   char *ptr = dst;
80   char buff[10];
81   wchar_t *pwcs;
82   size_t n;
83   int i;
84 
85 #ifdef _MB_CAPABLE
86   if (ps == NULL)
87     {
88       static NEWLIB_THREAD_LOCAL mbstate_t _wcsrtombs_state;
89       ps = &_wcsrtombs_state;
90     }
91 #endif
92 
93   /* If no dst pointer, treat len as maximum possible value. */
94   if (dst == NULL)
95     len = (size_t)-1;
96 
97   n = 0;
98   pwcs = (wchar_t *)(*src);
99 
100   while (n < len && nwc-- > 0)
101     {
102       int count = ps->__count;
103       wint_t wch = ps->__value.__wch;
104       int bytes = loc->wctomb (buff, *pwcs, ps);
105       if (bytes == -1)
106 	{
107 	  _REENT_ERRNO(r) = EILSEQ;
108 	  ps->__count = 0;
109 	  return (size_t)-1;
110 	}
111       if (n + bytes <= len)
112 	{
113           n += bytes;
114 	  if (dst)
115 	    {
116 	      for (i = 0; i < bytes; ++i)
117 	        *ptr++ = buff[i];
118 	      ++(*src);
119 	    }
120 	  if (*pwcs++ == 0x00)
121 	    {
122 	      if (dst)
123 	        *src = NULL;
124 	      ps->__count = 0;
125 	      return n - 1;
126 	    }
127 	}
128       else
129 	{
130 	  /* not enough room, we must back up state to before __WCTOMB call */
131 	  ps->__count = count;
132 	  ps->__value.__wch = wch;
133           len = 0;
134 	}
135     }
136 
137   return n;
138 }
139 
140 #ifndef _REENT_ONLY
141 size_t
wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)142 wcsnrtombs (char *__restrict dst,
143 	const wchar_t **__restrict src,
144 	size_t nwc,
145 	size_t len,
146 	mbstate_t *__restrict ps)
147 {
148   return _wcsnrtombs_l (dst, src, nwc, len, ps,
149 			__get_current_locale ());
150 }
151 #endif /* !_REENT_ONLY */
152