Subversion Repositories public

Rev

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