#include <stdlib.h>
#include <limits.h>
#include <stdint.h>
+#include "locale_impl.h"
#define UTF_32BE 0300
#define UTF_16LE 0301
#define BIG5 0340
#define EUC_KR 0350
-/* FIXME: these are not implemented yet
- * EUC: A1-FE A1-FE
- * GBK: 81-FE 40-7E,80-FE
- * Big5: A1-FE 40-7E,A1-FE
- */
-
/* Definitions of charmaps. Each charmap consists of:
* 1. Empty-string-terminated list of null-terminated aliases.
* 2. Special type code or number of elided entries.
* 3. Character table (size determined by field 2). */
static const unsigned char charmaps[] =
-"utf8\0\0\310"
+"utf8\0char\0\0\310"
"wchart\0\0\306"
"ucs2\0ucs2be\0\0\304"
"ucs2le\0\0\305"
"gb18030\0\0\330"
"gbk\0\0\331"
"gb2312\0\0\332"
-"big5\0bigfive\0cp950\0\0\340"
+"big5\0bigfive\0cp950\0big5hkscs\0\0\340"
"euckr\0ksc5601\0ksx1001\0cp949\0\0\350"
#include "codepages.h"
;
#include "big5.h"
};
+static const unsigned short hkscs[] = {
+#include "hkscs.h"
+};
+
static const unsigned short ksc[93][94] = {
#include "ksc.h"
};
static size_t find_charmap(const void *name)
{
const unsigned char *s;
+ if (!*(char *)name) name=charmaps; /* "utf8" */
for (s=charmaps; *s; ) {
if (!fuzzycmp(name, s)) {
for (; *s; s+=strlen((void *)s)+1);
int err;
unsigned char type = map[-1];
unsigned char totype = tomap[-1];
+ locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
if (!in || !*in || !*inb) return 0;
+ *ploc = UTF8_LOCALE;
+
for (; *inb; *in+=l, *inb-=l) {
c = *(unsigned char *)*in;
l = 1;
l = 2;
if (*inb < 2) goto starved;
d = *((unsigned char *)*in + 1);
- if (c-0xa1>=0xfa-0xa1) goto ilseq;
- c -= 0xa1;
if (d-0x40>=0xff-0x40 || d-0x7f<0xa1-0x7f) goto ilseq;
d -= 0x40;
if (d > 0x3e) d -= 0x22;
- c = big5[c][d];
+ 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:
break;
}
}
+ *ploc = loc;
return x;
ilseq:
err = EILSEQ;
x = -1;
end:
errno = err;
+ *ploc = loc;
return x;
}