Resolving a string to a function call in C++

Started by
4 comments, last by kodbert 21 years, 1 month ago
I''m having trouble coming up with an efficient way of taking a string, for example "setgravity 2" and converting it to a call for the function "setgravity" with an argument of the value 2. Ive been thinking about using the STL "map" or a hash-table, but i feel they don''t offer the speed i am after. Any ideas ? Thanks !
This is my signature.
Advertisement
std::map of strings to function pointers? if std::map isn''t fast enough, there probably isn''t anything fast enough to map strings to anything. how many of these functions are you after? anything less than 50 should be plenty fast. especially because it sounds like you are after a console type thing, which isn''t going to be calling functions like that much.
checkout std::hashmap, which is not technically a standard class, but which most decent STL implementations implement.

How appropriate. You fight like a cow.
quote:Original post by billybob
std::map of strings to function pointers? if std::map isn''t fast enough, there probably isn''t anything fast enough to map strings to anything. how many of these functions are you after? anything less than 50 should be plenty fast. especially because it sounds like you are after a console type thing, which isn''t going to be calling functions like that much.


This is exactly what I do!


  #include "CPluginBase.h"#include <map>#include <vector>#include <string>using namespace std;class CKeywordParser  {	CKeywordParser();public:	BOOL IsKeyword(string Keyword);	BOOL ProcessLine(string Line);	CKeywordParser* GetObject();	void AddKeyWord(string KeyWord, CPluginBase* Plugin);	BOOL ProcessKeyWord(string KeyWord, string params);		virtual ~CKeywordParser();	map<string,CPluginBase*> KeyWordTable;};//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CKeywordParser::CKeywordParser(){}CKeywordParser::~CKeywordParser(){	KeyWordTable.clear();}BOOL CKeywordParser::ProcessKeyWord(string KeyWord, string params){	//Singleton Logger	CLogger* Logger = NULL;	Logger = Logger->GetObject();	map<string,CPluginBase*>::iterator itr;	itr = KeyWordTable.find(KeyWord);	if( itr == KeyWordTable.end())	{		Logger->Warning("(CKeyWordParser): KeyWord Not Found");		return FALSE;	}	Logger->Report((itr->second)->ProcessKeyWord(KeyWord, params));	return TRUE;}void CKeywordParser::AddKeyWord(string KeyWord, CPluginBase *Plugin){	char LowerCase[256];	strcpy(LowerCase,KeyWord.c_str());	strlwr(LowerCase);	KeyWordTable.insert(pair<string,CPluginBase*>(LowerCase,Plugin));}CKeywordParser* CKeywordParser::GetObject(){	static CKeywordParser obj;	return &obj;}BOOL CKeywordParser::ProcessLine(string Line){	char TokenString[256] = {0};	char KeyWord[64] = {0};	char* token = NULL;	char seps[]   = " ()=,;:\"[]<>/\\|\r\t\n";	string parameters;	strcpy(TokenString,Line.c_str());	token = strtok(TokenString,seps);	strcpy(KeyWord,token);	token = strtok(NULL,seps);	while(token != NULL)	{		parameters += token;		parameters += " ";	}	return ProcessKeyWord(KeyWord,parameters);}//Determines if we struck a keywordBOOL CKeywordParser::IsKeyword(string Keyword){	//Singleton Logger	CLogger* Logger = NULL;	Logger = Logger->GetObject();	map<string,CPluginBase*>::iterator itr;	itr = KeyWordTable.find(Keyword);	if( itr == KeyWordTable.end())	{		return FALSE;	}	return TRUE;}  


However, this code uses polymorphism (the base class) to pass the keyword and the parameters to the appropiate class. If you were using a C style architecture, you would replace all of the instances of CPluginBase* with this:

  //Define teh type needed to store in the map#typedef string (*ParseFunction)(string) //map would look like:map<string,ParseFunction>KeyWordTable;//ProcessBOOL CKeywordParser::ProcessKeyWord(string KeyWord, string params){	map<string,ParseFunction>::iterator itr;	itr = KeyWordTable.find(KeyWord);	if( itr == KeyWordTable.end())	{		Logger->Warning("(CKeyWordParser): KeyWord Not Found");		return FALSE;	}else{ itr->second(params);}}void CKeywordParser::AddKeyWord(string KeyWord, ParseFunction Plugin){	char LowerCase[256];	strcpy(LowerCase,KeyWord.c_str());	strlwr(LowerCase);	KeyWordTable.insert(pair<string,ParseFunction>(LowerCase,Plugin));}//Usage://Define the function globally to change gravityvoid SetGravity(string parameter){//whatever}//Singleton ParserCKeywordparser* parser = NULL;parser = parser->GetObject();//add keywordpaser->AddKeyWord("setgravity", SetGravity);  


That above assumes you use a C style coding and each keyword has it''s own specific GLOBAL processing function.

one thing that might help AP, is to do typedef std::map[string, CPluginBase*] PluginTable. that way you don't have to do std::map[...,...] everywhere you want an iterator or something like that. just PluginTable::iterator.

edit: if you do it at class scope, it won't affect anything else either

edit again: and replace [ and ] with < and >

[edited by - billybob on March 16, 2003 9:34:52 PM]
quote:Original post by billybob
one thing that might help AP, is to do typedef std::map[string, CPluginBase*] PluginTable. that way you don''t have to do std::map[...,...] everywhere you want an iterator or something like that. just PluginTable::iterator.


Thanks for the tip! Those code snippets were actually from a test application I wrote before I integrated it into the actual code base.

I have certain conventions I''m required to adhere to, but that''s a great tip. I''ll see if I can run it by the lead.

This topic is closed to new replies.

Advertisement