1 /* Simple transformations functions.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 #include <sys/param.h>
29 __gconv_transform_dummy (struct gconv_step *step, struct gconv_step_data *data,
30 const char *inbuf, size_t *inlen, size_t *written,
35 /* We have no stateful encoding. So we don't have to do anything
41 do_write = MIN (*inlen, data->outbufsize - data->outbufavail);
43 memcpy (data->outbuf, inbuf, do_write);
46 data->outbufavail += do_write;
49 /* ### TODO Actually, this number must be devided according to the
50 size of the input charset. I.e., if the input is in UCS4 the
51 number of copied bytes must be divided by 4. */
60 __gconv_transform_init_rstate (struct gconv_step *step,
61 struct gconv_step_data *data)
63 /* We have to provide the transformation function an correctly initialized
64 object of type `mbstate_t'. This must be dynamically allocated. */
65 data->data = calloc (1, sizeof (mbstate_t));
67 return data->data == NULL ? GCONV_NOMEM : GCONV_OK;
72 __gconv_transform_end_rstate (struct gconv_step_data *data)
74 if (data->data != NULL)
80 __gconv_transform_ucs4_utf8 (struct gconv_step *step,
81 struct gconv_step_data *data, const char *inbuf,
82 size_t *inlen, size_t *written, int do_flush)
84 struct gconv_step *next_step = step + 1;
85 struct gconv_step_data *next_data = data + 1;
86 gconv_fct fct = next_step->fct;
90 /* If the function is called with no input this means we have to reset
91 to the initial state. The possibly partly converted input is
95 /* Clear the state. */
96 memset (data->data, '\0', sizeof (mbstate_t));
99 /* Call the steps down the chain if there are any. */
104 struct gconv_step *next_step = step + 1;
105 struct gconv_step_data *next_data = data + 1;
107 result = (*fct) (next_step, next_data, NULL, 0, written, 1);
109 /* Clear output buffer. */
110 data->outbufavail = 0;
119 const char *newinbuf = inbuf;
120 size_t actually = __wmemrtombs (&data->outbuf[data->outbufavail],
121 (const wchar_t **) &newinbuf,
122 *inlen / sizeof (wchar_t),
123 data->outbufsize - data->outbufavail,
124 (mbstate_t *) data->data);
126 /* Remember how much we converted. */
127 do_write += newinbuf - inbuf;
128 *inlen -= (newinbuf - inbuf) * sizeof (wchar_t);
130 data->outbufavail += actually;
134 /* This is the last step. */
135 result = (*inlen < sizeof (wchar_t)
136 ? GCONV_EMPTY_INPUT : GCONV_FULL_OUTPUT);
141 result = GCONV_EMPTY_INPUT;
143 if (data->outbufavail > 0)
145 /* Call the functions below in the chain. */
146 size_t newavail = data->outbufavail;
148 result = (*fct) (next_step, next_data, data->outbuf, &newavail,
151 /* Correct the output buffer. */
152 if (newavail != data->outbufavail && newavail > 0)
154 memmove (data->outbuf,
155 &data->outbuf[data->outbufavail - newavail],
157 data->outbufavail = newavail;
161 while (*inlen > 0 && result == GCONV_EMPTY_INPUT);
164 if (written != NULL && data->is_last)
165 *written = do_write / sizeof (wchar_t);
172 __gconv_transform_utf8_ucs4 (struct gconv_step *step,
173 struct gconv_step_data *data, const char *inbuf,
174 size_t *inlen, size_t *written, int do_flush)
176 struct gconv_step *next_step = step + 1;
177 struct gconv_step_data *next_data = data + 1;
178 gconv_fct fct = next_step->fct;
182 /* If the function is called with no input this means we have to reset
183 to the initial state. The possibly partly converted input is
187 /* Clear the state. */
188 memset (data->data, '\0', sizeof (mbstate_t));
191 /* Call the steps down the chain if there are any. */
196 struct gconv_step *next_step = step + 1;
197 struct gconv_step_data *next_data = data + 1;
199 result = (*fct) (next_step, next_data, NULL, 0, written, 1);
208 const char *newinbuf = inbuf;
209 size_t actually = __wmemrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
214 (mbstate_t *) data->data);
216 /* Remember how much we converted. */
217 do_write += actually;
218 *inlen -= newinbuf - inbuf;
220 data->outbufavail += actually * sizeof (wchar_t);
224 /* This is the last step. */
225 result = (data->outbufavail + sizeof (wchar_t) > data->outbufsize
226 ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT);
231 result = GCONV_EMPTY_INPUT;
233 if (data->outbufavail > 0)
235 /* Call the functions below in the chain. */
236 size_t newavail = data->outbufavail;
238 result = (*fct) (next_step, next_data, data->outbuf, &newavail,
241 /* Correct the output buffer. */
242 if (newavail != data->outbufavail && newavail > 0)
244 memmove (data->outbuf,
245 &data->outbuf[data->outbufavail - newavail],
247 data->outbufavail = newavail;
251 while (*inlen > 0 && result == GCONV_EMPTY_INPUT);
254 if (written != NULL && data->is_last)