/* $Id: decode.h,v 1.21 2014/02/10 10:50:35 onoe Exp $ */

/*-
 * Copyright (c) 1998-2000 Atsushi Onoe
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

struct decode {
	char	*buf;
	int	bufsiz;
	int	cnt;
	void	(*flsbuf)(struct decode *dp);
	void	*flsarg;
	u_long	pend;
	u_char	cscode[4];	/* G0-G3 */
	u_int	err:1,
		encoded:1,
		noconv:1,
		notext:1,
		sjis:2,
		utf8:1,
		gbk:1,
		shift:1,
		bclen:2,
		html:1;
	u_char	skip;
	char	skipbuf[8];
	int	skiplen;
};
#define	SKIP_COMMENT	0x80
#define	SKIP_STYLE	0x81
#define	SKIP_SCRIPT	0x82
#define	SKIP_PUT(dp, c)	do {						\
	(dp)->skipbuf[(dp)->skiplen++ % sizeof((dp)->skipbuf)] = 	\
		(char)(c);						\
} while (0)

extern const char b64[], hex[], uue[], hqx[];
extern char rb64[], rhex[], ruue[], rhqx[];

static void
OFLUSH(struct decode *dp)
{
	if (dp->bufsiz != 0 && dp->flsbuf != NULL) {
		(*dp->flsbuf)(dp);
	} else {
		dp->bufsiz += CHARBLOCK;
		dp->buf = realloc(dp->buf, dp->bufsiz);
	}
}

#define	OUTC(dp, c) do {						\
	if ((dp)->cnt >= (dp)->bufsiz)					\
		OFLUSH(dp);						\
	(dp)->buf[(dp)->cnt++] = (char)(c);				\
} while (0)

static void
BFLUSH(struct decode *dp)
{
	u_char x;
	int i;

	while (dp->bclen > 0) {
		for (i = 0; i < 4; i++) {
			if (6 * i < 8 * dp->bclen)
				x = b64[(dp->pend >> (6 * (3-i))) & 0x3f];
			else
				x = '=';
			OUTC(dp, x);
		}
		dp->pend = 0;
		dp->bclen = 0;
	}
}

#define	BOUTC(dp, c) do {						\
	(dp)->pend |= (u_char)(c) << (8 * (2 - (dp)->bclen));		\
	if (++(dp)->bclen == 3)						\
		BFLUSH(dp);						\
} while (0)
