core/logic/ShareSys.cpp
author David Anderson <dvander@alliedmods.net>
Fri Aug 30 10:10:57 2013 -0700 (2013-08-30)
changeset 4106 a39557bde4ac
parent 4067 cc438da4a30c
child 4108 dabaea5ab45c
permissions -rw-r--r--
Remove native override API (bug 5852 part 1, r=ds).
dvander@370
     1
/**
dvander@4067
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
dvander@229
    32
#include "ShareSys.h"
dvander@3872
    33
#include "ExtensionSys.h"
dvander@3872
    34
#include <ILibrarySys.h>
dvander@3872
    35
#include "common_logic.h"
dvander@3872
    36
#include "PluginSys.h"
dvander@229
    37
#include "HandleSys.h"
dvander@4106
    38
#include <assert.h>
dvander@229
    39
dvander@229
    40
ShareSystem g_ShareSys;
dvander@2086
    41
static unsigned int g_mark_serial = 0;
dvander@229
    42
dvander@229
    43
ShareSystem::ShareSystem()
dvander@229
    44
{
dvander@229
    45
	m_IdentRoot.ident = 0;
dvander@229
    46
	m_TypeRoot = 0;
dvander@229
    47
	m_IfaceType = 0;
dvander@229
    48
	m_CoreType = 0;
dvander@229
    49
}
dvander@229
    50
dvander@229
    51
IdentityToken_t *ShareSystem::CreateCoreIdentity()
dvander@229
    52
{
dvander@229
    53
	if (!m_CoreType)
dvander@229
    54
	{
dvander@229
    55
		m_CoreType = CreateIdentType("CORE");
dvander@229
    56
	}
dvander@229
    57
dvander@868
    58
	return CreateIdentity(m_CoreType, this);
dvander@229
    59
}
dvander@229
    60
dvander@1770
    61
void ShareSystem::Initialize()
dvander@229
    62
{
dvander@262
    63
	TypeAccess sec;
dvander@229
    64
dvander@3872
    65
	handlesys->InitAccessDefaults(&sec, NULL);
dvander@262
    66
	sec.ident = GetIdentRoot();
dvander@262
    67
dvander@3872
    68
	m_TypeRoot = handlesys->CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
dvander@3872
    69
	m_IfaceType = handlesys->CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
dvander@229
    70
dvander@229
    71
	/* Initialize our static identity handle */
dvander@3872
    72
	m_IdentRoot.ident = handlesys->CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
dvander@305
    73
dvander@336
    74
	/* Add the Handle System and others... they are too innocent and pure to do it themselves */
dvander@3872
    75
	AddInterface(NULL, handlesys);
dvander@3872
    76
	AddInterface(NULL, libsys);
dvander@229
    77
}
dvander@229
    78
dvander@229
    79
void ShareSystem::OnSourceModShutdown()
dvander@229
    80
{
dvander@229
    81
	if (m_CoreType)
dvander@229
    82
	{
dvander@3872
    83
		handlesys->RemoveType(m_CoreType, GetIdentRoot());
dvander@229
    84
	}
dvander@229
    85
dvander@3872
    86
	handlesys->RemoveType(m_IfaceType, GetIdentRoot());
dvander@3872
    87
	handlesys->RemoveType(m_TypeRoot, GetIdentRoot());
dvander@229
    88
}
dvander@229
    89
dvander@229
    90
IdentityType_t ShareSystem::FindIdentType(const char *name)
dvander@229
    91
{
dvander@229
    92
	HandleType_t type;
dvander@229
    93
dvander@3872
    94
	if (handlesys->FindHandleType(name, &type))
dvander@229
    95
	{
dvander@229
    96
		if (g_HandleSys.TypeCheck(type, m_TypeRoot))
dvander@229
    97
		{
dvander@229
    98
			return type;
dvander@229
    99
		}
dvander@229
   100
	}
dvander@229
   101
dvander@229
   102
	return 0;
dvander@229
   103
}
dvander@229
   104
dvander@229
   105
IdentityType_t ShareSystem::CreateIdentType(const char *name)
dvander@229
   106
{
dvander@229
   107
	if (!m_TypeRoot)
dvander@229
   108
	{
dvander@229
   109
		return 0;
dvander@229
   110
	}
dvander@229
   111
dvander@3872
   112
	return handlesys->CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
dvander@229
   113
}
dvander@229
   114
dvander@229
   115
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
dvander@229
   116
{
dvander@283
   117
	/* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */
dvander@229
   118
}
dvander@229
   119
dvander@868
   120
IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type, void *ptr)
dvander@229
   121
{
dvander@229
   122
	if (!m_TypeRoot)
dvander@229
   123
	{
dvander@229
   124
		return 0;
dvander@229
   125
	}
dvander@229
   126
dvander@229
   127
	/* :TODO: Cache? */
dvander@229
   128
	IdentityToken_t *pToken = new IdentityToken_t;
dvander@528
   129
dvander@528
   130
	HandleSecurity sec;
dvander@528
   131
	sec.pOwner = sec.pIdentity = GetIdentRoot();
dvander@528
   132
dvander@528
   133
	pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true);
dvander@868
   134
	pToken->ptr = ptr;
dvander@868
   135
	pToken->type = type;
dvander@229
   136
dvander@229
   137
	return pToken;
dvander@229
   138
}
dvander@229
   139
dvander@304
   140
bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
dvander@229
   141
{
dvander@229
   142
	if (!iface)
dvander@229
   143
	{
dvander@229
   144
		return false;
dvander@229
   145
	}
dvander@229
   146
dvander@229
   147
	IfaceInfo info;
dvander@229
   148
dvander@304
   149
	info.owner = myself;
dvander@229
   150
	info.iface = iface;
dvander@229
   151
	
dvander@229
   152
	m_Interfaces.push_back(info);
dvander@229
   153
dvander@229
   154
	return true;
dvander@229
   155
}
dvander@229
   156
dvander@229
   157
bool ShareSystem::RequestInterface(const char *iface_name, 
dvander@229
   158
								   unsigned int iface_vers, 
dvander@311
   159
								   IExtension *myself, 
dvander@229
   160
								   SMInterface **pIface)
dvander@229
   161
{
dvander@229
   162
	/* See if the interface exists */
dvander@229
   163
	List<IfaceInfo>::iterator iter;
dvander@229
   164
	SMInterface *iface;
dvander@304
   165
	IExtension *iface_owner;
dvander@229
   166
	bool found = false;
dvander@229
   167
	for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
dvander@229
   168
	{
dvander@229
   169
		IfaceInfo &info = (*iter);
dvander@229
   170
		iface = info.iface;
dvander@229
   171
		if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
dvander@229
   172
		{
dvander@229
   173
			if (iface->GetInterfaceVersion() == iface_vers
dvander@229
   174
				|| iface->IsVersionCompatible(iface_vers))
dvander@229
   175
			{
dvander@304
   176
				iface_owner = info.owner;
dvander@229
   177
				found = true;
dvander@229
   178
				break;
dvander@229
   179
			}
dvander@229
   180
		}
dvander@229
   181
	}
dvander@229
   182
dvander@229
   183
	if (!found)
dvander@229
   184
	{
dvander@229
   185
		return false;
dvander@229
   186
	}
dvander@229
   187
dvander@304
   188
	/* Add a dependency node */
dvander@229
   189
	if (iface_owner)
dvander@229
   190
	{
dvander@304
   191
		IfaceInfo info;
dvander@304
   192
		info.iface = iface;
dvander@304
   193
		info.owner = iface_owner;
dvander@311
   194
		g_Extensions.BindDependency(myself, &info);
dvander@229
   195
	}
dvander@229
   196
dvander@304
   197
	if (pIface)
dvander@304
   198
	{
dvander@304
   199
		*pIface = iface;
dvander@304
   200
	}
dvander@229
   201
dvander@304
   202
	return true;
dvander@229
   203
}
dvander@229
   204
dvander@312
   205
void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives)
dvander@229
   206
{
dvander@2086
   207
	CNativeOwner *pOwner;
dvander@2086
   208
dvander@2086
   209
	pOwner = g_Extensions.GetNativeOwner(myself);
dvander@2086
   210
dvander@2086
   211
	pOwner->AddNatives(natives);
dvander@229
   212
}
dvander@229
   213
dvander@229
   214
void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
dvander@229
   215
{
dvander@262
   216
	HandleSecurity sec;
dvander@262
   217
dvander@262
   218
	sec.pOwner = GetIdentRoot();
dvander@262
   219
	sec.pIdentity = GetIdentRoot();
dvander@262
   220
dvander@3872
   221
	handlesys->FreeHandle(identity->ident, &sec);
dvander@229
   222
	delete identity;
dvander@229
   223
}
dvander@229
   224
dvander@229
   225
void ShareSystem::DestroyIdentType(IdentityType_t type)
dvander@229
   226
{
dvander@3872
   227
	handlesys->RemoveType(type, GetIdentRoot());
dvander@229
   228
}
dvander@229
   229
dvander@304
   230
void ShareSystem::RemoveInterfaces(IExtension *pExtension)
dvander@304
   231
{
dvander@304
   232
	List<IfaceInfo>::iterator iter = m_Interfaces.begin();
dvander@304
   233
dvander@304
   234
	while (iter != m_Interfaces.end())
dvander@304
   235
	{
dvander@304
   236
		if ((*iter).owner == pExtension)
dvander@304
   237
		{
dvander@304
   238
			iter = m_Interfaces.erase(iter);
dvander@2086
   239
		}
dvander@2086
   240
		else
dvander@2086
   241
		{
dvander@304
   242
			iter++;
dvander@304
   243
		}
dvander@304
   244
	}
dvander@304
   245
}
dvander@324
   246
dvander@324
   247
void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool require, bool autoload)
dvander@324
   248
{
dvander@324
   249
	g_Extensions.AddDependency(myself, filename, require, autoload);
dvander@324
   250
}
dvander@324
   251
dvander@1572
   252
void ShareSystem::RegisterLibrary(IExtension *myself, const char *name)
dvander@1572
   253
{
dvander@1572
   254
	g_Extensions.AddLibrary(myself, name);
dvander@1572
   255
}
dvander@1689
   256
dvander@1689
   257
void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
dvander@1689
   258
{
dvander@4106
   259
	assert(false);
dvander@2086
   260
}
dvander@2086
   261
dvander@2086
   262
NativeEntry *ShareSystem::FindNative(const char *name)
dvander@2086
   263
{
dvander@4067
   264
	NativeEntry *entry;
dvander@4067
   265
	if (!m_NtvCache.retrieve(name, &entry))
dvander@2086
   266
		return NULL;
dvander@4067
   267
	return entry;
dvander@2086
   268
}
dvander@2086
   269
dvander@2086
   270
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
dvander@2086
   271
{
dvander@2086
   272
	sp_native_t *native;
dvander@2086
   273
	uint32_t i, native_count;
dvander@2086
   274
	IPluginContext *pContext;
dvander@2086
   275
dvander@2086
   276
	pContext = pPlugin->GetBaseContext();
dvander@2086
   277
dvander@2086
   278
	/* Generate a new serial ID, mark our dependencies with it. */
dvander@2086
   279
	g_mark_serial++;
dvander@3872
   280
	pPlugin->PropagateMarkSerial(g_mark_serial);
dvander@2086
   281
dvander@2086
   282
	native_count = pContext->GetNativesNum();
dvander@2086
   283
	for (i = 0; i < native_count; i++)
dvander@2086
   284
	{
dvander@2086
   285
		if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
dvander@2086
   286
			continue;
dvander@2086
   287
dvander@4106
   288
		// If we're already bound, no need to do anything else.
dvander@2086
   289
		if (native->status == SP_NATIVE_BOUND)
dvander@4106
   290
			continue;
dvander@4106
   291
dvander@2086
   292
		/* Otherwise, the native must be in our cache. */
dvander@4106
   293
		NativeEntry *pEntry = FindNative(native->name);
dvander@4106
   294
		if (!pEntry)
dvander@2086
   295
			continue;
dvander@2086
   296
dvander@3872
   297
		if (bCoreOnly && pEntry->owner != &g_CoreNatives)
dvander@2086
   298
			continue;
dvander@2086
   299
dvander@2086
   300
		BindNativeToPlugin(pPlugin, native, i, pEntry);
dvander@2086
   301
	}
dvander@2086
   302
}
dvander@2086
   303
dvander@2086
   304
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry)
dvander@2086
   305
{
dvander@2086
   306
	uint32_t i;
dvander@2086
   307
	sp_native_t *native;
dvander@2086
   308
	IPluginContext *pContext;
dvander@2086
   309
dvander@2086
   310
	pContext = pPlugin->GetBaseContext();
dvander@2086
   311
dvander@2086
   312
	if (pContext->FindNativeByName(pEntry->name, &i) != SP_ERROR_NONE)
dvander@2086
   313
	{
dvander@2086
   314
		return;
dvander@2086
   315
	}
dvander@2086
   316
	if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
dvander@2086
   317
	{
dvander@2086
   318
		return;
dvander@2086
   319
	}
dvander@2086
   320
dvander@2086
   321
	if (native->status == SP_NATIVE_BOUND)
dvander@2086
   322
	{
dvander@2086
   323
		return;
dvander@2086
   324
	}
dvander@2086
   325
dvander@2086
   326
	BindNativeToPlugin(pPlugin, native, i, pEntry);
dvander@1689
   327
}
dvander@2086
   328
dvander@2086
   329
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, 
dvander@2086
   330
									 sp_native_t *native,
dvander@2086
   331
									 uint32_t index,
dvander@2086
   332
									 NativeEntry *pEntry)
dvander@2086
   333
{
dvander@2086
   334
	/* Mark as bound... we do the rest next. */
dvander@2086
   335
	native->status = SP_NATIVE_BOUND;
dvander@2086
   336
	native->user = pEntry;
dvander@2086
   337
dvander@4106
   338
	/* Perform a bind. */
dvander@4106
   339
	native->pfn = pEntry->func;
dvander@4106
   340
dvander@4106
   341
	/* We don't bother with dependency crap if the owner is Core. */
dvander@4106
   342
	if (pEntry->owner != &g_CoreNatives)
dvander@2086
   343
	{
dvander@4106
   344
		/* The native is optional, this is a special case */
dvander@4106
   345
		if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
dvander@2086
   346
		{
dvander@4106
   347
			/* Only add if there is a valid owner. */
dvander@4106
   348
			if (pEntry->owner != NULL)
dvander@2086
   349
			{
dvander@4106
   350
				pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
dvander@2086
   351
			}
dvander@2086
   352
			else
dvander@2086
   353
			{
dvander@4106
   354
				native->status = SP_NATIVE_UNBOUND;
dvander@4106
   355
			}
dvander@4106
   356
		}
dvander@4106
   357
		/* Otherwise, we're a strong dependent and not a weak one */
dvander@4106
   358
		else
dvander@4106
   359
		{
dvander@4106
   360
			/* See if this has already been marked as a dependent.
dvander@4106
   361
			 * If it has, it means this relationship has already occurred, 
dvander@4106
   362
			 * and there is no reason to do it again.
dvander@4106
   363
			 */
dvander@4106
   364
			if (pEntry->owner != pPlugin->ToNativeOwner() 
dvander@4106
   365
				&& pEntry->owner->GetMarkSerial() != g_mark_serial)
dvander@4106
   366
			{
dvander@4106
   367
				/* This has not been marked as a dependency yet */
dvander@4106
   368
				//pPlugin->AddDependency(pEntry->owner);
dvander@4106
   369
				pEntry->owner->AddDependent(pPlugin);
dvander@4106
   370
				pEntry->owner->SetMarkSerial(g_mark_serial);
dvander@2086
   371
			}
dvander@2086
   372
		}
dvander@2086
   373
	}
dvander@2086
   374
}
dvander@2086
   375
dvander@2086
   376
NativeEntry *ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
dvander@2086
   377
{
dvander@2086
   378
	NativeEntry *pEntry;
dvander@2086
   379
dvander@2086
   380
	if ((pEntry = FindNative(ntv->name)) == NULL)
dvander@2086
   381
	{
dvander@2086
   382
		pEntry = new NativeEntry;
dvander@2086
   383
dvander@2086
   384
		pEntry->owner = pOwner;
dvander@2086
   385
		pEntry->name = ntv->name;
dvander@2086
   386
		pEntry->func = ntv->func;
dvander@2086
   387
		pEntry->fake = NULL;
dvander@2086
   388
dvander@2086
   389
		m_NtvCache.insert(ntv->name, pEntry);
dvander@2086
   390
dvander@2086
   391
		return pEntry;
dvander@2086
   392
	}
dvander@2086
   393
dvander@2086
   394
	if (pEntry->owner != NULL)
dvander@2086
   395
	{
dvander@2086
   396
		return NULL;
dvander@2086
   397
	}
dvander@2086
   398
dvander@2086
   399
	pEntry->owner = pOwner;
dvander@2086
   400
	pEntry->func = ntv->func;
dvander@2086
   401
	pEntry->name = ntv->name;
dvander@2086
   402
dvander@2086
   403
	return pEntry;
dvander@2086
   404
}
dvander@2086
   405
dvander@2086
   406
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
dvander@2086
   407
{
dvander@2086
   408
	NativeEntry *pEntry;
dvander@2086
   409
dvander@2086
   410
	if ((pEntry = FindNative(name)) == NULL)
dvander@2086
   411
	{
dvander@2086
   412
		return;
dvander@2086
   413
	}
dvander@2086
   414
dvander@2086
   415
	if (pEntry->owner != pOwner)
dvander@2086
   416
	{
dvander@2086
   417
		return;
dvander@2086
   418
	}
dvander@2086
   419
dvander@2211
   420
	if (pEntry->fake != NULL)
dvander@2211
   421
	{
dvander@2211
   422
		g_pSourcePawn2->DestroyFakeNative(pEntry->func);
dvander@2211
   423
		delete pEntry->fake;
dvander@2211
   424
		pEntry->fake = NULL;
dvander@2211
   425
	}
dvander@2211
   426
dvander@2086
   427
	pEntry->func = NULL;
dvander@2086
   428
	pEntry->name = NULL;
dvander@2086
   429
	pEntry->owner = NULL;
dvander@2086
   430
}
dvander@2086
   431
dvander@2086
   432
NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
dvander@2086
   433
{
dvander@2086
   434
	FakeNative *pFake;
dvander@2086
   435
	NativeEntry *pEntry;
dvander@2086
   436
	SPVM_NATIVE_FUNC gate;
dvander@2086
   437
dvander@2086
   438
	if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
dvander@2086
   439
	{
dvander@2086
   440
		return NULL;
dvander@2086
   441
	}
dvander@2086
   442
dvander@2086
   443
	pFake = new FakeNative;
dvander@2086
   444
dvander@2193
   445
	if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
dvander@2086
   446
	{
dvander@2086
   447
		delete pFake;
dvander@2086
   448
		return NULL;
dvander@2086
   449
	}
dvander@2086
   450
dvander@2086
   451
	if (pEntry == NULL)
dvander@2086
   452
	{
dvander@2086
   453
		pEntry = new NativeEntry;
dvander@2086
   454
		m_NtvCache.insert(name, pEntry);
dvander@2086
   455
	}
dvander@2086
   456
dvander@2086
   457
	pFake->call = pFunc;
dvander@2086
   458
	pFake->ctx = pFunc->GetParentContext();
dvander@3872
   459
	smcore.strncopy(pFake->name, name, sizeof(pFake->name));
dvander@2086
   460
	
dvander@2086
   461
	pEntry->fake = pFake;
dvander@2086
   462
	pEntry->func = gate;
dvander@2086
   463
	pEntry->name = pFake->name;
dvander@2086
   464
	pEntry->owner = g_PluginSys.GetPluginByCtx(pFake->ctx->GetContext());
dvander@2086
   465
dvander@2086
   466
	return pEntry;
dvander@2086
   467
}
dvander@2841
   468
dvander@2841
   469
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
dvander@2841
   470
		                                const char *name)
dvander@2841
   471
{
dvander@4067
   472
	if (m_caps.contains(name))
dvander@2841
   473
		return;
dvander@2841
   474
dvander@2841
   475
	Capability cap;
dvander@2841
   476
	cap.ext = myself;
dvander@2841
   477
	cap.provider = provider;
dvander@2841
   478
dvander@2841
   479
	m_caps.insert(name, cap);
dvander@2841
   480
}
dvander@2841
   481
dvander@2841
   482
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
dvander@2841
   483
		                                 const char *name)
dvander@2841
   484
{
dvander@4067
   485
	StringHashMap<Capability>::Result r = m_caps.find(name);
dvander@4067
   486
	if (!r.found())
dvander@4067
   487
		return;
dvander@4067
   488
	if (r->value.ext != myself || r->value.provider != provider)
dvander@2841
   489
		return;
dvander@2841
   490
dvander@4067
   491
	m_caps.remove(r);
dvander@2841
   492
}
dvander@2841
   493
dvander@2841
   494
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature, 
dvander@2841
   495
                                       const char *name)
dvander@2841
   496
{
dvander@2841
   497
	switch (feature)
dvander@2841
   498
	{
dvander@2841
   499
	case FeatureType_Native:
dvander@2841
   500
		return TestNative(pRuntime, name);
dvander@2841
   501
	case FeatureType_Capability:
dvander@2841
   502
		return TestCap(name);
dvander@2841
   503
	default:
dvander@2841
   504
		break;
dvander@2841
   505
	}
dvander@2841
   506
dvander@2841
   507
	return FeatureStatus_Unknown;
dvander@2841
   508
}
dvander@2841
   509
dvander@2841
   510
FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name)
dvander@2841
   511
{
dvander@2841
   512
	uint32_t index;
dvander@2841
   513
dvander@2841
   514
	if (pRuntime->FindNativeByName(name, &index) == SP_ERROR_NONE)
dvander@2841
   515
	{
dvander@2841
   516
		sp_native_t *native;
dvander@2841
   517
		if (pRuntime->GetNativeByIndex(index, &native) == SP_ERROR_NONE)
dvander@2841
   518
		{
dvander@2841
   519
			if (native->status == SP_NATIVE_BOUND)
dvander@2841
   520
				return FeatureStatus_Available;
dvander@2841
   521
			else
dvander@2841
   522
				return FeatureStatus_Unknown;
dvander@2841
   523
		}
dvander@2841
   524
	}
dvander@2841
   525
dvander@2841
   526
	NativeEntry *entry = FindNative(name);
dvander@4106
   527
	if (!entry)
dvander@2841
   528
		return FeatureStatus_Unknown;
dvander@2841
   529
dvander@4106
   530
	if (entry->owner && entry->func)
dvander@2841
   531
		return FeatureStatus_Available;
dvander@4106
   532
dvander@4106
   533
	return FeatureStatus_Unavailable;
dvander@2841
   534
}
dvander@2841
   535
dvander@2841
   536
FeatureStatus ShareSystem::TestCap(const char *name)
dvander@2841
   537
{
dvander@4067
   538
	StringHashMap<Capability>::Result r = m_caps.find(name);
dvander@4067
   539
	if (!r.found())
dvander@2841
   540
		return FeatureStatus_Unknown;
dvander@2841
   541
dvander@4067
   542
	return r->value.provider->GetFeatureStatus(FeatureType_Capability, name);
dvander@2841
   543
}