Annotation of embedaddon/libiconv/extras/iconv_string.c, revision 1.1

1.1     ! misho       1: /* Copyright (C) 1999-2001, 2003 Bruno Haible.
        !             2:    This file is not part of the GNU LIBICONV Library.
        !             3:    This file is put into the public domain.  */
        !             4: 
        !             5: #include "iconv_string.h"
        !             6: #include <iconv.h>
        !             7: #include <errno.h>
        !             8: #include <stdlib.h>
        !             9: #include <string.h>
        !            10: 
        !            11: #define tmpbufsize 4096
        !            12: 
        !            13: int iconv_string (const char* tocode, const char* fromcode,
        !            14:                   const char* start, const char* end,
        !            15:                   char** resultp, size_t* lengthp)
        !            16: {
        !            17:   iconv_t cd = iconv_open(tocode,fromcode);
        !            18:   size_t length;
        !            19:   char* result;
        !            20:   if (cd == (iconv_t)(-1)) {
        !            21:     if (errno != EINVAL)
        !            22:       return -1;
        !            23:     /* Unsupported fromcode or tocode. Check whether the caller requested
        !            24:        autodetection. */
        !            25:     if (!strcmp(fromcode,"autodetect_utf8")) {
        !            26:       int ret;
        !            27:       /* Try UTF-8 first. There are very few ISO-8859-1 inputs that would
        !            28:          be valid UTF-8, but many UTF-8 inputs are valid ISO-8859-1. */
        !            29:       ret = iconv_string(tocode,"UTF-8",start,end,resultp,lengthp);
        !            30:       if (!(ret < 0 && errno == EILSEQ))
        !            31:         return ret;
        !            32:       ret = iconv_string(tocode,"ISO-8859-1",start,end,resultp,lengthp);
        !            33:       return ret;
        !            34:     }
        !            35:     if (!strcmp(fromcode,"autodetect_jp")) {
        !            36:       int ret;
        !            37:       /* Try 7-bit encoding first. If the input contains bytes >= 0x80,
        !            38:          it will fail. */
        !            39:       ret = iconv_string(tocode,"ISO-2022-JP-2",start,end,resultp,lengthp);
        !            40:       if (!(ret < 0 && errno == EILSEQ))
        !            41:         return ret;
        !            42:       /* Try EUC-JP next. Short SHIFT_JIS inputs may come out wrong. This
        !            43:          is unavoidable. People will condemn SHIFT_JIS.
        !            44:          If we tried SHIFT_JIS first, then some short EUC-JP inputs would
        !            45:          come out wrong, and people would condemn EUC-JP and Unix, which
        !            46:          would not be good. */
        !            47:       ret = iconv_string(tocode,"EUC-JP",start,end,resultp,lengthp);
        !            48:       if (!(ret < 0 && errno == EILSEQ))
        !            49:         return ret;
        !            50:       /* Finally try SHIFT_JIS. */
        !            51:       ret = iconv_string(tocode,"SHIFT_JIS",start,end,resultp,lengthp);
        !            52:       return ret;
        !            53:     }
        !            54:     if (!strcmp(fromcode,"autodetect_kr")) {
        !            55:       int ret;
        !            56:       /* Try 7-bit encoding first. If the input contains bytes >= 0x80,
        !            57:          it will fail. */
        !            58:       ret = iconv_string(tocode,"ISO-2022-KR",start,end,resultp,lengthp);
        !            59:       if (!(ret < 0 && errno == EILSEQ))
        !            60:         return ret;
        !            61:       /* Finally try EUC-KR. */
        !            62:       ret = iconv_string(tocode,"EUC-KR",start,end,resultp,lengthp);
        !            63:       return ret;
        !            64:     }
        !            65:     errno = EINVAL;
        !            66:     return -1;
        !            67:   }
        !            68:   /* Determine the length we need. */
        !            69:   {
        !            70:     size_t count = 0;
        !            71:     char tmpbuf[tmpbufsize];
        !            72:     const char* inptr = start;
        !            73:     size_t insize = end-start;
        !            74:     while (insize > 0) {
        !            75:       char* outptr = tmpbuf;
        !            76:       size_t outsize = tmpbufsize;
        !            77:       size_t res = iconv(cd,&inptr,&insize,&outptr,&outsize);
        !            78:       if (res == (size_t)(-1) && errno != E2BIG) {
        !            79:         if (errno == EINVAL)
        !            80:           break;
        !            81:         else {
        !            82:           int saved_errno = errno;
        !            83:           iconv_close(cd);
        !            84:           errno = saved_errno;
        !            85:           return -1;
        !            86:         }
        !            87:       }
        !            88:       count += outptr-tmpbuf;
        !            89:     }
        !            90:     {
        !            91:       char* outptr = tmpbuf;
        !            92:       size_t outsize = tmpbufsize;
        !            93:       size_t res = iconv(cd,NULL,NULL,&outptr,&outsize);
        !            94:       if (res == (size_t)(-1)) {
        !            95:         int saved_errno = errno;
        !            96:         iconv_close(cd);
        !            97:         errno = saved_errno;
        !            98:         return -1;
        !            99:       }
        !           100:       count += outptr-tmpbuf;
        !           101:     }
        !           102:     length = count;
        !           103:   }
        !           104:   if (lengthp != NULL)
        !           105:     *lengthp = length;
        !           106:   if (resultp == NULL) {
        !           107:     iconv_close(cd);
        !           108:     return 0;
        !           109:   }
        !           110:   result = (*resultp == NULL ? malloc(length) : realloc(*resultp,length));
        !           111:   *resultp = result;
        !           112:   if (length == 0) {
        !           113:     iconv_close(cd);
        !           114:     return 0;
        !           115:   }
        !           116:   if (result == NULL) {
        !           117:     iconv_close(cd);
        !           118:     errno = ENOMEM;
        !           119:     return -1;
        !           120:   }
        !           121:   iconv(cd,NULL,NULL,NULL,NULL); /* return to the initial state */
        !           122:   /* Do the conversion for real. */
        !           123:   {
        !           124:     const char* inptr = start;
        !           125:     size_t insize = end-start;
        !           126:     char* outptr = result;
        !           127:     size_t outsize = length;
        !           128:     while (insize > 0) {
        !           129:       size_t res = iconv(cd,&inptr,&insize,&outptr,&outsize);
        !           130:       if (res == (size_t)(-1)) {
        !           131:         if (errno == EINVAL)
        !           132:           break;
        !           133:         else {
        !           134:           int saved_errno = errno;
        !           135:           iconv_close(cd);
        !           136:           errno = saved_errno;
        !           137:           return -1;
        !           138:         }
        !           139:       }
        !           140:     }
        !           141:     {
        !           142:       size_t res = iconv(cd,NULL,NULL,&outptr,&outsize);
        !           143:       if (res == (size_t)(-1)) {
        !           144:         int saved_errno = errno;
        !           145:         iconv_close(cd);
        !           146:         errno = saved_errno;
        !           147:         return -1;
        !           148:       }
        !           149:     }
        !           150:     if (outsize != 0) abort();
        !           151:   }
        !           152:   iconv_close(cd);
        !           153:   return 0;
        !           154: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>