Subversion Repositories public

Rev

Rev 69 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
69 luk 1
 
2
/// application arguments processor implementation
3
/**
4
 * \file appargs.cpp
5
 *
6
 * application arguments processor
7
 *
8
 * Copyright (C) 2007 Lukas Jelinek, <lukas@aiken.cz>
9
 *
10
 * This program is free software; you can redistribute it and/or
11
 * modify it under the terms of one of the following licenses:
12
 *
13
 * \li 1. X11-style license (see LICENSE-X11)
14
 * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
15
 * \li 3. GNU General Public License, version 2  (see LICENSE-GPL)
16
 *
17
 * If you want to help with choosing the best license for you,
18
 * please visit http://www.gnu.org/licenses/license-list.html.
19
 *
20
 */
21
 
22
 
23
#include "strtok.h"
24
 
25
#include "appargs.h"
26
 
27
 
28
size_t AppArgs::s_minCnt = 0;
29
size_t AppArgs::s_maxCnt = APPARGS_NOLIMIT;
30
 
31
AA_LONG_MAP AppArgs::s_longMap;
32
AA_SHORT_MAP AppArgs::s_shortMap;
33
AA_VAL_LIST AppArgs::s_valList;
34
 
35
 
36
void AppArgs::Init(size_t valMinCnt, size_t valMaxCnt)
37
{
38
  s_minCnt = valMinCnt;
39
  s_maxCnt = valMaxCnt;
40
}
41
 
42
void AppArgs::Destroy()
43
{
44
  AA_LONG_MAP::iterator it = s_longMap.begin();
45
  while (it != s_longMap.end()) {
46
    delete (*it).second;
47
    it++;
48
  }
49
 
50
  s_longMap.clear();
51
  s_shortMap.clear();
52
  s_valList.clear();
53
}
54
 
55
void AppArgs::Parse(int argc, const char* const* argv)
56
{
57
  for (int i=1; i<argc; i++) {
58
    // this shouldn't occur
59
    if (argv[i] == NULL)
60
      return;
61
 
62
    if (IsOption(argv[i])) {
63
      if (IsLongOption(argv[i])) {
64
        std::string name, val;
65
        bool hasVal;
66
        if (ParseLong(argv[i], name, val, hasVal)) {
67
          AA_LONG_MAP::iterator it = s_longMap.find(name);
68
          if (it != s_longMap.end()) {
69
            AppArgOption_t* pOpt = (*it).second;
70
            pOpt->found = true;
71
            pOpt->hasVal = hasVal;
72
            pOpt->val = val;
73
          }
74
        }
75
      }
76
      else {
77
        char name;
78
        std::string val;
79
        bool hasVal;
80
        ParseShort(argv[i], name, val, hasVal);
81
        AA_SHORT_MAP::iterator it = s_shortMap.find(name);
82
        if (it != s_shortMap.end()) {
83
          AppArgOption_t* pOpt = (*it).second;
84
          pOpt->found = true;
85
          if (hasVal) {
86
            pOpt->hasVal = true;
87
            pOpt->val = val;
88
          }
89
          else {
90
            if (i+1 < argc && !IsOption(argv[i+1])) {
91
              pOpt->hasVal = true;
92
              pOpt->val = argv[i+1];
93
              i++;
94
            }
95
            else {
96
              pOpt->hasVal = false;
97
            }
98
          }
99
        }
100
      }
101
    }
102
    else {
103
      s_valList.push_back(argv[i]);
104
    }
105
  }
106
}
107
 
108
bool AppArgs::IsValid()
109
{
110
  size_t size = s_valList.size();
111
  if (size < s_minCnt || size > s_maxCnt)
112
    return false;
113
 
114
  AA_LONG_MAP::iterator it = s_longMap.begin();
115
  while (it != s_longMap.end()) {
116
    AppArgOption_t* pOpt = (*it).second;
117
    if (pOpt->mand && !(pOpt->found))
118
      return false;
119
    if (pOpt->type == AAT_MANDATORY_VALUE && pOpt->found && !(pOpt->hasVal))
120
      return false;
121
    it++;
122
  }
123
 
124
  return true;
125
}
126
 
127
bool AppArgs::ExistsOption(const std::string& rArg)
128
{
129
  AA_LONG_MAP::iterator it = s_longMap.find(rArg);
130
  return it != s_longMap.end() && (*it).second->found;
131
}
132
 
133
bool AppArgs::GetOption(const std::string& rArg, std::string& rVal)
134
{
135
  AA_LONG_MAP::iterator it = s_longMap.find(rArg);
136
  if (it == s_longMap.end())
137
    return false;
138
 
139
  AppArgOption_t* pOpt = (*it).second;
140
  if (!(pOpt->found) || !(pOpt->hasVal))
141
    return false;
142
 
143
  rVal = pOpt->val;
144
  return true;
145
}
146
 
147
bool AppArgs::AddOption(const std::string& rName, char cShort, AppArgType_t type, bool fMandatory)
148
{
149
  if (s_longMap.find(rName) != s_longMap.end() || s_shortMap.find(cShort) != s_shortMap.end())
150
    return false;
151
 
152
  AppArgOption_t* pOpt = new AppArgOption_t();
153
  pOpt->found = false;
154
  pOpt->hasVal = false;
155
  pOpt->mand = fMandatory;
156
  pOpt->type = type;
157
 
158
  s_longMap.insert(AA_LONG_MAP::value_type(rName, pOpt));
159
  s_shortMap.insert(AA_SHORT_MAP::value_type(cShort, pOpt));
160
  return true;
161
}
162
 
163
size_t AppArgs::GetValueCount()
164
{
165
  return s_valList.size();
166
}
167
 
168
bool AppArgs::GetValue(size_t index, std::string& rVal)
169
{
170
  if (index > s_valList.size())
171
    return false;
172
 
173
  rVal = s_valList[index];
174
  return true;
175
}
176
 
177
void AppArgs::Dump()
178
{
179
  fprintf(stderr, "Options:\n");
180
  AA_LONG_MAP::iterator it = s_longMap.begin();
181
  while (it != s_longMap.end()) {
182
    AppArgOption_t* pOpt = (*it).second;
183
    AA_SHORT_MAP::iterator it2 = s_shortMap.begin();
184
    while (it2 != s_shortMap.end()) {
185
      if ((*it2).second == pOpt) {
186
        DumpOption((*it).first, (*it2).first, pOpt);
187
      }
188
      it2++;
189
    }      
190
    it++;
191
  }
192
 
193
  fprintf(stderr, "Values:\n");
194
 
195
  AA_VAL_LIST::iterator it3 = s_valList.begin();
196
  while (it3 != s_valList.end()) {
197
    fprintf(stderr, "%s\n", (*it3).c_str());
198
    it3++;
199
  }  
200
}
201
 
202
 
203
 
204
bool AppArgs::IsOption(const char* pchStr)
205
{
206
  if (strlen(pchStr) < 2)
207
    return false;
208
 
209
  return pchStr[0] == '-';
210
}
211
 
212
bool AppArgs::IsLongOption(const char* pchStr)
213
{
214
  return pchStr[1] == '-';
215
}
216
 
217
bool AppArgs::ParseLong(const char* pchStr, std::string& rName, std::string& rVal, bool& rfHasVal)
218
{
219
  StringTokenizer tok(pchStr+2, '=');
220
  if (!tok.HasMoreTokens())
221
    return false;
222
 
223
  rName = tok.GetNextToken();
224
  if (!tok.HasMoreTokens()) {
225
    rfHasVal = false;
226
    return true;
227
  }
228
 
229
  rVal = tok.GetRemainder();
230
  rfHasVal = true;
231
  return true;
232
}
233
 
234
void AppArgs::ParseShort(const char* pchStr, char& rcName, std::string& rVal, bool& rfHasVal)
235
{
236
  rcName = pchStr[1];
237
  size_t len = strlen(pchStr);
238
  if (len == 2) {
239
    rfHasVal = false;
240
    return;
241
  }
242
 
243
  rVal = pchStr + 2;
244
  rfHasVal = true;  
245
}
246
 
247
void AppArgs::DumpOption(const std::string& rName, char cShort, AppArgOption_t* pOpt)
248
{
249
  const char* s;
250
  switch (pOpt->type) {
251
    case AAT_NO_VALUE: s = "no value";
252
      break;
253
    case AAT_OPTIONAL_VALUE: s = "optional value";
254
      break;
255
    case AAT_MANDATORY_VALUE: s = "mandatory value";
256
      break;
257
    default:;
258
      s = "unknown";
259
  }
260
 
261
  fprintf(stderr, "long='%s', short='%c', type='%s', found=%s, has_value=%s, value='%s'\n",
262
      rName.c_str(),
263
      cShort,
264
      s,
265
      pOpt->found ? "YES" : "NO",
266
      pOpt->hasVal ? "YES" : "NO",
267
      pOpt->val.c_str()
268
  );
269
}
270
 
271