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,22 +4,19 @@
project(msh-console-library)
cmake_minimum_required(VERSION 2.8)
set(compilable OFF)
if(${compilable})
SET(CMAKE_CXX_FLAGS "-std=c++11")
FILE(GLOB sources *.cpp)
FILE(GLOB headers *.h)
SET(CMAKE_CXX_FLAGS "-std=c++11")
FILE(GLOB sources *.cpp)
FILE(GLOB headers *.h)
set(lib OFF)
if(${lib})
MESSAGE( STATUS "Building .so.1")
#compile the library
# Create a library which includes the source listed.
# The extension is already found. Any number of sources could be listed here.
list(REMOVE_ITEM SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
add_library (mshconsole SHARED ${SRC_LIST})
else(${lib})
MESSAGE( STATUS "Building exec (debug only)")
add_executable(${PROJECT_NAME} ${sources} ${headers})
endif(${lib})
endif(${compilable})
set(lib OFF)
if(${lib})
MESSAGE( STATUS "Building .so.1")
#compile the library
# Create a library which includes the source listed.
# The extension is already found. Any number of sources could be listed here.
list(REMOVE_ITEM SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
add_library (mshconsole SHARED ${SRC_LIST})
else(${lib})
MESSAGE( STATUS "Building exec (debug only)")
add_executable(${PROJECT_NAME} ${sources} ${headers})
endif(${lib})

View File

@ -1,29 +1,37 @@
#include "shell.h"
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){
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){
if(args==nullptr) return -1;
vector<LongData*> data;
for(size_t i=0; i<longOptions.size(); i++){
data.push_back(new LongData());
}
vector<bool> sLongData;
for(size_t i=0; i<shortOptions.size(); i++){
sLongData.push_back(false);
//filling longData
Datas longData;
for(size_t i=0; i<longOpts.size(); i++){
longData.push_back(new Data(longOpts[i]));
}
//filling string for getopt and shortData
string getoptarg;
for(size_t i=0; i<shortOptions.size(); i++){
getoptarg.append(1,shortOptions[i]);
Datas shortData;
for(size_t i=0; i<shortOpts.size(); i++){
shortData.push_back(new Data(shortOpts[i]));
getoptarg.append(1,shortOpts[i]->getOptionName()[0]);
}
getoptarg+=" -:";
//creating argv as char** for getopt compatibility
vector<char *> argv(args->size());
size_t i;
for (i = 0; i < args->size(); ++i)
@ -31,6 +39,7 @@ namespace mshconsole {
argv[i] = const_cast<char*>(&(args->operator[](i)[0]));
}
int argc=i;
//TODO: quotes for long options
try{
int c;
@ -38,9 +47,10 @@ namespace mshconsole {
optind=1;
while ((c = getopt (argc, argv.data(), getoptarg.c_str())) != -1){
if((c>='a'&&c<='z')||(c>='A'&&c>='Z')){
for(size_t i=0; i<shortOptions.size(); i++){
if(c==shortOptions[i]){
sLongData[i]=true;
for(size_t i=0; i<shortOpts.size(); i++){
if(c==shortOpts[i]->getOptionName()[0]){
shortData[i]->set(true);
break;
}
}
}
@ -48,59 +58,77 @@ namespace mshconsole {
string l(optarg);
bool getout = false;
try{
for(size_t i=0; i<longOptions.size(); i++){
if(l.find(longOptions[i]->getArgName()+"=")==0){
if(!(longOptions.at(i)->hasFlag(LongOption::STRING))){
for(size_t i=0; i<longOpts.size(); i++){
if(l.find(longOpts[i]->getOptionName()+"=")==0){
if(!(longOpts[i]->hasFlag(Option::STRING))){
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;
break;
}
if(l==longOptions[i]->getArgName()){
data[i]->set(true);
if(l==longOpts[i]->getOptionName()){
longData[i]->set(true);
getout=true;
break;
}
}
}
catch(LongData::MultipleDefinitionException){
catch(Data::MultipleDefinitionException){
getout=false;
}
if(!getout) throw OptionNotParsedCorrectlyException(static_cast<string>("--") + optarg);
}
else if(c=='?'){
//if (optopt == 'c')
// fprintf (stderr, "Option -%c requires an argument.\n", optopt); else
if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr, "Unknown option character `\\x%x'.\n",optopt);
//return 1;
return -1;
}
else //abort();
break;
}
//demo for debug
//demo of all options for debug (code to check)
/*
for(size_t i=0; i<longOptions.size(); i++){
cout << longOptions[i]->getArgName() << ": ";
for(size_t i=0; i<longOpts.size(); i++){
cout << longOpts[i]->getOptionName() << ": ";
LongData* now = data[i];
if(now->getState()==LongData::States::STRING) cout << now->getLongData();
else cout << now->getBoolState();
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";
}*/
}
catch(OptionNotParsedCorrectlyException e){
cout << "Error parsing option " << e.getOptarg() << "\n";
return -1;
}
catch(NotRightArgException){
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(){
@ -118,53 +146,5 @@ namespace mshconsole {
}
}
}
/*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("");
const string Command::Data::EMPTY("");
}

View File

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