#include "_jpeglib.h"
#include "jpeg.h"

// OnMemory版は#define ONMEM

static UR68	xdat={0,0};	// 保持中のデータ
static short	xbits=0;	// xdatの上位何ビットが有効か；＝０なら無し
#define	SZDATIN	16		// xdatの内データ保持に使うビット数(.w[LW])

#define	BitInInit()	{\
	xbits=0;	\
	xdat.l=0;	\
}

void m(BitInFlush())
// 新規データ／ファイル読みだし前の初期化
// 読みだしデータ／ファイルを切り替える時はこれを呼び出すこと
{
	BitInInit();
}

inline int Jgetc(JDATA(p))
// return : >=0:OK , EOF(<0):error（ファイルのみ）
{
int c;
	#ifdef ONMEM
	c=*(*p)++;
	#else
	if ((c=fgetc(p))<0) {
		//printf("Jgetc Error\n");
		c=EOF;
	}
	#endif
	//printf("<%02x>",c);
	return(c);
}

int m(GetMaker(JDATA(p)))
// リスタートマーカー(16bit)読みだし
// return : >=0:マーカーコード , EOF(<0):error（ファイルのみ） , EOF-1:マーカーでない
{
int c;
	BitInInit();
	c=Jgetc(p);
	#ifndef ONMEM
	if (c==EOF) {
		//printf("GetMaker Error1\n");
		return(EOF);
	}
	#endif
	if (c!=JPGMAKHED) {
		//printf("Err:$%02x\n",c);
		return(EOF-1);
	}
	// マーカー本体を返す
	c=Jgetc(p);
	#ifndef ONMEM
	if (c==EOF) {
		//printf("GetMaker Error2\n");
		return(EOF);
	}
	#endif
	return((JPGMAKHED<<8)|c);
}

static int Jgetw(JDATA(p))
// 16bit入力:JPEGセグメントマーカー対応
// return : >=0:OK , EOF(<0):error（ファイルのみ） , EOF-1:マーカー異常
{
int c,c1;
	// 読み出しとしては次のパターンがある(xx=８ビットデータ)。
	// 1. [xx xx]    : 通常
	// 2. [xx FF ??] : $xxFFがデータ,??は無視
	// 3. [FF ?? xx] : $FFxxがデータ,??は無視
	// 4. [xx EOF]   : [xx 00]として読み取る；ファイル最後で８ビットしかない
	c=Jgetc(p);
	#ifndef ONMEM
	if (c==EOF) {
		//printf("Jgetw Error1\n");
		return(EOF);
	}
	#endif
	if (c==JPGMAKHED) {
		// 3. [FF ?? xx] : $FFxxがデータ,??は無視
		// リスタートマーカーの処理がある時で??=RST0〜RST7なら、このパターンは必ず
		// リスタートマーカーでの読み込みになるので、BitInからは来ない（来たら異常）
		// （逆に言えば、ヘッダーにリスタートマーカー定義がある時は必ず
		// 　リスタートマーカー処理を行う必要がある。）
		c1=Jgetc(p);
		#ifndef ONMEM
		if (c1<=EOF) {
			//printf("Jgetw Error2\n");
			return(EOF);
		}
		#endif
		if (c1>=(RST0&0xff) && c1<=(RST7&0xff)) {
			// リスタートマーカーとして正しいなら、
			// 次の要求されるのはリスタートマーカー処理のはずなのでそれを返す
			//printf("Restart:$%02x]\n",c1);
			return((c<<8)|c1);
		}
		if (c1!=0x00) {
			// マーカーがおかしい
			//printf("マーカー異常:$%02x]\n",c1);
			return(EOF-1);
		}
	}
	c1=Jgetc(p);
	#ifndef ONMEM
	if (c1==EOF) { // 4のパターン（ファイル最後で８ビットしかない時）
		c1=0x00;
		// printf("Jgetw Error3\n");
		// return(EOF);
	}
	#endif
	if (c1==JPGMAKHED) {
		// 2. [xx FF ??] : $xxFFがデータ,??は無視
		// FF??がリスタートマーカーの可能性もあるので、ここでは８ビット読み込みに変更して
		// 次の読み込みでFFから読み込むようにする。
		//printf("Read8bit:%08b($%02x)]\n",c,c);
		xdat.w[LW]=(unshort)(c<<8);
		xbits=8; // 8bitReadの印
		// 今読み込んだJPGMAKHEDを戻す
		#ifdef ONMEM
		(*p)--;
		#else
		ungetc(c1,p);
		#endif
	} else {
		c=(c<<8)|c1;
		//printf("Read16bit:%016b($%04x)]\n",c,c);
		xdat.w[LW]=(unshort)c;
		xbits=16; // 16bitReadの印
	}
	return(c);
}

int m(BitIn(JDATA(p),int bits))
// p      : 入力するファイル "rb"でオープンしておくこと（ファイルのみ）
// bits   : 何ビット読み込むか(1〜16)
// return : 入力したデータ/EOF=エラー（ファイルのみ）
// ビット単位入力をするのは画像データ本体のみ
{
int bits0;
	bits0=bits;
	// 処理の手順は、.lを<<して.w[LW]から.w[HW]に入ったものを返す。
	xdat.w[HW]=0;
	if (xbits==0) goto XDATIN_READ; // データがない時
	while (xbits<bits) {
		// まず残り分を押し上げておく
		xdat.l<<=xbits;
		bits-=xbits;
		// 一端データを読み込んでから不足分を上げる
	    XDATIN_READ:;
		if (Jgetw(p)==EOF) return(EOF); // xbits=8/16とx.dat[LW]はここで設定
	}
	xdat.l<<=bits;
	xbits-=bits;
	return((int)xdat.w[HW]);
}

int m(BitIn1(JDATA(p)))
// １ビット専用BitIn（よく使うので別にして高速化した）
// p      : 入力するファイル "rb"でオープンしておくこと（ファイルのみ）
// return : 入力したデータ/EOF=エラー（ファイルのみ）
{
	xdat.w[HW]=0;
	if (xbits==0) {
		if (Jgetw(p)==EOF) {
			//printf("BitIn1 Error\n");
			return(EOF); // xbits=8/16とx.dat[LW]はここで設定
		}
	}
	xdat.l<<=1;
	xbits--;
	return((int)xdat.w[HW]);
}
