core/systems/PluginInfoDatabase.cpp
changeset 1952 b7aa2b626807
child 2289 44045ead61cd
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/core/systems/PluginInfoDatabase.cpp	Sun Mar 30 07:00:22 2008 +0000
     1.3 @@ -0,0 +1,349 @@
     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 <stdarg.h>
    1.36 +#include <string.h>
    1.37 +#include "PluginInfoDatabase.h"
    1.38 +#include "PluginSys.h"
    1.39 +
    1.40 +void PluginSettings::Init()
    1.41 +{
    1.42 +	name = -1;
    1.43 +	pause_val = false;
    1.44 +	type_val = PluginType_MapUpdated;
    1.45 +	optarray = -1;
    1.46 +	opts_num = 0;
    1.47 +	opts_size = 0;
    1.48 +	blockload_val = false;
    1.49 +}
    1.50 +
    1.51 +/**
    1.52 + * :TODO: write the logger, make these errors log instead of being static
    1.53 + * NOTE: once we do that, we will have to change some code to ignore sections
    1.54 + */
    1.55 +
    1.56 +CPluginInfoDatabase::CPluginInfoDatabase()
    1.57 +{
    1.58 +	m_strtab = NULL;
    1.59 +	m_infodb_count = 0;
    1.60 +	m_infodb_size = 0;
    1.61 +	m_infodb = -1;
    1.62 +}
    1.63 +
    1.64 +CPluginInfoDatabase::~CPluginInfoDatabase()
    1.65 +{
    1.66 +	delete m_strtab;
    1.67 +}
    1.68 +
    1.69 +void CPluginInfoDatabase::ReadSMC_ParseStart()
    1.70 +{
    1.71 +	/* Create or reset our string table */
    1.72 +	if (m_strtab)
    1.73 +	{
    1.74 +		m_strtab->Reset();
    1.75 +	} else {
    1.76 +		m_strtab = new BaseStringTable(1024);
    1.77 +	}
    1.78 +
    1.79 +	/* Set our internal states to the beginning */
    1.80 +	in_plugins = false;
    1.81 +	cur_plugin = -1;
    1.82 +	in_options = false;
    1.83 +	m_infodb_size = 0;
    1.84 +	m_infodb_count = 0;
    1.85 +	m_infodb = -1;
    1.86 +}
    1.87 +
    1.88 +SMCResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
    1.89 +{
    1.90 +	char buffer[512];
    1.91 +	va_list ap;
    1.92 +
    1.93 +	va_start(ap, fmt);
    1.94 +	vsnprintf(buffer, sizeof(buffer), fmt, ap);
    1.95 +	va_end(ap);
    1.96 +
    1.97 +	m_errmsg = m_strtab->AddString(buffer);
    1.98 +
    1.99 +	return SMCResult_HaltFail;
   1.100 +}
   1.101 +
   1.102 +unsigned int CPluginInfoDatabase::GetSettingsNum()
   1.103 +{
   1.104 +	return m_infodb_count;
   1.105 +}
   1.106 +
   1.107 +PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
   1.108 +{
   1.109 +	BaseMemTable *memtab = m_strtab->GetMemTable();
   1.110 +	int *table = (int *)memtab->GetAddress(m_infodb);
   1.111 +
   1.112 +	if (!table || index >= m_infodb_count)
   1.113 +	{
   1.114 +		return NULL;
   1.115 +	}
   1.116 +
   1.117 +	PluginSettings *plugin = (PluginSettings *)memtab->GetAddress(table[index]);
   1.118 +
   1.119 +	const char *name = m_strtab->GetString(plugin->name);
   1.120 +
   1.121 +	if (!name)
   1.122 +	{
   1.123 +		return NULL;
   1.124 +	}
   1.125 +
   1.126 +	if (!g_PluginSys.TestAliasMatch(name, filename))
   1.127 +	{
   1.128 +		return NULL;
   1.129 +	}
   1.130 +
   1.131 +	return plugin;
   1.132 +}
   1.133 +
   1.134 +void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
   1.135 +{
   1.136 +	PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
   1.137 +	if (!table)
   1.138 +	{
   1.139 +		*key = NULL;
   1.140 +		*val = NULL;
   1.141 +		return;
   1.142 +	}
   1.143 +
   1.144 +	if (opt_num >= settings->opts_num)
   1.145 +	{
   1.146 +		*key = NULL;
   1.147 +		*val = NULL;
   1.148 +		return;
   1.149 +	}
   1.150 +
   1.151 +	*key = m_strtab->GetString(table[opt_num].key);
   1.152 +	*val = m_strtab->GetString(table[opt_num].val);
   1.153 +}
   1.154 +
   1.155 +SMCResult CPluginInfoDatabase::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
   1.156 +{
   1.157 +	if (cur_plugin != -1)
   1.158 +	{
   1.159 +		PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
   1.160 +		if (!in_options)
   1.161 +		{
   1.162 +			if (strcmp(key, "pause") == 0)
   1.163 +			{
   1.164 +				if (strcasecmp(value, "yes") == 0)
   1.165 +				{
   1.166 +					plugin->pause_val = true;
   1.167 +				} 
   1.168 +				else 
   1.169 +				{
   1.170 +					plugin->pause_val = false;
   1.171 +				}
   1.172 +			} 
   1.173 +			else if (strcmp(key, "lifetime") == 0) 
   1.174 +			{
   1.175 +				if (strcasecmp(value, "private") == 0)
   1.176 +				{
   1.177 +					plugin->type_val = PluginType_Private;
   1.178 +				} 
   1.179 +				else if (strcasecmp(value, "mapsync") == 0) 
   1.180 +				{
   1.181 +					plugin->type_val = PluginType_MapUpdated;
   1.182 +				}
   1.183 +				else if (strcasecmp(value, "maponly") == 0) 
   1.184 +				{
   1.185 +					plugin->type_val = PluginType_MapOnly;
   1.186 +				}
   1.187 +				else if (strcasecmp(value, "global") == 0) 
   1.188 +				{
   1.189 +					plugin->type_val = PluginType_Global;
   1.190 +				}
   1.191 +				else 
   1.192 +				{
   1.193 +					return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
   1.194 +				}
   1.195 +			}
   1.196 +			else if (strcmp(key, "blockload") == 0) 
   1.197 +			{
   1.198 +				plugin->blockload_val = true;
   1.199 +			} 
   1.200 +			else 
   1.201 +			{
   1.202 +				return MakeError("Unknown property key: \"%s\"", key);
   1.203 +			}
   1.204 +		}
   1.205 +		else 
   1.206 +		{
   1.207 +			/* Cache every option, valid or not */
   1.208 +			int keyidx = m_strtab->AddString(key);
   1.209 +			int validx = m_strtab->AddString(value);
   1.210 +			PluginOpts *table;
   1.211 +			BaseMemTable *memtab = m_strtab->GetMemTable();
   1.212 +			plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
   1.213 +			if (plugin->opts_num + 1 > plugin->opts_size)
   1.214 +			{
   1.215 +				unsigned int oldsize = plugin->opts_size;
   1.216 +				if (oldsize == 0)
   1.217 +				{
   1.218 +					//right now we don't have many
   1.219 +					plugin->opts_size = 2;
   1.220 +				} 
   1.221 +				else
   1.222 +				{
   1.223 +					plugin->opts_size *= 2;
   1.224 +				}
   1.225 +				int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
   1.226 +				/* in case it resized */
   1.227 +				plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
   1.228 +				if (plugin->optarray != -1)
   1.229 +				{
   1.230 +					void *oldtable = memtab->GetAddress(plugin->optarray);
   1.231 +					memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
   1.232 +				}
   1.233 +				plugin->optarray = newidx;
   1.234 +			}
   1.235 +			else
   1.236 +			{
   1.237 +				table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
   1.238 +			}
   1.239 +			PluginOpts *opt = &table[plugin->opts_num++];
   1.240 +			opt->key = keyidx;
   1.241 +			opt->val = validx;
   1.242 +		}
   1.243 +	}
   1.244 +	else if (in_plugins)
   1.245 +	{
   1.246 +		return MakeError("Unknown property key: \"%s\"", key);
   1.247 +	}
   1.248 +	else 
   1.249 +	{
   1.250 +		/* Ignore anything we don't know about! */
   1.251 +	}
   1.252 +
   1.253 +	return SMCResult_Continue;
   1.254 +}
   1.255 +
   1.256 +SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
   1.257 +{
   1.258 +	if (in_plugins)
   1.259 +	{
   1.260 +		if (cur_plugin != -1)
   1.261 +		{
   1.262 +			if (in_options)
   1.263 +			{
   1.264 +				in_options = false;
   1.265 +			}
   1.266 +			else 
   1.267 +			{
   1.268 +				/* If the plugin is ending, add it to the table */
   1.269 +				BaseMemTable *memtab = m_strtab->GetMemTable();
   1.270 +				int *table;
   1.271 +				if (m_infodb_count + 1 > m_infodb_size)
   1.272 +				{
   1.273 +					unsigned int oldsize = m_infodb_size;
   1.274 +					if (!m_infodb_size)
   1.275 +					{
   1.276 +						m_infodb_size = 8;
   1.277 +					}
   1.278 +					else 
   1.279 +					{
   1.280 +						m_infodb_size *= 2;
   1.281 +					}
   1.282 +					int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
   1.283 +					if (m_infodb != -1)
   1.284 +					{
   1.285 +						void *oldtable = (int *)memtab->GetAddress(m_infodb);
   1.286 +						memcpy(table, oldtable, oldsize * sizeof(int));
   1.287 +					}
   1.288 +					m_infodb = newidx;
   1.289 +				}
   1.290 +				else 
   1.291 +				{
   1.292 +					table = (int *)memtab->GetAddress(m_infodb);
   1.293 +				}
   1.294 +				/* Assign to table and scrap the current plugin */
   1.295 +				table[m_infodb_count++] = cur_plugin;
   1.296 +				cur_plugin = -1;
   1.297 +			}
   1.298 +		}
   1.299 +		else 
   1.300 +		{
   1.301 +			in_plugins = false;
   1.302 +		}
   1.303 +	}
   1.304 +
   1.305 +	return SMCResult_Continue;
   1.306 +}
   1.307 +
   1.308 +SMCResult CPluginInfoDatabase::ReadSMC_NewSection(const SMCStates *states, const char *name)
   1.309 +{
   1.310 +	if (!in_plugins)
   1.311 +	{
   1.312 +		/* If we're not in the main Plugins section, and we don't get it for the name, error out */
   1.313 +		if (strcmp(name, "Plugins") != 0)
   1.314 +		{
   1.315 +			return MakeError("Unknown root section: \"%s\"", name);
   1.316 +		}
   1.317 +		else 
   1.318 +		{
   1.319 +			/* Otherwise set our states */
   1.320 +			in_plugins = true;
   1.321 +			cur_plugin = -1;
   1.322 +			in_options = false;
   1.323 +		}
   1.324 +	}
   1.325 +	else
   1.326 +	{
   1.327 +		if (cur_plugin == -1)
   1.328 +		{
   1.329 +			/* If we get a plugin node and we don't have a current plugin, create a new one */
   1.330 +			PluginSettings *plugin;
   1.331 +			int i_name = m_strtab->AddString(name);
   1.332 +			cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
   1.333 +			plugin->Init();
   1.334 +			plugin->name = i_name;
   1.335 +			in_options = false;
   1.336 +		} 
   1.337 +		else 
   1.338 +		{
   1.339 +			if (!in_options && strcmp(name, "Options") == 0)
   1.340 +			{
   1.341 +				in_options = true;
   1.342 +			}
   1.343 +			else
   1.344 +			{
   1.345 +				return MakeError("Unknown plugin sub-section: \"%s\"", name);
   1.346 +			}
   1.347 +		}
   1.348 +	}
   1.349 +
   1.350 +	return SMCResult_Continue;
   1.351 +}
   1.352 +