Changeset 24870


Ignore:
Timestamp:
2011-01-02T00:11:48+01:00 (7 years ago)
Author:
jow
Message:

[packages] libiconv: extend the library to support more charset conversions

Location:
packages/libs/libiconv
Files:
27 added
3 edited

Legend:

Unmodified
Added
Removed
  • packages/libs/libiconv/Makefile

    r24777 r24870  
    22# Copyright (C) 2010 OpenWrt.org 
    33# 
    4 # This is free software, licensed under the GNU General Public License v2. 
    5 # See /LICENSE for more information. 
     4# This Makefile and the code shipped in src/ is free software, licensed 
     5# under the GNU Lesser General Public License, version 2.1 and later. 
     6# See src/COPYING for more information. 
     7# 
     8# Refer to src/COPYRIGHT for copyright statements on the source files. 
    69# 
    710 
     
    912 
    1013PKG_NAME:=libiconv 
    11 PKG_RELEASE:=2 
     14PKG_RELEASE:=3 
    1215 
    1316include $(INCLUDE_DIR)/package.mk 
     
    1619  SECTION:=libs 
    1720  CATEGORY:=Libraries 
    18   TITLE:=Stub header for the GNU Character set conversion library 
     21  TITLE:=Tiny drop-in replacement for the GNU Character set conversion library 
    1922endef 
    2023 
  • packages/libs/libiconv/src/iconv.c

    r24777 r24870  
    1 /* 
    2  * Simple iconv library stub so that programs have something to link against 
    3  */ 
    4  
    5 #include <stddef.h> 
     1#include <iconv.h> 
     2#include <errno.h> 
     3#include <wchar.h> 
    64#include <string.h> 
    7 #include <errno.h> 
    8 #include <iconv.h> 
    9  
     5#include <strings.h> 
     6#include <stdlib.h> 
     7#include <limits.h> 
     8 
     9#include <dirent.h> 
     10#include <fcntl.h> 
     11#include <sys/mman.h> 
     12#include <sys/stat.h> 
     13#include <unistd.h> 
     14#include <stdint.h> 
     15 
     16/* builtin charmaps */ 
     17#include "charmaps.h" 
     18 
     19/* only 0-7 are valid as dest charset */ 
     20#define UTF_16BE    000 
     21#define UTF_16LE    001 
     22#define UTF_32BE    002 
     23#define UTF_32LE    003 
     24#define WCHAR_T     004 
     25#define UTF_8       005 
     26#define US_ASCII    006 
     27#define LATIN_1     007 
     28 
     29/* additional charsets with algorithmic conversion */ 
     30#define LATIN_9     010 
     31#define TIS_620     011 
     32#define JIS_0201    012 
     33 
     34/* some programs like php need this */ 
    1035int _libiconv_version = _LIBICONV_VERSION; 
    1136 
    12 iconv_t iconv_open (const char *tocode, const char *fromcode) 
    13 { 
    14         /* ASCII -> UTF8 and ASCII -> ISO-8859-x mappings can be 
    15          * faked without doing any actual conversion, mapping 
    16          * between identical charsets is a no-op, so claim to 
    17          * support those. */ 
    18         if (!strncasecmp(fromcode, tocode, strlen(fromcode)) || 
    19             (!strncasecmp(tocode,   "UTF-8",     strlen("UTF-8")) && 
    20              !strncasecmp(fromcode, "ASCII",     strlen("ASCII"))) || 
    21             (!strncasecmp(tocode,   "ISO-8859-", strlen("ISO-8859-")) && 
    22              !strncasecmp(fromcode, "ASCII",     strlen("ASCII")))) 
    23         { 
    24                 return (iconv_t)(1); 
     37/* these must match the constants above */ 
     38static const unsigned char charsets[] = 
     39        "\005" "UTF-8"      "\0" 
     40        "\004" "WCHAR_T"    "\0" 
     41        "\000" "UTF-16BE"   "\0" 
     42        "\001" "UTF-16LE"   "\0" 
     43        "\002" "UTF-32BE"   "\0" 
     44        "\003" "UTF-32LE"   "\0" 
     45        "\006" "US-ASCII"   "\0" 
     46        "\007" "ISO-8859-1" "\0" 
     47        "\007" "LATIN1"     "\0" 
     48        "\010" "ISO-8859-15""\0" 
     49        "\010" "LATIN9"     "\0" 
     50        "\011" "ISO-8859-11""\0" 
     51        "\011" "TIS-620"    "\0" 
     52        "\012" "JIS-0201"   "\0" 
     53        "\377"; 
     54 
     55/* separate identifiers for sbcs/dbcs/etc map type */ 
     56#define UCS2_8BIT   000 
     57#define UCS3_8BIT   001 
     58#define EUC         002 
     59#define EUC_TW      003 
     60#define SHIFT_JIS   004 
     61#define BIG5        005 
     62#define GBK         006 
     63 
     64/* FIXME: these are not implemented yet 
     65// EUC:   A1-FE A1-FE 
     66// GBK:   81-FE 40-7E,80-FE 
     67// Big5:  A1-FE 40-7E,A1-FE 
     68*/ 
     69 
     70static const unsigned short maplen[] = { 
     71        [UCS2_8BIT] = 4+ 2* 128, 
     72        [UCS3_8BIT] = 4+ 3* 128, 
     73        [EUC]       = 4+ 2* 94*94, 
     74        [SHIFT_JIS] = 4+ 2* 94*94, 
     75        [BIG5]      = 4+ 2* 94*157, 
     76        [GBK]       = 4+ 2* 126*190, 
     77        [EUC_TW]    = 4+ 2* 2*94*94, 
     78}; 
     79 
     80static int find_charmap(const char *name) 
     81{ 
     82        int i; 
     83        for (i = 0; i < (sizeof(charmaps) / sizeof(charmaps[0])); i++) 
     84                if (!strcasecmp(charmaps[i].name, name)) 
     85                        return i; 
     86        return -1; 
     87} 
     88 
     89static int find_charset(const char *name) 
     90{ 
     91        const unsigned char *s; 
     92        for (s=charsets; *s<0xff && strcasecmp(s+1, name); s+=strlen(s)+1); 
     93        return *s; 
     94} 
     95 
     96iconv_t iconv_open(const char *to, const char *from) 
     97{ 
     98        unsigned f, t; 
     99        int m; 
     100 
     101        if ((t = find_charset(to)) >= 8) 
     102                return -1; 
     103 
     104        if ((f = find_charset(from)) < 255) 
     105                return 0 | (t<<1) | (f<<4); 
     106 
     107        if ((m = find_charmap(from)) > -1) 
     108                return 1 | (t<<1) | (m<<4); 
     109 
     110        return -1; 
     111} 
     112 
     113int iconv_close(iconv_t cd) 
     114{ 
     115        return 0; 
     116} 
     117 
     118static inline wchar_t get_16(const unsigned char *s, int endian) 
     119{ 
     120        endian &= 1; 
     121        return s[endian]<<8 | s[endian^1]; 
     122} 
     123 
     124static inline void put_16(unsigned char *s, wchar_t c, int endian) 
     125{ 
     126        endian &= 1; 
     127        s[endian] = c>>8; 
     128        s[endian^1] = c; 
     129} 
     130 
     131size_t iconv(iconv_t cd, char **in, size_t *inb, char **out, size_t *outb) 
     132{ 
     133        size_t x=0; 
     134        unsigned char to = (cd>>1)&7; 
     135        unsigned char from = 255; 
     136        const unsigned char *map = 0; 
     137        mbstate_t st = {0}; 
     138        char tmp[MB_LEN_MAX]; 
     139        wchar_t c, d; 
     140        size_t k, l; 
     141        int err; 
     142 
     143        if (!in || !*in || !*inb) return 0; 
     144 
     145        if (cd & 1) 
     146                map = charmaps[cd>>4].map; 
     147        else 
     148                from = cd>>4; 
     149 
     150        for (; *inb; *in+=l, *inb-=l) { 
     151                c = *(unsigned char *)*in; 
     152                l = 1; 
     153                if (from >= UTF_8 && c < 0x80) goto charok; 
     154                switch (from) { 
     155                case WCHAR_T: 
     156                        l = sizeof(wchar_t); 
     157                        if (*inb < l) goto starved; 
     158                        c = *(wchar_t *)*in; 
     159                        break; 
     160                case UTF_8: 
     161                        l = mbrtowc(&c, *in, *inb, &st); 
     162                        if (!l) l++; 
     163                        else if (l == (size_t)-1) goto ilseq; 
     164                        else if (l == (size_t)-2) goto starved; 
     165                        break; 
     166                case US_ASCII: 
     167                        goto ilseq; 
     168                case LATIN_9: 
     169                        if ((unsigned)c - 0xa4 <= 0xbe - 0xa4) { 
     170                                static const unsigned char map[] = { 
     171                                        0, 0x60, 0, 0x61, 0, 0, 0, 0, 0, 0, 0, 
     172                                        0, 0, 0, 0, 0x7d, 0, 0, 0, 0x7e, 0, 0, 0, 
     173                                        0x52, 0x53, 0x78 
     174                                }; 
     175                                if (c == 0xa4) c = 0x20ac; 
     176                                else if (map[c-0xa5]) c = 0x100 | map[c-0xa5]; 
     177                        } 
     178                case LATIN_1: 
     179                        goto charok; 
     180                case TIS_620: 
     181                        if (c >= 0xa1) c += 0x0e01-0xa1; 
     182                        goto charok; 
     183                case JIS_0201: 
     184                        if (c >= 0xa1) { 
     185                                if (c <= 0xdf) c += 0xff61-0xa1; 
     186                                else goto ilseq; 
     187                        } 
     188                        goto charok; 
     189                case UTF_16BE: 
     190                case UTF_16LE: 
     191                        l = 2; 
     192                        if (*inb < 2) goto starved; 
     193                        c = get_16(*in, from); 
     194                        if ((unsigned)(c-0xdc00) < 0x400) goto ilseq; 
     195                        if ((unsigned)(c-0xd800) < 0x400) { 
     196                                l = 4; 
     197                                if (*inb < 4) goto starved; 
     198                                d = get_16(*in + 2, from); 
     199                                if ((unsigned)(c-0xdc00) >= 0x400) goto ilseq; 
     200                                c = ((c-0xd800)<<10) | (d-0xdc00); 
     201                        } 
     202                        break; 
     203                case UTF_32BE: 
     204                case UTF_32LE: 
     205                        l = 4; 
     206                        if (*inb < 4) goto starved; 
     207                        // FIXME 
     208                        // c = get_32(*in, from); 
     209                        break; 
     210                default: 
     211                        /* only support ascii supersets */ 
     212                        if (c < 0x80) break; 
     213                        switch (map[0]) { 
     214                        case UCS2_8BIT: 
     215                                c -= 0x80; 
     216                                break; 
     217                        case EUC: 
     218                                if ((unsigned)c - 0xa1 >= 94) goto ilseq; 
     219                                if ((unsigned)in[0][1] - 0xa1 >= 94) goto ilseq; 
     220                                c = (c-0xa1)*94 + (in[0][1]-0xa1); 
     221                                l = 2; 
     222                                break; 
     223                        case SHIFT_JIS: 
     224                                if ((unsigned)c - 0xa1 <= 0xdf-0xa1) { 
     225                                        c += 0xff61-0xa1; 
     226                                        goto charok; 
     227                                } 
     228                                // FIXME... 
     229                                l = 2; 
     230                                break; 
     231                        default: 
     232                                goto badf; 
     233                        } 
     234                        c = get_16(map + 4 + 2*c, 0); 
     235                        if (c == 0xffff) goto ilseq; 
     236                        goto charok; 
     237                } 
     238 
     239                if ((unsigned)c - 0xd800 < 0x800 || (unsigned)c >= 0x110000) 
     240                        goto ilseq; 
     241charok: 
     242                switch (to) { 
     243                case WCHAR_T: 
     244                        if (*outb < sizeof(wchar_t)) goto toobig; 
     245                        *(wchar_t *)*out = c; 
     246                        *out += sizeof(wchar_t); 
     247                        *outb -= sizeof(wchar_t); 
     248                        break; 
     249                case UTF_8: 
     250                        if (*outb < 4) { 
     251                                k = wctomb(tmp, c); 
     252                                if (*outb < k) goto toobig; 
     253                                memcpy(*out, tmp, k); 
     254                        } else k = wctomb(*out, c); 
     255                        *out += k; 
     256                        *outb -= k; 
     257                        break; 
     258                case US_ASCII: 
     259                        if (c > 0x7f) c = 0xfffd; 
     260                        /* fall thru and count replacement in latin1 case */ 
     261                case LATIN_1: 
     262                        if (!*outb) goto toobig; 
     263                        if (c < 0x100) **out = c; 
     264                        else x++, **out = '*'; //FIXME: translit? 
     265                        ++*out; 
     266                        --*outb; 
     267                        break; 
     268                case UTF_16BE: 
     269                case UTF_16LE: 
     270                        if (c < 0x10000) { 
     271                                if (*outb < 2) goto toobig; 
     272                                put_16(*out, c, to); 
     273                                *out += 2; 
     274                                *outb -= 2; 
     275                                break; 
     276                        } 
     277                        if (*outb < 4) goto toobig; 
     278                        put_16(*out, (c>>10)|0xd800, to); 
     279                        put_16(*out + 2, (c&0x3ff)|0xdc00, to); 
     280                        *out += 4; 
     281                        *outb -= 4; 
     282                        break; 
     283                default: 
     284                        goto badf; 
     285                } 
    25286        } 
    26         else 
    27         { 
    28                 return (iconv_t)(-1); 
    29         } 
    30 } 
    31  
    32 size_t iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, 
    33                           char **outbuf, size_t *outbytesleft) 
    34 { 
    35         size_t len = 0; 
    36  
    37         if (cd == (iconv_t)(1)) 
    38         { 
    39                 if ((*inbytesleft < 0) || (*outbytesleft < 0) || 
    40                     (outbuf == NULL) || (*outbuf == NULL)) 
    41                 { 
    42                         errno = EINVAL; 
    43                         return (size_t)(-1); 
    44                 } 
    45  
    46                 if ((inbuf != NULL) && (*inbuf != NULL)) 
    47                 { 
    48                         len = (*inbytesleft > *outbytesleft) 
    49                                 ? *outbytesleft : *inbytesleft; 
    50  
    51                         memcpy(*outbuf, *inbuf, len); 
    52  
    53                         *inbuf        += len; 
    54                         *inbytesleft  -= len; 
    55                         *outbuf       += len; 
    56                         *outbytesleft -= len; 
    57  
    58                         if (*inbytesleft > 0) 
    59                         { 
    60                                 errno = E2BIG; 
    61                                 return (size_t)(-1); 
    62                         } 
    63                 } 
    64  
    65                 return (size_t)(0); 
    66         } 
    67         else 
    68         { 
    69                 errno = EBADF; 
    70                 return (size_t)(-1); 
    71         } 
    72 } 
    73  
    74 int iconv_close (iconv_t cd) 
    75 { 
    76         return 0; 
    77 } 
     287        return x; 
     288ilseq: 
     289        err = EILSEQ; 
     290        x = -1; 
     291        goto end; 
     292badf: 
     293        err = EBADF; 
     294        x = -1; 
     295        goto end; 
     296toobig: 
     297        err = E2BIG; 
     298        goto end; 
     299starved: 
     300        err = EINVAL; 
     301end: 
     302        errno = err; 
     303        return x; 
     304} 
  • packages/libs/libiconv/src/include/iconv.h

    r24775 r24870  
    1 /* 
    2  * Very simple iconv api stub. 
    3  */ 
    4  
    51#ifndef _ICONV_H 
    62#define _ICONV_H 1 
    73 
    8 #define _LIBICONV_VERSION 0x010B    /* version number: (major<<8) + minor */ 
    9 extern  int _libiconv_version; /* Likewise */ 
    10  
    114#include <stddef.h> 
    125 
    13 typedef void *iconv_t; 
     6#define _LIBICONV_VERSION 0x010B    /* version number: (major<<8) + minor */ 
     7extern int _libiconv_version; /* Likewise */ 
     8 
     9typedef long iconv_t; 
    1410 
    1511extern iconv_t 
Note: See TracChangeset for help on using the changeset viewer.