/*	
 *	cliplzss.h
 *
 *	LZSS展開ルーチン
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2013 Naoyuki Sawa
 *
 *	* Thu Sep 10 00:42:56 JST 2009 Naoyuki Sawa
 *	- 新規作成。
 *	* Sun Jul 07 18:34:29 JST 2013 Naoyuki Sawa
 *	- LZSS_1、LZSS_1_init()、LZSS_1_get()を追加しました。
 *	- LZSS_2、LZSS_2_init()、LZSS_2_get()を追加しました。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_LZSS_H__
#define __CLIP_LZSS_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/****************************************************************************
 *	
 ****************************************************************************/

/* 「tool/dlzss12.exe -1 -e」で圧縮されたデータを、展開します。
 * [in]
 *	dst_data	出力バッファ。
 *	dst_lim		出力バッファの最大バイト数。
 *	src_data	入力データ。
 *	src_len		入力データのバイト数。
 * [out]
 *	戻り値		展開データのバイト数。
 * [note]
 *	* 「tool/dlzss12.exe -1 -e」は、ウインドウサイズ15、最大一致長17で、バイト単位の圧縮を行います。
 *	  圧縮データの詳細は、「tool/dlzss12/main.c」を参照してください。
 *	* 出力バッファのバイト数が、展開データのバイト数よりも小さい場合、超過した分は格納しません。
 *	  その場合も、展開データのバイト数は、本来の展開データのバイト数を返します。
 *	- dst_limに0を指定して、展開データのバイト数の情報を取得することも可能です。
 *	  その場合、dst_dataは参照されないので、NULLを指定しても構いません。
 *	  <例>
 *		dst_len = lzss_uncompress1(NULL, 0, src_data, src_len); // 展開データのバイト数を取得する
 *		dst_data = malloc(dst_len);                             // 出力バッファを確保する
 *		lzss_uncompress1(dst_data, dst_len, src_data, src_len); // 展開データを取得する
 */
int lzss_uncompress1(void* dst_data/*[dst_lim]*/, int dst_lim, const void* src_data/*[src_len]*/, int src_len);

/* 「tool/dlzss12.exe -2 -e」で圧縮されたデータを、展開します。
 * [in]
 *	dst_data	出力バッファ。
 *	dst_lim		出力バッファの最大バイト数。
 *	src_data	入力データ。
 *	src_len		入力データのバイト数。
 * [out]
 *	戻り値		展開データのバイト数。
 * [note]
 *	* 「tool/dlzss12.exe -2 -e」は、ウインドウサイズ4096、最大一致長17で、ハーフワード単位の圧縮を行います。
 *	  圧縮データの詳細は、「tool/dlzss12/main.c」を参照してください。
 *	* 出力バッファのバイト数が、展開データのバイト数よりも小さい場合、超過した分は格納しません。
 *	  その場合も、展開データのバイト数は、本来の展開データのバイト数を返します。
 *	- dst_limに0を指定して、展開データのバイト数の情報を取得することも可能です。
 *	  その場合、dst_dataは参照されないので、NULLを指定しても構いません。
 *	  <例>
 *		dst_len = lzss_uncompress2(NULL, 0, src_data, src_len); // 展開データのバイト数を取得する
 *		dst_data = malloc(dst_len);                             // 出力バッファを確保する
 *		lzss_uncompress2(dst_data, dst_len, src_data, src_len); // 展開データを取得する
 */
int lzss_uncompress2(void* dst_data/*[dst_lim]*/, int dst_lim, const void* src_data/*[src_len]*/, int src_len);

/****************************************************************************
 *	
 ****************************************************************************/

// - 「tool/dlzss12.exe -1 -e」で圧縮されたデータを、1バイトずつ逐次展開する展開ストリームです。
//   一度で展開する場合は、「lzss_uncompress1()」を使う方が、効率が良いです。
//
// - 「lzss_uncompress1(dstData, dstBytes, srcData, srcBytes)」に等価な処理は、以下のとおりです:
//   入力データの終端や、出力バッファの終端をチェックする必要が無い場合は、もっと単純化できます。
//
//	LZSS_1 lzss;
//	      unsigned char* dstData  = …; //出力バッファ
//	      unsigned       dstBytes = …; //出力バッファの最大バイト数
//	const          void* srcData  = …; //入力データ
//	      unsigned       srcBytes = …; //入力データのバイト数
//	      unsigned char* dstEnd   = (void*)((unsigned)dstData + dstBytes); //出力バッファの終端位置を求めておく
//	const unsigned char* srcEnd   = (void*)((unsigned)srcData + srcBytes); //入力データ  の終端位置を求めておく
//	LZSS_1_init(&lzss, srcData);				//展開ストリームを初期化する。
//	while((dstData < dstEnd) &&				//出力バッファの終端に達しておらず、かつ、
//	      ((lzss.data < srcEnd) || (lzss.len != 0))) {	//入力データ終端に達していないか，最後の圧縮コードを展開中ならば…
//		*dstData++ = LZSS_1_get(&lzss);			//次の1バイトを取得し、出力バッファに格納する。
//	}

typedef struct _LZSS_1 {
	const unsigned char* data;	/* + 0, 4 */
	unsigned char flag_mask;	/* + 4, 1 */
	unsigned char flag;		/* + 5, 1 */
	unsigned char len;		/* + 6, 1 */
	unsigned char dist;		/* + 7, 1 */
	unsigned char pos;		/* + 8, 1 */
	unsigned char dic[16];		/* + 9,16 */
} LZSS_1;				/* =25    */

/* 展開ストリームを初期化します。
 * [in]
 *	self	展開ストリーム構造体
 *	data	圧縮データ
 * [out]
 *	無し
 */
void LZSS_1_init(LZSS_1* self, const void* data);

/* 次の1バイトを取得します。
 * [in]
 *	self	展開ストリーム構造体
 * [out]
 *	戻り値	次の1バイト
 */
unsigned char LZSS_1_get(LZSS_1* self);

/*--------------------------------------------------------------------------*/

// - 「tool/dlzss12.exe -2 -e」で圧縮されたデータを、2バイトずつ逐次展開する展開ストリームです。
//   一度で展開する場合は、「lzss_uncompress2()」を使う方が、効率が良いです。
//
// - 「lzss_uncompress2(dstData, dstBytes, srcData, srcBytes)」に等価な処理は、以下のとおりです:
//   入力データの終端や、出力バッファの終端をチェックする必要が無い場合は、もっと単純化できます。
//
//	LZSS_2 lzss;
//	      unsigned short* dstData  = …; //出力バッファ
//	      unsigned        dstBytes = …; //出力バッファの最大バイト数
//	const          void*  srcData  = …; //入力データ
//	      unsigned        srcBytes = …; //入力データのバイト数
//	      unsigned short* dstEnd   = (void*)((unsigned)dstData + dstBytes); //出力バッファの終端位置を求めておく
//	const unsigned short* srcEnd   = (void*)((unsigned)srcData + srcBytes); //入力データ  の終端位置を求めておく
//	if(((dstBytes | srcBytes) & 1) != 0) { DIE(); }		//奇数サイズの入力データや、奇数サイズの出力バッファには対応していません。
//	LZSS_1_init(&lzss, srcData);				//展開ストリームを初期化する。
//	while((dstData < dstEnd) &&				//出力バッファの終端に達しておらず、かつ、
//	      ((lzss.data < srcEnd) || (lzss.len != 0))) {	//入力データ終端に達していないか，最後の圧縮コードを展開中ならば…
//		*dstData++ = LZSS_1_get(&lzss);			//次の1バイトを取得し、出力バッファに格納する。
//	}
//
// - ■重要な制限事項■
//   奇数サイズの入力データや、奇数サイズの出力バッファには対応していません。
//   本ストリームを使って展開するデータは、「tool/dlzss12.exe -2 -e」で圧縮する前に、元データを偶数サイズにパディングしてください。
//   尚、「lzss_uncompress2()」には、そのような制限はありませんので、「lzss_uncompress2()」を使う場合は、奇数サイズでも大丈夫です。

typedef struct _LZSS_2 {
	const unsigned short* data;	/* +   0,   4 */
	unsigned short flag_mask;	/* +   4,   2 */
	unsigned short flag;		/* +   6,   2 */
	unsigned short pos;		/* +   8,   2 */
	unsigned short dist;		/* +  10,   2 */
	unsigned char  len;		/* +  12,   1 */
//	unsigned char  padding;		/* +  13,   1 */
	unsigned short dic[4096];	/* +  14,8192 */
} LZSS_2;				/* =8206      */

/* 展開ストリームを初期化します。
 * [in]
 *	self	展開ストリーム構造体
 *	data	圧縮データ
 * [out]
 *	無し
 */
void LZSS_2_init(LZSS_2* self, const void* data);

/* 次の2バイトを取得します。
 * [in]
 *	self	展開ストリーム構造体
 * [out]
 *	戻り値	次の2バイト
 * [note]
 *	- 奇数サイズの圧縮データには対応していません。
 *	  本ストリームを使って展開するデータは、「tool/dlzss12.exe -2 -e」で圧縮する前に、元データを偶数サイズにパディングしてください。
 *	  尚、「lzss_uncompress2()」には、そのような制限はありませんので、「lzss_uncompress2()」を使う場合は、奇数サイズでも大丈夫です。
 */
unsigned short LZSS_2_get(LZSS_2* self);

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_LZSS_H__*/
