From 709a2e6c1c545fb20a8515c7f7001135a3c92872 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Wed, 6 Apr 2016 21:39:27 +0200 Subject: [PATCH] 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. --- msh-console-library/CMakeLists.txt | 33 ++++--- msh-console-library/command.cpp | 136 ++++++++++++----------------- msh-console-library/command.h | 88 ++++++------------- msh-console-library/data.cpp | 30 +++++++ msh-console-library/option.cpp | 17 ++++ msh-console-library/option.h | 20 +++++ 6 files changed, 167 insertions(+), 157 deletions(-) create mode 100644 msh-console-library/data.cpp create mode 100644 msh-console-library/option.cpp create mode 100644 msh-console-library/option.h diff --git a/msh-console-library/CMakeLists.txt b/msh-console-library/CMakeLists.txt index e3b1fe4..3ded61d 100644 --- a/msh-console-library/CMakeLists.txt +++ b/msh-console-library/CMakeLists.txt @@ -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}) diff --git a/msh-console-library/command.cpp b/msh-console-library/command.cpp index e358820..46348ff 100644 --- a/msh-console-library/command.cpp +++ b/msh-console-library/command.cpp @@ -1,29 +1,37 @@ #include "shell.h" namespace mshconsole { - Command::Command(const string& n, int (*funcptr)(CommandExecutor*,const vector&,const vector&, const char** argv)) : + Command::Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector 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* args, CommandExecutor* c){ if(args==nullptr) return -1; - vector data; - for(size_t i=0; i sLongData; - for(size_t i=0; igetOptionName()[0]); } getoptarg+=" -:"; + //creating argv as char** for getopt compatibility vector argv(args->size()); size_t i; for (i = 0; i < args->size(); ++i) @@ -31,6 +39,7 @@ namespace mshconsole { argv[i] = const_cast(&(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; igetOptionName()[0]){ + shortData[i]->set(true); + break; } } } @@ -48,59 +58,77 @@ namespace mshconsole { string l(optarg); bool getout = false; try{ - for(size_t i=0; igetArgName()+"=")==0){ - if(!(longOptions.at(i)->hasFlag(LongOption::STRING))){ + for(size_t i=0; igetOptionName()+"=")==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("--") + 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; igetArgName() << ": "; + for(size_t i=0; igetOptionName() << ": "; 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(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; ihowMany(); 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(""); } diff --git a/msh-console-library/command.h b/msh-console-library/command.h index 67e9e6d..003b5c7 100644 --- a/msh-console-library/command.h +++ b/msh-console-library/command.h @@ -2,7 +2,8 @@ #define COMMAND_H #include #include -#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 shortOptions; const string name; void checkObj(); + vector longOpts; + vector 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&, const vector&, const char** argv)); + class Datas : public vector{ + public: + Data* getOptData(const string& optionName) const; + }; + + Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector argv)); Command(const Command&); ~Command(); string getName(); int execute(const vector*, 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 longOptions; - int (*funcCommand)(CommandExecutor*,const vector&, const vector&, const char** argv); + int (*funcCommand)(CommandExecutor* whoExecuted,const Datas& data, const vector argv); }; - inline Command::LongOption::States operator|(Command::LongOption::States a, Command::LongOption::States b){ - return static_cast(static_cast(a) | static_cast(b)); - } + + + } diff --git a/msh-console-library/data.cpp b/msh-console-library/data.cpp new file mode 100644 index 0000000..3fdf9c8 --- /dev/null +++ b/msh-console-library/data.cpp @@ -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; iof->getOptionName()==opt) return operator[](i); + } + } +} diff --git a/msh-console-library/option.cpp b/msh-console-library/option.cpp new file mode 100644 index 0000000..36a565e --- /dev/null +++ b/msh-console-library/option.cpp @@ -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; + } +} diff --git a/msh-console-library/option.h b/msh-console-library/option.h new file mode 100644 index 0000000..992c4c9 --- /dev/null +++ b/msh-console-library/option.h @@ -0,0 +1,20 @@ +#include +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; + }; +}