1 /*
2  *
3  *  Copyright (C) 1998-2019, OFFIS e.V.
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  This software and supporting documentation were developed by
7  *
8  *    OFFIS e.V.
9  *    R&D Division Health
10  *    Escherweg 2
11  *    D-26121 Oldenburg, Germany
12  *
13  *
14  *  Module:  ofstd
15  *
16  *  Author:  Joerg Riesmeier
17  *
18  *  Purpose: Handle command line arguments (Header)
19  *
20  */
21 
22 
23 #ifndef OFCMDLN_H
24 #define OFCMDLN_H
25 
26 #include "dcmtk/config/osconfig.h"
27 #include "dcmtk/ofstd/oftypes.h"
28 #include "dcmtk/ofstd/ofexbl.h"
29 #include "dcmtk/ofstd/oflist.h"
30 #include "dcmtk/ofstd/ofstring.h"
31 #include "dcmtk/ofstd/ofconsol.h"
32 #include "dcmtk/ofstd/offile.h"
33 
34 #define INCLUDE_CSTDIO
35 #include "dcmtk/ofstd/ofstdinc.h"
36 
37 
38 /*--------------------*
39  *  macro definition  *
40  *--------------------*/
41 
42 // Only use wchar_t on windows (not mingw) and don't use it on MSC6
43 #if defined(HAVE_WINDOWS_H) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER > 1200)
44 # define DCMTK_USE_WCHAR_T
45 #endif
46 #if defined(WIDE_CHAR_MAIN_FUNCTION) && defined(DCMTK_USE_WCHAR_T)
47 // Windows-specific version supporting wide character encoding (UTF-16)
48 # define DCMTK_MAIN_FUNCTION int wmain(int argc, wchar_t *argv[])
49 #else
50 // default version supporting various character encodings (incl. UTF-8)
51 # define DCMTK_MAIN_FUNCTION int main(int argc, char *argv[])
52 #endif
53 
54 
55 /*--------------------*
56  *  type declaration  *
57  *--------------------*/
58 
59 /// signed integer value
60 typedef signed long OFCmdSignedInt;
61 /// unsigned integer value
62 typedef unsigned long OFCmdUnsignedInt;
63 /// floating point value
64 typedef double OFCmdFloat;
65 /// dynamic string value
66 typedef OFString OFCmdString;
67 
68 // necessary for MSVC5 :-/
69 typedef OFListIterator(OFString) OFListIterator_OFString;
70 
71 
72 /*------------------------*
73  *  forward declarations  *
74  *------------------------*/
75 
76 struct OFCmdOption;
77 struct OFCmdParamPos;
78 
79 
80 /*----------------------*
81  *  struct declaration  *
82  *----------------------*/
83 
84 /** Internal structure to store valid command line parameters.
85  *  Parameters are all command line arguments which are no options (e.g. file names).
86  */
87 struct DCMTK_OFSTD_EXPORT OFCmdParam
88 {
89 
90     /** mode specifying parameter's cardinality
91      */
92     enum E_ParamMode
93     {
94         /// parameter is required (# = 1), "option"
95         PM_Mandatory,
96         /// parameter is optional (# = 0..1), "[option]"
97         PM_Optional,
98         /// parameter is required, more than one value is allowed (# = 1..n), "option..."
99         PM_MultiMandatory,
100         /// parameter is optional, more than one value is allowed (# = 0..n), "[option...]"
101         PM_MultiOptional
102     };
103 
104     /** constructor
105      *
106      ** @param  param  parameter name
107      *  @param  descr  parameter description
108      *  @param  mode   parameter's cardinality mode
109      */
OFCmdParamOFCmdParam110     OFCmdParam(const char *param,
111                const char *descr,
112                const E_ParamMode mode)
113       : ParamName(param),
114         ParamDescription(descr),
115         ParamMode(mode)
116     {
117     }
118 
119     /// parameter name
120     const OFString ParamName;
121     /// parameter description
122     const OFString ParamDescription;
123     /// parameter's cardinality mode
124     const E_ParamMode ParamMode;
125 
126 private:
127 
128     /// private undefined assignment operator
129     OFCmdParam& operator=(const OFCmdParam& arg);
130 };
131 
132 
133 /*---------------------*
134  *  class declaration  *
135  *---------------------*/
136 
137 /** handles command line arguments.
138  *  This class is the interface to this module.
139  *  All methods which can be used from outside are defined here.
140  */
141 class DCMTK_OFSTD_EXPORT OFCommandLine
142 {
143 
144  public:
145 
146  // --- enumerations
147 
148     /** status of command line parsing
149      */
150     enum E_ParseStatus
151     {
152         /// normal, no errors
153         PS_Normal,
154         /// no arguments to be parsed
155         PS_NoArguments,
156         /// exclusive option used
157         PS_ExclusiveOption,
158         /// unknown option detected
159         PS_UnknownOption,
160         /// missing value(s) for an option
161         PS_MissingValue,
162         /// missing parameter
163         PS_MissingParameter,
164         /// too many parameters
165         PS_TooManyParameters,
166         /// cannot open command file
167         PS_CannotOpenCommandFile
168     };
169 
170 
171     /** status of converting string option value to value field
172      */
173     enum E_ValueStatus
174     {
175         /// normal, no errors
176         VS_Normal,
177         /// argument contains invalid char(s)
178         VS_Invalid,
179         /// no more arguments to be converted
180         VS_NoMore,
181         /// empty string argument
182         VS_Empty,
183         /// converted value falls below minimum
184         VS_Underflow,
185         /// converted value exceeds maximum
186         VS_Overflow
187     };
188 
189 
190     /** status of converting string parameter to value field
191      */
192     enum E_ParamValueStatus
193     {
194         /// normal, no errors
195         PVS_Normal,
196         /// argument contains invalid char(s)
197         PVS_Invalid,
198         /// specified parameter doesn't exist
199         PVS_CantFind,
200         /// empty string argument
201         PVS_Empty,
202         /// converted value falls below minimum
203         PVS_Underflow,
204         /// converted value exceeds maximum
205         PVS_Overflow
206     };
207 
208     /** mode for findOption() method
209      */
210     enum E_FindOptionMode
211     {
212         /// normal find
213         FOM_Normal,
214         /// find first option
215         FOM_First,
216         /// find next option
217         FOM_Next,
218         /// find first option (from left to right)
219         FOM_FirstFromLeft,
220         /// find next option (from left to right)
221         FOM_NextFromLeft
222     };
223 
224 
225  // --- constructor and destructor
226 
227     /** constructor
228      */
229     OFCommandLine();
230 
231     /** destructor
232      */
233     virtual ~OFCommandLine();
234 
235 
236  // --- initialization
237 
238     /** sets characters used to detect options
239      *
240      ** @param  chars  string containing all valid option characters (default: "+-")
241      */
242     void setOptionChars(const char *chars);
243 
244     /** sets default width of option columns
245      *
246      *  @param  longCols   minimum width of the long option column
247      *  @param  shortCols  minimum width of the short option column
248      */
249     void setOptionColumns(const int longCols,
250                           const int shortCols);
251 
252     /** sets default width of parameter column
253      *
254      *  @param  column  minimum width of the long option column
255      */
256     void setParamColumn(const int column);
257 
258     /** generates all exclusive options in "general" group (top-level).
259      *  The following options belong to this group:
260      *  - --help (-h): prints the help text and exits
261      *  - --version: prints version information and exit
262      *
263      *  @param  longCols   minimum width of the long option column
264      *  @param  shortCols  minimum width of the short option column
265      */
266     void addGeneralOptions(const int longCols = 0,
267                            const int shortCols = 0);
268 
269     /** adds an item to the list of valid options
270      *  (full version)
271      *
272      ** @param  longOpt     long option name
273      *  @param  shortOpt    short option name
274      *  @param  valueCount  number of additional values
275      *  @param  valueDescr  description of optional values
276      *  @param  optDescr    description of command line option (use '\\n' for line break)
277      *  @param  flags       optional flags (see AF_xxx below)
278      *
279      ** @return OFTrue if successfully added
280      */
281     OFBool addOption(const char *longOpt,
282                      const char *shortOpt,
283                      const int valueCount,
284                      const char *valueDescr,
285                      const char *optDescr,
286                      const int flags = 0);
287 
288     /** adds an item to the list of valid options
289      *  (without additional values)
290      *
291      ** @param  longOpt   long option name
292      *  @param  shortOpt  short option name
293      *  @param  optDescr  description of command line option (use '\\n' for line break)
294      *  @param  flags     optional flags (see AF_xxx below)
295      *
296      ** @return OFTrue if successfully added
297      */
298     OFBool addOption(const char *longOpt,
299                      const char *shortOpt,
300                      const char *optDescr,
301                      const int flags = 0);
302 
303     /** adds an item to the list of valid options
304      *  (without short name)
305      *
306      ** @param  longOpt     long option name
307      *  @param  valueCount  number of additional values
308      *  @param  valueDescr  description of optional values
309      *  @param  optDescr    description of command line option (use '\\n' for line break)
310      *  @param  flags       optional flags (see AF_xxx below)
311      *
312      ** @return OFTrue if successfully added
313      */
314     OFBool addOption(const char *longOpt,
315                      const int valueCount,
316                      const char *valueDescr,
317                      const char *optDescr,
318                      const int flags = 0);
319 
320     /** adds an item to the list of valid options
321      *  (without short name and additional values)
322      *
323      ** @param  longOpt   long option name
324      *  @param  optDescr  description of command line option (use '\\n' for line break)
325      *  @param  flags     optional flags (see AF_xxx below)
326      *
327      ** @return OFTrue if successfully added
328      */
329     OFBool addOption(const char *longOpt,
330                      const char *optDescr,
331                      const int flags = 0);
332 
333     /** adds a new group (top-level).
334      *  all following options belong to this group
335      *
336      ** @param  name       name of the group
337      *  @param  longCols   minimum width of the long option column
338      *  @param  shortCols  minimum width of the short option column
339      */
340     void addGroup(const char *name,
341                   const int longCols = 0,
342                   const int shortCols = 0);
343 
344     /** adds a new subgroup (beyond group-level).
345      *  all following options belong to this subgroup
346      *
347      ** @param  name       name of the subgroup
348      *  @param  longCols   minimum width of the long option column
349      *  @param  shortCols  minimum width of the short option column
350      */
351     void addSubGroup(const char *name,
352                      const int longCols = 0,
353                      const int shortCols = 0);
354 
355     /** adds an item to the list of valid parameters
356      *  (full version)
357      *
358      ** @param  param  parameter name
359      *  @param  descr  parameter description (use '\\n' for line break)
360      *  @param  mode   parameter's cardinality (see above)
361      *
362      ** @return OFTrue if successful, OFFalse otherwise
363      */
364     OFBool addParam(const char *param,
365                     const char *descr,
366                     const OFCmdParam::E_ParamMode mode = OFCmdParam::PM_Mandatory);
367 
368     /** adds an item to the list of valid parameters
369      *  (without description)
370      *
371      ** @param  param  parameter name
372      *  @param  mode   parameter's cardinality (see above)
373      *
374      ** @return OFTrue if successful, OFFalse otherwise
375      */
376     OFBool addParam(const char *param,
377                     const OFCmdParam::E_ParamMode mode = OFCmdParam::PM_Mandatory);
378 
379 
380  // --- get information
381 
382     /** get the name of the program (i.e. the value of argv[0])
383      *
384      ** @return name of the program
385      */
getProgramName()386     const OFString &getProgramName() const
387     {
388         return ProgramName;
389     }
390 
391     /** gets number of command line arguments.
392      *  (options and parameters)
393      *
394      ** @return number of command line arguments
395      */
getArgCount()396     int getArgCount() const
397     {
398         return OFstatic_cast(int, ArgumentList.size());
399     }
400 
401     /** sets first command line argument as the current one.
402      *  Useful for iterating over all arguments.
403      *
404      ** @return OFTrue if successful, OFFalse otherwise
405      */
406     OFBool gotoFirstArg();
407 
408     /** sets next command line argument as the current one.
409      *  Useful for iterating over all arguments.
410      *
411      ** @return OFTrue if successful, OFFalse otherwise
412      */
413     OFBool gotoNextArg();
414 
415     /** gets current command line argument as a C string
416      *  This is the argument which is currently parsed or has been selected as
417      *  the current one by gotoXXXArg().
418      ** @param  arg  reference to C string where argument should be stored
419      *
420      ** @return OFTrue if successful, OFFalse otherwise
421      */
422     OFBool getCurrentArg(const char *&arg);
423 
424     /** gets current command line argument as a C++ string.
425      *  This is the argument which is currently parsed or has been selected as
426      *  the current one by gotoXXXArg().
427      *
428      ** @param  arg  reference to C++ string where argument should be stored
429      *
430      ** @return OFTrue if successful, OFFalse otherwise
431      */
432     OFBool getCurrentArg(OFCmdString &arg);
433 
434     /** gets number of parameters in the parsed command line.
435      *  A parameter is an argument which is no option (e.g. a filename).
436      *
437      ** @return number of parameters
438      */
getParamCount()439     int getParamCount() const
440     {
441         return OFstatic_cast(int, ParamPosList.size());
442     }
443 
444     /** gets minimum number of parameters which should be accepted.
445      *
446      ** @return number of parameters
447      */
getMinParamCount()448     int getMinParamCount() const
449     {
450         return MinParamCount;
451     }
452 
453     /** gets maximum number of parameters which should be accepted.
454      *
455      ** @return number of parameters
456      */
getMaxParamCount()457     int getMaxParamCount() const
458     {
459         return MaxParamCount;
460     }
461 
462     /** checks whether the parsed command line contains any "exclusive" option
463      *  which does not require any mandatory parameter.  Examples for typical
464      *  exclusive options are "--help" and "--version".
465      *
466      ** @return OFTrue if an exclusive option is used, OFFalse otherwise
467      */
hasExclusiveOption()468     OFBool hasExclusiveOption() const
469     {
470         return ExclusiveOption;
471     }
472 
473     /** checks whether the wide character version of parseLine() has been used.
474      *  Support for wide character encoding is Windows-specific (i.e. UTF-16) because other
475      *  operating systems use UTF-8 for Unicode support.
476      *
477      ** @return OFTrue if wide char version of parseLine() has been used, OFFalse otherwise
478      */
getWideCharMode()479     OFBool getWideCharMode() const
480     {
481         return WideCharMode;
482     }
483 
484 
485   // --- find/get parameter (parameter is an argument which is no option)
486 
487     /** checks whether specified parameter exists in the command line.
488      *
489      ** @param  pos  position of parameter to be checked (1..n)
490      *
491      ** @return OFTrue if parameter exists, false otherwise
492      */
493     OFBool findParam(const int pos);
494 
495     /** gets value of specified parameter as signed integer.
496      *
497      ** @param  pos    position of parameter (1..n)
498      *  @param  value  reference to variable where the value should be stored
499      *
500      ** @return status of get/conversion, PVS_Normal if successful
501      *          (use getStatusString() for error string)
502      */
503     E_ParamValueStatus getParam(const int pos,
504                                 OFCmdSignedInt &value);
505 
506     /** get value of specified parameter as signed integer and checks for given boundary
507      *
508      ** @param  pos    position of parameter (1..n)
509      *  @param  value  reference to variable where the value should be stored
510      *  @param  low    minimum boundary for value (used for range check)
511      *  @param  incl   if OFTrue 'low' value is valid (included), otherwise invalid
512      *
513      ** @return status of get/conversion, PVS_Normal if successful
514      *          (use getStatusString() for error string)
515      */
516     E_ParamValueStatus getParamAndCheckMin(const int pos,
517                                            OFCmdSignedInt &value,
518                                            const OFCmdSignedInt low,
519                                            const OFExplicitBool incl = OFTrue);
520 
521     /** gets value of specified parameter as signed integer and checks for given boundaries
522      *
523      ** @param  pos    position of parameter (1..n)
524      *  @param  value  reference to variable where the value should be stored
525      *  @param  low    minimum boundary for value (used for range check, boundary included)
526      *  @param  high   maximum boundary for value (ditto)
527      *
528      ** @return status of get/conversion, PVS_Normal if successful
529      *          (use getStatusString() for error string)
530      */
531     E_ParamValueStatus getParamAndCheckMinMax(const int pos,
532                                               OFCmdSignedInt &value,
533                                               const OFCmdSignedInt low,
534                                               const OFCmdSignedInt high);
535 
536     /** gets value of specified parameter as unsigned integer.
537      *  NB: If command line argument specifies a negative value the result depends on the
538      *  signed->unsigned conversion implemented in sscanf() !!
539      *
540      ** @param  pos    position of parameter (1..n)
541      *  @param  value  reference to variable where the value should be stored
542      *
543      ** @return status of get/conversion, PVS_Normal if successful
544      *          (use getStatusString() for error string)
545      */
546     E_ParamValueStatus getParam(const int pos,
547                                 OFCmdUnsignedInt &value);
548 
549     /** gets value of specified parameter as unsigned integer and checks for given boundary.
550      *  NB: If command line argument specifies a negative value the result depends on the
551      *  signed->unsigned conversion implemented in sscanf() !!
552      *
553      ** @param  pos    position of parameter (1..n)
554      *  @param  value  reference to variable where the value should be stored
555      *  @param  low    minimum boundary for value (used for range check)
556      *  @param  incl   if OFTrue 'low' value is valid (included), otherwise invalid
557      *
558      ** @return status of get/conversion, PVS_Normal if successful
559      *          (use getStatusString() for error string)
560      */
561     E_ParamValueStatus getParamAndCheckMin(const int pos,
562                                            OFCmdUnsignedInt &value,
563                                            const OFCmdUnsignedInt low,
564                                            const OFExplicitBool incl = OFTrue);
565 
566     /** gets value of specified parameter as unsigned integer and checks for given boundaries.
567      *  NB: If command line argument specifies a negative value the result depends on the
568      *  signed->unsigned conversion implemented in sscanf() !!
569      *
570      ** @param  pos    position of parameter (1..n)
571      *  @param  value  reference to variable where the value should be stored
572      *  @param  low    minimum boundary for value (used for range check, boundary included)
573      *  @param  high   maximum boundary for value (ditto)
574      *
575      ** @return status of get/conversion, PVS_Normal if successful
576      *          (use getStatusString() for error string)
577      */
578     E_ParamValueStatus getParamAndCheckMinMax(const int pos,
579                                               OFCmdUnsignedInt &value,
580                                               const OFCmdUnsignedInt low,
581                                               const OFCmdUnsignedInt high);
582 
583     /** gets value of specified parameter as floating point.
584      *
585      ** @param  pos    position of parameter (1..n)
586      *  @param  value  reference to variable where the value should be stored
587      *
588      ** @return status of get/conversion, PVS_Normal if successful
589      *          (use getStatusString() for error string)
590      */
591     E_ParamValueStatus getParam(const int pos,
592                                 OFCmdFloat &value);
593 
594     /** gets value of specified parameter as floating point and checks for given boundary
595      *
596      ** @param  pos    position of parameter (1..n)
597      *  @param  value  reference to variable where the value should be stored
598      *  @param  low    minimum boundary for value (used for range check)
599      *  @param  incl   if OFTrue 'low' value is valid (included), otherwise invalid
600      *
601      ** @return status of get/conversion, PVS_Normal if successful
602      *          (use getStatusString() for error string)
603      */
604     E_ParamValueStatus getParamAndCheckMin(const int pos,
605                                            OFCmdFloat &value,
606                                            const OFCmdFloat low,
607                                            const OFExplicitBool incl = OFTrue);
608 
609     /** gets value of specified parameter as floating point and checks for given boundaries
610      *
611      ** @param  pos    position of parameter (1..n)
612      *  @param  value  reference to variable where the value should be stored
613      *  @param  low    minimum boundary for value (used for range check, boundary included)
614      *  @param  high   maximum boundary for value (ditto)
615      *
616      ** @return status of get/conversion, PVS_Normal if successful
617      *          (use getStatusString() for error string)
618      */
619     E_ParamValueStatus getParamAndCheckMinMax(const int pos,
620                                               OFCmdFloat &value,
621                                               const OFCmdFloat low,
622                                               const OFCmdFloat high);
623 
624     /** gets value of specified parameter as C string.
625      *
626      ** @param  pos    position of parameter (1..n)
627      *  @param  value  reference to variable where the value should be stored
628      *
629      ** @return status of get/conversion, PVS_Normal if successful
630      *          (use getStatusString() for error string)
631      */
632     E_ParamValueStatus getParam(const int pos,
633                                 const char *&value);
634 
635     /** gets value of specified parameter as C++ string.
636      *
637      ** @param  pos    position of parameter (1..n)
638      *  @param  value  reference to variable where the value should be stored
639      *
640      ** @return status of get/conversion, PVS_Normal if successful
641      *          (use getStatusString() for error string)
642      */
643     E_ParamValueStatus getParam(const int pos,
644                                 OFCmdString &value);
645 
646     /** gets value of specified parameter as an instance of OFFilename.
647      *  Please note that on Windows systems the returned filename might also contain a wide
648      *  character version (UTF-16) as an alternative representation.  See getWideCharMode().
649      *
650      ** @param  pos       position of parameter (1..n)
651      *  @param  filename  reference to variable where the value should be stored
652      *
653      ** @return status of get/conversion, PVS_Normal if successful
654      *          (use getStatusString() for error string)
655      */
656     E_ParamValueStatus getParam(const int pos,
657                                 OFFilename &filename);
658 
659 
660  // --- find/get option (option is an argument which starts with an option character, see above)
661 
662     /** checks whether specified option exists in the command line.
663      *  The search process starts from the last command line argument (which is a direct
664      *  predecessor of the optional defined reference parameter 'pos') and goes to the
665      *  first one.
666      *
667      ** @param  longOpt  name of option (in long format) to be checked
668      *  @param  pos      position of reference parameter
669      *                   (default: all parameters; if value is negative option must be a
670      *                    direct predecessor of the specified reference parameter '-pos',
671      *                    no further search processes will be performed; if search direction
672      *                    is left to right this parameter is ignored, also option blocks are
673      *                    not supported in this case)
674      *  @param  mode     find option mode (used to support option blocks and reverse search
675      *                   direction)
676      *
677      ** @return OFTrue if option exists, OFFalse otherwise
678      */
679     OFBool findOption(const char *longOpt,
680                       const signed int pos = 0,
681                       const E_FindOptionMode mode = FOM_Normal);
682 
683     /** sets first command line option as the current one.
684      *  Useful for iterating over all options.
685      *
686      ** @return OFTrue if successful, OFFalse otherwise
687      */
688     OFBool gotoFirstOption();
689 
690     /** sets next command line option as the current one.
691      *  Useful for iterating over all options.
692      *
693      ** @return OFTrue if successful, OFFalse otherwise
694      */
695     OFBool gotoNextOption();
696 
697     /** returns current option as a C string.
698      *  This is the option which has currently been parsed (e.g. used for error
699      *  output) or which has been selected as the current one by gotoXXXOption().
700      *
701      ** @param  opt  reference to C string where option should be stored
702      *
703      ** @return OFTrue if there is a current option, OFFalse otherwise
704      */
705     OFBool getCurrentOption(const char *&opt);
706 
707     /** returns current option as a C++ string.
708      *  This is the option which has currently been parsed (e.g. used for error
709      *  output) or which has been selected as the current one by gotoXXXOption().
710      *
711      ** @param  opt  reference to C++ string where option should be stored
712      *
713      ** @return OFTrue if there is a current option, OFFalse otherwise
714      */
715     OFBool getCurrentOption(OFCmdString &opt);
716 
717     /** starts an option block which can be used to support mutually exclusive options.
718      */
719     void beginOptionBlock();
720 
721     /** ends an option block which can be used to support mutually exclusive options.
722      */
723     void endOptionBlock();
724 
725 
726  // --- get value (used for option values)
727 
728     /** returns next argument as a signed integer value
729      *
730      ** @param  value  reference to signed integer variable where the value should be stored
731      *
732      ** @return status of get/conversion, VS_Normal if successful
733      *          (use getStatusString() for error string)
734      */
735     E_ValueStatus getValue(OFCmdSignedInt &value);
736 
737     /** returns next argument as a signed integer value and checks for given boundary
738      *
739      ** @param  value  reference to signed integer variable where the value should be stored
740      *  @param  low    minimum boundary for value (used for range check)
741      *  @param  incl   if OFTrue 'low' value is valid (included), otherwise invalid
742      *
743      ** @return status of get/conversion, VS_Normal if successful
744      *          (use getStatusString() for error string)
745      */
746     E_ValueStatus getValueAndCheckMin(OFCmdSignedInt &value,
747                                       const OFCmdSignedInt low,
748                                       const OFExplicitBool incl = OFTrue);
749 
750     /** returns next argument as a signed integer value and checks for given boundaries
751      *
752      ** @param  value  reference to signed integer variable where the value should be stored
753      *  @param  low    minimum boundary for value (used for range check, boundary included)
754      *  @param  high   maximum boundary for value (ditto)
755      *
756      ** @return status of get/conversion, VS_Normal if successful
757      *          (use getStatusString() for error string)
758      */
759     E_ValueStatus getValueAndCheckMinMax(OFCmdSignedInt &value,
760                                          const OFCmdSignedInt low,
761                                          const OFCmdSignedInt high);
762 
763     /** returns next argument as an unsigned integer value
764      *
765      ** @param  value  reference to unsigned integer variable where the value should be stored
766      *
767      ** @return status of get/conversion, VS_Normal if successful
768      *          (use getStatusString() for error string)
769      */
770     E_ValueStatus getValue(OFCmdUnsignedInt &value);
771 
772     /** returns next argument as an unsigned integer value and checks for given boundary
773      *
774      ** @param  value  reference to unsigned integer variable where the value should be stored
775      *  @param  low    minimum boundary for value (used for range check)
776      *  @param  incl   if OFTrue 'low' value is valid (included), otherwise invalid
777      *
778      ** @return status of get/conversion, VS_Normal if successful
779      *          (use getStatusString() for error string)
780      */
781     E_ValueStatus getValueAndCheckMin(OFCmdUnsignedInt &value,
782                                       const OFCmdUnsignedInt low,
783                                       const OFExplicitBool incl = OFTrue);
784 
785     /** returns next argument as an unsigned integer value and checks for given boundaries
786      *
787      ** @param  value  reference to unsigned integer variable where the value should be stored
788      *  @param  low    minimum boundary for value (used for range check, boundary included)
789      *  @param  high   maximum boundary for value (ditto)
790      *
791      ** @return status of get/conversion, VS_Normal if successful
792      *          (use getStatusString() for error string)
793      */
794     E_ValueStatus getValueAndCheckMinMax(OFCmdUnsignedInt &value,
795                                          const OFCmdUnsignedInt low,
796                                          const OFCmdUnsignedInt high);
797 
798     /** returns next argument as a floating point value
799      *
800      ** @param  value  reference to floating point variable where the value should be stored
801      *
802      ** @return status of get/conversion, VS_Normal if successful
803      *          (use getStatusString() for error string)
804      */
805     E_ValueStatus getValue(OFCmdFloat &value);
806 
807     /** returns next argument as a floating point value and checks for given boundary
808      *
809      ** @param  value  reference to floating point variable where the value should be stored
810      *  @param  low    minimum boundary for value (used for range check)
811      *  @param  incl   if OFTrue 'low' value is valid (included), otherwise invalid
812      *
813      ** @return status of get/conversion, VS_Normal if successful
814      *          (use getStatusString() for error string)
815      */
816     E_ValueStatus getValueAndCheckMin(OFCmdFloat &value,
817                                       const OFCmdFloat low,
818                                       const OFExplicitBool incl = OFTrue);
819 
820     /** returns next argument as a floating point value and checks for given boundaries
821      *
822      ** @param  value  reference to floating point variable where the value should be stored
823      *  @param  low    minimum boundary for value (used for range check, boundary included)
824      *  @param  high   maximum boundary for value (ditto)
825      *
826      ** @return status of get/conversion, VS_Normal if successful
827      *          (use getStatusString() for error string)
828      */
829     E_ValueStatus getValueAndCheckMinMax(OFCmdFloat &value,
830                                          const OFCmdFloat low,
831                                          const OFCmdFloat high);
832 
833     /** returns next argument as a C string
834      *
835      ** @param  value  reference to C string variable where the value should be stored
836      *
837      ** @return status of get/conversion, VS_Normal if successful
838      *          (use getStatusString() for error string)
839      */
840     E_ValueStatus getValue(const char *&value);
841 
842     /** returns next argument as a C++ string
843      *
844      ** @param  value  reference to C++ string variable where the value should be stored
845      *
846      ** @return status of get/conversion, VS_Normal if successful
847      *          (use getStatusString() for error string)
848      */
849     E_ValueStatus getValue(OFCmdString &value);
850 
851     /** returns next argument as an instance of OFFilename.
852      *  Please note that on Windows systems the returned filename might also contain a wide
853      *  character version (UTF-16) as an alternative representation.  See getWideCharMode().
854      *
855      ** @param  filename  reference to variable where the value should be stored
856      *
857      ** @return status of get/conversion, VS_Normal if successful
858      *          (use getStatusString() for error string)
859      */
860     E_ValueStatus getValue(OFFilename &filename);
861 
862 
863  // --- parsing command line
864 
865     /** parses specified command line arguments (argc, argv).  Sets 'WideCharMode' to OFFalse.
866      *  Additionally, create internal structures for evaluation and return status indicating
867      *  any errors that occurred during the parse process.
868      *
869      ** @param  argCount  number of command line arguments stored in argValue
870      *  @param  argValue  array where the command line arguments are stored
871      *  @param  flags     optional flags affecting the parse process (see PF_xxx below)
872      *  @param  startPos  index of first argument which should be parsed (starting from 0,
873      *                    default: 1)
874      *
875      ** @return status of parse process, PS_Normal if successful
876      *          (use getStatusString() for error string).  If an exclusive option is used,
877      *           the status code PS_ExclusiveOption is returned.
878      */
879     E_ParseStatus parseLine(int argCount,
880                             char *argValue[],
881                             const int flags = 0,
882                             const int startPos = 1);
883 
884 #ifdef DCMTK_USE_WCHAR_T
885 
886     /** parses specified command line arguments (argc, argv).  Sets 'WideCharMode' to OFTrue.
887      *  This is a Windows-specific version supporting the wide character encoding (UTF-16).
888      *  Internally, all character strings are stored in UTF-8, because this Unicode encoding is
889      *  supported by DICOM.  However, there are getValue() and getParam() methods that allow for
890      *  accessing filenames with wide character encoding (UTF-16).
891      *  Additionally, create internal structures for evaluation and return status indicating any
892      *  errors that occurred during the parse process.
893      *  @remarks this method is only available if OS is windows (not mingw) and
894      *  MSC6 is not used for building.
895      *
896      ** @param  argCount  number of command line arguments stored in argValue
897      *  @param  argValue  array where the command line arguments are stored
898      *  @param  flags     optional flags affecting the parse process (see PF_xxx below)
899      *  @param  startPos  index of first argument which should be parsed (starting from 0,
900      *                    default: 1)
901      *
902      ** @return status of parse process, PS_Normal if successful
903      *          (use getStatusString() for error string).  If an exclusive option is used,
904      *           the status code PS_ExclusiveOption is returned.
905      */
906     E_ParseStatus parseLine(int argCount,
907                             wchar_t *argValue[],
908                             const int flags = 0,
909                             const int startPos = 1);
910 
911 #endif  // DCMTK_USE_WCHAR_T
912 
913 
914  // --- get usage/status strings
915 
916     /** returns command line syntax as a C++ string (single text line).
917      *  Text consists of "[options]" (if defined by addOption()) and all parameters defined
918      *  by addParam().
919      *
920      ** @param  syntaxStr  reference to C++ string where the text should be stored
921      */
922     void getSyntaxString(OFString &syntaxStr) const;
923 
924     /** returns description of all options as a C++ string (multiple text lines).
925      *  Text consists of group headings, short and long option names, option descriptions and
926      *  additional option values.
927      *
928      ** @param  optionStr  reference to C++ string where the text should be stored
929      */
930     void getOptionString(OFString &optionStr) const;
931 
932     /** returns description of all parameters as a C++ string (multiple text lines).
933      *  Text consists of heading "parameters:" and parameter names and descriptions.
934      *
935      ** @param  paramStr  reference to C++ string where the text should be stored
936      */
937     void getParamString(OFString &paramStr) const;
938 
939     /** returns status of parseLine() as a C++ string
940      *
941      ** @param  status     value returned by method parseLine()
942      *  @param  statusStr  reference to C++string where the text should be stored
943      */
944     void getStatusString(const E_ParseStatus status,
945                          OFString &statusStr);
946 
947     /** returns status of getParam() as a C++ string
948      *
949      ** @param  status     value returned by method getParam()
950      *  @param  statusStr  reference to C++string where the text should be stored
951      */
952     void getStatusString(const E_ParamValueStatus status,
953                          OFString &statusStr);
954 
955     /** returns status of getValue() as a C++ string
956      *
957      ** @param  status     value returned by method getValue()
958      *  @param  statusStr  reference to C++string where the text should be stored
959      */
960     void getStatusString(const E_ValueStatus status,
961                          OFString &statusStr);
962 
963 
964  // --- flags (used for method parseLine())
965 
966     /// parsing flag to expand wildcard under Windows.
967     /// (not used anymore, only available for reasons of backward compatibility;
968     ///  link 'setargv.obj' to your program if you need wildcard expansion.)
969     static const int PF_ExpandWildcards;
970     /// disable support for command files ("@filename") containing additional arguments
971     static const int PF_NoCommandFiles;
972 
973  // --- flags (used for method addOption())
974 
975     /// exclusive option that overrides any other option (e.g.\ "--help")
976     static const int AF_Exclusive;
977     /// internal option that is not shown in the syntax usage output
978     static const int AF_Internal;
979     /// do not output a warning message if option has never been checked.
980     /// (useful if option is only checked depending on another option)
981     static const int AF_NoWarning;
982 
983 
984  protected:
985 
986     /** checks whether given option is valid (starting with an option char and not
987      *  followed by a number)
988      */
989     OFBool checkOption(const OFString &option,
990                        const OFBool mode = OFTrue) const;
991 
992     /** finds specified parameter and sets given iterator to this position
993      */
994     OFBool findParam(const int pos,
995                      OFListIterator(OFCmdParamPos *) &pos_iter);
996 
997     /** finds specified option and returns reference to its describing structure
998      */
999     const OFCmdOption *findCmdOption(const OFString &option) const;
1000 
1001     /** stores the specified parameter in the argument/parameter list
1002      */
1003     void storeParameter(const OFString &param,
1004                         const int directOption = 0);
1005 
1006     /** parse the given argument list and check it for known options/parameters
1007      */
1008     E_ParseStatus parseArgumentList(OFList<OFString> &argList,
1009                                     const int flags);
1010 
1011     /** check whether 'argValue' points to command file and parse content if so
1012      */
1013     E_ParseStatus parseCommandFile(const char *argValue,
1014                                    OFList<OFString> &argList);
1015 
1016 #ifdef DCMTK_USE_WCHAR_T
1017 
1018     /** check whether 'argValue' points to command file and parse content if so.
1019      *  This is a Windows-specific version supporting wide char encoding (UTF-16).
1020      *  @remarks this method is only available if OS is windows (not mingw) and
1021      *  MSC6 is not used for building.
1022      */
1023     E_ParseStatus parseCommandFile(const wchar_t *argValue,
1024                                    const OFString &strValue,
1025                                    OFList<OFString> &argList);
1026 
1027 #endif  // DCMTK_USE_WCHAR_T
1028 
1029     /** packs the two 16 bit values into one 32 bit value
1030      */
1031     int packColumnValues(int longCols,
1032                          int shortCols) const;
1033 
1034     /** unpacks two 16 bit values from one 32 bit value
1035      */
1036     void unpackColumnValues(const int value,
1037                             unsigned int &longCols,
1038                             unsigned int &shortCols) const;
1039 
1040     /** checks whether number of parameters in parsed command line is within the range
1041      *  of min/max (see below)
1042      */
1043     E_ParseStatus checkParamCount();
1044 
1045     /** returns last command line argument as a C++ string
1046      */
1047     OFBool getLastArg(OFString &arg);
1048 
1049     /** returns name of parameter which is missed in the parsed command line
1050      *  (used for error output)
1051      */
1052     OFBool getMissingParam(OFString &param);
1053 
1054 
1055  private:
1056 
1057     /// program name, i.e. the value of argv[0]
1058     OFString ProgramName;
1059 
1060     /// list of valid/defined command line options
1061     OFList<OFCmdOption *> ValidOptionList;
1062     /// list of valid/defined command line parameters
1063     OFList<OFCmdParam *> ValidParamList;
1064 
1065     /// list of command line arguments (after parsing)
1066     OFList<OFString> ArgumentList;
1067     /// current position in argument list
1068     OFListIterator(OFString) ArgumentIterator;
1069 
1070     /// list of parameter positions within argument list
1071     OFList<OFCmdParamPos *> ParamPosList;
1072     /// current position in param position list (numeric value)
1073     int ParamPosNumber;
1074     /// current position in param position list (iterator)
1075     OFListIterator(OFCmdParamPos *) ParamPosIterator;
1076     /// list of option positions within argument list
1077     OFList<OFListIterator_OFString> OptionPosList;
1078     /// current position in option position list
1079     OFListIterator(OFListIterator_OFString) OptionPosIterator;
1080     /// current position in option position list (used for option blocks)
1081     OFListIterator(OFListIterator_OFString) OptionBlockIterator;
1082 
1083     /// OFTrue if option block is active, OFFalse otherwise
1084     OFBool OptionBlockMode;
1085     /// C++ string consisting of all valid characters introducing an option
1086     OFString OptionChars;
1087 
1088     /// OFTrue if an "exclusive" option is used in the command line, OFFalse otherwise
1089     OFBool ExclusiveOption;
1090     /// OFTrue if wide character version of parseLine() has been used, OFFalse otherwise
1091     OFBool WideCharMode;
1092 
1093     /// width of column for long option names
1094     int LongColumn;
1095     /// width of column for short option names
1096     int ShortColumn;
1097     /// width of column for parameter names
1098     int ParamColumn;
1099 
1100     /// minimum number of parameters which should be accepted
1101     int MinParamCount;
1102     /// maximum number of parameter which should be accepted
1103     int MaxParamCount;
1104 
1105     /// mode of last added parameter (used for debug checking)
1106     OFCmdParam::E_ParamMode LastParamMode;
1107 
1108 
1109  private:
1110 
1111     /// private undefined copy constructor
1112     OFCommandLine(const OFCommandLine &obj);
1113     /// private undefined assignment operator
1114     OFCommandLine &operator=(const OFCommandLine &obj);
1115 };
1116 
1117 
1118 #endif
1119