summaryrefslogtreecommitdiff
path: root/ace/Arg_Shifter.h
blob: 2e61342d97fab02a95f7152403a0e9a441eb55e8 (plain)
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
// This may look like C, but it's really -*- C++ -*-

//=============================================================================
/**
 *  @file     Arg_Shifter.h
 *
 *  $Id$
 *
 *  @author  Seth Widoff
 */
//=============================================================================


#ifndef ACE_ARG_SHIFTER_H
#define ACE_ARG_SHIFTER_H
#include "ace/pre.h"

#include "ace/OS.h"


/**
 * @class ACE_Arg_Shifter
 *
 * @brief This ADT shifts known args to the back of the argv vector, so
 * deeper levels of argument parsing can locate the yet
 * unprocessed arguments at the beginning of the vector.
 *
 * The <ACE_Arg_Shifter> copies the pointers of the argv vector
 * into a temporary array. As the <ACE_Arg_Shifter> iterates over
 * the temp, is places known arguments in the rear of the argv
 * and unknown ones in the beginning. So, after having visited
 * all the arguments in the temp vector, <ACE_Arg_Shifter> has
 * placed all the unknown arguments in their original order at
 * the front of argv.
 */
class ACE_Export ACE_Arg_Shifter
{
public:
  // = Initialization and termination methods.
  /**
   * Initialize the <ACE_Arg_Shifter> to the vector over which to
   * iterate, also providing the temporary array if the client doesn't
   * want the arg_shifter to dynamically allocate its own. If internal
   * dynamic allocation fails, the <ACE_Arg_Shifter> will set all the
   * indices to the end of the vector, forbidding iteration. Following
   * iteration over argv, the argc value will contain the number of
   * unconsumed arguments.
   */
  ACE_Arg_Shifter (int& argc,
                   ACE_TCHAR **argv,
                   ACE_TCHAR **temp = 0);

  /// Destructor.
  ~ACE_Arg_Shifter (void);

  /// Get the current head of the vector.
  ACE_TCHAR *get_current (void) const;

  /**
   * If the <flag> matches the current_arg of arg shifter
   * this method will attempt to return the associated
   * parameter value
   *
   * Safe to call without checking that a current arg exists
   *
   * In the following examples, a pointer to the char* "value" is ret
   *
   * eg: main -foobar value, main -FooBar value
   *     main -FOOBARvalue
   *
   *     all of the above will all match the <flag> == -FooBar
   *     and will return a char* to "value"
   *
   *     main -foobar 4 would succeed and return a char* to "4"
   *     main -foobar -4 does not succeed (-4 is not a parameter)
   *          but instead, would return 0
   *
   * 0 is returned:
   *     If the current argument does not match flag
   *     If there is no parameter found after a 'matched' flag
   *
   * If the flag is matched and the flag and paramter DO NOT RUN
   * together, the flag is consumed, the parameter is returned,
   * and the new current argument is the parameter value.
   * ie '-foobarflag  VALUE' leaves the new cur arg == "VALUE"
   *
   * If the flag is matched and the flag and parameter RUN
   * together '-foobarflagVALUE', the flag is NOT consumed
   * and the cur arg is left pointing to the entire flag/value pair
   */
  ACE_TCHAR *get_the_parameter (const ACE_TCHAR* flag);

  /**
   * Check if the current argument matches (case insensitive) <flag>
   *
   * ------------------------------------------------------------
   *
   * Case A: Perfect Match (case insensitive)
   * 0 is returned.
   *
   *     ie: when current_arg = "-foobar" or "-FOOBAR" or "-fooBAR"
   *         this->cur_arg_strncasecmp ("-FooBar);
   *         will return 0
   *
   * ------------------------------------------------------------
   *
   * Case B: Perfect Match (case insensitive) but the current_arg
   * is longer than the flag. Returns a number equal to the index
   * in the char* indicating the start of the extra characters
   *
   *     ie: when current_arg = "-foobar98023"
   *         this->cur_arg_strncasecmp ("-FooBar);
   *         will return 7
   *
   * Notice: this number will always be > 0
   *
   * ------------------------------------------------------------
   *
   * Case C: If neither of Case A or B is met (no match)
   * then -1 is returned
   */
  int cur_arg_strncasecmp (const ACE_TCHAR *flag);

  /// Consume <number> argument(s) by sticking them/it on the end of
  /// the vector.
  int consume_arg (int number = 1);

  /// Place <number> arguments in the same relative order ahead of the
  /// known arguemnts in the vector.
  int ignore_arg (int number = 1);

  /// Returns the number of args left to see in the vector.
  int is_anything_left (void) const;

  /// Returns 1 if there's a next item in the vector and it begins with
  /// '-'.
  int is_option_next (void) const;

  /// Returns 1 if there's a next item in the vector and it doesn't
  /// begin with '-'.
  int is_parameter_next (void) const;

  /// Returns the number of irrelevant args seen.
  int num_ignored_args (void) const;

private:
  /// The size of the argument vector.
  int& argc_;

  /// The size of argv_.
  int total_size_;

  /// The temporary array over which we traverse.
  ACE_TCHAR **temp_;

  /// The array in which the arguments are reordered.
  ACE_TCHAR **argv_;

  /// The element in <temp_> we're currently examining.
  int current_index_;

  /// The index of <argv_> in which we'll stick the next unknown
  /// argument.
  int back_;

  /// The index of <argv_> in which we'll stick the next known
  /// argument.
  int front_;
};

#include "ace/post.h"
#endif /* ACE_ARG_SHIFTER_H */