1.1 --- a/core/systems/ShareSys.cpp Wed Nov 19 02:14:43 2008 -0600
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,529 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include "ShareSys.h"
1.36 -#include "HandleSys.h"
1.37 -#include "ExtensionSys.h"
1.38 -#include "LibrarySys.h"
1.39 -#include "PluginSys.h"
1.40 -#include "sm_stringutil.h"
1.41 -
1.42 -ShareSystem g_ShareSys;
1.43 -static unsigned int g_mark_serial = 0;
1.44 -
1.45 -ShareSystem::ShareSystem()
1.46 -{
1.47 - m_IdentRoot.ident = 0;
1.48 - m_TypeRoot = 0;
1.49 - m_IfaceType = 0;
1.50 - m_CoreType = 0;
1.51 -}
1.52 -
1.53 -IdentityToken_t *ShareSystem::CreateCoreIdentity()
1.54 -{
1.55 - if (!m_CoreType)
1.56 - {
1.57 - m_CoreType = CreateIdentType("CORE");
1.58 - }
1.59 -
1.60 - return CreateIdentity(m_CoreType, this);
1.61 -}
1.62 -
1.63 -void ShareSystem::Initialize()
1.64 -{
1.65 - TypeAccess sec;
1.66 -
1.67 - g_HandleSys.InitAccessDefaults(&sec, NULL);
1.68 - sec.ident = GetIdentRoot();
1.69 -
1.70 - m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
1.71 - m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
1.72 -
1.73 - /* Initialize our static identity handle */
1.74 - m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
1.75 -
1.76 - /* Add the Handle System and others... they are too innocent and pure to do it themselves */
1.77 - AddInterface(NULL, &g_HandleSys);
1.78 - AddInterface(NULL, &g_LibSys);
1.79 -}
1.80 -
1.81 -void ShareSystem::OnSourceModShutdown()
1.82 -{
1.83 - if (m_CoreType)
1.84 - {
1.85 - g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
1.86 - }
1.87 -
1.88 - g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
1.89 - g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
1.90 -}
1.91 -
1.92 -IdentityType_t ShareSystem::FindIdentType(const char *name)
1.93 -{
1.94 - HandleType_t type;
1.95 -
1.96 - if (g_HandleSys.FindHandleType(name, &type))
1.97 - {
1.98 - if (g_HandleSys.TypeCheck(type, m_TypeRoot))
1.99 - {
1.100 - return type;
1.101 - }
1.102 - }
1.103 -
1.104 - return 0;
1.105 -}
1.106 -
1.107 -IdentityType_t ShareSystem::CreateIdentType(const char *name)
1.108 -{
1.109 - if (!m_TypeRoot)
1.110 - {
1.111 - return 0;
1.112 - }
1.113 -
1.114 - return g_HandleSys.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
1.115 -}
1.116 -
1.117 -void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
1.118 -{
1.119 - /* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */
1.120 -}
1.121 -
1.122 -IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type, void *ptr)
1.123 -{
1.124 - if (!m_TypeRoot)
1.125 - {
1.126 - return 0;
1.127 - }
1.128 -
1.129 - /* :TODO: Cache? */
1.130 - IdentityToken_t *pToken = new IdentityToken_t;
1.131 -
1.132 - HandleSecurity sec;
1.133 - sec.pOwner = sec.pIdentity = GetIdentRoot();
1.134 -
1.135 - pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true);
1.136 - pToken->ptr = ptr;
1.137 - pToken->type = type;
1.138 -
1.139 - return pToken;
1.140 -}
1.141 -
1.142 -bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
1.143 -{
1.144 - if (!iface)
1.145 - {
1.146 - return false;
1.147 - }
1.148 -
1.149 - IfaceInfo info;
1.150 -
1.151 - info.owner = myself;
1.152 - info.iface = iface;
1.153 -
1.154 - m_Interfaces.push_back(info);
1.155 -
1.156 - return true;
1.157 -}
1.158 -
1.159 -bool ShareSystem::RequestInterface(const char *iface_name,
1.160 - unsigned int iface_vers,
1.161 - IExtension *myself,
1.162 - SMInterface **pIface)
1.163 -{
1.164 - /* See if the interface exists */
1.165 - List<IfaceInfo>::iterator iter;
1.166 - SMInterface *iface;
1.167 - IExtension *iface_owner;
1.168 - bool found = false;
1.169 - for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
1.170 - {
1.171 - IfaceInfo &info = (*iter);
1.172 - iface = info.iface;
1.173 - if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
1.174 - {
1.175 - if (iface->GetInterfaceVersion() == iface_vers
1.176 - || iface->IsVersionCompatible(iface_vers))
1.177 - {
1.178 - iface_owner = info.owner;
1.179 - found = true;
1.180 - break;
1.181 - }
1.182 - }
1.183 - }
1.184 -
1.185 - if (!found)
1.186 - {
1.187 - return false;
1.188 - }
1.189 -
1.190 - /* Add a dependency node */
1.191 - if (iface_owner)
1.192 - {
1.193 - IfaceInfo info;
1.194 - info.iface = iface;
1.195 - info.owner = iface_owner;
1.196 - g_Extensions.BindDependency(myself, &info);
1.197 - }
1.198 -
1.199 - if (pIface)
1.200 - {
1.201 - *pIface = iface;
1.202 - }
1.203 -
1.204 - return true;
1.205 -}
1.206 -
1.207 -void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives)
1.208 -{
1.209 - CNativeOwner *pOwner;
1.210 -
1.211 - pOwner = g_Extensions.GetNativeOwner(myself);
1.212 -
1.213 - pOwner->AddNatives(natives);
1.214 -}
1.215 -
1.216 -void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
1.217 -{
1.218 - HandleSecurity sec;
1.219 -
1.220 - sec.pOwner = GetIdentRoot();
1.221 - sec.pIdentity = GetIdentRoot();
1.222 -
1.223 - g_HandleSys.FreeHandle(identity->ident, &sec);
1.224 - delete identity;
1.225 -}
1.226 -
1.227 -void ShareSystem::DestroyIdentType(IdentityType_t type)
1.228 -{
1.229 - g_HandleSys.RemoveType(type, GetIdentRoot());
1.230 -}
1.231 -
1.232 -void ShareSystem::RemoveInterfaces(IExtension *pExtension)
1.233 -{
1.234 - List<IfaceInfo>::iterator iter = m_Interfaces.begin();
1.235 -
1.236 - while (iter != m_Interfaces.end())
1.237 - {
1.238 - if ((*iter).owner == pExtension)
1.239 - {
1.240 - iter = m_Interfaces.erase(iter);
1.241 - }
1.242 - else
1.243 - {
1.244 - iter++;
1.245 - }
1.246 - }
1.247 -}
1.248 -
1.249 -void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool require, bool autoload)
1.250 -{
1.251 - g_Extensions.AddDependency(myself, filename, require, autoload);
1.252 -}
1.253 -
1.254 -void ShareSystem::RegisterLibrary(IExtension *myself, const char *name)
1.255 -{
1.256 - g_Extensions.AddLibrary(myself, name);
1.257 -}
1.258 -
1.259 -void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
1.260 -{
1.261 - unsigned int i;
1.262 - NativeEntry *pEntry;
1.263 - CNativeOwner *pOwner;
1.264 -
1.265 - pOwner = g_Extensions.GetNativeOwner(myself);
1.266 -
1.267 - for (i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
1.268 - {
1.269 - if ((pEntry = FindNative(natives[i].name)) == NULL)
1.270 - {
1.271 - continue;
1.272 - }
1.273 -
1.274 - if (pEntry->owner != g_pCoreNatives)
1.275 - {
1.276 - continue;
1.277 - }
1.278 -
1.279 - if (pEntry->replacement.owner != NULL)
1.280 - {
1.281 - continue;
1.282 - }
1.283 -
1.284 - /* Now it's safe to add the override */
1.285 - pEntry->replacement.func = natives[i].func;
1.286 - pEntry->replacement.owner = pOwner;
1.287 - pOwner->AddReplacedNative(pEntry);
1.288 - }
1.289 -}
1.290 -
1.291 -NativeEntry *ShareSystem::FindNative(const char *name)
1.292 -{
1.293 - NativeEntry **ppEntry;
1.294 -
1.295 - if ((ppEntry = m_NtvCache.retrieve(name)) == NULL)
1.296 - {
1.297 - return NULL;
1.298 - }
1.299 -
1.300 - return *ppEntry;
1.301 -}
1.302 -
1.303 -void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
1.304 -{
1.305 - NativeEntry *pEntry;
1.306 - sp_native_t *native;
1.307 - uint32_t i, native_count;
1.308 - IPluginContext *pContext;
1.309 -
1.310 - pContext = pPlugin->GetBaseContext();
1.311 -
1.312 - /* Generate a new serial ID, mark our dependencies with it. */
1.313 - g_mark_serial++;
1.314 - pPlugin->PropogateMarkSerial(g_mark_serial);
1.315 -
1.316 - native_count = pContext->GetNativesNum();
1.317 - for (i = 0; i < native_count; i++)
1.318 - {
1.319 - if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
1.320 - {
1.321 - continue;
1.322 - }
1.323 -
1.324 - /* If we're bound, check if there is a replacement available.
1.325 - * If not, this native is totally finalized.
1.326 - */
1.327 - if (native->status == SP_NATIVE_BOUND)
1.328 - {
1.329 - pEntry = (NativeEntry *)native->user;
1.330 - assert(pEntry != NULL);
1.331 - if (pEntry->replacement.owner == NULL
1.332 - || (pEntry->replacement.owner != NULL
1.333 - && pEntry->replacement.func == native->pfn))
1.334 - {
1.335 - continue;
1.336 - }
1.337 - }
1.338 - /* Otherwise, the native must be in our cache. */
1.339 - else if ((pEntry = FindNative(native->name)) == NULL)
1.340 - {
1.341 - continue;
1.342 - }
1.343 -
1.344 - if (bCoreOnly && pEntry->owner != g_pCoreNatives)
1.345 - {
1.346 - continue;
1.347 - }
1.348 -
1.349 - BindNativeToPlugin(pPlugin, native, i, pEntry);
1.350 - }
1.351 -}
1.352 -
1.353 -void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry)
1.354 -{
1.355 - uint32_t i;
1.356 - sp_native_t *native;
1.357 - IPluginContext *pContext;
1.358 -
1.359 - pContext = pPlugin->GetBaseContext();
1.360 -
1.361 - if (pContext->FindNativeByName(pEntry->name, &i) != SP_ERROR_NONE)
1.362 - {
1.363 - return;
1.364 - }
1.365 - if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
1.366 - {
1.367 - return;
1.368 - }
1.369 -
1.370 - if (native->status == SP_NATIVE_BOUND)
1.371 - {
1.372 - return;
1.373 - }
1.374 -
1.375 - BindNativeToPlugin(pPlugin, native, i, pEntry);
1.376 -}
1.377 -
1.378 -void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
1.379 - sp_native_t *native,
1.380 - uint32_t index,
1.381 - NativeEntry *pEntry)
1.382 -{
1.383 - /* Mark as bound... we do the rest next. */
1.384 - native->status = SP_NATIVE_BOUND;
1.385 - native->user = pEntry;
1.386 -
1.387 - /* See if a replacement is available. */
1.388 - if (pEntry->replacement.owner != NULL)
1.389 - {
1.390 - /* Perform a replacement bind. */
1.391 - native->pfn = pEntry->replacement.func;
1.392 - pEntry->replacement.owner->AddWeakRef(WeakNative(pPlugin, index, pEntry));
1.393 - }
1.394 - else
1.395 - {
1.396 - /* Perform a normal bind. */
1.397 - native->pfn = pEntry->func;
1.398 -
1.399 - /* We don't bother with dependency crap if the owner is Core. */
1.400 - if (pEntry->owner != g_pCoreNatives)
1.401 - {
1.402 - /* The native is optional, this is a special case */
1.403 - if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
1.404 - {
1.405 - /* Only add if there is a valid owner. */
1.406 - if (pEntry->owner != NULL)
1.407 - {
1.408 - pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
1.409 - }
1.410 - else
1.411 - {
1.412 - native->status = SP_NATIVE_UNBOUND;
1.413 - }
1.414 - }
1.415 - /* Otherwise, we're a strong dependent and not a weak one */
1.416 - else
1.417 - {
1.418 - /* See if this has already been marked as a dependent.
1.419 - * If it has, it means this relationship has already occurred,
1.420 - * and there is no reason to do it again.
1.421 - */
1.422 - if (pEntry->owner != pPlugin
1.423 - && pEntry->owner->GetMarkSerial() != g_mark_serial)
1.424 - {
1.425 - /* This has not been marked as a dependency yet */
1.426 - //pPlugin->AddDependency(pEntry->owner);
1.427 - pEntry->owner->AddDependent(pPlugin);
1.428 - pEntry->owner->SetMarkSerial(g_mark_serial);
1.429 - }
1.430 - }
1.431 - }
1.432 - }
1.433 -}
1.434 -
1.435 -NativeEntry *ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
1.436 -{
1.437 - NativeEntry *pEntry;
1.438 -
1.439 - if ((pEntry = FindNative(ntv->name)) == NULL)
1.440 - {
1.441 - pEntry = new NativeEntry;
1.442 -
1.443 - pEntry->owner = pOwner;
1.444 - pEntry->name = ntv->name;
1.445 - pEntry->func = ntv->func;
1.446 - pEntry->replacement.func = NULL;
1.447 - pEntry->replacement.owner = NULL;
1.448 - pEntry->fake = NULL;
1.449 -
1.450 - m_NtvCache.insert(ntv->name, pEntry);
1.451 -
1.452 - return pEntry;
1.453 - }
1.454 -
1.455 - if (pEntry->owner != NULL)
1.456 - {
1.457 - return NULL;
1.458 - }
1.459 -
1.460 - pEntry->owner = pOwner;
1.461 - pEntry->func = ntv->func;
1.462 - pEntry->name = ntv->name;
1.463 -
1.464 - return pEntry;
1.465 -}
1.466 -
1.467 -void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
1.468 -{
1.469 - NativeEntry *pEntry;
1.470 -
1.471 - if ((pEntry = FindNative(name)) == NULL)
1.472 - {
1.473 - return;
1.474 - }
1.475 -
1.476 - if (pEntry->owner != pOwner)
1.477 - {
1.478 - return;
1.479 - }
1.480 -
1.481 - if (pEntry->fake != NULL)
1.482 - {
1.483 - g_pSourcePawn2->DestroyFakeNative(pEntry->func);
1.484 - delete pEntry->fake;
1.485 - pEntry->fake = NULL;
1.486 - }
1.487 -
1.488 - pEntry->func = NULL;
1.489 - pEntry->name = NULL;
1.490 - pEntry->owner = NULL;
1.491 - pEntry->replacement.func = NULL;
1.492 - pEntry->replacement.owner = NULL;
1.493 -}
1.494 -
1.495 -NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
1.496 -{
1.497 - FakeNative *pFake;
1.498 - NativeEntry *pEntry;
1.499 - SPVM_NATIVE_FUNC gate;
1.500 -
1.501 - if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
1.502 - {
1.503 - return NULL;
1.504 - }
1.505 -
1.506 - pFake = new FakeNative;
1.507 -
1.508 - if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
1.509 - {
1.510 - delete pFake;
1.511 - return NULL;
1.512 - }
1.513 -
1.514 - if (pEntry == NULL)
1.515 - {
1.516 - pEntry = new NativeEntry;
1.517 - m_NtvCache.insert(name, pEntry);
1.518 - }
1.519 -
1.520 - pFake->call = pFunc;
1.521 - pFake->ctx = pFunc->GetParentContext();
1.522 - strncopy(pFake->name, name, sizeof(pFake->name));
1.523 -
1.524 - pEntry->fake = pFake;
1.525 - pEntry->func = gate;
1.526 - pEntry->name = pFake->name;
1.527 - pEntry->owner = g_PluginSys.GetPluginByCtx(pFake->ctx->GetContext());
1.528 - pEntry->replacement.func = NULL;
1.529 - pEntry->replacement.owner = NULL;
1.530 -
1.531 - return pEntry;
1.532 -}