]> git.sesse.net Git - vlc/blob - src/extras/libc.c
direct3d11: implement the pixel format fallback
[vlc] / src / extras / libc.c
1 /*****************************************************************************
2  * libc.c: Extra libc function for some systems.
3  *****************************************************************************
4  * Copyright (C) 2002-2006 VLC authors and VideoLAN
5  *
6  * Authors: Gildas Bazin <gbazin@videolan.org>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <vlc_common.h>
27 #include <vlc_charset.h>
28
29 #include <errno.h>
30
31 #undef iconv_t
32 #undef iconv_open
33 #undef iconv
34 #undef iconv_close
35
36 #if defined(HAVE_ICONV)
37 #   include <iconv.h>
38 #endif
39
40 #if defined(__OS2__) && defined(__INNOTEK_LIBC__)
41 #   include <uconv.h>
42
43 typedef struct os2_iconv_t
44 {
45     UconvObject from;
46 } os2_iconv_t;
47 #endif
48
49 /*****************************************************************************
50  * Local conversion routine from ISO_6937 to UTF-8 charset. Support for this
51  * is still missing in libiconv, hence multiple operating systems lack it.
52  * The conversion table adds Euro sign (0xA4) as per ETSI EN 300 468 Annex A
53  *****************************************************************************/
54 #ifndef __linux__
55 static const uint16_t to_ucs4[128] =
56 {
57   /* 0x80 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
58   /* 0x88 */ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
59   /* 0x90 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
60   /* 0x98 */ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
61   /* 0xa0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0000, 0x00a7,
62   /* 0xa8 */ 0x00a4, 0x2018, 0x201c, 0x00ab, 0x2190, 0x2191, 0x2192, 0x2193,
63   /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00d7, 0x00b5, 0x00b6, 0x00b7,
64   /* 0xb8 */ 0x00f7, 0x2019, 0x201d, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
65   /* 0xc0 */ 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
66   /* 0xc8 */ 0xffff, 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff,
67   /* 0xd0 */ 0x2014, 0x00b9, 0x00ae, 0x00a9, 0x2122, 0x266a, 0x00ac, 0x00a6,
68   /* 0xd8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e,
69   /* 0xe0 */ 0x2126, 0x00c6, 0x00d0, 0x00aa, 0x0126, 0x0000, 0x0132, 0x013f,
70   /* 0xe8 */ 0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166, 0x014a, 0x0149,
71   /* 0xf0 */ 0x0138, 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0140,
72   /* 0xf8 */ 0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b, 0x00ad
73 };
74
75 /* The outer array range runs from 0xc1 to 0xcf, the inner range from 0x40
76    to 0x7f.  */
77 static const uint16_t to_ucs4_comb[15][64] =
78 {
79   /* 0xc1 */
80   {
81     /* 0x40 */ 0x0000, 0x00c0, 0x0000, 0x0000, 0x0000, 0x00c8, 0x0000, 0x0000,
82     /* 0x48 */ 0x0000, 0x00cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d2,
83     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d9, 0x0000, 0x0000,
84     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
85     /* 0x60 */ 0x0000, 0x00e0, 0x0000, 0x0000, 0x0000, 0x00e8, 0x0000, 0x0000,
86     /* 0x68 */ 0x0000, 0x00ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f2,
87     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f9, 0x0000, 0x0000,
88     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
89   },
90   /* 0xc2 */
91   {
92     /* 0x40 */ 0x0000, 0x00c1, 0x0000, 0x0106, 0x0000, 0x00c9, 0x0000, 0x0000,
93     /* 0x48 */ 0x0000, 0x00cd, 0x0000, 0x0000, 0x0139, 0x0000, 0x0143, 0x00d3,
94     /* 0x50 */ 0x0000, 0x0000, 0x0154, 0x015a, 0x0000, 0x00da, 0x0000, 0x0000,
95     /* 0x58 */ 0x0000, 0x00dd, 0x0179, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
96     /* 0x60 */ 0x0000, 0x00e1, 0x0000, 0x0107, 0x0000, 0x00e9, 0x0000, 0x0000,
97     /* 0x68 */ 0x0000, 0x00ed, 0x0000, 0x0000, 0x013a, 0x0000, 0x0144, 0x00f3,
98     /* 0x70 */ 0x0000, 0x0000, 0x0155, 0x015b, 0x0000, 0x00fa, 0x0000, 0x0000,
99     /* 0x78 */ 0x0000, 0x00fd, 0x017a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
100   },
101   /* 0xc3 */
102   {
103     /* 0x40 */ 0x0000, 0x00c2, 0x0000, 0x0108, 0x0000, 0x00ca, 0x0000, 0x011c,
104     /* 0x48 */ 0x0124, 0x00ce, 0x0134, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d4,
105     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x015c, 0x0000, 0x00db, 0x0000, 0x0174,
106     /* 0x58 */ 0x0000, 0x0176, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
107     /* 0x60 */ 0x0000, 0x00e2, 0x0000, 0x0109, 0x0000, 0x00ea, 0x0000, 0x011d,
108     /* 0x68 */ 0x0125, 0x00ee, 0x0135, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f4,
109     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x015d, 0x0000, 0x00fb, 0x0000, 0x0175,
110     /* 0x78 */ 0x0000, 0x0177, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
111   },
112   /* 0xc4 */
113   {
114     /* 0x40 */ 0x0000, 0x00c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
115     /* 0x48 */ 0x0000, 0x0128, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d1, 0x00d5,
116     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0168, 0x0000, 0x0000,
117     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
118     /* 0x60 */ 0x0000, 0x00e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
119     /* 0x68 */ 0x0000, 0x0129, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f1, 0x00f5,
120     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0169, 0x0000, 0x0000,
121     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
122   },
123   /* 0xc5 */
124   {
125     /* 0x40 */ 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0112, 0x0000, 0x0000,
126     /* 0x48 */ 0x0000, 0x012a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x014c,
127     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016a, 0x0000, 0x0000,
128     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
129     /* 0x60 */ 0x0000, 0x0101, 0x0000, 0x0000, 0x0000, 0x0113, 0x0000, 0x0000,
130     /* 0x68 */ 0x0000, 0x012b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x014d,
131     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016b, 0x0000, 0x0000,
132     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
133   },
134   /* 0xc6 */
135   {
136     /* 0x40 */ 0x0000, 0x0102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x011e,
137     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
138     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x0000, 0x0000,
139     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
140     /* 0x60 */ 0x0000, 0x0103, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x011f,
141     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
142     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x0000, 0x0000,
143     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
144   },
145   /* 0xc7 */
146   {
147     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x010a, 0x0000, 0x0116, 0x0000, 0x0120,
148     /* 0x48 */ 0x0000, 0x0130, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
149     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
150     /* 0x58 */ 0x0000, 0x0000, 0x017b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
151     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x010b, 0x0000, 0x0117, 0x0000, 0x0121,
152     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
153     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
154     /* 0x78 */ 0x0000, 0x0000, 0x017c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
155   },
156   /* 0xc8 */
157   {
158     /* 0x40 */ 0x0000, 0x00c4, 0x0000, 0x0000, 0x0000, 0x00cb, 0x0000, 0x0000,
159     /* 0x48 */ 0x0000, 0x00cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d6,
160     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00dc, 0x0000, 0x0000,
161     /* 0x58 */ 0x0000, 0x0178, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
162     /* 0x60 */ 0x0000, 0x00e4, 0x0000, 0x0000, 0x0000, 0x00eb, 0x0000, 0x0000,
163     /* 0x68 */ 0x0000, 0x00ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f6,
164     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00fc, 0x0000, 0x0000,
165     /* 0x78 */ 0x0000, 0x00ff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
166   },
167   /* 0xc9 */
168   {
169     0x0000,
170   },
171   /* 0xca */
172   {
173     /* 0x40 */ 0x0000, 0x00c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
174     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
175     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016e, 0x0000, 0x0000,
176     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
177     /* 0x60 */ 0x0000, 0x00e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
178     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
179     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016f, 0x0000, 0x0000,
180     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
181   },
182   /* 0xcb */
183   {
184     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x00c7, 0x0000, 0x0000, 0x0000, 0x0122,
185     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0136, 0x013b, 0x0000, 0x0145, 0x0000,
186     /* 0x50 */ 0x0000, 0x0000, 0x0156, 0x015e, 0x0162, 0x0000, 0x0000, 0x0000,
187     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
188     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x00e7, 0x0000, 0x0000, 0x0000, 0x0123,
189     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0137, 0x013c, 0x0000, 0x0146, 0x0000,
190     /* 0x70 */ 0x0000, 0x0000, 0x0157, 0x015f, 0x0163, 0x0000, 0x0000, 0x0000,
191     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
192   },
193   /* 0xcc */
194   {
195     0x0000,
196   },
197   /* 0xcd */
198   {
199     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
200     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0150,
201     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0170, 0x0000, 0x0000,
202     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
203     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
204     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0151,
205     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0171, 0x0000, 0x0000,
206     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
207   },
208   /* 0xce */
209   {
210     /* 0x40 */ 0x0000, 0x0104, 0x0000, 0x0000, 0x0000, 0x0118, 0x0000, 0x0000,
211     /* 0x48 */ 0x0000, 0x012e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
212     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0172, 0x0000, 0x0000,
213     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
214     /* 0x60 */ 0x0000, 0x0105, 0x0000, 0x0000, 0x0000, 0x0119, 0x0000, 0x0000,
215     /* 0x68 */ 0x0000, 0x012f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
216     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0173, 0x0000, 0x0000,
217     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
218   },
219   /* 0xcf */
220   {
221     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x010c, 0x010e, 0x011a, 0x0000, 0x0000,
222     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x013d, 0x0000, 0x0147, 0x0000,
223     /* 0x50 */ 0x0000, 0x0000, 0x0158, 0x0160, 0x0164, 0x0000, 0x0000, 0x0000,
224     /* 0x58 */ 0x0000, 0x0000, 0x017d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
225     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x010d, 0x010f, 0x011b, 0x0000, 0x0000,
226     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x013e, 0x0000, 0x0148, 0x0000,
227     /* 0x70 */ 0x0000, 0x0000, 0x0159, 0x0161, 0x0165, 0x0000, 0x0000, 0x0000,
228     /* 0x78 */ 0x0000, 0x0000, 0x017e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
229   }
230 };
231
232 static size_t ISO6937toUTF8( const unsigned char **inbuf, size_t *inbytesleft,
233                              unsigned char **outbuf, size_t *outbytesleft )
234
235
236 {
237     if( !inbuf || !(*inbuf) )
238         return (size_t)(0);    /* Reset state requested */
239
240     const unsigned char *iptr = *inbuf;
241     const unsigned char *iend = iptr + *inbytesleft;
242     unsigned char *optr = *outbuf;
243     unsigned char *oend = optr + *outbytesleft;
244     uint16_t ch;
245     int err = 0;
246
247     while ( iptr < iend )
248     {
249         if( *iptr < 0x80 )
250         {
251             if( optr >= oend )
252             {
253                 err = E2BIG;
254                 break;    /* No space in outbuf */
255             }
256             *optr++ = *iptr++;
257             continue;
258         }
259
260
261         if ( optr + 2 >= oend )
262         {
263             err = E2BIG;
264             break;        /* No space in outbuf for multibyte char */
265         }
266
267         ch = to_ucs4[*iptr - 0x80];
268
269         if( ch == 0xffff )
270         {
271             /* Composed character */
272             if ( iptr + 1 >= iend )
273             {
274                 err = EINVAL;
275                 break;    /* No next character */
276             }
277             if ( iptr[1] < 0x40 || iptr[1] >= 0x80 ||
278                  !(ch = to_ucs4_comb[iptr[0] - 0xc1][iptr[1] - 0x40]) )
279             {
280                 err = EILSEQ;
281                 break;   /* Illegal combination */
282             }
283             iptr += 2;
284
285         }
286         else
287         {
288             if ( !ch )
289             {
290                 err = EILSEQ;
291                 break;
292             }
293             iptr++;
294         }
295
296         if ( ch < 0x800 )
297         {
298             optr[1] = 0x80 | (ch & 0x3f);
299             optr[0] = 0xc0 | (ch >> 6);
300             optr +=2;
301         }
302         else
303         {
304             optr[2] = 0x80 | (ch & 0x3f);
305             ch >>= 6;
306             optr[1] = 0x80 | (ch & 0x3f);
307             optr[0] = 0xe0 | (ch >> 6);
308             optr += 3;
309         }
310
311     }
312     *inbuf = iptr;
313     *outbuf = optr;
314     *inbytesleft = iend - iptr;
315     *outbytesleft = oend - optr;
316
317     if( err )
318     {
319         errno = err;
320         return (size_t)(-1);
321     }
322
323     return (size_t)(0);
324
325 }
326 #endif
327
328 /*****************************************************************************
329  * iconv wrapper
330  *****************************************************************************/
331 vlc_iconv_t vlc_iconv_open( const char *tocode, const char *fromcode )
332 {
333 #ifndef __linux__
334     if( !strcasecmp(tocode, "UTF-8") && !strcasecmp(fromcode, "ISO_6937") )
335         return (vlc_iconv_t)(-2);
336 #endif
337 #if defined(HAVE_ICONV)
338 # if defined(__OS2__) && defined(__INNOTEK_LIBC__)
339     char tocode_ucs2[] = "UCS-2LE";
340     char fromcode_ucs2[] = "UCS-2LE";
341     os2_iconv_t *p_os2_iconv;
342
343     /* Workaround for UTF-16 because OS/2 supports UCS-2 only not UTF-16 */
344     if( !strncmp( tocode, "UTF-16", 6 ))
345     {
346         strncpy( tocode_ucs2 + 5, tocode + 6, 2 );
347         tocode = tocode_ucs2;
348     }
349
350     if( !strncmp( fromcode, "UTF-16", 6 ))
351     {
352         strncpy( fromcode_ucs2 + 5, fromcode + 6, 2 );
353         fromcode = fromcode_ucs2;
354     }
355
356     p_os2_iconv = ( os2_iconv_t * )iconv_open( tocode, fromcode );
357
358     if( p_os2_iconv != ( iconv_t )(-1))
359     {
360         /* Mimic a behavior of GNU libiconv */
361         uconv_attribute_t attr;
362
363         UniQueryUconvObject( p_os2_iconv->from, &attr,
364                              sizeof( uconv_attribute_t ),
365                              NULL, NULL, NULL );
366         attr.converttype |= CVTTYPE_PATH;
367         UniSetUconvObject( p_os2_iconv->from, &attr );
368     }
369
370     return ( vlc_iconv_t )p_os2_iconv;
371 # else
372     return iconv_open( tocode, fromcode );
373 # endif
374 #else
375     return (vlc_iconv_t)(-1);
376 #endif
377 }
378
379 size_t vlc_iconv( vlc_iconv_t cd, const char **inbuf, size_t *inbytesleft,
380                   char **outbuf, size_t *outbytesleft )
381 {
382 #ifndef __linux__
383     if ( cd == (vlc_iconv_t)(-2) )
384         return ISO6937toUTF8( (const unsigned char **)inbuf, inbytesleft,
385                               (unsigned char **)outbuf, outbytesleft );
386 #endif
387 #if defined(HAVE_ICONV)
388     return iconv( cd, (ICONV_CONST char **)inbuf, inbytesleft,
389                   outbuf, outbytesleft );
390 #else
391     abort ();
392 #endif
393 }
394
395 int vlc_iconv_close( vlc_iconv_t cd )
396 {
397 #ifndef __linux__
398     if ( cd == (vlc_iconv_t)(-2) )
399         return 0;
400 #endif
401 #if defined(HAVE_ICONV)
402     return iconv_close( cd );
403 #else
404     abort ();
405 #endif
406 }
407
408 /*****************************************************************************
409  * reduce a fraction
410  *   (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
411  *****************************************************************************/
412 bool vlc_ureduce( unsigned *pi_dst_nom, unsigned *pi_dst_den,
413                         uint64_t i_nom, uint64_t i_den, uint64_t i_max )
414 {
415     bool b_exact = 1;
416     uint64_t i_gcd;
417
418     if( i_den == 0 )
419     {
420         *pi_dst_nom = 0;
421         *pi_dst_den = 1;
422         return 1;
423     }
424
425     i_gcd = GCD( i_nom, i_den );
426     i_nom /= i_gcd;
427     i_den /= i_gcd;
428
429     if( i_max == 0 ) i_max = INT64_C(0xFFFFFFFF);
430
431     if( i_nom > i_max || i_den > i_max )
432     {
433         uint64_t i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
434         b_exact = 0;
435
436         for( ; ; )
437         {
438             uint64_t i_x = i_nom / i_den;
439             uint64_t i_a2n = i_x * i_a1_num + i_a0_num;
440             uint64_t i_a2d = i_x * i_a1_den + i_a0_den;
441
442             if( i_a2n > i_max || i_a2d > i_max ) break;
443
444             i_nom %= i_den;
445
446             i_a0_num = i_a1_num; i_a0_den = i_a1_den;
447             i_a1_num = i_a2n; i_a1_den = i_a2d;
448             if( i_nom == 0 ) break;
449             i_x = i_nom; i_nom = i_den; i_den = i_x;
450         }
451         i_nom = i_a1_num;
452         i_den = i_a1_den;
453     }
454
455     *pi_dst_nom = i_nom;
456     *pi_dst_den = i_den;
457
458     return b_exact;
459 }