New modules uniconv/u16-conv-from-enc and uniconv/u32-conv-from-enc.
[gnulib.git] / lib / uniconv / u-conv-from-enc.h
1 /* Conversion to UTF-16/UTF-32 from legacy encodings.
2    Copyright (C) 2002, 2006-2007 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 Library General Public License as published
6    by the Free Software Foundation; either version 2, or (at your option)
7    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    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17    USA.  */
18
19 int
20 FUNC (const char *fromcode,
21       enum iconv_ilseq_handler handler,
22       const char *src, size_t srclen,
23       size_t *offsets,
24       UNIT **resultp, size_t *lengthp)
25 {
26 #if HAVE_UTF_NAME
27   size_t length;
28
29   if (mem_iconveha (src, srclen, fromcode, UTF_NAME, true, handler,
30                     offsets, (char **) resultp, &length) < 0)
31     return -1;
32   if (offsets != NULL)
33     {
34       /* Convert 'char *' offsets to 'UNIT *' offsets.  */
35       size_t *offsets_end = offsets + srclen;
36       size_t *o;
37
38       for (o = offsets; o < offsets_end; o++)
39         if (*o != (size_t)(-1))
40           *o = *o / sizeof (UNIT);
41     }
42   if ((length % sizeof (UNIT)) != 0)
43     abort ();
44   *lengthp = length / sizeof (UNIT);
45   return 0;
46 #else
47   uint8_t *utf8_string = NULL;
48   size_t utf8_length = 0;
49   UNIT *result;
50
51   if (u8_conv_from_encoding (fromcode, handler, src, srclen, offsets,
52                              &utf8_string, &utf8_length) < 0)
53     return -1;
54   if (utf8_string == NULL)
55     {
56       *lengthp = 0;
57       return 0;
58     }
59   result = U8_TO_U (utf8_string, utf8_length, *resultp, lengthp);
60   if (result == NULL)
61     {
62       int saved_errno = errno;
63       free (utf8_string);
64       errno = saved_errno;
65       return -1;
66     }
67   if (offsets != NULL)
68     {
69       size_t length = *lengthp;
70       size_t *offsets_end = offsets + srclen;
71       size_t *o;
72       size_t off8 = 0;  /* offset into utf8_string */
73       size_t offunit = 0;       /* offset into result */
74
75       for (o = offsets; o < offsets_end; o++)
76         if (*o != (size_t)(-1))
77           {
78             while (off8 < *o)
79               {
80                 int count8 = u8_mblen (utf8_string + off8, utf8_length - off8);
81                 int countunit = U_MBLEN (result + offunit, length - offunit);
82                 if (count8 < 0 || countunit < 0)
83                   abort ();
84                 off8 += count8;
85                 offunit += countunit;
86               }
87             if (*o != off8)
88               abort ();
89             *o = offunit;
90           }
91     }
92   free (utf8_string);
93   *resultp = result;
94   return 0;
95 #endif
96 }