HSAdmin Backend Domains, E-Mail, Datenbanken
Purodha
2013-02-20 4a7e12928010374d76e677c8ec3ea4f5e63e9487
commit | author | age
c64ab5 1 /***************************************************************************
CD 2  *   Copyright (C) 2005 by Christof Donat   *
3  *   cdonat@gmx.de   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21
22 #include <vector>
23 #include <string>
24 #include "logger.h"
25 #include <boost/lexical_cast.hpp>
26 #include <boost/shared_ptr.hpp>
27 #include <boost/scoped_ptr.hpp>
28 #include <boost/algorithm/string.hpp>
29
30 /** abstractcommandlineparser holds some basic stuff for making commandline-Parsers easier. */
31
32 namespace abstractcommandlineparser {
33
34 #ifndef HSADMIN_ABSTRACTCMDLINEPARSER
35 #define HSADMIN_ABSTRACTCMDLINEPARSER
36
37 using std::vector;
38 using std::string;
39 using boost::shared_ptr;
40 using boost::scoped_ptr;
41 using boost::starts_with;
42 using boost::erase_first;
43
44 /** \brief template for Commandline-Parser
45  * 
46  *  Has two Parameters:
47  *  - class Options: This class must provide a method 'parseThis()'. - see template CmdLineOption for an example
48  *  - class parseResult: a shared pointer to an Object of this class is passed to the Options.
49  */
50 template<class Options,class parserResult> class CmdLineParser {
51     public:
52     /** \brief this actually not only instatiates the parser but also parses Parameters.
53      * 
54      *  takes the Options in a vector<string> 
55      */
56     CmdLineParser(vector<string> options) : m_parsed(new parserResult), m_parseSuccessful(false) {
57         Options o;
58         while( options.size() > 0 )
59             if( !(this->m_parseSuccessful = o.parseThis(options,m_parsed)) )
60                 return;
61     };
62
63     //! has the parser been successful?
64     inline bool operator!() { return !this->m_parseSuccessful; }
65
66     protected:
67     shared_ptr<parserResult> m_parsed;
68     bool m_parseSuccessful;
69 };
70
71
72 /** \brief base template for Option classes
73  *
74  * usually you would use one of the many specialisations
75  * has four parameters:
76  * - bool hasLongName: the Parameter has a long name (e.g. --verbose)
77  * - bool hasShortName: the Parameter has a short name (e.g. -v)
78  * - bool hasParameter: the Parameter is followed by another Parameter that belongs to it
79  * - class parseResult: takes the Parse results
80  * 
81  * You should implement a protected virtual method 'bool handle(string &parameter, shared_ptr<parseResult> result)'
82  * if you have 'hasParameter' set to true or 'bool handle(shared_ptr<parseResult> result)' otherwise. There you 
83  * can actually store your values in your parseResult.
84  */
85 template <bool hasLongName, bool hasShortName, bool hasParameter,class parseResult> class CmdLineOption {
86     public:
87     //! the actual parser function.
88     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {};
89 };
90
91 /** \brief base template for Option classes - specialisation
92  *
93  * this is the specialisation for Parameters that do have long and short names as well as a value.
94  *
95  * You should implement a protected virtual method 
96  * 'bool handle(string &parameter, shared_ptr<parseResult> result)'.
97  * There you can actually store your values in your parseResult.
98  */
99 template <class parseResult> class CmdLineOption<true, true, true,parseResult> {
100     public:
101     //! the actual parser function.
102     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
103         bool rval = false;
104         if( starts_with(options[0], "-"+m_shortName) ) {
105             if( rval = this->handle(options[1],result) ) {
106                 if( options[0] == "-"+m_shortName)
107                     options.erase(options.begin(),options.begin()+2);
108                 else {
109                     options.erase(options.begin()+1);
110                     erase_first(options[0], m_shortName);
111                 }
112             }
113         } else {
114             if( starts_with(options[0], "--"+m_longName+m_parameterSeparator) ) {
115                 string p = options[0].substr(m_longName.size()+m_parameterSeparator.size()+2);
116                 if( rval = this->handle(p,result) )
117                     options.erase(options.begin());
118             }
119         }
120         return rval;
121     }
122
123     protected:
124     string m_longName;
125     string m_shortName;
126     string m_parameterSeparator;
127
128     //! the handle function.
129     virtual bool handle(string &parameter, shared_ptr<parseResult> result) { return true; };
130 };
131
132 /** \brief base template for Option classes - specialisation
133  *
134  * this is the specialisation for Parameters that do have long and short names but no value.
135  *
136  * You should implement a protected virtual method 
137  * 'bool handle(shared_ptr<parseResult> result)'.
138  * There you can actually store your values in your parseResult.
139  */
140 template <class parseResult> class CmdLineOption<true, true, false,parseResult> {
141     public:
142     //! the actual parser function.
143     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
144         bool rval = false;
145         if( options[0] == "-"+m_shortName || options[0] == "--"+m_longName ) {
146             if( rval = this->handle(result) )
147                 options.erase(options.begin());
148         } else if( starts_with(options[0], "-"+m_shortName) && (rval = this->handle(result)) )
149             erase_first(options[0], m_shortName);
150         return rval;
151     }
152
153     protected:
154     string m_longName;
155     string m_shortName;
156
157     //! the handle function.
158     virtual bool handle(shared_ptr<parseResult> result) { return true; };
159 };
160
161 /** \brief base template for Option classes - specialisation
162  *
163  * this is the specialisation for Parameters that only have a long name and a value but no short name.
164  *
165  * You should implement a protected virtual method 
166  * 'bool handle(string &parameter, shared_ptr<parseResult> result)'.
167  * There you can actually store your values in your parseResult.
168  */
169 template <class parseResult> class CmdLineOption<true, false, true,parseResult> {
170     public:
171     //! the actual parser function.
172     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
173         bool rval = false;
174         if( starts_with(options[0], "--"+m_longName+m_parameterSeparator) ) {
175             string p = options[0].substr(m_longName.size()+m_parameterSeparator.size()+2);
176             if ( rval = this->handle(p, result) )
177                 options.erase(options.begin());
178         }
179         return rval;
180     }
181
182     protected:
183     string m_longName;
184     string m_parameterSeparator;
185
186     //! the handle function.
187     virtual bool handle(string &parameter, shared_ptr<parseResult> result) { return true; };
188 };
189
190 /** \brief base template for Option classes - specialisation
191  *
192  * this is the specialisation for Parameters that only have a long name but no value or short name.
193  *
194  * You should implement a protected virtual method 
195  * 'bool handle(shared_ptr<parseResult> result)'.
196  * There you can actually store your values in your parseResult.
197  */
198 template <class parseResult> class CmdLineOption<true, false, false,parseResult> {
199     public:
200     //! the actual parser function.
201     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
202         bool rval = false;
203         if( options[0] == "--"+m_longName && (rval = this->handle(result)) )
204             options.erase(options.begin());
205         return rval;
206     }
207
208     protected:
209     string m_longName;
210
211     //! the handle function.
212     virtual bool handle(shared_ptr<parseResult> result) { return true; };
213 };
214
215
216 /** \brief base template for Option classes - specialisation
217  *
218  * this is the specialisation for Parameters that only have short name and a value but no long name.
219  *
220  * You should implement a protected virtual method 
221  * 'bool handle(string &parameter, shared_ptr<parseResult> result)'.
222  * There you can actually store your values in your parseResult.
223  */
224 template <class parseResult> class CmdLineOption<false, true, true,parseResult> {
225     public:
226     //! the actual parser function.
227     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
228         bool rval = false;
229         if( starts_with(options[0], "-"+m_shortName) && (rval = this->handle(options[1],result)) ) {
230             if( options[0] == "-"+m_shortName)
231                 options.erase(options.begin(),options.begin()+2);
232             else {
233                 options.erase(options.begin()+1);
234                 erase_first(options[0], m_shortName);
235             }
236         }
237         return rval;
238     }
239
240     protected:
241     string m_shortName;
242
243     //! the handle function.
244     virtual bool handle(string &parameter, shared_ptr<parseResult> result) { return true; };
245 };
246
247 /** \brief base template for Option classes - specialisation
248  *
249  * this is the specialisation for Parameters that only have short name bot no value or long name.
250  *
251  * You should implement a protected virtual method 
252  * 'bool handle(shared_ptr<parseResult> result)'.
253  * There you can actually store your values in your parseResult.
254  */
255 template <class parseResult> class CmdLineOption<false, true, false,parseResult> {
256     public:
257     //! the actual parser function.
258     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
259         bool rval = false;
260         if( starts_with(options[0], "-"+m_shortName) && (rval = this->handle(result)) ) {
261             if( options[0] == "-"+m_shortName )
262                 options.erase(options.begin());
263             else
264                 erase_first(options[0], m_shortName);
265         }
266         return rval;
267     }
268
269     protected:
270     string m_shortName;
271
272     //! the handle function.
273     virtual bool handle(shared_ptr<parseResult> result) { return true; };
274 };
275
276 /** \brief base template for Option classes - specialisation
277  *
278  * this is the specialisation for Parameters that only have  a value but neither a long or short name.
279  *
280  * You should implement a protected virtual method 
281  * 'bool handle(string &parameter, shared_ptr<parseResult> result)'.
282  * There you can actually store your values in your parseResult.
283  */
284 template <class parseResult> class CmdLineOption<false, false, true,parseResult> {
285     public:
286     //! the actual parser function.
287     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
288         bool rval = false;
289         if( !starts_with(options[0], "-") && (rval = this->handle(options[0],result)) )
290             options.erase(options.begin());
291         return rval;
292     }
293
294     protected:
295     //! the handle function.
296     virtual bool handle(string &parameter, shared_ptr<parseResult> result) { return true; };
297 };
298
299
300 /** \brief base template for Option classes - specialisation
301  *
302  * this is the specialisation for Parameters that neither have a value, a long or short name.
303  *
304  * You should implement a protected virtual method 
305  * 'bool handle(shared_ptr<parseResult> result)'.
306  * There you can actually store your values in your parseResult.
307  */
308 template <class parseResult> class CmdLineOption<false, false, false,parseResult> {
309     public:
310     //! the actual parser function.
311     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
312         bool rval = false;
313         if( !starts_with(options[0], "-") && (rval = this->handle(result)) )
314             options.erase(options.begin());
315         return rval;
316     }
317
318     protected:
319     //! the handle function.
320     virtual bool handle(shared_ptr<parseResult> result) { return true; };
321 };
322
323 //! just needed for typelists
324 class nullType {};
325
326 //! typelist for multiple Options parser
327 template<class CAR, class CDR> class typelist {
328     public:
329     typedef CAR car;
330     typedef CDR cdr;
331 };
332
333 /** \brief A Commandline-Option for CmdLineParser that works with a typelist of Options.
334  *
335  * this is meant to combine multiple Parameters in a typelist to build a complex Command Line parser
336  */
337 template<class tl, class parseResult> class CmdLineOptionList : public CmdLineOption<false,false,false,parseResult> {
338     public:
339     //! the actual parser function.
340     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
341         return m_first.parseThis(options,result) || m_second.parseThis(options,result);
342     }
343
344     private:
345     typename tl::car                                 m_first;
346     CmdLineOptionList<typename tl::cdr,parseResult>  m_second;
347 };
348
349 /** \brief specialisation for empty type list
350  */
351 template<class parseResult> class CmdLineOptionList<nullType,parseResult> : public CmdLineOption<false,false,false,parseResult> {
352     public:
353     //! the actual parser function; always returns false.
354     bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
355         return false;
356     }
357 };
358
359 #define Parameterlist1(t1) \
360     abstractcommandlineparser::typelist<t1,abstractcommandlineparser::nullType>
361 #define Parameterlist2(t1,t2) \
362     abstractcommandlineparser::typelist<t1,Parameterlist1(t2) >
363 #define Parameterlist3(t1,t2,t3) \
364     abstractcommandlineparser::typelist<t1,Parameterlist2(t2,t3) >
365 #define Parameterlist4(t1,t2,t3,t4) \
366     abstractcommandlineparser::typelist<t1,Parameterlist3(t2,t3,t4) >
367 #define Parameterlist5(t1,t2,t3,t4,t5) \
368     abstractcommandlineparser::typelist<t1,Parameterlist4(t2,t3,t4,t5) >
369 #define Parameterlist6(t1,t2,t3,t4,t5,t6) \
370     abstractcommandlineparser::typelist<t1,Parameterlist5(t2,t3,t4,t5,t6) >
371 #define Parameterlist7(t1,t2,t3,t4,t5,t6,t7) \
372     abstractcommandlineparser::typelist<t1,Parameterlist6(t2,t3,t4,t5,t6,t7) >
373 #define Parameterlist8(t1,t2,t3,t4,t5,t6,t7,t8) \
374     abstractcommandlineparser::typelist<t1,Parameterlist7(t2,t3,t4,t5,t6,t7,t8) >
375 #define Parameterlist9(t1,t2,t3,t4,t5,t6,t7,t8,t9) \
376     abstractcommandlineparser::typelist<t1,Parameterlist8(t2,t3,t4,t5,t6,t7,t8,t9) >
377 #define Parameterlist10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) \
378     abstractcommandlineparser::typelist<t1,Parameterlist9(t2,t3,t4,t5,t6,t7,t8,t9,t10) >
379 #define Parameterlist11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) \
380     abstractcommandlineparser::typelist<t1,Parameterlist10(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) >
381 #define Parameterlist12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) \
382     abstractcommandlineparser::typelist<t1,Parameterlist11(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) >
383 #define Parameterlist13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) \
384     abstractcommandlineparser::typelist<t1,Parameterlist12(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) >
385 #define Parameterlist14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) \
386     abstractcommandlineparser::typelist<t1,Parameterlist13(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) >
387 #define Parameterlist15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) \
388     abstractcommandlineparser::typelist<t1,Parameterlist14(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) >
389 #define Parameterlist16(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16) \
390     abstractcommandlineparser::typelist<t1,Parameterlist15(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16) >
391 #define Parameterlist17(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17) \
392     abstractcommandlineparser::typelist<t1,Parameterlist16(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17) >
393 #define Parameterlist18(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18) \
394     abstractcommandlineparser::typelist<t1,Parameterlist17(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18) >
395 #define Parameterlist19(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19) \
396     abstractcommandlineparser::typelist<t1,Parameterlist18(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19) >
397 #define Parameterlist20(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20) \
398     abstractcommandlineparser::typelist<t1,Parameterlist19(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20) >
399 #define Parameterlist21(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21) \
400     abstractcommandlineparser::typelist<t1,Parameterlist20(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21) >
401 #define Parameterlist22(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22) \
402     abstractcommandlineparser::typelist<t1,Parameterlist21(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22) >
403 #define Parameterlist23(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23) \
404     abstractcommandlineparser::typelist<t1,Parameterlist22(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23) >
405 #define Parameterlist24(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24) \
406     abstractcommandlineparser::typelist<t1,Parameterlist23(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24) >
407
408 #else
409
410 template<class Options,class parseResult> class CmdLineParser;
411 template <bool hasLongName, bool hasShortName, bool hasParameter,class parseResult> class CmdLineOption;
412 class nullType;
413 template<class CAR, class CDR> class typelist;
414 template<class tl, class parseResult> class CmdLineOptionList;
415
416 #endif /* HSADMIN_ABSTRACTCMDLINEPARSER */
417 };