core/systems/PluginInfoDatabase.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sun Jan 07 01:30:28 2007 +0000 (2007-01-07)
changeset 274 959c85596341
parent 264 31c842fad591
child 293 83b5a2d33e3d
permissions -rw-r--r--
Added a bunch of new file natives.
Fixed possible corruption in snprintf when input buffer was bigger than output buffer and relaying on its retval.
Fixed all cases when the above situation happened.
Fixed _PrintToHL2Log not taking va_list in.
     1 #include <stdarg.h>
     2 #include <string.h>
     3 #include "PluginInfoDatabase.h"
     4 #include "PluginSys.h"
     5 
     6 void PluginSettings::Init()
     7 {
     8 	name = -1;
     9 	pause_val = false;
    10 	type_val = PluginType_MapUpdated;
    11 	optarray = -1;
    12 	opts_num = 0;
    13 	opts_size = 0;
    14 }
    15 
    16 /**
    17  * :TODO: write the logger, make these errors log instead of being static
    18  * NOTE: once we do that, we will have to change some code to ignore sections
    19  */
    20 
    21 CPluginInfoDatabase::CPluginInfoDatabase()
    22 {
    23 	m_strtab = NULL;
    24 	m_infodb_count = 0;
    25 	m_infodb_size = 0;
    26 	m_infodb = -1;
    27 }
    28 
    29 CPluginInfoDatabase::~CPluginInfoDatabase()
    30 {
    31 	delete m_strtab;
    32 }
    33 
    34 void CPluginInfoDatabase::ReadSMC_ParseStart()
    35 {
    36 	/* Create or reset our string table */
    37 	if (m_strtab)
    38 	{
    39 		m_strtab->Reset();
    40 	} else {
    41 		m_strtab = new BaseStringTable(1024);
    42 	}
    43 
    44 	/* Set our internal states to the beginning */
    45 	in_plugins = false;
    46 	cur_plugin = -1;
    47 	in_options = false;
    48 	m_infodb_size = 0;
    49 	m_infodb_count = 0;
    50 	m_infodb = -1;
    51 }
    52 
    53 SMCParseResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
    54 {
    55 	char buffer[512];
    56 	va_list ap;
    57 
    58 	va_start(ap, fmt);
    59 	vsnprintf(buffer, sizeof(buffer), fmt, ap);
    60 	va_end(ap);
    61 
    62 	m_errmsg = m_strtab->AddString(buffer);
    63 
    64 	return SMCParse_HaltFail;
    65 }
    66 
    67 unsigned int CPluginInfoDatabase::GetSettingsNum()
    68 {
    69 	return m_infodb_count;
    70 }
    71 
    72 PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
    73 {
    74 	BaseMemTable *memtab = m_strtab->GetMemTable();
    75 	int *table = (int *)memtab->GetAddress(m_infodb);
    76 
    77 	if (!table || index >= m_infodb_count)
    78 	{
    79 		return NULL;
    80 	}
    81 
    82 	PluginSettings *plugin = (PluginSettings *)memtab->GetAddress(table[index]);
    83 
    84 	const char *name = m_strtab->GetString(plugin->name);
    85 
    86 	if (!name)
    87 	{
    88 		return NULL;
    89 	}
    90 
    91 	if (!g_PluginSys.TestAliasMatch(name, filename))
    92 	{
    93 		return NULL;
    94 	}
    95 
    96 	return plugin;
    97 }
    98 
    99 void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
   100 {
   101 	PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
   102 	if (!table)
   103 	{
   104 		*key = NULL;
   105 		*val = NULL;
   106 		return;
   107 	}
   108 
   109 	if (opt_num >= settings->opts_num)
   110 	{
   111 		*key = NULL;
   112 		*val = NULL;
   113 		return;
   114 	}
   115 
   116 	*key = m_strtab->GetString(table[opt_num].key);
   117 	*val = m_strtab->GetString(table[opt_num].val);
   118 }
   119 
   120 SMCParseResult CPluginInfoDatabase::ReadSMC_KeyValue(const char *key, 
   121 													 const char *value, 
   122 													 bool key_quotes, 
   123 													 bool value_quotes)
   124 {
   125 	if (cur_plugin != -1)
   126 	{
   127 		PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
   128 		if (!in_options)
   129 		{
   130 			if (strcmp(key, "pause") == 0)
   131 			{
   132 				if (strcasecmp(value, "yes") == 0)
   133 				{
   134 					plugin->pause_val = true;
   135 				} else {
   136 					plugin->pause_val = false;
   137 				}
   138 			} else if (strcmp(key, "lifetime") == 0) {
   139 				if (strcasecmp(value, "private") == 0)
   140 				{
   141 					plugin->type_val = PluginType_Private;
   142 				} else if (strcasecmp(value, "mapsync") == 0) {
   143 					plugin->type_val = PluginType_MapUpdated;
   144 				} else if (strcasecmp(value, "maponly") == 0) {
   145 					plugin->type_val = PluginType_MapOnly;
   146 				} else if (strcasecmp(value, "global") == 0) {
   147 					plugin->type_val = PluginType_Global;
   148 				} else {
   149 					return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
   150 				}
   151 			} else {
   152 				return MakeError("Unknown property key: \"%s\"", key);
   153 			}
   154 		} else {
   155 			/* Cache every option, valid or not */
   156 			int keyidx = m_strtab->AddString(key);
   157 			int validx = m_strtab->AddString(value);
   158 			PluginOpts *table;
   159 			BaseMemTable *memtab = m_strtab->GetMemTable();
   160 			if (plugin->opts_num + 1 > plugin->opts_size)
   161 			{
   162 				unsigned int oldsize = plugin->opts_size;
   163 				if (oldsize == 0)
   164 				{
   165 					//right now we don't have many
   166 					plugin->opts_size = 2;
   167 				} else {
   168 					plugin->opts_size *= 2;
   169 				}
   170 				int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
   171 				if (plugin->optarray != -1)
   172 				{
   173 					void *oldtable = memtab->GetAddress(plugin->optarray);
   174 					memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
   175 				}
   176 				plugin->optarray = newidx;
   177 			} else {
   178 				table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
   179 			}
   180 			PluginOpts *opt = &table[plugin->opts_num++];
   181 			opt->key = keyidx;
   182 			opt->val = validx;
   183 		}
   184 	} else if (in_plugins) {
   185 		return MakeError("Unknown property key: \"%s\"", key);
   186 	} else {
   187 		/* Ignore anything we don't know about! */
   188 	}
   189 
   190 	return SMCParse_Continue;
   191 }
   192 
   193 SMCParseResult CPluginInfoDatabase::ReadSMC_LeavingSection()
   194 {
   195 	if (in_plugins)
   196 	{
   197 		if (cur_plugin != -1)
   198 		{
   199 			if (in_options)
   200 			{
   201 				in_options = false;
   202 			} else {
   203 				/* If the plugin is ending, add it to the table */
   204 				BaseMemTable *memtab = m_strtab->GetMemTable();
   205 				int *table;
   206 				if (m_infodb_count + 1 > m_infodb_size)
   207 				{
   208 					unsigned int oldsize = m_infodb_size;
   209 					if (!m_infodb_size)
   210 					{
   211 						m_infodb_size = 8;
   212 					} else {
   213 						m_infodb_size *= 2;
   214 					}
   215 					int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
   216 					if (m_infodb != -1)
   217 					{
   218 						void *oldtable = (int *)memtab->GetAddress(m_infodb);
   219 						memcpy(table, oldtable, oldsize * sizeof(int));
   220 					}
   221 					m_infodb = newidx;
   222 				} else {
   223 					table = (int *)memtab->GetAddress(m_infodb);
   224 				}
   225 				/* Assign to table and scrap the current plugin */
   226 				table[m_infodb_count++] = cur_plugin;
   227 				cur_plugin = -1;
   228 			}
   229 		} else {
   230 			in_plugins = false;
   231 		}
   232 	}
   233 
   234 	return SMCParse_Continue;
   235 }
   236 
   237 SMCParseResult CPluginInfoDatabase::ReadSMC_NewSection(const char *name, bool opt_quotes)
   238 {
   239 	if (!in_plugins)
   240 	{
   241 		/* If we're not in the main Plugins section, and we don't get it for the name, error out */
   242 		if (strcmp(name, "Plugins") != 0)
   243 		{
   244 			return MakeError("Unknown root section: \"%s\"", name);
   245 		} else {
   246 			/* Otherwise set our states */
   247 			in_plugins = true;
   248 			cur_plugin = -1;
   249 			in_options = false;
   250 		}
   251 	} else {
   252 		if (cur_plugin == -1)
   253 		{
   254 			/* If we get a plugin node and we don't have a current plugin, create a new one */
   255 			PluginSettings *plugin;
   256 			cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
   257 			plugin->Init();
   258 			plugin->name = m_strtab->AddString(name);
   259 			in_options = false;
   260 		} else {
   261 			if (!in_options && strcmp(name, "Options") == 0)
   262 			{
   263 				in_options = true;
   264 			} else {
   265 				return MakeError("Unknown plugin sub-section: \"%s\"", name);
   266 			}
   267 		}
   268 	}
   269 
   270 	return SMCParse_Continue;
   271 }