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