1 /* Copyright (C) 1996-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
24 #include <wcsmbsload.h>
26 #include <pointer_guard.h>
29 # define EILSEQ EINVAL
33 /* This is the private state used if PS is NULL. */
34 static mbstate_t state
;
37 __wcsrtombs (char *dst
, const wchar_t **src
, size_t len
, mbstate_t *ps
)
39 struct __gconv_step_data data
;
42 struct __gconv_step
*tomb
;
43 const struct gconv_fcts
*fcts
;
45 /* Tell where we want the result. */
46 data
.__invocation_counter
= 0;
47 data
.__internal_use
= 1;
48 data
.__flags
= __GCONV_IS_LAST
;
49 data
.__statep
= ps
?: &state
;
51 /* Get the conversion functions. */
52 fcts
= get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE
));
54 /* Get the structure with the function pointers. */
56 __gconv_fct fct
= tomb
->__fct
;
57 if (tomb
->__shlib_handle
!= NULL
)
60 /* We have to handle DST == NULL special. */
64 unsigned char buf
[256]; /* Just an arbitrary value. */
65 const wchar_t *srcend
= *src
+ __wcslen (*src
) + 1;
66 const unsigned char *inbuf
= (const unsigned char *) *src
;
69 temp_state
= *data
.__statep
;
70 data
.__statep
= &temp_state
;
73 data
.__outbufend
= buf
+ sizeof (buf
);
79 status
= DL_CALL_FCT (fct
, (tomb
, &data
, &inbuf
,
80 (const unsigned char *) srcend
, NULL
,
83 /* Count the number of bytes. */
84 result
+= data
.__outbuf
- buf
;
86 while (status
== __GCONV_FULL_OUTPUT
);
88 if (status
== __GCONV_OK
|| status
== __GCONV_EMPTY_INPUT
)
90 /* There better should be a NUL byte at the end. */
91 assert (data
.__outbuf
[-1] == '\0');
92 /* Don't count the NUL character in. */
98 /* This code is based on the safe assumption that all internal
99 multi-byte encodings use the NUL byte only to mark the end
101 const wchar_t *srcend
= *src
+ __wcsnlen (*src
, len
) + 1;
104 data
.__outbuf
= (unsigned char *) dst
;
105 data
.__outbufend
= (unsigned char *) dst
+ len
;
107 status
= DL_CALL_FCT (fct
, (tomb
, &data
, (const unsigned char **) src
,
108 (const unsigned char *) srcend
, NULL
,
111 /* Count the number of bytes. */
112 result
= data
.__outbuf
- (unsigned char *) dst
;
114 /* We have to determine whether the last character converted
115 is the NUL character. */
116 if ((status
== __GCONV_OK
|| status
== __GCONV_EMPTY_INPUT
)
117 && data
.__outbuf
[-1] == '\0')
119 assert (data
.__outbuf
!= (unsigned char *) dst
);
120 assert (__mbsinit (data
.__statep
));
126 /* There must not be any problems with the conversion but illegal input
128 assert (status
== __GCONV_OK
|| status
== __GCONV_EMPTY_INPUT
129 || status
== __GCONV_ILLEGAL_INPUT
130 || status
== __GCONV_INCOMPLETE_INPUT
131 || status
== __GCONV_FULL_OUTPUT
);
133 if (status
!= __GCONV_OK
&& status
!= __GCONV_FULL_OUTPUT
134 && status
!= __GCONV_EMPTY_INPUT
)
136 result
= (size_t) -1;
137 __set_errno (EILSEQ
);
142 weak_alias (__wcsrtombs
, wcsrtombs
)