Second patch from X-Fixer: tweaks for better MSVC build
[flac.git] / src / plugin_common / charset.c
1 /* plugin_common - Routines common to several plugins
2  * Copyright (C) 2002,2003  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 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
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         out = malloc(outsize);
87         outleft = outsize - 1;
88         outptr = out;
89
90 retry:
91         if (iconv(cd, &input, &length, &outptr, &outleft) == -1)
92         {
93                 int used;
94                 switch (errno)
95                 {
96                         case E2BIG:
97                                 used = outptr - out;
98                                 outsize = (outsize - 1) * 2 + 1;
99                                 out = realloc(out, outsize);
100                                 outptr = out + used;
101                                 outleft = outsize - 1 - used;
102                                 goto retry;
103                         case EINVAL:
104                                 break;
105                         case EILSEQ:
106                                 /* Invalid sequence, try to get the rest of the string */
107                                 input++;
108                                 length = strlen(input);
109                                 goto retry;
110                         default:
111 #ifdef DEBUG
112                                 fprintf(stderr, "convert_string(): Conversion failed. Inputstring: %s; Error: %s", string, strerror(errno));
113 #endif
114                                 break;
115                 }
116         }
117         *outptr = '\0';
118
119         iconv_close(cd);
120         return out;
121 }
122 #else
123 char* FLAC_plugin__charset_convert_string (const char *string, char *from, char *to)
124 {
125         (void)from, (void)to;
126         if (!string)
127                 return NULL;
128         return strdup(string);
129 }
130 #endif
131
132 #ifdef HAVE_ICONV
133 int FLAC_plugin__charset_test_conversion (char *from, char *to)
134 {
135         iconv_t cd;
136
137         if ((cd=iconv_open(to,from)) == (iconv_t)-1)
138         {
139                 /* Conversion not supported */
140                 return 0;
141         }
142         iconv_close(cd);
143         return 1;
144 }
145 #else
146 int FLAC_plugin__charset_test_conversion (char *from, char *to)
147 {
148         (void)from, (void)to;
149         return 1;
150 }
151 #endif