X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Flocale%2Ficonv.c;h=a0b0232015a2be6d4a3f42ea081b1eae1d055c95;hb=e13a2b8953ef;hp=d3caafa75aae5f61ae3cb33105d088a5d02efec6;hpb=734062b298e129a8f8bdae299f8d2b7b19419867;p=musl diff --git a/src/locale/iconv.c b/src/locale/iconv.c index d3caafa7..a0b02320 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -20,6 +20,7 @@ #define GB18030 0330 #define GBK 0331 #define GB2312 0332 +#define BIG5 0340 #define EUC_KR 0350 /* FIXME: these are not implemented yet @@ -48,6 +49,7 @@ static const unsigned char charmaps[] = "gb18030\0\0\330" "gbk\0\0\331" "gb2312\0\0\332" +"big5\0bigfive\0cp950\0big5hkscs\0\0\340" "euckr\0ksc5601\0ksx1001\0cp949\0\0\350" #include "codepages.h" ; @@ -64,6 +66,14 @@ static const unsigned short gb18030[126][190] = { #include "gb18030.h" }; +static const unsigned short big5[89][157] = { +#include "big5.h" +}; + +static const unsigned short hkscs[] = { +#include "hkscs.h" +}; + static const unsigned short ksc[93][94] = { #include "ksc.h" }; @@ -284,6 +294,43 @@ size_t iconv(iconv_t cd0, char **restrict in, size_t *restrict inb, char **restr if (d>63) d--; c = gb18030[c][d]; break; + case BIG5: + l = 2; + if (*inb < 2) goto starved; + d = *((unsigned char *)*in + 1); + if (d-0x40>=0xff-0x40 || d-0x7f<0xa1-0x7f) goto ilseq; + d -= 0x40; + if (d > 0x3e) d -= 0x22; + if (c-0xa1>=0xfa-0xa1) { + if (c-0x87>=0xff-0x87) goto ilseq; + if (c < 0xa1) c -= 0x87; + else c -= 0x87 + (0xfa-0xa1); + c = (hkscs[4867+(c*157+d)/16]>>(c*157+d)%16)%2<<17 + | hkscs[c*157+d]; + /* A few HKSCS characters map to pairs of UCS + * characters. These are mapped to surrogate + * range in the hkscs table then hard-coded + * here. Ugly, yes. */ + if (c/256 == 0xdc) { + if (totype-0300U > 8) k = 2; + else k = "\10\4\4\10\4\4\10\2\4"[totype-0300]; + if (k > *outb) goto toobig; + x += iconv((iconv_t)(uintptr_t)to, + &(char *){"\303\212\314\204" + "\303\212\314\214" + "\303\252\314\204" + "\303\252\314\214" + +c%256}, &(size_t){4}, + out, outb); + continue; + } + if (!c) goto ilseq; + break; + } + c -= 0xa1; + c = big5[c][d]|(c==0x27&&(d==0x3a||d==0x3c||d==0x42))<<17; + if (!c) goto ilseq; + break; case EUC_KR: l = 2; if (*inb < 2) goto starved;