Add possibility to set Required Parameters.
authorRafał Długołęcki <rafal@dlugolecki.net.pl>
Tue, 5 May 2015 23:43:12 +0000 (01:43 +0200)
committerRafał Długołęcki <rafal@dlugolecki.net.pl>
Tue, 5 May 2015 23:43:12 +0000 (01:43 +0200)
include/argument.h
include/command.h
include/option.h
include/parameter.h
include/required.h [new file with mode: 0644]
src/main.cpp

index b07ae67080925875a3a039218288640f31680bd7..1dae06f15010d9f86cba696e82cc3754dfea6fec 100644 (file)
@@ -11,8 +11,7 @@
 namespace command {
     /**
      * Class responsible for handling commandline arguments.
-     * Arguments are required, non-named parameters of program.
-     * Accepts
+     * Arguments are non-named parameters of program.
      *
      * Example:
      *  ./myprog ARGUMENT
@@ -22,9 +21,6 @@ namespace command {
     template<typename ArgumentType>
     class Argument : public Parameter, public Callable<ArgumentType> {
     protected:
-        /** Variable indicating if current Argument was already used or not */
-        bool used = false;
-
         ArgumentType value;
     public:
         typedef class Argument Type;
@@ -68,14 +64,14 @@ namespace command {
          *  against next value.
          */
         virtual bool understand(const std::string & argv) {
-            if (!used) {
+            if (!isUsed()) {
                 std::stringstream ss;
 
                 ss << argv;
                 ss >> value;
 
                 if (!ss.fail()) {
-                    used = true;
+                    this->used = true;
                     return true;
                 }
             }
index 8ecb280e78aff6bb4080c40fd2ae086f65b44f12..6e8ecf66b7000e564b43f375c67d1ec73649b64e 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <string>
 #include <vector>
+#include <typeinfo>
 
 #include "parameter.h"
 
@@ -32,6 +33,10 @@ namespace command {
                 releaseMemory();
                 throw;
             }
+            catch(std::logic_error exception) {
+                releaseMemory();
+                throw;
+            }
         }
 
         /**
@@ -53,6 +58,11 @@ namespace command {
                     }
                 }
             }
+            for(Parameter *param : parameters) {
+                if (param->isRequired() && !param->isUsed()) {
+                    throw std::logic_error(param->describe() + " is required but it was not handled");
+                }
+            }
         }
 
         /**
index 426942bf41cb7cd4616af64ab655a99cee41a8d3..935914e86112dca86c6e8bf5fad935785773c843 100644 (file)
@@ -10,7 +10,7 @@
 namespace command {
     /**
      * Class responsible for handling commandline options.
-     * Options are non-required, named parameters of program.
+     * Options are named parameters of program.
      *
      * Example:
      *  ./myprog OptionName=OptionValue
@@ -33,9 +33,6 @@ namespace command {
          */
         OptionType value;
 
-        /** Variable indicating if current Option was already used or not */
-        bool used = false;
-
     public:
         /**
          * Default constructor.
@@ -90,7 +87,7 @@ namespace command {
         virtual bool understand(const std::string & argv)
             throw(std::invalid_argument) {
 
-            if ((!used) && (argv.find(name) == 0)) {
+            if ((!isUsed()) && (argv.find(name) == 0)) {
                 std::size_t pos = argv.find("=");
 
                 if (pos != name.size()) {
@@ -136,10 +133,6 @@ namespace command {
          * Current Option name
          */
         const OptionName name;
-
-        /** Variable indicating if current Option was already used or not */
-        bool used = false;
-
     public:
         /**
          * Default constructor.
@@ -175,7 +168,7 @@ namespace command {
          *  used to check against next value.
          */
         virtual bool understand(const std::string & argv) {
-            if ((!used) &&
+            if ((!isUsed()) &&
                 (argv == name)) {
                 used = true;
                 return true;
index 1396f830d07ed3d63f11eb9540f6bc028a71c4cd..a54a967e36e87bd0c9394d31b5a4b24dde22c541 100644 (file)
@@ -14,6 +14,10 @@ namespace command {
      *  ./myprog ARGUMENT
      */
     class Parameter : public Descriptive {
+    protected:
+        /** Variable indicating if current Parameter was already used or not */
+        bool used = false;
+
     public:
         typedef class Parameter Type;
         /**
@@ -37,6 +41,17 @@ namespace command {
          * parameter.
          */
         virtual bool understand(const std::string & ) = 0;
+
+        /**
+         * Indicates if current Parameter is required
+         */
+        virtual bool isRequired() {
+            return false;
+        };
+
+        virtual bool isUsed() {
+            return used;
+        }
     };
 }
 
diff --git a/include/required.h b/include/required.h
new file mode 100644 (file)
index 0000000..bdb6299
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __COMMAND_REQUIRED_H
+#define __COMMAND_REQUIRED_H
+
+#include "parameter.h"
+
+namespace command {
+    /**
+     * Required Parameter decorator. Makes passed Parameters treated as required
+     */
+    class Required : public Parameter {
+    protected:
+        /**
+         * Parameter which will be treated as required
+         */
+        Parameter * parameter;
+
+    public:
+        /**
+         * Default constructor.
+         *
+         * @param parameter Parameter which will be treated as required
+         */
+        Required(Parameter * parameter)
+            : Parameter(parameter->describe()), parameter(parameter) {
+        }
+
+        /**
+         * Default destructor. Releases allocated memory
+         */
+        virtual ~Required() {
+            delete parameter;
+        }
+
+        /**
+         * Method used for handling method calls to linked Parameter
+         */
+        virtual void handle() {
+            parameter->handle();
+        }
+
+        /**
+         * Method used for checking if the given user value is understandable by
+         * parameter.
+         *
+         * @param value value from argv to check against
+         */
+        virtual bool understand(const std::string & value) {
+            return parameter->understand(value);
+        }
+
+        /**
+         * Indicates if current Parameter is required
+         */
+        virtual bool isRequired() {
+            return true;
+        };
+
+        /**
+         * Indicates if current Parameter is already used
+         */
+        virtual bool isUsed() {
+            return parameter->isUsed();
+        };
+    };
+}
+
+#endif /* __COMMAND_PARAMETER_H */
index 5a42e860c14eaad667c3ca656e93be3b23ca85e1..5cf4e83d018373e5e665bafaee685ee2989e7bff 100644 (file)
@@ -3,8 +3,11 @@
 
 #include "option.h"
 #include "argument.h"
+#include "required.h"
 #include "command.h"
 
+using namespace command;
+
 void argument_function(bool a) {
     std::cout << "Argument: " << a << std::endl;
 }
@@ -18,11 +21,11 @@ void void_function(void) {
 }
 
 int main(int argc, char *argv[]) {
-    command::Command command(argc, argv, {
-//         new command::Argument<std::string>("File path", [](std::string value)->void { std::cout << "Hello from lambda " << value << std::endl; }),
-        new command::Argument<bool>("File path", argument_function),
-        new command::Option<std::string>("f", "Optional file", option_function),
-        new command::Option<void>("h", "Help", void_function)
+    Command command(argc, argv, {
+//         new Argument<std::string>("File path", [](std::string value)->void { std::cout << "Hello from lambda " << value << std::endl; }),
+        new Required(new Argument<bool>("File path", argument_function)),
+        new Option<std::string>("f", "Optional file", option_function),
+        new Option<void>("h", "Help", void_function)
     });
 
     return 0;