File: arg.h

package info (click to toggle)
xstow 1.0.2-1
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 1,064 kB
  • ctags: 1,073
  • sloc: cpp: 7,264; sh: 1,216; makefile: 196; awk: 26
file content (467 lines) | stat: -rw-r--r-- 10,697 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
/*
 * $Log: arg.h,v $
 * Revision 1.3  2010/07/21 19:38:25  martin
 * gcc-4 Port
 *
 * Revision 1.2  2005/07/04 21:59:42  martin
 * added logging to all files
 *
 */
#ifndef arg_h
#define arg_h

/*
  Experimental Version of LeoArg 2
*/

#include <string>
#include <vector>
#include <list>

#include "ref.h"
#include "range.h"

namespace Arg {
  
  class Rule
    {
    protected:
      bool continue_on_match;
      bool continue_on_fail;

      std::string description;
      std::string error;

    public:
      
      Rule( bool com = true, bool cof = true );
      virtual ~Rule();

      virtual bool match( const std::string &value ) const = 0;
      virtual bool continueOnMatch() const;
      virtual bool continueOnFail() const;
      virtual bool matchEmpty() const;

      virtual void setDescription( const std::string &des );
      virtual std::string getDescription() const;
      virtual bool hasDescription() const;

      virtual std::string getError() const;
    };

  typedef std::vector<std::string> vec_string;

  class OptionNameRule : public Rule
    {
    protected:
      mutable Ref<vec_string> prefixes;
      mutable Ref<vec_string> names;

    public:
      OptionNameRule();
      OptionNameRule( Ref<vec_string> prefixes, Ref<vec_string> names );
      
      void setPrefixes( Ref<vec_string> p = Ref<vec_string>()) { prefixes = p; }
      void setNames( Ref<vec_string> n = Ref<vec_string>() ) { names = n; }

      Ref<vec_string> getNames() const { return names; }
      Ref<vec_string> getPrefixes() const { return prefixes; }

      bool match( const std::string &option ) const;

      std::string getDescription( unsigned int s1 = 5, unsigned int s2 = 40) const;
      bool hasDescription() const { return !names->empty(); }
    };

  template<class R, class S> bool convert( Ref<R> r, Ref<S> &s )
    {
      if( !r )
	return false;

      S *ss = dynamic_cast<S*>( r.address() );

      if( ss )
	{
	  s = Ref<S>(ss, false);
	  return true;
	}

      return false;
    }

  template<class S, class R> Ref<S> convert( Ref<R> r )
    {
      Ref<S> s;

      convert( r, s );
      
      return s;
    }

  class IsOptionRule : public Rule
    {
    protected:
      mutable Ref<vec_string> prefixes;

    public:
      IsOptionRule() : prefixes( new vec_string() ) {}
      IsOptionRule( Ref<vec_string> prefixes );

      void setPrefixes( Ref<vec_string> p = Ref<vec_string>() ) { prefixes = p; }
      Ref<vec_string> getPrefixes() const { return prefixes; }

      bool match( const std::string &option ) const;
    };
  
  class IsValueRule : public Rule
    {
    protected:
      mutable Ref<vec_string> states;
      bool cs;

    public:
      IsValueRule( bool cs = false );
      IsValueRule( Ref<vec_string> states, bool case_sensitiv = false);

      void setStates( Ref<vec_string> s ) { states = s; }
      Ref<vec_string> getStates() const { return states; }      

      bool match( const std::string &value ) const;

      std::string getDescription() const;
      bool hasDescription() const { return !states->empty(); }
    };

  class IsBoolRule : public IsValueRule
    {
    public:
      IsBoolRule();

      bool match( const std::string &value ) const;
      bool matchEmpty() const;
    };

  class AnyStringRule : public Rule
    {
    public:
      AnyStringRule() : Rule() {}

      bool match( const std::string &value ) const { return true; }
    };

  class IsIntRule : public Rule
    {
    public:
      IsIntRule();

      bool match( const std::string &value ) const;
    };

  class Option
    {
    public:

      static const unsigned int infinite = static_cast<unsigned int>( -1 );

    protected:
      
      mutable Ref< Rule > name_rule;  // check if option name is valid
      mutable Ref< Rule > value_rule; // check if the value is valid

      mutable Ref< vec_string > values;

      unsigned int min_values;
      unsigned int max_values;

      bool isset;
      bool required;

      std::string description;

      unsigned int option_id;

    public:
      Option();
      Option( Ref< Rule > name_rule, Ref< Rule > value_rule );
      virtual ~Option();

      void setNameRule( Ref< Rule > nr ) { name_rule = nr; }
      void setValueRule( Ref< Rule > vr ) { value_rule = vr; }

      Ref< Rule > getNameRule() const { return name_rule; }
      Ref< Rule > getValueRule() const { return value_rule; }

      unsigned int getMinValues() const { return min_values; }
      unsigned int getMaxValues() const { return max_values; }

      void setMinValues( unsigned int min ) { min_values = min; }
      void setMaxValues( unsigned int max ) { max_values = max; }

      bool matchName( const std::string &name ) const;
      bool matchValue( const std::string &value ) const;

      void addValue( const std::string &value ) { values->push_back( value ); }
      
      bool addName( const std::string &name );

      bool isSet() const { return isset; }
      void setSet( bool s ) { isset = s; }

      bool isRequired() const { return required; }
      void setRequired( bool r ) { required = r; }

      Ref< vec_string > getValues() const { return values; }

      void setDescription( const std::string &des ) { description = des; }
      virtual std::string getDescription( unsigned int s1 = 5, 
					  unsigned int s2 = 20, 
					  unsigned int s3 = 40, 
					  unsigned int console_width = 80 ) const;
      virtual bool hasDescription() const;

      unsigned int getId() const { return option_id; }
      void setId( unsigned int id ) { option_id = id; }

    };

  class BoolOption : public Option
    {
    public:
      BoolOption();
      BoolOption( const std::string &name );
      BoolOption( Ref< vec_string > names );

      bool getState() const;
    };

  class StringOption : public Option
    {
    public:
      StringOption();
      StringOption( const std::string &name, const std::string &value_description = "" );
      
      void setValueDescription( const std::string &description );
    };

  class EnumOption : public Option
    {
    public:
      explicit EnumOption( bool case_sensitiv = false );
      explicit EnumOption( const std::string &name, bool case_sensitiv = false );
      explicit EnumOption( const char *name, bool case_sensitiv = false );	

      void addEnum( const std::string &name );      
    };

  class EmptyOptionNameRule : public OptionNameRule
    {
    public:
      EmptyOptionNameRule();

      bool match( const std::string &option ) const;

      bool hasDescription() const { return false; }
    };

  class EmptyStringOption : public StringOption
    {
    public:
      EmptyStringOption();

      bool hasDescription() const { return false; }
    };

  class FlagOption : public BoolOption
    {
    public:
      FlagOption() : BoolOption() { setMaxValues(0); }
      FlagOption( const std::string &name ) 
	: BoolOption( name ) 
	{ 
	  setMaxValues(0); 
	}

      virtual std::string getDescription( unsigned int s1 = 5, 
					  unsigned int s2 = 20, 
					  unsigned int s3 = 40,
					  unsigned int console_width = 80 ) const;
    };

  class IntOption : public Option
    {
    public:
      IntOption();
      IntOption( const std::string &name );

    };

  struct EnumLink
  {
	enum ETYPE {
	  FIRST__,
	  AND,
	  OR,
	  LAST__
	};
  };
  
  typedef EnumRange<EnumLink> LINK;

  struct SOption
  {
    std::string option;
    vec_string  values;
  };

  typedef std::list<SOption> list_soption;

  class Arg;

  class OptionChain
    {
    public:

      typedef std::vector< Ref<Option> > rvec_option;

      struct Error
      {
	std::string err;
	std::string value;
	Ref<Option> option;	

	Error( Ref<Option> option, const std::string err, const std::string value )
	  : err( err ), value( value ), option( option )
	{}
      };

      typedef std::vector<Error> vec_err;

    protected:

      Ref<rvec_option> options;
      LINK mode;
      Ref<vec_string> prefixes;
      unsigned int min_match;

      bool continue_on_fail;
      bool continue_on_match;

      Arg *arg;

      vec_err err_options;

    public:
      OptionChain( LINK m = LINK::OR );

      void addOption( Ref<Option> option );

      template<class X> void addOption( Ref<X> option )
	{
	  addOption( Ref<Option>( *option, false ) );
	}

      template<class X> void addOptionR( X* option )
	{
	  addOption( Ref<Option>( *option, false ) );
	}
      
      Ref<vec_string> getPrefixes() const { return prefixes; }
      void setPrefixes( Ref<vec_string> p ) { prefixes = p; }

      unsigned int getMinMatch() const { return min_match; }
      void setMinMatch( unsigned int val ) { min_match = val; }

      bool parse( list_soption &arg );

      bool getContinueOnFail() const { return continue_on_fail; }
      void setContinueOnFail( bool cof ) { continue_on_fail = cof; }

      bool getContinueOnMatch() const { return continue_on_match; }
      void setContinueOnMatch( bool com ) { continue_on_match = com; }

      void setArg( Arg *arg_ ) { arg = arg_; }

      vec_err getErrOptions() const { return err_options; }
    };

  class Arg
    {
    public:

    protected:
      
      std::vector<Ref<OptionChain> > chains;
      mutable std::vector<Ref<Option> > options; // for help page

      int argc;
      char **argv;

      Ref<Rule> is_option;
      Ref<vec_string> prefixes;

      unsigned int min_match;

      unsigned int option_id;

    public:

      Arg( int argc, char **argv );

      void addPrefix( const std::string &s );

      void addChain( Ref<OptionChain> chain );

      template<class X> void addChainR( X* chain )
	{
	  addChain( Ref<OptionChain>( *chain, false ) );
	}

      void addOption( Ref<Option> option );

      template<class X> void addOption( Ref<X> option )
	{
	  addOption( Ref<Option>(  *option, false ) );
	}

      template<class X> void addOptionR( X* option )
	{
	  addOption( Ref<Option>( *option, false ) );
	}

      bool parse();

      void setMinMatch( unsigned int mm  ) { min_match = mm; }

      void addHelp( Ref<Option> option );

      template<class X> void addHelpR( X* help )
	{ 
	  addHelp( Ref<Option>( *help, false ) );
	}

      std::string getHelp( unsigned int s1 = 5, 
			   unsigned int s2 = 20, 
			   unsigned int s3 = 40, unsigned int console_width = 80 ) const;

      unsigned int getOptionId() { return option_id++; }

    private:

      list_soption parse_args();

    };

  inline bool operator==( const Option &a, const Option &b );

  std::ostream& operator<<( std::ostream& out, OptionChain::vec_err & err );


  int get_terminal_width(); 

} // namespace Arg


std::ostream& operator<<( std::ostream& out, Ref<Arg::vec_string> values );


#endif