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