• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmio/strtolocale.c

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     /*@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 }

Generated on Fri Dec 3 2010 20:54:41 for rpm by  doxygen 1.7.2