1 #ifndef AESALON_MISC_ARGUMENT_PARSER_H
2 #define AESALON_MISC_ARGUMENT_PARSER_H
9 #include "SmartPointer.h"
10 #include "Exception.h"
11 #include "StreamAsString.h"
12 #include "InvalidCastException.h"
17 class ArgumentException
: public Exception
{
19 ArgumentException(std::string message
) : Exception(message
) {}
22 class NoArgumentToArgumentException
: public ArgumentException
{
24 NoArgumentToArgumentException(std::string which
) : ArgumentException(StreamAsString()
25 << "Argument expects argument: " << which
) {}
26 NoArgumentToArgumentException(char which
) : ArgumentException(StreamAsString()
27 << "Argument expects argument: -" << which
) {}
30 class UnknownArgumentException
: public ArgumentException
{
32 UnknownArgumentException(std::string what
) : ArgumentException(StreamAsString()
33 << "Unknown argument encountered: \"" << what
<< "\"") {}
34 UnknownArgumentException(char what
) : ArgumentException(StreamAsString()
35 << "Unknown short-form argument: \'" << what
<< "\'") {}
38 /* The Argument class needs to encapsulate two very different jobs.
39 The first, and most obvious, is a simple boolean toggle switch, such as
40 '--enable-debug-information'/'--disable-debug-information'; with shortened
41 versions like -E/-d, that have a default value.
42 The second, and second-most-obvious, is a string argument, something along
43 the lines of '--library-path ./libaesalon_overload.so'/
44 '-L ./libaesalon_overload.so' -- these may also have a default value.
45 These may also be used in short-form as '-Ll ./library.so logfile.log'.
48 class BooleanArgument
;
53 enum argument_type_e
{
60 Argument(argument_type_e type
) : type(type
) {}
61 virtual ~Argument() {}
63 argument_type_e
get_type() const { return type
; }
65 /*SmartPointer<BooleanArgument> to_bool() const {
66 if(get_type() == BOOLEAN_ARGUMENT) return dynamic_cast<BooleanArgument *>(const_cast<Argument *>(this));
67 throw InvalidCastException();
69 SmartPointer<StringArgument> to_string() const {
70 if(get_type() == STRING_ARGUMENT) return dynamic_cast<StringArgument *>(const_cast<Argument *>(this));
71 throw InvalidCastException();
73 virtual Argument
*convert() = 0;
76 class BooleanArgument
: public Argument
{
78 std::string enable_long_form
;
79 char enable_short_form
;
80 std::string disable_long_form
;
81 char disable_short_form
;
84 BooleanArgument(std::string enable_long_form
, char enable_short_form
,
85 std::string disable_long_form
, char disable_short_form
,
86 bool default_value
= false) : Argument(Argument::BOOLEAN_ARGUMENT
),
87 enable_long_form(enable_long_form
),
88 enable_short_form(enable_short_form
),
89 disable_long_form(disable_long_form
),
90 disable_short_form(disable_short_form
),
91 status(default_value
) {}
92 virtual ~BooleanArgument() {}
94 std::string
get_enable_long_form() const { return enable_long_form
; }
95 char get_enable_short_form() const { return enable_short_form
; }
96 std::string
get_disable_long_form() const { return disable_long_form
; }
97 char get_disable_short_form() const { return disable_short_form
; }
99 void set_status(bool new_status
) { status
= new_status
; }
100 void toggle_status() { status
= !status
; }
101 bool get_status() const { return status
; }
103 virtual BooleanArgument
*convert() { return this; }
106 class StringArgument
: public Argument
{
108 std::string long_form
;
112 StringArgument(std::string long_form
, char short_form
,
113 std::string default_value
= "") : Argument(Argument::STRING_ARGUMENT
),
114 long_form(long_form
), short_form(short_form
), value(default_value
) {}
115 virtual ~StringArgument() {}
117 std::string
get_long_form() const { return long_form
; }
118 char get_short_form() const { return short_form
; }
120 void set_value(std::string new_value
) { value
= new_value
; }
121 std::string
get_value() const { return value
; }
123 virtual StringArgument
*convert() { return this; }
128 std::string filename
;
130 FileArgument(std::string filename
) : filename(filename
) {}
131 virtual ~FileArgument() {}
133 std::string
get_filename() const { return filename
; }
136 class ArgumentParser
: public Misc::Singleton
<ArgumentParser
> {
138 typedef std::map
<std::string
, SmartPointer
<Argument
> > argument_map_t
;
139 typedef std::vector
<SmartPointer
<FileArgument
> > file_argument_vector_t
;
141 argument_map_t argument_map
;
142 file_argument_vector_t file_argument_vector
;
144 ArgumentParser() : Singleton
<ArgumentParser
>() {}
145 virtual ~ArgumentParser();
147 void add_argument(std::string reference_name
, SmartPointer
<Argument
> argument
) {
148 argument_map
[reference_name
] = argument
;
150 SmartPointer
<Argument
> get_argument(std::string reference_name
) {
151 return argument_map
[reference_name
];
154 void add_file(SmartPointer
<FileArgument
> file
) {
155 file_argument_vector
.push_back(file
);
157 SmartPointer
<FileArgument
> get_file(std::size_t which
) {
158 return file_argument_vector
[which
];
160 std::size_t get_files() const { return file_argument_vector
.size(); }
162 void parse_argv(char *argv
[]);
166 } // namespace Aesalon