/*	
 *	clipintf.c
 *
 *	インターフェイス
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2005 Naoyuki Sawa
 *
 *	* Mon Dec 26 01:25:00 JST 2005 Naoyuki Sawa
 *	- 新規作成。
 *	  コードサイズ節約のために、実装をclipmisc.cからclipintf.cへ分離しました。
 */
#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();
		}

		/* オブジェクトに、インターフェイスを格納します。 */
		*(UNKNOWN_INTERFACE**)((int)this + map->offset) = unknown;

		/* インターフェイスマップの、次の要素へ進みます。 */
		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) {

			/* インターフェイスポインタを決定します。 */
			unknown = (UNKNOWN_INTERFACE**)((int)this + map->offset);

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

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

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

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

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