initial import of plugin database (UNTESTED)

added file pattern matching routine (TESTED)
added memtable caching (UNTESTED)

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40208
This commit is contained in:
David Anderson
2006-12-10 09:19:59 +00:00
parent f807575429
commit a1e58aa9ef
9 changed files with 764 additions and 7 deletions
+223 -3
View File
@@ -2,6 +2,7 @@
#include "PluginSys.h"
#include "LibrarySys.h"
#include "sourcemm_api.h"
#include "CTextParsers.h"
CPluginManager g_PluginMngr;
@@ -288,9 +289,19 @@ void CPluginManager::CPluginIterator::Reset()
* PLUGIN MANAGER *
******************/
void CPluginManager::RefreshOrLoadPlugins(const char *basedir)
void CPluginManager::RefreshOrLoadPlugins(const char *config, const char *basedir)
{
IDirectory *dir = g_LibSys.OpenDirectory(basedir);
/* First read in the database of plugin settings */
SMCParseError err;
unsigned int line, col;
if ((err=g_TextParse.ParseFile_SMC(config, &m_PluginInfo, &line, &col)) != SMCParse_Okay)
{
/* :TODO: log the error, don't bail out though */
}
//:TODO: move this to a separate recursive function and do stuff
/*IDirectory *dir = g_LibSys.OpenDirectory(basedir);
while (dir->MoreFiles())
{
if (dir->IsEntryDirectory() && (strcmp(dir->GetEntryName(), "disabled") != 0))
@@ -300,7 +311,7 @@ void CPluginManager::RefreshOrLoadPlugins(const char *basedir)
RefreshOrLoadPlugins(basedir);
}
}
g_LibSys.CloseDirectory(dir);
g_LibSys.CloseDirectory(dir);*/
}
IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t err_max)
@@ -446,6 +457,215 @@ CFunction *CPluginManager::GetFunctionFromPool(funcid_t f, CPlugin *plugin)
}
}
bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath)
{
/* As an optimization, we do not call strlen, but compute the length in the first pass */
size_t alias_len = 0;
size_t local_len = 0;
const char *ptr = alias;
unsigned int alias_explicit_paths = 0;
unsigned int alias_path_end = 0;
while (*ptr != '\0')
{
if (*ptr == '\\' || *ptr == '/')
{
alias_explicit_paths++;
alias_path_end = alias_len;
}
alias_len++;
ptr++;
}
if (alias_path_end == alias_len - 1)
{
/* Trailing slash is totally invalid here */
return false;
}
ptr = localpath;
unsigned int local_explicit_paths = 0;
unsigned int local_path_end = 0;
while (*ptr != '\0')
{
if (*ptr == '\\' || *ptr == '/')
{
local_explicit_paths++;
local_path_end = local_len;
}
local_len++;
ptr++;
}
/* If the alias has more explicit paths than the real path,
* no match will be possible.
*/
if (alias_explicit_paths > local_explicit_paths)
{
return false;
}
if (alias_explicit_paths)
{
/* We need to find if the paths match now. For example, these should all match:
* csdm csdm
* csdm optional/csdm
* csdm/ban optional/crab/csdm/ban
*/
const char *aliasptr = alias;
const char *localptr = localpath;
bool match = true;
do
{
if (*aliasptr != *localptr)
{
/* We have to knock one path off */
local_explicit_paths--;
if (alias_explicit_paths > local_explicit_paths)
{
/* Skip out if we're gonna have an impossible match */
return false;
}
/* Eat up localptr tokens until we get a result */
while (((localptr - localpath) < (int)local_path_end)
&& *localptr != '/'
&& *localptr != '\\')
{
localptr++;
}
/* Check if we hit the end of our searchable area.
* This probably isn't possible because of the path
* count check, but it's a good idea anyway.
*/
if ((localptr - localpath) >= (int)local_path_end)
{
return false;
} else {
/* Consume the slash token */
localptr++;
}
/* Reset the alias pointer so we can continue consuming */
aliasptr = alias;
match = false;
continue;
}
/* Note:
* This is safe because if localptr terminates early, aliasptr will too
*/
do
{
/* We should never reach the end of the string because of this check. */
bool aliasend = (aliasptr - alias) > (int)alias_path_end;
bool localend = (localptr - localpath) > (int)local_path_end;
if (aliasend || localend)
{
if (aliasend && localend)
{
/* we matched, and we can break out now */
match = true;
break;
}
/* Otherwise, we've hit the end somehow and rest won't match up. Break out. */
match = false;
break;
}
/* If we got here, it's safe to compare the next two tokens */
if (*localptr != *aliasptr)
{
match = false;
break;
}
localptr++;
aliasptr++;
} while (true);
} while (!match);
}
/* If we got here, it's time to compare filenames */
const char *aliasptr = alias;
const char *localptr = localpath;
if (alias_explicit_paths)
{
aliasptr = &alias[alias_path_end + 1];
}
if (local_explicit_paths)
{
localptr = &localpath[local_path_end + 1];
}
while (true)
{
if (*aliasptr == '*')
{
/* First, see if this is the last character */
if (aliasptr - alias == alias_len - 1)
{
/* If so, there's no need to match anything else */
return true;
}
/* Otherwise, we need to search for an appropriate matching sequence in local.
* Note that we only need to search up to the next asterisk.
*/
aliasptr++;
bool match = true;
const char *local_orig = localptr;
do
{
match = true;
while (*aliasptr != '\0' && *aliasptr != '*')
{
/* Since aliasptr is never '\0', localptr hitting the end will fail */
if (*aliasptr != *localptr)
{
match = false;
break;
}
aliasptr++;
localptr++;
}
if (!match)
{
/* If we didn't get a match, we need to advance the search stream.
* This will let us skip tokens while still searching for another match.
*/
localptr = ++local_orig;
/* Make sure we don't go out of bounds */
if (*localptr == '\0')
{
break;
}
}
} while (!match);
if (!match)
{
return false;
} else {
/* If we got a match, move on to the next token */
continue;
}
} else if (*aliasptr == '\0') {
if (*localptr == '\0'
||
strcmp(localptr, ".smx") == 0)
{
return true;
} else {
return false;
}
} else if (*aliasptr != *localptr) {
return false;
}
aliasptr++;
localptr++;
}
return true;
}
CPluginManager::~CPluginManager()
{
//:TODO: we need a good way to free what we're holding