/*	
 *	clipmisc.h
 *
 *	エラー処理、その他いろいろです。
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2009 Naoyuki Sawa
 *
 *	* Wed Dec 12 21:51:29 JST 2001 Naoyuki Sawa
 *	- 作成開始。
 *	* Sun Jan 26 19:33:00 JST 2003 Naoyuki Sawa
 *	- die()関数に__attribute__((noreturn))属性を追加。
 *	  メモ:__attribute__((...))は関数宣言時のみ指定可能です。
 *	       関数実装時に指定するとコンパイルエラーとなります。
 *	* Sun May 4 18:05:00 JST 2003 Naoyuki Sawa
 *	- fpk_size()/fpk_load()を追加しました。
 *	* Wed Aug 20 06:00:00 JST 2003 Naoyuki Sawa
 *	- fpk_address()を追加しました。
 *	* Sat Nov 22 06:00:00 JST 2003 Naoyuki Sawa
 *	- トレース出力(TRACE_ON/TRACE/trace())を追加しました。
 *	* Sun Dec 28 13:49:00 JST 2003 Naoyuki Sawa
 *	- DDA構造体をcliprend.hから移動してきました。
 *	* Thu Jul 22 12:30:00 JST 2004 Naoyuki Sawa
 *	- RND8_RANGE()とRND16_RANGE()を追加しました。
 *	- COUNTOF()を追加しました。
 *	* Wed Sep 15 06:36:00 JST 2004 Naoyuki Sawa
 *	- コンパイラバグ回避のため、RND8/16,RND8/16_RANGEをマクロ→関数化しました。
 *	  過去のソースの互換性のため、関数を呼び出すマクロも定義してあります。
 *	* Sun Oct 31 13:19:00 JST 2004 Naoyuki Sawa
 *	- LEBYTE()/LEHALF()/LEWORD()/BEBYTE()/BEHALF()/BEWORD()マクロを
 *	  clippce.hからclipmisc.hへ移動してきました。
 *	- HIBYTE()/LOBYTE()/HIHALF()/LOHALF()マクロを追加しました。
 *	* Sun Dec 4 04:01:00 JST 2004 Naoyuki Sawa
 *	- Win32プロジェクトからのインクルードできるよう、
 *	  die()とtrace()の宣言をPIECEシンボル定義の有無によって場合分けしました。
 *	- DDA構造体にコメントを追加しました。(コメント追加のみ。定義変更は無し。)
 *	* Sun Dec 12 09:59:00 JST 2004 Naoyuki Sawa
 *	- BLOCKSIZE、SPEAKER_FREQUENCYはP/ECE特有の定数ですが、Win32版テストプログラムからも参照するために、
 *	  clippce.hからclipmisc.hへ移動しました。
 *	* Wed Feb 02 21:01:00 JST 2005 Naoyuki Sawa
 *	- mirror_table[]の宣言と、MIRROR()マクロを追加しました。
 *	  mirror_table[]の実体は、clipmirr.cにあります。
 *	* Wed Mar 31 06:00:00 JST 2005 Naoyuki Sawa
 *	- shuffle()関数を追加しました。
 *	* Wed Jun 01 19:58:00 JST 2005 Naoyuki Sawa
 *	- xsize2_table[]の宣言と、XSIZE2()マクロを追加しました。
 *	  xsize2_table[]の実体は、clipxsz2.cにあります。
 *	* Sun Jul 17 17:35:00 JST 2005 Naoyuki Sawa
 *	- COUNTOF()マクロの名称をARRAY_SIZE()に変更しました。
 *	- FIELD_OFFSET()マクロとCONTAINING_RECORD()を追加しました。
 *	* Sun Jul 31 08:07:00 JST 2005 Naoyuki Sawa
 *	- PUT_LEBYTE()/PUT_LEHALF()/PUT_LEWORD()/PUT_BEBYTE()/PUT_BEHALF()/PUT_BEWORD()を追加しました。
 *	- LEBYTE()/LEHALF()/LEWORD()/BEBYTE()/BEHALF()/BEWORD()を、GET_LEBYTE()/GET_LEHALF()/GET_LEWORD()/GET_BEBYTE()/GET_BEHALF()/GET_BEWORD()に改名しました。
 *	  LEBYTE()/LEHALF()/LEWORD()/BEBYTE()/BEHALF()/BEWORD()も、残しておくことにします。残しておくことにした理由は、次のとおりです。
 *	  1. これまでに、LEBYTE()/LEHALF()/LEWORD()/BEBYTE()/BEHALF()/BEWORD()を使って書いたソースコードの、互換性維持のため。
 *	  2. PUT_BEWORD()等よりも、GET_BEWORD()等の方が使う機会が多いと思うので、GET_BEWORD()等の省略記法として、BEWORD()等が使えると便利だから。
 *	* Fri Aug 05 18:19:00 JST 2005 Naoyuki Sawa
 *	- XCHG()マクロを追加しました。
 *	* Wed Aug 17 18:45:00 JST 2005 Naoyuki Sawa
 *	- 任意長パケットキュー(QUEUE)を追加しました。
 *	* Mon Aug 22 22:12:00 JST 2005 Naoyuki Sawa
 *	- ダブルリンクリストを追加しました。
 *	* Fri Aug 26 18:39:00 JST 2005 Naoyuki Sawa
 *	- リンクバッファ(BUFFER)を追加しました。
 *	  2005/08/26現在の実装は、実際にはリング構造でなく、メモリ移動を使った簡易実装となっています。
 *	  もしも今後、速度性能が問題となった場合は、実際にリング構造を使って再実装する予定です。
 *	  その際に、内部処理を変更しても、プログラムインターフェイスは変化しないはずです。
 *	* Thu Sep 15 23:00:00 JST 2005 Naoyuki Sawa
 *	- queue_space()、buffer_space()を追加しました。
 *	* Fri Sep 16 06:00:00 JST 2005 Naoyuki Sawa
 *	- read_queue()にて、packet=NULLが指定された場合に、読み出したパケットデータを破棄するようにしました。
 *	- read_buffer()にて、data=NULLが指定された場合に、読み出したデータを破棄するようにしました。
 *	- create_queue()にて、capacity引数“+sizeof(int)”のストレージを確保するように変更しました。
 *	  最大で、capacityバイトのパケットを一つ、キューに格納できるようにするためです。
 *	  これまでは、呼び出し側にてsizeof(int)を加算して、create_queue()を呼び出していました。
 *	- peek_queue()、peek_buffer()を追加しました。
 *	* Mon Oct 31 05:10:00 JST 2005 Naoyuki Sawa
 *	- shuffle()関数にて、seed引数を参照で受け取り、乱数シードを更新するよう変更しました。
 *	  これまでは、呼び出し側にて乱数シードを更新する必要がありましたが、今後は不要となります。
 *	  <変更前の使用例> shuffle(array, 10, sizeof(int), RND16(seed));
 *	  <変更後の使用例> shuffle(array, 10, sizeof(int), &seed);
 *	* Wed Nov 30 22:35:00 JST 2005 Naoyuki Sawa
 *	- Windowsヘッダファイルとの衝突回避を追加しました。
 *	  これまでは、clipmisc.hを使うWin32プロジェクトが、各々のextclip.hの中で個別に対策していました。
 *	- die()とtrace()をVisual C++でのコンパイルに対応し、実装をclipmisc.hからclipmisc.cへ移動しました。
 *	  これまでのWin32プロジェクトは、clipmisc.hのインクルードのみを行っていましたが、
 *	  今後は、clipmisc.cをプロジェクトに加えて、コンパイル・リンクするよう変更してください。
 *	- fpk_load()コンパイル時の、Visual C++の警告を抑制しました。
 *	- ファイルパック形式、オンメモリファイルパック形式は、利用頻度が低いので、
 *	  コードサイズ節約のために、実装をclipmisc.cからclipfpk.cへ分離しました。
 *	* Thu Dec 01 12:13:00 JST 2005 Naoyuki Sawa
 *	- ユーティリティ：マップを追加しました。
 *	* Thu Dec 02 04:53:00 JST 2005 Naoyuki Sawa
 *	- ユーティリティ：簡略版COMを追加しました。
 *	* Sun Dec 04 15:04:00 JST 2005 Naoyuki Sawa
 *	- query_interface_map()を追加しました。
 *	- safe_addref()、safe_release()、safe_assign()を追加しました。
 *	* Mon Dec 05 04:12:00 JST 2005 Naoyuki Sawa
 *	- safe_attach()、safe_detach()を追加しました。
 *	* Tue Dec 06 02:54:00 JST 2005 Naoyuki Sawa
 *	- Win32版die()に、__declspec(noreturn)の属性を追加しました。
 *	  この変更により、P/ECEとWin32のDIE()マクロを分けて定義する必要が無くなりました。
 *	* Wed Dec 07 04:39:00 JST 2005 Naoyuki Sawa
 *	- safe_query_interface()を追加しました。
 *	* Sat Dec 10 19:24:00 JST 2005 Naoyuki Sawa
 *	- safe_attach()の、(src)式の評価と、(dst)の参照カウント減少の順番を修正しました。
 *	* Sat Dec 10 22:58:00 JST 2005 Naoyuki Sawa
 *	- safe_addref(ptr)が、ptrを返すように変更しました。
 *	* Sun Dec 11 05:44:00 JST 2005 Naoyuki Sawa
 *	- unk_copy()、unk_delete()、unk_equals()を追加しました。
 *	* Sun Dec 11 20:47:00 JST 2005 Naoyuki Sawa
 *	- map_get()の仕様を変更し、値の複製を作って、戻り値とするようにしました。
 *	  これまでは、マップ要素が保持している値を、そのまま返していました。
 *	  このように変更した理由は、仕様の統一のためです。
 *	  特に、UNKNOWN_INTERFACEを値とするMAPにおいて、map_get()の特別扱いをしなくて済むようになりました。
 *	* Mon Dec 12 21:33:00 JST 2005 Naoyuki Sawa
 *	- safe_assign_interface()を追加しました。
 *	* Tue Dec 13 19:00:00 JST 2005 Naoyuki Sawa
 *	- reference_equals()を追加しました。
 *	* Tue Dec 20 05:00:00 JST 2005 Naoyuki Sawa
 *	- apply_interface_map()を追加しました。
 *	* Sun Dec 25 04:58:00 JST 2005 Naoyuki Sawa
 *	- map_remove()の仕様を変更し、削除した要素の値を返さず、自動的に削除するようにしました。
 *	  実際の利用において、削除した要素の値を使うことが少なく、自動的に削除される方が便利と判断したからです。
 *	  削除した要素の値が必要な場合は、あらかじめ、map_get()を用いて値を取得しておいてください。
 *	* Sun Dec 25 15:44:00 JST 2005 Naoyuki Sawa
 *	- map_clear()を追加しました。
 *	- ユーティリティ：可変長配列を追加しました。
 *	* Mon Dec 26 01:25:00 JST 2005 Naoyuki Sawa
 *	- コレクション関連の実装を、clipmisc.cからclipcoll.cへ分離しました。
 *	- インターフェイス関連の実装を、clipmisc.cからclipintf.cへ分離しました。
 *	* Fri Jan 06 21:27:00 JST 2006 Naoyuki Sawa
 *	- map_duplicate()、array_duplicate()を追加しました。
 *	* Wed Jan 18 19:00:00 JST 2006 Naoyuki Sawa
 *	- map_keys()を追加しました。
 *	* Mon Jan 30 08:44:00 JST 2006 Naoyuki Sawa
 *	- マクロの中で使っている変数名を、tmp→__tmp__に変更しました。
 *	  マクロの外で使っている変数名との衝突を避けるためです。
 *	* Fri Apr 14 21:09:00 JST 2006 Naoyuki Sawa
 *	- ARRAY_SIZE()の戻り値を(size_t)→(int)に変更しました。
 *	- これまでは、ARRAY_SIZE()の戻り値と(int)値の比較を行うと、符号無し比較が行われていました。
 *	  負値との比較を行う場合は、ARRAY_SIZE()の戻り値を明示的に(int)にキャストする必要がありました。
 *	    (変更前) if(i >      ARRAY_SIZE(array)) { ... } // iが-1の場合に、誤って「True」と判断されてしまう。
 *	    (変更前) if(i > (int)ARRAY_SIZE(array)) { ... } // 正しい判断のためには、明示的なキャストが必要だった。
 *	- 今回の変更により、ARRAY_SIZE()の戻り値は常に(int)になったので、利用側での明示的なキャストは不要になりました。
 *	    (変更後) if(i >      ARRAY_SIZE(array)) { ... } // iが-1の場合も、正しく「False」と判断します。
 *	* Sat Jun 17 05:11:45 JST 2006 Naoyuki Sawa
 *	- clipstd.hにてstddef.hのincludeを有効にしたので、offsetof()マクロが利用できるようになりました。
 *	  もう、FIELD_OFFSET()マクロは不要になったので、削除しました。
 *	  今後は、windows.h互換のFIELD_OFFSET()マクロではなく、ANSI標準のoffsetof()マクロを使ってください。
 *	* Thu Jul 06 12:09:17 JST 2006 Naoyuki Sawa
 *	- rnd32()、RND32()、rnd32_range()、RND32_RANGE()を追加しました。
 *	- shuffle()において、16bit乱数→32bit乱数を利用するよう変更しました。
 *	  この変更により、65536要素以上の配列をシャッフルできなかった制限が無くなりました。
 *	* Tue Nov 07 01:17:45 JST 2006 Naoyuki Sawa
 *	- map_empty()、array_empty()を追加しました。
 *	* Tue Nov 07 12:46:58 JST 2006 Naoyuki Sawa
 *	- ARRAY(可変長配列、array_*())をLIST(リスト、list_*())に変更しました。
 *	  プログラムの内容は変わらず、名前が変わっただけです。
 *	  これまでARRAYの処理内容はリストであったにもかかわらず、LIST_ENTRYとの名前衝突を避けるためにあえてARRAYと名付けていました。
 *	  しかし、やはり実態との一致を優先することにし、ARRAY_ENTRY構造体をLIST_NODEに改名して、LIST_ENTRYとの名前衝突を避けました。
 *	  この名前付けルールに合わせて、MAP_ENTRY構造体もMAP_NODEに改名しました。
 *	* Mon Dec 04 16:44:51 JST 2006 Naoyuki Sawa
 *	- ユーティリティ：プールを追加しました。
 *	* Wed Dec 06 03:36:51 JST 2006 Naoyuki Sawa
 *	- pool_free()から返却先プールの引数を不要としました。
 *	* Tue Jan 02 22:11:35 JST 2007 Naoyuki Sawa
 *	- プールに、参照カウント式ガーベージコレクションの機能を内包しました。
 *	* Sun Nov 04 14:59:39 JST 2007 Naoyuki Sawa
 *	- UPDOWN_MOTION()マクロを追加しました。
 *	* Tue Apr 01 12:10:19 JST 2008 Naoyuki Sawa
 *	- linux2.6 の include/linux/kernel.h を参考に、コンパイル時型検査のマクロを作成しました。
 *	* Sat Mar 14 21:13:42 JST 2009 Naoyuki Sawa
 *	- プールに、確保時コールバックと解放時コールバックを追加しました。
 */
#ifndef __CLIP_MISC_H__
#define __CLIP_MISC_H__

/*****************************************************************************
 *	Windowsヘッダファイルとの衝突回避
 *****************************************************************************/

#ifdef WIN32

#undef HIBYTE
#undef LOBYTE

//#undef FIELD_OFFSET → 2006/06/17 FIELD_OFFSET()の定義を削除したので、もう、windows.hとの衝突回避は不要になりました。
#undef CONTAINING_RECORD

#define _LIST_ENTRY _xLIST_ENTRY
#define  LIST_ENTRY  xLIST_ENTRY

#define strcasecmp  stricmp
#define strncasecmp strnicmp

#endif /*WIN32*/

/*****************************************************************************
 *	汎用マクロ・関数
 *****************************************************************************/

/* * Tue Apr 01 12:10:19 JST 2008 Naoyuki Sawa
 * - linux2.6 の include/linux/kernel.h を参考に、コンパイル時型検査のマクロを作成しました。
 *   typecheck()は常に1と評価されるので、タイプセーフなマクロからの利用が容易です。
 *   <例> #define less_than(a,b) (typecheck(fixed,a)&&typecheck(fixed,b)&&(int)(a)<(int)(b))
 * - Check at compile time that something is of a particular type.
 *   Always evaluates to 1 so you may use it easily in comparisons.
 */
#define typecheck(type, x) ({			\
	type      __dummy1__;			\
	typeof(x) __dummy2__;			\
	(void)(&__dummy1__ == &__dummy2__);	\
	1; })

#define DIE()		die(__FILE__ "(%d)", __LINE__)

#ifdef DEBUG
#define ASSERT(f)	((void)((f) || (die(__FILE__ "(%d): %s", __LINE__, #f), 0)))
#define VERIFY(f)	ASSERT(f)
#else /*DEBUG*/
#define ASSERT(f)	((void)0)
#define VERIFY(f)	((void)(f))
#endif /*DEBUG*/

/* ビット操作 */
#define BTST(a, b)	(((char*)(a))[(b) / 8] &    1 << ((b) & 7) )
#define BCLR(a, b)	(((char*)(a))[(b) / 8] &= ~(1 << ((b) & 7)))
#define BSET(a, b)	(((char*)(a))[(b) / 8] |=   1 << ((b) & 7) )
#define BNOT(a, b)	(((char*)(a))[(b) / 8] ^=   1 << ((b) & 7) )

/* 16ビット整数値のバイトスワップ */
#define SWAPH(a) \
	(((a) >> 8 & 0x00ff) | \
	 ((a) << 8 & 0xff00))
/* 32ビット整数値のバイトスワップ */
#define SWAPW(a) \
	(((a) >> 24 & 0x000000ff) | \
	 ((a) >>  8 & 0x0000ff00) | \
	 ((a) <<  8 & 0x00ff0000) | \
	 ((a) << 24 & 0xff000000))

/* 任意の型の二つの変数を入れ替えます。(gcc拡張機能を使っているので、VC++では使えません。) */
#define XCHG(a, b) do {		\
	typeof(a) __a__ = (a);	\
	typeof(b) __b__ = (b);	\
	(a) = __b__;		\
	(b) = __a__;		\
} while(0)

/* GET_LEBYTE()/GET_LEHALF()/GET_LEWORD()/GET_BEBYTE()/GET_BEHALF()/GET_BEWORD()の省略記法 */
#define LEBYTE(p)	GET_LEBYTE(p)
#define LEHALF(p)	GET_LEHALF(p)
#define LEWORD(p)	GET_LEWORD(p)
#define BEBYTE(p)	GET_BEBYTE(p)
#define BEHALF(p)	GET_BEHALF(p)
#define BEWORD(p)	GET_BEWORD(p)

/* リトルエンディアンのバイトオーダーでバイト値、ハーフワード値、ワード値を読み出します。
 * ポインタpはハーフワード境界やワード境界に整列されていなくても構いません。
 */
#define GET_LEBYTE(p)	((unsigned char )(((unsigned char*)(p))[0]<< 0))
#define GET_LEHALF(p)	((unsigned short)(((unsigned char*)(p))[0]<< 0|((unsigned char*)(p))[1]<< 8))
#define GET_LEWORD(p)	((unsigned int  )(((unsigned char*)(p))[0]<< 0|((unsigned char*)(p))[1]<< 8|((unsigned char*)(p))[2]<<16|((unsigned char*)(p))[3]<<24))

/* ビッグエンディアンのバイトオーダーでバイト値、ハーフワード値、ワード値を読み出します。
 * ポインタpはハーフワード境界やワード境界に整列されていなくても構いません。
 */
#define GET_BEBYTE(p)	((unsigned char )(((unsigned char*)(p))[0]<< 0))
#define GET_BEHALF(p)	((unsigned short)(((unsigned char*)(p))[0]<< 8|((unsigned char*)(p))[1]<< 0))
#define GET_BEWORD(p)	((unsigned int  )(((unsigned char*)(p))[0]<<24|((unsigned char*)(p))[1]<<16|((unsigned char*)(p))[2]<< 8|((unsigned char*)(p))[3]<< 0))

/* リトルエンディアンのバイトオーダーでバイト値、ハーフワード値、ワード値を書き込みます。
 * ポインタpはハーフワード境界やワード境界に整列されていなくても構いません。
 */
#define PUT_LEBYTE(p,v)	do { ((unsigned char*)(p))[0]=(unsigned char)((v)>> 0); } while(0)
#define PUT_LEHALF(p,v)	do { ((unsigned char*)(p))[0]=(unsigned char)((v)>> 0); ((unsigned char*)(p))[1]=(unsigned char)((v)>> 8); } while(0)
#define PUT_LEWORD(p,v)	do { ((unsigned char*)(p))[0]=(unsigned char)((v)>> 0); ((unsigned char*)(p))[1]=(unsigned char)((v)>> 8); ((unsigned char*)(p))[2]=(unsigned char)((v)>>16); ((unsigned char*)(p))[3]=(unsigned char)((v)>>24); } while(0)

/* ビッグエンディアンのバイトオーダーでバイト値、ハーフワード値、ワード値を書き込みます。
 * ポインタpはハーフワード境界やワード境界に整列されていなくても構いません。
 */
#define PUT_BEBYTE(p,v)	do { ((unsigned char*)(p))[0]=(unsigned char)((v)>> 0); } while(0)
#define PUT_BEHALF(p,v)	do { ((unsigned char*)(p))[0]=(unsigned char)((v)>> 8); ((unsigned char*)(p))[1]=(unsigned char)((v)>> 0); } while(0)
#define PUT_BEWORD(p,v)	do { ((unsigned char*)(p))[0]=(unsigned char)((v)>>24); ((unsigned char*)(p))[1]=(unsigned char)((v)>>16); ((unsigned char*)(p))[2]=(unsigned char)((v)>> 8); ((unsigned char*)(p))[3]=(unsigned char)((v)>> 0); } while(0)

/* ハーフワード値の上位バイト、下位バイトを取得します。 */
#define HIBYTE(h)	((unsigned char)((h) >> 8))
#define LOBYTE(h)	((unsigned char)((h) >> 0))

/* ワード値の上位ハーフワード、下位ハーフワードを取得します。 */
#define HIHALF(w)	((unsigned short)((w) >> 16))
#define LOHALF(w)	((unsigned short)((w) >>  0))

///* 8ビット乱数(『Z80マシン語秘伝の書』より) */
//#define RND8(s)	(((s) = (s) * 5 + 0x3711) >> 8 & 0xff)
///* 16ビット乱数(VisualC++ 6.0 \VC98\CRT\SRC\RAND.C を参考にしました) */
//#define RND16(s)	(((s) = (s) * 214013 + 2531011) >> 16 & 0xffff)
//↓2004/09/15 コンパイラバグ(?)で負値になってしまう場合があったので、本体処理を関数化しました。
//↓           過去のソースの互換性のため、関数を呼び出すマクロも定義してあります。
/* 8ビット乱数 */
int rnd8(int* seed);			/* 戻り値の型は符号付き(int)で、範囲は+0x00000000～+0x000000FFです。 */
#define RND8(s)		(rnd8(&(s)))
/* 16ビット乱数 */
int rnd16(int* seed);			/* 戻り値の型は符号付き(int)で、範囲は+0x00000000～+0x0000FFFFです。 */
#define RND16(s)	(rnd16(&(s)))
/* 32ビット乱数 */
int rnd32(int* seed);			/* 戻り値の型は符号付き(int)で、範囲は-0x80000000～+0x7FFFFFFFです。要注意!! */
#define RND32(s)	(rnd32(&(s)))

/* (a)以上(b)★未満★の乱数を生成 */
//#define RND8_RANGE(s, a, b)	(RND8(s) % ((b) - (a)) + (a))
//#define RND16_RANGE(s, a, b)	(RND16(s) % ((b) - (a)) + (a))
//↓2004/09/15 コンパイラバグ(?)で負値になってしまう場合があったので、本体処理を関数化しました。
//↓           過去のソースの互換性のため、関数を呼び出すマクロも定義してあります。
/* (a)以上(b)★未満★の乱数を生成 */
int rnd8_range(int* seed, int a, int b);
#define RND8_RANGE(s, a, b)	(rnd8_range(&(s), (a), (b)))
int rnd16_range(int* seed, int a, int b);
#define RND16_RANGE(s, a, b)	(rnd16_range(&(s), (a), (b)))
int rnd32_range(int* seed, int a, int b);
#define RND32_RANGE(s, a, b)	(rnd32_range(&(s), (a), (b)))

/* 配列(array)の要素数を求めます。 */
//#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
//↓2006/04/14 ARRAY_SIZE()の戻り値を(size_t)→(int)に変更しました。
//↓これまでは、ARRAY_SIZE()の戻り値と(int)値の比較を行うと、符号無し比較が行われていました。
//↓負値との比較を行う場合は、ARRAY_SIZE()の戻り値を明示的に(int)にキャストする必要がありました。
//↓  (変更前) if(i >      ARRAY_SIZE(array)) { ... } // iが-1の場合に、誤って「True」と判断されてしまう。
//↓  (変更前) if(i > (int)ARRAY_SIZE(array)) { ... } // 正しい判断のためには、明示的なキャストが必要だった。
//↓今回の変更により、ARRAY_SIZE()の戻り値は常に(int)になったので、利用側での明示的なキャストは不要になりました。
//↓  (変更後) if(i > ARRAY_SIZE(array)) { ... } // iが-1であっても、正しく「False」と判断します。
#define ARRAY_SIZE(array) ((int)(sizeof(array) / sizeof((array)[0])))

///* 構造体(type)の先頭から、フィールド(field)までのオフセットバイト数を求めます。 */
//#define FIELD_OFFSET(type,field) ((int)&(((type*)0)->field))
//↓削除しました。
// * Sat Jun 17 05:11:45 JST 2006 Naoyuki Sawa
// - clipstd.hにてstddef.hのincludeを有効にしたので、offsetof()マクロが利用できるようになりました。
//   もう、FIELD_OFFSET()マクロは不要になったので、削除しました。
//   今後は、windows.h互換のFIELD_OFFSET()マクロではなく、ANSI標準のoffsetof()マクロを使ってください。

/* 構造体(type)のフィールド(field)のアドレスから、構造体(type)の先頭アドレスを求めます。 */
//#define CONTAINING_RECORD(address,type,field)	((type*)((int)(address) - FIELD_OFFSET(type,field)))
//↓Sat Jun 17 05:11:45 JST 2006 Naoyuki Sawa FIELD_OFFSET()→offsetof()を使うように変更しました。
#define CONTAINING_RECORD(address,type,field)	((type*)((int)(address) - offsetof(type,field)))

/* 1バイト値をビット反転します。
 * 注意!! 引数は、0x00～0xffの範囲でなければいけません。
 *        範囲外の値を指定すると、誤った結果となります。
 */
#define MIRROR(a)	(mirror_table[(a)])
extern const unsigned char mirror_table[0x100]; /* -> clipmirr.c */

/* 1バイト値(1ビット×8ピクセル)を水平に二倍拡大します。
 * 注意!! 引数は、0x00～0xffの範囲でなければいけません。
 *        範囲外の値を指定すると、誤った結果となります。
 */
#define XSIZE2(a)	(xsize2_table[(a)])
extern const unsigned short xsize2_table[0x100]; /* -> clipxsz2.c */

/* 往復運動カウンタを生成します。
 * - あまり頻繁に使うものでもないと思ったので、clipmiscモジュールのサイズが無駄に増えないよう、マクロにしました。
 *   もし、頻繁に使う場合は、アプリケーション内で関数化してください。
 * <使用例>
 *	UPDOWN_MOTION(now,5) → 0,1,2,3,4,3,2,1,0,1,2,...
 */
#define UPDOWN_MOTION(i,n)	(abs(((i)+((n)-2))%(((n)-1)*2)-((n)-2)))

/* 配列要素をシャッフルします。
 * [in]
 *	base		配列の先頭アドレス。
 *	num		配列の要素数。
 *	width		配列要素ひとつ当りのバイト数。
 *	seed		シャッフル用乱数シード。
 * [note]
 *	* 引数の並びは、最後のseed以外、標準Cライブラリのqsort()関数に互換です。
 *	* numが0未満ならば、不正な配列と見なしてアサートします。
 *	// * 2005/03/31現在の実装は、16bit乱数を利用しているために、65536要素以上の配列をシャッフルできません。
 *	//   numが65536よりも大きいと、アサートします。
 *	↓2006/07/06 追記
 *	* Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
 *	- rnd32()の新設に伴い、16bit乱数→32bit乱数を利用するよう変更しました。
 *	  この変更により、65536要素以上の配列をシャッフルできなかった制限が無くなりました。
 */
//void shuffle(void* base, int num, int width, int seed);
//↓* Mon Oct 31 05:10:00 JST 2005 Naoyuki Sawa
//↓- shuffle()関数にて、seed引数を参照で受け取り、乱数シードを更新するよう変更しました。
//↓  これまでは、呼び出し側にて乱数シードを更新する必要がありましたが、今後は不要となります。
//↓  <変更前の使用例> shuffle(array, 10, sizeof(int), RND16(seed));
//↓  <変更後の使用例> shuffle(array, 10, sizeof(int), &seed);
void shuffle(void* base, int num, int width, int* seed);

/* DDA(Digital Differential Analysis)構造体
 * * Sun Dec 4 04:01:00 JST 2004 Naoyuki Sawa (コメント追加のみ)
 * - 現在値を保持するフィールドはありません。
 *   現在値はDDA構造体とは別に保持してください。
 *   ただし、DDA構造体の一部のフィールドが不要となる場合は、そこに保持することもできます。
 *   詳しくは、次のコメントを参照してください。
 * - DDA構造体を汎用にサポートする関数はないので、各フィールドは任意に利用して構いません。
 *   たとえば、進行方向が＋方向固定ならば、多くの場合、繰上げ時の変化量は1固定となります。
 *   その場合、vを使う必要がなくなるので、代りに現在値をvに保持することができます。
 */
typedef struct _DDA {
	int n;			/* + 0,4 端数の増加量     */
	int d;			/* + 4,4 端数             */
	int u;			/* + 8,4 毎回の変化量     */
	int v;			/* +12,4 繰上げ時の変化量 */
				/* =16                    */
} DDA;

/* * Sun Dec 12 09:59:00 JST 2004 Naoyuki Sawa
 * - BLOCKSIZE、SPEAKER_FREQUENCYはP/ECE特有の定数ですが、Win32版テストプログラムからも参照するために、
 *   clippce.hからclipmisc.hへ移動しました。
 */
#define BLOCKSIZE		4096	/* フラッシュメモリのセクタサイズ */
#define SPEAKER_FREQUENCY	16000	/* P/ECEスピーカー出力周波数[Hz] */

/*****************************************************************************
 *	エラー処理
 *****************************************************************************/

/* エラーメッセージを表示し、プログラムを強制終了します。
 * [in]
 *	fmt,...		printf()の引数と同様です。
 * [note]
 *	* この関数は処理を返しません。
 */
#ifdef PIECE
void die(const char* fmt, ...) __attribute__((noreturn));
#else /*PIECE*/
__declspec(noreturn) void die(const char* fmt, ...);
#endif /*PIECE*/

/*****************************************************************************
 *	トレース出力
 *****************************************************************************/

/* !!要注意!! TRACE()マクロはアプリケーション専用です。CLiPライブラリの中で使わないように!!
 *            (TRACE()マクロはTRACE_ONシンボルの定義によって振る舞いが変わるので、
 *             あらかじめコンパイルされるライブラリの中ではTRACE_ONによる振る舞いの切り替えが効かないから)
 *
 * * トレース出力を利用する場合は、  clip.hをインクルードする前に「#define TRACE_ON 1」を定義してください。
 *   トレース出力を利用しない場合は、clip.hをインクルードする前に「#define TRACE_ON 0」を定義するか、
 *   またはTRACE_ONシンボルを定義しないでください。
 * * トレース出力を利用しない場合は、トレース文字列はCコンパイラの最適化によって削除されます。
 *   TRACE()呼び出しを削除しなくても、トレース文字列がメモリを圧迫することはありません。
 */
#if defined(TRACE_ON) && (TRACE_ON)
#define TRACE	trace
#else
#define TRACE	1 ? (void)0 : trace
#endif

/* 標準エラー出力へのfprintfです。
 * [in]
 *	fmt,...		printf()の引数と同様です。
 * [note]
 *	* TRACEマクロ経由で利用します。
 */
void trace(const char* fmt, ...);

/*****************************************************************************
 *	ユーティリティ：任意長パケットキュー
 *****************************************************************************/

/* * 任意長パケットのFIFOキューを表します。キューの構造は下図のとおりです。
 *
 *	+==================+･･････････････････････････････････････････････
 *	|     capacity     |　↑　　　　　　　　　　　　　　　　　　　　　
 *	+------------------+　│QUEUE 　　　　　　　　　　　　　　　　　　
 *	|       size       |　↓　　　　　　　　　　　　　　　　　　　　　
 *	+==================+･･････････････････････････････････････････････
 *	| 1個目のﾊﾟｹｯﾄｻｲｽﾞ |　　word　　　　　　　　　　↑　　　↑　　　　
 *	+------------------+･･････････････････････････　│　　　│　　　　
 *	|                  |　↑　　　　　　　　　　　　│　　　│　　　　
 *	| 1個目のﾊﾟｹｯﾄﾃﾞｰﾀ |　│byte[1個目のﾊﾟｹｯﾄｻｲｽﾞ]　│　　　│　　　　
 *	|                  |　↓　　　　　　　　　　　　│　　　│　　　　
 *	+------------------+･･････････････････････････　│　　　│　　　　
 *	| 2個目のﾊﾟｹｯﾄｻｲｽﾞ |　　word　　　　　　　　　　│　　　│　　　　
 *	+------------------+･･････････････････････････　│　　　│　　　　
 *	|                  |　↑　　　　　　　　　　　　│　　　│　　　　
 *	| 2個目のﾊﾟｹｯﾄﾃﾞｰﾀ |　│byte[2個目のﾊﾟｹｯﾄｻｲｽﾞ]　│　　　│　　　　
 *	|                  |　↓　　　　　　　　　　　　│　　　│　　　　
 *	+------------------+･･････････････････････････　│　　　│　　　　
 *	|        ・        |　　　　　　　　　　　　　　│size　│capacity
 *	|        ・        |　　　　　　　　　　　　　　│　　　│　　　　
 *	|        ・        |　　　　　　　　　　　　　　│　　　│　　　　
 *	+------------------+･･････････････････････････　│　　　│　　　　
 *	| N個目のﾊﾟｹｯﾄｻｲｽﾞ |　　word　　　　　　　　　　│　　　│　　　　
 *	+------------------+･･････････････････････････　│　　　│　　　　
 *	|                  |　↑　　　　　　　　　　　　│　　　│　　　　
 *	| N個目のﾊﾟｹｯﾄﾃﾞｰﾀ |　│byte[N個目のﾊﾟｹｯﾄｻｲｽﾞ]　│　　　│　　　　
 *	|                  |　↓　　　　　　　　　　　　↓　　　│　　　　
 *	+------------------+･･････････････････････････････････　│　　　　
 *	|                  |　　　　　　　　　　　　　　　　　　│　　　　
 *	|    (空き領域)    |　　　　　　　　　　　　　　　　　　│　　　　
 *	|                  |　　　　　　　　　　　　　　　　　　↓　　　　
 *	+==================+･･････････････････････････････････････････････
 */
typedef struct _QUEUE {
	int capacity;	/* ストレージの総容量 */
	int size;	/* ストレージの使用量 */
	/*unsigned char storage[capacity]*/
} QUEUE;

/* キューを作成します。
 * [in]
 *	capacity	ストレージサイズ。
 *			実際に確保するストレージサイズは、capacity+sizeof(int)となります。
 *			[note]を参照してください。
 * [out]
 *	戻り値		作成したキュー。
 * [note]
 *	* キューの使用が終わったら、delete_queue()で削除してください。
 *	* create_queue()が実際に確保するストレージサイズは、(capacity+sizeof(int))です。
 *	  最大で、capacityバイトのパケットを一つ、キューに格納できるようにするためです。
 *	  呼び出し側にて、パケットサイズ格納用のsizeof(int)を加算して指定する必要はありません。
 */
QUEUE* create_queue(int capacity);

/* キューを削除します。
 * [in]
 *	queue		削除するキュー。
 */
void delete_queue(QUEUE* queue);

/* キューを空にします。
 * [in]
 *	queue		空にするキュー。
 */
void clear_queue(QUEUE* queue);

/* キューにパケットを追加します。
 * [in]
 *	queue		キュー。
 *	packet		追加するパケットデータ。
 *	length		追加するパケットサイズ。(0、または、正数)
 * [out]
 *	戻り値		成功ならば、パケットサイズをそのまま返します。
 *			失敗ならば、負数を返します。
 * [note]
 *	* 0バイトのパケットを追加することも可能です。
 *	  戻り値「0」は、成功を意味することに注意してください。
 */
int write_queue(QUEUE* queue, const void* packet/*[length]*/, int length);

/* キューからパケットを取り出します。
 * [in]
 *	queue		キュー。
 *	packet		取り出したパケットデータを格納するメモリ領域。
 *			NULLを指定すると、読み出したパケットデータを破棄します。
 *	length		取り出したパケットサイズ。(0、または、正数)
 * [out]
 *	戻り値		成功ならば、取り出したパケットサイズを返します。
 *			失敗ならば、負数を返します。
 * [note]
 *	* 0バイトのパケットを取り出すことも有り得ます。
 *	  戻り値「0」は、成功を意味することに注意してください。
 *	* packet=NULLを指定した場合、読み出したパケットデータを破棄します。
 *	  その際も、length引数は意味を持つことに注意してください。
 *	  キューの先頭にある任意長のパケットを破棄するには、次のように呼び出してください。
 *		read_queue(queue, NULL, INT_MAX);
 */
int read_queue(QUEUE* queue, void* packet/*[maxlength]*/, int maxlength);

/* キューの先頭のパケットを参照します。
 * [in]
 *	queue		キュー。
 *	length		パケットサイズを格納する変数へのポインタ。
 *			NULLを指定すると、パケットサイズを格納しません。
 * [out]
 *	戻り値		パケットデータの先頭アドレス。
 *			キューが空の場合、NULLを返し、パケットサイズを格納しません。
 * [note]
 *	* キューが空の場合と、先頭のパケットが0バイトの場合の違いに注意してください。
 *	  キューが空の場合は、NULLを返し、パケットサイズを格納しません。
 *	  先頭のパケットが0バイトの場合は、NULL以外のポインタを返し、パケットサイズに0を格納します。
 */
const void* peek_queue(QUEUE* queue, int* length);

/* キューに追加可能な、最大パケットサイズを求めます。
 * [in]
 *	queue		キュー。
 * [out]
 *	戻り値		最大パケットサイズ。
 */
int queue_space(QUEUE* queue);

/*****************************************************************************
 *	ユーティリティ：リングバッファ
 *****************************************************************************/

/* 2005/08/26現在の実装は、実際にはリング構造でなく、メモリ移動を使った簡易実装となっています。
 * もしも今後、速度性能が問題となった場合は、実際にリング構造を使って再実装する予定です。
 * その際に、内部処理を変更しても、プログラムインターフェイスは変化しないはずです。
 */
typedef struct _BUFFER {
	int capacity;	/* ストレージの総容量 */
	int size;	/* ストレージの使用量 */
	/*unsigned char storage[capacity]*/
} BUFFER;

/* バッファを作成します。
 * [in]
 *	capacity	ストレージサイズ。
 * [out]
 *	戻り値		作成したバッファ。
 * [note]
 *	* バッファの使用が終わったら、delete_buffer()で削除してください。
 */
BUFFER* create_buffer(int capacity);

/* バッファを削除します。
 * [in]
 *	buffer		削除するバッファ。
 */
void delete_buffer(BUFFER* buffer);

/* バッファを空にします。
 * [in]
 *	queue		空にするバッファ。
 */
void clear_buffer(BUFFER* buffer);

/* バッファにデータを書き込みます。
 * [in]
 *	buffer		バッファ。
 *	data		書き込むデータ。
 *	length		書き込むデータ長。
 * [out]
 *	戻り値		実際に書き込んだデータ長を返します。(0≦戻り値≦length)
 *			ストレージの空き容量が不足している場合、部分的な書き込みとなります。
 *			部分的な書き込みを行った場合、戻り値は、lengthよりも小さくなります。
 */
int write_buffer(BUFFER* buffer, const void* data/*[length]*/, int length);

/* バッファからデータを読み出します。
 * [in]
 *	buffer		バッファ。
 *	data		読み出したデータを格納するメモリ領域。
 *			NULLを指定すると、読み出したデータを破棄します。
 *	maxlength	読み出すデータの最大長。
 * [out]
 *	戻り値		実際に読み出したデータ長を返します。(0≦戻り値≦length)
 */
int read_buffer(BUFFER* buffer, void* data/*[maxlength]*/, int maxlength);

/* バッファのデータを参照します。
 * [in]
 *	buffer		バッファ。
 *	length		データ長を格納する変数へのポインタ。
 *			NULLを指定すると、データ長を格納しません。
 * [out]
 *	戻り値		ストレージの先頭アドレス。
 * [note]
 *	* この関数は、必ず成功します。
 *	  バッファが空の場合も、ストレージの先頭アドレスを返し、データ長に0を格納します。
 */
const void* peek_buffer(BUFFER* buffer, int* length);

/* バッファに書き込み可能な、最大データ長を求めます。
 * [in]
 *	buffer		バッファ。
 * [out]
 *	戻り値		最大データ長。
 */
int buffer_space(BUFFER* buffer);

/*****************************************************************************
 *	ユーティリティ：ダブルリンクリスト
 *****************************************************************************/

/* Windows DDK互換の、ダブルリンクリスト操作関数群です。
 * CONTAINING_RECORD()マクロと併せて、使用してください。
 */
typedef struct _LIST_ENTRY {
	struct _LIST_ENTRY *Flink;	/* 前方リンク */
	struct _LIST_ENTRY *Blink;	/* 後方リンク */
} LIST_ENTRY;

/* ダブルリンクリストを初期化します。 */
void InitializeListHead(LIST_ENTRY* ListHead);

/* ダブルリンクリストが空か否か、判定します。 */
int IsListEmpty(LIST_ENTRY* ListHead);

/* ダブルリンクリストから、先頭の要素を取り除きます。 */
LIST_ENTRY* RemoveHeadList(LIST_ENTRY* ListHead);

/* ダブルリンクリストから、末尾の要素を取り除きます。 */
LIST_ENTRY* RemoveTailList(LIST_ENTRY* ListHead);

/* ダブルリンクリストから、指定した要素を取り除きます。 */
void RemoveEntryList(LIST_ENTRY* Entry);

/* ダブルリンクリストの先頭に、指定した要素を追加します。 */
void InsertHeadList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry);

/* ダブルリンクリストの末尾に、指定した要素を追加します。 */
void InsertTailList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry);

/*****************************************************************************
 *	ユーティリティ：コレクションのヘルパ関数
 *****************************************************************************/

/* ヘルパ関数の実装例: コレクションがメモリ管理を行わないポインタ、または、数値
 */
void* ptr_copy(void* a);
void  ptr_delete(void* a);
int   ptr_equals(void* a, void* b);

/* ヘルパ関数の実装例: コレクションがメモリ管理を行う文字列
 * * map_put()は、渡された文字列をコピーして、コレクションに保持します。
 * // * map_get()は、文字列をコピーせず、保持している文字列のポインタをそのまま返します。
 * //   必要に応じて、map_get()の呼び出し元が、文字列のコピーを作成してください。
 * ↓2005/12/11 仕様変更
 * * map_get()は、保持している文字列のコピーを作成して、呼び出し元に返します。
 *   map_get()の呼び出し元は、文字列の使用が終了したら、str_delete()を使って文字列を解放してください。
 *   str_delete()の実装は、単にfree()を行っているだけなので、直接free()を使って解放しても構いません。
 */
void* str_copy(void* a);
void  str_delete(void* a);
int   str_equals(void* a, void* b);

/* ヘルパ関数の実装例: インターフェイスポインタ (UNKNOWN_INTERFACE**)
 * * キーとして用いた場合の等価判定は、オブジェクト比較です。
 *   オブジェクトが複数のインターフェイスをサポートしている場合、
 *   そのオブジェクトに対するUNKNOWNインターフェイスポインタは、複数存在します。
 *   unk_equals()は、それらの異なるインターフェイスポインタを等価と見なします。
 *   このような挙動が必要ない場合(単なるポインタ比較で良い場合)は、
 *   unk_equals()の代りに、ptr_equals()を使ってください。
 * * map_put()は、渡されたインターフェイスポインタをaddref()して、コレクションに保持します。
 * // * map_get()は、インターフェイスポインタをaddref()せず、そのまま返します。
 * //   この挙動は、参照カウントの増減ルール[ルール1-1]に反する、特例です。
 * //   必要に応じて、map_get()の呼び出し元が、addref()を行ってください。
 * //   呼び出し元が、addref()を行わなかった場合は、release()も不要です。
 * ↓2005/12/11 仕様変更
 * * map_get()が、インターフェイスポインタをaddref()して、呼び出し元に返すようになりました。
 *   呼び出し元が、map_get()から返されたインターフェイスポインタに対し、addref()する必要はありません。
 *   呼び出し元は、返されたインターフェイスポインタの使用が終了したら、release()を行う必要があります。
 *   以上の挙動は、参照カウントの増減ルール[ルール1-1]に準拠しています。
 *   すなわち、2005/12/11の仕様変更により、map_get()の挙動だけを特別扱いする必要が無くなりました。
 */
void* unk_copy(void* a);
void  unk_delete(void* a);
int   unk_equals(void* a, void* b);

/*****************************************************************************
 *	ユーティリティ：マップ (コレクション)
 *****************************************************************************/

/* マップ情報 */
typedef struct _MAP_INFO {
	void* (*key_copy)(void* key);			/* キーを複製する、ヘルパ関数 */
	void  (*key_delete)(void* key);			/* キーを削除する、ヘルパ関数 */
	int   (*key_equals)(void* key1, void* key2);	/* キーを比較する、ヘルパ関数 */
	void* (*val_copy)(void* val);			/* 値  を複製する、ヘルパ関数 */
	void  (*val_delete)(void* val);			/* 値  を削除する、ヘルパ関数 */
} MAP_INFO;

/* マップ */
typedef struct _MAP {
	LIST_ENTRY list_head;	/* MAP_NODEのリストヘッダ */
	MAP_INFO map_info;	/* マップ情報 */
} MAP;

/* マップ要素
 * * ガベージコレクションを使用可能とするために、マップ要素とリストエントリの先頭アドレスを揃えてあります。
 *   両者のアドレスが違っていると、ガベージコレクタが未開放のマップ要素を誤って開放してしまうためです。
 * - ガベージコレクションの使用は必須ではありません。
 *   MAP構造体やMAP_NODE構造体のメモリ開放は、ライブラリが明示的に行っています。
 *   キーと値のメモリ管理は、アプリケーション定義のヘルパ関数にて、明示的に行うことが可能です。
 * - ガベージコレクションを使うと、明示的な、キーと値のメモリ解放を省略し、ヘルパ関数を簡略化できます。
 */
typedef struct _MAP_NODE {
	LIST_ENTRY list_entry;	/* MAP_NODEのリストエントリ */
	void* key;		/* キー (実際の型はアプリケーション定義) */
	void* val;		/* 値   (実際の型はアプリケーション定義) */
} MAP_NODE;

/* マップを作成します。
 * [in]
 *	map_info	マップ情報。
 * [out]
 *	戻り値		マップ。
 */
MAP* map_create(const MAP_INFO* map_info);

/* マップを削除します。
 * [in]
 *	map		マップ。
 * [note]
 *	* 自動的にmap_clear()を呼び、残っているマップ要素をすべて削除します。
 *	  明示的にmap_clear()を呼んでおく必要はありません。
 */
void map_delete(MAP* map);

/* マップの全要素を削除します。
 * [in]
 *	map		マップ。
 * [note]
 *	* 各マップ要素について、key_delete()ヘルパ関数を用いて、キーを削除します。
 *	                        val_delete()ヘルパ関数を用いて、値  を削除します。
 */
void map_clear(MAP* map);

/* 指定されたキーに対応するマップ要素が有るか、判定します。
 * [in]
 *	map		マップ。
 *	key		キー。
 * [out]
 *	戻り値		マップ要素が有れば、  0以外の値を返します。
 *			マップ要素が無ければ、0を返します。
 */
int map_contains(MAP* map, void* key);

/* 指定されたキーに対応するマップ要素を作成し、値を格納します。
 * [in]
 *	map		マップ。
 *	key		キー。
 *	val		値。
 * [note]
 *	* key_copy()ヘルパ関数を用いて、キーを複製し、マップ要素に格納します。
 *	  アプリケーションは、呼び出し時に指定したkeyを維持する必要はありません。
 *	  ただし、key_copy()ヘルパ関数が複製を行わない場合は、この限りではありません。
 *	* val_copy()ヘルパ関数を用いて、値を複製し、マップ要素に格納します。
 *	  アプリケーションは、呼び出し時に指定したvalを維持する必要はありません。
 *	  ただし、val_copy()ヘルパ関数が複製を行わない場合は、この限りではありません。
 *	* 既に、指定されたキーに対応する値が存在する場合は、既存の値を削除します。
 *	  既存の値の削除には、val_delete()ヘルパ関数が利用されます。
 */
void map_put(MAP* map, void* key, void* val);

/* 指定されたキーに対応するマップ要素の、値を取得します。
 * [in]
 *	map		マップ。
 *	key		キー。
 * [out]
 *	戻り値		値。
 * [note]
 *	* 指定されたキーに対応するマップ要素が存在しない場合は、アサートします。
 *	  先にmap_contains()を用いて、キーに対応するマップ要素が存在することを確認してください。
 *	  <例>	if(map_contains(map, key)) {
 *			val = map_get(map, key);
 *			...
 *			free(val); // 2005/12/11の仕様変更により、値の解放が必要となりました。
 *		}
 *	// * 返される値は、複製ではなく、マップ要素が保持している値をそのまま返します。
 *	//   呼び出し側アプリケーションにて、返された値を削除してはいけません。
 *	//↓2005/12/11 仕様変更
 *	* map_get()は、val_copy()ヘルパ関数を用いて値の複製を作成し、その複製を返します。
 *	  返された値の所有権は、map_get()を呼び出した側のみに有ります。
 *	  map_get()を呼び出した側は、返された値を適切に解放することを忘れないでください。
 */
void* map_get(MAP* map, void* key);

/* 指定されたキーに対応するマップ要素を削除します。
 * [in]
 *	map		マップ。
 *	key		キー。
 * [note]
 *	* 指定されたキーに対応するマップ要素が存在しない場合は、アサートします。
 *	  先にmap_contains()を用いて、キーに対応するマップ要素が存在することを確認してください。
 *	  <例>	if(map_contains(map, key)) {
 *			map_remove(map, key);
 *		}
 *	* 削除するマップ要素のキーは、key_delete()ヘルパ関数を用いて、自動的に削除されます。
 *	  削除するマップ要素の値  は、val_delete()ヘルパ関数を用いて、自動的に削除されます。
 */
void map_remove(MAP* map, void* key);

/* マップを複製します。
 * [in]
 *	map		複製元のマップ。
 * [out]
 *	戻り値		複製したマップ。
 * [note]
 *	* この関数が行う処理は、以下のとおりです。
 *	  1. 複製元のマップと同じマップ情報を持つ、空のマップを作成します。
 *	     これが、複製先のマップとなります。
 *	  2. 複製元のマップの各要素のキーと値について、key_copyとval_copy()ヘルパ関数を用いて複製し、
 *	     複製先のマップへ追加します。
 *	  3. 複製先のマップを返します。
 */
MAP* map_duplicate(MAP* map);

/* マップ要素に含まれている、すべてのキーから成る、リストを作成します。
 * [in]
 *	map		マップ。
 * [out]
 *	戻り値		リスト。
 * [note]
 *	* 作成されたリストのヘルパ関数は、作成元のマップのヘルパ関数の一部と同一となります。
 *	  リスト情報のヘルパ関数と、マップのヘルパ関数との対応は、以下のとおりです。
 *		==== 作成元のマップ ====    ==== 作成されたリスト ====
 *		map->map_info.key_copy   → list->list_info.val_copy  
 *		map->map_info.key_delete → list->list_info.val_delete
 *		map->map_info.key_equals → 使いません
 *		map->map_info.val_copy   → 使いません
 *		map->map_info.val_delete → 使いません
 *	* 返されたリストが不要になったら、呼び出し元にてlist_delete()を実行し、リストを削除してください。
 */
struct _LIST* map_keys(MAP* map);

/* マップが空か否か調べます。
 * [in]
 *	map		マップ。
 * [out]
 *	戻り値		空ならば0以外を返します。
 *			空でなければ0を返します。
 */
int map_empty(MAP* map);

/*****************************************************************************
 *	ユーティリティ：リスト (コレクション)
 *****************************************************************************/

/* リスト情報 */
typedef struct _LIST_INFO {
	void* (*val_copy)(void* val);	/* 値を複製する、ヘルパ関数 */
	void  (*val_delete)(void* val);	/* 値を削除する、ヘルパ関数 */
} LIST_INFO;

/* リスト */
typedef struct _LIST {
	LIST_ENTRY list_head;	/* LIST_NODEのリストヘッダ */
	LIST_INFO list_info;	/* リスト情報 */
} LIST;

/* リスト要素
 * * ガベージコレクションを使用可能とするために、リスト要素とリストエントリの先頭アドレスを揃えてあります。
 *   両者のアドレスが違っていると、ガベージコレクタが未開放のリスト要素を誤って開放してしまうためです。
 * - ガベージコレクションの使用は必須ではありません。
 *   LIST構造体やLIST_NODE構造体のメモリ開放は、ライブラリが明示的に行っています。
 *   値のメモリ管理は、アプリケーション定義のヘルパ関数にて、明示的に行うことが可能です。
 * - ガベージコレクションを使うと、明示的な、値のメモリ解放を省略し、ヘルパ関数を簡略化できます。
 */
typedef struct _LIST_NODE {
	LIST_ENTRY list_entry;	/* LIST_NODEのリストエントリ */
	void* val;		/* 値 (実際の型はアプリケーション定義) */
} LIST_NODE;

/* リストを作成します。
 * [in]
 *	list_info	リスト情報。
 * [out]
 *	戻り値		リスト。
 */
LIST* list_create(const LIST_INFO* list_info);

/* リストを削除します。
 * [in]
 *	list		リスト。
 * [note]
 *	* 自動的にlist_clear()を呼び、残っているマップ要素をすべて削除します。
 *	  明示的にlist_clear()を呼んでおく必要はありません。
 */
void list_delete(LIST* list);

/* リストの全要素を削除します。
 * [in]
 *	list		リスト。
 * [note]
 *	* 各リスト要素について、val_delete()ヘルパ関数を用いて、値を削除します。
 */
void list_clear(LIST* list);

/* リストの要素数を取得します。
 * [in]
 *	list		リスト。
 * [out]
 *	戻り値		要素数。
 */
int list_size(LIST* list);

/* インデクスにて指定された位置に、値を格納します。
 * [in]
 *	list		リスト。
 *	index		インデクス。(0～size-1)
 *	val		値。
 * [note]
 *	* インデクスは、有効な位置(0以上、配列サイズ未満)でなければなりません。
 *	  この範囲外のインデクスが指定された場合は、アサートします。
 *	  空のリストに対してこの関数を呼び出した場合は、常にアサートします。
 *	* val_copy()ヘルパ関数を用いて、値を複製し、リスト要素に格納します。
 *	  アプリケーションは、呼び出し時に指定したvalを維持する必要はありません。
 *	  ただし、val_copy()ヘルパ関数が複製を行わない場合は、この限りではありません。
 *	* 指定された位置に存在する既存の値は、自動的に削除されます。
 *	  既存の値の削除には、val_delete()ヘルパ関数が利用されます。
 */
void list_set(LIST* list, int index, void* val);

/* インデクスにて指定された位置の、値を取得します。
 * [in]
 *	list		リスト。
 *	index		インデクス。(0～size-1)
 * [out]
 *	戻り値		値。
 * [note]
 *	* インデクスは、有効な位置(0以上、配列サイズ未満)でなければなりません。
 *	  この範囲外のインデクスが指定された場合は、アサートします。
 *	  空のリストに対してこの関数を呼び出した場合は、常にアサートします。
 *	* list_get()は、val_copy()ヘルパ関数を用いて値の複製を作成し、その複製を返します。
 *	  返された値の所有権は、list_get()を呼び出した側のみに有ります。
 *	  list_get()を呼び出した側は、返された値を適切に解放することを忘れないでください。
 */
void* list_get(LIST* list, int index);

/* リストの末尾に、値を追加します。
 * [in]
 *	list		リスト。
 *	val		値。
 * [note]
 *	* "list_insert(list, list_size(list), val)"と等価です。
 */
void list_add(LIST* list, void* val);

/* インデクスにて指定された位置に、値を追加します。
 * [in]
 *	list		リスト。
 *	index		インデクス。(0～size)
 *	val		値。
 * [note]
 *	* インデクスは、有効な位置(0以上、配列サイズ未満)、または、末尾(=配列サイズ)でなければなりません。
 *	  この範囲外のインデクスが指定された場合は、アサートします。
 *	* val_copy()ヘルパ関数を用いて、値を複製し、リスト要素に格納します。
 *	  アプリケーションは、呼び出し時に指定したvalを維持する必要はありません。
 *	  ただし、val_copy()ヘルパ関数が複製を行わない場合は、この限りではありません。
 *	* インデクスに、配列サイズ未満を指定した場合、追加した位置よりも後の要素は、ひとつづつ、後へ移動します。
 */
void list_insert(LIST* list, int index, void* val);

/* インデクスにて指定された位置の、値を削除します。
 * [in]
 *	list		リスト。
 *	index		インデクス。(0～size-1)
 * [note]
 *	* インデクスは、有効な位置(0以上、配列サイズ未満)でなければなりません。
 *	  この範囲外のインデクスが指定された場合は、アサートします。
 *	  空のリストに対してこの関数を呼び出した場合は、常にアサートします。
 *	* 指定された位置に存在する既存の値は、自動的に削除されます。
 *	  既存の値の削除には、val_delete()ヘルパ関数が利用されます。
 *	* 削除した位置よりも後の要素は、ひとつづつ、前へ移動します。
 */
void list_remove(LIST* list, int index);

/* リストを複製します。
 * [in]
 *	list		複製元のリスト。
 * [out]
 *	戻り値		複製したリスト。
 * [note]
 *	* この関数が行う処理は、以下のとおりです。
 *	  1. 複製元のリストと同じリスト情報を持つ、空のリストを作成します。
 *	     これが、複製先のリストとなります。
 *	  2. 複製元のリストの各要素の値について、val_copy()ヘルパ関数を用いて複製し、
 *	     複製先のリストへ追加します。
 *	  3. 複製先のリストを返します。
 */
LIST* list_duplicate(LIST* list);

/* リストが空か否か調べます。
 * [in]
 *	list		リスト。
 * [out]
 *	戻り値		空ならば0以外を返します。
 *			空でなければ0を返します。
 * [note]
 *	* リストが空か否かを調べるだけならば、
 *		if(!list_size(list)) { 空の場合の処理 } else { 空でない場合の処理 }
 *	  とするよりも、
 *		if(list_empty(list)) { 空の場合の処理 } else { 空でない場合の処理 }
 *	  とする方が高速です。
 */
int list_empty(LIST* list);

/*****************************************************************************
 *	ユーティリティ：プール (コレクション)
 *****************************************************************************/

#if 0 /*{{2006/12/06:pool_free()から返却先プールの引数を不要とする変更により削除*/
///* * Mon Dec 04 16:24:06 JST 2006 Naoyuki Sawa
// * - malloc()、free()のオーバーヘッドを避けるための、メモリブロックプールです。
// *   明示的な、プールの初期化とクリーンアップを行わなくて良いのが特徴です。
// * - 以下のように利用してください。
// *
// * ①POOL構造体を、グローバル変数(またはstatic変数)として定義してください。
// *   定義と同時に、sizeメンバをメモリブロック単位のサイズに初期化してください。
// *
// *	POOL foo_pool = { sizeof(FOO) };
// *
// * ②pool_alloc()を呼び出して、メモリブロックを確保してください。
// *   適切に、ヒープまたはプールからメモリブロックが割り当てられます。
// *   割り当てに失敗した場合は、pool_alloc()内部でアサートするので、戻り値を検査する必要はありません。
// *   返されたメモリブロックは、pool_alloc()によってゼロクリアされています。
// *
// *	int main(int argc, char* argv[]) {
// *		FOO* foo1 = pool_alloc(&foo_pool);
// *
// * ③pool_free()を呼び出して、不要になったメモリブロックをプールに返してください。
// *
// *		pool_free(&foo_pool, foo1);
// *
// * ④最終的な、プールのクリーンアップは不要です。
// *   割り当てたメモリブロックが全てプールに返されたタイミングで、自動的に全てヒープに返されます。
// *
// *		foo1 = pool_alloc(&foo_pool);	// 割り当て数1、プール数0 (ヒープから確保)
// *		foo2 = pool_alloc(&foo_pool);	// 割り当て数2、プール数0 (ヒープから確保)
// *		pool_free(&foo_pool, foo1);	// 割り当て数1、プール数1 (プールへ返す)
// *		foo3 = pool_alloc(&foo_pool);	// 割り当て数2、プール数0 (プールから確保)
// *		pool_free(&foo_pool, foo2);	// 割り当て数1、プール数1 (プールへ返す)
// *		pool_free(&foo_pool, foo3);	// 割り当て数0、プール数2 (プールへ返す)→(ヒープへ返す)→プール数0
// *
// * - 上では構造体FOOだけのためにfoo_poolを用意していますが、複数の構造体で一つのプールを共有することも可能です。
// *   たとえば、構造体FOOとBARで一つのプールを共有する場合、大きい方の構造体サイズをPOOL.sizeに設定してください。
// * - 割り当て数がひんぱんに0に戻るような割り当て/開放パターンの場合、オーバーヘッドが低減されない場合があります。
// *
// *		foo1 = pool_alloc(&foo_pool);	// 割り当て数1、プール数0 (ヒープから確保)
// *		pool_free(&foo_pool, foo1);	// 割り当て数0、プール数1 (プールへ返す)→(ヒープへ返す)→プール数0
// *		foo2 = pool_alloc(&foo_pool);	// 割り当て数1、プール数0 (ヒープから確保)
// *		pool_free(&foo_pool, foo2);	// 割り当て数0、プール数1 (プールへ返す)→(ヒープへ返す)→プール数0
// *		foo3 = pool_alloc(&foo_pool);	// 割り当て数1、プール数0 (ヒープから確保)
// *		pool_free(&foo_pool, foo3);	// 割り当て数0、プール数1 (プールへ返す)→(ヒープへ返す)→プール数0
// *
// * - 4バイト余計に割り当てて先頭に返却先プールへのポインタを格納し、ユーザーには+4の位置を示す方法もあります。
// *   そのようにすれば、pool_free()から返却先プールの引数が不要になり便利なのですが、今回は採用しませんでした。
// *   ユーザーが保持するポインタがメモリブロック先頭を指していないと、ガーベージコレクタと併用できなくなるからです。
// */
//typedef struct _POOL {
//	int size;			/* 割り当てるメモリブロック単位のバイト数 */
//	int cnt;			/* (割り当て回数 - 開放回数) */
//	struct _POOL_NODE* first;	/* プール内の最初のメモリブロックへのリンク (NULL=空) */
//} POOL;
//
//typedef struct _POOL_NODE {
//	struct _POOL_NODE* next;	/* プール内の次のメモリブロックへのリンク (NULL=終端) */
//} POOL_NODE;
//
///* メモリブロックを確保します。
// * [in]
// *	pool		プール。
// * [out]
// *	戻り値		メモリブロック。
// */
//void* pool_alloc(POOL* pool);
//
///* メモリブロックを開放します。
// * [in]
// *	pool		プール。
// *	ptr		メモリブロック。
// */
//void pool_free(POOL* pool, void* ptr);
#endif /*}}2006/12/06:pool_free()から返却先プールの引数を不要とする変更により削除*/
//↓ * Wed Dec 06 03:36:51 JST 2006 Naoyuki Sawa
//↓ - pool_free()から返却先プールの引数を不要としました。
//↓   メモリブロック当り12バイトのオーバーヘッドが増えましたが、使い易さを優先してこのような仕様に変更しました。
//↓ - 割り当て中のメモリブロック先頭をチェインすることで、ガーベージコレクションの対象となることを防いでいます。
//↓   なぜこのような対策が必要かは、上のコメントアウトしたブロック内のコメントの、最後の部分を参照してください。
//↓ - pool_free()から返却先プールの引数を不要としたこと以外は、使用方法は変わっていません。
//↓   上のコメントアウトしたブロック内のコメントを参照してください。

/* * Tue Jan 02 22:11:35 JST 2007 Naoyuki Sawa
 * - プールに、参照カウント式ガーベージコレクションの機能を内包しました。
 * - プールから確保したメモリブロックは、常にプールにチェインにされているため、不要になったブロックを判断できず、通常のGCで回収できません。
 *   そこで、参照カウント式ガーベージコレクションの機能を内包することにしました。
 * - この機能はプールに直接関係のある機能ではなく、単純な確保と解放だけの管理ならば、ガーベージコレクションの仕組みは不要です。
 *   しかし、複数の箇所からメモリブロックを共有するような使い方をする場合、いずれ必要になる機能でもあります。
 *   必要な場合だけ、アプリケーション側で参照カウントの管理を行う方法もありますが、簡単のため、プールの機能に内包してしまうことにしました。
 * - この機能追加によるアプリケーションインターフェイスの変化は、pool_lock()が増えたことだけです。
 *   pool_alloc()直後の参照カウントは1であり、pool_free()すれば0になって解放されるので、既存のアプリケーションへの影響はありません。
 *   メモリブロック毎に4バイトのオーバーヘッド(参照カウントの分)が増えてしまいましたが、まあ、許容範囲だと思います。
 * - NULLポインタに対するpool_lock()とpool_free()は何も行わないようにしました。
 *   従って、あるメモリブロックpの参照カウントを増やす場合に、pがNULLであるか否かを判断する必要はありません。
 *   pがNULLならば、何も行いません。
 *
 *	<例>
 *		void MyClass_constructor(MyClass* This, void* p) {
 *			This->p = p;
 *			pool_lock(This->p); // pがNULLでも大丈夫
 *		}
 *		void MyClass_destructor(MyClass* This) {
 *			pool_free(This->p); // pがNULLでも大丈夫
 *		}
 *
 * - 通常のGCとの併用も可能です。
 *   その場合、malloc()/free()で確保・解放するオブジェクトはマーク&スイープ方式のGC、
 *   pool_alloc()/pool_free()/pool_lock()で確保・解放するオブジェクトは参照カウント式のGC、と、二方式のGCが混在することに注意してください。
 * - 以下に、使用例を示します。
 *
 *	void main() {
 *		void* p;
 *		p = pool_alloc(&pool);	// 参照カウント=1
 *		foo1(p);		// 参照カウント=2
 *		foo2(p);		// 参照カウント=3
 *		pool_free(p);		// 参照カウント=2
 *		bar1(p);		// 参照カウント=1
 *		bar2(p);		// 参照カウント=0 -> 解放
 *	}
 *
 *	void* g_ptr1;
 *	void foo1(void* p) {
 *		g_ptr1 = p;
 *		pool_lock(g_ptr1);	// 参照カウント+1
 *	}
 *	void bar1() {
 *		pool_free(g_ptr1);	// 参照カウント-1
 *		g_ptr1 = NULL;
 *	}
 *
 *	void* g_ptr2;
 *	void foo2(void* p) {
 *		g_ptr2 = p;
 *		pool_lock(g_ptr2);	// 参照カウント+1
 *	}
 *	void bar2() {
 *		pool_free(g_ptr2);	// 参照カウント-1
 *		g_ptr2 = NULL;
 *	}
 *
 */

/* * Sat Mar 14 21:13:42 JST 2009 Naoyuki Sawa
 * - プールに、確保時コールバックと解放時コールバックを追加しました。
 * - 以下に、使用例を示します。
 *
 *	void foo_init_proc(void* data) {
 *		// 確保したメモリブロックの、共通初期化処理など
 *	}
 *	void foo_free_proc(void* data) {
 *		// 解放するメモリブロックの、共通クリーンアップ処理など
 *	}
 *	POOL foo_pool = { sizeof(FOO), foo_init_proc, foo_free_proc };
 *	void main() {
 *		FOO* foo = pool_alloc(&foo_pool);	// foo_init_proc()が呼び出されます。
 *		pool_lock(foo);		// 参照カウント=2
 *		pool_free(foo);		// 参照カウント=1
 *		pool_free(foo);		// 参照カウント=0。foo_free_proc()が呼び出されます。
 *	}
 */

//{{2009/03/14:確保時コールバックと解放時コールバックを追加するために変更
//typedef struct _POOL {
//	int size;		/* このフィールドだけ、ユーザーが設定してください */
//	int init;		/* (内部使用: 初期化済み or 未初期化の判断用) */
//	LIST_ENTRY alloc_list;	/* (内部使用: 割り当て中メモリブロックの先頭をチェインし、GCを防ぐ) */
//	LIST_ENTRY free_list;	/* (内部使用: 解放されたメモリブロックの先頭をチェインして保持する) */
//} POOL;
//↓2009/03/14:確保時コールバックと解放時コールバックを追加するために変更
typedef struct _POOL {
	int size;			/* 割り当てるメモリブロックのバイト数。(ユーザーが設定してください) */
	void (*init)(void* data);	/* 確保時コールバック。(ユーザーが設定してください。不要ならばNULL) */
	void (*free)(void* data);	/* 解放時コールバック。(ユーザーが設定してください。不要ならばNULL) */
	int mark;			/* (内部使用: 初期化済み or 未初期化の判断用) */
	LIST_ENTRY alloc_list;		/* (内部使用: 割り当て中メモリブロックの先頭をチェインし、GCを防ぐ) */
	LIST_ENTRY free_list;		/* (内部使用: 解放されたメモリブロックの先頭をチェインして保持する) */
} POOL;
//}}2009/03/14:確保時コールバックと解放時コールバックを追加するために変更

typedef struct _POOL_NODE {			/* (内部使用) */
	LIST_ENTRY list_entry;			/* POOL.alloc_list、または、POOL.free_listにチェインする */
	POOL* pool;				/* このメモリブロックの割り当て元プールへのポインタ */
	/*{{2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包*/
	int ref_cnt;				/* 参照カウント */
	/*}}2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包*/
	/*unsigned char data[pool->size];*/	/* ユーザーには、この領域の先頭アドレスが返されます */
} POOL_NODE;

/* メモリブロックを確保します。
 * [in]
 *	pool		プール。
 * [out]
 *	戻り値		メモリブロック。
 * [note]
 *	{{2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包
 *	- メモリブロックを確保した直後の、参照カウントの初期値は1です。
 *	}}2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包
 */
void* pool_alloc(POOL* pool);

/* メモリブロックを開放します。
 * [in]
 *	data		メモリブロック。
 *			NULLならば、何も行いません。
 * [note]
 *	{{2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包
 *	- 参照カウントを減らし、参照カウントが残っていたら解放しません。
 *	}}2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包
 */
void pool_free(void* data/*NULLOK*/);

/*{{2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包*/
/* 参照カウントを増やします。
 * [in]
 *	data		メモリブロック。
 *			NULLならば、何も行いません。
 */
void pool_lock(void* data/*NULLOK*/);
/*}}2007/01/02追加: 参照カウント式ガーベージコレクションの機能を内包*/

/*****************************************************************************
 *	ユーティリティ：簡略版COM (Component Object Model)
 *****************************************************************************/

/* 参照カウントの増減ルール (暫定版。※TODO:あとで詳しく書く。)
 *
 *	以下、呼び出す側(A)、呼び出される側(B、C)とする。
 *
 *	[ルール1-1]
 *	Bの戻り値としてインターフェイスを返す場合、Aのために、参照カウントを+1しておく。
 *	Aは、インターフェイスの使用が終わったら、参照カウントを-1する。
 *
 *		INTERFACE** B() {
 *			safe_addref(g_intf);	// refcnt+1
 *			return g_intf;
 *		}
 *
 *		void A() {
 *			INTERFACE** intf = B();
 *			...
 *			safe_release(intf);	// refcnt-1
 *		}
 *
 *	[ルール1-2]
 *	Bがオブジェクト生成関数である場合も、[ルール1-1]に従う。
 *	つまり、Bは参照カウント1のオブジェクトを作成し、そのインターフェイスをAに返す。
 *	Aは、返されたインターフェイスが、新規作成されたものか、既存のものか、判断する必要が無い。
 *
 *		INTERFACE** B() {
 *			OBJECT** obj = calloc(1, OBJECT);
 *			obj->refcnt = 1;		// refcnt=1
 *			obj->interface = &interface;	// VTBL設定
 *			...
 *			return &obj->interface;
 *		}
 *
 *		void A() {
 *			INTERFACE** intf = B();
 *			...
 *			safe_release(intf);		// refcnt-1
 *		}
 *
 *	[ルール2-1]
 *	AがBへの入力引数としてインターフェイスを渡す場合、Aは参照カウントを増減しない。
 *	Bは、インターフェイスの使用が関数内のみならば、参照カウントを増減しない。
 *
 *		void A() {
 *			B(g_intf);
 *		}
 *
 *		void B(INTERFACE** intf) {
 *			...
 *		}
 *
 *	[ルール2-2]
 *	Bが、グローバル変数等にインターフェイスを保持するならば、参照カウントを+1する。
 *	グローバル変数等への保持が終了したら、参照カウントを-1する。
 *
 *		void A() {
 *			B(g_intf);
 *			...
 *			C();
 *		}
 *
 *		void B(INTERFACE** intf) {
 *			g_intf = intf;
 *			safe_addref(g_intf);		// refcnt+1
 *		}
 *
 *		void C(INTERFACE** intf) {
 *			safe_release(g_intf);		// refcnt-1
 *		}
 */

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

/* インターフェイスを定義するためのマクロです。
 * * 簡易UUIDとして、万国標準時1970/1/1 00:00:00からの経過秒数を利用します。
 *   clip/tool/timestmp.exeコマンドを使って、生成できます。
 */
#define DEFINE_INTERFACE(intfname, timestmp, method_list)		\
	enum { intfname##_ID = timestmp };				\
	typedef struct _##intfname intfname;				\
	struct _##intfname {						\
		void* (*query_interface)(intfname** intf, int id);	\
		void  (*addref)(intfname** intf);			\
		void  (*release)(intfname** intf);			\
		method_list						\
	};

/* 基底インターフェイス(UNKNOWN_INTERFACE)を定義します。
 * * method_listが空であるために、DEFINE_INTERFACEマクロが利用できません。
 *   止むを得ず、UNKNOWN_INTERFACEだけは、マクロを使わずに定義しています。
 */
enum { UNKNOWN_INTERFACE_ID = 0/*1970/01/01 09:00:00*/ };
typedef struct _UNKNOWN_INTERFACE UNKNOWN_INTERFACE;
struct _UNKNOWN_INTERFACE {
	void* (*query_interface)(UNKNOWN_INTERFACE** intf, int id);
	void  (*addref)(UNKNOWN_INTERFACE** intf);
	void  (*release)(UNKNOWN_INTERFACE** intf);
};

//----------------------------------------------------------------------------
//				実装例
//----------------------------------------------------------------------------
//	
//	/*----- *.hファイルに記述し、公開する部分 -----*/
//	
//	DEFINE_INTERFACE(SAMPLE_INTERFACE, 1133444760/*2005/12/01 22:46:00*/,
//		void (*put)(SAMPLE_INTERFACE** intf, int value);
//		int  (*get)(SAMPLE_INTERFACE** intf);
//	);
//	
//	SAMPLE_INTERFACE** sample_create(int initial_value);
//	
//	/*----- *.cファイルに記述し、非公開の部分 -----*/
//	
//	static void* sample_query_interface(SAMPLE_INTERFACE** intf, int id);
//	static void sample_addref(SAMPLE_INTERFACE** intf);
//	static void sample_release(SAMPLE_INTERFACE** intf);
//	static void sample_put(SAMPLE_INTERFACE** intf, int value);
//	static int sample_get(SAMPLE_INTERFACE** intf);
//	
//	static SAMPLE_INTERFACE sample_interface = {
//		sample_query_interface,
//		sample_addref,
//		sample_release,
//		sample_put,
//		sample_get,
//	};
//	
//	typedef struct _SAMPLE {
//		SAMPLE_INTERFACE* sample_interface;
//		int refcnt;
//		int value;
//	} SAMPLE;
//	
//	SAMPLE_INTERFACE**
//	sample_create(int initial_value)
//	{
//		SAMPLE* this = calloc(1, sizeof(SAMPLE));
//		if(!this) {
//			DIE();
//		}
//		this->sample_interface = &sample_interface;
//		this->refcnt = 1; /* 作成直後の参照カウントは1 */
//		this->value = initial_value;
//		return &this->sample_interface;
//	}
//	
//	static void
//	sample_delete(SAMPLE* this)
//	{
//		free(this);
//		printf("Delete!\n");
//	}
//	
//	static void*
//	sample_query_interface(SAMPLE_INTERFACE** intf, int id)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample_interface);
//		UNKNOWN_INTERFACE** unknown;
//		switch(id) {
//		case UNKNOWN_INTERFACE_ID:
//		case SAMPLE_INTERFACE_ID:
//			unknown = (void*)&this->sample_interface;
//			this->refcnt++; /* query_interface()が成功したら参照カウントを+1 */
//			break;
//		default:
//			unknown = NULL;
//			break;
//		}
//		return unknown;
//	}
//	
//	static void
//	sample_addref(SAMPLE_INTERFACE** intf)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample_interface);
//		this->refcnt++;
//	}
//	
//	static void
//	sample_release(SAMPLE_INTERFACE** intf)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample_interface);
//		if(!--this->refcnt) {
//			sample_delete(this);
//		}
//	}
//	
//	static void
//	sample_put(SAMPLE_INTERFACE** intf, int value)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample_interface);
//		this->value = value;
//	}
//	
//	static int
//	sample_get(SAMPLE_INTERFACE** intf)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample_interface);
//		return this->value;
//	}
//	
//	/*----- テストプログラム -----*/
//	
//	void
//	test_main()
//	{
//		SAMPLE_INTERFACE** sample = sample_create(123);
//		printf("%d\n", (*sample)->get(sample));	/* "123"と表示されます */
//		(*sample)->put(sample, 456);
//		printf("%d\n", (*sample)->get(sample));	/* "456"と表示されます */
//		(*sample)->release(sample);		/* "Delete!"と表示されます */
//	}
//	
//----------------------------------------------------------------------------

/* * オブジェクト初期化と、query_interface()の実装を簡単にする、ヘルパ関数のための構造体です。
 *   インターフェイスを実装するクラス毎に、あらかじめINTERFACE_MAPの配列を定義しておけば、
 *   オブジェクト初期化とquery_interface()の処理の大部分を、ヘルパ関数に任せられます。
 * * インターフェイスマップは、INTERFACE_MAP.id=0の要素で終端します。
 *   インターフェイスID=0は、実際にはUNKNOWN_INTERFACE_IDに相当するのですが、
 *   INTERFACE_MAPの配列においては、UNKNOWN_INTERFACE_IDでなく、単なる終端マークと見なします。
 * * インターフェイスマップには、UNKNOWN_INTERFACEに相当する要素は含めません。
 *   その代りに、先頭のインターフェイスが「暗黙のUNKNOWN_INTERFACE」として扱われます。
 *   UNKNOWN_INTERFACE_IDを指定して、query_interface_map()を呼び出した場合、
 *   query_interface_map()は、インターフェイスマップの先頭の要素のインターフェイスを、
 *   「暗黙のUNKNOWN_INTERFACE」として、呼び出し元に返します。
 * * 上述のように、先頭のインターフェイスを固定的に「暗黙のUNKNOWN_INTERFACE」とするために、
 *   インターフェイスマップには、少なくとも一つ以上の有効な要素が必要です。
 *   すなわち、インターフェイスマップの先頭の要素が、id=0であってはいけません。
 *   言い換えると、INTERFACE_MAPを利用してインターフェイスを管理するオブジェクトは、
 *   UNKNOWN_INTERFACE以外に、一つ以上のインターフェイスを持っている必要があります。
 */
typedef struct _INTERFACE_MAP {
	int id;		/* インターフェイスID (id=0にて終端。終端要素のoffset,vtblは無意味) */
	int offset;	/* オブジェクトの先頭から、インターフェイスまでのオフセットバイト数 */
	void* vtbl;	/* インターフェイスVTBLのポインタ (apply_interface_map()だけが参照) */
} INTERFACE_MAP;

/* オブジェクト作成時に、インターフェイスを格納する、ヘルパ関数です。
 * [in]
 *	this		オブジェクトの先頭アドレス。
 *	map		インターフェイスマップ。
 *			INTERFACE_MAP.id=0の要素で、明示的に配列を終端してください。
 * [note]
 *	* query_interface_map()のコメントと、後述の利用例を参照してください。
 */
void apply_interface_map(void* this, const INTERFACE_MAP* map);

/* インターフェイスマップを検索する、ヘルパ関数です。
 * [in]
 *	this		オブジェクトの先頭アドレス。
 *	id		検索するインターフェイスID。
 *	map		インターフェイスマップ。
 *			INTERFACE_MAP.id=0の要素で、明示的に配列を終端してください。
 * [out]
 *	戻り値		成功ならば、参照カウントを+1し、インターフェイスを返します。
 *			失敗ならば、参照カウントを変更せず、NULLを返します。
 * [note]
 *	* インターフェイスマップに、UNKNOWN_INTERFACEに対応する要素を含めてはいけません。
 *	  id=UNKNOWN_INTERFACE_IDが指定された場合、最初の要素のインターフェイスを返します。
 *	  すなわち、インターフェイスマップの最初の要素が「代表UNKNOWN_INTERFACE」になります。
 */
void* query_interface_map(void* this, int id, const INTERFACE_MAP* map);

//----------------------------------------------------------------------------
//				利用例
//----------------------------------------------------------------------------
//	
//	typedef struct _SAMPLE {
//		int refcnt;
//		SAMPLE1_INTERFACE* sample1_interface;
//		SAMPLE2_INTERFACE* sample2_interface;
//		SAMPLE3_INTERFACE* sample3_interface;
//		int value;
//	} SAMPLE;
//	
//	SAMPLE1_INTERFACE sample1_interface = { ... };
//	SAMPLE2_INTERFACE sample2_interface = { ... };
//	SAMPLE3_INTERFACE sample3_interface = { ... };
//	
//	static const INTERFACE_MAP sample_interface_map[] = {
//		{ SAMPLE1_INTERFACE_ID, FIELD_OFFSET(SAMPLE, sample1_interface), &sample1_interface },
//		{ SAMPLE2_INTERFACE_ID, FIELD_OFFSET(SAMPLE, sample2_interface), &sample2_interface },
//		{ SAMPLE3_INTERFACE_ID, FIELD_OFFSET(SAMPLE, sample3_interface), &sample3_interface },
//		{ 0 } /* インターフェイスマップの終端。忘れないで!! */
//	};
//	
//	SAMPLE*
//	sample_create()
//	{
//		SAMPLE* this = calloc(1, sizeof(SAMPLE));
//		if(!this) {
//			DIE();
//		}
//		this->refcnt = 1;
//		apply_interface_map(this, sample_interface_map);
//		return this;
//	}
//	
//	static void*
//	sample1_query_interface(SAMPLE1_INTERFACE** intf, int id)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample1_interface);
//		return query_interface_map(this, id, sample_interface_map);
//	}
//	
//	static void*
//	sample2_query_interface(SAMPLE2_INTERFACE** intf, int id)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample2_interface);
//		return query_interface_map(this, id, sample_interface_map);
//	}
//	
//	static void*
//	sample3_query_interface(SAMPLE3_INTERFACE** intf, int id)
//	{
//		SAMPLE* this = CONTAINING_RECORD(intf, SAMPLE, sample3_interface);
//		return query_interface_map(this, id, sample_interface_map);
//	}
//	
//----------------------------------------------------------------------------

/* インターフェイスポインタの参照カウントを、増加します。
 * インターフェイスポインタがNULLだったら、何もしません。
 */
//#define safe_addref(ptr) do {		\
//	if(ptr) {			\
//		(*(ptr))->addref(ptr);	\
//	}				\
//} while(0)
//↓2005/12/10 safe_addref(ptr)が、ptrを返すように変更しました。
//↓このような仕様とした理由は、safe_addref(ptr)の後、直ちにptrを返す関数のためです。
//↓上述の、参照カウントの増減ルール[ルール1-1]を参照してください。
//↓これまでは、
//↓	safe_addref(ptr);
//↓	return ptr;
//↓と記述していた処理を、今後は、
//↓	return safe_addref(ptr);
//↓と記述することができるようになりました。
#define safe_addref(ptr) ((ptr) ? ((*(ptr))->addref(ptr), (ptr)) : (ptr))

/* インターフェイスポインタの参照カウントを減少後、NULLにします。
 * インターフェイスポインタがもともとNULLだったら、何もしません。
 */
#define safe_release(ptr) do {		\
	if(ptr) {			\
		(*(ptr))->release(ptr);	\
		(ptr) = NULL;		\
	}				\
} while(0)

/* インターフェイスポインタに、新しいインターフェイスをアサインします。
 * - dstとsrcが、同じオブジェクトを指している可能性があるので、
 *   新しくアサインするインターフェイスの参照カウントを増加した後、
 *   既存インターフェイスの参照カウントを減少することに注意してください。
 *   この手順を逆順にすると、途中でオブジェクトが削除されてしまいます。
 * - <使用例>
 *	SAMPLE_INTERFACE** sample1 = sample_create(123); // sample(123)'s refcnt=1
 *	SAMPLE_INTERFACE** sample2 = sample_create(456); // sample(456)'s refcnt=1
 *	safe_assign(sample1, sample2); // sample(123)'s refcnt=0, sample(456)'s refcnt=2
 */
#define safe_assign(dst, src) do {			\
	UNKNOWN_INTERFACE** __tmp__ = (void*)(dst);	\
	(dst) = (src);					\
	safe_addref(dst);				\
	safe_release(__tmp__);				\
} while(0)

/* インターフェイスポインタに、新しいインターフェイスをアタッチします。
 * - 新しくアサインするインターフェイスを得る式(src)の中に、(dst)が含まれている可能性があるので、
 *   式(src)を評価した後に、(dst)の参照カウントを減少することに注意してください。
 *   この手順を逆順にすると、途中でオブジェクトが削除されてしまいます。
 *	<例> safe_attach(sample, (*sample)->clone(sample));
 * - safe_assign()との違いは、新しいインターフェイスの参照カウントを増加しないことです。
 * - <使用例>
 *	SAMPLE_INTERFACE** sample = sample_create(123); // sample(123)'s refcnt=1
 *	safe_attach(sample, sample_create(234)); // sample(123)'s refcnt=0, sample(456)'s refcnt=1
 */
#define safe_attach(dst, src) do {			\
	UNKNOWN_INTERFACE** __tmp__ = (void*)(dst);	\
	(dst) = (src);					\
	safe_release(__tmp__);				\
} while(0)

/* インターフェイスを取り出し、インターフェイスポインタをクリアします。
 * - 参照カウントの増加、減少は伴いません。
 * - P/ECEでは、GCC拡張機能を利用して、マクロのみで定義しています。
 *   Win32では、GCC拡張機能が利用できないため、マクロとインライン関数で定義しています。
 *   Win32では、やむを得ず(void*)へのキャストを行うため、型チェックが少し甘くなります。
 * - <使用例>
 *	SAMPLE_INTERFACE** sample = sample_create(123); // sample(123)'s refcnt=1
 *	return safe_detach(sample); // sample(123)'s refcnt=1
 *   上述の使用例は、safe_detach()を使わず、単純に、
 *	return sample_create(123);
 *   と変更する方法でも、同じ結果が得られます。
 */
#ifdef PIECE
#define safe_detach(ptr) ({			\
	typeof(ptr) __tmp__ = (ptr);		\
	(ptr) = NULL;				\
	__tmp__;				\
})
#else /*PIECE*/
#define safe_detach(ptr) _safe_detach(&(ptr))
static __inline void* _safe_detach(void* _pptr) {
	UNKNOWN_INTERFACE*** pptr = _pptr;
	UNKNOWN_INTERFACE**   ptr = *pptr;
	*pptr = NULL;
	return ptr;
}
#endif /*PIECE*/

/* 安全なquery_interface()呼び出しを行います。
 * - インターフェイスポインタがNULLでなければ、query_interface()を呼び出し、戻り値を適切にキャストします。
 *   インターフェイスポインタがNULLならば、query_interface()を呼び出さずに、NULLを返します。
 * - P/ECE版は、GCC拡張機能を利用し、引数ptrを複数回評価しない、安全な実装となっています。
 *   Win32版は、GCC拡張機能が利用できないため、やむを得ず、引数ptrを複数回評価しています。
 *   引数ptrに、関数呼び出しを含む式や、副作用のある式を指定しないよう、注意してください。
 * - <使用例>
 *	SAMPLE_INTERFACE** sample = safe_query_interface(unknown, SAMPLE_INTERFACE);
 */
#ifdef PIECE
#define safe_query_interface(ptr, intfname) ((intfname**)({			\
	typeof(ptr) __tmp__ = (ptr);						\
	(__tmp__) ? (*(__tmp__))->query_interface((__tmp__), intfname##_ID)	\
	      : NULL;								\
}))
#else /*PIECE*/
#define safe_query_interface(ptr, intfname) ((intfname**)(	\
	(ptr) ? (*(ptr))->query_interface((ptr), intfname##_ID)	\
	      : NULL						\
))
#endif /*PIECE*/

/* safe_query_interface()とsafe_attach()は、同時に使うケースが多いので、簡略表記を用意しました。
 * 以下のコード:
 *	SAMPLE1_INTERFACE** sample1 = ...;
 *	SAMPLE2_INTERFACE** sample2 = ...;
 *	safe_attach(sample2, safe_query_interface(sample1, SAMPLE2_INTERFACE));
 * を、次のように記述できます。
 *	SAMPLE1_INTERFACE** sample1 = ...;
 *	SAMPLE2_INTERFACE** sample2 = ...;
 *	safe_assign_interface(sample2, sample1, SAMPLE2);
 * safe_attach_interface()ではなく、safe_assign_interface()というマクロ名にした理由は、
 * オブジェクトの参照カウント数の合計が、新たに1増えることを強調するためです。
 */
#define safe_assign_interface(dst_ptr, src_ptr, dst_intfname)			\
	safe_attach((dst_ptr), safe_query_interface((src_ptr), dst_intfname))

/* 二つのインターフェイスポインタが、同じオブジェクトに属するものか否か、調べます。
 * 同じオブジェクトに属するものならば1、さもなくば0を返します。
 * - 以下のいずれか条件に一致する場合、同じオブジェクトに属すると判断します。
 *	①intf1とintf2が、いずれもNULLの場合。
 *	②intf1とintf2に対し、明示的にUNKNOWN_INTERFACEを要求し、それらが一致した場合。
 * - P/ECEでは、GCC拡張機能を利用して、マクロのみで定義しています。
 *   Win32では、GCC拡張機能が利用できないため、マクロとインライン関数で定義しています。
 *   Win32では、やむを得ず(void*)へのキャストを行うため、型チェックが少し甘くなります。
 * - .NET Frameworkの、Object.ReferenceEqualsメソッドから、名前を借りました。
 */
#ifdef PIECE
#define reference_equals(intf1, intf2) ({						\
	UNKNOWN_INTERFACE** unk1 = safe_query_interface((intf1), UNKNOWN_INTERFACE);	\
	UNKNOWN_INTERFACE** unk2 = safe_query_interface((intf2), UNKNOWN_INTERFACE);	\
	if(unk1) (*unk1)->release(unk1);						\
	if(unk2) (*unk2)->release(unk2);						\
	unk1 == unk2;									\
})
#else /*PIECE*/
#define reference_equals(intf1, intf2) _reference_equals((void*)(intf1), (void*)(intf2))
static __inline int _reference_equals(UNKNOWN_INTERFACE** intf1, UNKNOWN_INTERFACE** intf2) {
	UNKNOWN_INTERFACE** unk1 = safe_query_interface((intf1), UNKNOWN_INTERFACE);
	UNKNOWN_INTERFACE** unk2 = safe_query_interface((intf2), UNKNOWN_INTERFACE);
	if(unk1) (*unk1)->release(unk1);
	if(unk2) (*unk2)->release(unk2);
	return unk1 == unk2;
}
#endif /*PIECE*/

/*****************************************************************************
 *	ユーティリティ：ファイルパック形式
 *****************************************************************************/

/*                           0 +-----------------------------+
 *                             | FILE_PAC_INFO               |
 *                             +-----------------------------+
 *                             | FILE_INFO[0]                |
 *                             +-----------------------------+
 *                             | FILE_INFO[1]                |
 *                             +-----------------------------+
 *                             =                             =
 *                             +-----------------------------+
 *                             | FILE_INFO[famount-1]        |
 *         FILE_INFO[0].offset +-----------------------------+－
 *                             |                             |↑
 *                             | ファイル[0]のデータ         |｜FILE_INFO[0].size + 3 & ~3
 *                             |                             |↓
 *         FILE_INFO[1].offset +-----------------------------+－
 *                             |                             |↑
 *                             | ファイル[1]のデータ         |｜FILE_INFO[1].size + 3 & ~3
 *                             |                             |↓
 *                             +-----------------------------+－
 *                             =                             =
 * FILE_INFO[famount-1].offset +-----------------------------+－
 *                             |                             |↑
 *                             | ファイル[famount-1]のデータ |｜FILE_INFO[famount-1].size
 *                             |                             |↓
 *                             +-----------------------------+－
 */
#define FILE_PAC_INFO_HEAD	 ('F' << 24 | 'P' << 16 | 'A' << 8 | 'K')
typedef struct _FILE_PAC_INFO {	/* ファイルパック情報                   */
	unsigned long head;	/* シグネチャ('FPAK'固定。並びは"KAPF") */
	long famount;		/* ファイル数                           */
} FILE_PAC_INFO;
typedef struct _FILE_INFO {	/* ファイル情報                         */
	char fname[16];		/* ファイル名                           */
	unsigned long offset;	/* オフセット(fpkファイル先頭を0とする) */
	unsigned long size;	/* ファイルサイズ                       */
} FILE_INFO;

/* fpkファイル内のファイルサイズを取得します。
 * [in]
 *	fname		fpkファイル名。
 *	name		ファイルエントリ名。
 * [out]
 *	戻り値		ファイルサイズ[バイト]。
 * [note]
 *	* ファイルエントリ名は、大文字小文字を区別せずに比較します。
 *	* ファイルエントリが見つからなかった場合は、アサートします。
 */
int fpk_size(const char* fname, const char* name);

/* fpkファイル内のファイルを読み込みます。
 * [in]
 *	fname		fpkファイル名。
 *	name		ファイルエントリ名。
 *	buffer		バッファアドレス。
 *	buflen		バッファサイズ。
 * [out]
 *	戻り値		実際に読み込んだファイルサイズ[バイト]。
 * [note]
 *	* ファイルエントリ名は、大文字小文字を区別せずに比較します。
 *	* ファイルエントリが見つからなかった場合は、アサートします。
 *	* バッファサイズがファイルサイズ未満の場合は、アサートします。
 */
int fpk_load(const char* fname, const char* name, void* buffer, int buflen);

/*****************************************************************************
 *	ユーティリティ：オンメモリファイルパック形式
 *****************************************************************************/

/* オンメモリfpk内のファイル先頭アドレスを取得します。
 * [in]
 *	fpk		オンメモリfpkの先頭アドレス。
 *	name		ファイルエントリ名。
 *	size		ファイルサイズを格納する変数へのポインタ。
 *			NULLを指定するとファイルサイズは格納されません。
 * [out]
 *	戻り値		実際に読み込んだファイルサイズ[バイト]。
 * [note]
 *	* ファイルエントリ名は、大文字小文字を区別せずに比較します。
 *	* ファイルエントリが見つからなかった場合は、アサートします。
 */
const void* fpk_address(const void* fpk, const char* name, int* size);

#endif /*__CLIP_MISC_H__*/
