core/systems/PluginInfoDatabase.cpp
author David Anderson <dvander@alliedmods.net>
Sun Dec 10 09:19:59 2006 +0000 (2006-12-10)
changeset 203 c7f86f9e6f60
child 205 b766f3af24bd
permissions -rw-r--r--
initial import of plugin database (UNTESTED)
added file pattern matching routine (TESTED)
added memtable caching (UNTESTED)
     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 }
    49 
    50 SMCParseResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
    51 {
    52 	char buffer[512];
    53 	va_list ap;
    54 
    55 	va_start(ap, fmt);
    56 	vsnprintf(buffer, sizeof(buffer), fmt, ap);
    57 	va_end(ap);
    58 
    59 	m_errmsg = m_strtab->AddString(buffer);
    60 
    61 	return SMCParse_HaltFail;
    62 }
    63 
    64 unsigned int CPluginInfoDatabase::GetSettingsNum()
    65 {
    66 	return m_infodb_count;
    67 }
    68 
    69 PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
    70 {
    71 	BaseMemTable *memtab = m_strtab->GetMemTable();
    72 	PluginSettings *table = (PluginSettings *)memtab->GetAddress(m_infodb);
    73 
    74 	if (!table || index >= m_infodb_count)
    75 	{
    76 		return NULL;
    77 	}
    78 
    79 	const char *name = m_strtab->GetString(table[index].name);
    80 
    81 	if (!name)
    82 	{
    83 		return NULL;
    84 	}
    85 
    86 	if (!g_PluginMngr.TestAliasMatch(name, filename))
    87 	{
    88 		return NULL;
    89 	}
    90 
    91 	return &table[index];
    92 }
    93 
    94 void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
    95 {
    96 	PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
    97 	if (!table)
    98 	{
    99 		*key = NULL;
   100 		*val = NULL;
   101 		return;
   102 	}
   103 
   104 	if (opt_num >= settings->opts_num)
   105 	{
   106 		*key = NULL;
   107 		*val = NULL;
   108 		return;
   109 	}
   110 
   111 	*key = m_strtab->GetString(table[opt_num].key);
   112 	*val = m_strtab->GetString(table[opt_num].val);
   113 }
   114 
   115 SMCParseResult CPluginInfoDatabase::ReadSMC_KeyValue(const char *key, 
   116 													 const char *value, 
   117 													 bool key_quotes, 
   118 													 bool value_quotes)
   119 {
   120 	if (cur_plugin != -1)
   121 	{
   122 		PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
   123 		if (!in_options)
   124 		{
   125 			if (strcmp(key, "pause") == 0)
   126 			{
   127 				if (strcasecmp(value, "yes") == 0)
   128 				{
   129 					plugin->pause_val = true;
   130 				} else {
   131 					plugin->pause_val = false;
   132 				}
   133 			} else if (strcmp(key, "lifetime") == 0) {
   134 				if (strcasecmp(value, "private") == 0)
   135 				{
   136 					plugin->type_val = PluginType_Private;
   137 				} else if (strcasecmp(value, "mapsync") == 0) {
   138 					plugin->type_val = PluginType_MapUpdated;
   139 				} else if (strcasecmp(value, "maponly") == 0) {
   140 					plugin->type_val = PluginType_MapOnly;
   141 				} else if (strcasecmp(value, "global") == 0) {
   142 					plugin->type_val = PluginType_Global;
   143 				} else {
   144 					return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
   145 				}
   146 			} else {
   147 				return MakeError("Unknown property key: \"%s\"", key);
   148 			}
   149 		} else {
   150 			/* Cache every option, valid or not */
   151 			int keyidx = m_strtab->AddString(key);
   152 			int validx = m_strtab->AddString(value);
   153 			PluginOpts *table;
   154 			BaseMemTable *memtab = m_strtab->GetMemTable();
   155 			if (plugin->opts_num + 1 > plugin->opts_size)
   156 			{
   157 				unsigned int oldsize = plugin->opts_size;
   158 				if (oldsize == 0)
   159 				{
   160 					//right now we don't have many
   161 					plugin->opts_size = 2;
   162 				} else {
   163 					plugin->opts_size *= 2;
   164 				}
   165 				int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
   166 				if (plugin->optarray != -1)
   167 				{
   168 					void *oldtable = memtab->GetAddress(plugin->optarray);
   169 					memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
   170 				}
   171 				plugin->optarray = newidx;
   172 			} else {
   173 				table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
   174 			}
   175 			PluginOpts *opt = &table[plugin->opts_num++];
   176 			opt->key = keyidx;
   177 			opt->val = validx;
   178 		}
   179 	} else if (in_plugins) {
   180 		return MakeError("Unknown property key: \"%s\"", key);
   181 	} else {
   182 		/* Ignore anything we don't know about! */
   183 	}
   184 
   185 	return SMCParse_Continue;
   186 }
   187 
   188 SMCParseResult CPluginInfoDatabase::ReadSMC_LeavingSection()
   189 {
   190 	if (in_plugins)
   191 	{
   192 		if (cur_plugin == -1)
   193 		{
   194 			if (in_options)
   195 			{
   196 				in_options = false;
   197 			} else {
   198 				/* If the plugin is ending, add it to the table */
   199 				BaseMemTable *memtab = m_strtab->GetMemTable();
   200 				int *table;
   201 				if (m_infodb_count + 1 > m_infodb_size)
   202 				{
   203 					unsigned int oldsize = m_infodb_size;
   204 					if (!m_infodb_size)
   205 					{
   206 						m_infodb_size = 8;
   207 					} else {
   208 						m_infodb_size *= 2;
   209 					}
   210 					int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
   211 					if (m_infodb != -1)
   212 					{
   213 						void *oldtable = (int *)memtab->GetAddress(m_infodb);
   214 						memcpy(table, oldtable, oldsize * sizeof(int));
   215 					}
   216 					m_infodb = newidx;
   217 				} else {
   218 					table = (int *)memtab->GetAddress(m_infodb);
   219 				}
   220 				/* Assign to table and scrap the current plugin */
   221 				table[m_infodb_count++] = cur_plugin;
   222 				cur_plugin = -1;
   223 			}
   224 		} else {
   225 			in_plugins = false;
   226 		}
   227 	}
   228 
   229 	return SMCParse_Continue;
   230 }
   231 
   232 SMCParseResult CPluginInfoDatabase::ReadSMC_NewSection(const char *name, bool opt_quotes)
   233 {
   234 	if (!in_plugins)
   235 	{
   236 		/* If we're not in the main Plugins section, and we don't get it for the name, error out */
   237 		if (strcmp(name, "Plugins") != 0)
   238 		{
   239 			return MakeError("Unknown root section: \"%s\"", name);
   240 		} else {
   241 			/* Otherwise set our states */
   242 			in_plugins = true;
   243 			cur_plugin = -1;
   244 			in_options = false;
   245 		}
   246 	} else {
   247 		if (cur_plugin == -1)
   248 		{
   249 			/* If we get a plugin node and we don't have a current plugin, create a new one */
   250 			PluginSettings *plugin;
   251 			cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
   252 			plugin->Init();
   253 			plugin->name = m_strtab->AddString(name);
   254 			in_options = false;
   255 		} else {
   256 			if (!in_options && strcmp(name, "Options") == 0)
   257 			{
   258 				in_options = true;
   259 			} else {
   260 				return MakeError("Unknown plugin sub-section: \"%s\"", name);
   261 			}
   262 		}
   263 	}
   264 
   265 	return SMCParse_Continue;
   266 }