/*
 *	cliphfm.c
 *
 *	Canonical Huffman Code
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2016 Naoyuki Sawa
 *
 *	* Fri Nov 21 20:05:45 JST 2014 Naoyuki Sawa
 *	- 1st リリース。
 *	- 下記の記事を参考にしました。
 *	  「高速に符号／復号を行える最小冗長符号「Canonical Huffman Code」」(http://codezine.jp/article/detail/376)
 *	  (ダウンロードして「keep/高速に符号／復号を行える最小冗長符号「Canonical Huffman Code」.7z」に保存しておきました。)
 *	  アルゴリズムは参考にしましたが、サンプルソースの実装はよく理解できなかったので、ほぼ新規に実装しました。
 *	  サンプルソースよりも、当モジュールの実装の方が、デコーダのフットプリントが小さくて、P/ECEに適していると思います。
 *	  また、圧縮時に格納する符号表が小さく済むよう工夫したので、サンプルソースよりも当モジュールの実装の方が、僅かに圧縮率が高いです。
 *	  さらに、サンプルソースは元データのサイズをヘッダに格納していますが、当モジュールは終端符号で判断する点が、優れていると思います。
 *	* Sat Nov 22 10:24:01 JST 2014 Naoyuki Sawa
 *	- 圧縮データの作成は、DOSコマンドラインツール「tool/dphfm」を利用してください。
 *	* Sat Nov 22 14:56:38 JST 2014 Naoyuki Sawa
 *	- HuffmanDecoder_Getc()をアセンブラ化しました。
 *	  HuffmanDecoder_Decode()で、約39KB⇒約62KBの展開を行った時の速度が、約1.106秒⇒約0.790秒に高速化しました。(Clock=48MHz,Code=SRAM,Stack=FRAM)
 *	* Sat Nov 22 16:01:39 JST 2014 Naoyuki Sawa
 *	- HuffmanDecoder_Init()をアセンブラ化しました。
 *	  コードサイズが12バイト小さくなりました。速度にはほとんど影響ありません。
 *	* Sat Nov 22 17:24:18 JST 2014 Naoyuki Sawa
 *	- HuffmanDecoder_Decode()をアセンブラ化しました。
 *	  HuffmanDecoder_Decode()で、約39KB⇒約62KBの展開を行った時の速度が、約0.790秒⇒約0.759秒に高速化しました。(Clock=48MHz,Code=SRAM,Stack=FRAM)
 *	* Sun Nov 23 01:00:09 JST 2014 Naoyuki Sawa
 *	- cliphfm.cから、デコーダー部分をframhfm.cに分離しました。
 *	  P/ECE上ではデコーダーしか使用しないことが多いので、常にエンコーダーがリンクされて容量が増加することを防ぐためです。
 *	  framhfm.cを高速RAMに配置して、高速化することも可能です。
 *	  framhfm.cを高速RAMに配置すると、HuffmanDecoder_Decode()で、約39KB⇒約62KBの展開を行った時の速度が、約0.759秒⇒約0.419秒に高速化しました。(Clock=48MHz,Code=FRAM,Stack=FRAM)
 *	* Sun Nov 23 21:49:53 JST 2014 Naoyuki Sawa
 *	- HuffmanDecoder_Getc()に、「工夫した計算順序」を適用しました。(C言語版とアセンブラ版の両方)
 *	  HuffmanDecoder_Decode()で、約39KB⇒約62KBの展開を行った時の速度が、約0.759秒⇒約0.756秒に高速化しました。(Clock=48MHz,Code=SRAM,Stack=FRAM)
 *	* Thu Sep 29 21:37:05 JST 2016 Naoyuki Sawa
 *	- Hewではエンコーダーを含めないようにしました。
 */
#include "clip.h"

//[note]
// - エンコード処理において、仮想的な終端値(256)に、明示的な終端符号を割り当てています。
//   そのようにする必要が有る理由を、説明します。
// - 終端符号は、値(0〜255)の符号よりも辞書比較で大きな値ならば何でも良いので、32bitの(-1)固定で良いように思うかも知れません。
//   しかし、それではだめです。
// - たとえば、値'A'と'B'だけが出現するときに、明示的な終端符号を割り当てなければ、('A'=0,'B'=1,終端符号=111…111)となります。
//   デコーダが、ビットストリームから1を読み込むと、すぐに'B'と判断してしまい、終端符号が存在しないのと同じになってしまいます。
// - 一方、明示的な終端符号を割り当てなければ、('A'=00,'B'=01,終端符号=10),又は,('A'=00,'B'=10,終端符号=11)となります。
//   これならば、デコーダが終端符号を判断することができます。
// - 以上が、エンコード処理において、仮想的な終端値(256)に、明示的な終端符号を割り当てる必要が有る理由です。
//   尚、明示的な終端符号を割り当ててしまえば、実際には、終端符号としてその値を格納しても、32bitの(-1)を格納しても構いません。
//   どちらにしても、値(0〜255)の符号よりも、辞書比較で大きな値であるからです。
//   当モジュールの実装では、実際に割り当てた終端符号を格納するようにしました。
//   他方、現在(2014/11/24)作成中の、clipdrh.c(差分圧縮⇒連長圧縮⇒ハフマン圧縮)モジュールでは、32bitの(-1)を格納する予定です。
// - 尚、「実際に割り当てた終端符号」は32bit未満の符号でありますが、32bit分格納しておく必要があります。
//   なぜならば、デコーダーは、実際の符号長にかかわらず32bit取得するからです。
//   具体的には、HuffmanEncoder_Encode()内のコメントを参照してください。

#ifndef __RENESAS__	//{{2016/09/29追加:Hewではエンコーダーを含めないようにしました。}}
/****************************************************************************
 *	ハフマンエンコーダー
 ****************************************************************************/
//ハフマン木のノード
typedef struct _ST_HuffmanNode {
	int				value;				//値(0〜256)					(値=256)は終端値を意味する。		子を持つ場合は、値は意味を持たない。
	int				count;				//出現回数										子を持つ場合は、子の出現回数の合計。
	struct _ST_HuffmanNode*		left;				//左側の子へのポインタ									NULL=子を持っていないことを示す。
	struct _ST_HuffmanNode*		right;				//右側の子へのポインタ									NULL=子を持っていないことを示す。
} ST_HuffmanNode;
/*--------------------------------------------------------------------------*/
//ハフマンエンコーダー構造体
typedef struct _ST_HuffmanEncoder {
	ST_HuffmanNode*			TBL_Node[257];			//親を持っていないノードのポインタ配列		(値=256)は終端値を意味する。
	unsigned char			TBL_CodeLen[257];		//値の符号長(0〜32)				(値=256)は終端値を意味する。		0=出現回数が0であったことを示す。
	unsigned short			TBL_ValueOrder[257];		//値を符号長の昇順にソートするための配列	(値=256)は終端値を意味する。		ただし、符号長が0(=出現回数が0)である値は、後とする。
	unsigned short			TBL_CodeLenCount[32];		//符号長が割り当てられた値の数(0〜256)		(値=256)は終端値を意味する。		[0]=符号長1が割り当てられた値の数,[1]=符号長1が割り当てられた値の数,…,[31]=符号長32が割り当てられた値の数	【重要】終端値は数に含めない。終端符号を最長かつ最大の符号とし、終端符号を符号表に含めない。こうしておくことによって、デコーダが符号表を最後まで検索しても一致しなければ、終端符号だと判断できる。
	unsigned			TBL_Code[257];			//値の符号					(値=256)は終端値を意味する。		ただし、符号長が0(=出現回数が0)である値の符号は、意味を持たない。
} ST_HuffmanEncoder;
/*--------------------------------------------------------------------------*/
//(ST_HuffmanNode*)を、(ST_HuffmanNode.count)の昇順にソートする、比較関数。
//ただし、(ST_HuffmanNode*)がNULLポインタである要素は、後とする。
static int HuffmanEncoder_CompareNodeCount(const void* _x, const void* _y) {
	ST_HuffmanNode* px = *(ST_HuffmanNode**)_x;
	ST_HuffmanNode* py = *(ST_HuffmanNode**)_y;
	unsigned xCount = (px ? px->count : 0) - 1;	//┬(ST_HuffmanNode.count=0)のノードは、呼び出し元にて削除済みである。
	unsigned yCount = (py ? py->count : 0) - 1;	//┘従って、(px=NULL)時のみ(x=-1)となる。(py=NULL)時のみ(y=-1)となる。
	if(xCount < yCount) { return -1; }
	if(xCount > yCount) { return  1; }
	return 0;
}
/*--------------------------------------------------------------------------*/
//値を符号長の昇順にソートする、比較関数。
//ただし、符号長が0(=出現回数が0)である値は、後とする。
//符号長が同じである場合は、値の昇順とする。この条件は必須でなく、圧縮率に影響しない。
static int HuffmanEncoder_CompareValueOrder(const void* _x, const void* _y, void* _arg) {
	ST_HuffmanEncoder* pHuffmanEncoder = _arg;
	int xValue = *(unsigned short*)_x;
	int yValue = *(unsigned short*)_y;
	int xCodeLen = (unsigned char)(pHuffmanEncoder->TBL_CodeLen[xValue] - 1);
	int yCodeLen = (unsigned char)(pHuffmanEncoder->TBL_CodeLen[yValue] - 1);
	if(xCodeLen < yCodeLen) { return -1; }
	if(xCodeLen > yCodeLen) { return  1; }
	if(xValue < yValue) { return -1; }	//┬符号長が同じである場合は、値の昇順とする。
	if(xValue > yValue) { return  1; }	//┘この条件は必須でなく、圧縮率に影響しない。
	return 0;
}
/*--------------------------------------------------------------------------*/
//ノードを開放しながら、値の符号長を決定する。
static void HuffmanNode_CodeLen(ST_HuffmanEncoder* pHuffmanEncoder, ST_HuffmanNode* pNode, int codeLen) {
//誤//	codeLen++;								//符号長を増やす。									←ここで符号長を増やすのは誤りであることに注意せよ。
	if(!!pNode->left ^ !!pNode->right) { DIE(); }				//左側だけ,又は,右側だけに子を持つ親は存在しないはず。もし存在したらバグである。	│符号の一桁は、ノードの'点'に割り当てるのではなく、左右の子への'斜め線'に割り当てるので、
	if(pNode->left) {							//内部ノードならば…									←ここで符号長を増やすのが正解である。
/*正*/		codeLen++;							//符号長を増やす。
		HuffmanNode_CodeLen(pHuffmanEncoder, pNode->left,  codeLen);	//左側の子について再帰する。
		HuffmanNode_CodeLen(pHuffmanEncoder, pNode->right, codeLen);	//右側の子について再帰する。
	} else {								//葉ノードならば…
		if(pHuffmanEncoder->TBL_CodeLen[pNode->value]) { DIE(); }	//同じ値のノードが複数存在することは無いはずなので、既に符号長が格納されていることは無いはず。もし格納されていたらバグである。
		//[note]
		//当プログラムは、符号長が32を超えると、正しく処理できません。
		//しかし、実際には、符号長が32を超えケースは、まずありません。
		//符号長が32を超えるのは、値の出現回数が2^31以上となる場合だからです。
		//当プログラムは、数ギガバイトのデータに対する使用は想定していません。
		//従って、符号長が32を超えるケースを考慮する必要はありません。
		//
		//　　　／＼　　　　　　　　　
		//　2^31　／＼　　　　　　　　符号長 1
		//　　2^30　／＼　　　　　　　符号長 2
		//　　　2^29　（略）　　　　　符号長 3
		//　　　　　　　／＼　　　　　
		//　　　　　2^２　／＼　　　　符号長30
		//　　　　　　2^１　／＼　　　符号長31
		//　　　　　　　2^０　　2^０　符号長32
		//　　　　　　　↑出現回数↑　
		if(codeLen > 32) { DIE(); }					//万一、数ギガバイトのデータに対して使用した場合、ここで停止する可能性があります。
		pHuffmanEncoder->TBL_CodeLen[pNode->value] = codeLen;		//符号長を格納する。
	}
	free(pNode);								//ノードを開放する。
}
/*--------------------------------------------------------------------------*/
//圧縮元データ全体をエンコードし、圧縮データを作成する。
// - dstは、32bit境界に整列されたバッファであること。srcはアライメント不要。
// - 圧縮データがdstBytesを超えた場合は、越えた部分は格納しない。
//   格納の可否に関係なく、戻り値は、圧縮データのバイト数である。
//   この性質を利用して、一回目は(dst=NULL,dstBytes=0)で呼び出し、必要なバッファサイズを確認,確保した後、再度呼び出す方法も可能です。
//   <例>
//   │dstBytes=HuffmanEncoder_Encode(src,srcBytes,NULL,0);
//   │dst=malloc(dstBytes);
//   │HuffmanEncoder_Encode(src,srcBytes,dst,dstBytes);
int HuffmanEncoder_Encode(const void* _src, int srcBytes, void* dst, int dstBytes) {
	ST_HuffmanEncoder stHuffmanEncoder;	//約3KB
	const unsigned char* src = _src;
	      unsigned char* hdr;
	unsigned short* pValueOrder;
	ST_HuffmanNode* pNode;
	int i, value, code, codeLen, codeLenDiff, codeLenMask, codeLenCount, dstPos, dstBits;
//{{データが0バイトの場合の特例処理
	//データが0バイトの場合は、エンコーダ側のみ、特例処理を行う。
	// - データが0バイトの場合も、通常通りに処理しようとすると、終端値(256)だけから符号表を作成して情報量が0になり、終端値(256)の符号長が0になってしまう。
	//   もし、符号長0を有効な符号として、通常の処理で対応できるように変更すると、却って複雑になる。
	//   それよりも、データが0バイトの場合を特例処理にする方が、適切だと判断した。
	//   データが0バイトの場合は、(codeLenMask=0,code=終端符号)だけの圧縮データを出力して、エンコード処理を終了する。
	// - デコーダ側では、データが0バイトの場合を考慮する必要は無く、特例処理は不要である。
	//   (codeLenMask=0,code=終端符号)だけの圧縮データを、デコーダの通常の処理どおりに処理すれば、初回で終端と見なして(-1)を返す。
	// - 終端符号は何でも構わないが、判り易さのために、0とすることにした。
	//   HuffmanDecoder_Getc()が、実際の符号長にかかわらず、現在のビット位置から32bit取得するために置いておくだけであり、厳密には0ビットの終端符号である。
	//   0ビットの終端符号であるから、HuffmanDecoder_Getc()が読み込んだ値を使用することは無い。
	if(!srcBytes) {
		if(dstBytes >= 4) { ((int*)dst)[0] = 0; }	//codeLenMask=0
		if(dstBytes >= 8) { ((int*)dst)[1] = 0; }	//code=終端符号
		return 8;
	}
//}}データが0バイトの場合の特例処理
	//構造体をクリアする。
	memset(&stHuffmanEncoder, 0, sizeof stHuffmanEncoder);
	//--- 符号表を作成する処理 ---
	//値のノードを作成する。
	for(i = 0; i < 257; i++) {
		pNode = calloc(1, sizeof(ST_HuffmanNode));
		if(!pNode) { DIE(); }
		pNode->value = i;
		stHuffmanEncoder.TBL_Node[i] = pNode;
	}
	//値の出現回数を数える。
	for(i = 0; i < srcBytes; i++) {
		value = src[i];
		stHuffmanEncoder.TBL_Node[value]->count++;
	}
	//終端値(256)は、1回出現したこととする。
	//終端値(256)は、src[]の中に現れないが、圧縮データを出力する処理の最後に出力するので、1回出現したと見なすのが適切である。
	stHuffmanEncoder.TBL_Node[256]->count++;
	//出現回数が0であった値のノードを削除する。
	for(i = 0; i < 257; i++) {
		pNode = stHuffmanEncoder.TBL_Node[i];
		if(!pNode->count) {
			free(pNode);
			stHuffmanEncoder.TBL_Node[i] = NULL;
		}
	}
	//親を持っていないノードが1個になるまで繰り返す処理。
	for(;;) {
		//(ST_HuffmanNode*)を、(ST_HuffmanNode.count)の昇順にソートする。
		//ただし、(ST_HuffmanNode*)がNULLポインタである要素は、後とする。
		qsort(stHuffmanEncoder.TBL_Node, 257, sizeof stHuffmanEncoder.TBL_Node[0], HuffmanEncoder_CompareNodeCount);
		//親を持っていないノードが1個になったら、抜ける。
		if(!stHuffmanEncoder.TBL_Node[0]) { DIE(); }	//最小でも、(何かの値)と(終端値)が、それぞれ1回以上出現しているので、親を持っていないノードが0個になることは無いはず。ここで停止したらバグである。
		if(!stHuffmanEncoder.TBL_Node[1]) { break; }
		//出現回数が最小のノード2個を子ノードとして、親ノードを作成する。
		pNode = calloc(1, sizeof(ST_HuffmanNode));	//親ノードを作成する。
		if(!pNode) { DIE(); }
		pNode->count = stHuffmanEncoder.TBL_Node[0]->count + stHuffmanEncoder.TBL_Node[1]->count;	//左右の子ノードの、出現回数を合計する。
		pNode->left  = stHuffmanEncoder.TBL_Node[0];	//親ノードに、左側の子ノードを格納する。
		pNode->right = stHuffmanEncoder.TBL_Node[1];	//親ノードに、右側の子ノードを格納する。
		stHuffmanEncoder.TBL_Node[0] = pNode;		//左側の子ノードが有った位置に、親ノードを格納する。
		stHuffmanEncoder.TBL_Node[1] = NULL;		//右側の子ノードが有った位置を、空にする。
	}
	//ノードを開放しながら、値の符号長を決定する。
	HuffmanNode_CodeLen(&stHuffmanEncoder, stHuffmanEncoder.TBL_Node[0], 0);
	//値を符号長の昇順にソートする。
	//ただし、符号長が0(=出現回数が0)である値は、後とする。
	//符号長が同じである場合は、値の昇順とする。この条件は必須でなく、圧縮率に影響しない。
	for(i = 0; i < 257; i++) { stHuffmanEncoder.TBL_ValueOrder[i] = i; }
	qsort_r(stHuffmanEncoder.TBL_ValueOrder, 257, sizeof stHuffmanEncoder.TBL_ValueOrder[0], HuffmanEncoder_CompareValueOrder, &stHuffmanEncoder);
//{{終端符号を最後にする処理
// - 泥臭い処理ですが、必要です。
//   ここまでの処理の結果で、終端値(256)が、TBL_ValueOrder[]の中で最後の値になっているとは限らないからです。
// - ここまでの処理の中で、ソートの条件を工夫しても、自然に↑の並びとすることは難しいです。
//   なぜならば、ハフマン木の生成は、子の出現回数の合算で比較するので、終端値(256)自身の出現回数が最小(=1)であっても、他のノードとの合算によっては、木の右端に来るとは限らないからです。
// - エレガントな方法は思い付かないので、泥臭い処理ではありますが、ハフマン木が完成した後に、終端値(256)と、TBL_ValueOrder[]の中で最後の値とを、交換することにしました。
//   泥臭い処理はここだけであり、エンコーダの他の処理や、デコーダの処理では、考慮しなくて構いません。
	{
		int j = -1;	//TBL_ValueOrder[]の中で、終端値(256)のインデクスを検索する。
		int k = -1;	//TBL_ValueOrder[]の中で最後に現れる、符号長が0でない(=出現回数が0でない)値のインデクスを検索する。
		for(i = 0; i < 257; i++) {
			value = stHuffmanEncoder.TBL_ValueOrder[i];
			if(value == 256) { if(j != -1) { DIE(); } j = i; }	//終端値(256)のインデクス
			if(stHuffmanEncoder.TBL_CodeLen[value]) { k = i; }	//TBL_ValueOrder[]の中で最後に現れる、符号長が0でない(=出現回数が0でない)値のインデクス
		}
		if((j == -1) || (k == -1)) { DIE(); }	//見つからないことは無いはず。ここで停止したらバグである。
		//「終端値(256)」自身が既に、「TBL_ValueOrder[]の中で最後に現れる、符号長が0でない(=出現回数が0でない)値」となっていた場合を除き…
		if(j != k) {	//この判断は必要です。ポインタ越しに同じ変数に対して、下記のXorのアルゴリズムで交換を行おうとすると、交換せずに0になってしまいます。		※※※※※※※※※※TODO:他のモジュールにも、左記のバグが潜んでいないか、折をみて見直しを行おうと思う。※※※※※※※※※※
			//「終端値(256)」と、「TBL_ValueOrder[]の中で最後に現れる、符号長が0でない(=出現回数が0でない)値」との、符号長を交換する。
			value = stHuffmanEncoder.TBL_ValueOrder[k];		//TBL_ValueOrder[]の中で最後に現れる、符号長が0でない(=出現回数が0でない)値
			stHuffmanEncoder.TBL_CodeLen[value] ^= stHuffmanEncoder.TBL_CodeLen[256];	//┐
			stHuffmanEncoder.TBL_CodeLen[256]   ^= stHuffmanEncoder.TBL_CodeLen[value];	//├交換
			stHuffmanEncoder.TBL_CodeLen[value] ^= stHuffmanEncoder.TBL_CodeLen[256];	//┘
			stHuffmanEncoder.TBL_ValueOrder[j]  ^= stHuffmanEncoder.TBL_ValueOrder[k];	//┐
			stHuffmanEncoder.TBL_ValueOrder[k]  ^= stHuffmanEncoder.TBL_ValueOrder[j];	//├交換
			stHuffmanEncoder.TBL_ValueOrder[j]  ^= stHuffmanEncoder.TBL_ValueOrder[k];	//┘
		}
	}
//}}終端符号を最後にする処理
	//値の符号を割り当てる。
	code = codeLen = 0;
	pValueOrder = stHuffmanEncoder.TBL_ValueOrder;			//値を符号長の昇順に走査するポインタ
	for(;;) {
		value = *pValueOrder++;					//符号長の昇順に、値を取得する。
		if((codeLenDiff = stHuffmanEncoder.TBL_CodeLen[value] - codeLen)) {	//符号長が変化したら…
			code   <<= codeLenDiff;				//符号長が増えた分、符号を左シフトする。
			codeLen += codeLenDiff;				//符号長を更新する。
		}
		stHuffmanEncoder.TBL_Code[value] = code++;		//値の符号を格納する。符号を次へ進める。
		if(value == 256) { break; }				//終端値ならば抜ける。				//┬【重要】終端値は数に含めない。終端符号を最長かつ最大の符号とし、終端符号を符号表に含めない。こうしておくことによって、デコーダが符号表を最後まで検索しても一致しなければ、終端符号だと判断できる。
		stHuffmanEncoder.TBL_CodeLenCount[codeLen - 1]++;	//符号長が割り当てられた値の数を増やす。	//┘
	}
//{{バグ検出のためだけの処理です。コードが安定したら削除して構いません。
	//上のブロックのループを抜けた時に、pValueOrderは、終端値(256)の次のエントリを指している。
	//TBL_ValueOrder[]の中で、終端値(256)は、出現回数が0でない値の最後のエントリのはずなので、(泥臭い処理にてそのようにしたので)
	//pValueOrderは、出現回数が0の値を指しているか(出現回数が0の値が有った場合),又は,TBL_ValueOrder[]の最後のエントリ+1を指しているはず(出現回数が0の値が無かった場合)。
	//そうなっていなければ、当関数のバグである。
	       if(pValueOrder < &stHuffmanEncoder.TBL_ValueOrder[257]) {
		if(stHuffmanEncoder.TBL_CodeLen[*pValueOrder]) { DIE(); }	//バグ
	} else if(pValueOrder > &stHuffmanEncoder.TBL_ValueOrder[257]) {
		DIE();								//バグ
	}
//}}バグ検出のためだけの処理です。コードが安定したら削除して構いません。
	//--- 符号表を出力する処理 ---
	//符号表の部分は、bitarray_msb1st_getではなく、(codeLenMask+バイト配列)と見なしてアクセスする。エンコーダとデコーダでアクセス方法を合わせないと、バイト配列部分の順序が一致しないので注意せよ。
	dstPos  =  0;
	dstBits = (dstBytes << 3);
	hdr     =  dst;
	//値が割り当てられている符号長の、ビットマスクを作成する。
	codeLenMask = 0;
	for(i = 0; i < 32; i++) {
		codeLenMask <<= 1;					//┬bit31=符号長1,bit30=符号長2,…,bit1=符号長31,bit0=符号長32
		codeLenMask  |= !!stHuffmanEncoder.TBL_CodeLenCount[i];	//┘上位ビット先行とした理由は、デコーダをasm化した時に「add %rX,%rX;jruge 〜」で処理するためです。
	}
	//値が割り当てられている符号長の、ビットマスクを出力する。
	if((dstPos + 32) <= dstBits) {
		*(int*)hdr  = codeLenMask;
		       hdr += 4;
	}
	dstPos += 32;
	//符号長に割り当てられている、値を出力する。
	pValueOrder = stHuffmanEncoder.TBL_ValueOrder;			//値を符号長の昇順に走査するポインタ
	for(i = 0; i < 32; i++) {
		codeLenCount = stHuffmanEncoder.TBL_CodeLenCount[i];	//符号長が割り当てられた値の数を取得する。
		if(codeLenCount) {					//符号長が割り当てられた値の数が、0でなければ…
			if((dstPos + 8) <= dstBits) {
				*hdr++ = codeLenCount - 1;		//(符号長が割り当てられた値の数-1)を出力する。		//エンコーダの(-1)とデコーダが(+1)が相殺して、(1〜256)に復元する。
			}
			dstPos += 8;
			do {
				if((dstPos + 8) <= dstBits) {
					value = *pValueOrder;
					*hdr++ = value;			//符号長に割り当てられている値を出力する。
				}
				dstPos += 8;
				pValueOrder++;
			} while(--codeLenCount);
		}
	}
	//圧縮データの部分は、bitarray_msb1st_getでアクセスするので、32bit境界まで進めておく必要が有る。
	while(dstPos & 31) {
		if((dstPos + 8) <= dstBits) { *hdr++ = 0; }		//符号表の部分と、圧縮データの部分のギャップは、不定値でも構わないが、判り易さのために、0で埋めておくことにした。
		dstPos += 8;
	}
	//--- 圧縮データを出力する処理 ---
	//値の符号を出力する。
	for(i = 0; i < srcBytes; i++) {
		value = src[i];
		codeLen = stHuffmanEncoder.TBL_CodeLen[value];
		if(!codeLen) { DIE(); }		//バグ
		if((dstPos + codeLen) <= dstBits) {
			code = stHuffmanEncoder.TBL_Code[value];
			bitarray_msb1st_set(dst, dstPos, codeLen, code);
		}
		dstPos += codeLen;
	}
	//終端符号を出力する。
	codeLen = stHuffmanEncoder.TBL_CodeLen[256];
	if((dstPos + codeLen) <= dstBits) {
		code = stHuffmanEncoder.TBL_Code[256];
		bitarray_msb1st_set(dst, dstPos, codeLen, code);
	}
	dstPos += codeLen;
	//デコーダーは、実際の符号長にかかわらず32bit取得するので、終端符号は32bit分出力しておく必要がある。
	// - そうしないと、終端符号の符号長が32bitに満たない部分を、圧縮データサイズを超えた部分から取得してしまうおそれがある。
	//   実際には、終端符号の符号長が32bitに満たない部分が不定値でも結果に影響は無いし、数バイト超えてリードアクセスしたぐらいで一般保護エラーが出ることは無いだろうが、厳密には有り得る。
	//   以上の理由より、終端符号は32bit分出力しておくべきである。
	if(codeLen & 31) {
		codeLen = 32 - (codeLen & 31);
		if((dstPos + codeLen) <= dstBits) {
			bitarray_msb1st_set(dst, dstPos, codeLen, 0);	//終端符号の余りのビットは、不定値でも構わないが、判り易さのために、0で埋めておくことにした。
		}
		dstPos += codeLen;
	}
	//圧縮データの部分は、bitarray_msb1st_getでアクセスするので、32bit単位に切上げておく必要が有る。
	// - 上の処理で、終端符号は32bit分出力したこととは、別の問題であることに注意せよ。
	//   上の処理は、デコーダーの都合である。
	//   この処理は、bitarray_msb1st_getの都合である。
	// - この処理を行わないと、上の処理で終端符号を32bit分出力して、出力サイズが(4N+1)バイトになったとすると、bitarray_msb1st_getが、3バイト分データを突き抜けてアクセスするおそれがある。
	//   実際には、3バイト分突き抜けた部分が不定値でも結果に影響は無いし、数バイト超えてリードアクセスしたぐらいで一般保護エラーが出ることは無いだろうが、厳密には有り得る。
	//   以上の理由より、圧縮データは32bit単位に切上げておくべきである。
	if(dstPos & 31) {
		codeLen = 32 - (dstPos & 31);
		if((dstPos + codeLen) <= dstBits) {
			bitarray_msb1st_set(dst, dstPos, codeLen, 0);	//圧縮データの余りのビットは、不定値でも構わないが、判り易さのために、0で埋めておくことにした。
		}
		dstPos += codeLen;
	}
	//出力バイト数を返す。
	return dstPos >> 3;
}
#endif//__RENESAS__	//{{2016/09/29追加:Hewではエンコーダーを含めないようにしました。}}
