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 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 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 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 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 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