/*	
 *	cliptlz.h
 *
 *	簡易LZ圧縮
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2008 Naoyuki Sawa
 *
 *	* Sun Feb 17 22:17:30 JST 2008 Naoyuki Sawa
 *	- 1st リリース。
 *	- フットプリントの極小化を目的として作成した、簡易LZ圧縮形式です。
 *	  一般的なLZ圧縮形式では、展開ストリームごとに数キロバイトの辞書バッファを持つのですが、
 *	  組み込み用CPなどのRAMの少ない環境で、多数の展開ストリームを並行して読み出す必要が有る場合に、
 *	  展開ストリームあたりの管理構造体サイズが大きすぎてネックとなります。
 *	  本モジュールの圧縮形式は辞書バッファを15バイトとし、それに合わせて展開ルーチンも最適化しました。
 *	  辞書バッファが小さいため圧縮効率は良くありませんが、前述のようなRAMの少ない環境でも利用可能です。
 *	* Mon Mar 02 21:48:23 JST 2009 Naoyuki Sawa
 *	- TinyLZc構造体、TinyLZc_init()関数、TinyLZc_put()関数を追加しました。
 *	- TinyLZ_compress()関数を再実装し、P/ECEコンパイル時も有効にしました。
 */
#ifndef __CLIP_TLZ_H__
#define __CLIP_TLZ_H__

/****************************************************************************
 *	展開
 ****************************************************************************/

/* 簡易LZ圧縮の展開ストリームを管理する構造体です。 */
typedef struct _TinyLZ {
	const unsigned char* p;		/* + 0, 4 */
	unsigned char len_pos;		/* + 4, 1 = (len<<4)|pos */
	unsigned char dic[15];		/* + 5,15 */
} TinyLZ;				/* =20 */

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

/* 展開ストリームを初期化します。
 * [in]
 *	tlz		TinyLZ構造体へのポインタ。
 *	p		圧縮データの先頭アドレス。
 */
void TinyLZ_init(TinyLZ* tlz, const void* p);

/* 展開ストリームから1バイト読み出します。
 * [in]
 *	tlz		TinyLZ構造体へのポインタ。
 * [out]
 *	戻り値		読み出したデータ。(0〜255)
 * [note]
 *	* 本モジュールの圧縮形式には、展開ストリームの終端を判断する機能が有りません。
 *	  フットプリントを極小化するために、圧縮形式を単純化したためです。
 *	  アプリケーション側で以下のような方法を使って、展開ストリームの終端を判断してください。
 *
 *	- 圧縮前のデータを固定サイズとする方法
 *		TinyLZ_init(&tlz, compressed_data);
 *		for(i = 0; i < UNCOMPRESSED_SIZE; i++) {
 *			c = TinyLZ_get(&tlz);
 *			...
 *		}
 *
 *	- 圧縮前のデータに終端マークを埋め込んでおく方法
 *		TinyLZ_init(&tlz, compressed_data);
 *		for(;;) {
 *			c = TinyLZ_get(&tlz);
 *			if(c == '\x1A') break;
 *			...
 *		}
 *
 *	- 圧縮データの終端を監視する方法 (TinyLZ_uncompress()の実装を参照してください)
 *		TinyLZ_init(&tlz, compressed_data);
 *		while((tlz.p < &compressed_data[COMPRESSED_SIZE]) || (tlz.len_pos > 15)) {
 *			c = TinyLZ_get(&tlz);
 *			...
 *		}
 */
int TinyLZ_get(TinyLZ* tlz);

/* 圧縮データを展開します。
 * [in]
 *	_dst		展開バッファの先頭アドレス。
 *	dst_max		展開バッファのバイト数。
 *	_src		圧縮データの先頭アドレス。
 *	src_len		圧縮データのバイト数。
 * [out]
 *	戻り値		展開データのバイト数。
 *	_dst[]		展開データ。
 * [note]
 *	* 展開データが展開バッファを超える場合、超えた分は書き込みません。
 *	  その場合も、戻り値の展開データのバイト数は、超えた分を含みます。
 *	  この挙動を利用して、たとえば以下のように処理することができます。
 *		dst_max = TinyLZ_uncompress(NULL, 0, src, src_len); // 展開データのバイト数を取得
 *		dst = malloc(dst_len);                              // 展開バッファを確保
 *		TinyLZ_uncompress(dst, dst_max, src, src_len);      // 展開
 *	* 本モジュールの基本的な使い方は、TinyLZ_init()とTinyLZ_get()を使って1バイトづつ展開ですが、
 *	  圧縮データ全体を一気に展開するユーティリティとして、本関数を用意しました。
 */
int TinyLZ_uncompress(void* _dst, int dst_max, const void* _src, int src_len);

/****************************************************************************
 *	圧縮
 ****************************************************************************/

/* 簡易LZ圧縮の圧縮ストリームを管理する構造体です。 */
typedef struct _TinyLZc {
	unsigned char* dst;				/* + 0, 4 */
	unsigned char* end;				/* + 4, 4 */
	unsigned char src_len;				/* + 8, 1 */
	unsigned char imm_len;				/* + 9, 1 */
	unsigned char buf[15/*dic*/ + 15/*src*/];	/* +10,30 */
} TinyLZc;						/* +40 */

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

/* 圧縮ストリームを初期化します。
 * [in]
 *	self		TinyLZc構造体へのポインタ。
 *	dst		圧縮データ格納バッファの先頭アドレス。
 *	dst_max		圧縮データ格納バッファの最大バイト数。
 */
void TinyLZc_init(TinyLZc* self, void* dst, int dst_max);

/* 圧縮ストリームに1バイト書き込みます。
 * [in]
 *	self		TinyLZc構造体へのポインタ。
 *	c		書き込むデータ(0〜255)、または、EOF(-1)。
 * [note]
 *	* TinyLZc_init()、TinyLZc_put()の使用方法は、TinyLZ_compress()の実装を参照してください。
 *	  おおよそ、以下のようになります。
 *
 *		unsigned char in_data[...];	// 圧縮データ(入力)
 *		unsigned char out_buf[...];	// 展開データ(出力)
 *		int out_len;			// 展開データのバイト数(出力)
 *		TinyLZc lzc;
 *
 *		TinyLZc_init(&lzc, out_buf, sizeof out_buf);	// 圧縮ストリームを初期化
 *		for(i = 0; i < sizeof in_data; i++) {
 *			TinyLZc_put(&lzc, in_data[i]);		// 圧縮ストリームへ書き込み
 *		}
 *		TinyLZc_put(&lzc, EOF);				// 圧縮ストリームをフラッシュ(必須!!忘れないで!!)
 *		out_len = lzc.dst - out_buf;			// 圧縮データサイズを取得
 */
void TinyLZc_put(TinyLZc* self, int c);

/* データを圧縮します。
 * [in]
 *	_dst		圧縮バッファの先頭アドレス。
 *	dst_max		圧縮バッファのバイト数。
 *	_src		データの先頭アドレス。
 *	src_len		データのバイト数。
 * [out]
 *	戻り値		圧縮データのバイト数。
 *	_dst[]		圧縮データ。
 * [note]
 *	* 圧縮データが圧縮バッファを超える場合、超えた分は書き込みません。
 *	  その場合も、戻り値の圧縮データのバイト数は、超えた分を含みます。
 *	  この挙動を利用して、たとえば以下のように処理することができます。
 *		dst_max = TinyLZ_compress(NULL, 0, src, src_len); // 圧縮データのバイト数を取得
 *		dst = malloc(dst_len);                            // 圧縮バッファを確保
 *		TinyLZ_compress(dst, dst_max, src, src_len);      // 圧縮
 *	* P/ECE実機上では利用しないと判断して、実効ファイルサイズ節約のために外しました。
 *	  圧縮データの作成は、DOSコマンドラインツール「tool/dtinylz」を利用してください。
 *	  →2009/03/02追記:これまで、本関数は単独で実装しており、メモリ消費量が多かったために、
 *	    上述のようにP/ECE実機上では利用しないと判断し、条件コンパイルで無効にしていました。
 *	    今回、TinyLZc構造体、TinyLZc_init関数、TinyLZc_put関数の圧縮ストリーム実装に伴い、
 *	    本関数もこれらを利用して、メモリ消費量を非常に小さくおさえることができました。
 *	    P/ECE実機上でも充分利用可能と考えて、P/ECEでコンパイルする場合も有効にしました。
 */
int TinyLZ_compress(void* _dst, int dst_max, const void* _src, int src_len);

#endif /*__CLIP_TLZ_H__*/
