rpm 5.2.1
|
00001 00005 #include "system.h" 00006 #ifdef HAVE_LANGINFO_H 00007 #include <langinfo.h> 00008 #endif 00009 #ifdef HAVE_ICONV 00010 #include <iconv.h> 00011 #endif 00012 #include <rpmiotypes.h> 00013 #include "debug.h" 00014 00015 const char * xstrtolocale(const char *str) 00016 { 00017 #ifdef HAVE_ICONV 00018 /*@only@*/ 00019 static char *locale_encoding = NULL; 00020 static int locale_encoding_is_utf8 = 0; 00021 iconv_t cd; 00022 size_t src_size, dest_size; 00023 char *result, *dest; 00024 const char *src; 00025 00026 if (locale_encoding == NULL) { 00027 #ifdef HAVE_LANGINFO_H 00028 const char *encoding = nl_langinfo(CODESET); 00029 #else 00030 const char *encoding = "char"; 00031 #endif 00032 locale_encoding = xmalloc(strlen(encoding) + 11); 00033 sprintf(locale_encoding, "%s//TRANSLIT", encoding); 00034 locale_encoding_is_utf8 = strcasecmp(encoding, "UTF-8") == 0; 00035 } 00036 00037 if (!str || !*str || locale_encoding_is_utf8) 00038 return str; 00039 00040 cd = iconv_open(locale_encoding, "UTF-8"); 00041 if (cd == (iconv_t)-1) 00042 return str; 00043 00044 src_size = strlen(str); 00045 dest_size = src_size + 1; 00046 result = xmalloc(dest_size); 00047 src = str; 00048 dest = result; 00049 for(;;) { 00050 size_t status = iconv(cd, (char **)&src, &src_size, &dest, &dest_size); 00051 if (status == (size_t)-1) { 00052 size_t dest_offset; 00053 if (errno != E2BIG) { 00054 free(result); 00055 (void) iconv_close(cd); 00056 return str; 00057 } 00058 dest_offset = dest - result; 00059 dest_size += 16; 00060 result = xrealloc(result, dest_offset + dest_size); 00061 dest = result + dest_offset; 00062 } else if (src_size == 0) { 00063 if (src == NULL) break; 00064 src = NULL; 00065 } 00066 } 00067 (void) iconv_close(cd); 00068 free((void *)str); 00069 if (dest_size == 0) { 00070 size_t dest_offset = dest - result; 00071 result = xrealloc(result, dest_offset + 1); 00072 dest = result + dest_offset; 00073 } 00074 *dest = '\0'; 00075 return result; 00076 #else 00077 return str; 00078 #endif 00079 }