cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1131 lines · 25.7 KB · C
RawDownload
/* * _codecs_iso2022.c: Codecs collection for ISO-2022 encodings. * * Written by Hye-Shik Chang <perky@FreeBSD.org> */ #define USING_IMPORTED_MAPS#define USING_BINARY_PAIR_SEARCH#define EXTERN_JISX0213_PAIR#define EMULATE_JISX0213_2000_ENCODE_INVALID MAP_UNMAPPABLE#define EMULATE_JISX0213_2000_DECODE_INVALID MAP_UNMAPPABLE #include "cjkcodecs.h"#include "alg_jisx0201.h"#include "emu_jisx0213_2000.h"#include "mappings_jisx0213_pair.h" /* STATE    state->c[0-3] 	00000000	||^^^^^|	|+-----+----  G0-3 Character Set	+-----------  Is G0-3 double byte?    state->c[4] 	00000000	      ||	      |+----  Locked-Shift?	      +-----  ESC Throughout*/ #define ESC			0x1B#define SO			0x0E#define SI			0x0F#define LF			0x0A #define MAX_ESCSEQLEN		16 #define CHARSET_ISO8859_1	'A'#define CHARSET_ASCII		'B'#define CHARSET_ISO8859_7	'F'#define CHARSET_JISX0201_K	'I'#define CHARSET_JISX0201_R	'J' #define CHARSET_GB2312		('A'|CHARSET_DBCS)#define CHARSET_JISX0208	('B'|CHARSET_DBCS)#define CHARSET_KSX1001		('C'|CHARSET_DBCS)#define CHARSET_JISX0212	('D'|CHARSET_DBCS)#define CHARSET_GB2312_8565	('E'|CHARSET_DBCS)#define CHARSET_CNS11643_1	('G'|CHARSET_DBCS)#define CHARSET_CNS11643_2	('H'|CHARSET_DBCS)#define CHARSET_JISX0213_2000_1	('O'|CHARSET_DBCS)#define CHARSET_JISX0213_2	('P'|CHARSET_DBCS)#define CHARSET_JISX0213_2004_1	('Q'|CHARSET_DBCS)#define CHARSET_JISX0208_O	('@'|CHARSET_DBCS) #define CHARSET_DBCS		0x80#define ESCMARK(mark)		((mark) & 0x7f) #define IS_ESCEND(c)	(((c) >= 'A' && (c) <= 'Z') || (c) == '@')#define IS_ISO2022ESC(c2) \		((c2) == '(' || (c2) == ')' || (c2) == '$' || \		 (c2) == '.' || (c2) == '&')	/* this is not a complete list of ISO-2022 escape sequence headers.	 * but, it's enough to implement CJK instances of iso-2022. */ #define MAP_UNMAPPABLE		0xFFFF#define MAP_MULTIPLE_AVAIL	0xFFFE /* for JIS X 0213 */ #define F_SHIFTED		0x01#define F_ESCTHROUGHOUT		0x02 #define STATE_SETG(dn, v)	((state)->c[dn]) = (v);#define STATE_GETG(dn)		((state)->c[dn]) #define STATE_G0		STATE_GETG(0)#define STATE_G1		STATE_GETG(1)#define STATE_G2		STATE_GETG(2)#define STATE_G3		STATE_GETG(3)#define STATE_SETG0(v)		STATE_SETG(0, v)#define STATE_SETG1(v)		STATE_SETG(1, v)#define STATE_SETG2(v)		STATE_SETG(2, v)#define STATE_SETG3(v)		STATE_SETG(3, v) #define STATE_SETFLAG(f)	((state)->c[4]) |= (f);#define STATE_GETFLAG(f)	((state)->c[4] & (f))#define STATE_CLEARFLAG(f)	((state)->c[4]) &= ~(f);#define STATE_CLEARFLAGS()	((state)->c[4]) = 0; #define ISO2022_CONFIG		((const struct iso2022_config *)config)#define CONFIG_ISSET(flag)	(ISO2022_CONFIG->flags & (flag))#define CONFIG_DESIGNATIONS	(ISO2022_CONFIG->designations) /* iso2022_config.flags */#define NO_SHIFT		0x01#define USE_G2			0x02#define USE_JISX0208_EXT	0x04 /*-*- internal data structures -*-*/ typedef int (*iso2022_init_func)(void);typedef ucs4_t (*iso2022_decode_func)(const unsigned char *data);typedef DBCHAR (*iso2022_encode_func)(const ucs4_t *data, Py_ssize_t *length); struct iso2022_designation {	unsigned char mark;	unsigned char plane;	unsigned char width;	iso2022_init_func initializer;	iso2022_decode_func decoder;	iso2022_encode_func encoder;}; struct iso2022_config {	int flags;	const struct iso2022_designation *designations; /* non-ascii desigs */}; /*-*- iso-2022 codec implementation -*-*/ CODEC_INIT(iso2022){	const struct iso2022_designation *desig = CONFIG_DESIGNATIONS;	for (desig = CONFIG_DESIGNATIONS; desig->mark; desig++)		if (desig->initializer != NULL && desig->initializer() != 0)			return -1;	return 0;} ENCODER_INIT(iso2022){	STATE_CLEARFLAGS()	STATE_SETG0(CHARSET_ASCII)	STATE_SETG1(CHARSET_ASCII)	return 0;} ENCODER_RESET(iso2022){	if (STATE_GETFLAG(F_SHIFTED)) {		WRITE1(SI)		NEXT_OUT(1)		STATE_CLEARFLAG(F_SHIFTED)	}	if (STATE_G0 != CHARSET_ASCII) {		WRITE3(ESC, '(', 'B')		NEXT_OUT(3)		STATE_SETG0(CHARSET_ASCII)	}	return 0;} ENCODER(iso2022){	while (inleft > 0) {		const struct iso2022_designation *dsg;		DBCHAR encoded;		ucs4_t c = **inbuf;		Py_ssize_t insize; 		if (c < 0x80) {			if (STATE_G0 != CHARSET_ASCII) {				WRITE3(ESC, '(', 'B')				STATE_SETG0(CHARSET_ASCII)				NEXT_OUT(3)			}			if (STATE_GETFLAG(F_SHIFTED)) {				WRITE1(SI)				STATE_CLEARFLAG(F_SHIFTED)				NEXT_OUT(1)			}			WRITE1((unsigned char)c)			NEXT(1, 1)			continue;		} 		DECODE_SURROGATE(c)		insize = GET_INSIZE(c); 		encoded = MAP_UNMAPPABLE;		for (dsg = CONFIG_DESIGNATIONS; dsg->mark; dsg++) {			Py_ssize_t length = 1;			encoded = dsg->encoder(&c, &length);			if (encoded == MAP_MULTIPLE_AVAIL) {				/* this implementation won't work for pair				 * of non-bmp characters. */				if (inleft < 2) {					if (!(flags & MBENC_FLUSH))						return MBERR_TOOFEW;					length = -1;				}				else					length = 2;#if Py_UNICODE_SIZE == 2				if (length == 2) {					ucs4_t u4in[2];					u4in[0] = (ucs4_t)IN1;					u4in[1] = (ucs4_t)IN2;					encoded = dsg->encoder(u4in, &length);				} else					encoded = dsg->encoder(&c, &length);#else				encoded = dsg->encoder(*inbuf, &length);#endif				if (encoded != MAP_UNMAPPABLE) {					insize = length;					break;				}			}			else if (encoded != MAP_UNMAPPABLE)				break;		} 		if (!dsg->mark)			return 1;		assert(dsg->width == 1 || dsg->width == 2); 		switch (dsg->plane) {		case 0: /* G0 */			if (STATE_GETFLAG(F_SHIFTED)) {				WRITE1(SI)				STATE_CLEARFLAG(F_SHIFTED)				NEXT_OUT(1)			}			if (STATE_G0 != dsg->mark) {				if (dsg->width == 1) {					WRITE3(ESC, '(', ESCMARK(dsg->mark))					STATE_SETG0(dsg->mark)					NEXT_OUT(3)				}				else if (dsg->mark == CHARSET_JISX0208) {					WRITE3(ESC, '$', ESCMARK(dsg->mark))					STATE_SETG0(dsg->mark)					NEXT_OUT(3)				}				else {					WRITE4(ESC, '$', '(',						ESCMARK(dsg->mark))					STATE_SETG0(dsg->mark)					NEXT_OUT(4)				}			}			break;		case 1: /* G1 */			if (STATE_G1 != dsg->mark) {				if (dsg->width == 1) {					WRITE3(ESC, ')', ESCMARK(dsg->mark))					STATE_SETG1(dsg->mark)					NEXT_OUT(3)				}				else {					WRITE4(ESC, '$', ')',						ESCMARK(dsg->mark))					STATE_SETG1(dsg->mark)					NEXT_OUT(4)				}			}			if (!STATE_GETFLAG(F_SHIFTED)) {				WRITE1(SO)				STATE_SETFLAG(F_SHIFTED)				NEXT_OUT(1)			}			break;		default: /* G2 and G3 is not supported: no encoding in			  * CJKCodecs are using them yet */			return MBERR_INTERNAL;		} 		if (dsg->width == 1) {			WRITE1((unsigned char)encoded)			NEXT_OUT(1)		}		else {			WRITE2(encoded >> 8, encoded & 0xff)			NEXT_OUT(2)		}		NEXT_IN(insize)	} 	return 0;} DECODER_INIT(iso2022){	STATE_CLEARFLAGS()	STATE_SETG0(CHARSET_ASCII)	STATE_SETG1(CHARSET_ASCII)	STATE_SETG2(CHARSET_ASCII)	return 0;} DECODER_RESET(iso2022){	STATE_SETG0(CHARSET_ASCII)	STATE_CLEARFLAG(F_SHIFTED)	return 0;} static Py_ssize_tiso2022processesc(const void *config, MultibyteCodec_State *state,		  const unsigned char **inbuf, Py_ssize_t *inleft){	unsigned char charset, designation;	Py_ssize_t i, esclen; 	for (i = 1;i < MAX_ESCSEQLEN;i++) {		if (i >= *inleft)			return MBERR_TOOFEW;		if (IS_ESCEND((*inbuf)[i])) {			esclen = i + 1;			break;		}		else if (CONFIG_ISSET(USE_JISX0208_EXT) && i+1 < *inleft &&			 (*inbuf)[i] == '&' && (*inbuf)[i+1] == '@')			i += 2;	} 	if (i >= MAX_ESCSEQLEN)		return 1; /* unterminated escape sequence */ 	switch (esclen) {	case 3:		if (IN2 == '$') {			charset = IN3 | CHARSET_DBCS;			designation = 0;		}		else {			charset = IN3;			if (IN2 == '(') designation = 0;			else if (IN2 == ')') designation = 1;			else if (CONFIG_ISSET(USE_G2) && IN2 == '.')				designation = 2;			else return 3;		}		break;	case 4:		if (IN2 != '$')			return 4; 		charset = IN4 | CHARSET_DBCS;		if (IN3 == '(') designation = 0;		else if (IN3 == ')') designation = 1;		else return 4;		break;	case 6: /* designation with prefix */		if (CONFIG_ISSET(USE_JISX0208_EXT) &&		    (*inbuf)[3] == ESC && (*inbuf)[4] == '$' &&		    (*inbuf)[5] == 'B') {			charset = 'B' | CHARSET_DBCS;			designation = 0;		}		else			return 6;		break;	default:		return esclen;	} 	/* raise error when the charset is not designated for this encoding */	if (charset != CHARSET_ASCII) {		const struct iso2022_designation *dsg; 		for (dsg = CONFIG_DESIGNATIONS; dsg->mark; dsg++)			if (dsg->mark == charset)				break;		if (!dsg->mark)			return esclen;	} 	STATE_SETG(designation, charset)	*inleft -= esclen;	(*inbuf) += esclen;	return 0;} #define ISO8859_7_DECODE(c, assi)					\	if ((c) < 0xa0) (assi) = (c);					\	else if ((c) < 0xc0 && (0x288f3bc9L & (1L << ((c)-0xa0))))	\		(assi) = (c);						\	else if ((c) >= 0xb4 && (c) <= 0xfe && ((c) >= 0xd4 ||		\		 (0xbffffd77L & (1L << ((c)-0xb4)))))			\		(assi) = 0x02d0 + (c);					\	else if ((c) == 0xa1) (assi) = 0x2018;				\	else if ((c) == 0xa2) (assi) = 0x2019;				\	else if ((c) == 0xaf) (assi) = 0x2015; static Py_ssize_tiso2022processg2(const void *config, MultibyteCodec_State *state,		 const unsigned char **inbuf, Py_ssize_t *inleft,		 Py_UNICODE **outbuf, Py_ssize_t *outleft){	/* not written to use encoder, decoder functions because only few	 * encodings use G2 designations in CJKCodecs */	if (STATE_G2 == CHARSET_ISO8859_1) {		if (IN3 < 0x80)			OUT1(IN3 + 0x80)		else			return 3;	}	else if (STATE_G2 == CHARSET_ISO8859_7) {		ISO8859_7_DECODE(IN3 ^ 0x80, **outbuf)		else return 3;	}	else if (STATE_G2 == CHARSET_ASCII) {		if (IN3 & 0x80) return 3;		else **outbuf = IN3;	}	else		return MBERR_INTERNAL; 	(*inbuf) += 3;	*inleft -= 3;	(*outbuf) += 1;	*outleft -= 1;	return 0;} DECODER(iso2022){	const struct iso2022_designation *dsgcache = NULL; 	while (inleft > 0) {		unsigned char c = IN1;		Py_ssize_t err; 		if (STATE_GETFLAG(F_ESCTHROUGHOUT)) {			/* ESC throughout mode:			 * for non-iso2022 escape sequences */			WRITE1(c) /* assume as ISO-8859-1 */			NEXT(1, 1)			if (IS_ESCEND(c)) {				STATE_CLEARFLAG(F_ESCTHROUGHOUT)			}			continue;		} 		switch (c) {		case ESC:			REQUIRE_INBUF(2)			if (IS_ISO2022ESC(IN2)) {				err = iso2022processesc(config, state,							inbuf, &inleft);				if (err != 0)					return err;			}			else if (CONFIG_ISSET(USE_G2) && IN2 == 'N') {/* SS2 */				REQUIRE_INBUF(3)				err = iso2022processg2(config, state,					inbuf, &inleft, outbuf, &outleft);				if (err != 0)					return err;			}			else {				WRITE1(ESC)				STATE_SETFLAG(F_ESCTHROUGHOUT)				NEXT(1, 1)			}			break;		case SI:			if (CONFIG_ISSET(NO_SHIFT))				goto bypass;			STATE_CLEARFLAG(F_SHIFTED)			NEXT_IN(1)			break;		case SO:			if (CONFIG_ISSET(NO_SHIFT))				goto bypass;			STATE_SETFLAG(F_SHIFTED)			NEXT_IN(1)			break;		case LF:			STATE_CLEARFLAG(F_SHIFTED)			WRITE1(LF)			NEXT(1, 1)			break;		default:			if (c < 0x20) /* C0 */				goto bypass;			else if (c >= 0x80)				return 1;			else {				const struct iso2022_designation *dsg;				unsigned char charset;				ucs4_t decoded; 				if (STATE_GETFLAG(F_SHIFTED))					charset = STATE_G1;				else					charset = STATE_G0; 				if (charset == CHARSET_ASCII) {bypass:					WRITE1(c)					NEXT(1, 1)					break;				} 				if (dsgcache != NULL &&

Lines 1–500 of 1131.