core/systems/ExtensionSys.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 16 19:41:21 2007 +0000 (2007-01-16)
changeset 298 07f6b2fe8468
child 304 fa485d2f25ed
permissions -rw-r--r--
initial import of extension API and SDK as well as auto-loading
     1 #include "ExtensionSys.h"
     2 #include "LibrarySys.h"
     3 #include "ShareSys.h"
     4 #include "CLogger.h"
     5 
     6 CExtensionManager g_Extensions;
     7 IdentityType_t g_ExtType;
     8 
     9 CExtension::CExtension(const char *filename, char *error, size_t err_max)
    10 {
    11 	m_File.assign(filename);
    12 	m_pAPI = NULL;
    13 	m_pIdentToken = NULL;
    14 
    15 	char path[PLATFORM_MAX_PATH+1];
    16 	g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename);
    17 
    18 	m_pLib = g_LibSys.OpenLibrary(path, error, err_max);
    19 
    20 	if (m_pLib == NULL)
    21 	{
    22 		return;
    23 	}
    24 
    25 	typedef IExtensionInterface *(*GETAPI)();
    26 	GETAPI pfnGetAPI = NULL;
    27 
    28 	if ((pfnGetAPI=(GETAPI)m_pLib->GetSymbolAddress("GetSMExtAPI")) == NULL)
    29 	{
    30 		m_pLib->CloseLibrary();
    31 		m_pLib = NULL;
    32 		snprintf(error, err_max, "Unable to find extension entry point");
    33 		return;
    34 	}
    35 
    36 	m_pAPI = pfnGetAPI();
    37 	if (!m_pAPI || m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION)
    38 	{
    39 		m_pLib->CloseLibrary();
    40 		m_pLib = NULL;
    41 		snprintf(error, err_max, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION);
    42 		return;
    43 	}
    44 
    45 	if (m_pAPI->IsMetamodExtension())
    46 	{
    47 		/* :TODO: STUFF */
    48 	}
    49 
    50 	m_pIdentToken = g_ShareSys.CreateIdentity(g_ExtType);
    51 
    52 	if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, err_max, g_SourceMod.IsLateLoadInMap()))
    53 	{
    54 		if (m_pAPI->IsMetamodExtension())
    55 		{
    56 			/* :TODO: stuff */
    57 		}
    58 		m_pAPI = NULL;
    59 		m_pLib->CloseLibrary();
    60 		m_pLib = NULL;
    61 		g_ShareSys.DestroyIdentity(m_pIdentToken);
    62 		m_pIdentToken = NULL;
    63 		return;
    64 	}
    65 }
    66 
    67 CExtension::~CExtension()
    68 {
    69 	if (m_pAPI)
    70 	{
    71 		m_pAPI->OnExtensionUnload();
    72 	}
    73 
    74 	if (m_pIdentToken)
    75 	{
    76 		g_ShareSys.DestroyIdentity(m_pIdentToken);
    77 	}
    78 
    79 	if (m_pLib)
    80 	{
    81 		m_pLib->CloseLibrary();
    82 	}
    83 }
    84 
    85 void CExtension::SetError(const char *error)
    86 {
    87 	m_Error.assign(error);
    88 }
    89 
    90 IExtensionInterface *CExtension::GetAPI()
    91 {
    92 	return m_pAPI;
    93 }
    94 
    95 const char *CExtension::GetFilename()
    96 {
    97 	return m_File.c_str();
    98 }
    99 
   100 IdentityToken_t *CExtension::GetIdentity()
   101 {
   102 	return m_pIdentToken;
   103 }
   104 
   105 bool CExtension::IsLoaded()
   106 {
   107 	return (m_pLib != NULL);
   108 }
   109 
   110 void CExtensionManager::OnSourceModAllInitialized()
   111 {
   112 	g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
   113 }
   114 
   115 void CExtensionManager::OnSourceModShutdown()
   116 {
   117 	g_ShareSys.DestroyIdentType(g_ExtType);
   118 }
   119 
   120 IExtension *CExtensionManager::LoadAutoExtension(const char *path)
   121 {
   122 	char error[256];
   123 	CExtension *p = new CExtension(path, error, sizeof(error));
   124 
   125 	if (!p->IsLoaded())
   126 	{
   127 		g_Logger.LogError("[SOURCEMOD] Unable to load extension \"%s\": %s", path, error);
   128 		p->SetError(error);
   129 	}
   130 
   131 	m_Libs.push_back(p);
   132 
   133 	return p;
   134 }
   135 
   136 IExtension *CExtensionManager::FindExtensionByFile(const char *file)
   137 {
   138 	List<CExtension *>::iterator iter;
   139 	CExtension *pExt;
   140 
   141 	/* Make sure the file direction is right */
   142 	char path[PLATFORM_MAX_PATH+1];
   143 	g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
   144 
   145 	for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
   146 	{
   147 		pExt = (*iter);
   148 		if (strcmp(pExt->GetFilename(), path) == 0)
   149 		{
   150 			return pExt;
   151 		}
   152 	}
   153 
   154 	return NULL;
   155 }
   156 
   157 IExtension *CExtensionManager::FindExtensionByName(const char *ext)
   158 {
   159 	List<CExtension *>::iterator iter;
   160 	CExtension *pExt;
   161 	IExtensionInterface *pAPI;
   162 	const char *name;
   163 
   164 	for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
   165 	{
   166 		pExt = (*iter);
   167 		if (!pExt->IsLoaded())
   168 		{
   169 			continue;
   170 		}
   171 		if ((pAPI = pExt->GetAPI()) == NULL)
   172 		{
   173 			continue;
   174 		}
   175 		name = pAPI->GetExtensionName();
   176 		if (!name)
   177 		{
   178 			continue;
   179 		}
   180 		if (strcmp(name, ext) == 0)
   181 		{
   182 			return pExt;
   183 		}
   184 	}
   185 
   186 	return NULL;
   187 }
   188 
   189 IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime lifetime, char *error, size_t err_max)
   190 {
   191 	CExtension *pExt = new CExtension(file, error, err_max);
   192 
   193 	/* :NOTE: lifetime is currently ignored */
   194 
   195 	if (!pExt->IsLoaded())
   196 	{
   197 		delete pExt;
   198 		return NULL;
   199 	}
   200 
   201 	m_Libs.push_back(pExt);
   202 
   203 	return pExt;
   204 }
   205 
   206 bool CExtensionManager::UnloadExtension(IExtension *pExt)
   207 {
   208 	/* :TODO: implement */
   209 	return true;
   210 }
   211 
   212 unsigned int CExtensionManager::NumberOfPluginDependents(IExtension *pExt, unsigned int *optional)
   213 {
   214 	/* :TODO: implement */
   215 	return 0;
   216 }
   217 
   218 bool CExtensionManager::IsExtensionUnloadable(IExtension *pExtension)
   219 {
   220 	/* :TODO: implement */
   221 	return true;
   222 }