X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Ftext%2Funicode.c;h=499b0e7906393545911bf3d246928fede056ec15;hb=5158c3af473f61e501440e1fb499271d69b6fe55;hp=bc4943b86647fdcf738b0f7aa94e556b2c461e84;hpb=3d411bb1961ac34d986efa67f71da44c2475f51d;p=vlc diff --git a/src/text/unicode.c b/src/text/unicode.c index bc4943b866..499b0e7906 100644 --- a/src/text/unicode.c +++ b/src/text/unicode.c @@ -27,6 +27,7 @@ *****************************************************************************/ #include #include +#include "libvlc.h" /* utf8_mkdir */ #include @@ -62,100 +63,51 @@ # define ASSUME_UTF8 1 #endif -#ifndef ASSUME_UTF8 -# if defined (HAVE_ICONV) -/* libiconv is more powerful than Win32 API (it has translit) */ -# define USE_ICONV 1 -# elif defined (WIN32) || defined (UNDER_CE) -# define USE_MB2MB 1 -# else -# error No UTF8 charset conversion implemented on this platform! -# endif +#if defined (ASSUME_UTF8) +/* Cool */ +#elif defined (WIN32) || defined (UNDER_CE) +# define USE_MB2MB 1 +#elif defined (HAVE_ICONV) +# define USE_ICONV 1 +#else +# error No UTF8 charset conversion implemented on this platform! #endif -typedef struct locale_data_t -{ #if defined (USE_ICONV) - vlc_iconv_t hd; - vlc_mutex_t lock; -#elif defined (USE_MB2MB) - UINT fromCP; - UINT toCP; -#endif -} locale_data_t; - -static locale_data_t from_locale, to_locale; +static char charset[sizeof ("CSISO11SWEDISHFORNAMES//translit")] = ""; - -void LocaleInit( vlc_object_t *p_this ) +static void find_charset_once (void) { -#if defined USE_ICONV char *psz_charset; - - if( vlc_current_charset( &psz_charset ) ) - /* UTF-8 */ - from_locale.hd = to_locale.hd = (vlc_iconv_t)(-1); - else - { - /* not UTF-8 */ - char psz_buf[strlen( psz_charset ) + sizeof( "//translit" )]; - const char *psz_conv; - - /* - * Still allow non-ASCII characters when the locale is not set. - * Western Europeans are being favored for historical reasons. - */ - if( strcmp( psz_charset, "ASCII" ) ) - { - sprintf( psz_buf, "%s//translit", psz_charset ); - psz_conv = psz_buf; - } - else - psz_conv = "ISO-8859-1//translit"; - - vlc_mutex_init( p_this, &from_locale.lock ); - vlc_mutex_init( p_this, &to_locale.lock ); - from_locale.hd = vlc_iconv_open( "UTF-8", psz_conv ); - to_locale.hd = vlc_iconv_open( psz_conv, "UTF-8" ); - } - - free( psz_charset ); - - assert( (from_locale.hd == (vlc_iconv_t)(-1)) - == (to_locale.hd == (vlc_iconv_t)(-1)) ); - -#elif defined (USE_MB2MB) - to_locale.toCP = from_locale.fromCP = CP_ACP; - from_locale.toCP = to_locale.fromCP = CP_UTF8; -#else - (void)p_this; -#endif + if (vlc_current_charset (&psz_charset) + || (psz_charset == NULL) + || (strcmp (psz_charset, "ASCII") == 0) + || ((size_t)snprintf (charset, sizeof (charset), "%s//translit", + psz_charset) >= sizeof (charset))) + strcpy (charset, "UTF-8"); + + free (psz_charset); } -void LocaleDeinit( void ) +static int find_charset (void) { -#ifdef USE_ICONV - if( to_locale.hd != (vlc_iconv_t)(-1) ) - { - vlc_iconv_close( to_locale.hd ); - vlc_mutex_destroy( &to_locale.lock ); - } - - if( from_locale.hd != (vlc_iconv_t)(-1) ) - { - vlc_iconv_close( from_locale.hd ); - vlc_mutex_destroy( &from_locale.lock ); - } -#endif + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once (&once, find_charset_once); + return !strcmp (charset, "UTF-8"); } +#endif + -static char *locale_fast (const char *string, locale_data_t *p) +static char *locale_fast (const char *string, vlc_bool_t from) { #if defined (USE_ICONV) - vlc_iconv_t hd = p->hd; + if (find_charset ()) + return (char *)string; + vlc_iconv_t hd = vlc_iconv_open (from ? "UTF-8" : charset, + from ? charset : "UTF-8"); if (hd == (vlc_iconv_t)(-1)) - return (char *)string; + return strdup (string); /* Uho! */ const char *iptr = string; size_t inb = strlen (string); @@ -165,9 +117,6 @@ static char *locale_fast (const char *string, locale_data_t *p) if (string == NULL) return NULL; - vlc_mutex_lock (&p->lock); - vlc_iconv (hd, NULL, NULL, NULL, NULL); - while (vlc_iconv (hd, &iptr, &inb, &optr, &outb) == (size_t)(-1)) { *optr++ = '?'; @@ -176,8 +125,8 @@ static char *locale_fast (const char *string, locale_data_t *p) inb--; vlc_iconv (hd, NULL, NULL, NULL, NULL); } - vlc_mutex_unlock (&p->lock); *optr = '\0'; + vlc_iconv_close (hd); assert (inb == 0); assert (*iptr == '\0'); @@ -186,25 +135,22 @@ static char *locale_fast (const char *string, locale_data_t *p) return strdup (output); #elif defined (USE_MB2MB) char *out; - wchar_t *wide; int len; if (string == NULL) return NULL; - len = MultiByteToWideChar (p->fromCP, 0, string, -1, NULL, 0); - if (len == 0) - return NULL; - + len = 1 + MultiByteToWideChar (from ? CP_ACP : CP_UTF8, + 0, string, -1, NULL, 0); wchar_t wide[len]; - MultiByteToWideChar (p->fromCP, 0, string, -1, wide, len); - len = WideCharToMultiByte (p->toCP, 0, wide, -1, NULL, 0, NULL, NULL); - if (len == 0) - return NULL; + MultiByteToWideChar (from ? CP_ACP : CP_UTF8, 0, string, -1, wide, len); + len = 1 + WideCharToMultiByte (from ? CP_UTF8 : CP_ACP, 0, wide, -1, NULL, 0, NULL, NULL); out = malloc (len); + if (out == NULL) + return NULL; - WideCharToMultiByte (p->toCP, 0, wide, -1, out, len, NULL, NULL); + WideCharToMultiByte (from ? CP_UTF8 : CP_ACP, 0, wide, -1, out, len, NULL, NULL); return out; #else return (char *)string; @@ -212,14 +158,14 @@ static char *locale_fast (const char *string, locale_data_t *p) } -static inline char *locale_dup (const char *string, locale_data_t *p) +static inline char *locale_dup (const char *string, vlc_bool_t from) { #if defined (USE_ICONV) - return (p->hd == (vlc_iconv_t)(-1)) - ? strdup (string) - : locale_fast (string, p); + if (find_charset ()) + return strdup (string); + return locale_fast (string, from); #elif defined (USE_MB2MB) - return locale_fast (string, p); + return locale_fast (string, from); #else return strdup (string); #endif @@ -229,10 +175,7 @@ static inline char *locale_dup (const char *string, locale_data_t *p) void LocaleFree (const char *str) { #if defined (USE_ICONV) - assert ((to_locale.hd == (vlc_iconv_t)(-1)) - == (from_locale.hd == (vlc_iconv_t)(-1))); - - if( to_locale.hd != (vlc_iconv_t)(-1) ) + if (!find_charset ()) free ((char *)str); #elif defined (USE_MB2MB) free ((char *)str); @@ -251,12 +194,12 @@ void LocaleFree (const char *str) */ char *FromLocale (const char *locale) { - return locale_fast (locale, &from_locale); + return locale_fast (locale, VLC_TRUE); } char *FromLocaleDup (const char *locale) { - return locale_dup (locale, &from_locale); + return locale_dup (locale, VLC_TRUE); } @@ -271,13 +214,13 @@ char *FromLocaleDup (const char *locale) */ char *ToLocale (const char *utf8) { - return locale_fast (utf8, &to_locale); + return locale_fast (utf8, VLC_FALSE); } static char *ToLocaleDup (const char *utf8) { - return locale_dup (utf8, &to_locale); + return locale_dup (utf8, VLC_FALSE); } @@ -383,7 +326,7 @@ FILE *utf8_fopen (const char *filename, const char *mode) * @return A 0 return value indicates success. A -1 return value indicates an * error, and an error code is stored in errno */ -int utf8_mkdir( const char *dirname ) +int utf8_mkdir( const char *dirname, mode_t mode ) { #if defined (UNDER_CE) || defined (WIN32) wchar_t wname[MAX_PATH + 1]; @@ -430,7 +373,7 @@ int utf8_mkdir( const char *dirname ) errno = ENOENT; return -1; } - res = mkdir( locname, 0755 ); + res = mkdir( locname, mode ); LocaleFree( locname ); return res; @@ -475,7 +418,7 @@ DIR *utf8_opendir( const char *dirname ) * * @param dir The directory that is being read * - * @return a UTF-8 string of the directory entry. Use LocaleFree() to free this memory + * @return a UTF-8 string of the directory entry. Use free() to free this memory. */ char *utf8_readdir( DIR *dir ) { @@ -619,6 +562,50 @@ int utf8_lstat( const char *filename, struct stat *buf) return utf8_statEx( filename, buf, VLC_FALSE ); } +/** + * utf8_unlink: Calls unlink() after conversion of file name to OS locale + * + * @param filename a UTF-8 string with the name of the file you want to delete. + * @return A 0 return value indicates success. A -1 return value indicates an + * error, and an error code is stored in errno + */ +int utf8_unlink( const char *filename ) +{ +#if defined (WIN32) || defined (UNDER_CE) + if( GetVersion() < 0x80000000 ) + { + /* for Windows NT and above */ + wchar_t wpath[MAX_PATH + 1]; + + if( !MultiByteToWideChar( CP_UTF8, 0, filename, -1, wpath, MAX_PATH ) ) + { + errno = ENOENT; + return -1; + } + wpath[MAX_PATH] = L'\0'; + + /* + * unlink() cannot open files with non-“ANSI” characters on Windows. + * We use _wunlink() instead. + */ + return _wunlink( wpath ); + } +#endif + const char *local_name = ToLocale( filename ); + + if( local_name == NULL ) + { + errno = ENOENT; + return -1; + } + + int ret = unlink( local_name ); + LocaleFree( local_name ); + return ret; +} + + + /** * utf8_*printf: *printf with conversion from UTF-8 to local encoding */