core/systems/ShareSys.cpp
author David Anderson <dvander@alliedmods.net>
Mon Oct 15 04:06:57 2007 +0000 (2007-10-15)
changeset 1572 adbc41dc9cd0
parent 1330 ab94316bb52b
child 1689 451c11ef473a
permissions -rw-r--r--
fixed an overall deficiency where libraries did not include extensions. extensions can now mark themselves as libraries, and they thus become fully optional just as plugins do. additionally, a bug was fixed where plugins could be accidentally marked as required instead of optional. these changes resulted in a bcompat API bump to the extension/sharesys interface.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "ShareSys.h"
    33 #include "HandleSys.h"
    34 #include "ExtensionSys.h"
    35 #include "LibrarySys.h"
    36 
    37 ShareSystem g_ShareSys;
    38 
    39 ShareSystem::ShareSystem()
    40 {
    41 	m_IdentRoot.ident = 0;
    42 	m_TypeRoot = 0;
    43 	m_IfaceType = 0;
    44 	m_CoreType = 0;
    45 }
    46 
    47 IdentityToken_t *ShareSystem::CreateCoreIdentity()
    48 {
    49 	if (!m_CoreType)
    50 	{
    51 		m_CoreType = CreateIdentType("CORE");
    52 	}
    53 
    54 	return CreateIdentity(m_CoreType, this);
    55 }
    56 
    57 void ShareSystem::OnSourceModStartup(bool late)
    58 {
    59 	TypeAccess sec;
    60 
    61 	g_HandleSys.InitAccessDefaults(&sec, NULL);
    62 	sec.ident = GetIdentRoot();
    63 
    64 	m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
    65 	m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
    66 
    67 	/* Initialize our static identity handle */
    68 	m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
    69 
    70 	/* Add the Handle System and others... they are too innocent and pure to do it themselves */
    71 	AddInterface(NULL, &g_HandleSys);
    72 	AddInterface(NULL, &g_LibSys);
    73 }
    74 
    75 void ShareSystem::OnSourceModShutdown()
    76 {
    77 	if (m_CoreType)
    78 	{
    79 		g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
    80 	}
    81 
    82 	g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
    83 	g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
    84 }
    85 
    86 IdentityType_t ShareSystem::FindIdentType(const char *name)
    87 {
    88 	HandleType_t type;
    89 
    90 	if (g_HandleSys.FindHandleType(name, &type))
    91 	{
    92 		if (g_HandleSys.TypeCheck(type, m_TypeRoot))
    93 		{
    94 			return type;
    95 		}
    96 	}
    97 
    98 	return 0;
    99 }
   100 
   101 IdentityType_t ShareSystem::CreateIdentType(const char *name)
   102 {
   103 	if (!m_TypeRoot)
   104 	{
   105 		return 0;
   106 	}
   107 
   108 	return g_HandleSys.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
   109 }
   110 
   111 void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
   112 {
   113 	/* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */
   114 }
   115 
   116 IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type, void *ptr)
   117 {
   118 	if (!m_TypeRoot)
   119 	{
   120 		return 0;
   121 	}
   122 
   123 	/* :TODO: Cache? */
   124 	IdentityToken_t *pToken = new IdentityToken_t;
   125 
   126 	HandleSecurity sec;
   127 	sec.pOwner = sec.pIdentity = GetIdentRoot();
   128 
   129 	pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true);
   130 	pToken->ptr = ptr;
   131 	pToken->type = type;
   132 
   133 	return pToken;
   134 }
   135 
   136 bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
   137 {
   138 	if (!iface)
   139 	{
   140 		return false;
   141 	}
   142 
   143 	IfaceInfo info;
   144 
   145 	info.owner = myself;
   146 	info.iface = iface;
   147 	
   148 	m_Interfaces.push_back(info);
   149 
   150 	return true;
   151 }
   152 
   153 bool ShareSystem::RequestInterface(const char *iface_name, 
   154 								   unsigned int iface_vers, 
   155 								   IExtension *myself, 
   156 								   SMInterface **pIface)
   157 {
   158 	/* See if the interface exists */
   159 	List<IfaceInfo>::iterator iter;
   160 	SMInterface *iface;
   161 	IExtension *iface_owner;
   162 	bool found = false;
   163 	for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
   164 	{
   165 		IfaceInfo &info = (*iter);
   166 		iface = info.iface;
   167 		if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
   168 		{
   169 			if (iface->GetInterfaceVersion() == iface_vers
   170 				|| iface->IsVersionCompatible(iface_vers))
   171 			{
   172 				iface_owner = info.owner;
   173 				found = true;
   174 				break;
   175 			}
   176 		}
   177 	}
   178 
   179 	if (!found)
   180 	{
   181 		return false;
   182 	}
   183 
   184 	/* Add a dependency node */
   185 	if (iface_owner)
   186 	{
   187 		IfaceInfo info;
   188 		info.iface = iface;
   189 		info.owner = iface_owner;
   190 		g_Extensions.BindDependency(myself, &info);
   191 	}
   192 
   193 	if (pIface)
   194 	{
   195 		*pIface = iface;
   196 	}
   197 
   198 	return true;
   199 }
   200 
   201 void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives)
   202 {
   203 	g_Extensions.AddNatives(myself, natives);
   204 }
   205 
   206 void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
   207 {
   208 	HandleSecurity sec;
   209 
   210 	sec.pOwner = GetIdentRoot();
   211 	sec.pIdentity = GetIdentRoot();
   212 
   213 	g_HandleSys.FreeHandle(identity->ident, &sec);
   214 	delete identity;
   215 }
   216 
   217 void ShareSystem::DestroyIdentType(IdentityType_t type)
   218 {
   219 	g_HandleSys.RemoveType(type, GetIdentRoot());
   220 }
   221 
   222 void ShareSystem::RemoveInterfaces(IExtension *pExtension)
   223 {
   224 	List<IfaceInfo>::iterator iter = m_Interfaces.begin();
   225 
   226 	while (iter != m_Interfaces.end())
   227 	{
   228 		if ((*iter).owner == pExtension)
   229 		{
   230 			iter = m_Interfaces.erase(iter);
   231 		} else {
   232 			iter++;
   233 		}
   234 	}
   235 }
   236 
   237 void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool require, bool autoload)
   238 {
   239 	g_Extensions.AddDependency(myself, filename, require, autoload);
   240 }
   241 
   242 void ShareSystem::RegisterLibrary(IExtension *myself, const char *name)
   243 {
   244 	g_Extensions.AddLibrary(myself, name);
   245 }