1/* $Id: CoinParam.hpp 1494 2011-11-01 16:58:47Z tkr $ */
2#ifndef CoinParam_H
3#define CoinParam_H
4
5/*
6 Copyright (C) 2002, International Business Machines
7 Corporation and others. All Rights Reserved.
8
9 This code is licensed under the terms of the Eclipse Public License (EPL).
10*/
11
12/*! \file CoinParam.hpp
13 \brief Declaration of a class for command line parameters.
14*/
15
16#include <vector>
17#include <string>
18#include <cstdio>
19
20/*! \class CoinParam
21 \brief A base class for `keyword value' command line parameters.
22
23 The underlying paradigm is that a parameter specifies an action to be
24 performed on a target object. The base class provides two function
25 pointers, a `push' function and a `pull' function. By convention, a push
26 function will set some value in the target object or perform some action
27 using the target object. A `pull' function will retrieve some value from
28 the target object. This is only a convention, however; CoinParam and
29 associated utilities make no use of these functions and have no hardcoded
30 notion of how they should be used.
31
32 The action to be performed, and the target object, will be specific to a
33 particular application. It is expected that users will derive
34 application-specific parameter classes from this base class. A derived
35 class will typically add fields and methods to set/get a code for the
36 action to be performed (often, an enum class) and the target object (often,
37 a pointer or reference).
38
39 Facilities provided by the base class and associated utility routines
40 include:
41 <ul>
42 <li> Support for common parameter types with numeric, string, or
43 keyword values.
44 <li> Support for short and long help messages.
45 <li> Pointers to `push' and `pull' functions as described above.
46 <li> Command line parsing and keyword matching.
47 </ul>
48 All utility routines are declared in the #CoinParamUtils namespace.
49
50 The base class recognises five types of parameters: actions (which require
51 no value); numeric parameters with integer or real (double) values; keyword
52 parameters, where the value is one of a defined set of value-keywords;
53 and string parameters (where the value is a string).
54 The base class supports the definition of a valid range, a default value,
55 and short and long help messages for a parameter.
56
57 As defined by the #CoinParamFunc typedef, push and pull functions
58 should take a single parameter, a pointer to a CoinParam. Typically this
59 object will actually be a derived class as described above, and the
60 implementation function will have access to all capabilities of CoinParam and
61 of the derived class.
62
63 When specified as command line parameters, the expected syntax is `-keyword
64 value' or `-keyword=value'. You can also use the Gnu double-dash style,
65 `--keyword'. Spaces around the `=' will \e not work.
66
67 The keyword (name) for a parameter can be defined with an `!' to mark the
68 minimal match point. For example, allow!ableGap will be considered matched
69 by the strings `allow', `allowa', `allowab', \e etc. Similarly, the
70 value-keyword strings for keyword parameters can be defined with `!' to
71 mark the minimal match point. Matching of keywords and value-keywords is
72 \e not case sensitive.
73*/
74
75class CoinParam
76{
77
78public:
79
80/*! \name Subtypes */
81//@{
82
83 /*! \brief Enumeration for the types of parameters supported by CoinParam
84
85 CoinParam provides support for several types of parameters:
86 <ul>
87 <li> Action parameters, which require no value.
88 <li> Integer and double numeric parameters, with upper and lower bounds.
89 <li> String parameters that take an arbitrary string value.
90 <li> Keyword parameters that take a defined set of string (value-keyword)
91 values. Value-keywords are associated with integers in the order in
92 which they are added, starting from zero.
93 </ul>
94 */
95 typedef enum { coinParamInvalid = 0,
96 coinParamAct, coinParamInt, coinParamDbl,
97 coinParamStr, coinParamKwd } CoinParamType ;
98
99 /*! \brief Type declaration for push and pull functions.
100
101 By convention, a return code of 0 indicates execution without error, >0
102 indicates nonfatal error, and <0 indicates fatal error. This is only
103 convention, however; the base class makes no use of the push and pull
104 functions and has no hardcoded interpretation of the return code.
105 */
106 typedef int (*CoinParamFunc)(CoinParam *param) ;
107
108//@}
109
110/*! \name Constructors and Destructors
111
112 Be careful how you specify parameters for the constructors! Some compilers
113 are entirely too willing to convert almost anything to bool.
114*/
115//@{
116
117 /*! \brief Default constructor */
118
119 CoinParam() ;
120
121 /*! \brief Constructor for a parameter with a double value
122
123 The default value is 0.0. Be careful to clearly indicate that \p lower and
124 \p upper are real (double) values to distinguish this constructor from the
125 constructor for an integer parameter.
126 */
127 CoinParam(std::string name, std::string help,
128 double lower, double upper, double dflt = 0.0,
129 bool display = true) ;
130
131 /*! \brief Constructor for a parameter with an integer value
132
133 The default value is 0.
134 */
135 CoinParam(std::string name, std::string help,
136 int lower, int upper, int dflt = 0,
137 bool display = true) ;
138
139 /*! \brief Constructor for a parameter with keyword values
140
141 The string supplied as \p firstValue becomes the first value-keyword.
142 Additional value-keywords can be added using appendKwd(). It's necessary
143 to specify both the first value-keyword (\p firstValue) and the default
144 value-keyword index (\p dflt) in order to distinguish this constructor
145 from the constructors for string and action parameters.
146
147 Value-keywords are associated with an integer, starting with zero and
148 increasing as each keyword is added. The value-keyword given as \p
149 firstValue will be associated with the integer zero. The integer supplied
150 for \p dflt can be any value, as long as it will be valid once all
151 value-keywords have been added.
152 */
153 CoinParam(std::string name, std::string help,
154 std::string firstValue, int dflt, bool display = true) ;
155
156 /*! \brief Constructor for a string parameter
157
158 For some compilers, the default value (\p dflt) must be specified
159 explicitly with type std::string to distinguish the constructor for a
160 string parameter from the constructor for an action parameter. For
161 example, use std::string("default") instead of simply "default", or use a
162 variable of type std::string.
163 */
164 CoinParam(std::string name, std::string help,
165 std::string dflt, bool display = true) ;
166
167 /*! \brief Constructor for an action parameter */
168
169 CoinParam(std::string name, std::string help,
170 bool display = true) ;
171
172 /*! \brief Copy constructor */
173
174 CoinParam(const CoinParam &orig) ;
175
176 /*! \brief Clone */
177
178 virtual CoinParam *clone() ;
179
180 /*! \brief Assignment */
181
182 CoinParam &operator=(const CoinParam &rhs) ;
183
184 /*! \brief Destructor */
185
186 virtual ~CoinParam() ;
187
188//@}
189
190/*! \name Methods to query and manipulate the value(s) of a parameter */
191//@{
192
193 /*! \brief Add an additional value-keyword to a keyword parameter */
194
195 void appendKwd(std::string kwd) ;
196
197 /*! \brief Return the integer associated with the specified value-keyword
198
199 Returns -1 if no value-keywords match the specified string.
200 */
201 int kwdIndex(std::string kwd) const ;
202
203 /*! \brief Return the value-keyword that is the current value of the
204 keyword parameter
205 */
206 std::string kwdVal() const ;
207
208 /*! \brief Set the value of the keyword parameter using the integer
209 associated with a value-keyword.
210
211 If \p printIt is true, the corresponding value-keyword string will be
212 echoed to std::cout.
213 */
214 void setKwdVal(int value, bool printIt = false) ;
215
216 /*! \brief Set the value of the keyword parameter using a value-keyword
217 string.
218
219 The given string will be tested against the set of value-keywords for
220 the parameter using the shortest match rules.
221 */
222 void setKwdVal(const std::string value ) ;
223
224 /*! \brief Prints the set of value-keywords defined for this keyword
225 parameter
226 */
227 void printKwds() const ;
228
229
230 /*! \brief Set the value of a string parameter */
231
232 void setStrVal(std::string value) ;
233
234 /*! \brief Get the value of a string parameter */
235
236 std::string strVal() const ;
237
238
239 /*! \brief Set the value of a double parameter */
240
241 void setDblVal(double value) ;
242
243 /*! \brief Get the value of a double parameter */
244
245 double dblVal() const ;
246
247
248 /*! \brief Set the value of a integer parameter */
249
250 void setIntVal(int value) ;
251
252 /*! \brief Get the value of a integer parameter */
253
254 int intVal() const ;
255
256
257 /*! \brief Add a short help string to a parameter */
258
259 inline void setShortHelp(const std::string help) { shortHelp_ = help ; }
260
261 /*! \brief Retrieve the short help string */
262
263 inline std::string shortHelp() const { return (shortHelp_) ; }
264
265 /*! \brief Add a long help message to a parameter
266
267 See printLongHelp() for a description of how messages are broken into
268 lines.
269 */
270 inline void setLongHelp(const std::string help) { longHelp_ = help ; }
271
272 /*! \brief Retrieve the long help message */
273
274 inline std::string longHelp() const { return (longHelp_) ; }
275
276 /*! \brief Print long help
277
278 Prints the long help string, plus the valid range and/or keywords if
279 appropriate. The routine makes a best effort to break the message into
280 lines appropriate for an 80-character line. Explicit line breaks in the
281 message will be observed. The short help string will be used if
282 long help is not available.
283 */
284 void printLongHelp() const ;
285
286//@}
287
288/*! \name Methods to query and manipulate a parameter object */
289//@{
290
291 /*! \brief Return the type of the parameter */
292
293 inline CoinParamType type() const { return (type_) ; }
294
295 /*! \brief Set the type of the parameter */
296
297 inline void setType(CoinParamType type) { type_ = type ; }
298
299 /*! \brief Return the parameter keyword (name) string */
300
301 inline std::string name() const { return (name_) ; }
302
303 /*! \brief Set the parameter keyword (name) string */
304
305 inline void setName(std::string name) { name_ = name ; processName() ; }
306
307 /*! \brief Check if the specified string matches the parameter keyword (name)
308 string
309
310 Returns 1 if the string matches and meets the minimum match length,
311 2 if the string matches but doesn't meet the minimum match length,
312 and 0 if the string doesn't match. Matches are \e not case-sensitive.
313 */
314 int matches (std::string input) const ;
315
316 /*! \brief Return the parameter keyword (name) string formatted to show
317 the minimum match length
318
319 For example, if the parameter name was defined as allow!ableGap, the
320 string returned by matchName would be allow(ableGap).
321 */
322 std::string matchName() const ;
323
324 /*! \brief Set visibility of parameter
325
326 Intended to control whether the parameter is shown when a list of
327 parameters is processed. Used by CoinParamUtils::printHelp when printing
328 help messages for a list of parameters.
329 */
330 inline void setDisplay(bool display) { display_ = display ; }
331
332 /*! \brief Get visibility of parameter */
333
334 inline bool display() const { return (display_) ; }
335
336 /*! \brief Get push function */
337
338 inline CoinParamFunc pushFunc() { return (pushFunc_) ; }
339
340 /*! \brief Set push function */
341
342 inline void setPushFunc(CoinParamFunc func) { pushFunc_ = func ; }
343
344 /*! \brief Get pull function */
345
346 inline CoinParamFunc pullFunc() { return (pullFunc_) ; }
347
348 /*! \brief Set pull function */
349
350 inline void setPullFunc(CoinParamFunc func) { pullFunc_ = func ; }
351
352//@}
353
354private:
355
356/*! \name Private methods */
357//@{
358
359 /*! Process a name for efficient matching */
360 void processName() ;
361
362//@}
363
364/*! \name Private parameter data */
365//@{
366 /// Parameter type (see #CoinParamType)
367 CoinParamType type_ ;
368
369 /// Parameter name
370 std::string name_ ;
371
372 /// Length of parameter name
373 size_t lengthName_ ;
374
375 /*! \brief Minimum length required to declare a match for the parameter
376 name.
377 */
378 size_t lengthMatch_ ;
379
380 /// Lower bound on value for a double parameter
381 double lowerDblValue_ ;
382
383 /// Upper bound on value for a double parameter
384 double upperDblValue_ ;
385
386 /// Double parameter - current value
387 double dblValue_ ;
388
389 /// Lower bound on value for an integer parameter
390 int lowerIntValue_ ;
391
392 /// Upper bound on value for an integer parameter
393 int upperIntValue_ ;
394
395 /// Integer parameter - current value
396 int intValue_ ;
397
398 /// String parameter - current value
399 std::string strValue_ ;
400
401 /// Set of valid value-keywords for a keyword parameter
402 std::vector<std::string> definedKwds_ ;
403
404 /*! \brief Current value for a keyword parameter (index into #definedKwds_)
405 */
406 int currentKwd_ ;
407
408 /// Push function
409 CoinParamFunc pushFunc_ ;
410
411 /// Pull function
412 CoinParamFunc pullFunc_ ;
413
414 /// Short help
415 std::string shortHelp_ ;
416
417 /// Long help
418 std::string longHelp_ ;
419
420 /// Display when processing lists of parameters?
421 bool display_ ;
422//@}
423
424} ;
425
426/*! \relatesalso CoinParam
427 \brief A type for a parameter vector.
428*/
429typedef std::vector<CoinParam*> CoinParamVec ;
430
431/*! \relatesalso CoinParam
432 \brief A stream output function for a CoinParam object.
433*/
434std::ostream &operator<< (std::ostream &s, const CoinParam &param) ;
435
436/*
437 Bring in the utility functions for parameter handling (CbcParamUtils).
438*/
439
440/*! \brief Utility functions for processing CoinParam parameters.
441
442 The functions in CoinParamUtils support command line or interactive
443 parameter processing and a help facility. Consult the `Related Functions'
444 section of the CoinParam class documentation for individual function
445 documentation.
446*/
447namespace CoinParamUtils {
448 /*! \relatesalso CoinParam
449 \brief Take command input from the file specified by src.
450
451 Use stdin for \p src to specify interactive prompting for commands.
452 */
453 void setInputSrc(FILE *src) ;
454
455 /*! \relatesalso CoinParam
456 \brief Returns true if command line parameters are being processed.
457 */
458 bool isCommandLine() ;
459
460 /*! \relatesalso CoinParam
461 \brief Returns true if parameters are being obtained from stdin.
462 */
463 bool isInteractive() ;
464
465 /*! \relatesalso CoinParam
466 \brief Attempt to read a string from the input.
467
468 \p argc and \p argv are used only if isCommandLine() would return true.
469 If \p valid is supplied, it will be set to 0 if a string is parsed
470 without error, 2 if no field is present.
471 */
472 std::string getStringField(int argc, const char *argv[], int *valid) ;
473
474 /*! \relatesalso CoinParam
475 \brief Attempt to read an integer from the input.
476
477 \p argc and \p argv are used only if isCommandLine() would return true.
478 If \p valid is supplied, it will be set to 0 if an integer is parsed
479 without error, 1 if there's a parse error, and 2 if no field is present.
480 */
481 int getIntField(int argc, const char *argv[], int *valid) ;
482
483 /*! \relatesalso CoinParam
484 \brief Attempt to read a real (double) from the input.
485
486 \p argc and \p argv are used only if isCommandLine() would return true.
487 If \p valid is supplied, it will be set to 0 if a real number is parsed
488 without error, 1 if there's a parse error, and 2 if no field is present.
489 */
490 double getDoubleField(int argc, const char *argv[], int *valid) ;
491
492 /*! \relatesalso CoinParam
493 \brief Scan a parameter vector for parameters whose keyword (name) string
494 matches \p name using minimal match rules.
495
496 \p matchNdx is set to the index of the last parameter that meets the
497 minimal match criteria (but note there should be at most one matching
498 parameter if the parameter vector is properly configured). \p shortCnt
499 is set to the number of short matches (should be zero for a properly
500 configured parameter vector if a minimal match is found). The return
501 value is the number of matches satisfying the minimal match requirement
502 (should be 0 or 1 in a properly configured vector).
503 */
504 int matchParam(const CoinParamVec &paramVec, std::string name,
505 int &matchNdx, int &shortCnt) ;
506
507 /*! \relatesalso CoinParam
508 \brief Get the next command keyword (name)
509
510 To be precise, return the next field from the current command input
511 source, after a bit of processing. In command line mode (isCommandLine()
512 returns true) the next field will normally be of the form `-keyword' or
513 `--keyword' (\e i.e., a parameter keyword), and the string returned would
514 be `keyword'. In interactive mode (isInteractive() returns true), the
515 user will be prompted if necessary. It is assumed that the user knows
516 not to use the `-' or `--' prefixes unless specifying parameters on the
517 command line.
518
519 There are a number of special cases if we're in command line mode. The
520 order of processing of the raw string goes like this:
521 <ul>
522 <li> A stand-alone `-' is forced to `stdin'.
523 <li> A stand-alone '--' is returned as a word; interpretation is up to
524 the client.
525 <li> A prefix of '-' or '--' is stripped from the string.
526 </ul>
527 If the result is the string `stdin', command processing shifts to
528 interactive mode and the user is immediately prompted for a new command.
529
530 Whatever results from the above sequence is returned to the user as the
531 return value of the function. An empty string indicates end of input.
532
533 \p prompt will be used only if it's necessary to prompt the user in
534 interactive mode.
535 */
536
537 std::string getCommand(int argc, const char *argv[],
538 const std::string prompt, std::string *pfx = nullptr) ;
539
540 /*! \relatesalso CoinParam
541 \brief Look up the command keyword (name) in the parameter vector.
542 Print help if requested.
543
544 In the most straightforward use, \p name is a string without `?', and the
545 value returned is the index in \p paramVec of the single parameter that
546 matched \p name. One or more '?' characters at the end of \p name is a
547 query for information. The routine prints short (one '?') or long (more
548 than one '?') help messages for a query. Help is also printed in the case
549 where the name is ambiguous (some of the matches did not meet the minimal
550 match length requirement).
551
552 Note that multiple matches meeting the minimal match requirement is a
553 configuration error. The mimimal match length for the parameters
554 involved is too short.
555
556 If provided as parameters, on return
557 <ul>
558 <li> \p matchCnt will be set to the number of matches meeting the
559 minimal match requirement
560 <li> \p shortCnt will be set to the number of matches that did not
561 meet the miminal match requirement
562 <li> \p queryCnt will be set to the number of '?' characters at the
563 end of the name
564 </ul>
565
566 The return values are:
567 <ul>
568 <li> >0: index in \p paramVec of the single unique match for \p name
569 <li> -1: a query was detected (one or more '?' characters at the end
570 of \p name
571 <li> -2: one or more short matches, not a query
572 <li> -3: no matches, not a query
573 <li> -4: multiple matches meeting the minimal match requirement
574 (configuration error)
575 </ul>
576 */
577 int lookupParam(std::string name, CoinParamVec &paramVec,
578 int *matchCnt = nullptr, int *shortCnt = nullptr, int *queryCnt = nullptr) ;
579
580 /*! \relatesalso CoinParam
581 \brief Utility to print a long message as filled lines of text
582
583 The routine makes a best effort to break lines without exceeding the
584 standard 80 character line length. Explicit newlines in \p msg will
585 be obeyed.
586 */
587 void printIt(const char *msg) ;
588
589 /*! \relatesalso CoinParam
590 \brief Utility routine to print help given a short match or explicit
591 request for help.
592
593 The two really are related, in that a query (a string that ends with
594 one or more `?' characters) will often result in a short match. The
595 routine expects that \p name matches a single parameter, and does not
596 look for multiple matches.
597
598 If called with \p matchNdx < 0, the routine will look up \p name in \p
599 paramVec and print the full name from the parameter. If called with \p
600 matchNdx > 0, it just prints the name from the specified parameter. If
601 the name is a query, short (one '?') or long (more than one '?') help
602 is printed.
603
604 */ void shortOrHelpOne(CoinParamVec &paramVec,int matchNdx, std::string
605 name, int numQuery) ;
606
607 /*! \relatesalso CoinParam
608 \brief Utility routine to print help given multiple matches.
609
610 If the name is not a query, or asks for short help (\e i.e., contains
611 zero or one '?' characters), the list of matching names is printed. If
612 the name asks for long help (contains two or more '?' characters),
613 short help is printed for each matching name.
614 */
615 void shortOrHelpMany(CoinParamVec &paramVec,
616 std::string name, int numQuery) ;
617
618 /*! \relatesalso CoinParam
619 \brief Print a generic `how to use the command interface' help message.
620
621 The message is hard coded to match the behaviour of the parsing utilities.
622 */
623 void printGenericHelp() ;
624
625 /*! \relatesalso CoinParam
626 \brief Utility routine to print help messages for one or more
627 parameters.
628
629 Intended as a utility to implement explicit `help' commands. Help will be
630 printed for all parameters in \p paramVec from \p firstParam to \p
631 lastParam, inclusive. If \p shortHelp is true, short help messages will
632 be printed. If \p longHelp is true, long help messages are printed. \p
633 shortHelp overrules \p longHelp. If neither is true, only command
634 keywords are printed. \p prefix is printed before each line; it's an
635 imperfect attempt at indentation.
636 */
637 void printHelp(CoinParamVec &paramVec, int firstParam, int lastParam,
638 std::string prefix,
639 bool shortHelp, bool longHelp, bool hidden) ;
640}
641
642
643#endif /* CoinParam_H */
644