0
|
1 /* The copyright in this software is being made available under the BSD
|
|
2 * License, included below. This software may be subject to other third party
|
|
3 * and contributor rights, including patent rights, and no such rights are
|
|
4 * granted under this license.
|
|
5 *
|
|
6 * Copyright (c) 2010-2014, ITU/ISO/IEC
|
|
7 * All rights reserved.
|
|
8 *
|
|
9 * Redistribution and use in source and binary forms, with or without
|
|
10 * modification, are permitted provided that the following conditions are met:
|
|
11 *
|
|
12 * * Redistributions of source code must retain the above copyright notice,
|
|
13 * this list of conditions and the following disclaimer.
|
|
14 * * Redistributions in binary form must reproduce the above copyright notice,
|
|
15 * this list of conditions and the following disclaimer in the documentation
|
|
16 * and/or other materials provided with the distribution.
|
|
17 * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
|
|
18 * be used to endorse or promote products derived from this software without
|
|
19 * specific prior written permission.
|
|
20 *
|
|
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
|
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
31 * THE POSSIBILITY OF SUCH DAMAGE.
|
|
32 */
|
|
33 #include <iostream>
|
|
34 #include <sstream>
|
|
35 #include <string>
|
|
36 #include <list>
|
|
37 #include <map>
|
|
38
|
|
39 #ifndef __PROGRAM_OPTIONS_LITE__
|
|
40 #define __PROGRAM_OPTIONS_LITE__
|
|
41
|
|
42 //! \ingroup TAppCommon
|
|
43 //! \{
|
|
44
|
|
45
|
|
46 namespace df
|
|
47 {
|
|
48 namespace program_options_lite
|
|
49 {
|
|
50 struct Options;
|
|
51
|
|
52 struct ParseFailure : public std::exception
|
|
53 {
|
|
54 ParseFailure(std::string arg0, std::string val0) throw()
|
|
55 : arg(arg0), val(val0)
|
|
56 {}
|
|
57
|
|
58 ~ParseFailure() throw() {};
|
|
59
|
|
60 std::string arg;
|
|
61 std::string val;
|
|
62
|
|
63 const char* what() const throw() { return "Option Parse Failure"; }
|
|
64 };
|
|
65
|
|
66 void doHelp(std::ostream& out, Options& opts, unsigned columns = 80);
|
|
67 unsigned parseGNU(Options& opts, unsigned argc, const char* argv[]);
|
|
68 unsigned parseSHORT(Options& opts, unsigned argc, const char* argv[]);
|
|
69 std::list<const char*> scanArgv(Options& opts, unsigned argc, const char* argv[]);
|
|
70 void scanLine(Options& opts, std::string& line);
|
|
71 void scanFile(Options& opts, std::istream& in);
|
|
72 void setDefaults(Options& opts);
|
|
73 void parseConfigFile(Options& opts, const std::string& filename);
|
|
74 bool storePair(Options& opts, const std::string& name, const std::string& value);
|
|
75
|
|
76 /** OptionBase: Virtual base class for storing information relating to a
|
|
77 * specific option This base class describes common elements. Type specific
|
|
78 * information should be stored in a derived class. */
|
|
79 struct OptionBase
|
|
80 {
|
|
81 OptionBase(const std::string& name, const std::string& desc)
|
|
82 : opt_string(name), opt_desc(desc)
|
|
83 {};
|
|
84
|
|
85 virtual ~OptionBase() {}
|
|
86
|
|
87 /* parse argument arg, to obtain a value for the option */
|
|
88 virtual void parse(const std::string& arg) = 0;
|
|
89 /* set the argument to the default value */
|
|
90 virtual void setDefault() = 0;
|
|
91
|
|
92 std::string opt_string;
|
|
93 std::string opt_desc;
|
|
94 };
|
|
95
|
|
96 /** Type specific option storage */
|
|
97 template<typename T>
|
|
98 struct Option : public OptionBase
|
|
99 {
|
|
100 Option(const std::string& name, T& storage, T default_val, const std::string& desc)
|
|
101 : OptionBase(name, desc), opt_storage(storage), opt_default_val(default_val)
|
|
102 {}
|
|
103
|
|
104 void parse(const std::string& arg);
|
|
105
|
|
106 void setDefault()
|
|
107 {
|
|
108 opt_storage = opt_default_val;
|
|
109 }
|
|
110
|
|
111 T& opt_storage;
|
|
112 T opt_default_val;
|
|
113 };
|
|
114
|
|
115 /* Generic parsing */
|
|
116 template<typename T>
|
|
117 inline void
|
|
118 Option<T>::parse(const std::string& arg)
|
|
119 {
|
|
120 std::istringstream arg_ss (arg,std::istringstream::in);
|
|
121 arg_ss.exceptions(std::ios::failbit);
|
|
122 try
|
|
123 {
|
|
124 arg_ss >> opt_storage;
|
|
125 }
|
|
126 catch (...)
|
|
127 {
|
|
128 throw ParseFailure(opt_string, arg);
|
|
129 }
|
|
130 }
|
|
131
|
|
132 /* string parsing is specialized -- copy the whole string, not just the
|
|
133 * first word */
|
|
134 template<>
|
|
135 inline void
|
|
136 Option<std::string>::parse(const std::string& arg)
|
|
137 {
|
|
138 opt_storage = arg;
|
|
139 }
|
|
140
|
|
141 /** Option class for argument handling using a user provided function */
|
|
142 struct OptionFunc : public OptionBase
|
|
143 {
|
|
144 typedef void (Func)(Options&, const std::string&);
|
|
145
|
|
146 OptionFunc(const std::string& name, Options& parent_, Func *func_, const std::string& desc)
|
|
147 : OptionBase(name, desc), parent(parent_), func(func_)
|
|
148 {}
|
|
149
|
|
150 void parse(const std::string& arg)
|
|
151 {
|
|
152 func(parent, arg);
|
|
153 }
|
|
154
|
|
155 void setDefault()
|
|
156 {
|
|
157 return;
|
|
158 }
|
|
159
|
|
160 private:
|
|
161 Options& parent;
|
|
162 void (*func)(Options&, const std::string&);
|
|
163 };
|
|
164
|
|
165 class OptionSpecific;
|
|
166 struct Options
|
|
167 {
|
|
168 ~Options();
|
|
169
|
|
170 OptionSpecific addOptions();
|
|
171
|
|
172 struct Names
|
|
173 {
|
|
174 Names() : opt(0) {};
|
|
175 ~Names()
|
|
176 {
|
|
177 if (opt)
|
|
178 delete opt;
|
|
179 }
|
|
180 std::list<std::string> opt_long;
|
|
181 std::list<std::string> opt_short;
|
|
182 OptionBase* opt;
|
|
183 };
|
|
184
|
|
185 void addOption(OptionBase *opt);
|
|
186
|
|
187 typedef std::list<Names*> NamesPtrList;
|
|
188 NamesPtrList opt_list;
|
|
189
|
|
190 typedef std::map<std::string, NamesPtrList> NamesMap;
|
|
191 NamesMap opt_long_map;
|
|
192 NamesMap opt_short_map;
|
|
193 };
|
|
194
|
|
195 /* Class with templated overloaded operator(), for use by Options::addOptions() */
|
|
196 class OptionSpecific
|
|
197 {
|
|
198 public:
|
|
199 OptionSpecific(Options& parent_) : parent(parent_) {}
|
|
200
|
|
201 /**
|
|
202 * Add option described by name to the parent Options list,
|
|
203 * with storage for the option's value
|
|
204 * with default_val as the default value
|
|
205 * with desc as an optional help description
|
|
206 */
|
|
207 template<typename T>
|
|
208 OptionSpecific&
|
|
209 operator()(const std::string& name, T& storage, T default_val, const std::string& desc = "")
|
|
210 {
|
|
211 parent.addOption(new Option<T>(name, storage, default_val, desc));
|
|
212 return *this;
|
|
213 }
|
|
214
|
|
215 /**
|
|
216 * Add option described by name to the parent Options list,
|
|
217 * with desc as an optional help description
|
|
218 * instead of storing the value somewhere, a function of type
|
|
219 * OptionFunc::Func is called. It is upto this function to correctly
|
|
220 * handle evaluating the option's value.
|
|
221 */
|
|
222 OptionSpecific&
|
|
223 operator()(const std::string& name, OptionFunc::Func *func, const std::string& desc = "")
|
|
224 {
|
|
225 parent.addOption(new OptionFunc(name, parent, func, desc));
|
|
226 return *this;
|
|
227 }
|
|
228 private:
|
|
229 Options& parent;
|
|
230 };
|
|
231
|
|
232 } /* namespace: program_options_lite */
|
|
233 } /* namespace: df */
|
|
234
|
|
235 //! \}
|
|
236
|
|
237 #endif
|