path, tag_id3: use g_convert() instead of charConv.c
GLib provides an easier API for character set conversion than iconv(). Use g_convert() / g_convert_with_fallback() for all character conversions. We should optimize the path.h API later to return a newly allocated buffer, so we can just pass GLib's return value.
This commit is contained in:
		| @@ -45,7 +45,6 @@ mpd_headers = \ | |||||||
| 	output_control.h \ | 	output_control.h \ | ||||||
| 	audioOutputs/audioOutput_shout.h \ | 	audioOutputs/audioOutput_shout.h \ | ||||||
| 	buffer2array.h \ | 	buffer2array.h \ | ||||||
| 	charConv.h \ |  | ||||||
| 	command.h \ | 	command.h \ | ||||||
| 	idle.h \ | 	idle.h \ | ||||||
| 	condition.h \ | 	condition.h \ | ||||||
| @@ -131,7 +130,6 @@ mpd_SOURCES = \ | |||||||
| 	output_control.c \ | 	output_control.c \ | ||||||
| 	output_init.c \ | 	output_init.c \ | ||||||
| 	buffer2array.c \ | 	buffer2array.c \ | ||||||
| 	charConv.c \ |  | ||||||
| 	command.c \ | 	command.c \ | ||||||
| 	idle.c \ | 	idle.c \ | ||||||
| 	condition.c \ | 	condition.c \ | ||||||
|   | |||||||
							
								
								
									
										177
									
								
								src/charConv.c
									
									
									
									
									
								
							
							
						
						
									
										177
									
								
								src/charConv.c
									
									
									
									
									
								
							| @@ -1,177 +0,0 @@ | |||||||
| /* the Music Player Daemon (MPD) |  | ||||||
|  * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) |  | ||||||
|  * This project's homepage is: http://www.musicpd.org |  | ||||||
|  * |  | ||||||
|  * This program is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "charConv.h" |  | ||||||
| #include "utf8.h" |  | ||||||
| #include "utils.h" |  | ||||||
| #include "path.h" |  | ||||||
| #include "os_compat.h" |  | ||||||
|  |  | ||||||
| #include "../config.h" |  | ||||||
|  |  | ||||||
| #ifdef HAVE_ICONV |  | ||||||
| #include <iconv.h> |  | ||||||
| static iconv_t char_conv_iconv; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static char *char_conv_to; |  | ||||||
| static char *char_conv_from; |  | ||||||
| static int8_t char_conv_same; |  | ||||||
| static int8_t char_conv_use_iconv; |  | ||||||
|  |  | ||||||
| /* 1 is to use latin1ToUtf8 |  | ||||||
|    0 is not to use latin1/utf8 converter |  | ||||||
|   -1 is to use utf8ToLatin1*/ |  | ||||||
| static int8_t char_conv_latin1ToUtf8; |  | ||||||
|  |  | ||||||
| #define BUFFER_SIZE	MPD_PATH_MAX |  | ||||||
|  |  | ||||||
| static void closeCharSetConversion(void); |  | ||||||
|  |  | ||||||
| int setCharSetConversion(const char *to, const char *from) |  | ||||||
| { |  | ||||||
| 	if (char_conv_to && char_conv_from) { |  | ||||||
| 		if (char_conv_latin1ToUtf8 && |  | ||||||
| 		    !strcmp(from, char_conv_to) && |  | ||||||
| 		    !strcmp(to, char_conv_from)) { |  | ||||||
| 			char *swap = char_conv_from; |  | ||||||
| 			char_conv_from = char_conv_to; |  | ||||||
| 			char_conv_to = swap; |  | ||||||
| 			char_conv_latin1ToUtf8 *= -1; |  | ||||||
| 			return 0; |  | ||||||
| 		} else if (!strcmp(to, char_conv_to) && |  | ||||||
| 		           !strcmp(from,char_conv_from)) { |  | ||||||
| 			return 0; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	closeCharSetConversion(); |  | ||||||
|  |  | ||||||
| 	if (0 == strcmp(to, from)) { |  | ||||||
| 		char_conv_same = 1; |  | ||||||
| 		char_conv_to = xstrdup(to); |  | ||||||
| 		char_conv_from = xstrdup(from); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (strcmp(to, "UTF-8") == 0 && strcmp(from, "ISO-8859-1") == 0) { |  | ||||||
| 		char_conv_latin1ToUtf8 = 1; |  | ||||||
| 	} else if (strcmp(to, "ISO-8859-1") == 0 && strcmp(from, "UTF-8") == 0) { |  | ||||||
| 		char_conv_latin1ToUtf8 = -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (char_conv_latin1ToUtf8 != 0) { |  | ||||||
| 		char_conv_to = xstrdup(to); |  | ||||||
| 		char_conv_from = xstrdup(from); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| #ifdef HAVE_ICONV |  | ||||||
| 	if ((char_conv_iconv = iconv_open(to, from)) == (iconv_t) (-1)) |  | ||||||
| 		return -1; |  | ||||||
|  |  | ||||||
| 	char_conv_to = xstrdup(to); |  | ||||||
| 	char_conv_from = xstrdup(from); |  | ||||||
| 	char_conv_use_iconv = 1; |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| #else |  | ||||||
| 	return -1; |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #ifdef HAVE_ICONV |  | ||||||
| static inline size_t deconst_iconv(iconv_t cd, |  | ||||||
| 				   const char **inbuf, size_t *inbytesleft, |  | ||||||
| 				   char **outbuf, size_t *outbytesleft) |  | ||||||
| { |  | ||||||
| 	union { |  | ||||||
| 		const char **a; |  | ||||||
| 		char **b; |  | ||||||
| 	} deconst; |  | ||||||
|  |  | ||||||
| 	deconst.a = inbuf; |  | ||||||
|  |  | ||||||
| 	return iconv(cd, deconst.b, inbytesleft, outbuf, outbytesleft); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| char *char_conv_str(char *dest, const char *string) |  | ||||||
| { |  | ||||||
| 	if (!char_conv_to) |  | ||||||
| 		return NULL; |  | ||||||
|  |  | ||||||
| 	if (char_conv_same) |  | ||||||
| 		return strcpy(dest, string); |  | ||||||
|  |  | ||||||
| #ifdef HAVE_ICONV |  | ||||||
| 	if (char_conv_use_iconv) { |  | ||||||
| 		/* not optimized: */ |  | ||||||
| 		char buffer[BUFFER_SIZE]; |  | ||||||
| 		size_t inleft = strlen(string); |  | ||||||
| 		size_t outleft; |  | ||||||
| 		size_t retlen = 0; |  | ||||||
| 		size_t err; |  | ||||||
| 		char *bufferPtr; |  | ||||||
|  |  | ||||||
| 		dest[0] = '\0'; |  | ||||||
|  |  | ||||||
| 		while (inleft) { |  | ||||||
| 			bufferPtr = buffer; |  | ||||||
| 			outleft = BUFFER_SIZE; |  | ||||||
| 			err = |  | ||||||
| 			    deconst_iconv(char_conv_iconv, &string, &inleft, |  | ||||||
| 					  &bufferPtr, &outleft); |  | ||||||
| 			if (outleft == BUFFER_SIZE |  | ||||||
| 			    || (err == (size_t)-1L && errno != E2BIG)) { |  | ||||||
| 				return NULL; |  | ||||||
| 			} |  | ||||||
| 			memcpy(dest + retlen, buffer, BUFFER_SIZE - outleft); |  | ||||||
| 			retlen += BUFFER_SIZE - outleft; |  | ||||||
| 			dest[retlen] = '\0'; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return dest; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	switch (char_conv_latin1ToUtf8) { |  | ||||||
| 	case 1: |  | ||||||
| 		return latin1_to_utf8(dest, string); |  | ||||||
| 	case -1: |  | ||||||
| 		return utf8_to_latin1(dest, string); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void closeCharSetConversion(void) |  | ||||||
| { |  | ||||||
| 	if (char_conv_to) { |  | ||||||
| #ifdef HAVE_ICONV |  | ||||||
| 		if (char_conv_use_iconv) |  | ||||||
| 			iconv_close(char_conv_iconv); |  | ||||||
| #endif |  | ||||||
| 		free(char_conv_to); |  | ||||||
| 		free(char_conv_from); |  | ||||||
| 		char_conv_to = NULL; |  | ||||||
| 		char_conv_from = NULL; |  | ||||||
| 		char_conv_same = 0; |  | ||||||
| 		char_conv_latin1ToUtf8 = 0; |  | ||||||
| 		char_conv_use_iconv = 0; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,26 +0,0 @@ | |||||||
| /* the Music Player Daemon (MPD) |  | ||||||
|  * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) |  | ||||||
|  * This project's homepage is: http://www.musicpd.org |  | ||||||
|  * |  | ||||||
|  * This program is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 2 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #ifndef CHAR_CONV_H |  | ||||||
| #define CHAR_CONV_H |  | ||||||
|  |  | ||||||
| int setCharSetConversion(const char *to, const char *from); |  | ||||||
|  |  | ||||||
| char *char_conv_str(char *dest, const char *string); |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
							
								
								
									
										54
									
								
								src/path.c
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/path.c
									
									
									
									
									
								
							| @@ -18,7 +18,6 @@ | |||||||
|  |  | ||||||
| #include "path.h" | #include "path.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| #include "charConv.h" |  | ||||||
| #include "conf.h" | #include "conf.h" | ||||||
| #include "utf8.h" | #include "utf8.h" | ||||||
| #include "utils.h" | #include "utils.h" | ||||||
| @@ -32,28 +31,48 @@ | |||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #include <glib.h> | ||||||
|  |  | ||||||
| const char *musicDir; | const char *musicDir; | ||||||
| static const char *playlistDir; | static const char *playlistDir; | ||||||
| static size_t music_dir_len; | static size_t music_dir_len; | ||||||
| static size_t playlist_dir_len; | static size_t playlist_dir_len; | ||||||
| static char *fsCharset; | static char *fsCharset; | ||||||
|  |  | ||||||
| static char *path_conv_charset(char *dest, const char *to, |  | ||||||
| 			       const char *from, const char *str) |  | ||||||
| { |  | ||||||
| 	return setCharSetConversion(to, from) ? NULL : char_conv_str(dest, str); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| char *fs_charset_to_utf8(char *dst, const char *str) | char *fs_charset_to_utf8(char *dst, const char *str) | ||||||
| { | { | ||||||
| 	char *ret = path_conv_charset(dst, "UTF-8", fsCharset, str); | 	gchar *p; | ||||||
| 	return (ret && !validUtf8String(ret, strlen(ret))) ? NULL : ret; | 	GError *error = NULL; | ||||||
|  |  | ||||||
|  | 	p = g_convert(str, -1, | ||||||
|  | 		      fsCharset, "utf-8", | ||||||
|  | 		      NULL, NULL, &error); | ||||||
|  | 	if (p == NULL) | ||||||
|  | 		/* no fallback */ | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	g_strlcpy(dst, p, MPD_PATH_MAX); | ||||||
|  | 	g_free(p); | ||||||
|  | 	return dst; | ||||||
| } | } | ||||||
|  |  | ||||||
| char *utf8_to_fs_charset(char *dst, const char *str) | char *utf8_to_fs_charset(char *dst, const char *str) | ||||||
| { | { | ||||||
| 	char *ret = path_conv_charset(dst, fsCharset, "UTF-8", str); | 	gchar *p; | ||||||
| 	return ret ? ret : strcpy(dst, str); | 	GError *error = NULL; | ||||||
|  |  | ||||||
|  | 	p = g_convert(str, -1, | ||||||
|  | 		      "utf-8", fsCharset, | ||||||
|  | 		      NULL, NULL, &error); | ||||||
|  | 	if (p == NULL) { | ||||||
|  | 		/* fall back to UTF-8 */ | ||||||
|  | 		g_error_free(error); | ||||||
|  | 		return strcpy(dst, str); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	g_strlcpy(dst, p, MPD_PATH_MAX); | ||||||
|  | 	g_free(p); | ||||||
|  | 	return dst; | ||||||
| } | } | ||||||
|  |  | ||||||
| void setFsCharset(const char *charset) | void setFsCharset(const char *charset) | ||||||
| @@ -67,19 +86,6 @@ void setFsCharset(const char *charset) | |||||||
|  |  | ||||||
| 	DEBUG("setFsCharset: fs charset is: %s\n", fsCharset); | 	DEBUG("setFsCharset: fs charset is: %s\n", fsCharset); | ||||||
|  |  | ||||||
| 	if (setCharSetConversion("UTF-8", fsCharset) != 0) { |  | ||||||
| 		WARNING("fs charset conversion problem: " |  | ||||||
| 			"not able to convert from \"%s\" to \"%s\"\n", |  | ||||||
| 			fsCharset, "UTF-8"); |  | ||||||
| 		error = 1; |  | ||||||
| 	} |  | ||||||
| 	if (setCharSetConversion(fsCharset, "UTF-8") != 0) { |  | ||||||
| 		WARNING("fs charset conversion problem: " |  | ||||||
| 			"not able to convert from \"%s\" to \"%s\"\n", |  | ||||||
| 			"UTF-8", fsCharset); |  | ||||||
| 		error = 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (error) { | 	if (error) { | ||||||
| 		free(fsCharset); | 		free(fsCharset); | ||||||
| 		WARNING("setting fs charset to ISO-8859-1!\n"); | 		WARNING("setting fs charset to ISO-8859-1!\n"); | ||||||
|   | |||||||
| @@ -21,9 +21,9 @@ | |||||||
| #include "utils.h" | #include "utils.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| #include "conf.h" | #include "conf.h" | ||||||
| #include "charConv.h" |  | ||||||
|  |  | ||||||
| #ifdef HAVE_ID3TAG | #ifdef HAVE_ID3TAG | ||||||
|  | #include <glib.h> | ||||||
| #include <id3tag.h> | #include <id3tag.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -54,16 +54,21 @@ static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4, | |||||||
| 	/* use encoding field here? */ | 	/* use encoding field here? */ | ||||||
| 	if (is_id3v1 && | 	if (is_id3v1 && | ||||||
| 	    (encoding = getConfigParamValue(CONF_ID3V1_ENCODING))) { | 	    (encoding = getConfigParamValue(CONF_ID3V1_ENCODING))) { | ||||||
|  | 		GError *error = NULL; | ||||||
|  |  | ||||||
| 		isostr = id3_ucs4_latin1duplicate(ucs4); | 		isostr = id3_ucs4_latin1duplicate(ucs4); | ||||||
| 		if (mpd_unlikely(!isostr)) { | 		if (mpd_unlikely(!isostr)) { | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		} | 		} | ||||||
| 		setCharSetConversion("UTF-8", encoding); |  | ||||||
| 		utf8 = xmalloc(strlen((char *)isostr) + 1); | 		utf8 = (id3_utf8_t *) | ||||||
| 		utf8 = (id3_utf8_t *)char_conv_str((char *)utf8, (char *)isostr); | 			g_convert_with_fallback((const char*)isostr, -1, | ||||||
| 		if (!utf8) { | 						encoding, "utf-8", | ||||||
|  | 						NULL, NULL, NULL, &error); | ||||||
|  | 		if (utf8 == NULL) { | ||||||
| 			DEBUG("Unable to convert %s string to UTF-8: " | 			DEBUG("Unable to convert %s string to UTF-8: " | ||||||
| 			      "'%s'\n", encoding, isostr); | 			      "'%s'\n", encoding, isostr); | ||||||
|  | 			g_error_free(error); | ||||||
| 			free(isostr); | 			free(isostr); | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		} | 		} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann