]> git.ipfire.org Git - thirdparty/glibc.git/blame - wcsmbs/wcsnrtombs.c
Remove "Contributed by" lines
[thirdparty/glibc.git] / wcsmbs / wcsnrtombs.c
CommitLineData
2b778ceb 1/* Copyright (C) 1996-2021 Free Software Foundation, Inc.
33a934a3 2 This file is part of the GNU C Library.
036cc82f 3
33a934a3 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
036cc82f 8
33a934a3
UD
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
41bdb6e2 12 Lesser General Public License for more details.
036cc82f 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
036cc82f 17
915a6c51 18#include <assert.h>
55985355 19#include <dlfcn.h>
036cc82f 20#include <errno.h>
4bca4c17 21#include <gconv.h>
036cc82f 22#include <wchar.h>
4bca4c17
UD
23#include <wcsmbsload.h>
24
915a6c51 25#include <sysdep.h>
036cc82f
RM
26
27#ifndef EILSEQ
4bca4c17 28# define EILSEQ EINVAL
036cc82f
RM
29#endif
30
31
4bca4c17
UD
32/* This is the private state used if PS is NULL. */
33static mbstate_t state;
036cc82f
RM
34
35/* This is a non-standard function but it is very useful in the
36 implementation of stdio because we have to deal with unterminated
37 buffers. At most NWC wide character will be converted. */
38size_t
9dd346ff
JM
39__wcsnrtombs (char *dst, const wchar_t **src, size_t nwc, size_t len,
40 mbstate_t *ps)
036cc82f 41{
d64b6ad0 42 struct __gconv_step_data data;
8619129f 43 const wchar_t *srcend;
4bca4c17 44 int status;
23f0c99c 45 size_t result;
d64b6ad0 46 struct __gconv_step *tomb;
96310297 47 const struct gconv_fcts *fcts;
036cc82f 48
4bca4c17 49 /* Tell where we want the result. */
d64b6ad0
UD
50 data.__invocation_counter = 0;
51 data.__internal_use = 1;
85830c4c 52 data.__flags = __GCONV_IS_LAST;
d64b6ad0 53 data.__statep = ps ?: &state;
036cc82f 54
4bca4c17
UD
55 if (nwc == 0)
56 return 0;
8619129f 57 srcend = *src + __wcsnlen (*src, nwc - 1) + 1;
036cc82f 58
96310297
RM
59 /* Get the conversion functions. */
60 fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
f4017d20 61
d64b6ad0 62 /* Get the structure with the function pointers. */
96310297 63 tomb = fcts->tomb;
915a6c51
UD
64 __gconv_fct fct = tomb->__fct;
65#ifdef PTR_DEMANGLE
66 if (tomb->__shlib_handle != NULL)
67 PTR_DEMANGLE (fct);
68#endif
d64b6ad0 69
4bca4c17
UD
70 /* We have to handle DST == NULL special. */
71 if (dst == NULL)
72 {
72098116 73 mbstate_t temp_state;
b117f744 74 unsigned char buf[256]; /* Just an arbitrary value. */
9c7ff11a 75 const unsigned char *inbuf = (const unsigned char *) *src;
23f0c99c 76 size_t dummy;
f4017d20 77
72098116
UD
78 temp_state = *data.__statep;
79 data.__statep = &temp_state;
80
23f0c99c 81 result = 0;
d64b6ad0 82 data.__outbufend = buf + sizeof (buf);
036cc82f 83
4bca4c17 84 do
d079f321 85 {
d64b6ad0 86 data.__outbuf = buf;
d079f321 87
915a6c51
UD
88 status = DL_CALL_FCT (fct, (tomb, &data, &inbuf,
89 (const unsigned char *) srcend, NULL,
90 &dummy, 0, 1));
23f0c99c
UD
91
92 /* Count the number of bytes. */
d64b6ad0 93 result += data.__outbuf - buf;
d079f321 94 }
d64b6ad0 95 while (status == __GCONV_FULL_OUTPUT);
036cc82f 96
d64b6ad0
UD
97 if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
98 && data.__outbuf[-1] == '\0')
4bca4c17
UD
99 /* Don't count the NUL character in. */
100 --result;
101 }
102 else
103 {
104 /* This code is based on the safe assumption that all internal
105 multi-byte encodings use the NUL byte only to mark the end
106 of the string. */
23f0c99c
UD
107 size_t dummy;
108
1c99f950
UD
109 data.__outbuf = (unsigned char *) dst;
110 data.__outbufend = (unsigned char *) dst + len;
4bca4c17 111
915a6c51
UD
112 status = DL_CALL_FCT (fct, (tomb, &data, (const unsigned char **) src,
113 (const unsigned char *) srcend, NULL,
114 &dummy, 0, 1));
23f0c99c
UD
115
116 /* Count the number of bytes. */
d64b6ad0 117 result = data.__outbuf - (unsigned char *) dst;
4bca4c17
UD
118
119 /* We have to determine whether the last character converted
120 is the NUL character. */
d64b6ad0
UD
121 if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
122 && data.__outbuf[-1] == '\0')
036cc82f 123 {
d64b6ad0
UD
124 assert (data.__outbuf != (unsigned char *) dst);
125 assert (__mbsinit (data.__statep));
036cc82f 126 *src = NULL;
4bca4c17 127 --result;
036cc82f 128 }
4bca4c17 129 }
036cc82f 130
4bca4c17
UD
131 /* There must not be any problems with the conversion but illegal input
132 characters. */
d64b6ad0
UD
133 assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
134 || status == __GCONV_ILLEGAL_INPUT
135 || status == __GCONV_INCOMPLETE_INPUT
136 || status == __GCONV_FULL_OUTPUT);
036cc82f 137
d64b6ad0
UD
138 if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
139 && status != __GCONV_EMPTY_INPUT)
4bca4c17
UD
140 {
141 result = (size_t) -1;
142 __set_errno (EILSEQ);
036cc82f
RM
143 }
144
4bca4c17 145 return result;
036cc82f
RM
146}
147weak_alias (__wcsnrtombs, wcsnrtombs)