summaryrefslogtreecommitdiff
path: root/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/GetPot
diff options
context:
space:
mode:
Diffstat (limited to 'utils/zenutils/libraries/getpot-c++-1.1.18/getpot/GetPot')
-rw-r--r--utils/zenutils/libraries/getpot-c++-1.1.18/getpot/GetPot2440
1 files changed, 2440 insertions, 0 deletions
diff --git a/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/GetPot b/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/GetPot
new file mode 100644
index 0000000000..4c305f6532
--- /dev/null
+++ b/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/GetPot
@@ -0,0 +1,2440 @@
1// -*- c++ -*- vim: set syntax=cpp:
2// GetPot Version $$Version$$ $$Date$$
3//
4// WEBSITE: http://getpot.sourceforge.net
5//
6// NOTE: The LPGL License for this library is only valid in case that
7// it is not used for the production or development of applications
8// dedicated to military industry. This is what the author calls
9// the 'unofficial peace version of the LPGL'.
10//
11// This library is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Lesser General Public License as
13// published by the Free Software Foundation; either version 2.1 of the
14// License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful, but
17// WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24// USA
25//
26// (C) 2001-2007 Frank R. Schaefer <fschaef@users.sf.net>
27//==========================================================================
28
29#ifndef __include_guard_GETPOT_H__
30#define __include_guard_GETPOT_H__
31
32#if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC)
33#define strtok_r(a, b, c) strtok(a, b)
34#endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC
35
36extern "C" {
37// leave the 'extern C' to make it 100% sure to work -
38// expecially with older distributions of header files.
39#ifndef WIN32
40// this is necessary (depending on OS)
41#include <ctype.h>
42#endif
43#include <stdio.h>
44#include <stdarg.h>
45#include <assert.h>
46#include <string.h>
47}
48#include <cmath>
49#include <string>
50#include <vector>
51#include <algorithm>
52
53#include <fstream>
54#include <iostream> // not every compiler distribution includes <iostream>
55// // with <fstream>
56
57typedef std::vector<std::string> STRING_VECTOR;
58
59#define victorate(TYPE, VARIABLE, ITERATOR) \
60 std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin(); \
61 for(; (ITERATOR) != (VARIABLE).end(); (ITERATOR)++)
62
63
64class GetPot {
65 //--------
66 inline void __basic_initialization();
67public:
68 // (*) constructors, destructor, assignment operator -----------------------
69 inline GetPot();
70 inline GetPot(const GetPot&);
71 inline GetPot(const int argc_, char** argv_,
72 const char* FieldSeparator=0x0);
73 inline GetPot(const char* FileName,
74 const char* CommentStart=0x0, const char* CommentEnd=0x0,
75 const char* FieldSeparator=0x0);
76 inline ~GetPot();
77 inline GetPot& operator=(const GetPot&);
78
79
80 // (*) absorbing contents of another GetPot object
81 inline void absorb(const GetPot& That);
82 // -- for ufo detection: recording requested arguments, options etc.
83 inline void clear_requests();
84 inline void disable_request_recording() { __request_recording_f = false; }
85 inline void enable_request_recording() { __request_recording_f = true; }
86
87 // (*) direct access to command line arguments -----------------------------
88 inline const std::string operator[](unsigned Idx) const;
89 inline int get(unsigned Idx, int Default) const;
90 inline double get(unsigned Idx, const double& Default) const;
91 inline const std::string get(unsigned Idx, const char* Default) const;
92 inline unsigned size() const;
93
94 // (*) flags ---------------------------------------------------------------
95 inline bool options_contain(const char* FlagList) const;
96 inline bool argument_contains(unsigned Idx, const char* FlagList) const;
97
98 // (*) variables -----------------------------------------------------------
99 // -- scalar values
100 inline int operator()(const char* VarName, int Default) const;
101 inline double operator()(const char* VarName, const double& Default) const;
102 inline const std::string operator()(const char* VarName, const char* Default) const;
103 // -- vectors
104 inline int operator()(const char* VarName, int Default, unsigned Idx) const;
105 inline double operator()(const char* VarName, const double& Default, unsigned Idx) const;
106 inline const std::string operator()(const char* VarName, const char* Default, unsigned Idx) const;
107
108 // -- setting variables
109 // i) from outside of GetPot (considering prefix etc.)
110 // ii) from inside, use '__set_variable()' below
111 inline void set(const char* VarName, const char* Value, const bool Requested = true);
112 inline void set(const char* VarName, const double& Value, const bool Requested = true);
113 inline void set(const char* VarName, const int Value, const bool Requested = true);
114
115 inline unsigned vector_variable_size(const char* VarName) const;
116 inline STRING_VECTOR get_variable_names() const;
117 inline STRING_VECTOR get_section_names() const;
118
119
120 // (*) cursor oriented functions -------------------------------------------
121 inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); }
122 inline bool search_failed() const { return search_failed_f; }
123
124 // -- enable/disable search for an option in loop
125 inline void disable_loop() { search_loop_f = false; }
126 inline void enable_loop() { search_loop_f = true; }
127
128 // -- reset cursor to position '1'
129 inline void reset_cursor();
130 inline void init_multiple_occurrence();
131
132 // -- search for a certain option and set cursor to position
133 inline bool search(const char* option);
134 inline bool search(unsigned No, const char* P, ...);
135 // -- get argument at cursor++
136 inline int next(int Default);
137 inline double next(const double& Default);
138 inline const std::string next(const char* Default);
139 // -- search for option and get argument at cursor++
140 inline int follow(int Default, const char* Option);
141 inline double follow(const double& Default, const char* Option);
142 inline const std::string follow(const char* Default, const char* Option);
143 // -- search for one of the given options and get argument that follows it
144 inline int follow(int Default, unsigned No, const char* Option, ...);
145 inline double follow(const double& Default, unsigned No, const char* Option, ...);
146 inline const std::string follow(const char* Default, unsigned No, const char* Option, ...);
147 // -- lists of nominuses following an option
148 inline std::vector<std::string> nominus_followers(const char* Option);
149 inline std::vector<std::string> nominus_followers(unsigned No, ...);
150
151 // -- directly followed arguments
152 inline int direct_follow(int Default, const char* Option);
153 inline double direct_follow(const double& Default, const char* Option);
154 inline const std::string direct_follow(const char* Default, const char* Option);
155
156 inline std::vector<std::string> string_tails(const char* StartString);
157 inline std::vector<int> int_tails(const char* StartString, const int Default = 1);
158 inline std::vector<double> double_tails(const char* StartString, const double Default = 1.0);
159
160 // (*) nominus arguments ---------------------------------------------------
161 inline STRING_VECTOR nominus_vector() const;
162 inline unsigned nominus_size() const { return static_cast<unsigned int>(idx_nominus.size()); }
163 inline std::string next_nominus();
164
165 // (*) unidentified flying objects -----------------------------------------
166 inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const;
167 inline STRING_VECTOR unidentified_arguments(const STRING_VECTOR& Knowns) const;
168 inline STRING_VECTOR unidentified_arguments() const;
169
170 inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const;
171 inline STRING_VECTOR unidentified_options(const STRING_VECTOR& Knowns) const;
172 inline STRING_VECTOR unidentified_options() const;
173
174 inline std::string unidentified_flags(const char* Known,
175 int ArgumentNumber /* =-1 */) const;
176
177 inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const;
178 inline STRING_VECTOR unidentified_variables(const STRING_VECTOR& Knowns) const;
179 inline STRING_VECTOR unidentified_variables() const;
180
181 inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const;
182 inline STRING_VECTOR unidentified_sections(const STRING_VECTOR& Knowns) const;
183 inline STRING_VECTOR unidentified_sections() const;
184
185 inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const;
186 inline STRING_VECTOR unidentified_nominuses(const STRING_VECTOR& Knowns) const;
187 inline STRING_VECTOR unidentified_nominuses() const;
188
189 // (*) output --------------------------------------------------------------
190 inline int print() const;
191
192private:
193 // (*) Type Declaration ----------------------------------------------------
194 struct variable {
195 //-----------
196 // Variable to be specified on the command line or in input files.
197 // (i.e. of the form var='12 312 341')
198
199 // -- constructors, destructors, assignment operator
200 variable();
201 variable(const variable&);
202 variable(const char* Name, const char* Value, const char* FieldSeparator);
203 ~variable();
204 variable& operator=(const variable& That);
205
206 void take(const char* Value, const char* FieldSeparator);
207
208 // -- get a specific element in the string vector
209 // (return 0 if not present)
210 const std::string* get_element(unsigned Idx) const;
211
212 // -- data memebers
213 std::string name; // identifier of variable
214 STRING_VECTOR value; // value of variable stored in vector
215 std::string original; // value of variable as given on command line
216 };
217
218 // (*) member variables --------------------------------------------------------------
219 std::string prefix; // prefix automatically added in queries
220 std::string section; // (for dollar bracket parsing)
221 STRING_VECTOR section_list; // list of all parsed sections
222 // -- argument vector
223 STRING_VECTOR argv; // vector of command line arguments stored as strings
224 unsigned cursor; // cursor for argv
225 bool search_loop_f; // shall search start at beginning after
226 // // reaching end of arg array ?
227 bool search_failed_f; // flag indicating a failed search() operation
228 // // (e.g. next() functions react with 'missed')
229
230 // -- nominus vector
231 int nominus_cursor; // cursor for nominus_pointers
232 std::vector<unsigned> idx_nominus; // indecies of 'no minus' arguments
233
234 // -- variables
235 // (arguments of the form "variable=value")
236 std::vector<variable> variables;
237
238 // -- comment delimiters
239 std::string _comment_start;
240 std::string _comment_end;
241
242 // -- field separator (separating elements of a vector)
243 std::string _field_separator;
244
245 // -- some functions return a char pointer to a temporarily existing string
246 // this container makes them 'available' until the getpot object is destroyed.
247 std::vector<char*> __internal_string_container;
248
249 // -- keeping track about arguments that are requested, so that the UFO detection
250 // can be simplified
251 STRING_VECTOR _requested_arguments;
252 STRING_VECTOR _requested_variables;
253 STRING_VECTOR _requested_sections;
254
255 bool __request_recording_f; // speed: request recording can be turned off
256
257 // -- if an argument is requested record it and the 'tag' the section branch to which
258 // it belongs. Caution: both functions mark the sections as 'tagged'.
259 void __record_argument_request(const std::string& Arg);
260 void __record_variable_request(const std::string& Arg);
261
262 // (*) helper functions ----------------------------------------------------
263 // set variable from inside GetPot (no prefix considered)
264 inline void __set_variable(const char* VarName, const char* Value);
265
266 // -- produce three basic data vectors:
267 // - argument vector
268 // - nominus vector
269 // - variable dictionary
270 inline void __parse_argument_vector(const STRING_VECTOR& ARGV);
271
272 // -- helpers for argument list processing
273 // * search for a variable in 'variables' array
274 inline const variable* __find_variable(const char*) const;
275 // * support finding directly followed arguments
276 inline const char* __match_starting_string(const char* StartString);
277 // * support search for flags in a specific argument
278 inline bool __check_flags(const std::string& Str, const char* FlagList) const;
279 // * type conversion if possible
280 inline int __convert_to_type(const std::string& String, int Default) const;
281 inline double __convert_to_type(const std::string& String, double Default) const;
282 // * prefix extraction
283 const std::string __get_remaining_string(const std::string& String,
284 const std::string& Start) const;
285 // * search for a specific string
286 inline bool __search_string_vector(const STRING_VECTOR& Vec,
287 const std::string& Str) const;
288
289 // -- helpers to parse input file
290 // create an argument vector based on data found in an input file, i.e.:
291 // 1) delete comments (in between '_comment_start' '_comment_end')
292 // 2) contract assignment expressions, such as
293 // my-variable = '007 J. B.'
294 // into
295 // my-variable='007 J. B.'
296 // 3) interprete sections like '[../my-section]' etc.
297 inline void __skip_whitespace(std::istream& istr);
298 inline const std::string __get_next_token(std::istream& istr);
299 inline const std::string __get_string(std::istream& istr);
300 inline const std::string __get_until_closing_bracket(std::istream& istr);
301
302 inline STRING_VECTOR __read_in_stream(std::istream& istr);
303 inline STRING_VECTOR __read_in_file(const char* FileName);
304 inline std::string __process_section_label(const std::string& Section,
305 STRING_VECTOR& section_stack);
306
307 // -- dollar bracket expressions
308 std::string __DBE_expand_string(const std::string str);
309 std::string __DBE_expand(const std::string str);
310 const GetPot::variable* __DBE_get_variable(const std::string str);
311 STRING_VECTOR __DBE_get_expr_list(const std::string str, const unsigned ExpectedNumber);
312
313 std::string __double2string(const double& Value) const {
314 // -- converts a double integer into a string
315 char* tmp = new char[128];
316#ifndef WIN32
317 snprintf(tmp, (int)sizeof(char)*128, "%e", Value);
318#else
319 _snprintf(tmp, sizeof(char)*128, "%e", Value);
320#endif
321 std::string result(tmp);
322 delete [] tmp;
323 return result;
324 }
325
326 std::string __int2string(const int& Value) const {
327 // -- converts an integer into a string
328 char* tmp = new char[128];
329#ifndef WIN32
330 snprintf(tmp, (int)sizeof(char)*128, "%i", Value);
331#else
332 _snprintf(tmp, sizeof(char)*128, "%i", Value);
333#endif
334 std::string result(tmp);
335 delete [] tmp;
336 return result;
337 }
338
339 STRING_VECTOR __get_section_tree(const std::string& FullPath) {
340 // -- cuts a variable name into a tree of sub-sections. this is requested for recording
341 // requested sections when dealing with 'ufo' detection.
342 STRING_VECTOR result;
343 const char* Start = FullPath.c_str();
344
345 for(char *p = (char*)Start; *p ; p++) {
346 if( *p == '/' ) {
347 *p = '\0'; // set terminating zero for convinience
348 const std::string Section = Start;
349 *p = '/'; // reset slash at place
350 result.push_back(Section);
351 }
352 }
353
354 return result;
355 }
356};
357
358
359///////////////////////////////////////////////////////////////////////////////
360// (*) constructors, destructor, assignment operator
361//.............................................................................
362//
363inline void
364GetPot::__basic_initialization()
365{
366 cursor = 0; nominus_cursor = -1;
367 search_failed_f = true; search_loop_f = true;
368 prefix = ""; section = "";
369
370 // automatic request recording for later ufo detection
371 __request_recording_f = true;
372
373 // comment start and end strings
374 _comment_start = std::string("#");
375 _comment_end = std::string("\n");
376
377 // default: separate vector elements by whitespaces
378 _field_separator = " \t\n";
379}
380
381inline
382GetPot::GetPot()
383{
384 __basic_initialization();
385
386 STRING_VECTOR _apriori_argv;
387 _apriori_argv.push_back(std::string("Empty"));
388 __parse_argument_vector(_apriori_argv);
389}
390
391inline
392GetPot::GetPot(const int argc_, char ** argv_,
393 const char* FieldSeparator /* =0x0 */)
394 // leave 'char**' non-const to honor less capable compilers ...
395{
396 // TODO: Ponder over the problem when the argument list is of size = 0.
397 // This is 'sabotage', but it can still occur if the user specifies
398 // it himself.
399 assert(argc_ >= 1);
400 __basic_initialization();
401
402 // if specified -> overwrite default string
403 if( FieldSeparator ) _field_separator = std::string(FieldSeparator);
404
405 // -- make an internal copy of the argument list:
406 STRING_VECTOR _apriori_argv;
407 // -- for the sake of clarity: we do want to include the first argument in the argument vector !
408 // it will not be a nominus argument, though. This gives us a minimun vector size of one
409 // which facilitates error checking in many functions. Also the user will be able to
410 // retrieve the name of his application by "get[0]"
411 _apriori_argv.push_back(std::string(argv_[0]));
412 int i=1;
413 for(; i<argc_; ++i) {
414 std::string tmp(argv_[i]); // recall the problem with temporaries,
415 _apriori_argv.push_back(tmp); // reference counting in arguement lists ...
416 }
417 __parse_argument_vector(_apriori_argv);
418}
419
420
421inline
422GetPot::GetPot(const char* FileName,
423 const char* CommentStart /* = 0x0 */, const char* CommentEnd /* = 0x0 */,
424 const char* FieldSeparator/* = 0x0 */)
425{
426 __basic_initialization();
427
428 // if specified -> overwrite default strings
429 if( CommentStart ) _comment_start = std::string(CommentStart);
430 if( CommentEnd ) _comment_end = std::string(CommentEnd);
431 if( FieldSeparator ) _field_separator = FieldSeparator;
432
433 STRING_VECTOR _apriori_argv;
434 // -- file name is element of argument vector, however, it is not parsed for
435 // variable assignments or nominuses.
436 _apriori_argv.push_back(std::string(FileName));
437
438 STRING_VECTOR args = __read_in_file(FileName);
439 _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end());
440 __parse_argument_vector(_apriori_argv);
441}
442
443inline
444GetPot::GetPot(const GetPot& That)
445{ GetPot::operator=(That); }
446
447inline
448GetPot::~GetPot()
449{
450 // may be some return strings had to be created, delete now !
451 victorate(char*, __internal_string_container, it)
452 delete [] *it;
453}
454
455inline GetPot&
456GetPot::operator=(const GetPot& That)
457{
458 if (&That == this) return *this;
459
460 _comment_start = That._comment_start;
461 _comment_end = That._comment_end;
462 argv = That.argv;
463 variables = That.variables;
464 prefix = That.prefix;
465
466 cursor = That.cursor;
467 nominus_cursor = That.nominus_cursor;
468 search_failed_f = That.search_failed_f;
469
470 idx_nominus = That.idx_nominus;
471 search_loop_f = That.search_loop_f;
472
473 return *this;
474}
475
476
477inline void
478GetPot::absorb(const GetPot& That)
479{
480 if (&That == this) return;
481
482 STRING_VECTOR __tmp(That.argv);
483
484 __tmp.erase(__tmp.begin());
485
486 __parse_argument_vector(__tmp);
487}
488
489inline void
490GetPot::clear_requests()
491{
492 _requested_arguments.erase(_requested_arguments.begin(), _requested_arguments.end());
493 _requested_variables.erase(_requested_variables.begin(), _requested_variables.end());
494 _requested_sections.erase(_requested_sections.begin(), _requested_sections.end());
495}
496
497inline void
498GetPot::__parse_argument_vector(const STRING_VECTOR& ARGV)
499{
500 if( ARGV.size() == 0 ) return;
501
502 // build internal databases:
503 // 1) array with no-minus arguments (usually used as filenames)
504 // 2) variable assignments:
505 // 'variable name' '=' number | string
506 STRING_VECTOR section_stack;
507 STRING_VECTOR::const_iterator it = ARGV.begin();
508
509
510 section = "";
511
512 // -- do not parse the first argument, so that it is not interpreted a s a nominus or so.
513 argv.push_back(*it);
514 ++it;
515
516 // -- loop over remaining arguments
517 unsigned i=1;
518 for(; it != ARGV.end(); ++it, ++i) {
519 std::string arg = *it;
520
521 if( arg.length() == 0 ) continue;
522
523 // -- [section] labels
524 if( arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']' ) {
525
526 // (*) sections are considered 'requested arguments'
527 if( __request_recording_f ) _requested_arguments.push_back(arg);
528
529 const std::string Name = __DBE_expand_string(arg.substr(1, arg.length()-2));
530 section = __process_section_label(Name, section_stack);
531 // new section --> append to list of sections
532 if( find(section_list.begin(), section_list.end(), section) == section_list.end() )
533 if( section.length() != 0 ) section_list.push_back(section);
534 argv.push_back(arg);
535 }
536 else {
537 arg = section + __DBE_expand_string(arg);
538 argv.push_back(arg);
539 }
540
541 // -- separate array for nominus arguments
542 if( arg[0] != '-' ) idx_nominus.push_back(unsigned(i));
543
544 // -- variables: does arg contain a '=' operator ?
545 const char* p = arg.c_str();
546 for(; *p ; p++) {
547 if( *p == '=' ) {
548 // (*) record for later ufo detection
549 // arguments carriying variables are always treated as 'requested' arguments.
550 // as a whole! That is 'x=4712' is considered a requested argument.
551 //
552 // unrequested variables have to be detected with the ufo-variable
553 // detection routine.
554 if( __request_recording_f ) _requested_arguments.push_back(arg);
555
556 // set terminating 'zero' to treat first part as single string
557 // => arg (from start to 'p') = Name of variable
558 // p+1 (until terminating zero) = value of variable
559 char* o = (char*)p++;
560 *o = '\0'; // set temporary terminating zero
561 // __set_variable(...)
562 // calls __find_variable(...) which registers the search
563 // temporarily disable this
564 const bool tmp = __request_recording_f;
565 __request_recording_f = false;
566 __set_variable(arg.c_str(), p); // v-name = c_str() bis 'p', value = rest
567 __request_recording_f = tmp;
568 *o = '='; // reset the original '='
569 break;
570 }
571 }
572 }
573}
574
575
576inline STRING_VECTOR
577GetPot::__read_in_file(const char* FileName)
578{
579 std::ifstream i(FileName);
580 if( ! i ) return STRING_VECTOR();
581 // argv[0] == the filename of the file that was read in
582 return __read_in_stream(i);
583}
584
585inline STRING_VECTOR
586GetPot::__read_in_stream(std::istream& istr)
587{
588 STRING_VECTOR brute_tokens;
589 while(istr) {
590 __skip_whitespace(istr);
591 const std::string Token = __get_next_token(istr);
592 if( Token.length() == 0 || Token[0] == EOF) break;
593 brute_tokens.push_back(Token);
594 }
595
596 // -- reduce expressions of token1'='token2 to a single
597 // string 'token1=token2'
598 // -- copy everything into 'argv'
599 // -- arguments preceded by something like '[' name ']' (section)
600 // produce a second copy of each argument with a prefix '[name]argument'
601 unsigned i1 = 0;
602 unsigned i2 = 1;
603 unsigned i3 = 2;
604
605 STRING_VECTOR arglist;
606 while( i1 < brute_tokens.size() ) {
607 const std::string& SRef = brute_tokens[i1];
608 // 1) concatinate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef'
609 // note: java.lang.String: substring(a,b) = from a to b-1
610 // C++ string: substr(a,b) = from a to a + b
611 if( i2 < brute_tokens.size() && brute_tokens[i2] == "=" ) {
612 if( i3 >= brute_tokens.size() )
613 arglist.push_back(brute_tokens[i1] + brute_tokens[i2]);
614 else
615 arglist.push_back(brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3]);
616 i1 = i3+1; i2 = i3+2; i3 = i3+3;
617 continue;
618 }
619 else {
620 arglist.push_back(SRef);
621 i1=i2; i2=i3; i3++;
622 }
623 }
624 return arglist;
625}
626
627inline void
628GetPot::__skip_whitespace(std::istream& istr)
629 // find next non-whitespace while deleting comments
630{
631 int tmp = istr.get();
632 do {
633 // -- search a non whitespace
634 while( isspace(tmp) ) {
635 tmp = istr.get();
636 if( ! istr ) return;
637 }
638
639 // -- look if characters match the comment starter string
640 unsigned i=0;
641 for(; i<_comment_start.length() ; ++i) {
642 if( tmp != _comment_start[i] ) {
643 // NOTE: Due to a 'strange behavior' in Microsoft's streaming lib we do
644 // a series of unget()s instead a quick seek. See
645 // http://sourceforge.net/tracker/index.php?func=detail&aid=1545239&group_id=31994&atid=403915
646 // for a detailed discussion.
647
648 // -- one step more backwards, since 'tmp' already at non-whitespace
649 do istr.unget(); while( i-- != 0 );
650 return;
651 }
652 tmp = istr.get();
653 if( ! istr ) { istr.unget(); return; }
654 }
655 // 'tmp' contains last character of _comment_starter
656
657 // -- comment starter found -> search for comment ender
658 unsigned match_no=0;
659 while(1+1 == 2) {
660 tmp = istr.get();
661 if( ! istr ) { istr.unget(); return; }
662
663 if( tmp == _comment_end[match_no] ) {
664 match_no++;
665 if( match_no == _comment_end.length() ) {
666 istr.unget();
667 break; // shuffle more whitespace, end of comment found
668 }
669 }
670 else
671 match_no = 0;
672 }
673
674 tmp = istr.get();
675
676 } while( istr );
677 istr.unget();
678}
679
680inline const std::string
681GetPot::__get_next_token(std::istream& istr)
682 // get next concatinates string token. consider quotes that embrace
683 // whitespaces
684{
685 std::string token;
686 int tmp = 0;
687 int last_letter = 0;
688 while(1+1 == 2) {
689 last_letter = tmp; tmp = istr.get();
690 if( tmp == EOF
691 || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\') ) {
692 return token;
693 }
694 else if( tmp == '\'' && last_letter != '\\' ) {
695 // QUOTES: un-backslashed quotes => it's a string
696 token += __get_string(istr);
697 continue;
698 }
699 else if( tmp == '{' && last_letter == '$') {
700 token += '{' + __get_until_closing_bracket(istr);
701 continue;
702 }
703 else if( tmp == '$' && last_letter == '\\') {
704 token += tmp; tmp = 0; // so that last_letter will become = 0, not '$';
705 continue;
706 }
707 else if( tmp == '\\' && last_letter != '\\')
708 continue; // don't append un-backslashed backslashes
709 token += tmp;
710 }
711}
712
713inline const std::string
714GetPot::__get_string(std::istream& istr)
715 // parse input until next matching '
716{
717 std::string str;
718 int tmp = 0;
719 int last_letter = 0;
720 while(1 + 1 == 2) {
721 last_letter = tmp; tmp = istr.get();
722 if( tmp == EOF) return str;
723 // un-backslashed quotes => it's the end of the string
724 else if( tmp == '\'' && last_letter != '\\') return str;
725 else if( tmp == '\\' && last_letter != '\\') continue; // don't append
726
727 str += tmp;
728 }
729}
730
731inline const std::string
732GetPot::__get_until_closing_bracket(std::istream& istr)
733 // parse input until next matching }
734{
735 std::string str = "";
736 int tmp = 0;
737 int last_letter = 0;
738 int brackets = 1;
739 while(1 + 1 == 2) {
740 last_letter = tmp; tmp = istr.get();
741 if( tmp == EOF) return str;
742 else if( tmp == '{' && last_letter == '$') brackets += 1;
743 else if( tmp == '}') {
744 brackets -= 1;
745 // un-backslashed brackets => it's the end of the string
746 if( brackets == 0) return str + '}';
747 else if( tmp == '\\' && last_letter != '\\')
748 continue; // do not append an unbackslashed backslash
749 }
750 str += tmp;
751 }
752}
753
754inline std::string
755GetPot::__process_section_label(const std::string& Section,
756 STRING_VECTOR& section_stack)
757{
758 std::string sname = Section;
759 // 1) subsection of actual section ('./' prefix)
760 if( sname.length() >= 2 && sname.substr(0, 2) == "./" ) {
761 sname = sname.substr(2);
762 }
763 // 2) subsection of parent section ('../' prefix)
764 else if( sname.length() >= 3 && sname.substr(0, 3) == "../" ) {
765 do {
766 if( section_stack.end() != section_stack.begin() )
767 section_stack.pop_back();
768 sname = sname.substr(3);
769 } while( sname.substr(0, 3) == "../" );
770 }
771 // 3) subsection of the root-section
772 else {
773 section_stack.erase(section_stack.begin(), section_stack.end());
774 // [] => back to root section
775 }
776
777 if( sname != "" ) {
778 // parse section name for 'slashes'
779 unsigned i=0;
780 while( i < sname.length() ) {
781 if( sname[i] == '/' ) {
782 section_stack.push_back(sname.substr(0,i));
783 if( i+1 < sname.length() )
784 sname = sname.substr(i+1);
785 i = 0;
786 }
787 else
788 ++i;
789 }
790 section_stack.push_back(sname);
791 }
792 std::string section = "";
793 if( section_stack.size() != 0 ) {
794 victorate(std::string, section_stack, it)
795 section += *it + "/";
796 }
797 return section;
798}
799
800
801// convert string to DOUBLE, if not possible return Default
802inline double
803GetPot::__convert_to_type(const std::string& String, double Default) const
804{
805 double tmp;
806 if( sscanf(String.c_str(),"%lf", &tmp) != 1 ) return Default;
807 return tmp;
808}
809
810// convert string to INT, if not possible return Default
811inline int
812GetPot::__convert_to_type(const std::string& String, int Default) const
813{
814 // NOTE: intermediate results may be floating points, so that the string
815 // may look like 2.0e1 (i.e. float format) => use float conversion
816 // in any case.
817 return (int)__convert_to_type(String, (double)Default);
818}
819
820//////////////////////////////////////////////////////////////////////////////
821// (*) cursor oriented functions
822//.............................................................................
823inline const std::string
824GetPot::__get_remaining_string(const std::string& String, const std::string& Start) const
825 // Checks if 'String' begins with 'Start' and returns the remaining String.
826 // Returns None if String does not begin with Start.
827{
828 if( Start == "" ) return String;
829 // note: java.lang.String: substring(a,b) = from a to b-1
830 // C++ string: substr(a,b) = from a to a + b
831 if( String.find(Start) == 0 ) return String.substr(Start.length());
832 else return "";
833}
834
835// -- search for a certain argument and set cursor to position
836inline bool
837GetPot::search(const char* Option)
838{
839 unsigned OldCursor = cursor;
840 const std::string SearchTerm = prefix + Option;
841
842 // (*) record requested arguments for later ufo detection
843 __record_argument_request(SearchTerm);
844
845 if( OldCursor >= argv.size() ) OldCursor = static_cast<unsigned int>(argv.size()) - 1;
846 search_failed_f = true;
847
848 // (*) first loop from cursor position until end
849 unsigned c = cursor;
850 for(; c < argv.size(); c++) {
851 if( argv[c] == SearchTerm )
852 { cursor = c; search_failed_f = false; return true; }
853 }
854 if( ! search_loop_f ) return false;
855
856 // (*) second loop from 0 to old cursor position
857 for(c = 1; c < OldCursor; c++) {
858 if( argv[c] == SearchTerm )
859 { cursor = c; search_failed_f = false; return true; }
860 }
861 // in case nothing is found the cursor stays where it was
862 return false;
863}
864
865
866inline bool
867GetPot::search(unsigned No, const char* P, ...)
868{
869 // (*) recording the requested arguments happens in subroutine 'search'
870 if( No == 0 ) return false;
871
872 // search for the first argument
873 if( search(P) == true ) return true;
874
875 // start interpreting variable argument list
876 va_list ap;
877 va_start(ap, P);
878 unsigned i = 1;
879 for(; i < No; ++i) {
880 char* Opt = va_arg(ap, char *);
881 if( search(Opt) == true ) break;
882 }
883
884 if( i < No ) {
885 ++i;
886 // loop was left before end of array --> hit but
887 // make sure that the rest of the search terms is marked
888 // as requested.
889 for(; i < No; ++i) {
890 char* Opt = va_arg(ap, char *);
891 // (*) record requested arguments for later ufo detection
892 __record_argument_request(Opt);
893 }
894 va_end(ap);
895 return true;
896 }
897
898 va_end(ap);
899 // loop was left normally --> no hit
900 return false;
901}
902
903inline void
904GetPot::reset_cursor()
905{ search_failed_f = false; cursor = 0; }
906
907inline void
908GetPot::init_multiple_occurrence()
909{ disable_loop(); reset_cursor(); }
910///////////////////////////////////////////////////////////////////////////////
911// (*) direct access to command line arguments
912//.............................................................................
913//
914inline const std::string
915GetPot::operator[](unsigned idx) const
916{ return idx < argv.size() ? argv[idx] : ""; }
917
918inline int
919GetPot::get(unsigned Idx, int Default) const
920{
921 if( Idx >= argv.size() ) return Default;
922 return __convert_to_type(argv[Idx], Default);
923}
924
925inline double
926GetPot::get(unsigned Idx, const double& Default) const
927{
928 if( Idx >= argv.size() ) return Default;
929 return __convert_to_type(argv[Idx], Default);
930}
931
932inline const std::string
933GetPot::get(unsigned Idx, const char* Default) const
934{
935 if( Idx >= argv.size() ) return Default;
936 else return argv[Idx];
937}
938
939inline unsigned
940GetPot::size() const
941{ return static_cast<unsigned int>(argv.size()); }
942
943
944// -- next() function group
945inline int
946GetPot::next(int Default)
947{
948 if( search_failed_f ) return Default;
949 cursor++;
950 if( cursor >= argv.size() )
951 { cursor = static_cast<unsigned int>(argv.size()); return Default; }
952
953 // (*) record requested argument for later ufo detection
954 __record_argument_request(argv[cursor]);
955
956 const std::string Remain = __get_remaining_string(argv[cursor], prefix);
957
958 return Remain != "" ? __convert_to_type(Remain, Default) : Default;
959}
960
961inline double
962GetPot::next(const double& Default)
963{
964 if( search_failed_f ) return Default;
965 cursor++;
966
967 if( cursor >= argv.size() )
968 { cursor = static_cast<unsigned int>(argv.size()); return Default; }
969
970 // (*) record requested argument for later ufo detection
971 __record_argument_request(argv[cursor]);
972
973 std::string Remain = __get_remaining_string(argv[cursor], prefix);
974
975 return Remain != "" ? __convert_to_type(Remain, Default) : Default;
976}
977
978inline const std::string
979GetPot::next(const char* Default)
980{
981 using namespace std;
982
983 if( search_failed_f ) return Default;
984 cursor++;
985
986 if( cursor >= argv.size() )
987 { cursor = static_cast<unsigned int>(argv.size()); return Default; }
988
989 // (*) record requested argument for later ufo detection
990 __record_argument_request(argv[cursor]);
991
992 const std::string Remain = __get_remaining_string(argv[cursor], prefix);
993
994 if( Remain == "" ) return Default;
995
996
997 // (*) function returns a pointer to a char array (inside Remain)
998 // this array will be deleted, though after this function call.
999 // To ensure propper functioning, create a copy inside *this
1000 // object and only delete it, when *this is deleted.
1001 char* result = new char[Remain.length()+1];
1002 strncpy(result, Remain.c_str(), Remain.length()+1);
1003
1004 // store the created string internally, delete if when object deleted
1005 __internal_string_container.push_back(result);
1006
1007 return result;
1008}
1009
1010// -- follow() function group
1011// distinct option to be searched for
1012inline int
1013GetPot::follow(int Default, const char* Option)
1014{
1015 // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1016 if( search(Option) == false ) return Default;
1017 return next(Default);
1018}
1019
1020inline double
1021GetPot::follow(const double& Default, const char* Option)
1022{
1023 // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1024 if( search(Option) == false ) return Default;
1025 return next(Default);
1026}
1027
1028inline const std::string
1029GetPot::follow(const char* Default, const char* Option)
1030{
1031 // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1032 if( search(Option) == false ) return Default;
1033 return next(Default);
1034}
1035
1036// -- second follow() function group
1037// multiple option to be searched for
1038inline int
1039GetPot::follow(int Default, unsigned No, const char* P, ...)
1040{
1041 // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1042 if( No == 0 ) return Default;
1043 if( search(P) == true ) return next(Default);
1044
1045 va_list ap;
1046 va_start(ap, P);
1047 unsigned i=1;
1048 for(; i<No; ++i) {
1049 char* Opt = va_arg(ap, char *);
1050 if( search(Opt) == true ) {
1051 va_end(ap);
1052 return next(Default);
1053 }
1054 }
1055 va_end(ap);
1056 return Default;
1057}
1058
1059inline double
1060GetPot::follow(const double& Default, unsigned No, const char* P, ...)
1061{
1062 // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1063 if( No == 0 ) return Default;
1064 if( search(P) == true ) return next(Default);
1065
1066 va_list ap;
1067 va_start(ap, P);
1068 for(unsigned i=1; i<No; ++i) {
1069 char* Opt = va_arg(ap, char *);
1070 if( search(Opt) == true ) {
1071 va_end(ap);
1072 return next(Default);
1073 }
1074 }
1075 va_end(ap);
1076 return Default;
1077}
1078
1079inline const std::string
1080GetPot::follow(const char* Default, unsigned No, const char* P, ...)
1081{
1082 // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1083 if( No == 0 ) return Default;
1084 if( search(P) == true ) return next(Default);
1085
1086 va_list ap;
1087 va_start(ap, P);
1088 unsigned i=1;
1089 for(; i<No; ++i) {
1090 char* Opt = va_arg(ap, char *);
1091 if( search(Opt) == true ) {
1092 va_end(ap);
1093 return next(Default);
1094 }
1095 }
1096 va_end(ap);
1097 return Default;
1098}
1099
1100
1101///////////////////////////////////////////////////////////////////////////////
1102// (*) lists of nominus following an option
1103//.............................................................................
1104//
1105inline std::vector<std::string>
1106GetPot::nominus_followers(const char* Option)
1107{
1108 std::vector<std::string> result_list;
1109 if( search(Option) == false ) return result_list;
1110 while( 1 + 1 == 2 ) {
1111 ++cursor;
1112 if( cursor >= argv.size() ) {
1113 cursor = argv.size() - 1;
1114 return result_list;
1115 }
1116 if( argv[cursor].length() >= 1 ) {
1117 if( argv[cursor][0] == '-' ) {
1118 return result_list;
1119 }
1120 // -- record for later ufo-detection
1121 __record_argument_request(argv[cursor]);
1122 // -- append to the result list
1123 result_list.push_back(argv[cursor]);
1124 }
1125 }
1126}
1127
1128inline std::vector<std::string>
1129GetPot::nominus_followers(unsigned No, ...)
1130{
1131 std::vector<std::string> result_list;
1132 // (*) record requested of argument is entirely handled in 'search()'
1133 // and 'nominus_followers()'
1134 if( No == 0 ) return result_list;
1135
1136 va_list ap;
1137 va_start(ap, No);
1138 for(unsigned i=0; i<No; ++i) {
1139 char* Option = va_arg(ap, char *);
1140 std::vector<std::string> tmp = nominus_followers(Option);
1141 result_list.insert(result_list.end(), tmp.begin(), tmp.end());
1142
1143 // std::cerr << "option = '" << Option << "'" << std::endl;
1144 // std::cerr << "length = " << tmp.size() << std::endl;
1145 // std::cerr << "new result list = <";
1146 // for(std::vector<std::string>::const_iterator it = result_list.begin();
1147 // it != result_list.end(); ++it)
1148 // std::cerr << *it << ", ";
1149 // std::cerr << ">\n";
1150 }
1151 va_end(ap);
1152 return result_list;
1153}
1154
1155
1156///////////////////////////////////////////////////////////////////////////////
1157// (*) directly connected options
1158//.............................................................................
1159//
1160inline int
1161GetPot::direct_follow(int Default, const char* Option)
1162{
1163 const char* FollowStr = __match_starting_string(Option);
1164 if( FollowStr == 0x0 ) return Default;
1165
1166 // (*) record requested of argument for later ufo-detection
1167 __record_argument_request(std::string(Option) + FollowStr);
1168
1169 if( ++cursor >= static_cast<unsigned int>(argv.size()) ) cursor = static_cast<unsigned int>(argv.size());
1170 return __convert_to_type(FollowStr, Default);
1171}
1172
1173inline double
1174GetPot::direct_follow(const double& Default, const char* Option)
1175{
1176 const char* FollowStr = __match_starting_string(Option);
1177 if( FollowStr == 0 ) return Default;
1178
1179 // (*) record requested of argument for later ufo-detection
1180 __record_argument_request(std::string(Option) + FollowStr);
1181
1182 if( ++cursor >= static_cast<unsigned int>(argv.size()) ) cursor = static_cast<unsigned int>(argv.size());
1183 return __convert_to_type(FollowStr, Default);
1184}
1185
1186inline const std::string
1187GetPot::direct_follow(const char* Default, const char* Option)
1188{
1189 if( search_failed_f ) return Default;
1190 const char* FollowStr = __match_starting_string(Option);
1191 if( FollowStr == 0 ) return Default;
1192
1193 // (*) record requested of argument for later ufo-detection
1194 if( FollowStr ) __record_argument_request(std::string(Option) + FollowStr);
1195
1196 if( ++cursor >= static_cast<unsigned int>(argv.size()) ) cursor = static_cast<unsigned int>(argv.size());
1197 return std::string(FollowStr);
1198}
1199
1200inline std::vector<std::string>
1201GetPot::string_tails(const char* StartString)
1202{
1203 std::vector<std::string> result;
1204 const unsigned N = static_cast<unsigned int>(strlen(StartString));
1205
1206 std::vector<std::string>::iterator it = argv.begin();
1207
1208 unsigned idx = 0;
1209 while( it != argv.end() ) {
1210 // (*) does start string match the given option?
1211 // NO -> goto next option
1212 if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; }
1213
1214 // append the found tail to the result vector
1215 result.push_back((*it).substr(N));
1216
1217 // adapt the nominus vector
1218 std::vector<unsigned>::iterator nit = idx_nominus.begin();
1219 for(; nit != idx_nominus.end(); ++nit) {
1220 if( *nit == idx ) {
1221 idx_nominus.erase(nit);
1222 for(; nit != idx_nominus.end(); ++nit) *nit -= 1;
1223 break;
1224 }
1225 }
1226
1227 // erase the found option
1228 argv.erase(it);
1229
1230 // 100% safe solution: set iterator back to the beginning.
1231 // (normally, 'it--' would be enough, but who knows how the
1232 // iterator is implemented and .erase() definitely invalidates
1233 // the current iterator position.
1234 if( argv.empty() ) break;
1235 it = argv.begin();
1236 }
1237 cursor = 0;
1238 nominus_cursor = -1;
1239 return result;
1240}
1241
1242inline std::vector<int>
1243GetPot::int_tails(const char* StartString, const int Default /* = -1 */)
1244{
1245 std::vector<int> result;
1246 const unsigned N = static_cast<unsigned int>(strlen(StartString));
1247
1248 std::vector<std::string>::iterator it = argv.begin();
1249
1250 unsigned idx = 0;
1251 while( it != argv.end() ) {
1252 // (*) does start string match the given option?
1253 // NO -> goto next option
1254 if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; }
1255
1256 // append the found tail to the result vector
1257 result.push_back(__convert_to_type((*it).substr(N), Default));
1258
1259 // adapt the nominus vector
1260 std::vector<unsigned>::iterator nit = idx_nominus.begin();
1261 for(; nit != idx_nominus.end(); ++nit) {
1262 if( *nit == idx ) {
1263 idx_nominus.erase(nit);
1264 for(; nit != idx_nominus.end(); ++nit) *nit -= 1;
1265 break;
1266 }
1267 }
1268
1269 // erase the found option
1270 argv.erase(it);
1271
1272 // 100% safe solution: set iterator back to the beginning.
1273 // (normally, 'it--' would be enough, but who knows how the
1274 // iterator is implemented and .erase() definitely invalidates
1275 // the current iterator position.
1276 if( argv.empty() ) break;
1277 it = argv.begin();
1278 }
1279 cursor = 0;
1280 nominus_cursor = -1;
1281 return result;
1282}
1283
1284inline std::vector<double>
1285GetPot::double_tails(const char* StartString,
1286 const double Default /* = -1.0 */)
1287{
1288 std::vector<double> result;
1289 const unsigned N = static_cast<unsigned int>(strlen(StartString));
1290
1291 std::vector<std::string>::iterator it = argv.begin();
1292 unsigned idx = 0;
1293 while( it != argv.end() ) {
1294 // (*) does start string match the given option?
1295 // NO -> goto next option
1296 if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; }
1297
1298 // append the found tail to the result vector
1299 result.push_back(__convert_to_type((*it).substr(N), Default));
1300
1301 // adapt the nominus vector
1302 std::vector<unsigned>::iterator nit = idx_nominus.begin();
1303 for(; nit != idx_nominus.end(); ++nit) {
1304 if( *nit == idx ) {
1305 idx_nominus.erase(nit);
1306 for(; nit != idx_nominus.end(); ++nit) *nit -= 1;
1307 break;
1308 }
1309 }
1310
1311 // erase the found option
1312 argv.erase(it);
1313
1314 // 100% safe solution: set iterator back to the beginning.
1315 // (normally, 'it--' would be enough, but who knows how the
1316 // iterator is implemented and .erase() definitely invalidates
1317 // the current iterator position.
1318 if( argv.empty() ) break;
1319 it = argv.begin();
1320 }
1321 cursor = 0;
1322 nominus_cursor = -1;
1323 return result;
1324}
1325
1326
1327
1328
1329
1330inline const char*
1331GetPot::__match_starting_string(const char* StartString)
1332 // pointer to the place where the string after
1333 // the match inside the found argument starts.
1334 // 0 no argument matches the starting string.
1335{
1336 const unsigned N = static_cast<unsigned int>(strlen(StartString));
1337 unsigned OldCursor = cursor;
1338
1339 if( OldCursor >= static_cast<unsigned int>(argv.size()) ) OldCursor = static_cast<unsigned int>(argv.size()) - 1;
1340 search_failed_f = true;
1341
1342 // (*) first loop from cursor position until end
1343 unsigned c = cursor;
1344 for(; c < argv.size(); c++) {
1345 if( strncmp(StartString, argv[c].c_str(), N) == 0)
1346 { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); }
1347 }
1348
1349 if( ! search_loop_f ) return false;
1350
1351 // (*) second loop from 0 to old cursor position
1352 for(c = 1; c < OldCursor; c++) {
1353 if( strncmp(StartString, argv[c].c_str(), N) == 0)
1354 { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); }
1355 }
1356 return 0;
1357}
1358
1359///////////////////////////////////////////////////////////////////////////////
1360// (*) search for flags
1361//.............................................................................
1362//
1363inline bool
1364GetPot::options_contain(const char* FlagList) const
1365{
1366 // go through all arguments that start with a '-' (but not '--')
1367 std::string str;
1368 STRING_VECTOR::const_iterator it = argv.begin();
1369 for(; it != argv.end(); ++it) {
1370 str = __get_remaining_string(*it, prefix);
1371
1372 if( str.length() >= 2 && str[0] == '-' && str[1] != '-' )
1373 if( __check_flags(str, FlagList) ) return true;
1374 }
1375 return false;
1376}
1377
1378inline bool
1379GetPot::argument_contains(unsigned Idx, const char* FlagList) const
1380{
1381 if( Idx >= argv.size() ) return false;
1382
1383 // (*) record requested of argument for later ufo-detection
1384 // an argument that is checked for flags is considered to be 'requested'
1385 ((GetPot*)this)->__record_argument_request(argv[Idx]);
1386
1387 if( prefix == "" )
1388 // search argument for any flag in flag list
1389 return __check_flags(argv[Idx], FlagList);
1390
1391 // if a prefix is set, then the argument index is the index
1392 // inside the 'namespace'
1393 // => only check list of arguments that start with prefix
1394 unsigned no_matches = 0;
1395 unsigned i=0;
1396 for(; i<argv.size(); ++i) {
1397 const std::string Remain = __get_remaining_string(argv[i], prefix);
1398 if( Remain != "") {
1399 no_matches += 1;
1400 if( no_matches == Idx)
1401 return __check_flags(Remain, FlagList);
1402 }
1403 }
1404 // no argument in this namespace
1405 return false;
1406}
1407
1408inline bool
1409GetPot::__check_flags(const std::string& Str, const char* FlagList) const
1410{
1411 const char* p=FlagList;
1412 for(; *p != '\0' ; p++)
1413 if( Str.find(*p) != std::string::npos ) return true; // found something
1414 return false;
1415}
1416
1417///////////////////////////////////////////////////////////////////////////////
1418// (*) nominus arguments
1419inline STRING_VECTOR
1420GetPot::nominus_vector() const
1421 // return vector of nominus arguments
1422{
1423 STRING_VECTOR nv;
1424 std::vector<unsigned>::const_iterator it = idx_nominus.begin();
1425 for(; it != idx_nominus.end(); ++it) {
1426 nv.push_back(argv[*it]);
1427
1428 // (*) record for later ufo-detection
1429 // when a nominus vector is requested, the entire set of nominus arguments are
1430 // tagged as 'requested'
1431 ((GetPot*)this)->__record_argument_request(argv[*it]);
1432 }
1433 return nv;
1434}
1435
1436inline std::string
1437GetPot::next_nominus()
1438{
1439 if( nominus_cursor < int(idx_nominus.size()) - 1 ) {
1440 const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
1441
1442 // (*) record for later ufo-detection
1443 __record_argument_request(Tmp);
1444
1445 // -- cannot use the Tmp variable, since it is temporary and c_str() will return a pointer
1446 // to something that does no longer exist.
1447 return Tmp;
1448 }
1449 return std::string("");
1450}
1451
1452///////////////////////////////////////////////////////////////////////////////
1453// (*) variables
1454//.............................................................................
1455//
1456inline int
1457GetPot::operator()(const char* VarName, int Default) const
1458{
1459 // (*) recording of requested variables happens in '__find_variable()'
1460 const variable* sv = __find_variable(VarName);
1461 if( sv == 0 ) return Default;
1462 return __convert_to_type(sv->original, Default);
1463}
1464
1465inline double
1466GetPot::operator()(const char* VarName, const double& Default) const
1467{
1468 // (*) recording of requested variables happens in '__find_variable()'
1469 const variable* sv = __find_variable(VarName);
1470 if( sv == 0 ) return Default;
1471 return __convert_to_type(sv->original, Default);
1472}
1473
1474inline const std::string
1475GetPot::operator()(const char* VarName, const char* Default) const
1476{
1477 // (*) recording of requested variables happens in '__find_variable()'
1478 const variable* sv = __find_variable(VarName);
1479 if( sv == 0 ) return Default;
1480 // -- returning a c_str() pointer is OK here, since the variable remains existant,
1481 // while 'sv' of course is delete at the end of the function.
1482 return sv->original;
1483}
1484
1485inline int
1486GetPot::operator()(const char* VarName, int Default, unsigned Idx) const
1487{
1488 // (*) recording of requested variables happens in '__find_variable()'
1489 const variable* sv = __find_variable(VarName);
1490 if( sv == 0 ) return Default;
1491 const std::string* element = sv->get_element(Idx);
1492 if( element == 0 ) return Default;
1493 return __convert_to_type(*element, Default);
1494}
1495
1496inline double
1497GetPot::operator()(const char* VarName, const double& Default, unsigned Idx) const
1498{
1499 // (*) recording of requested variables happens in '__find_variable()'
1500 const variable* sv = __find_variable(VarName);
1501 if( sv == 0 ) return Default;
1502 const std::string* element = sv->get_element(Idx);
1503 if( element == 0 ) return Default;
1504 return __convert_to_type(*element, Default);
1505}
1506
1507inline const std::string
1508GetPot::operator()(const char* VarName, const char* Default, unsigned Idx) const
1509{
1510 // (*) recording of requested variables happens in '__find_variable()'
1511 const variable* sv = __find_variable(VarName);
1512 if( sv == 0 ) return Default;
1513 const std::string* element = sv->get_element(Idx);
1514 if( element == 0 ) return Default;
1515 return *element;
1516}
1517
1518inline void
1519GetPot::__record_argument_request(const std::string& Name)
1520{
1521 if( ! __request_recording_f ) return;
1522
1523 // (*) record requested variable for later ufo detection
1524 _requested_arguments.push_back(Name);
1525
1526 // (*) record considered section for ufo detection
1527 STRING_VECTOR STree = __get_section_tree(Name);
1528 victorate(std::string, STree, it)
1529 if( find(_requested_sections.begin(), _requested_sections.end(), *it) == _requested_sections.end() )
1530 if( section.length() != 0 ) _requested_sections.push_back(*it);
1531}
1532
1533inline void
1534GetPot::__record_variable_request(const std::string& Name)
1535{
1536 if( ! __request_recording_f ) return;
1537
1538 // (*) record requested variable for later ufo detection
1539 _requested_variables.push_back(Name);
1540
1541 // (*) record considered section for ufo detection
1542 STRING_VECTOR STree = __get_section_tree(Name);
1543 victorate(std::string, STree, it)
1544 if( find(_requested_sections.begin(), _requested_sections.end(), *it) == _requested_sections.end() )
1545 if( section.length() != 0 ) _requested_sections.push_back(*it);
1546}
1547
1548// (*) following functions are to be used from 'outside', after getpot has parsed its
1549// arguments => append an argument in the argument vector that reflects the addition
1550inline void
1551GetPot::__set_variable(const char* VarName, const char* Value)
1552{
1553 const GetPot::variable* Var = __find_variable(VarName);
1554 if( Var == 0 ) variables.push_back(variable(VarName, Value, _field_separator.c_str()));
1555 else ((GetPot::variable*)Var)->take(Value, _field_separator.c_str());
1556}
1557
1558inline void
1559GetPot::set(const char* VarName, const char* Value, const bool Requested /* = yes */)
1560{
1561 const std::string Arg = prefix + std::string(VarName) + std::string("=") + std::string(Value);
1562 argv.push_back(Arg);
1563 __set_variable(VarName, Value);
1564
1565 // if user does not specify the variable as 'not being requested' it will be
1566 // considered amongst the requested variables
1567 if( Requested ) __record_variable_request(Arg);
1568}
1569
1570inline void
1571GetPot::set(const char* VarName, const double& Value, const bool Requested /* = yes */)
1572{ __set_variable(VarName, __double2string(Value).c_str()); }
1573
1574inline void
1575GetPot::set(const char* VarName, const int Value, const bool Requested /* = yes */)
1576{ __set_variable(VarName, __int2string(Value).c_str()); }
1577
1578
1579inline unsigned
1580GetPot::vector_variable_size(const char* VarName) const
1581{
1582 const variable* sv = __find_variable(VarName);
1583 if( sv == 0 ) return 0;
1584 return static_cast<unsigned int>(sv->value.size());
1585}
1586
1587inline STRING_VECTOR
1588GetPot::get_variable_names() const
1589{
1590 STRING_VECTOR result;
1591 std::vector<GetPot::variable>::const_iterator it = variables.begin();
1592 for(; it != variables.end(); ++it) {
1593 const std::string Tmp = __get_remaining_string((*it).name, prefix);
1594 if( Tmp != "" ) result.push_back(Tmp);
1595 }
1596 return result;
1597}
1598
1599inline STRING_VECTOR
1600GetPot::get_section_names() const
1601{ return section_list; }
1602
1603inline const GetPot::variable*
1604GetPot::__find_variable(const char* VarName) const
1605{
1606 const std::string Name = prefix + VarName;
1607
1608 // (*) record requested variable for later ufo detection
1609 ((GetPot*)this)->__record_variable_request(Name);
1610
1611 std::vector<variable>::const_iterator it = variables.begin();
1612 for(; it != variables.end(); ++it) {
1613 if( (*it).name == Name ) return &(*it);
1614 }
1615 return 0;
1616}
1617
1618///////////////////////////////////////////////////////////////////////////////
1619// (*) ouput (basically for debugging reasons
1620//.............................................................................
1621//
1622inline int
1623GetPot::print() const
1624{
1625 std::cout << "argc = " << static_cast<unsigned int>(argv.size()) << std::endl;
1626 STRING_VECTOR::const_iterator it = argv.begin();
1627 for(; it != argv.end(); ++it)
1628 std::cout << *it << std::endl;
1629 std::cout << std::endl;
1630 return 1;
1631}
1632
1633// (*) dollar bracket expressions (DBEs) ------------------------------------
1634//
1635// 1) Entry Function: __DBE_expand_string()
1636// Takes a string such as
1637//
1638// "${+ ${x} ${y}} Subject-${& ${section} ${subsection}}: ${title}"
1639//
1640// calls __DBE_expand() for each of the expressions
1641//
1642// ${+ ${x} ${y}}
1643// ${& ${section} ${subsection}}
1644// ${Title}
1645//
1646// and returns the string
1647//
1648// "4711 Subject-1.01: Mit den Clowns kamen die Schwaene"
1649//
1650// assuming that
1651// x = "4699"
1652// y = "12"
1653// section = "1."
1654// subsection = "01"
1655// title = "Mit den Clowns kamen die Schwaene"
1656//
1657// 2) __DBE_expand():
1658//
1659// checks for the command, i.e. the 'sign' that follows '${'
1660// divides the argument list into sub-expressions using
1661// __DBE_get_expr_list()
1662//
1663// ${+ ${x} ${y}} -> "${x}" "${y}"
1664// ${& ${section} ${subsection}} -> "${section}" "${subsection}"
1665// ${Title} -> Nothing, variable expansion
1666//
1667// 3) __DBE_expression_list():
1668//
1669// builds a vector of unbracketed whitespace separated strings, i.e.
1670//
1671// " ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
1672//
1673// is split into a vector
1674//
1675// [0] ${Number}.a
1676// [1] ${: Das Marmorbild}
1677// [2] AB-${& Author= ${Eichendorf}}-1870
1678//
1679// Each sub-expression is expanded using expand().
1680//---------------------------------------------------------------------------
1681inline std::string
1682GetPot::__DBE_expand_string(const std::string str)
1683{
1684 // Parses for closing operators '${ }' and expands them letting
1685 // white spaces and other letters as they are.
1686 std::string new_string = "";
1687 unsigned open_brackets = 0;
1688 unsigned first = 0;
1689 unsigned i = 0;
1690 for(; i<str.size(); ++i) {
1691 if( i < str.size() - 2 && str.substr(i, 2) == "${" ) {
1692 if( open_brackets == 0 ) first = i+2;
1693 open_brackets++;
1694 }
1695 else if( str[i] == '}' && open_brackets > 0) {
1696 open_brackets -= 1;
1697 if( open_brackets == 0 ) {
1698 const std::string Replacement = __DBE_expand(str.substr(first, i - first));
1699 new_string += Replacement;
1700 }
1701 }
1702 else if( open_brackets == 0 )
1703 new_string += str[i];
1704 }
1705 return new_string;
1706}
1707
1708inline STRING_VECTOR
1709GetPot::__DBE_get_expr_list(const std::string str_, const unsigned ExpectedNumber)
1710 // ensures that the resulting vector has the expected number
1711 // of arguments, but they may contain an error message
1712{
1713 std::string str = str_;
1714 // Separates expressions by non-bracketed whitespaces, expands them
1715 // and puts them into a list.
1716
1717 unsigned i=0;
1718 // (1) eat initial whitespaces
1719 for(; i < str.size(); ++i)
1720 if( ! isspace(str[i]) ) break;
1721
1722 STRING_VECTOR expr_list;
1723 unsigned open_brackets = 0;
1724 std::vector<unsigned> start_idx;
1725 unsigned start_new_string = i;
1726 unsigned l = static_cast<unsigned int>(str.size());
1727
1728 // (2) search for ${ } expressions ...
1729 while( i < l ) {
1730 const char letter = str[i];
1731 // whitespace -> end of expression
1732 if( isspace(letter) && open_brackets == 0) {
1733 expr_list.push_back(str.substr(start_new_string, i - start_new_string));
1734 bool no_breakout_f = true;
1735 for(++i; i < l ; ++i) {
1736 if( ! isspace(str[i]) )
1737 { no_breakout_f = false; start_new_string = i; break; }
1738 }
1739 if( no_breakout_f ) {
1740 // end of expression list
1741 if( expr_list.size() < ExpectedNumber ) {
1742 const std::string pre_tmp("<< ${ }: missing arguments>>");
1743 STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
1744 expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
1745 }
1746 return expr_list;
1747 }
1748 }
1749
1750 // dollar-bracket expression
1751 if( str.length() >= i+2 && str.substr(i, 2) == "${" ) {
1752 open_brackets++;
1753 start_idx.push_back(i+2);
1754 }
1755 else if( letter == '}' && open_brackets > 0) {
1756 int start = start_idx[start_idx.size()-1];
1757 start_idx.pop_back();
1758 const std::string Replacement = __DBE_expand(str.substr(start, i-start));
1759 if( start - 3 < (int)0)
1760 str = Replacement + str.substr(i+1);
1761 else
1762 str = str.substr(0, start-2) + Replacement + str.substr(i+1);
1763 l = static_cast<unsigned int>(str.size());
1764 i = start + static_cast<unsigned int>(Replacement.size()) - 3;
1765 open_brackets--;
1766 }
1767 ++i;
1768 }
1769
1770 // end of expression list
1771 expr_list.push_back(str.substr(start_new_string, i-start_new_string));
1772
1773 if( expr_list.size() < ExpectedNumber ) {
1774 const std::string pre_tmp("<< ${ }: missing arguments>>");
1775 STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
1776 expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
1777 }
1778
1779 return expr_list;
1780}
1781
1782inline const GetPot::variable*
1783GetPot::__DBE_get_variable(std::string VarName)
1784{
1785 static GetPot::variable ev;
1786 std::string secure_Prefix = prefix;
1787
1788 prefix = section;
1789 // (1) first search in currently active section
1790 const GetPot::variable* var = __find_variable(VarName.c_str());
1791 if( var != 0 ) { prefix = secure_Prefix; return var; }
1792
1793 // (2) search in root name space
1794 prefix = "";
1795 var = __find_variable(VarName.c_str());
1796 if( var != 0 ) { prefix = secure_Prefix; return var; }
1797
1798 prefix = secure_Prefix;
1799
1800 // error occured => variable name == ""
1801 char* tmp = new char[VarName.length() + 25];
1802#ifndef WIN32
1803 snprintf(tmp, (int)sizeof(char)*(VarName.length() + 25),
1804#else
1805 _snprintf(tmp, sizeof(char)*(VarName.length() + 25),
1806#endif
1807 "<<${ } variable '%s' undefined>>", VarName.c_str());
1808 ev.name = "";
1809 ev.original = std::string(tmp);
1810 delete [] tmp;
1811 return &ev;
1812}
1813
1814inline std::string
1815GetPot::__DBE_expand(const std::string expr)
1816{
1817 // ${: } pure text
1818 if( expr[0] == ':' )
1819 return expr.substr(1);
1820
1821 // ${& expr expr ... } text concatination
1822 else if( expr[0] == '&' ) {
1823 const STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 1);
1824
1825 STRING_VECTOR::const_iterator it = A.begin();
1826 std::string result = *it++;
1827 for(; it != A.end(); ++it) result += *it;
1828
1829 return result;
1830 }
1831
1832 // ${<-> expr expr expr} text replacement
1833 else if( expr.length() >= 3 && expr.substr(0, 3) == "<->" ) {
1834 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(3), 3);
1835 std::string::size_type tmp = 0;
1836 const std::string::size_type L = A[1].length();
1837 while( (tmp = A[0].find(A[1])) != std::string::npos ) {
1838 A[0].replace(tmp, L, A[2]);
1839 }
1840 return A[0];
1841 }
1842 // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
1843 else if( expr[0] == '+' ) {
1844 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
1845 STRING_VECTOR::const_iterator it = A.begin();
1846 double result = __convert_to_type(*it++, 0.0);
1847 for(; it != A.end(); ++it)
1848 result += __convert_to_type(*it, 0.0);
1849
1850 return __double2string(result);
1851 }
1852 else if( expr[0] == '-' ) {
1853 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
1854 STRING_VECTOR::const_iterator it = A.begin();
1855 double result = __convert_to_type(*it++, 0.0);
1856 for(; it != A.end(); ++it)
1857 result -= __convert_to_type(*it, 0.0);
1858
1859 return __double2string(result);
1860 }
1861 else if( expr[0] == '*' ) {
1862 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
1863 STRING_VECTOR::const_iterator it = A.begin();
1864 double result = __convert_to_type(*it++, 0.0);
1865 for(; it != A.end(); ++it)
1866 result *= __convert_to_type(*it, 0.0);
1867
1868 return __double2string(result);
1869 }
1870 else if( expr[0] == '/' ) {
1871
1872 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
1873 STRING_VECTOR::const_iterator it = A.begin();
1874 double result = __convert_to_type(*it++, 0.0);
1875 if( result == 0 ) return "0.0";
1876 for(; it != A.end(); ++it) {
1877 const double Q = __convert_to_type(*it, 0.0);
1878 if( Q == 0.0 ) return "0.0";
1879 result /= Q;
1880 }
1881 return __double2string(result);
1882 }
1883
1884 // ${^ ... } power expressions
1885 else if( expr[0] == '^' ) {
1886 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
1887 STRING_VECTOR::const_iterator it = A.begin();
1888 double result = __convert_to_type(*it++, 0.0);
1889 for(; it != A.end(); ++it)
1890 result = pow(result, __convert_to_type(*it, 0.0));
1891 return __double2string(result);
1892 }
1893
1894 // ${== } ${<= } ${>= } comparisons (return the number of the first 'match'
1895 else if( expr.length() >= 2 &&
1896 ( expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
1897 expr.substr(0,2) == "<=" || expr[0] == '>' || expr[0] == '<')) {
1898 // differentiate between two and one sign operators
1899 unsigned op = 0;
1900 enum { EQ, GEQ, LEQ, GT, LT };
1901 if ( expr.substr(0, 2) == "==" ) op = EQ;
1902 else if ( expr.substr(0, 2) == ">=" ) op = GEQ;
1903 else if ( expr.substr(0, 2) == "<=" ) op = LEQ;
1904 else if ( expr[0] == '>' ) op = GT;
1905 else /* "<" */ op = LT;
1906
1907 STRING_VECTOR a;
1908 if ( op == GT || op == LT ) a = __DBE_get_expr_list(expr.substr(1), 2);
1909 else a = __DBE_get_expr_list(expr.substr(2), 2);
1910
1911 std::string x_orig = a[0];
1912 double x = __convert_to_type(x_orig, 1e37);
1913 unsigned i = 1;
1914
1915 STRING_VECTOR::const_iterator y_orig = a.begin();
1916 for(y_orig++; y_orig != a.end(); y_orig++) {
1917 double y = __convert_to_type(*y_orig, 1e37);
1918
1919 // set the strings as reference if one wasn't a number
1920 if ( x == 1e37 || y == 1e37 ) {
1921 // it's a string comparison
1922 if( (op == EQ && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
1923 (op == LEQ && x_orig <= *y_orig) || (op == GT && x_orig > *y_orig) ||
1924 (op == LT && x_orig < *y_orig) )
1925 return __int2string(i);
1926 }
1927 else {
1928 // it's a number comparison
1929 if( (op == EQ && x == y) || (op == GEQ && x >= y) ||
1930 (op == LEQ && x <= y) || (op == GT && x > y) ||
1931 (op == LT && x < y) )
1932 return __int2string(i);
1933 }
1934 ++i;
1935 }
1936
1937 // nothing fulfills the condition => return 0
1938 return "0";
1939 }
1940 // ${?? expr expr} select
1941 else if( expr.length() >= 2 && expr.substr(0, 2) == "??" ) {
1942 STRING_VECTOR a = __DBE_get_expr_list(expr.substr(2), 2);
1943 double x = __convert_to_type(a[0], 1e37);
1944 // last element is always the default argument
1945 if( x == 1e37 || x < 0 || x >= a.size() - 1 ) return a[a.size()-1];
1946
1947 // round x to closest integer
1948 return a[int(x+0.5)];
1949 }
1950 // ${? expr expr expr} if then else conditions
1951 else if( expr[0] == '?' ) {
1952 STRING_VECTOR a = __DBE_get_expr_list(expr.substr(1), 2);
1953 if( __convert_to_type(a[0], 0.0) == 1.0 ) return a[1];
1954 else if( a.size() > 2 ) return a[2];
1955 }
1956 // ${! expr} maxro expansion
1957 else if( expr[0] == '!' ) {
1958 const GetPot::variable* Var = __DBE_get_variable(expr.substr(1));
1959 // error
1960 if( Var->name == "" ) return std::string(Var->original);
1961
1962 const STRING_VECTOR A = __DBE_get_expr_list(Var->original, 2);
1963 return A[0];
1964 }
1965 // ${@: } - string subscription
1966 else if( expr.length() >= 2 && expr.substr(0,2) == "@:" ) {
1967 const STRING_VECTOR A = __DBE_get_expr_list(expr.substr(2), 2);
1968 double x = __convert_to_type(A[1], 1e37);
1969
1970 // last element is always the default argument
1971 if( x == 1e37 || x < 0 || x >= A[0].size() - 1)
1972 return "<<1st index out of range>>";
1973
1974 if( A.size() > 2 ) {
1975 double y = __convert_to_type(A[2], 1e37);
1976 if ( y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x )
1977 return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
1978 else if( y == -1 )
1979 return A[0].substr(int(x+0.5));
1980 return "<<2nd index out of range>>";
1981 }
1982 else {
1983 char* tmp = new char[2];
1984 tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
1985 std::string result(tmp);
1986 delete [] tmp;
1987 return result;
1988 }
1989 }
1990 // ${@ } - vector subscription
1991 else if( expr[0] == '@' ) {
1992 STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
1993 const GetPot::variable* Var = __DBE_get_variable(A[0]);
1994 // error
1995 if( Var->name == "" ) {
1996 // make a copy of the string if an error occured
1997 // (since the error variable is a static variable inside get_variable())
1998 return std::string(Var->original);
1999 }
2000
2001 double x = __convert_to_type(A[1], 1e37);
2002
2003 // last element is always the default argument
2004 if (x == 1e37 || x < 0 || x >= Var->value.size() )
2005 return "<<1st index out of range>>";
2006
2007 if ( A.size() > 2) {
2008 double y = __convert_to_type(A[2], 1e37);
2009 int begin = int(x+0.5);
2010 int end = 0;
2011 if ( y != 1e37 && y > 0 && y <= Var->value.size() && y > x)
2012 end = int(y+1.5);
2013 else if( y == -1 )
2014 end = static_cast<unsigned int>(Var->value.size());
2015 else
2016 return "<<2nd index out of range>>";
2017
2018 std::string result = *(Var->get_element(begin));
2019 int i = begin+1;
2020 for(; i < end; ++i)
2021 result += std::string(" ") + *(Var->get_element(i));
2022 return result;
2023 }
2024 else
2025 return *(Var->get_element(int(x+0.5)));
2026 }
2027
2028 const STRING_VECTOR A = __DBE_get_expr_list(expr, 1);
2029 const GetPot::variable* B = __DBE_get_variable(A[0]);
2030
2031 // make a copy of the string if an error occured
2032 // (since the error variable is a static variable inside get_variable())
2033 if( B->name == "" ) return std::string(B->original);
2034 // (psuggs@pobox.com mentioned to me the warning MSVC++6.0 produces
2035 // with: else return B->original (thanks))
2036 return B->original;
2037}
2038
2039
2040///////////////////////////////////////////////////////////////////////////////
2041// (*) unidentified flying objects
2042//.............................................................................
2043//
2044inline bool
2045GetPot::__search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
2046{
2047 victorate(std::string, VecStr, itk) {
2048 if( *itk == Str ) return true;
2049 }
2050 return false;
2051}
2052
2053inline STRING_VECTOR
2054GetPot::unidentified_arguments(unsigned Number,
2055 const char* KnownArgument1, ...) const
2056{
2057 STRING_VECTOR known_arguments;
2058
2059 // (1) create a vector of known arguments
2060 if( Number == 0 ) return STRING_VECTOR();
2061
2062 va_list ap;
2063 va_start(ap, KnownArgument1);
2064 known_arguments.push_back(std::string(KnownArgument1));
2065 unsigned i=1;
2066 for(; i<Number; ++i)
2067 known_arguments.push_back(std::string(va_arg(ap, char *)));
2068 va_end(ap);
2069
2070 return unidentified_arguments(known_arguments);
2071}
2072
2073inline STRING_VECTOR
2074GetPot::unidentified_arguments() const
2075{ return unidentified_arguments(_requested_arguments); }
2076
2077inline STRING_VECTOR
2078GetPot::unidentified_arguments(const STRING_VECTOR& Knowns) const
2079{
2080 STRING_VECTOR ufos;
2081 STRING_VECTOR::const_iterator it = argv.begin();
2082 ++it; // forget about argv[0] (application or filename)
2083 for(; it != argv.end(); ++it) {
2084 // -- argument belongs to prefixed section ?
2085 const std::string arg = __get_remaining_string(*it, prefix);
2086 if( arg == "" ) continue;
2087
2088 // -- check if in list
2089 if( __search_string_vector(Knowns, arg) == false)
2090 ufos.push_back(*it);
2091 }
2092 return ufos;
2093}
2094
2095inline STRING_VECTOR
2096GetPot::unidentified_options(unsigned Number,
2097 const char* KnownOption1, ...) const
2098{
2099 STRING_VECTOR known_options;
2100
2101 // (1) create a vector of known arguments
2102 if( Number == 0 ) return STRING_VECTOR();
2103
2104 va_list ap;
2105 va_start(ap, KnownOption1);
2106 known_options.push_back(std::string(KnownOption1));
2107 unsigned i=1;
2108 for(; i<Number; ++i)
2109 known_options.push_back(std::string(va_arg(ap, char *)));
2110 va_end(ap);
2111
2112 return unidentified_options(known_options);
2113}
2114
2115inline STRING_VECTOR
2116GetPot::unidentified_options() const
2117{
2118 // -- every option is an argument.
2119 // -- the set of requested arguments contains the set of requested options.
2120 // -- IF the set of requested arguments contains unrequested options,
2121 // THEN they were requested as 'follow' and 'next' arguments and not as real options.
2122 //
2123 // => it is not necessary to separate requested options from the list
2124 STRING_VECTOR option_list;
2125 victorate(std::string, _requested_arguments, it) {
2126 const std::string arg = *it;
2127 if( arg.length() == 0 ) continue;
2128 if( arg[0] == '-' ) option_list.push_back(arg);
2129 }
2130 return unidentified_options(option_list);
2131}
2132
2133inline STRING_VECTOR
2134GetPot::unidentified_options(const STRING_VECTOR& Knowns) const
2135{
2136 STRING_VECTOR ufos;
2137 STRING_VECTOR::const_iterator it = argv.begin();
2138 ++it; // forget about argv[0] (application or filename)
2139 for(; it != argv.end(); ++it) {
2140 // -- argument belongs to prefixed section ?
2141 const std::string arg = __get_remaining_string(*it, prefix);
2142 if( arg == "" ) continue;
2143
2144 // is argument really an option (starting with '-') ?
2145 if( arg.length() < 1 || arg[0] != '-' ) continue;
2146
2147 if( __search_string_vector(Knowns, arg) == false)
2148 ufos.push_back(*it);
2149 }
2150
2151 return ufos;
2152}
2153
2154inline std::string
2155GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
2156 // Two modes:
2157 // ArgumentNumber >= 0 check specific argument
2158 // ArgumentNumber == -1 check all options starting with one '-'
2159 // for flags
2160{
2161 std::string ufos;
2162 STRING_VECTOR known_arguments;
2163 std::string KFL(KnownFlagList);
2164
2165 // (2) iteration over '-' arguments (options)
2166 if( ArgumentNumber == -1 ) {
2167 STRING_VECTOR::const_iterator it = argv.begin();
2168 ++it; // forget about argv[0] (application or filename)
2169 for(; it != argv.end(); ++it) {
2170 // -- argument belongs to prefixed section ?
2171 const std::string arg = __get_remaining_string(*it, prefix);
2172 if( arg == "" ) continue;
2173
2174 // -- does arguments start with '-' (but not '--')
2175 if ( arg.length() < 2 ) continue;
2176 else if( arg[0] != '-' ) continue;
2177 else if( arg[1] == '-' ) continue;
2178
2179 // -- check out if flags inside option are contained in KnownFlagList
2180 const char* p=arg.c_str();
2181 p++; // skip starting minus
2182 for(; *p != '\0' ; p++)
2183 if( KFL.find(*p) == std::string::npos ) ufos += *p;
2184 }
2185 }
2186 // (1) check specific argument
2187 else {
2188 // -- only check arguments that start with prefix
2189 int no_matches = 0;
2190 unsigned i=1;
2191 for(; i<argv.size(); ++i) {
2192 const std::string Remain = __get_remaining_string(argv[i], prefix);
2193 if( Remain != "") {
2194 no_matches++;
2195 if( no_matches == ArgumentNumber) {
2196 // -- the right argument number inside the section is found
2197 // => check it for flags
2198 const char* p = Remain.c_str();
2199 p++; // skip starting minus
2200 for(; *p != '\0' ; p++)
2201 if( KFL.find(*p) == std::string::npos ) ufos += *p;
2202 return ufos;
2203 }
2204 }
2205 }
2206 }
2207 return ufos;
2208}
2209
2210inline STRING_VECTOR
2211GetPot::unidentified_variables(unsigned Number,
2212 const char* KnownVariable1, ...) const
2213{
2214 STRING_VECTOR known_variables;
2215
2216 // create vector of known arguments
2217 if( Number == 0 ) return STRING_VECTOR();
2218
2219 va_list ap;
2220 va_start(ap, KnownVariable1);
2221 known_variables.push_back(std::string(KnownVariable1));
2222 unsigned i=1;
2223 for(; i<Number; ++i)
2224 known_variables.push_back(std::string(va_arg(ap, char *)));
2225 va_end(ap);
2226
2227 return unidentified_variables(known_variables);
2228}
2229
2230inline STRING_VECTOR
2231GetPot::unidentified_variables(const STRING_VECTOR& Knowns) const
2232{
2233 STRING_VECTOR ufos;
2234
2235 victorate(GetPot::variable, variables, it) {
2236 // -- check if variable has specific prefix
2237 const std::string var_name = __get_remaining_string((*it).name, prefix);
2238 if( var_name == "" ) continue;
2239
2240 // -- check if variable is known
2241 if( __search_string_vector(Knowns, var_name) == false)
2242 ufos.push_back((*it).name);
2243 }
2244 return ufos;
2245}
2246
2247inline STRING_VECTOR
2248GetPot::unidentified_variables() const
2249{ return unidentified_variables(_requested_variables); }
2250
2251
2252inline STRING_VECTOR
2253GetPot::unidentified_sections(unsigned Number,
2254 const char* KnownSection1, ...) const
2255{
2256 STRING_VECTOR known_sections;
2257
2258 // (1) create a vector of known arguments
2259 if( Number == 0 ) return STRING_VECTOR();
2260
2261 va_list ap;
2262 va_start(ap, KnownSection1);
2263 known_sections.push_back(std::string(KnownSection1));
2264 unsigned i=1;
2265 for(; i<Number; ++i) {
2266 std::string tmp = std::string(va_arg(ap, char *));
2267 if( tmp.length() == 0 ) continue;
2268 if( tmp[tmp.length()-1] != '/' ) tmp += '/';
2269 known_sections.push_back(tmp);
2270 }
2271 va_end(ap);
2272
2273 return unidentified_sections(known_sections);
2274}
2275
2276inline STRING_VECTOR
2277GetPot::unidentified_sections() const
2278{ return unidentified_sections(_requested_sections); }
2279
2280inline STRING_VECTOR
2281GetPot::unidentified_sections(const STRING_VECTOR& Knowns) const
2282{
2283 STRING_VECTOR ufos;
2284
2285 victorate(std::string, section_list, it) {
2286 // -- check if section conform to prefix
2287 const std::string sec_name = __get_remaining_string(*it, prefix);
2288 if( sec_name == "" ) continue;
2289
2290 // -- check if section is known
2291 if( __search_string_vector(Knowns, sec_name) == false )
2292 ufos.push_back(*it);
2293 }
2294
2295 return ufos;
2296}
2297
2298
2299inline STRING_VECTOR
2300GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
2301{
2302 STRING_VECTOR known_nominuses;
2303
2304 // create vector of known arguments
2305 if( Number == 0 ) return STRING_VECTOR();
2306
2307 va_list ap;
2308 va_start(ap, Known);
2309 known_nominuses.push_back(std::string(Known));
2310 unsigned i=1;
2311 for(; i<Number; ++i) {
2312 std::string tmp = std::string(va_arg(ap, char *));
2313 if( tmp.length() == 0 ) continue;
2314 known_nominuses.push_back(tmp);
2315 }
2316 va_end(ap);
2317
2318 return unidentified_nominuses(known_nominuses);
2319}
2320
2321inline STRING_VECTOR
2322GetPot::unidentified_nominuses() const {
2323 // -- every nominus is an argument.
2324 // -- the set of requested arguments contains the set of requested nominuss.
2325 // -- IF the set of requested arguments contains unrequested nominuss,
2326 // THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
2327 //
2328 // => it is not necessary to separate requested nominus from the list
2329
2330 return unidentified_nominuses(_requested_arguments);
2331}
2332
2333inline STRING_VECTOR
2334GetPot::unidentified_nominuses(const STRING_VECTOR& Knowns) const
2335{
2336 STRING_VECTOR ufos;
2337
2338 // (2) iterate over all arguments
2339 STRING_VECTOR::const_iterator it = argv.begin();
2340 ++it; // forget about argv[0] (application or filename)
2341 for(; it != argv.end(); ++it) {
2342 // -- check if nominus part of prefix
2343 const std::string arg = __get_remaining_string(*it, prefix);
2344 if( arg == "" ) continue;
2345
2346 if( arg.length() < 1 ) continue;
2347 // option ? --> not a nomius
2348 if( arg[0] == '-' ) continue;
2349 // section ? --> not a real nominus
2350 if( arg[0] == '[' && arg[arg.length()-1] == ']' ) continue;
2351 // variable definition ? --> not a real nominus
2352 bool continue_f = false;
2353 unsigned i=0;
2354 for(; i<arg.length() ; ++i)
2355 if( arg[i] == '=' ) { continue_f = true; break; }
2356 if( continue_f ) continue;
2357
2358 // real nominuses are compared with the given list
2359 if( __search_string_vector(Knowns, arg) == false )
2360 ufos.push_back(*it);
2361 }
2362 return ufos;
2363}
2364
2365
2366///////////////////////////////////////////////////////////////////////////////
2367// (*) variable class
2368//.............................................................................
2369//
2370inline
2371GetPot::variable::variable()
2372{}
2373
2374inline
2375GetPot::variable::variable(const variable& That)
2376{
2377#ifdef WIN32
2378 operator=(That);
2379#else
2380 GetPot::variable::operator=(That);
2381#endif
2382}
2383
2384
2385inline
2386GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
2387 : name(Name)
2388{
2389 // make a copy of the 'Value'
2390 take(Value, FieldSeparator);
2391}
2392
2393inline const std::string*
2394GetPot::variable::get_element(unsigned Idx) const
2395{ if( Idx >= value.size() ) return 0; else return &(value[Idx]); }
2396
2397inline void
2398GetPot::variable::take(const char* Value, const char* FieldSeparator)
2399{
2400 using namespace std;
2401
2402 original = std::string(Value);
2403
2404 // separate string by white space delimiters using 'strtok'
2405 // thread safe usage of strtok (no static members)
2406 char* spt = 0;
2407 // make a copy of the 'Value'
2408 char* copy = new char[strlen(Value)+1];
2409 strcpy(copy, Value);
2410 char* follow_token = strtok_r(copy, FieldSeparator, &spt);
2411 if( value.size() != 0 ) value.erase(value.begin(), value.end());
2412 while(follow_token != 0) {
2413 value.push_back(std::string(follow_token));
2414 follow_token = strtok_r(NULL, FieldSeparator, &spt);
2415 }
2416
2417 delete [] copy;
2418}
2419
2420inline
2421GetPot::variable::~variable()
2422{}
2423
2424inline GetPot::variable&
2425GetPot::variable::operator=(const GetPot::variable& That)
2426{
2427 if( &That != this) {
2428 name = That.name;
2429 value = That.value;
2430 original = That.original;
2431 }
2432 return *this;
2433}
2434
2435#undef victorate
2436
2437
2438#endif // __include_guard_GETPOT_H__
2439
2440