1/* Conversion to UTF-16/UTF-32 from legacy encodings. 2 Copyright (C) 2002, 2006-2007, 2009-2010 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify it 5 under the terms of the GNU Lesser General Public License as published 6 by the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17UNIT * 18FUNC (const char *fromcode, 19 enum iconv_ilseq_handler handler, 20 const char *src, size_t srclen, 21 size_t *offsets, 22 UNIT *resultbuf, size_t *lengthp) 23{ 24#if HAVE_UTF_NAME 25 char *result = (char *) resultbuf; 26 size_t length = *lengthp * sizeof (UNIT); 27 28 if (mem_iconveha (src, srclen, fromcode, UTF_NAME, true, handler, 29 offsets, &result, &length) < 0) 30 return NULL; 31 if (offsets != NULL) 32 { 33 /* Convert 'char *' offsets to 'UNIT *' offsets. */ 34 size_t *offsets_end = offsets + srclen; 35 size_t *o; 36 37 for (o = offsets; o < offsets_end; o++) 38 if (*o != (size_t)(-1)) 39 *o = *o / sizeof (UNIT); 40 } 41 if ((length % sizeof (UNIT)) != 0) 42 abort (); 43 *lengthp = length / sizeof (UNIT); 44 return (UNIT *) result; 45#else 46 uint8_t *utf8_string; 47 size_t utf8_length; 48 UNIT *result; 49 50 utf8_string = 51 u8_conv_from_encoding (fromcode, handler, src, srclen, offsets, 52 NULL, &utf8_length); 53 if (utf8_string == NULL) 54 return NULL; 55 result = U8_TO_U (utf8_string, utf8_length, resultbuf, lengthp); 56 if (result == NULL) 57 { 58 int saved_errno = errno; 59 free (utf8_string); 60 errno = saved_errno; 61 return NULL; 62 } 63 if (offsets != NULL) 64 { 65 size_t length = *lengthp; 66 size_t *offsets_end = offsets + srclen; 67 size_t *o; 68 size_t off8 = 0; /* offset into utf8_string */ 69 size_t offunit = 0; /* offset into result */ 70 71 for (o = offsets; o < offsets_end; o++) 72 if (*o != (size_t)(-1)) 73 { 74 while (off8 < *o) 75 { 76 int count8 = u8_mblen (utf8_string + off8, utf8_length - off8); 77 int countunit = U_MBLEN (result + offunit, length - offunit); 78 if (count8 < 0 || countunit < 0) 79 abort (); 80 off8 += count8; 81 offunit += countunit; 82 } 83 if (*o != off8) 84 abort (); 85 *o = offunit; 86 } 87 } 88 free (utf8_string); 89 return result; 90#endif 91} 92