core/systems/PluginInfoDatabase.cpp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1231 17badaf66ce4
child 1436 38994f8f28c3
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

(This day shall henceforth be known as the Eighty Column Massacre of '07)
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 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@203
    32
#include <stdarg.h>
dvander@203
    33
#include <string.h>
dvander@203
    34
#include "PluginInfoDatabase.h"
dvander@203
    35
#include "PluginSys.h"
dvander@203
    36
dvander@203
    37
void PluginSettings::Init()
dvander@203
    38
{
dvander@203
    39
	name = -1;
dvander@203
    40
	pause_val = false;
dvander@203
    41
	type_val = PluginType_MapUpdated;
dvander@203
    42
	optarray = -1;
dvander@203
    43
	opts_num = 0;
dvander@203
    44
	opts_size = 0;
dvander@203
    45
}
dvander@203
    46
dvander@203
    47
/**
dvander@203
    48
 * :TODO: write the logger, make these errors log instead of being static
dvander@203
    49
 * NOTE: once we do that, we will have to change some code to ignore sections
dvander@203
    50
 */
dvander@203
    51
dvander@203
    52
CPluginInfoDatabase::CPluginInfoDatabase()
dvander@203
    53
{
dvander@203
    54
	m_strtab = NULL;
dvander@203
    55
	m_infodb_count = 0;
dvander@203
    56
	m_infodb_size = 0;
dvander@203
    57
	m_infodb = -1;
dvander@203
    58
}
dvander@203
    59
dvander@203
    60
CPluginInfoDatabase::~CPluginInfoDatabase()
dvander@203
    61
{
dvander@203
    62
	delete m_strtab;
dvander@203
    63
}
dvander@203
    64
dvander@203
    65
void CPluginInfoDatabase::ReadSMC_ParseStart()
dvander@203
    66
{
dvander@203
    67
	/* Create or reset our string table */
dvander@203
    68
	if (m_strtab)
dvander@203
    69
	{
dvander@203
    70
		m_strtab->Reset();
dvander@203
    71
	} else {
dvander@203
    72
		m_strtab = new BaseStringTable(1024);
dvander@203
    73
	}
dvander@203
    74
dvander@203
    75
	/* Set our internal states to the beginning */
dvander@203
    76
	in_plugins = false;
dvander@203
    77
	cur_plugin = -1;
dvander@203
    78
	in_options = false;
dvander@264
    79
	m_infodb_size = 0;
dvander@264
    80
	m_infodb_count = 0;
dvander@264
    81
	m_infodb = -1;
dvander@203
    82
}
dvander@203
    83
dvander@203
    84
SMCParseResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
dvander@203
    85
{
dvander@203
    86
	char buffer[512];
dvander@203
    87
	va_list ap;
dvander@203
    88
dvander@203
    89
	va_start(ap, fmt);
dvander@203
    90
	vsnprintf(buffer, sizeof(buffer), fmt, ap);
dvander@203
    91
	va_end(ap);
dvander@203
    92
dvander@203
    93
	m_errmsg = m_strtab->AddString(buffer);
dvander@203
    94
dvander@203
    95
	return SMCParse_HaltFail;
dvander@203
    96
}
dvander@203
    97
dvander@203
    98
unsigned int CPluginInfoDatabase::GetSettingsNum()
dvander@203
    99
{
dvander@203
   100
	return m_infodb_count;
dvander@203
   101
}
dvander@203
   102
dvander@203
   103
PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
dvander@203
   104
{
dvander@203
   105
	BaseMemTable *memtab = m_strtab->GetMemTable();
dvander@205
   106
	int *table = (int *)memtab->GetAddress(m_infodb);
dvander@203
   107
dvander@203
   108
	if (!table || index >= m_infodb_count)
dvander@203
   109
	{
dvander@203
   110
		return NULL;
dvander@203
   111
	}
dvander@203
   112
dvander@205
   113
	PluginSettings *plugin = (PluginSettings *)memtab->GetAddress(table[index]);
dvander@205
   114
dvander@205
   115
	const char *name = m_strtab->GetString(plugin->name);
dvander@203
   116
dvander@203
   117
	if (!name)
dvander@203
   118
	{
dvander@203
   119
		return NULL;
dvander@203
   120
	}
dvander@203
   121
dvander@211
   122
	if (!g_PluginSys.TestAliasMatch(name, filename))
dvander@203
   123
	{
dvander@203
   124
		return NULL;
dvander@203
   125
	}
dvander@203
   126
dvander@205
   127
	return plugin;
dvander@203
   128
}
dvander@203
   129
dvander@203
   130
void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
dvander@203
   131
{
dvander@203
   132
	PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
dvander@203
   133
	if (!table)
dvander@203
   134
	{
dvander@203
   135
		*key = NULL;
dvander@203
   136
		*val = NULL;
dvander@203
   137
		return;
dvander@203
   138
	}
dvander@203
   139
dvander@203
   140
	if (opt_num >= settings->opts_num)
dvander@203
   141
	{
dvander@203
   142
		*key = NULL;
dvander@203
   143
		*val = NULL;
dvander@203
   144
		return;
dvander@203
   145
	}
dvander@203
   146
dvander@203
   147
	*key = m_strtab->GetString(table[opt_num].key);
dvander@203
   148
	*val = m_strtab->GetString(table[opt_num].val);
dvander@203
   149
}
dvander@203
   150
dvander@203
   151
SMCParseResult CPluginInfoDatabase::ReadSMC_KeyValue(const char *key, 
dvander@203
   152
													 const char *value, 
dvander@203
   153
													 bool key_quotes, 
dvander@203
   154
													 bool value_quotes)
dvander@203
   155
{
dvander@203
   156
	if (cur_plugin != -1)
dvander@203
   157
	{
dvander@203
   158
		PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
dvander@203
   159
		if (!in_options)
dvander@203
   160
		{
dvander@203
   161
			if (strcmp(key, "pause") == 0)
dvander@203
   162
			{
dvander@203
   163
				if (strcasecmp(value, "yes") == 0)
dvander@203
   164
				{
dvander@203
   165
					plugin->pause_val = true;
dvander@203
   166
				} else {
dvander@203
   167
					plugin->pause_val = false;
dvander@203
   168
				}
dvander@203
   169
			} else if (strcmp(key, "lifetime") == 0) {
dvander@203
   170
				if (strcasecmp(value, "private") == 0)
dvander@203
   171
				{
dvander@203
   172
					plugin->type_val = PluginType_Private;
dvander@203
   173
				} else if (strcasecmp(value, "mapsync") == 0) {
dvander@203
   174
					plugin->type_val = PluginType_MapUpdated;
dvander@203
   175
				} else if (strcasecmp(value, "maponly") == 0) {
dvander@203
   176
					plugin->type_val = PluginType_MapOnly;
dvander@203
   177
				} else if (strcasecmp(value, "global") == 0) {
dvander@203
   178
					plugin->type_val = PluginType_Global;
dvander@203
   179
				} else {
dvander@203
   180
					return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
dvander@203
   181
				}
dvander@203
   182
			} else {
dvander@203
   183
				return MakeError("Unknown property key: \"%s\"", key);
dvander@203
   184
			}
dvander@203
   185
		} else {
dvander@203
   186
			/* Cache every option, valid or not */
dvander@203
   187
			int keyidx = m_strtab->AddString(key);
dvander@203
   188
			int validx = m_strtab->AddString(value);
dvander@203
   189
			PluginOpts *table;
dvander@203
   190
			BaseMemTable *memtab = m_strtab->GetMemTable();
dvander@203
   191
			if (plugin->opts_num + 1 > plugin->opts_size)
dvander@203
   192
			{
dvander@203
   193
				unsigned int oldsize = plugin->opts_size;
dvander@203
   194
				if (oldsize == 0)
dvander@203
   195
				{
dvander@203
   196
					//right now we don't have many
dvander@203
   197
					plugin->opts_size = 2;
dvander@203
   198
				} else {
dvander@203
   199
					plugin->opts_size *= 2;
dvander@203
   200
				}
dvander@203
   201
				int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
dvander@293
   202
				/* in case it resized */
dvander@293
   203
				plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
dvander@203
   204
				if (plugin->optarray != -1)
dvander@203
   205
				{
dvander@203
   206
					void *oldtable = memtab->GetAddress(plugin->optarray);
dvander@203
   207
					memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
dvander@203
   208
				}
dvander@203
   209
				plugin->optarray = newidx;
dvander@203
   210
			} else {
dvander@203
   211
				table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
dvander@203
   212
			}
dvander@203
   213
			PluginOpts *opt = &table[plugin->opts_num++];
dvander@203
   214
			opt->key = keyidx;
dvander@203
   215
			opt->val = validx;
dvander@203
   216
		}
dvander@203
   217
	} else if (in_plugins) {
dvander@203
   218
		return MakeError("Unknown property key: \"%s\"", key);
dvander@203
   219
	} else {
dvander@203
   220
		/* Ignore anything we don't know about! */
dvander@203
   221
	}
dvander@203
   222
dvander@203
   223
	return SMCParse_Continue;
dvander@203
   224
}
dvander@203
   225
dvander@203
   226
SMCParseResult CPluginInfoDatabase::ReadSMC_LeavingSection()
dvander@203
   227
{
dvander@203
   228
	if (in_plugins)
dvander@203
   229
	{
dvander@205
   230
		if (cur_plugin != -1)
dvander@203
   231
		{
dvander@203
   232
			if (in_options)
dvander@203
   233
			{
dvander@203
   234
				in_options = false;
dvander@203
   235
			} else {
dvander@203
   236
				/* If the plugin is ending, add it to the table */
dvander@203
   237
				BaseMemTable *memtab = m_strtab->GetMemTable();
dvander@203
   238
				int *table;
dvander@203
   239
				if (m_infodb_count + 1 > m_infodb_size)
dvander@203
   240
				{
dvander@203
   241
					unsigned int oldsize = m_infodb_size;
dvander@203
   242
					if (!m_infodb_size)
dvander@203
   243
					{
dvander@203
   244
						m_infodb_size = 8;
dvander@203
   245
					} else {
dvander@203
   246
						m_infodb_size *= 2;
dvander@203
   247
					}
dvander@203
   248
					int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
dvander@203
   249
					if (m_infodb != -1)
dvander@203
   250
					{
dvander@203
   251
						void *oldtable = (int *)memtab->GetAddress(m_infodb);
dvander@203
   252
						memcpy(table, oldtable, oldsize * sizeof(int));
dvander@203
   253
					}
dvander@203
   254
					m_infodb = newidx;
dvander@203
   255
				} else {
dvander@203
   256
					table = (int *)memtab->GetAddress(m_infodb);
dvander@203
   257
				}
dvander@203
   258
				/* Assign to table and scrap the current plugin */
dvander@203
   259
				table[m_infodb_count++] = cur_plugin;
dvander@203
   260
				cur_plugin = -1;
dvander@203
   261
			}
dvander@203
   262
		} else {
dvander@203
   263
			in_plugins = false;
dvander@203
   264
		}
dvander@203
   265
	}
dvander@203
   266
dvander@203
   267
	return SMCParse_Continue;
dvander@203
   268
}
dvander@203
   269
dvander@203
   270
SMCParseResult CPluginInfoDatabase::ReadSMC_NewSection(const char *name, bool opt_quotes)
dvander@203
   271
{
dvander@203
   272
	if (!in_plugins)
dvander@203
   273
	{
dvander@203
   274
		/* If we're not in the main Plugins section, and we don't get it for the name, error out */
dvander@203
   275
		if (strcmp(name, "Plugins") != 0)
dvander@203
   276
		{
dvander@203
   277
			return MakeError("Unknown root section: \"%s\"", name);
dvander@203
   278
		} else {
dvander@203
   279
			/* Otherwise set our states */
dvander@203
   280
			in_plugins = true;
dvander@203
   281
			cur_plugin = -1;
dvander@203
   282
			in_options = false;
dvander@203
   283
		}
dvander@203
   284
	} else {
dvander@203
   285
		if (cur_plugin == -1)
dvander@203
   286
		{
dvander@203
   287
			/* If we get a plugin node and we don't have a current plugin, create a new one */
dvander@203
   288
			PluginSettings *plugin;
dvander@203
   289
			cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
dvander@203
   290
			plugin->Init();
dvander@203
   291
			plugin->name = m_strtab->AddString(name);
dvander@203
   292
			in_options = false;
dvander@203
   293
		} else {
dvander@203
   294
			if (!in_options && strcmp(name, "Options") == 0)
dvander@203
   295
			{
dvander@203
   296
				in_options = true;
dvander@203
   297
			} else {
dvander@203
   298
				return MakeError("Unknown plugin sub-section: \"%s\"", name);
dvander@203
   299
			}
dvander@203
   300
		}
dvander@203
   301
	}
dvander@203
   302
dvander@203
   303
	return SMCParse_Continue;
dvander@203
   304
}