Continued work on options. New interface and imprementation. The new interface allows shortOptions with string values, but this is still not implemented. Added

operator for parsing elements in Datas easily. fixed #2.
This commit is contained in:
Claudio Maggioni 2016-04-06 21:39:27 +02:00
parent 00d937f28c
commit 709a2e6c1c
6 changed files with 167 additions and 157 deletions

View file

@ -4,8 +4,6 @@
project(msh-console-library) project(msh-console-library)
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
set(compilable OFF)
if(${compilable})
SET(CMAKE_CXX_FLAGS "-std=c++11") SET(CMAKE_CXX_FLAGS "-std=c++11")
FILE(GLOB sources *.cpp) FILE(GLOB sources *.cpp)
FILE(GLOB headers *.h) FILE(GLOB headers *.h)
@ -22,4 +20,3 @@ if(${compilable})
MESSAGE( STATUS "Building exec (debug only)") MESSAGE( STATUS "Building exec (debug only)")
add_executable(${PROJECT_NAME} ${sources} ${headers}) add_executable(${PROJECT_NAME} ${sources} ${headers})
endif(${lib}) endif(${lib})
endif(${compilable})

View file

@ -1,29 +1,37 @@
#include "shell.h" #include "shell.h"
namespace mshconsole { namespace mshconsole {
Command::Command(const string& n, int (*funcptr)(CommandExecutor*,const vector<LongData*>&,const vector<bool>&, const char** argv)) : Command::Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector<char*> argv)) :
name(n), funcCommand(funcptr){ name(n), funcCommand(funcptr){
checkObj(); checkObj();
} }
void Command::addOption(Option *a){
if(a->getOptionName().length()==1){
shortOpts.push_back(a);
}
else longOpts.push_back(a);
}
int Command::execute(const vector<string>* args, CommandExecutor* c){ int Command::execute(const vector<string>* args, CommandExecutor* c){
if(args==nullptr) return -1; if(args==nullptr) return -1;
vector<LongData*> data;
for(size_t i=0; i<longOptions.size(); i++){ //filling longData
data.push_back(new LongData()); Datas longData;
} for(size_t i=0; i<longOpts.size(); i++){
longData.push_back(new Data(longOpts[i]));
vector<bool> sLongData;
for(size_t i=0; i<shortOptions.size(); i++){
sLongData.push_back(false);
} }
//filling string for getopt and shortData
string getoptarg; string getoptarg;
for(size_t i=0; i<shortOptions.size(); i++){ Datas shortData;
getoptarg.append(1,shortOptions[i]); for(size_t i=0; i<shortOpts.size(); i++){
shortData.push_back(new Data(shortOpts[i]));
getoptarg.append(1,shortOpts[i]->getOptionName()[0]);
} }
getoptarg+=" -:"; getoptarg+=" -:";
//creating argv as char** for getopt compatibility
vector<char *> argv(args->size()); vector<char *> argv(args->size());
size_t i; size_t i;
for (i = 0; i < args->size(); ++i) for (i = 0; i < args->size(); ++i)
@ -31,6 +39,7 @@ namespace mshconsole {
argv[i] = const_cast<char*>(&(args->operator[](i)[0])); argv[i] = const_cast<char*>(&(args->operator[](i)[0]));
} }
int argc=i; int argc=i;
//TODO: quotes for long options //TODO: quotes for long options
try{ try{
int c; int c;
@ -38,9 +47,10 @@ namespace mshconsole {
optind=1; optind=1;
while ((c = getopt (argc, argv.data(), getoptarg.c_str())) != -1){ while ((c = getopt (argc, argv.data(), getoptarg.c_str())) != -1){
if((c>='a'&&c<='z')||(c>='A'&&c>='Z')){ if((c>='a'&&c<='z')||(c>='A'&&c>='Z')){
for(size_t i=0; i<shortOptions.size(); i++){ for(size_t i=0; i<shortOpts.size(); i++){
if(c==shortOptions[i]){ if(c==shortOpts[i]->getOptionName()[0]){
sLongData[i]=true; shortData[i]->set(true);
break;
} }
} }
} }
@ -48,59 +58,77 @@ namespace mshconsole {
string l(optarg); string l(optarg);
bool getout = false; bool getout = false;
try{ try{
for(size_t i=0; i<longOptions.size(); i++){ for(size_t i=0; i<longOpts.size(); i++){
if(l.find(longOptions[i]->getArgName()+"=")==0){ if(l.find(longOpts[i]->getOptionName()+"=")==0){
if(!(longOptions.at(i)->hasFlag(LongOption::STRING))){ if(!(longOpts[i]->hasFlag(Option::STRING))){
throw NotRightArgException(); throw NotRightArgException();
} }
data[i]->set(l.substr(longOptions[i]->getArgName().size()+1,l.size())); longData[i]->set(l.substr(longOpts[i]->getOptionName().size()+1,l.size()));
getout = true; getout = true;
break; break;
} }
if(l==longOptions[i]->getArgName()){ if(l==longOpts[i]->getOptionName()){
data[i]->set(true); longData[i]->set(true);
getout=true; getout=true;
break; break;
} }
} }
} }
catch(LongData::MultipleDefinitionException){ catch(Data::MultipleDefinitionException){
getout=false; getout=false;
} }
if(!getout) throw OptionNotParsedCorrectlyException(static_cast<string>("--") + optarg); if(!getout) throw OptionNotParsedCorrectlyException(static_cast<string>("--") + optarg);
} }
else if(c=='?'){ else if(c=='?'){
//if (optopt == 'c')
// fprintf (stderr, "Option -%c requires an argument.\n", optopt); else
if (isprint (optopt)) if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt); fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else else
fprintf (stderr, "Unknown option character `\\x%x'.\n",optopt); fprintf (stderr, "Unknown option character `\\x%x'.\n",optopt);
//return 1; return -1;
} }
else //abort(); else //abort();
break; break;
} }
//demo for debug
//demo of all options for debug (code to check)
/* /*
for(size_t i=0; i<longOptions.size(); i++){ for(size_t i=0; i<longOpts.size(); i++){
cout << longOptions[i]->getArgName() << ": "; cout << longOpts[i]->getOptionName() << ": ";
LongData* now = data[i]; LongData* now = data[i];
if(now->getState()==LongData::States::STRING) cout << now->getLongData(); if(now->getState()==LongData::States::STRING) cout << now->getLongData();
else cout << now->getBoolState(); else cout << now->getBoolState();
cout << "\n"; cout << "\n";
} }
for(size_t i=0; i<shortOptions.size(); i++){ for(size_t i=0; i<shortOpts.size(); i++){
cout << shortOptions[i] << ": " << sLongData[i] << "\n"; cout << shortOptions[i] << ": " << sLongData[i] << "\n";
}*/ }*/
} }
catch(OptionNotParsedCorrectlyException e){ catch(OptionNotParsedCorrectlyException e){
cout << "Error parsing option " << e.getOptarg() << "\n"; cout << "Error parsing option " << e.getOptarg() << "\n";
return -1;
} }
catch(NotRightArgException){ catch(NotRightArgException){
cout << "Error on options argument type\n"; cout << "Error on options argument type\n";
return -1;
} }
return (*funcCommand)(c,data,sLongData, const_cast<const char**>(argv.data()));
//making one big Data vector
shortOpts.insert(
shortOpts.end(),
std::make_move_iterator(longOpts.begin()),
std::make_move_iterator(longOpts.end())
);
//deleting options and command name from argv
argv.erase(argv.begin()); //argv[0] = command name
for(int i=0; i<argv.size(); i++){
if(argv[0][0]=='-'){
argv.erase(argv.begin()+i);
i--;
}
}
return (*funcCommand)(c,shortData, argv);
} }
string Command::getName(){ string Command::getName(){
@ -118,53 +146,5 @@ namespace mshconsole {
} }
} }
} }
const string Command::Data::EMPTY("");
/*Command::Options *Command::getCmdOpts() const
{
return cmdOpts;
}
void Command::setCmdOpts(Command::Options *value)
{
cmdOpts = value;
}
Command::~Command(){
numCom--;
}
unsigned int Command::numCom = 0;
const Command::Options *(Command::defaultOpts) = new Command::Options();
string Command::Options::Option::getOShort() const
{
return oShort;
}
void Command::Options::Option::setOShort(const string &value)
{
oShort = value;
}
string Command::Options::Option::getOLong() const
{
return oLong;
}
void Command::Options::Option::setOLong(const string &value)
{
oLong = value;
}
void Command::Options::addOption(Command::Options::Option *a){
for(size_t i=0; i<this->howMany(); i++){
if(a->getOShort()==(this->operator [](i)->getOShort())||a->getOLong()==(this->operator [](i)->getOLong())){
throw OptionNameConflictException();
}
}
opts.push_back(a);
}*/
const string Command::LongData::EMPTY("");
} }

View file

@ -2,7 +2,8 @@
#define COMMAND_H #define COMMAND_H
#include <string> #include <string>
#include <vector> #include <vector>
#include "shell.h" //#include "shell.h"
#include "option.h"
#include "commandexecutor.h" #include "commandexecutor.h"
using std::string; using std::string;
@ -22,13 +23,13 @@ namespace mshconsole{
class CommandNameNotValidException {}; class CommandNameNotValidException {};
class NotRightArgException {}; class NotRightArgException {};
vector<char> shortOptions;
const string name; const string name;
void checkObj(); void checkObj();
vector<Option*> longOpts;
vector<Option*> shortOpts;
public: public:
class LongData{ class Data{
public: public:
enum States{ enum States{
STRING=4, STRING=4,
@ -38,77 +39,42 @@ namespace mshconsole{
class MultipleDefinitionException{}; class MultipleDefinitionException{};
private: private:
string sLongData; string sData;
const Option* of;
enum States state; enum States state;
static const string EMPTY; static const string EMPTY;
bool isSLongDataValorized; bool isSDataValorized;
Data(const Option* o) : sData(), state(Data::FALSE), isSDataValorized(false), of(o) {}
public: public:
LongData() : sLongData(), state(LongData::FALSE), isSLongDataValorized(false) {} void set(bool b);
void set(bool b){ void set(const string& s);
if(isSLongDataValorized) throw MultipleDefinitionException(); enum States getState() const;
b ? state=LongData::TRUE : state=LongData::FALSE; const string& getData() const;
isSLongDataValorized=true; bool getBoolState() const;
} friend class Command;
void set(const string& s){ friend class Datas;
if(isSLongDataValorized) throw MultipleDefinitionException();
state=LongData::STRING;
sLongData=s;
isSLongDataValorized=true;
}
enum LongData::States getState() const{
return state;
}
const string& getLongData() const{
if(state!=LongData::STRING) return EMPTY;
else return sLongData;
}
bool getBoolState() const{
return state!=LongData::FALSE;
}
}; };
Command(const string& n, int (*funcptr)(CommandExecutor*, const vector<LongData*>&, const vector<bool>&, const char** argv)); class Datas : public vector<Data*>{
public:
Data* getOptData(const string& optionName) const;
};
Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector<char*> argv));
Command(const Command&); Command(const Command&);
~Command(); ~Command();
string getName(); string getName();
int execute(const vector<string>*, CommandExecutor*); int execute(const vector<string>*, CommandExecutor*);
void addOption(Option* a);
class LongOption{
string argName;
public:
enum States{
STRING=2,
BOOL=1
};
private: private:
enum States want; int (*funcCommand)(CommandExecutor* whoExecuted,const Datas& data, const vector<char*> argv);
public:
LongOption(const string& s, enum States b) : argName(s), want(b) {}
enum States getWant() const{
return want;
}
const string& getArgName(){
return argName;
}
bool hasFlag(enum States s){
return want & s;
}
};
void addLongOption(LongOption* a){
longOptions.push_back(a);
}
void addShortOption(char a){
shortOptions.push_back(a);
}
private:
vector<LongOption*> longOptions;
int (*funcCommand)(CommandExecutor*,const vector<LongData*>&, const vector<bool>&, const char** argv);
}; };
inline Command::LongOption::States operator|(Command::LongOption::States a, Command::LongOption::States b){
return static_cast<Command::LongOption::States>(static_cast<int>(a) | static_cast<int>(b));
}
} }

View file

@ -0,0 +1,30 @@
#include "command.h"
namespace mshconsole{
void Command::Data::set(bool b){
if(isSDataValorized) throw MultipleDefinitionException();
b ? state=Data::TRUE : state=Data::FALSE;
isSDataValorized=true;
}
void Command::Data::set(const string& s){
if(isSDataValorized) throw MultipleDefinitionException();
state=Data::STRING;
sData=s;
isSDataValorized=true;
}
enum Command::Data::States Command::Data::getState() const{
return state;
}
const string& Command::Data::getData() const{
if(state!=Data::STRING) return EMPTY;
else return sData;
}
bool Command::Data::getBoolState() const{
return state!=Data::FALSE;
}
Command::Data* Command::Datas::getOptData(const string& opt) const{
for(size_t i=0; i<size(); i++){
if(operator[](i)->of->getOptionName()==opt) return operator[](i);
}
}
}

View file

@ -0,0 +1,17 @@
#include "option.h"
namespace mshconsole{
Option::Option(const string &s, States b): optionName(s), want(b){
if(optionName.length()<1){
throw OptionNameEmptyException{};
}
}
const string& Option::getOptionName() const{
return optionName;
}
bool Option::hasFlag(enum States s) const{
return want & s;
}
}

View file

@ -0,0 +1,20 @@
#include <string>
using std::string;
namespace mshconsole{
class Option{
string optionName;
class OptionNameEmptyException{};
public:
enum States{
STRING=2,
BOOL=1
};
private:
enum States want;
public:
Option(const string& s, enum States b);
const string& getOptionName() const;
bool hasFlag(enum States s) const;
};
}