// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef TXT_COMMAND_H #define TXT_COMMAND_H //------------------------------------------------------------------------------------------------- // includes //------------------------------------------------------------------------------------------------- #include "nel/misc/types_nl.h" #include "nel/misc/common.h" #include "nel/misc/debug.h" #include "nel/misc/sstring.h" //------------------------------------------------------------------------------------------------- // MACRO TXT_COMMAND_SET //------------------------------------------------------------------------------------------------- #define TXT_COMMAND_SET(setName,CONTEXT_CLASS)\ class __CTxtCommandSet_##setName: public ITxtCommandSet\ {\ public:\ static __CTxtCommandSet_##setName* getInstance()\ {\ static __CTxtCommandSet_##setName *p=NULL;\ if (p==NULL) p= new __CTxtCommandSet_##setName;\ return p;\ }\ };\ static CTxtCommandSetPtr<__CTxtCommandSet_##setName> setName; //------------------------------------------------------------------------------------------------- // MACRO TXT_COMMAND //------------------------------------------------------------------------------------------------- #define TXT_COMMAND(cmdName,setName,CONTEXT_CLASS)\ struct __CTxtCommand_##cmdName##CONTEXT_CLASS: public ITxtCommand\ {\ static __CTxtCommand_##cmdName##CONTEXT_CLASS* getInstance()\ {\ static __CTxtCommand_##cmdName##CONTEXT_CLASS *p=NULL;\ if (p==NULL) p= new __CTxtCommand_##cmdName##CONTEXT_CLASS;\ return p;\ }\ virtual const char* getName() const {return #cmdName;}\ virtual CTxtCommandResult execute(CONTEXT_CLASS& context,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& fullCmdLine);\ private:\ __CTxtCommand_##cmdName##CONTEXT_CLASS() {}\ };\ static ITxtCommandRegisterer<__CTxtCommand_##cmdName##CONTEXT_CLASS,__CTxtCommandSet_##setName> __CTxtCommand_##cmdName##CONTEXT_CLASS##_Registerer;\ CTxtCommandResult __CTxtCommand_##cmdName##CONTEXT_CLASS::execute(CONTEXT_CLASS& context,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& fullCmdLine) //------------------------------------------------------------------------------------------------- // class CTxtCommandResult //------------------------------------------------------------------------------------------------- class CTxtCommandResult { public: enum TType { SUCCESS, // command execution was successful SYNTAX_ERROR, // there was a syntax error in the command line BAD_PERMISSION, // the user doesn't have the right to run the given command UNKNOWN_COMMAND, // behave as if the command was not recognised EXECUTION_ERROR // there was an error during execution of the command }; CTxtCommandResult(const bool& success): _Type(success?SUCCESS:SYNTAX_ERROR) {} CTxtCommandResult(const TType& type): _Type(type) {} CTxtCommandResult(const TType& type,const NLMISC::CSString& reason): _Type(type), _Reason(reason) {} TType getType() const { return _Type; } const NLMISC::CSString& getReason() const { return _Reason; } private: TType _Type; NLMISC::CSString _Reason; }; //------------------------------------------------------------------------------------------------- // class ITxtCommand //------------------------------------------------------------------------------------------------- template class ITxtCommand { public: virtual const char* getName() const =0; virtual CTxtCommandResult execute(CONTEXT_CLASS& context,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& fullCmdLine) =0; }; //------------------------------------------------------------------------------------------------- // class ITxtCommandRegisterer //------------------------------------------------------------------------------------------------- template struct ITxtCommandRegisterer { ITxtCommandRegisterer() { SET::getInstance()->registerTxtCommand(CMD::getInstance()); } }; //------------------------------------------------------------------------------------------------- // class ITxtCommandSet //------------------------------------------------------------------------------------------------- template class ITxtCommandSet { public: void registerTxtCommand(ITxtCommand* txtCommand) { nlassert(_TxtCommands.find(txtCommand->getName())==_TxtCommands.end()); _TxtCommands[txtCommand->getName()]= txtCommand; } CTxtCommandResult execute(CONTEXT_CLASS& context,const NLMISC::CSString& cmdLine) { NLMISC::CSString cmdTail=cmdLine; NLMISC::CSString keyword=cmdTail.firstWord(true); typename TTxtCommands::iterator it= _TxtCommands.find(keyword); if (it==_TxtCommands.end()) return CTxtCommandResult::UNKNOWN_COMMAND; NLMISC::CVectorSString args; cmdTail.splitWords(args); return it->second->execute(context,args,cmdTail,cmdLine); } private: typedef ITxtCommand TTxtCommand; typedef std::map TTxtCommands; TTxtCommands _TxtCommands; }; //------------------------------------------------------------------------------------------------- // class ITxtCommandRegisterer //------------------------------------------------------------------------------------------------- template struct CTxtCommandSetPtr { CTxtCommandSetPtr() { SET::getInstance(); } SET& operator*() { return *SET::getInstance(); } SET* operator->() { return SET::getInstance(); } }; //------------------------------------------------------------------------------------------------- #endif