/*	
 *	clipintf.c
 *
 *	インターフェイス
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2016 Naoyuki Sawa
 *
 *	* Mon Dec 26 01:25:00 JST 2005 Naoyuki Sawa
 *	- 新規作成。
 *	  コードサイズ節約のために、実装をclipmisc.cからclipintf.cへ分離しました。
 *	* Sat Apr 30 21:45:42 JST 2016 Naoyuki Sawa
 *	- 変数名を'this'⇒'This'に変更しました。
 *	  VC++6.0ではCソースのコンパイルでも変数名にthisは使えないようだからです。(GCCならばokなのですが…)
 *	  この変更により、当モジュールもVC++6.0でコンパイル出来るようになり、libclipに含めました。
 *	  詳細は、/clip/libclip/extclip.h の同日のコメントを参照して下さい。
 *	* Sun Sep 04 21:41:17 JST 2016 Naoyuki Sawa
 *	- apply_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。
 *	  query_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。
 *	  64ビット対応のための準備ですが、32ビットでも(char*)で行う方が本当は正しいからです。
 *	  とは言え、32ビットではどちらでも同じ結果になるので、既存の32ビットコードには影響有りません。
 */
#include "clip.h"

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

void
apply_interface_map(void* This, const INTERFACE_MAP* map)
{
	UNKNOWN_INTERFACE* unknown;

	/* 暗黙のUNKNOWN_INTERFACE以外に、一つ以上のインターフェイスが必要。 */
	if(!map->id) {
		DIE();
	}

	/* インターフェイスマップの各インターフェイスについて... */
	do {

		/* 念のため、INTERFACE_MAP.vtblの設定忘れを検査します。 */
		unknown = map->vtbl;
		if(!unknown) {
			DIE();
		}

		/* オブジェクトに、インターフェイスを格納します。 */
//{{2016/09/04変更:apply_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。
//		*(UNKNOWN_INTERFACE**)((int)This + map->offset) = unknown;
//↓2016/09/04変更:apply_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。
		*(UNKNOWN_INTERFACE**)((char*)This + map->offset) = unknown;
//}}2016/09/04変更:apply_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。

		/* インターフェイスマップの、次の要素へ進みます。 */
		map++;

	} while(map->id); /* id=0で終端 */
}

void*
query_interface_map(void* This, int id, const INTERFACE_MAP* map)
{
	UNKNOWN_INTERFACE** unknown;

	/* 暗黙のUNKNOWN_INTERFACE以外に、一つ以上のインターフェイスが必要。 */
	if(!map->id) {
		DIE();
	}

	/* インターフェイスマップを走査して... */
	do {

		/* 現在の要素のインターフェイスIDが、指定されたIDに一致するか、
		 * または、指定されたIDが、UNKNOWN_INTERFACE_IDだったならば...
		 * (UNKNOWN_INTERFACE_IDが指定されたら、最初の要素にHITします)
		 */
		if((map->id == id) || id == UNKNOWN_INTERFACE_ID) {

			/* インターフェイスポインタを決定します。 */
//{{2016/09/04変更:query_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。
//			unknown = (UNKNOWN_INTERFACE**)((int)This + map->offset);
//↓2016/09/04変更:query_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。
			unknown = (UNKNOWN_INTERFACE**)((char*)This + map->offset);
//}}2016/09/04変更:query_interface_map()が、(int)でアドレス演算を行っていたのを、(char*)で行うように修正しました。

			/* 参照カウントを増やします。(QueryInterfaceの仕様) */
			(*unknown)->addref(unknown);

			/* インターフェイスポインタを返します。 */
			return unknown;
		}

		/* インターフェイスマップの、次の要素へ進みます。 */
		map++;

	} while(map->id); /* id=0で終端 */

	return NULL; /* 見つからなかった */
}
