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>