summaryrefslogtreecommitdiff
path: root/src/stable/optparser.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/optparser.h')
-rw-r--r--src/stable/optparser.h223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/stable/optparser.h b/src/stable/optparser.h
new file mode 100644
index 0000000..f2fe531
--- /dev/null
+++ b/src/stable/optparser.h
@@ -0,0 +1,223 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_OPT_PARSER_H
9#define BU_OPT_PARSER_H
10
11#include "bu/string.h"
12#include "bu/list.h"
13#include "bu/hash.h"
14#include "bu/signals.h"
15#include "bu/array.h"
16#include "bu/membuf.h"
17#include "bu/formatter.h"
18#include "bu/variant.h"
19
20namespace Bu
21{
22 typedef Bu::Array<Bu::String> StrArray;
23
24 /**
25 * POSIX/Gnu style command line parser. Handles long and short options in
26 * a variety of fun and useful ways, along with singal based callbacks and
27 * automatic variable setting. It's pretty easy to use, and very flexible.
28 *
29 * OptParser supports it's own builtin help mechanism which automatically
30 * enumerates the available options and their help in a well formatted and
31 * easy to read way, automatically formatting your help text per option and
32 * allows for addition "help banners" which can be placed wherever you
33 * would like.
34 */
35 class OptParser
36 {
37 private:
38 class _ValueProxy
39 {
40 public:
41 _ValueProxy();
42 virtual ~_ValueProxy();
43
44 virtual void setValueFromStr( const Bu::String & )=0;
45 virtual void setValue( const Bu::Variant &vVar )=0;
46 virtual _ValueProxy *clone()=0;
47 };
48
49 template<typename ptype>
50 class ValueProxy : public _ValueProxy
51 {
52 public:
53 ValueProxy( ptype &v ) :
54 v( v )
55 {
56 }
57
58 virtual ~ValueProxy()
59 {
60 }
61
62 virtual void setValueFromStr( const Bu::String &sVal )
63 {
64 Bu::MemBuf mb( sVal );
65 Bu::Formatter f( mb );
66 f << Bu::Fmt().tokenize( false );
67 f >> v;
68 }
69
70 virtual void setValue( const Bu::Variant &vVar )
71 {
72 if( vVar.getType() == typeid(ptype) )
73 {
74 v = vVar.get<ptype>();
75 }
76 else if( vVar.getType() == typeid(Bu::String) )
77 {
78 setValueFromStr( vVar.get<Bu::String>() );
79 }
80 else
81 {
82 Bu::MemBuf mb;
83 Bu::Formatter f( mb );
84// f << vVar;
85 setValueFromStr( mb.getString() );
86 }
87 }
88
89 virtual _ValueProxy *clone()
90 {
91 return new ValueProxy<ptype>( v );
92 }
93
94 private:
95 ptype &v;
96 };
97
98 public:
99 typedef Signal1<int, StrArray> OptionSignal;
100 class Option
101 {
102 public:
103 Option();
104 Option( const Option &rSrc );
105 virtual ~Option();
106
107 char cOpt;
108 Bu::String sOpt;
109 Bu::String sHelp;
110 OptionSignal sUsed;
111 _ValueProxy *pProxy;
112 Bu::Variant sOverride;
113 Bu::String sHelpDefault;
114 };
115
116 private:
117 typedef Bu::List<Option> OptionList;
118 typedef Bu::Hash<char, Option *> ShortOptionHash;
119 typedef Bu::Hash<Bu::String, Option *> LongOptionHash;
120
121 class Banner
122 {
123 public:
124 Bu::String sText;
125 bool bFormatted;
126 OptionList::const_iterator iAfter;
127 };
128
129 typedef Bu::List<Banner> BannerList;
130
131 public:
132 OptParser();
133 virtual ~OptParser();
134
135 void parse( int argc, char **argv );
136 void parse( const Bu::String &sLine );
137
138 void addOption( const Option &opt );
139
140 template<typename vtype>
141 void addOption( vtype &var, char cOpt, const Bu::String &sOpt,
142 const Bu::String &sHelp )
143 {
144 Option o;
145 o.cOpt = cOpt;
146 o.sOpt = sOpt;
147 o.pProxy = new ValueProxy<vtype>( var );
148 o.sHelp = sHelp;
149 addOption( o );
150 }
151
152 template<typename vtype>
153 void addOption( vtype &var, const Bu::String &sOpt,
154 const Bu::String &sHelp )
155 {
156 addOption( var, '\0', sOpt, sHelp );
157 }
158
159 template<typename vtype>
160 void addOption( vtype &var, char cOpt, const Bu::String &sHelp )
161 {
162 addOption( var, cOpt, "", sHelp );
163 }
164
165 void addOption( OptionSignal sUsed, char cOpt, const Bu::String &sOpt,
166 const Bu::String &sHelp )
167 {
168 Option o;
169 o.cOpt = cOpt;
170 o.sOpt = sOpt;
171 o.sUsed = sUsed;
172 o.sHelp = sHelp;
173 addOption( o );
174 }
175
176 void addOption( OptionSignal sUsed, const Bu::String &sOpt,
177 const Bu::String &sHelp )
178 {
179 addOption( sUsed, '\0', sOpt, sHelp );
180 }
181
182 void addOption( OptionSignal sUsed, char cOpt,
183 const Bu::String &sHelp )
184 {
185 addOption( sUsed, cOpt, "", sHelp );
186 }
187
188 void setOverride( char cOpt, const Bu::Variant &sOverride );
189 void setOverride( const Bu::String &sOpt,
190 const Bu::Variant &sOverride );
191
192 void setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt );
193
194 void addHelpOption( char c='h', const Bu::String &s="help",
195 const Bu::String &sHelp="This help." );
196 void addHelpBanner( const Bu::String &sText, bool bFormatted=true );
197
198 int optHelp( StrArray aParams );
199
200 /**
201 * This function is called when an unrecognized option is found, the
202 * default behaviour is to print an error to stdout and exit( 1 ), if
203 * you want to do something different, just override this function.
204 * This is also called by default when something is found that hasn't
205 * been handled by an option, and isn't an option (starts with - or --).
206 * To change this behaviour call
207 */
208 virtual void optionError( const Bu::String &sOption );
209
210 void setNonOption( OptionSignal sSignal );
211
212 private:
213 Bu::String format( const Bu::String &sIn, int iWidth, int iIndent );
214
215 OptionList lOption;
216 ShortOptionHash hsOption;
217 LongOptionHash hlOption;
218 BannerList lBanner;
219 OptionSignal sNonOption;
220 };
221};
222
223#endif