Go to the documentation of this file.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
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 }