xref: /haiku/src/system/libroot/posix/glibc/iconv/gconv_simple.c (revision 1026b0a1a76dc88927bb8175c470f638dc5464ee)
1 /* Simple transformations functions.
2    Copyright (C) 1997-2003, 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20 
21 #include <errno.h>
22 #include <gconv.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <wchar.h>
27 #include <gconv_int.h>
28 
29 #include <libroot/wchar_private.h>
30 
31 #define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, BtowcFct, \
32 			       MinF, MaxF, MinT, MaxT) \
33   extern int Fct (struct __gconv_step *, struct __gconv_step_data *,	      \
34 		  __const unsigned char **, __const unsigned char *,	      \
35 		  unsigned char **, size_t *, int, int);
36 #include "gconv_builtin.h"
37 
38 
39 /* Convert from ISO 646-IRV to the internal (UCS4-like) format.  */
40 #define DEFINE_INIT			0
41 #define DEFINE_FINI			0
42 #define MIN_NEEDED_FROM		1
43 #define MIN_NEEDED_TO		4
44 #define FROM_DIRECTION		1
45 #define FROM_LOOP			ascii_internal_loop
46 #define TO_LOOP				ascii_internal_loop /* This is not used.  */
47 #define FUNCTION_NAME		__gconv_transform_ascii_internal
48 #define ONE_DIRECTION		1
49 
50 #define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
51 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
52 #define LOOPFCT				FROM_LOOP
53 #define BODY																\
54 {																			\
55     if (__builtin_expect(*inptr > '\x7f', 0)) {								\
56 		/* The value is too large.  We don't try transliteration here since	\
57 		   this is not an error because of the lack of possibilities to		\
58 		   represent the result.  This is a genuine bug in the input since	\
59 		   ASCII does not allow such values.  */							\
60 		STANDARD_FROM_LOOP_ERR_HANDLER(1);									\
61     } else {																\
62     	/* It's an one byte sequence.  */									\
63 		*((uint32_t*)outptr) = *inptr++;									\
64 		outptr += sizeof(uint32_t);											\
65     }																		\
66 }
67 #define LOOP_NEED_FLAGS
68 #include <iconv/loop.c>
69 #include <iconv/skeleton.c>
70 
71 
72 /* Convert from the internal (UCS4-like) format to ISO 646-IRV.  */
73 #define DEFINE_INIT			0
74 #define DEFINE_FINI			0
75 #define MIN_NEEDED_FROM		4
76 #define MIN_NEEDED_TO		1
77 #define FROM_DIRECTION		1
78 #define FROM_LOOP			internal_ascii_loop
79 #define TO_LOOP				internal_ascii_loop /* This is not used.  */
80 #define FUNCTION_NAME		__gconv_transform_internal_ascii
81 #define ONE_DIRECTION		1
82 
83 #define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
84 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
85 #define LOOPFCT				FROM_LOOP
86 #define BODY																\
87 {																			\
88     if (__builtin_expect(*((const uint32_t*)inptr) > 0x7f, 0)) {			\
89 		UNICODE_TAG_HANDLER(*((const uint32_t*)inptr), 4);					\
90 		STANDARD_TO_LOOP_ERR_HANDLER(4);									\
91     } else {																\
92 		/* It's an one byte sequence.  */									\
93 		*outptr++ = *((const uint32_t*)inptr);								\
94 		inptr += sizeof(uint32_t);											\
95     }																		\
96 }
97 #define LOOP_NEED_FLAGS
98 #include <iconv/loop.c>
99 #include <iconv/skeleton.c>
100 
101 
102 /* Convert from multibyte to wchar_t format.  */
103 #define DEFINE_INIT			0
104 #define DEFINE_FINI			0
105 #define MIN_NEEDED_FROM		1
106 #define MAX_NEEDED_FROM		MB_LEN_MAX
107 #define MIN_NEEDED_TO		4
108 #define MAX_NEEDED_TO		4
109 #define FROM_DIRECTION		1
110 #define FROM_LOOP			multibyte_wchar_loop
111 #define TO_LOOP				multibyte_wchar_loop /* This is not used.  */
112 #define FUNCTION_NAME		__gconv_transform_multibyte_wchar
113 #define ONE_DIRECTION		1
114 
115 #define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
116 #define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
117 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
118 #define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
119 #define LOOPFCT				FROM_LOOP
120 #define BODY \
121 {									      									\
122 	size_t inLen = inend - inptr;											\
123 	mbstate_t *state = step_data->__statep;									\
124 	size_t result 															\
125 		= __mbrtowc((wchar_t*)outptr, (const char*)inptr, inLen, state);	\
126 	if (result == (size_t)-1) {									      		\
127 		/* illegal character, skip it */									\
128 		STANDARD_FROM_LOOP_ERR_HANDLER(1);									\
129 	} else if (result == (size_t)-2) {										\
130 		/* input too short, do nothing */									\
131 	} else if (result == 0) {												\
132 		/* termination character found */									\
133 		outptr += sizeof(wchar_t);											\
134 		++inptr;															\
135 	} else {																\
136 		/* a character has been converted */								\
137 		inptr += result;													\
138 		outptr += sizeof(wchar_t);											\
139 	}																		\
140 }
141 #define LOOP_NEED_FLAGS
142 #include <iconv/loop.c>
143 #include <iconv/skeleton.c>
144 
145 
146 /* Convert from wchar_t to multibyte format.  */
147 #define DEFINE_INIT			0
148 #define DEFINE_FINI			0
149 #define MIN_NEEDED_FROM		4
150 #define MAX_NEEDED_FROM		4
151 #define MIN_NEEDED_TO		MB_LEN_MAX
152 #define MAX_NEEDED_TO		MB_LEN_MAX
153 #define FROM_DIRECTION		1
154 #define FROM_LOOP			wchar_multibyte_loop
155 #define TO_LOOP				wchar_multibyte_loop /* This is not used.  */
156 #define FUNCTION_NAME		__gconv_transform_wchar_multibyte
157 #define ONE_DIRECTION		1
158 
159 #define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
160 #define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
161 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
162 #define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
163 #define LOOPFCT				FROM_LOOP
164 #define BODY \
165 {									      									\
166 	mbstate_t *state = step_data->__statep;									\
167 	size_t result = __wcrtomb((char*)outptr, *(wchar_t*)inptr, state);		\
168 	if (result == (size_t)-1) {									      		\
169 		/* illegal character, skip it */									\
170 		STANDARD_TO_LOOP_ERR_HANDLER(sizeof(wchar_t));						\
171 	} else if (result == 0) {												\
172 		/* termination character found */									\
173 		inptr += sizeof(wchar_t);											\
174 		++outptr;															\
175 	} else {																\
176 		/* a character has been converted */								\
177 		outptr += result;													\
178 		inptr += sizeof(wchar_t);											\
179 	}																		\
180 }
181 #define LOOP_NEED_FLAGS
182 #include <iconv/loop.c>
183 #include <iconv/skeleton.c>
184