disable plugin_xmms on x84_64
[flac.git] / src / plugin_common / charset.c
1 /* plugin_common - Routines common to several plugins
2  * Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Josh Coalson
3  *
4  * Only slightly modified charset.c from:
5  *  EasyTAG - Tag editor for MP3 and OGG files
6  *  Copyright (C) 1999-2001  Håvard Kvålen <havardk@xmms.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (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 General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #if HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #ifdef HAVE_ICONV
33 #include <iconv.h>
34 #endif
35
36 #ifdef HAVE_LANGINFO_CODESET
37 #include <langinfo.h>
38 #endif
39
40 #include "charset.h"
41
42
43 /*************
44  * Functions *
45  *************/
46
47 char* FLAC_plugin__charset_get_current (void)
48 {
49         char *charset = getenv("CHARSET");
50
51 #ifdef HAVE_LANGINFO_CODESET
52         if (!charset)
53                 charset = nl_langinfo(CODESET);
54 #endif
55         if (!charset)
56                 charset = "ISO-8859-1";
57
58         return charset;
59 }
60
61
62 #ifdef HAVE_ICONV
63 char* FLAC_plugin__charset_convert_string (const char *string, char *from, char *to)
64 {
65         size_t outleft, outsize, length;
66         iconv_t cd;
67         char *out, *outptr;
68         const char *input = string;
69
70         if (!string)
71                 return NULL;
72
73         length = strlen(string);
74
75         if ((cd = iconv_open(to, from)) == (iconv_t)-1)
76         {
77 #ifdef DEBUG
78                 fprintf(stderr, "convert_string(): Conversion not supported. Charsets: %s -> %s", from, to);
79 #endif
80                 return strdup(string);
81         }
82
83         /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
84         /* + 1 for nul in case len == 1 */
85         outsize = ((length + 3) & ~3) + 1;
86         if(outsize < length) /* overflow check */
87                 return NULL;
88         out = (char*)malloc(outsize);
89         outleft = outsize - 1;
90         outptr = out;
91
92 retry:
93         if (iconv(cd, (char**)&input, &length, &outptr, &outleft) == (size_t)(-1))
94         {
95                 int used;
96                 switch (errno)
97                 {
98                         case E2BIG:
99                                 used = outptr - out;
100                                 if((outsize - 1) * 2 + 1 <= outsize) { /* overflow check */
101                                         free(out);
102                                         return NULL;
103                                 }
104                                 outsize = (outsize - 1) * 2 + 1;
105                                 out = realloc(out, outsize);
106                                 outptr = out + used;
107                                 outleft = outsize - 1 - used;
108                                 goto retry;
109                         case EINVAL:
110                                 break;
111                         case EILSEQ:
112                                 /* Invalid sequence, try to get the rest of the string */
113                                 input++;
114                                 length = strlen(input);
115                                 goto retry;
116                         default:
117 #ifdef DEBUG
118                                 fprintf(stderr, "convert_string(): Conversion failed. Inputstring: %s; Error: %s", string, strerror(errno));
119 #endif
120                                 break;
121                 }
122         }
123         *outptr = '\0';
124
125         iconv_close(cd);
126         return out;
127 }
128 #else
129 char* FLAC_plugin__charset_convert_string (const char *string, char *from, char *to)
130 {
131         (void)from, (void)to;
132         if (!string)
133                 return NULL;
134         return strdup(string);
135 }
136 #endif
137
138 #ifdef HAVE_ICONV
139 int FLAC_plugin__charset_test_conversion (char *from, char *to)
140 {
141         iconv_t cd;
142
143         if ((cd=iconv_open(to,from)) == (iconv_t)-1)
144         {
145                 /* Conversion not supported */
146                 return 0;
147         }
148         iconv_close(cd);
149         return 1;
150 }
151 #else
152 int FLAC_plugin__charset_test_conversion (char *from, char *to)
153 {
154         (void)from, (void)to;
155         return 1;
156 }
157 #endif