1 /* Generic conversion to and from 8bit charsets,
2    converting from UCS using gaps.
3    Copyright (C) 1997-2022 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5 
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the 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    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <https://www.gnu.org/licenses/>.  */
19 
20 #include <dlfcn.h>
21 #include <stdint.h>
22 
23 struct gap
24 {
25   uint16_t start;
26   uint16_t end;
27   int32_t idx;
28 };
29 
30 /* Now we can include the tables.  */
31 #include TABLES
32 
33 #ifndef NONNUL
34 # define NONNUL(c)	((c) != '\0')
35 #endif
36 
37 
38 #define FROM_LOOP		from_gap
39 #define TO_LOOP			to_gap
40 #define DEFINE_INIT		1
41 #define DEFINE_FINI		1
42 #define MIN_NEEDED_FROM		1
43 #define MIN_NEEDED_TO		4
44 #define ONE_DIRECTION		0
45 
46 
47 /* First define the conversion function from the 8bit charset to UCS4.  */
48 #define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
49 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
50 #define LOOPFCT			FROM_LOOP
51 #define BODY \
52   {									      \
53     uint32_t ch = to_ucs4[*inptr];					      \
54 									      \
55     if (HAS_HOLES && __builtin_expect (ch == L'\0', 0) && NONNUL (*inptr))    \
56       {									      \
57 	/* This is an illegal character.  */				      \
58 	STANDARD_FROM_LOOP_ERR_HANDLER (1);				      \
59       }									      \
60     else								      \
61       {									      \
62 	put32 (outptr, ch);						      \
63 	outptr += 4;							      \
64       }									      \
65 									      \
66     ++inptr;								      \
67   }
68 #define LOOP_NEED_FLAGS
69 #define ONEBYTE_BODY \
70   {									      \
71     uint32_t ch = to_ucs4[c];						      \
72 									      \
73     if (HAS_HOLES && __builtin_expect (ch == L'\0', 0) && NONNUL (c))	      \
74       return WEOF;							      \
75     else								      \
76       return ch;							      \
77   }
78 #include <iconv/loop.c>
79 
80 
81 /* Next, define the other direction.  */
82 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
83 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
84 #define LOOPFCT			TO_LOOP
85 #define BODY \
86   {									      \
87     const struct gap *rp = from_idx;					      \
88     uint32_t ch = get32 (inptr);					      \
89     unsigned char res;							      \
90 									      \
91     if (__glibc_unlikely (ch >= 0xffff))				      \
92       {									      \
93 	UNICODE_TAG_HANDLER (ch, 4);					      \
94 	rp = NULL;							      \
95       }									      \
96     else								      \
97       while (ch > rp->end)						      \
98 	++rp;								      \
99     if (__builtin_expect (rp == NULL, 0)				      \
100 	|| __builtin_expect (ch < rp->start, 0)				      \
101 	|| (res = from_ucs4[ch + rp->idx],				      \
102 	    __builtin_expect (res, '\1') == '\0' && ch != 0))		      \
103       {									      \
104 	/* This is an illegal character.  */				      \
105 	STANDARD_TO_LOOP_ERR_HANDLER (4);				      \
106       }									      \
107 									      \
108     *outptr++ = res;							      \
109     inptr += 4;								      \
110   }
111 #define LOOP_NEED_FLAGS
112 #include <iconv/loop.c>
113 
114 
115 /* Now define the toplevel functions.  */
116 #include <iconv/skeleton.c>
117