// 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: public ITxtCommand\
{\
static __CTxtCommand_##cmdName* getInstance()\
{\
static __CTxtCommand_##cmdName *p=NULL;\
if (p==NULL) p= new __CTxtCommand_##cmdName;\
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() {}\
};\
static ITxtCommandRegisterer<__CTxtCommand_##cmdName,__CTxtCommandSet_##setName> __CTxtCommand_##cmdName##_Registerer;\
CTxtCommandResult __CTxtCommand_##cmdName::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