rpm 5.2.1

- 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 }