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:
parent
00d937f28c
commit
709a2e6c1c
6 changed files with 167 additions and 157 deletions
|
@ -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})
|
|
||||||
|
|
|
@ -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("");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
msh-console-library/data.cpp
Normal file
30
msh-console-library/data.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
msh-console-library/option.cpp
Normal file
17
msh-console-library/option.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
20
msh-console-library/option.h
Normal file
20
msh-console-library/option.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue