Back to index

im-sdk  12.3.91
csconv.c
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 #if !defined(HAVE_ICONV)
00005 #error "csconv needs iconv"
00006 #endif
00007 #include "csconv.h"
00008 #include <stdio.h>
00009 #include <iconv.h>
00010 #ifdef HAVE_ERRNO_H
00011 #include <errno.h>
00012 #endif
00013 #ifdef HAVE_STDLIB_H
00014 #include <stdlib.h>
00015 #endif
00016 #ifdef HAVE_CTYPE_H
00017 #include <ctype.h>
00018 #endif
00019 #ifdef HAVE_STRING_H
00020 #include <string.h>
00021 #endif
00022 #ifdef HAVE_LOCALE_H
00023 #include <locale.h>
00024 #endif
00025 
00026 struct _csconv_info {
00027     iconv_t cd;
00028 };
00029 
00030 
00031 #define skip_space(p) for(; *p != '\0' && isspace(*p); p++);
00032 
00033 static char*
00034 get_item(char *item_buf, char *line, char **next_ptr)
00035 {
00036     char *p = line;
00037     size_t r = 0;
00038     skip_space(p);
00039     for(; p[r] != '\0' && isgraph(p[r]); r++) ;
00040     *next_ptr = p + r;
00041     if (!item_buf) return NULL;
00042     strncpy(item_buf, p, r);
00043     item_buf[r] = '\0';
00044     return item_buf;
00045 }
00046 
00047 static int
00048 read_conf(
00049     const char *locale,
00050     const char *to,
00051     const char *from,
00052     char **norm_to,
00053     char **norm_from
00054 )
00055 {
00056     FILE *fp;
00057     char buf[128];
00058     int retval = -1;
00059     /* TODO */
00060 
00061     *norm_to = *norm_from = NULL;
00062 
00063     /* FIXME */
00064     /* should we read other configuration files 
00065      * such as ~/.iiim/encoding.norm ?
00066      */
00067     fp = fopen(CSCONV_DIR "/encoding.norm", "r");
00068     if (!fp) return -1;
00069 
00070     while((fgets(buf, sizeof(buf), fp) != NULL)) {
00071         /* TODO */
00072         char tmp[16];
00073         char *p = buf;
00074         int len = strlen(buf);
00075         /* skip comment */
00076         if (('#' == *p ) || ((1 < len) && ('/' == *p) && ('/' == *(p + 1)))) continue;
00077         if ('\n' == *p || '\0' == *p) continue;
00078         get_item(NULL, p, &p); /* skip os */
00079         if (strcmp(locale, get_item(tmp, p, &p))) continue;
00080         if (strcmp(to, get_item(tmp, p, &p))) continue;
00081         if (strcmp(from, get_item(tmp, p, &p))) continue;
00082         /* found */
00083         get_item(NULL, p, &p); /* skip locale */
00084         if (get_item(tmp, p, &p) != NULL) *norm_to = strdup(tmp);
00085         if (get_item(tmp, p, &p) != NULL) {
00086             *norm_from = strdup(tmp);
00087             retval = 0;
00088         }
00089         break;
00090     }
00091     fclose(fp);
00092     return retval;
00093 }
00094 
00095 csconv_t
00096 csconv_open_locale(
00097     const char *locale,
00098     const char *tocode,
00099     const char *fromcode
00100 )
00101 {
00102     csconv_t conv = NULL;
00103     char *from = NULL, *to = NULL;
00104 
00105     if (locale == NULL) goto error;
00106     if ((read_conf(locale, tocode, fromcode, &to, &from) == -1)) goto error;
00107     conv = calloc(1, sizeof(*conv));
00108     if (!conv) goto error;
00109 
00110     conv->cd = iconv_open(to, from);
00111     if (conv->cd == (iconv_t) -1) goto error;
00112     free(from);
00113     free(to);
00114     return conv;
00115 
00116 error:
00117     if (conv) free(conv);
00118     if (from) free(from);
00119     if (to) free(to);
00120 #ifdef HAVE_ERRNO_H
00121     errno = EINVAL;
00122 #endif
00123     return (csconv_t)-1;
00124 }
00125 
00126 
00127 csconv_t
00128 csconv_open(
00129     const char *tocode,
00130     const char *fromcode
00131 )
00132 {
00133 #ifdef HAVE_LOCALE_H
00134     /* try to find current locale */
00135     /* we should pass NULL as a second argument */
00136     return csconv_open_locale(setlocale(LC_CTYPE, NULL), tocode, fromcode);
00137 #endif
00138 #ifdef HAVE_ERRNO_H
00139     /* we cannot determine locale */
00140     /* set errno to EINVAL */
00141     errno = EINVAL;
00142 #endif
00143     return (csconv_t)-1;
00144 }
00145 
00146 size_t
00147 csconv(csconv_t cd,
00148        const char **inbuf,
00149        size_t *inbytesleft,
00150        char **putbuf,
00151        size_t *outbytesleft
00152 )
00153 {
00154     if (!cd || cd == (csconv_t)-1) {
00155 #ifdef HAVE_ERRNO_H
00156       errno = EINVAL;
00157 #endif
00158       return (size_t)-1;
00159     }
00160     return iconv(cd->cd, (ICONV_CONST char**)inbuf, inbytesleft, putbuf, outbytesleft);
00161 }
00162 
00163 int
00164 csconv_close(
00165     csconv_t cd
00166 )
00167 {
00168     int retval = 0;
00169     if (!cd || cd == (csconv_t)-1) return -1;
00170     retval = iconv_close(cd->cd);
00171     free(cd);
00172     return retval;
00173 }