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