]> sourceware.org Git - glibc.git/blame - iconv/loop.c
Update.
[glibc.git] / iconv / loop.c
CommitLineData
8619129f 1/* Conversion loop frame work.
63e04088 2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
8619129f
UD
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
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.
10
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.
15
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. */
20
21/* This file provides a frame for the reader loop in all conversion modules.
22 The actual code must (of course) be provided in the actual module source
23 code but certain actions can be written down generically, with some
24 customization options which are these:
25
26 MIN_NEEDED_INPUT minimal number of input bytes needed for the next
27 conversion.
28 MIN_NEEDED_OUTPUT minimal number of bytes produced by the next round
29 of conversion.
30
31 MAX_NEEDED_INPUT you guess it, this is the maximal number of input
32 bytes needed. It defaults to MIN_NEEDED_INPUT
33 MAX_NEEDED_OUTPUT likewise for output bytes.
34
8619129f
UD
35 LOOPFCT name of the function created. If not specified
36 the name is `loop' but this prevents the use
37 of multiple functions in the same file.
38
8619129f
UD
39 BODY this is supposed to expand to the body of the loop.
40 The user must provide this.
28f1c862 41
66175fa8
UD
42 EXTRA_LOOP_DECLS extra arguments passed from converion loop call.
43
44 INIT_PARAMS code to define and initialize variables from params.
45 UPDATE_PARAMS code to store result in params.
8619129f
UD
46*/
47
fd1b5c0f 48#include <assert.h>
b35e58e4 49#include <endian.h>
8619129f 50#include <gconv.h>
b35e58e4
UD
51#include <stdint.h>
52#include <string.h>
d64b6ad0 53#include <wchar.h>
8619129f
UD
54#include <sys/param.h> /* For MIN. */
55#define __need_size_t
56#include <stddef.h>
57
58
b35e58e4
UD
59/* We have to provide support for machines which are not able to handled
60 unaligned memory accesses. Some of the character encodings have
61 representations with a fixed width of 2 or 4 bytes. But if we cannot
62 access unaligned memory we still have to read byte-wise. */
63#undef FCTNAME2
64#if defined _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
65/* We can handle unaligned memory access. */
66# define get16(addr) *((uint16_t *) (addr))
67# define get32(addr) *((uint32_t *) (addr))
68
69/* We need no special support for writing values either. */
70# define put16(addr, val) *((uint16_t *) (addr)) = (val)
71# define put32(addr, val) *((uint32_t *) (addr)) = (val)
72
73# define FCTNAME2(name) name
74#else
75/* Distinguish between big endian and little endian. */
76# if __BYTE_ORDER == __LITTLE_ENDIAN
77# define get16(addr) \
78 (((__const unsigned char *) (addr))[1] << 8 \
79 | ((__const unsigned char *) (addr))[0])
80# define get32(addr) \
81 (((((__const unsigned char *) (addr))[3] << 8 \
82 | ((__const unsigned char *) (addr))[2]) << 8 \
83 | ((__const unsigned char *) (addr))[1]) << 8 \
84 | ((__const unsigned char *) (addr))[0])
85
cb2c5501 86# define put16(addr, val) \
b35e58e4 87 ({ uint16_t __val = (val); \
cb2c5501
UD
88 ((unsigned char *) (addr))[0] = __val; \
89 ((unsigned char *) (addr))[1] = __val >> 8; \
b35e58e4 90 (void) 0; })
cb2c5501
UD
91# define put32(addr, val) \
92 ({ uint32_t __val = (val); \
93 ((unsigned char *) (addr))[0] = __val; \
b35e58e4 94 __val >>= 8; \
cb2c5501 95 ((unsigned char *) (addr))[1] = __val; \
b35e58e4 96 __val >>= 8; \
cb2c5501 97 ((unsigned char *) (addr))[2] = __val; \
b35e58e4 98 __val >>= 8; \
cb2c5501 99 ((unsigned char *) (addr))[3] = __val; \
b35e58e4
UD
100 (void) 0; })
101# else
102# define get16(addr) \
103 (((__const unsigned char *) (addr))[0] << 8 \
104 | ((__const unsigned char *) (addr))[1])
105# define get32(addr) \
106 (((((__const unsigned char *) (addr))[0] << 8 \
107 | ((__const unsigned char *) (addr))[1]) << 8 \
108 | ((__const unsigned char *) (addr))[2]) << 8 \
109 | ((__const unsigned char *) (addr))[3])
110
cb2c5501 111# define put16(addr, val) \
b35e58e4 112 ({ uint16_t __val = (val); \
cb2c5501
UD
113 ((unsigned char *) (addr))[1] = __val; \
114 ((unsigned char *) (addr))[2] = __val >> 8; \
b35e58e4 115 (void) 0; })
cb2c5501
UD
116# define put32(addr, val) \
117 ({ uint32_t __val = (val); \
118 ((unsigned char *) (addr))[3] = __val; \
b35e58e4 119 __val >>= 8; \
cb2c5501 120 ((unsigned char *) (addr))[2] = __val; \
b35e58e4 121 __val >>= 8; \
cb2c5501 122 ((unsigned char *) (addr))[1] = __val; \
b35e58e4 123 __val >>= 8; \
cb2c5501 124 ((unsigned char *) (addr))[0] = __val; \
b35e58e4
UD
125 (void) 0; })
126# endif
127
128# define FCTNAME2(name) name##_unaligned
129#endif
130#define FCTNAME(name) FCTNAME2(name)
131
132
8619129f
UD
133/* We need at least one byte for the next round. */
134#ifndef MIN_NEEDED_INPUT
5aa8ff62 135# error "MIN_NEEDED_INPUT definition missing"
8619129f
UD
136#endif
137
138/* Let's see how many bytes we produce. */
139#ifndef MAX_NEEDED_INPUT
140# define MAX_NEEDED_INPUT MIN_NEEDED_INPUT
141#endif
142
143/* We produce at least one byte in the next round. */
144#ifndef MIN_NEEDED_OUTPUT
5aa8ff62 145# error "MIN_NEEDED_OUTPUT definition missing"
8619129f
UD
146#endif
147
148/* Let's see how many bytes we produce. */
149#ifndef MAX_NEEDED_OUTPUT
150# define MAX_NEEDED_OUTPUT MIN_NEEDED_OUTPUT
151#endif
152
153/* Default name for the function. */
154#ifndef LOOPFCT
155# define LOOPFCT loop
156#endif
157
158/* Make sure we have a loop body. */
159#ifndef BODY
160# error "Definition of BODY missing for function" LOOPFCT
161#endif
162
8619129f 163
28f1c862
UD
164/* If no arguments have to passed to the loop function define the macro
165 as empty. */
166#ifndef EXTRA_LOOP_DECLS
167# define EXTRA_LOOP_DECLS
168#endif
169
170
85830c4c
UD
171/* To make it easier for the writers of the modules, we define a macro
172 to test whether we have to ignore errors. */
173#define ignore_errors_p() (flags & __GCONV_IGNORE_ERRORS)
174
175
d6204268
UD
176/* Error handling with transliteration/transcription function use and
177 ignoring of errors. Note that we cannot use the do while (0) trick
178 since `break' and `continue' must reach certain points. */
179#define STANDARD_ERR_HANDLER(Incr) \
180 { \
181 struct __gconv_trans_data *trans; \
182 \
183 result = __GCONV_ILLEGAL_INPUT; \
184 /* First try the transliteration methods. */ \
185 for (trans = step_data->__trans; trans != NULL; trans = trans->__next) \
186 { \
187 result = DL_CALL_FCT (trans->__trans_fct, \
188 (step, step_data, trans->__data, *inptrp, \
189 &inptr, inend, &outptr, irreversible)); \
190 if (result != __GCONV_ILLEGAL_INPUT) \
191 break; \
192 } \
7888313d 193 /* If any of them recognized the input continue with the loop. */ \
d6204268 194 if (result != __GCONV_ILLEGAL_INPUT) \
7888313d 195 continue; \
d6204268
UD
196 \
197 /* Next see whether we have to ignore the error. If not, stop. */ \
198 if (! ignore_errors_p ()) \
199 break; \
200 \
201 /* When we come here it means we ignore the character. */ \
202 ++*irreversible; \
203 inptr += Incr; \
204 continue; \
205 }
206
207
8619129f
UD
208/* The function returns the status, as defined in gconv.h. */
209static inline int
55985355
UD
210FCTNAME (LOOPFCT) (struct __gconv_step *step,
211 struct __gconv_step_data *step_data,
212 const unsigned char **inptrp, const unsigned char *inend,
b35e58e4 213 unsigned char **outptrp, unsigned char *outend,
38677ace 214 size_t *irreversible EXTRA_LOOP_DECLS)
8619129f 215{
55985355
UD
216#ifdef LOOP_NEED_STATE
217 mbstate_t *state = step_data->__statep;
218#endif
219#ifdef LOOP_NEED_FLAGS
220 int flags = step_data->__flags;
221#endif
222#ifdef LOOP_NEED_DATA
223 void *data = step->__data;
224#endif
225 int result = __GCONV_EMPTY_INPUT;
8619129f
UD
226 const unsigned char *inptr = *inptrp;
227 unsigned char *outptr = *outptrp;
8619129f 228
66175fa8
UD
229#ifdef INIT_PARAMS
230 INIT_PARAMS;
231#endif
232
55985355 233 while (inptr != inend)
8619129f 234 {
55985355 235 /* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the
ca3c0135 236 compiler generating better code. They will be optimized away
55985355
UD
237 since MIN_NEEDED_OUTPUT is always a constant. */
238 if ((MIN_NEEDED_OUTPUT != 1
239 && __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
240 || (MIN_NEEDED_OUTPUT == 1
241 && __builtin_expect (outptr >= outend, 0)))
242 {
243 /* Overflow in the output buffer. */
244 result = __GCONV_FULL_OUTPUT;
245 break;
246 }
247 if (MIN_NEEDED_INPUT > 1
248 && __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
8619129f 249 {
55985355
UD
250 /* We don't have enough input for another complete input
251 character. */
252 result = __GCONV_INCOMPLETE_INPUT;
253 break;
8619129f 254 }
55985355
UD
255
256 /* Here comes the body the user provides. It can stop with
257 RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the
258 input characters vary in size), GCONV_ILLEGAL_INPUT, or
259 GCONV_FULL_OUTPUT (if the output characters vary in size). */
260 BODY
8619129f
UD
261 }
262
8619129f
UD
263 /* Update the pointers pointed to by the parameters. */
264 *inptrp = inptr;
265 *outptrp = outptr;
66175fa8
UD
266#ifdef UPDATE_PARAMS
267 UPDATE_PARAMS;
268#endif
8619129f
UD
269
270 return result;
271}
272
273
b02b4774
UD
274/* Include the file a second time to define the function to handle
275 unaligned access. */
fdf64555
UD
276#if !defined DEFINE_UNALIGNED && !defined _STRING_ARCH_unaligned \
277 && MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
278 && MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
fd1b5c0f
UD
279# undef get16
280# undef get32
281# undef put16
282# undef put32
283# undef unaligned
284
b35e58e4
UD
285# define DEFINE_UNALIGNED
286# include "loop.c"
287# undef DEFINE_UNALIGNED
288#endif
289
290
fd1b5c0f
UD
291#if MAX_NEEDED_INPUT > 1
292# define SINGLE(fct) SINGLE2 (fct)
293# define SINGLE2(fct) fct##_single
294static inline int
55985355
UD
295SINGLE(LOOPFCT) (struct __gconv_step *step,
296 struct __gconv_step_data *step_data,
297 const unsigned char **inptrp, const unsigned char *inend,
fd1b5c0f 298 unsigned char **outptrp, unsigned char *outend,
55985355 299 size_t *irreversible EXTRA_LOOP_DECLS)
fd1b5c0f 300{
55985355
UD
301 mbstate_t *state = step_data->__statep;
302#ifdef LOOP_NEED_FLAGS
303 int flags = step_data->__flags;
304#endif
305#ifdef LOOP_NEED_DATA
306 void *data = step->__data;
307#endif
fd1b5c0f
UD
308 int result = __GCONV_OK;
309 unsigned char bytebuf[MAX_NEEDED_INPUT];
310 const unsigned char *inptr = *inptrp;
311 unsigned char *outptr = *outptrp;
312 size_t inlen;
313
314#ifdef INIT_PARAMS
315 INIT_PARAMS;
316#endif
317
318#ifdef UNPACK_BYTES
319 UNPACK_BYTES
320#else
321 /* Add the bytes from the state to the input buffer. */
322 for (inlen = 0; inlen < (state->__count & 7); ++ inlen)
323 bytebuf[inlen] = state->__value.__wchb[inlen];
324#endif
325
326 /* Are there enough bytes in the input buffer? */
316518d6 327 if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
fd1b5c0f 328 {
fd1b5c0f 329 *inptrp = inend;
316518d6 330#ifdef STORE_REST
fd1b5c0f
UD
331 inptr = bytebuf;
332 inptrp = &inptr;
333 inend = &bytebuf[inlen];
334
335 STORE_REST
336#else
337 /* We don't have enough input for another complete input
338 character. */
339 while (inptr < inend)
340 state->__value.__wchb[inlen++] = *inptr++;
341#endif
342
343 return __GCONV_INCOMPLETE_INPUT;
344 }
345
346 /* Enough space in output buffer. */
347 if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
348 || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
349 /* Overflow in the output buffer. */
350 return __GCONV_FULL_OUTPUT;
351
352 /* Now add characters from the normal input buffer. */
353 do
354 bytebuf[inlen++] = *inptr++;
316518d6 355 while (inlen < MAX_NEEDED_INPUT && inptr < inend);
fd1b5c0f
UD
356
357 inptr = bytebuf;
316518d6 358 inend = &bytebuf[inlen];
55985355 359
fd1b5c0f
UD
360 do
361 {
362 BODY
363 }
364 while (0);
365
316518d6
UD
366 /* Now we either have produced an output character and consumed all the
367 bytes from the state and at least one more, or the character is still
368 incomplete, or we have some other error (like illegal input character,
369 no space in output buffer). */
5ea1a82d 370 if (__builtin_expect (inptr != bytebuf, 1))
fd1b5c0f 371 {
316518d6 372 /* We found a new character. */
fd1b5c0f
UD
373 assert (inptr - bytebuf > (state->__count & 7));
374
375 *inptrp += inptr - bytebuf - (state->__count & 7);
376 *outptrp = outptr;
377
316518d6
UD
378 result = __GCONV_OK;
379
fd1b5c0f
UD
380 /* Clear the state buffer. */
381 state->__count &= ~7;
382 }
316518d6
UD
383 else if (result == __GCONV_INCOMPLETE_INPUT)
384 {
385 /* This can only happen if we have less than MAX_NEEDED_INPUT bytes
386 available. */
387 assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
388
389 *inptrp += inend - bytebuf - (state->__count & 7);
390#ifdef STORE_REST
391 inptrp = &inptr;
392
393 STORE_REST
394#else
395 /* We don't have enough input for another complete input
396 character. */
397 while (inptr < inend)
398 state->__value.__wchb[inlen++] = *inptr++;
399#endif
400 }
fd1b5c0f
UD
401
402 return result;
403}
404# undef SINGLE
405# undef SINGLE2
406#endif
407
408
8619129f
UD
409/* We remove the macro definitions so that we can include this file again
410 for the definition of another function. */
411#undef MIN_NEEDED_INPUT
412#undef MAX_NEEDED_INPUT
413#undef MIN_NEEDED_OUTPUT
414#undef MAX_NEEDED_OUTPUT
415#undef LOOPFCT
8619129f
UD
416#undef BODY
417#undef LOOPFCT
28f1c862 418#undef EXTRA_LOOP_DECLS
66175fa8
UD
419#undef INIT_PARAMS
420#undef UPDATE_PARAMS
55985355
UD
421#undef UNPACK_BYTES
422#undef LOOP_NEED_STATE
423#undef LOOP_NEED_FLAGS
424#undef LOOP_NEED_DATA
fd1b5c0f
UD
425#undef get16
426#undef get32
427#undef put16
428#undef put32
429#undef unaligned
This page took 0.133866 seconds and 5 git commands to generate.