/*
 *	clipbpe.h
 *
 *	Byte Pair Encoding
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2015-2016 Naoyuki Sawa
 *
 *	* Thu Jan 29 21:20:19 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	- 下記の資料を参考にさせて頂きました。
 *	  「Vector - bpe - BPE圧縮/展開するコマンドラインツール」(http://www.vector.co.jp/soft/dl/winnt/util/se498916.html)
 *	  「ひそかにぐあんをめぐらして - Byte Pair Encoding・その１」(http://musyozoku211.blog118.fc2.com/blog-entry-8.html)
 *	* Fri Jan 30 21:08:25 JST 2015 Naoyuki Sawa
 *	- 「１バイトづつ展開する関数(展開ストリーム)」を高速化するために、大幅な変更を行いました。
 *	  データの特性に関係無く、「１バイトづつ展開する関数(展開ストリーム)」が常に安定した速度で動作するようになりました。
 *	  今回の変更によって、僅かに圧縮率が低下しましたが、ほとんど無視できるレベルだと思います。
 *	* Tue Nov 03 21:42:14 JST 2015 Naoyuki Sawa
 *	- 「Boehm GC」をマルチスレッド対応にした事に伴い、当モジュール内の_beginthread()を_beginthreadex()に変更しました。
 *	  詳細は、/clip/tool/gc/README.TXT の同日のコメントを参照して下さい。
 *	* Sat Nov 14 21:55:38 JST 2015 Naoyuki Sawa
 *	- マルチスレッド版の実装を修正しました。主な変更点は、以下の通りです。
 *	- BytePairEncodingEncoder_Encode()の'CloseHandle(stMT.hEvent)'が、BytePairEncodingEncoder_EncodeTry()の最後の'SetEvent(pMT->hEvent)'よりも先に行われる可能性が有り、
 *	  CloseHandle()よりも後にSetEvent()が行われる可能性の有るバグが有りました。本日、マルチスレッド版の実装を修正して、この不具合は無くなりました。
 *	  上記の不具合修正を含めて、マルチスレッド版の処理内容を見直して、整理しました。
 *	- これまでは、プロジェクトの設定によって、シングルスレッド版(通常版)と、マルチスレッド版を、自動的に切り替えてビルドしていました。
 *	  今後は、シングルスレッド版の関数(BytePairEncodingEncoder_EncodeST)とマルチスレッド版の関数(BytePairEncodingEncoder_EncodeMT)を、明示的に呼び分けられるようにしました。
 *	  シングルスレッド版とマルチスレッド版を呼び分けられるようにした理由は、/clip/tool/dpbpe/main.c の同日のコメントを参照して下さい。
 *	  尚、BytePairEncodingEncoder_Encodeをマクロ定義して、自動的な切り替えにも対応していますので、既存のアプリケーションのソースを変更する必要は有りません。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Thu Apr 28 21:03:22 JST 2016 Naoyuki Sawa
 *	- BytePairEncodingDecoder_Decode()に、展開元データの終端位置を受け取る引数を追加しました。
 *	  使い方はだいたいstrtol()と同様です。
 *	  'const void** srcEndPtr'ではなく'void** srcEndPtr'としたのは、strtol()の流儀に合わせたからです。('const void** srcEndPtr'の方が安全だとは思うのですが…)
 *	  この引数を追加した理由は、サイズ不明の展開元データが複数連続して格納されている場合に、実行時にそれらを切り分けて展開できるようにするためです。
 *	  □使用例
 *	  │BytePairEncodingDecoder_Decode(src, dst1, dstCap1, &src);	//一つ目の展開元データブロックを展開し、展開元データのポインタを二つ目の展開元データの先頭位置へ進める。
 *	  │BytePairEncodingDecoder_Decode(src, dst2, dstCap2, NULL);	//二つ目の展開元データブロックを展開する。
 *	- BytePairEncodingDecoder_GetEndPtr()を追加しました。
 *	  この関数を追加した目的は、上記と同じです。
 *	  戻り値の型を'const void*'ではなく'void*'としたのは、strtol()の流儀に合わせたからです。('const void*'の方が安全だとは思うのですが…)
 *	  □使用例
 *	  │BytePairEncodingDecoder_Init(&stDecoder, src);						//一つ目の展開元ストリームを初期化する。
 *	  │while((c = BytePairEncodingDecoder_Getc(&stDecoder)) != -1) { 〜 }				//一つ目の展開元データブロックを展開する。
 *	  │BytePairEncodingDecoder_Init(&stDecoder, BytePairEncodingDecoder_GetEndPtr(&stDecoder));	//二つ目の展開元ストリームを初期化する。
 *	  │while((c = BytePairEncodingDecoder_Getc(&stDecoder)) != -1) { 〜 }				//二つ目の展開元データブロックを展開する。
 *	* Fri Sep 16 21:30:10 JST 2016 Naoyuki Sawa
 *	- ローカルシンボル'BYTEPAIRENCODINGENCODER_PRINTPROGRESS'を廃止して、グローバル変数'BytePairEncodingEncoder_PrintProgress'を追加しました。
 *	  BytePairEncodingEncoder_PrintProgressが0以外ならばBytePairEncodingEncoder_EncodeST(),及び,BytePairEncodingEncoder_EncodeMT()が進捗表示を行い、0ならば進捗表示を行いません。
 *	  これまではBYTEPAIRENCODINGENCODER_PRINTPROGRESSによってコンパイル時に決定していたため実行時に選択出来ませんでしたが、今回の変更によって実行時に選択出来るようになりました。
 *	  そうした理由は、上記の関数を使用するツール(主にdLedSeqC.exe)がオプションによって進捗表示を抑制しても、呼び出し先の上記関数が進捗表示を行ってしまう問題が生じたからです。
 *	  今後は、上記の関数を利用するツールが明示的にBytePairEncodingEncoder_PrintProgressを設定して、進捗表示の有無を選択して下さい。
 *	  尚、BytePairEncodingEncoder_PrintProgressの初期値は、これまでの動作との互換性のために、Windowsならば1(=進捗表示有り)、Windows以外(P/ECEも含む)ならば0(=進捗表示無し)としてあります。
 *	* Thu Sep 29 21:37:05 JST 2016 Naoyuki Sawa
 *	- Hewではエンコーダーを含めないようにしました。
 */
#ifndef __CLIP_BPE_H__
#define __CLIP_BPE_H__

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

#ifndef __RENESAS__	//{{2016/09/29追加:Hewではエンコーダーを含めないようにしました。}}
/****************************************************************************
 *	BytePairEncodingエンコーダー
 ****************************************************************************/
//{{2016/09/16追加:ローカルシンボル'BYTEPAIRENCODINGENCODER_PRINTPROGRESS'を廃止して、グローバル変数'BytePairEncodingEncoder_PrintProgress'を追加しました。
extern int BytePairEncodingEncoder_PrintProgress;	//0=進捗表示無し,0以外=進捗表示有り
//}}2016/09/16追加:ローカルシンボル'BYTEPAIRENCODINGENCODER_PRINTPROGRESS'を廃止して、グローバル変数'BytePairEncodingEncoder_PrintProgress'を追加しました。
int BytePairEncodingEncoder_EncodeST(const void* _src, int srcLen, void* _dst, int dstCap);	//シングルスレッド版	｢ﾌﾟﾛｼﾞｪｸﾄの設定｣⇒｢C/C++｣⇒｢ｺｰﾄﾞ生成｣⇒｢使用するﾗﾝﾀｲﾑﾗｲﾌﾞﾗﾘ｣⇒｢ｼﾝｸﾞﾙｽﾚｯﾄﾞ｣/｢ｼﾝｸﾞﾙｽﾚｯﾄﾞ(ﾃﾞﾊﾞｯｸﾞ)｣を選択した場合､BytePairEncodingEncoder_Encode()はこちらを使用します｡	｢ﾏﾙﾁｽﾚｯﾄﾞ｣/｢ﾏﾙﾁｽﾚｯﾄﾞ(ﾃﾞﾊﾞｯｸﾞ)｣を選択した場合でも､明示的にBytePairEncodingEncoder_EncodeST()を使用する事は出来ます｡
#define BytePairEncodingEncoder_Encode	BytePairEncodingEncoder_EncodeST
#if     defined(_WIN32) && defined(_MT)
int BytePairEncodingEncoder_EncodeMT(const void* _src, int srcLen, void* _dst, int dstCap);	//マルチスレッド版	｢ﾌﾟﾛｼﾞｪｸﾄの設定｣⇒｢C/C++｣⇒｢ｺｰﾄﾞ生成｣⇒｢使用するﾗﾝﾀｲﾑﾗｲﾌﾞﾗﾘ｣⇒｢ﾏﾙﾁｽﾚｯﾄﾞ｣/｢ﾏﾙﾁｽﾚｯﾄﾞ(ﾃﾞﾊﾞｯｸﾞ)｣を選択した場合､BytePairEncodingEncoder_Encode()こちらを使用します｡		｢ｼﾝｸﾞﾙｽﾚｯﾄﾞ｣/｢ｼﾝｸﾞﾙｽﾚｯﾄﾞ(ﾃﾞﾊﾞｯｸﾞ)｣を選択した場合に､明示的にBytePairEncodingEncoder_EncodeMT()を使用する事は出来ません｡
#undef  BytePairEncodingEncoder_Encode
#define BytePairEncodingEncoder_Encode	BytePairEncodingEncoder_EncodeMT
#endif//defined(_WIN32) && defined(_MT)
#endif//__RENESAS__	//{{2016/09/29追加:Hewではエンコーダーを含めないようにしました。}}
/****************************************************************************
 *	BytePairEncodingデコーダー
 ****************************************************************************/
typedef struct _ST_BytePairEncodingDecoder {	//アセンブラ版から参照するのでレイアウト固定です。
	const unsigned char*	blk;		//+ 0,4 現在のブロック
	      unsigned short	ofs;		//+ 4,2 現在のブロック内の走査位置オフセット	0〜65535
	      unsigned char	lev;		//+ 6,1 スタックレベル				0〜9
	      unsigned char	stk[9];		//+ 7,9 スタック				ペアを展開する時に、ペアの上位8bitをスタックに積む。スタックを増やすと圧縮率が向上するが、実験した所これ以上増やしても違いが少ない。
} ST_BytePairEncodingDecoder;			//=16
/*--------------------------------------------------------------------------*/
//--- 全体を一度で展開する関数 ---
//{{2016/04/28変更:BytePairEncodingDecoder_Decode()に、展開元データの終端位置を受け取る引数を追加しました。
//int BytePairEncodingDecoder_Decode(const void* _src, void* _dst, int dstCap);
//↓2016/04/28変更:BytePairEncodingDecoder_Decode()に、展開元データの終端位置を受け取る引数を追加しました。
int BytePairEncodingDecoder_Decode(const void* _src, void* _dst, int dstCap, void** srcEndPtr/*NULL可*/);
//}}2016/04/28変更:BytePairEncodingDecoder_Decode()に、展開元データの終端位置を受け取る引数を追加しました。
//--- １バイトづつ展開する関数(展開ストリーム) ---
void BytePairEncodingDecoder_Init(ST_BytePairEncodingDecoder* pDecoder, const void* _src);
int BytePairEncodingDecoder_Getc(ST_BytePairEncodingDecoder* pDecoder);
//{{2016/04/28追加:BytePairEncodingDecoder_GetEndPtr()を追加しました。
void* BytePairEncodingDecoder_GetEndPtr(ST_BytePairEncodingDecoder* pDecoder);
//}}2016/04/28追加:BytePairEncodingDecoder_GetEndPtr()を追加しました。

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

#endif//__CLIP_BPE_H__
