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