Arg.h
1/*
2 Copyright (C) 2006,2010 by Tommi Maekitalo
3 Copyright (C) 2006-2016 by Marc Duerner
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 As a special exception, you may use this file as part of a free
11 software library without restriction. Specifically, if other files
12 instantiate templates or use macros or inline functions from this
13 file, or you compile this file and link it with other files to
14 produce an executable, this file does not by itself cause the
15 resulting executable to be covered by the GNU General Public
16 License. This exception does not however invalidate any other
17 reasons why the executable file might be covered by the GNU Library
18 General Public License.
19
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 MA 02110-1301 USA
29*/
30
31#ifndef Pt_Arg_h
32#define Pt_Arg_h
33
34#include <Pt/Api.h>
35#include <sstream>
36#include <cstring>
37
38namespace Pt {
39
41class ArgBase
42{
43 public:
44 ArgBase()
45 : m_isset(false)
46 { }
47
49 bool isSet() const
50 { return m_isset; }
51
52 protected:
53 bool m_isset;
54
56 static void removeArg(int& argc, char* argv[], int pos, int n)
57 {
58 for ( ; pos < argc - n; ++pos)
59 argv[pos] = argv[pos + n];
60
61 argc -= n;
62 argv[argc] = 0;
63 }
64};
65
67template <typename T>
68class ArgBaseT : public ArgBase
69{
70 protected:
71 explicit ArgBaseT(const T& def)
72 : m_value(def)
73 { }
74
76 bool extract(const char* str, int& argc, char* argv[], int i, int n)
77 {
78 std::istringstream s(str);
79 s >> m_value;
80 if( ! s.fail() )
81 {
82 m_isset = true;
83 removeArg(argc, argv, i, n);
84 return true;
85 }
86
87 return false;
88 }
89
90 public:
92 const T& get() const
93 { return m_value; }
94
95 private:
96 T m_value;
97};
98
100template <>
101class ArgBaseT<const char*> : public ArgBase
102{
103 protected:
104 explicit ArgBaseT(const char* def)
105 : m_value(def)
106 { }
107
109 bool extract(const char* str, int& argc, char* argv[], int i, int n)
110 {
111 m_value = str;
112 m_isset = true;
113 removeArg(argc, argv, i, n);
114 return true;
115 }
116
117 public:
119 const char* get() const
120 { return m_value; }
121
122 private:
123 const char* m_value;
124};
125
127template <>
128class ArgBaseT<std::string> : public ArgBase
129{
130 protected:
131 explicit ArgBaseT(const std::string& def)
132 : m_value(def)
133 { }
134
136 bool extract(const char* str, int& argc, char* argv[], int i, int n)
137 {
138 m_value = str;
139 m_isset = true;
140 removeArg(argc, argv, i, n);
141 return true;
142 }
143
144 public:
146 const std::string& get() const
147 { return m_value; }
148
149 private:
150 std::string m_value;
151};
152
209template <typename T>
210class Arg : public ArgBaseT<T>
211{
212 public:
215 Arg(const T& def = T())
216 : ArgBaseT<T>(def)
217 { }
218
226 Arg(int& argc, char* argv[], char ch, const T& def = T())
227 : ArgBaseT<T>(def)
228 {
229 set(argc, argv, ch);
230 }
231
239 Arg(int& argc, char* argv[], const char* str, const T& def = T())
240 : ArgBaseT<T>(def)
241 {
242 this->m_isset = set(argc, argv, str);
243 }
244
247 Arg(int& argc, char* argv[])
248 : ArgBaseT<T>(T())
249 {
250 this->m_isset = set(argc, argv);
251 }
252
259 bool set(int& argc, char* argv[], char ch)
260 {
261 // don't extract value, when already found
262 if(this->m_isset)
263 return false;
264
265 for(int i = 1; i < argc; ++i)
266 {
267 if (argv[i] && argv[i][0] == '-' && argv[i][1] == ch)
268 {
269 if(argv[i][2] == '\0' && i < argc - 1)
270 {
271 // -O foo
272 if (this->extract(argv[i + 1], argc, argv, i, 2))
273 return true;
274 }
275
276 // -Ofoo
277 if( this->extract(argv[i] + 2, argc, argv, i, 1) )
278 return true;
279 }
280 }
281
282 return false;
283 }
284
291 bool set(int& argc, char* argv[], const char* str)
292 {
293 // don't extract value, when already found
294 if (this->m_isset)
295 return false;
296
297 std::size_t n = std::strlen(str);
298 for (int i = 1; i < argc; ++i)
299 {
300 if(argv[i] && (std::strncmp(argv[i], str, n) == 0))
301 {
302 if (i < argc - 1 && argv[i][n] == '\0')
303 {
304 // --option value
305 if (this->extract(argv[i + 1], argc, argv, i, 2))
306 return true;
307 }
308
309 if (argv[i][n] == '=')
310 {
311 // --option=value
312 if (this->extract(argv[i] + n + 1, argc, argv, i, 1))
313 return true;
314 }
315 }
316 }
317
318 return false;
319 }
320
323 bool set(int& argc, char* argv[])
324 {
325 // don't extract value, when already found
326 if (this->m_isset)
327 return false;
328
329 if (argc > 1)
330 this->extract(argv[1], argc, argv, 1, 1);
331
332 return this->m_isset;
333 }
334};
335
344template <>
345class Arg<bool> : public ArgBase
346{
347 public:
350 Arg(bool def = false)
351 : m_value(def)
352 { }
353
356 Arg(int& argc, char* argv[], char ch, bool def = false)
357 : m_value(def)
358 {
359 m_isset = set(argc, argv, ch);
360 }
361
364 Arg(int& argc, char* argv[], const char* str, bool def = false)
365 : m_value(def)
366 {
367 m_isset = set(argc, argv, str);
368 }
369
372 bool set(int& argc, char* argv[], char ch)
373 {
374 // don't extract value, when already found
375 if (m_isset)
376 return false;
377
378 for (int i = 1; i < argc; ++i)
379 {
380 if (argv[i][0] == '-' && argv[i][1] != '-')
381 {
382 // starts with a '-', but not with "--"
383 if (argv[i][1] == ch && argv[i][2] == '\0')
384 {
385 // single option found
386 m_value = true;
387 m_isset = true;
388 removeArg(argc, argv, i, 1);
389 return true;
390 }
391 else if(argv[i][1] == ch &&
392 argv[i][2] == '-' &&
393 argv[i][3] == '\0')
394 {
395 // Option was explicitly disabled with -x-
396 m_value = false;
397 m_isset = true;
398 removeArg(argc, argv, i, 1);
399 return true;
400 }
401 else
402 {
403 // check for optiongroup
404 for (char* p = argv[i] + 1; *p != '\0'; ++p)
405 {
406 if (*p == ch)
407 {
408 // here it is - extract it
409 m_value = true;
410 m_isset = true;
411 do
412 {
413 *p = *(p + 1);
414 }
415 while (*p++ != '\0');
416
417 return true;
418 }
419 }
420 }
421 }
422 }
423
424 return false;
425 }
426
429 bool set(int& argc, char* argv[], const char* str)
430 {
431 // don't extract value, when already found
432 if(m_isset)
433 return false;
434
435 for (int i = 1; i < argc; ++i)
436 {
437 if (std::strcmp(argv[i], str) == 0)
438 {
439 m_value = true;
440 m_isset = true;
441 removeArg(argc, argv, i, 1);
442 return true;
443 }
444 }
445
446 return false;
447 }
448
451 bool get() const
452 { return m_value; }
453
456 operator bool() const
457 { return m_value; }
458
459 private:
460 bool m_value;
461};
462
467template <typename T>
468inline std::ostream& operator<<(std::ostream& out, const Arg<T>& arg)
469{
470 return out << arg.get();
471}
472
473} // namespace Pt
474
475#endif
Arg(bool def=false)
Constructs with a default value.
Definition Arg.h:350
const T & get() const
Returns the value.
Definition Arg.h:92
bool get() const
Returns the switch value.
Definition Arg.h:451
bool set(int &argc, char *argv[], const char *str)
Extracts a long switch from argc and argv.
Definition Arg.h:429
Arg(int &argc, char *argv[], const char *str, bool def=false)
Extracts a long switch from argc and argv.
Definition Arg.h:364
Arg(int &argc, char *argv[], char ch, bool def=false)
Extracts a short switch from argc and argv.
Definition Arg.h:356
bool set(int &argc, char *argv[], char ch)
Extracts a short switch from argc and argv.
Definition Arg.h:372
bool set(int &argc, char *argv[])
Extracts the next positional argument from argv.
Definition Arg.h:323
std::ostream & operator<<(std::ostream &out, const Arg< T > &arg)
Write Arg to an std::ostream.
Definition Arg.h:468
Arg(int &argc, char *argv[])
Extracts the next positional argument from argv.
Definition Arg.h:247
bool set(int &argc, char *argv[], const char *str)
Extracts a long option from argc and argv.
Definition Arg.h:291
Arg(int &argc, char *argv[], char ch, const T &def=T())
Extracts a short option from argc and argv.
Definition Arg.h:226
Arg(int &argc, char *argv[], const char *str, const T &def=T())
Extracts a long option from argc and argv.
Definition Arg.h:239
bool set(int &argc, char *argv[], char ch)
Extracts a short option from argc and argv.
Definition Arg.h:259
Arg(const T &def=T())
Constructs with a default value.
Definition Arg.h:215
Core module.
Definition Allocator.h:33