1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2000-2001 Boris Popov
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29
30 // Modified to support the Haiku FAT driver.
31
32 #include "sys/param.h"
33 #include "sys/systm.h"
34 #include "sys/cdefs.h"
35 #include "sys/malloc.h"
36 #include "sys/iconv.h"
37
38
39 int printf(const char* format, ...);
40
41
42 /*! Create an instance of a converter.
43
44 */
45 int
fat_iconv_open(const char * to,const char * from,void ** handle)46 fat_iconv_open(const char* to, const char* from, void** handle)
47 {
48 #ifdef USER
49 iconv_t descriptor = iconv_open(to, from);
50 if (descriptor == (iconv_t)(-1))
51 return errno;
52 *handle = descriptor;
53
54 return 0;
55 #else
56 return ENOTSUP;
57 #endif // !USER
58 }
59
60
61 int
fat_iconv_close(void * handle)62 fat_iconv_close(void* handle)
63 {
64 #ifdef USER
65 iconv_t* descriptor = (iconv_t*)handle;
66 int error = 0;
67
68 error = iconv_close(descriptor);
69
70 return error;
71 #else
72 return ENOTSUP;
73 #endif // !USER
74 }
75
76
77 int
iconv_conv(void * handle,const char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)78 iconv_conv(void* handle, const char** inbuf, size_t* inbytesleft, char** outbuf,
79 size_t* outbytesleft)
80 {
81 #ifdef USER
82 while (iconv(handle, __DECONST(char**, inbuf), inbytesleft, outbuf, outbytesleft) != (size_t)-1
83 && *inbytesleft > 0 && strlen(*inbuf) > 0)
84 ;
85
86 return 0;
87 #else
88 return ENOTSUP;
89 #endif // !USER
90 }
91
92
93 int
iconv_convchr(void * handle,const char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)94 iconv_convchr(void* handle, const char** inbuf, size_t* inbytesleft, char** outbuf,
95 size_t* outbytesleft)
96 {
97 #ifdef USER
98 int status = iconv(handle, __DECONST(char**, inbuf), inbytesleft, outbuf, outbytesleft);
99
100 return status;
101 #else
102 return ENOTSUP;
103 #endif // !USER
104 }
105
106
107 /*! Only those casetype values used by the FAT driver are implemented.
108
109 */
110 int
iconv_convchr_case(void * handle,const char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int casetype)111 iconv_convchr_case(void* handle, const char** inbuf, size_t* inbytesleft, char** outbuf,
112 size_t* outbytesleft, int casetype)
113 {
114 #ifdef USER
115 size_t status = 0;
116 int inbufAdvanced = 0;
117
118 if (casetype == KICONV_FROM_LOWER || casetype == KICONV_FROM_UPPER) {
119 char finalInbuf[4];
120 char* finalInbufPtr = finalInbuf;
121 int (*tocase)(int ch) = (casetype == KICONV_FROM_LOWER) ? tolower : toupper;
122
123 // The characters must be set to the indicated case before conversion.
124 // Since iconv only takes one char at a time, just set 1 (possibly multibyte)
125 // character, not the whole inbuf.
126 int i;
127 for (i = 0; i < 4; i++)
128 finalInbuf[i] = tocase((*inbuf)[i]);
129
130 status = iconv(handle, &finalInbufPtr, inbytesleft, outbuf, outbytesleft);
131 if (status == (size_t)(-1))
132 printf("FAT iconv_convchr_case: %s\n", strerror(errno));
133
134 // iconv has incremented finalInbufPtr instead of inbuf; update inbuf manually
135 inbufAdvanced = finalInbufPtr - finalInbuf;
136 *inbuf += inbufAdvanced;
137
138 return status;
139 }
140 if (casetype == KICONV_LOWER) {
141 status = iconv(handle, __DECONST(char**, inbuf), inbytesleft, outbuf, outbytesleft);
142 // Outbuf will be advanced one slot by iconv each time it's called.
143 // Just deal with the one char that is pointed to right now.
144 **outbuf = tolower(**outbuf);
145 return status;
146 }
147
148 printf("FAT iconv_convchr_case: unrecognized casetype\n");
149 return -1;
150 #else
151 return ENOTSUP;
152 #endif // !USER
153 }
154