/*	
 *	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の少ない環境でも利用可能です。
 */
#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);

#ifndef PIECE
/* データを圧縮します。
 * [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」を利用してください。
 */
int TinyLZ_compress(void* _dst, int dst_max, const void* _src, int src_len);
#endif /*PIECE*/

#endif /*__CLIP_TLZ_H__*/
