Line data Source code
1 : // -*- c++ -*-
2 : // GetPot Version libMeshHPCT_fork-1.2 Apr/14/2010
3 : // Based on "getpot-1.1.1.tgz" version from SourceForge
4 : //
5 : // New code (C) 2009-2013 Roy Stogner, Karl Schulz
6 : //
7 : // GetPot Version 1.0 Sept/13/2002
8 : //
9 : // WEBSITE: http://getpot.sourceforge.net
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-2002 Frank R. Schaefer
27 : //==========================================================================
28 : #ifndef LIBMESH_GETPOT_H
29 : #define LIBMESH_GETPOT_H
30 :
31 : #if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC)
32 : #define strtok_r(a, b, c) strtok(a, b)
33 : #endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC
34 :
35 : #include <algorithm>
36 : #include <cstddef>
37 : #include <fstream>
38 : #include <iostream> // not every compiler distribution includes <iostream> with <fstream>
39 : #include <memory>
40 : #include <set>
41 : #include <sstream>
42 : #include <stdexcept>
43 : #include <string>
44 : #include <typeinfo>
45 : #include <vector>
46 :
47 : #include <cmath>
48 : #include <cstdlib>
49 : #include <ctime>
50 : #include <cctype>
51 :
52 : extern "C" {
53 : #include <stdarg.h> // --> va_list and friends
54 : #include <string.h> // --> strcmp, strncmp, strlen, strncpy
55 : }
56 :
57 : // Undefine USE_LIBMESH to avoid libMesh-specific code
58 :
59 : #define USE_LIBMESH 1
60 :
61 : #ifdef USE_LIBMESH
62 :
63 : #include "libmesh/libmesh_common.h"
64 :
65 : // We need a mutex to keep const operations thread-safe in the
66 : // presence of mutable containers. Right now GetPot supports a
67 : // Threads::scoped_mutex wrapper around TBB, and we're assuming that
68 : // users aren't doing any threaded GetPot usage when TBB threads are
69 : // disabled.
70 : #if !defined(GETPOT_DISABLE_MUTEX)
71 : #include "libmesh/threads.h"
72 : #define SCOPED_MUTEX libMesh::Threads::spin_mutex::scoped_lock lock(_getpot_mtx)
73 : #define GETPOT_MUTEX_DECLARE mutable libMesh::Threads::spin_mutex _getpot_mtx
74 : #else
75 : #define SCOPED_MUTEX
76 : #define GETPOT_MUTEX_DECLARE
77 : #endif
78 :
79 : #define getpot_cerr libMesh::err
80 : #define getpot_error() libmesh_error()
81 : #define getpot_file_error(filename) libmesh_file_error(filename)
82 : #define getpot_cast_int libMesh::cast_int
83 :
84 : // If libmesh detected the inverse hyperbolic trig functions, set
85 : // special #defines for getpot.h
86 : #ifdef LIBMESH_HAVE_CXX11_INVERSE_HYPERBOLIC_SINE
87 : #define HAVE_INVERSE_HYPERBOLIC_SINE
88 : #endif
89 :
90 : #ifdef LIBMESH_HAVE_CXX11_INVERSE_HYPERBOLIC_COSINE
91 : #define HAVE_INVERSE_HYPERBOLIC_COSINE
92 : #endif
93 :
94 : #ifdef LIBMESH_HAVE_CXX11_INVERSE_HYPERBOLIC_TANGENT
95 : #define HAVE_INVERSE_HYPERBOLIC_TANGENT
96 : #endif
97 :
98 : #else // !USE_LIBMESH
99 :
100 : // Currently threaded GetPot use is only supported via libMesh Threads
101 : #define GETPOT_DISABLE_MUTEX
102 : #define SCOPED_MUTEX
103 : #define GETPOT_MUTEX_DECLARE
104 :
105 : #define getpot_cerr std::cerr
106 : #define getpot_error() throw std::runtime_error(std::string("GetPot Error"))
107 : #define getpot_file_error(filename) getpot_error()
108 : #define getpot_cast_int static_cast
109 :
110 : // Clang provides the __has_builtin macro, we define it for compilers
111 : // that don't...
112 : #ifndef __has_builtin
113 : #define __has_builtin(x) 0
114 : #endif
115 :
116 : // Fine-grained ifdefs for all three inverse hyperbolic trig
117 : // functions. This works for the two clang compilers I tried it
118 : // on... a hand-built one and one from Apple.
119 : #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(asinh))
120 : #define HAVE_INVERSE_HYPERBOLIC_SINE
121 : #endif
122 :
123 : #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(acosh))
124 : #define HAVE_INVERSE_HYPERBOLIC_COSINE
125 : #endif
126 :
127 : #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(atanh))
128 : #define HAVE_INVERSE_HYPERBOLIC_TANGENT
129 : #endif
130 :
131 : #endif // #ifdef USE_LIBMESH
132 :
133 :
134 : typedef std::vector<std::string> STRING_VECTOR;
135 :
136 : #define victorate(TYPE, VARIABLE, ITERATOR) \
137 : std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin(); \
138 : for (; (ITERATOR) != (VARIABLE).end(); ++(ITERATOR))
139 :
140 : // We allow GETPOT_NAMESPACE to be defined before this file is
141 : // included; if libraries using two different versions of GetPot might
142 : // be linked together, the result may be unsafe unless they're put in
143 : // different namespaces.
144 : #ifdef GETPOT_NAMESPACE
145 : namespace GETPOT_NAMESPACE {
146 : #endif
147 :
148 : /**
149 : * GetPot - A class for parsing command line arguments and
150 : * configuration files.
151 : *
152 : * \author Frank R. Schaefer
153 : * \date (C) 2001-2002
154 : */
155 3064 : class GetPot
156 : {
157 : inline void _basic_initialization();
158 :
159 : public:
160 : /**
161 : * constructors, destructor, assignment operator
162 : */
163 : inline GetPot();
164 : inline GetPot(const GetPot&);
165 : inline GetPot(const int argc_, const char* const* argv_,
166 : const char* FieldSeparator=0x0);
167 : inline GetPot(const char* FileName,
168 : const char* CommentStart=0x0, const char* CommentEnd=0x0,
169 : const char* FieldSeparator=0x0);
170 : inline GetPot(const std::string& FileName,
171 : const std::string& CommentStart = std::string("#"),
172 : const std::string& CommentEnd = std::string("\n"),
173 : const std::string& FieldSeparator = std::string(" \t\n"));
174 :
175 : /**
176 : * This constructor is mainly for testing. The std::string based constructor
177 : * should be preferred.
178 : */
179 : inline GetPot(std::istream& FileStream,
180 : const std::string& CommentStart = std::string("#"),
181 : const std::string& CommentEnd = std::string("\n"),
182 : const std::string& FieldSeparator = std::string(" \t\n"));
183 : inline ~GetPot();
184 : inline GetPot& operator=(const GetPot&);
185 :
186 : /**
187 : * Re-initialization methods
188 : */
189 : inline void parse_command_line(const int argc_, const char * const* argv_,
190 : const char* FieldSeparator =0x0);
191 : inline void parse_input_file(const std::string& FileName,
192 : const std::string& CommentStart=std::string("#"),
193 : const std::string& CommentEnd=std::string("\n"),
194 : const std::string& FieldSeparator=std::string(" \t\n"));
195 :
196 : inline void parse_input_stream(std::istream& FileStream,
197 : const std::string& FileName=std::string("ParsedFromStream"),
198 : const std::string& CommentStart=std::string("#"),
199 : const std::string& CommentEnd=std::string("\n"),
200 : const std::string& FieldSeparator=std::string(" \t\n"));
201 :
202 : /**
203 : * absorbing contents of another GetPot object
204 : */
205 : inline void absorb(const GetPot& Other);
206 :
207 : /**
208 : * for ufo detection: recording requested arguments, options etc.
209 : */
210 : inline void clear_requests();
211 : inline void disable_request_recording() { request_recording_f = false; }
212 : inline void enable_request_recording() { request_recording_f = true; }
213 :
214 : /**
215 : * direct access to command line arguments
216 : */
217 : inline const char* operator[](unsigned Idx) const;
218 :
219 : template <typename T>
220 : inline T get(unsigned Idx, const T& Default) const;
221 :
222 : inline const char* get(unsigned Idx, const char* Default) const;
223 : inline unsigned size() const;
224 :
225 : /**
226 : * flags
227 : */
228 : inline bool options_contain(const char* FlagList) const;
229 : inline bool argument_contains(unsigned Idx, const char* FlagList) const;
230 :
231 : /**
232 : * variables
233 : */
234 :
235 : /**
236 : * check for a variable
237 : */
238 : inline bool have_variable(const char* VarName) const;
239 : inline bool have_variable(const std::string& VarName) const;
240 :
241 : /**
242 : * Check for a section name. When querying, the section_name
243 : * can be of the form
244 : * Section1 or Section1/
245 : *
246 : * Section1/Section2 or Section1/Section2/
247 : *
248 : * etc.
249 : */
250 : bool have_section(const char* section_name) const;
251 :
252 : /**
253 : * Check for a section name. When querying, the section_name
254 : * can be of the form
255 : * Section1 or Section1/
256 : *
257 : * Section1/Section2 or Section1/Section2/
258 : *
259 : * etc.
260 : */
261 : bool have_section(const std::string& section_name) const;
262 :
263 : /**
264 : * scalar values
265 : */
266 : template<typename T>
267 : inline T operator()(const char* VarName, const T& Default) const;
268 :
269 : template<typename T>
270 : inline T operator()(const std::string& VarName, const T& Default) const;
271 :
272 : inline const char* operator()(const char* VarName, const char* Default) const;
273 : inline const char* operator()(const std::string& VarName, const char* Default) const;
274 :
275 : /**
276 : * vectors
277 : */
278 : template<typename T>
279 : inline T operator()(const char* VarName, const T& Default, unsigned Idx) const;
280 :
281 : template<typename T>
282 : inline T operator()(const std::string& VarName, const T& Default, unsigned Idx) const;
283 :
284 : inline const char* operator()(const char* VarName, const char* Default, unsigned Idx) const;
285 : inline const char* operator()(const std::string& VarName, const char* Default, unsigned Idx) const;
286 :
287 : /**
288 : * access variables, but error out if not present
289 : * scalar values
290 : */
291 : template<typename T>
292 : inline T get_value_no_default(const char* VarName, const T& Default) const;
293 :
294 : template<typename T>
295 : inline T get_value_no_default(const std::string& VarName, const T& Default) const;
296 :
297 : inline const char* get_value_no_default(const char* VarName, const char* Default) const;
298 : inline const char* get_value_no_default(const std::string& VarName, const char* Default) const;
299 :
300 : /**
301 : * vectors
302 : */
303 : template<typename T>
304 : inline T get_value_no_default(const char* VarName, const T& Default, unsigned Idx) const;
305 :
306 : template<typename T>
307 : inline T get_value_no_default(const std::string& VarName, const T& Default, unsigned Idx) const;
308 :
309 : inline const char* get_value_no_default(const char* VarName, const char* Default, unsigned Idx) const;
310 : inline const char* get_value_no_default(const std::string& VarName, const char* Default, unsigned Idx) const;
311 :
312 : /**
313 : * setting variables
314 : * i) from outside of GetPot (considering prefix etc.)
315 : * ii) from inside, use '_set_variable()' below
316 : */
317 : template<typename T>
318 : inline void set(const char* VarName, const T& Value, const bool Requested = true);
319 :
320 : template<typename T>
321 : inline void set(const std::string& VarName, const T& Value, const bool Requested = true);
322 :
323 : inline void set(const char* VarName, const char* Value, const bool Requested = true);
324 : inline void set(const std::string& VarName, const char* Value, const bool Requested = true);
325 :
326 : inline unsigned vector_variable_size(const char* VarName) const;
327 : inline unsigned vector_variable_size(const std::string& VarName) const;
328 :
329 : /*
330 : * Return a list of all variables set by the current input
331 : */
332 : inline STRING_VECTOR get_variable_names() const;
333 :
334 : /*
335 : * Return a list of all sections present in the current input
336 : */
337 : inline STRING_VECTOR get_section_names() const;
338 :
339 : /*
340 : * Return a list of all subsections of the given section name in the
341 : * current input.
342 : *
343 : * Subsections will be returned in the order they appear in the
344 : * input.
345 : *
346 : * Subsections which exist multiple times in the input file will
347 : * only be returned once, in the position of their first appearance.
348 : */
349 : inline STRING_VECTOR get_subsection_names(const std::string & section_name) const;
350 :
351 : inline std::set<std::string> get_overridden_variables() const;
352 :
353 : /**
354 : * cursor oriented functions
355 : */
356 : inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); }
357 : inline bool search_failed() const { return search_failed_f; }
358 :
359 : /**
360 : * enable/disable search for an option in loop
361 : */
362 0 : inline void disable_loop() { search_loop_f = false; }
363 0 : inline void enable_loop() { search_loop_f = true; }
364 :
365 : /**
366 : * reset cursor to position '1'
367 : */
368 : inline void reset_cursor();
369 : inline void init_multiple_occurrence();
370 :
371 : /**
372 : * search for a certain option and set cursor to position
373 : */
374 : inline bool search(const char* option);
375 : inline bool search(const std::string& option);
376 : inline bool search(unsigned No, const char* P, ...);
377 :
378 : /**
379 : * get argument at cursor++
380 : */
381 : template<typename T>
382 : inline T next(const T& Default);
383 :
384 : inline const char* next(const char* Default);
385 :
386 : /**
387 : * search for option and get argument at cursor++
388 : */
389 : template<typename T>
390 : inline T follow(const T& Default, const char* Option);
391 :
392 : inline const char* follow(const char* Default, const char* Option);
393 :
394 : /**
395 : * search for one of the given options and get argument that follows it
396 : */
397 : template<typename T>
398 : inline T follow(const T& Default, unsigned No, const char* Option, ...);
399 :
400 : inline const char* follow(const char* Default, unsigned No, const char* Option, ...);
401 :
402 : /**
403 : * directly followed arguments
404 : */
405 : template<typename T>
406 : inline T direct_follow(const T& Default, const char* Option);
407 :
408 : inline const char* direct_follow(const char* Default, const char* Option);
409 :
410 : /**
411 : * nominus arguments
412 : */
413 : inline void reset_nominus_cursor();
414 : inline STRING_VECTOR nominus_vector() const;
415 : inline unsigned nominus_size() const { return getpot_cast_int<unsigned>(idx_nominus.size()); }
416 : inline const char* next_nominus();
417 : inline std::string next_nominus_string();
418 :
419 : /**
420 : * unidentified flying objects
421 : */
422 : inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const;
423 : inline STRING_VECTOR unidentified_arguments(const std::set<std::string>& Knowns) const;
424 : inline STRING_VECTOR unidentified_arguments(const std::vector<std::string>& Knowns) const;
425 : inline STRING_VECTOR unidentified_arguments() const;
426 :
427 : inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const;
428 : inline STRING_VECTOR unidentified_options(const std::set<std::string>& Knowns) const;
429 : inline STRING_VECTOR unidentified_options(const std::vector<std::string>& Knowns) const;
430 : inline STRING_VECTOR unidentified_options() const;
431 :
432 : inline std::string unidentified_flags(const char* Known, int ArgumentNumber /* =-1 */) const;
433 :
434 : inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const;
435 : inline STRING_VECTOR unidentified_variables(const std::set<std::string>& Knowns) const;
436 : inline STRING_VECTOR unidentified_variables(const std::vector<std::string>& Knowns) const;
437 : inline STRING_VECTOR unidentified_variables() const;
438 :
439 : inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const;
440 : inline STRING_VECTOR unidentified_sections(const std::set<std::string>& Knowns) const;
441 : inline STRING_VECTOR unidentified_sections(const std::vector<std::string>& Knowns) const;
442 : inline STRING_VECTOR unidentified_sections() const;
443 :
444 : inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const;
445 : inline STRING_VECTOR unidentified_nominuses(const std::set<std::string>& Knowns) const;
446 : inline STRING_VECTOR unidentified_nominuses(const std::vector<std::string>& Knowns) const;
447 : inline STRING_VECTOR unidentified_nominuses() const;
448 :
449 : /**
450 : * Accessors for requested variables
451 : */
452 : std::set<std::string> get_requested_arguments() const;
453 : std::set<std::string> get_requested_variables() const;
454 : std::set<std::string> get_requested_sections() const;
455 :
456 : /**
457 : * output
458 : */
459 :
460 : /**
461 : * Print everything
462 : */
463 : inline int print(std::ostream &out_stream = std::cout) const;
464 :
465 : /**
466 : * Print everything after skipping skip_count arguments, with a
467 : * custom prefix. skip_count defaults to 1 to handle the common
468 : * "executable input_file" command line case.
469 : */
470 : inline int print(const char *custom_prefix,
471 : std::ostream &out_stream = std::cout,
472 : unsigned int skip_count=1) const;
473 :
474 : private:
475 :
476 : /**
477 : * Variable to be specified on the command line or in input files.
478 : * (i.e. of the form var='12 312 341')
479 : */
480 : struct variable
481 : {
482 : /**
483 : * constructors, destructors, assignment operator
484 : */
485 : variable();
486 : variable(const variable&);
487 : variable(const char* Name, const char* Value, const char* FieldSeparator);
488 : ~variable();
489 : variable& operator=(const variable& Other);
490 :
491 : void take(const char* Value, const char* FieldSeparator);
492 :
493 : /**
494 : * get a specific element in the string vector
495 : * (return 0 if not present)
496 : */
497 : const std::string* get_element(unsigned Idx) const;
498 :
499 : /**
500 : * data members
501 : */
502 : std::string name; // identifier of variable
503 : STRING_VECTOR value; // value of variable stored in vector
504 : std::string original; // value of variable as given on command line
505 : };
506 :
507 : /**
508 : * member variables
509 : */
510 : std::string prefix; // prefix automatically added in queries
511 : std::string section; // (for dollar bracket parsing)
512 : STRING_VECTOR section_list; // list of all parsed sections
513 :
514 : /**
515 : * argument vector
516 : */
517 : STRING_VECTOR argv; // vector of command line arguments stored as strings
518 : unsigned cursor; // cursor for argv
519 : bool search_loop_f; // shall search start at beginning after reaching end of arg array ?
520 : bool search_failed_f; // flag indicating a failed search() operation (e.g. next() functions react with 'missed')
521 : std::set<std::string> overridden_vars; // vector of variables that were supplied more than once during parsing
522 :
523 : /**
524 : * nominus vector
525 : */
526 : int nominus_cursor; // cursor for nominus_pointers
527 : std::vector<unsigned> idx_nominus; // indices of 'no minus' arguments
528 :
529 : /**
530 : * variables (arguments of the form "variable=value")
531 : */
532 : std::vector<variable> variables;
533 :
534 : /**
535 : * comment delimiters
536 : */
537 : std::string _comment_start;
538 : std::string _comment_end;
539 :
540 : /**
541 : * field separator (separating elements of a vector)
542 : */
543 : std::string _field_separator;
544 :
545 : /**
546 : * we have some mutable non-thread-safe members, but we
547 : * want to be able to call const member functions from
548 : * multiple threads at once, so we'll wrap access to
549 : * mutable objects in a mutex.
550 : */
551 : GETPOT_MUTEX_DECLARE;
552 :
553 : /**
554 : * Transparent comparator object used for making std::sets that
555 : * contain unique_ptrs.
556 : */
557 : struct ltstr
558 : {
559 : /**
560 : * As of C++14, std::set::find() can be a templated overload.
561 : * https://en.cppreference.com/w/cpp/container/set/find
562 : * We enable this by defining is_transparent as a type.
563 : * See also: the CompareUnderlying struct in libmesh/utility.h
564 : */
565 : using is_transparent = void;
566 :
567 28 : bool operator()(const std::unique_ptr<const char[]> & s1,
568 : const std::unique_ptr<const char[]> & s2) const
569 1005 : { return strcmp(s1.get(), s2.get()) < 0; }
570 :
571 12 : bool operator()(const std::unique_ptr<const char[]> & s1,
572 : const char * const & s2) const
573 507 : { return strcmp(s1.get(), s2) < 0; }
574 :
575 0 : bool operator()(const char * const & s1,
576 : const std::unique_ptr<const char[]> & s2) const
577 24 : { return strcmp(s1, s2.get()) < 0; }
578 : };
579 :
580 : /**
581 : * some functions return a char pointer to a string created on the fly.
582 : * this container makes them 'available' until the getpot object is destroyed.
583 : * user codes are recommended to instead request std::string values.
584 : * We use char* here because c_str() results are only
585 : * guaranteed to remain valid until a non-const string
586 : * method is called
587 : */
588 : mutable std::set<std::unique_ptr<const char[]>, ltstr> _internal_string_container;
589 :
590 : /**
591 : * some functions return a char pointer to a temporarily existing string
592 : * this function adds them to our container
593 : */
594 : const char* _internal_managed_copy(const std::string& Arg) const;
595 :
596 : /**
597 : * keeping track about arguments that are requested, so that the UFO detection
598 : * can be simplified
599 : */
600 : mutable std::set<std::string> _requested_arguments;
601 : mutable std::set<std::string> _requested_variables;
602 : mutable std::set<std::string> _requested_sections;
603 :
604 : bool request_recording_f; // speed: request recording can be turned off
605 :
606 : /**
607 : * if an argument is requested record it and the 'tag' the section branch to which
608 : * it belongs. Caution: both functions mark the sections as 'tagged'.
609 : * These are "const" functions but they do modify the
610 : * mutable _requested_* members
611 : */
612 : void _record_argument_request(const std::string& Arg) const;
613 : void _record_variable_request(const std::string& Arg) const;
614 :
615 : /**
616 : * helper functions
617 : */
618 :
619 : /**
620 : * set variable from inside GetPot (no prefix considered)
621 : */
622 : inline void _set_variable(const std::string& VarName,
623 : const std::string& Value,
624 : const bool Requested);
625 :
626 : /**
627 : * produce three basic data vectors:
628 : * - argument vector
629 : * - nominus vector
630 : * - variable dictionary
631 : */
632 : inline void _parse_argument_vector(const STRING_VECTOR& ARGV);
633 :
634 : /**
635 : * helpers for argument list processing
636 : */
637 :
638 : /**
639 : * search for a variable in 'variables' array
640 : */
641 : inline const variable* _find_variable(const char*) const;
642 :
643 : /**
644 : * search (and record request) for a variable in 'variables' array
645 : */
646 : inline const variable* _request_variable(const char*) const;
647 :
648 : /**
649 : * support finding directly followed arguments
650 : */
651 : inline const char* _match_starting_string(const char* StartString);
652 :
653 : /**
654 : * support search for flags in a specific argument
655 : */
656 : inline bool _check_flags(const std::string& Str, const char* FlagList) const;
657 :
658 : /**
659 : * type conversion if possible
660 : */
661 : template<typename T>
662 : inline T _convert_to_type(const std::string& String, const T& Default) const;
663 :
664 : inline std::string _convert_to_type(const std::string& String, const char* Default) const;
665 :
666 : template<typename T>
667 : inline T _convert_to_type_no_default(const char* VarName, const std::string& String, const T& Default) const;
668 :
669 : inline std::string _convert_to_type_no_default(const char* VarName, const std::string& String, const char* Default) const;
670 :
671 : /**
672 : * prefix extraction
673 : */
674 : const std::string _get_remaining_string(const std::string& String,
675 : const std::string& Start) const;
676 : /**
677 : * search for a specific string
678 : */
679 : inline bool _search_string_vector(const STRING_VECTOR& Vec,
680 : const std::string& Str) const;
681 :
682 : /**
683 : * helpers to parse input file
684 : * create an argument vector based on data found in an input file, i.e.:
685 : * 1) delete comments (in between '_comment_start' '_comment_end')
686 : * 2) contract assignment expressions, such as
687 : * my-variable = '007 J. B.'
688 : * into
689 : * my-variable='007 J. B.'
690 : * 3) interpret sections like '[../my-section]' etc.
691 : */
692 : inline void _skip_whitespace(std::istream& istr);
693 : inline const std::string _get_next_token(std::istream& istr);
694 : inline const std::string _get_string(std::istream& istr);
695 : inline const std::string _get_until_closing_bracket(std::istream& istr);
696 : inline const std::string _get_until_closing_square_bracket(std::istream& istr);
697 :
698 : inline STRING_VECTOR _read_in_stream(std::istream& istr);
699 : inline std::string _process_section_label(const std::string& Section,
700 : STRING_VECTOR& section_stack);
701 :
702 : /**
703 : * dollar bracket expressions
704 : */
705 : std::string _DBE_expand_string(const std::string& str);
706 : std::string _DBE_expand(const std::string& str);
707 : const GetPot::variable* _DBE_get_variable(const std::string& str);
708 : STRING_VECTOR _DBE_get_expr_list(const std::string& str, const unsigned ExpectedNumber);
709 :
710 : template <typename T>
711 0 : static std::string _convert_from_type(const T& Value)
712 : {
713 0 : std::ostringstream out_string;
714 0 : out_string << Value;
715 0 : return out_string.str();
716 0 : }
717 :
718 : /**
719 : * cuts a variable name into a tree of sub-sections. this is requested for recording
720 : * requested sections when dealing with 'ufo' detection.
721 : */
722 12337886 : static STRING_VECTOR _get_section_tree(const std::string& FullPath)
723 : {
724 42014 : STRING_VECTOR result;
725 315678034 : for (std::size_t pos = 0; pos != FullPath.size(); ++pos)
726 : {
727 303340148 : if (FullPath[pos] == '/')
728 16 : result.push_back(FullPath.substr(0,pos));
729 : }
730 :
731 12337886 : return result;
732 0 : }
733 : };
734 :
735 :
736 : ///////////////////////////////////////////////////////////////////////////////
737 : // (*) constructors, destructor, assignment operator
738 : //.............................................................................
739 : //
740 : inline void
741 9216 : GetPot::_basic_initialization()
742 : {
743 9216 : cursor = 0;
744 9216 : nominus_cursor = -1;
745 9216 : search_failed_f = true;
746 9216 : search_loop_f = true;
747 9216 : prefix = "";
748 9216 : section = "";
749 :
750 : // automatic request recording for later ufo detection
751 9216 : request_recording_f = true;
752 :
753 : // comment start and end strings
754 9216 : _comment_start = std::string("#");
755 9216 : _comment_end = std::string("\n");
756 :
757 : // default: separate vector elements by whitespaces
758 9216 : _field_separator = " \t\n";
759 9216 : }
760 :
761 :
762 :
763 : inline
764 : GetPot::GetPot() :
765 : prefix(),
766 : section(),
767 : section_list(),
768 : argv(),
769 : cursor(),
770 : search_loop_f(),
771 : search_failed_f(),
772 : nominus_cursor(),
773 : idx_nominus(),
774 : variables(),
775 : _comment_start(),
776 : _comment_end(),
777 : _field_separator(),
778 : #if !defined(GETPOT_DISABLE_MUTEX)
779 : _getpot_mtx(),
780 : #endif
781 : _internal_string_container(),
782 : _requested_arguments(),
783 : _requested_variables(),
784 : _requested_sections(),
785 : request_recording_f()
786 : {
787 : _basic_initialization();
788 : }
789 :
790 :
791 :
792 : inline
793 31130 : GetPot::GetPot(const int argc_, const char * const * argv_,
794 31130 : const char* FieldSeparator /* =0x0 */) :
795 : // leave 'char**' non-const to honor less capable compilers ...
796 29322 : prefix(),
797 29322 : section(),
798 29322 : section_list(),
799 29322 : argv(),
800 29322 : cursor(),
801 29322 : search_loop_f(),
802 29322 : search_failed_f(),
803 29322 : nominus_cursor(),
804 : idx_nominus(),
805 29322 : variables(),
806 29322 : _comment_start(),
807 29322 : _comment_end(),
808 29322 : _field_separator(),
809 : #if !defined(GETPOT_DISABLE_MUTEX)
810 : _getpot_mtx(),
811 : #endif
812 : _internal_string_container(),
813 : _requested_arguments(),
814 : _requested_variables(),
815 : _requested_sections(),
816 34874 : request_recording_f()
817 : {
818 31130 : this->parse_command_line(argc_, argv_, FieldSeparator);
819 31130 : }
820 :
821 :
822 :
823 : // leave 'char**' non-const to honor less capable compilers ...
824 : inline void
825 24146 : GetPot::parse_command_line(const int argc_, const char * const * argv_,
826 : const char* FieldSeparator /* =0x0 */)
827 : {
828 24146 : _basic_initialization();
829 :
830 : // if specified -> overwrite default string
831 24146 : if (FieldSeparator)
832 0 : _field_separator = std::string(FieldSeparator);
833 :
834 : // -- make an internal copy of the argument list:
835 1480 : STRING_VECTOR _apriori_argv;
836 : // -- for the sake of clarity: we do want to include the first
837 : // argument of the first parsing source in the argument vector!
838 : // it will not be a nominus argument, though. This gives us a
839 : // minimum vector size of one which facilitates error checking
840 : // in many functions. Also the user will be able to retrieve
841 : // the name of his application or input file by "get[0]"
842 25082 : _apriori_argv.push_back(std::string(argv_[0]));
843 370510 : for (int i=1; i<argc_; i++)
844 : {
845 347636 : std::string tmp(argv_[i]); // recall the problem with temporaries,
846 346364 : _apriori_argv.push_back(tmp); // reference counting in argument lists ...
847 : }
848 24146 : _parse_argument_vector(_apriori_argv);
849 24146 : }
850 :
851 :
852 :
853 : inline
854 0 : GetPot::GetPot(const char* FileName,
855 : const char* CommentStart /* = 0x0 */, const char* CommentEnd /* = 0x0 */,
856 0 : const char* FieldSeparator/* = 0x0 */) :
857 0 : prefix(),
858 0 : section(),
859 0 : section_list(),
860 0 : argv(),
861 0 : cursor(),
862 0 : search_loop_f(),
863 0 : search_failed_f(),
864 0 : nominus_cursor(),
865 : idx_nominus(),
866 0 : variables(),
867 0 : _comment_start(),
868 0 : _comment_end(),
869 0 : _field_separator(),
870 : #if !defined(GETPOT_DISABLE_MUTEX)
871 : _getpot_mtx(),
872 : #endif
873 : _internal_string_container(),
874 : _requested_arguments(),
875 : _requested_variables(),
876 : _requested_sections(),
877 0 : request_recording_f()
878 : {
879 0 : const std::string& StrCommentStart = CommentStart ? CommentStart : std::string("#");
880 0 : const std::string& StrCommentEnd = CommentEnd ? CommentEnd : std::string("\n");
881 0 : const std::string& StrFieldSeparator = FieldSeparator ? FieldSeparator : std::string(" \t\n");
882 0 : this->parse_input_file(FileName, StrCommentStart, StrCommentEnd, StrFieldSeparator);
883 0 : }
884 :
885 :
886 :
887 : inline
888 12 : GetPot::GetPot(const std::string& FileName,
889 : const std::string& CommentStart,
890 : const std::string& CommentEnd,
891 12 : const std::string& FieldSeparator) :
892 0 : prefix(),
893 0 : section(),
894 0 : section_list(),
895 0 : argv(),
896 0 : cursor(),
897 0 : search_loop_f(),
898 0 : search_failed_f(),
899 0 : nominus_cursor(),
900 : idx_nominus(),
901 0 : variables(),
902 0 : _comment_start(),
903 0 : _comment_end(),
904 0 : _field_separator(),
905 : #if !defined(GETPOT_DISABLE_MUTEX)
906 : _getpot_mtx(),
907 : #endif
908 : _internal_string_container(),
909 : _requested_arguments(),
910 : _requested_variables(),
911 : _requested_sections(),
912 60 : request_recording_f()
913 : {
914 12 : this->parse_input_file(FileName, CommentStart, CommentEnd, FieldSeparator);
915 12 : }
916 :
917 : inline void
918 0 : GetPot::parse_input_file(const std::string& FileName,
919 : const std::string& CommentStart,
920 : const std::string& CommentEnd,
921 : const std::string& FieldSeparator)
922 : {
923 0 : std::ifstream input(FileName.c_str());
924 :
925 0 : if (!input)
926 0 : getpot_file_error(FileName);
927 :
928 0 : this->parse_input_stream(input,FileName,CommentStart,CommentEnd,FieldSeparator);
929 0 : }
930 :
931 :
932 : inline
933 : GetPot::GetPot(std::istream& FileStream,
934 : const std::string& CommentStart,
935 : const std::string& CommentEnd,
936 : const std::string& FieldSeparator) :
937 : prefix(),
938 : section(),
939 : section_list(),
940 : argv(),
941 : cursor(),
942 : search_loop_f(),
943 : search_failed_f(),
944 : nominus_cursor(),
945 : idx_nominus(),
946 : variables(),
947 : _comment_start(),
948 : _comment_end(),
949 : _field_separator(),
950 : #if !defined(GETPOT_DISABLE_MUTEX)
951 : _getpot_mtx(),
952 : #endif
953 : _internal_string_container(),
954 : _requested_arguments(),
955 : _requested_variables(),
956 : _requested_sections(),
957 : request_recording_f()
958 : {
959 : this->parse_input_stream(FileStream,
960 : std::string("ParsedFromStream"),// We don't have a filename here
961 : CommentStart, CommentEnd, FieldSeparator);
962 : }
963 :
964 :
965 : inline void
966 0 : GetPot::parse_input_stream(std::istream& FileStream,
967 : const std::string& FileName,
968 : const std::string& CommentStart,
969 : const std::string& CommentEnd,
970 : const std::string& FieldSeparator)
971 : {
972 0 : _basic_initialization();
973 :
974 : // overwrite default strings
975 0 : _comment_start = std::string(CommentStart);
976 0 : _comment_end = std::string(CommentEnd);
977 0 : _field_separator = FieldSeparator;
978 :
979 0 : STRING_VECTOR _apriori_argv;
980 : // -- the first element of the argument vector stores the name of
981 : // the first parsing source; however, this element is not
982 : // parsed for variable assignments or nominuses.
983 : //
984 : // Regardless, we don't add more than one name to the argument
985 : // vector. In this case, we're parsing from a stream, so we'll
986 : // hardcode the "filename" to "ParsedFromStream"
987 0 : _apriori_argv.push_back(FileName);
988 :
989 0 : STRING_VECTOR args = _read_in_stream(FileStream);
990 0 : _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end());
991 0 : _parse_argument_vector(_apriori_argv);
992 0 : }
993 :
994 :
995 :
996 : inline
997 : GetPot::GetPot(const GetPot& Other) :
998 : prefix(Other.prefix),
999 : section(Other.section),
1000 : section_list(Other.section_list),
1001 : argv(Other.argv),
1002 : cursor(Other.cursor),
1003 : search_loop_f(Other.search_loop_f),
1004 : search_failed_f(Other.search_failed_f),
1005 : overridden_vars(),
1006 : nominus_cursor(Other.nominus_cursor),
1007 : idx_nominus(Other.idx_nominus),
1008 : variables(Other.variables),
1009 : _comment_start(Other._comment_start),
1010 : _comment_end(Other._comment_end),
1011 : _field_separator(Other._field_separator),
1012 : // #if !defined(GETPOT_DISABLE_MUTEX)
1013 : // _getpot_mtx(Other._getpot_mtx),
1014 : // #endif
1015 : _internal_string_container(),
1016 : _requested_arguments(Other._requested_arguments),
1017 : _requested_variables(Other._requested_variables),
1018 : _requested_sections(Other._requested_sections),
1019 : request_recording_f(Other.request_recording_f)
1020 : {
1021 : for (const auto & otherstr : Other._internal_string_container)
1022 : {
1023 : auto newlen = strlen(otherstr.get()) + 1;
1024 : auto newcopy = std::make_unique<char[]>(newlen);
1025 : strncpy(newcopy.get(), otherstr.get(), newlen);
1026 : this->_internal_string_container.insert(std::move(newcopy));
1027 : }
1028 : }
1029 :
1030 :
1031 :
1032 : inline
1033 26076 : GetPot::~GetPot() = default;
1034 :
1035 :
1036 :
1037 : inline GetPot&
1038 : GetPot::operator=(const GetPot& Other)
1039 : {
1040 : if (&Other == this)
1041 : return *this;
1042 :
1043 : prefix = Other.prefix;
1044 : section = Other.section;
1045 : section_list = Other.section_list;
1046 : argv = Other.argv;
1047 : cursor = Other.cursor;
1048 : search_loop_f = Other.search_loop_f;
1049 : search_failed_f = Other.search_failed_f;
1050 : nominus_cursor = Other.nominus_cursor;
1051 : overridden_vars = Other.overridden_vars;
1052 : idx_nominus = Other.idx_nominus;
1053 : variables = Other.variables;
1054 : _comment_start = Other._comment_start;
1055 : _comment_end = Other._comment_end;
1056 : _field_separator = Other._field_separator;
1057 : // #if !defined(GETPOT_DISABLE_MUTEX)
1058 : // _getpot_mtx = Other._getpot_mtx;
1059 : // #endif
1060 : _requested_arguments = Other._requested_arguments;
1061 : _requested_variables = Other._requested_variables;
1062 : _requested_sections = Other._requested_sections;
1063 : request_recording_f = Other.request_recording_f;
1064 :
1065 : // Clear existing strings
1066 : _internal_string_container.clear();
1067 :
1068 : for (const auto & otherstr : Other._internal_string_container)
1069 : {
1070 : auto newlen = strlen(otherstr.get()) + 1;
1071 : auto newcopy = std::make_unique<char[]>(newlen);
1072 : strncpy(newcopy.get(), otherstr.get(), newlen);
1073 : this->_internal_string_container.insert(std::move(newcopy));
1074 : }
1075 :
1076 : return *this;
1077 : }
1078 :
1079 :
1080 :
1081 : inline void
1082 : GetPot::absorb(const GetPot& Other)
1083 : {
1084 : if (&Other == this)
1085 : return;
1086 :
1087 : // variables that are not influenced by absorption:
1088 : // _comment_start
1089 : // _comment_end
1090 : // cursor
1091 : // nominus_cursor
1092 : // search_failed
1093 : // idx_nominus
1094 : // search_loop_f
1095 : argv = Other.argv;
1096 : variables = Other.variables;
1097 :
1098 : if (request_recording_f)
1099 : {
1100 : // Get a lock before touching anything mutable
1101 : SCOPED_MUTEX;
1102 :
1103 : _requested_arguments.insert(Other._requested_arguments.begin(), Other._requested_arguments.end());
1104 : _requested_variables.insert(Other._requested_variables.begin(), Other._requested_variables.end());
1105 : _requested_sections.insert(Other._requested_sections.begin(), Other._requested_sections.end());
1106 : }
1107 : }
1108 :
1109 :
1110 :
1111 : inline void
1112 : GetPot::clear_requests()
1113 : {
1114 : // Get a lock before touching anything mutable
1115 : SCOPED_MUTEX;
1116 :
1117 : _requested_arguments.clear();
1118 : _requested_variables.clear();
1119 : _requested_sections.clear();
1120 : }
1121 :
1122 :
1123 :
1124 : inline void
1125 9204 : GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV)
1126 : {
1127 9204 : if (ARGV.empty())
1128 0 : return;
1129 :
1130 : // build internal databases:
1131 : // 1) array with no-minus arguments (usually used as filenames)
1132 : // 2) variable assignments:
1133 : // 'variable name' '=' number | string
1134 768 : STRING_VECTOR section_stack;
1135 256 : STRING_VECTOR::const_iterator it = ARGV.begin();
1136 :
1137 :
1138 9204 : section = "";
1139 :
1140 : // -- do not parse the first argument, so that this parsing source
1141 : // name is not interpreted a s a nominus or so. If we already
1142 : // have parsed arguments, don't bother adding another parsing
1143 : // source name
1144 9204 : if (argv.empty())
1145 9204 : argv.push_back(*it);
1146 256 : ++it;
1147 :
1148 : // -- loop over remaining arguments
1149 150124 : for (; it != ARGV.end(); ++it)
1150 : {
1151 139728 : std::string arg = *it;
1152 :
1153 140920 : if (arg.length() == 0)
1154 0 : continue;
1155 :
1156 : // -- [section] labels and [include file] directives
1157 140920 : if (arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']')
1158 : {
1159 :
1160 : // Is this an include file directive?
1161 0 : std::size_t include_pos = arg.find("include ", 1);
1162 0 : if (include_pos != std::string::npos)
1163 : {
1164 :
1165 : const std::string includefile =
1166 0 : _DBE_expand_string(arg.substr(9, arg.length()-9-include_pos));
1167 :
1168 : this->parse_input_file
1169 0 : (includefile, _comment_start, _comment_end, _field_separator);
1170 : }
1171 :
1172 : else
1173 : {
1174 : // (*) sections are considered 'requested arguments'
1175 0 : if (request_recording_f)
1176 : {
1177 : // Get a lock before touching anything mutable
1178 0 : SCOPED_MUTEX;
1179 :
1180 0 : _requested_arguments.insert(arg);
1181 : }
1182 :
1183 0 : const std::string Name = _DBE_expand_string(arg.substr(1, arg.length()-2));
1184 0 : section = _process_section_label(Name, section_stack);
1185 : // new section --> append to list of sections
1186 0 : if (find(section_list.begin(), section_list.end(), section) == section_list.end())
1187 0 : if (section.length() != 0) section_list.push_back(section);
1188 0 : argv.push_back(arg);
1189 : }
1190 : }
1191 : else
1192 : {
1193 142112 : arg = section + _DBE_expand_string(arg);
1194 140920 : argv.push_back(arg);
1195 : }
1196 :
1197 : // -- separate array for nominus arguments
1198 140920 : if (arg[0] != '-')
1199 69606 : idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1));
1200 :
1201 : // -- variables: does arg contain a '=' operator ?
1202 1192 : const std::size_t equals_pos = arg.find_first_of('=');
1203 140920 : if (equals_pos != std::string::npos)
1204 : {
1205 : // (*) record for later ufo detection
1206 : // arguments carrying variables are always treated as 'requested' arguments.
1207 : // unrequested variables have to be detected with the ufo-variable
1208 : // detection routine.
1209 4760 : if (request_recording_f)
1210 : {
1211 : // Get a lock before touching anything mutable
1212 656 : SCOPED_MUTEX;
1213 :
1214 4432 : _requested_arguments.insert(arg);
1215 : }
1216 :
1217 : // => arg (from start to '=') = Name of variable
1218 : // (from '=' to end) = value of variable
1219 9192 : _set_variable(arg.substr(0,equals_pos),
1220 9520 : arg.substr(equals_pos+1), false);
1221 : }
1222 : }
1223 8692 : }
1224 :
1225 :
1226 :
1227 : inline STRING_VECTOR
1228 0 : GetPot::_read_in_stream(std::istream& istr)
1229 : {
1230 0 : STRING_VECTOR brute_tokens;
1231 0 : while (istr)
1232 : {
1233 0 : _skip_whitespace(istr);
1234 0 : const std::string Token = _get_next_token(istr);
1235 : // Allow 'keyword =' to parse with an empty string as value.
1236 : // Only break at EOF.
1237 : // if (Token.length() == 0 || Token[0] == EOF) break;
1238 0 : if (Token[0] == EOF)
1239 0 : break;
1240 0 : brute_tokens.push_back(Token);
1241 : }
1242 :
1243 : // -- reduce expressions of token1'='token2 to a single
1244 : // string 'token1=token2'
1245 : // -- copy everything into 'argv'
1246 : // -- arguments preceded by something like '[' name ']' (section)
1247 : // produce a second copy of each argument with a prefix '[name]argument'
1248 0 : unsigned i1 = 0;
1249 0 : unsigned i2 = 1;
1250 0 : unsigned i3 = 2;
1251 :
1252 0 : STRING_VECTOR arglist;
1253 0 : while (i1 < brute_tokens.size())
1254 : {
1255 : // 1) concatenate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef'
1256 : // note: java.lang.String: substring(a,b) = from a to b-1
1257 : // C++ string: substr(a,b) = from a to a + b
1258 0 : std::string result;
1259 0 : if (i2 < brute_tokens.size() && brute_tokens[i2] == "=")
1260 : {
1261 0 : if (i3 >= brute_tokens.size())
1262 0 : result = brute_tokens[i1] + brute_tokens[i2];
1263 : else
1264 0 : result = brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3];
1265 0 : i1 = i3+1; i2 = i3+2; i3 = i3+3;
1266 : }
1267 0 : else if (i2 < brute_tokens.size() &&
1268 0 : brute_tokens[i2].length() > 0 &&
1269 0 : brute_tokens[i2][0] == '=')
1270 : {
1271 : // This case should not be hit if '=' at the beginning of a word
1272 : // is always separated into its own word
1273 0 : result = brute_tokens[i1] + brute_tokens[i2];
1274 0 : i1 = i3; i2 = i3+1; i3 = i3+2;
1275 : }
1276 0 : else if (i2 < brute_tokens.size() && brute_tokens[i1][brute_tokens[i1].size()-1] == '=')
1277 : {
1278 0 : result = brute_tokens[i1] + brute_tokens[i2];
1279 0 : i1 = i3; i2 = i3+1; i3 = i3+2;
1280 : }
1281 : else
1282 : {
1283 0 : result = brute_tokens[i1];
1284 0 : i1=i2; i2=i3; i3++;
1285 : }
1286 :
1287 : // Now strip out any comment
1288 0 : size_t comment_start_loc = result.find(_comment_start, 0);
1289 0 : if (comment_start_loc != std::string::npos)
1290 0 : result = result.substr(0, comment_start_loc);
1291 :
1292 0 : arglist.push_back(result);
1293 : }
1294 0 : return arglist;
1295 0 : }
1296 :
1297 :
1298 :
1299 : inline void
1300 0 : GetPot::_skip_whitespace(std::istream& istr)
1301 : {
1302 : // find next non-whitespace while deleting comments
1303 0 : int tmp = istr.get();
1304 0 : do {
1305 : // -- search a non whitespace
1306 0 : while (std::isspace(tmp))
1307 : {
1308 0 : tmp = istr.get();
1309 0 : if (!istr)
1310 0 : return;
1311 : }
1312 :
1313 : // -- look if characters match the comment starter string
1314 0 : for (unsigned i=0; i<_comment_start.length() ; i++)
1315 : {
1316 0 : if (tmp != _comment_start[i])
1317 : {
1318 : // -- one step more backwards, since 'tmp' already at non-whitespace
1319 0 : istr.unget();
1320 0 : return;
1321 : }
1322 :
1323 : // RHS: Why is this here? It breaks on empty comments
1324 : // tmp = istr.get();
1325 : // if (!istr) { istr.unget(); return; }
1326 : }
1327 : // 'tmp' contains last character of _comment_starter
1328 :
1329 : // -- comment starter found -> search for comment ender
1330 0 : unsigned match_no=0;
1331 : while (true)
1332 : {
1333 0 : tmp = istr.get();
1334 0 : if (!istr)
1335 : {
1336 0 : istr.unget();
1337 0 : return;
1338 : }
1339 :
1340 0 : if (tmp == _comment_end[match_no])
1341 : {
1342 0 : match_no++;
1343 0 : if (match_no == _comment_end.length())
1344 : {
1345 0 : istr.unget();
1346 0 : break; // shuffle more whitespace, end of comment found
1347 : }
1348 : }
1349 : else
1350 0 : match_no = 0;
1351 : }
1352 :
1353 0 : tmp = istr.get();
1354 :
1355 0 : } while (istr);
1356 0 : istr.unget();
1357 : }
1358 :
1359 :
1360 :
1361 : inline const std::string
1362 0 : GetPot::_get_next_token(std::istream& istr)
1363 : {
1364 : // get next concatenates string token. consider quotes that embrace
1365 : // whitespaces
1366 0 : std::string token;
1367 0 : int tmp = 0;
1368 : while (true)
1369 : {
1370 0 : int last_letter = tmp;
1371 0 : tmp = istr.get();
1372 :
1373 0 : if (tmp == '=')
1374 : {
1375 : // Always break at '='.
1376 : // This separates '=' at the beginning of a word into its own word.
1377 0 : token += getpot_cast_int<char>(tmp);
1378 0 : return token;
1379 : }
1380 :
1381 0 : else if (tmp == EOF || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\'))
1382 0 : return token;
1383 :
1384 0 : else if (tmp == '\'' && last_letter != '\\')
1385 : {
1386 : // QUOTES: un-backslashed quotes => it's a string
1387 0 : token += _get_string(istr);
1388 0 : continue;
1389 : }
1390 :
1391 0 : else if (tmp == '{' && last_letter == '$')
1392 : {
1393 0 : token += '{' + _get_until_closing_bracket(istr);
1394 0 : continue;
1395 : }
1396 :
1397 0 : else if (tmp == '[')
1398 : {
1399 0 : token += '[' + _get_until_closing_square_bracket(istr);
1400 0 : continue;
1401 : }
1402 :
1403 0 : else if (tmp == '$' && last_letter == '\\')
1404 : {
1405 0 : token += getpot_cast_int<char>(tmp); tmp = 0; // so that last_letter will become = 0, not '$';
1406 0 : continue;
1407 : }
1408 :
1409 0 : else if (tmp == '\\' && last_letter != '\\')
1410 0 : continue; // don't append un-backslashed backslashes
1411 :
1412 0 : token += getpot_cast_int<char>(tmp);
1413 0 : }
1414 : }
1415 :
1416 :
1417 :
1418 : inline const std::string
1419 0 : GetPot::_get_string(std::istream& istr)
1420 : {
1421 : // parse input until next matching '
1422 0 : std::string str;
1423 0 : int tmp = 0;
1424 : while (true)
1425 : {
1426 0 : int last_letter = tmp;
1427 0 : tmp = istr.get();
1428 0 : if (tmp == EOF)
1429 0 : return str;
1430 :
1431 : // un-backslashed quotes => it's the end of the string
1432 0 : else if (tmp == '\'' && last_letter != '\\')
1433 0 : return str;
1434 :
1435 0 : else if (tmp == '\\' && last_letter != '\\')
1436 0 : continue; // don't append
1437 :
1438 0 : str += getpot_cast_int<char>(tmp);
1439 0 : }
1440 : }
1441 :
1442 :
1443 :
1444 : inline const std::string
1445 0 : GetPot::_get_until_closing_bracket(std::istream& istr)
1446 : {
1447 : // parse input until next matching }
1448 0 : std::string str = "";
1449 0 : int tmp = 0;
1450 0 : int brackets = 1;
1451 : while (true)
1452 : {
1453 0 : int last_letter = tmp;
1454 0 : tmp = istr.get();
1455 0 : if (tmp == EOF)
1456 0 : return str;
1457 :
1458 0 : else if (tmp == '{' && last_letter == '$')
1459 0 : brackets += 1;
1460 :
1461 0 : else if (tmp == '}')
1462 : {
1463 0 : brackets -= 1;
1464 : // un-backslashed brackets => it's the end of the string
1465 0 : if (brackets == 0)
1466 0 : return str + '}';
1467 :
1468 0 : else if (tmp == '\\' && last_letter != '\\')
1469 0 : continue; // do not append an unbackslashed backslash
1470 : }
1471 0 : str += getpot_cast_int<char>(tmp);
1472 0 : }
1473 : }
1474 :
1475 :
1476 :
1477 : inline const std::string
1478 0 : GetPot::_get_until_closing_square_bracket(std::istream& istr)
1479 : {
1480 : // parse input until next matching ]
1481 0 : std::string str = "";
1482 0 : int brackets = 1;
1483 : while (true)
1484 : {
1485 0 : int tmp = istr.get();
1486 0 : if (tmp == EOF)
1487 0 : return str;
1488 :
1489 0 : else if (tmp == '[')
1490 0 : brackets += 1;
1491 :
1492 0 : else if (tmp == ']')
1493 : {
1494 0 : brackets -= 1;
1495 0 : if (brackets == 0)
1496 0 : return str + ']';
1497 : }
1498 :
1499 0 : str += getpot_cast_int<char>(tmp);
1500 0 : }
1501 : }
1502 :
1503 :
1504 :
1505 : inline std::string
1506 0 : GetPot::_process_section_label(const std::string& Section,
1507 : STRING_VECTOR& section_stack)
1508 : {
1509 0 : std::string sname = Section;
1510 : // 1) subsection of actual section ('./' prefix)
1511 0 : if (sname.length() >= 2 && sname.substr(0, 2) == "./")
1512 0 : sname = sname.substr(2);
1513 :
1514 : // 2) subsection of parent section ('../' prefix)
1515 0 : else if (sname.length() >= 3 && sname.substr(0, 3) == "../")
1516 : {
1517 0 : do
1518 : {
1519 0 : if (section_stack.end() != section_stack.begin())
1520 0 : section_stack.pop_back();
1521 0 : sname = sname.substr(3);
1522 0 : } while (sname.substr(0, 3) == "../");
1523 : }
1524 :
1525 : // 3) subsection of the root-section
1526 : else
1527 : // [] => back to root section
1528 0 : section_stack.erase(section_stack.begin(), section_stack.end());
1529 :
1530 0 : if (sname != "")
1531 : {
1532 : // parse section name for 'slashes'
1533 0 : unsigned i=0;
1534 0 : while (i < sname.length())
1535 : {
1536 0 : if (sname[i] == '/')
1537 : {
1538 0 : section_stack.push_back(sname.substr(0,i));
1539 0 : if (i+1 < sname.length())
1540 0 : sname = sname.substr(i+1);
1541 0 : i = 0;
1542 : }
1543 : else
1544 0 : i++;
1545 : }
1546 0 : section_stack.push_back(sname);
1547 : }
1548 :
1549 0 : std::string section_label = "";
1550 0 : if (!section_stack.empty())
1551 : {
1552 0 : victorate(std::string, section_stack, it)
1553 0 : section_label += *it + "/";
1554 : }
1555 0 : return section_label;
1556 : }
1557 :
1558 :
1559 :
1560 : // Use C++ istream/ostream to handle most type conversions.
1561 : template <typename T>
1562 : inline T
1563 17102 : GetPot::_convert_to_type(const std::string& String, const T& Default) const
1564 : {
1565 17102 : std::istringstream in_string(String);
1566 : T retval;
1567 11558 : in_string >> retval;
1568 17102 : if (in_string.fail())
1569 0 : retval = Default;
1570 17690 : return retval;
1571 16514 : }
1572 :
1573 :
1574 :
1575 : // copy string - operator>> would have stopped upon seeing whitespace!
1576 : template <>
1577 : inline std::string
1578 270 : GetPot::_convert_to_type(const std::string& String, const std::string&) const
1579 : {
1580 2550 : return String;
1581 : }
1582 :
1583 :
1584 :
1585 : // copy string
1586 : inline std::string
1587 : GetPot::_convert_to_type(const std::string& String, const char*) const
1588 : {
1589 : return String;
1590 : }
1591 :
1592 :
1593 :
1594 : // be more liberal than std C++ in what we interpret as a boolean
1595 : template<>
1596 : inline bool
1597 277 : GetPot::_convert_to_type<bool>(const std::string& String, const bool & Default) const
1598 : {
1599 269 : std::string newstring(String);
1600 : //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
1601 1525 : for (unsigned int i=0; i<newstring.length(); ++i)
1602 1284 : newstring[i] = getpot_cast_int<char>(toupper(newstring[i]));
1603 :
1604 : // "true"/"True"/"TRUE" should work
1605 277 : if (newstring.find("TRUE")!=std::string::npos)
1606 0 : return true;
1607 :
1608 140 : if (newstring.find("FALSE")!=std::string::npos)
1609 0 : return false;
1610 :
1611 : // And if we don't find that, let's search for an integer and use C unsigned
1612 : // int->bool conversion before giving up; i.e. a user could specify "0" for
1613 : // false or "1" for true
1614 0 : std::istringstream in_string(String);
1615 : unsigned int retval;
1616 0 : in_string >> retval;
1617 0 : if (in_string.fail())
1618 0 : return Default;
1619 :
1620 0 : return retval;
1621 0 : }
1622 :
1623 :
1624 :
1625 : // Use C++ istream/ostream to handle most type conversions.
1626 : template <typename T>
1627 : inline T
1628 : GetPot::_convert_to_type_no_default(const char* VarName, const std::string& String, const T&) const
1629 : {
1630 : std::istringstream in_string(String);
1631 : T retval;
1632 : in_string >> retval;
1633 : if (in_string.fail())
1634 : {
1635 : getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl;
1636 : getpot_cerr <<" value = "<<String<<" expected type = "<<typeid(T).name()<<std::endl;
1637 : getpot_error();
1638 : }
1639 : return retval;
1640 : }
1641 :
1642 :
1643 :
1644 : // copy string - operator>> would have stopped upon seeing whitespace!
1645 : template <>
1646 : inline std::string
1647 : GetPot::_convert_to_type_no_default(const char*, const std::string& String, const std::string&) const
1648 : {
1649 : return String;
1650 : }
1651 :
1652 :
1653 :
1654 : // copy string
1655 : inline std::string
1656 : GetPot::_convert_to_type_no_default(const char*, const std::string& String, const char*) const
1657 : {
1658 : return String;
1659 : }
1660 :
1661 :
1662 :
1663 : // be more liberal than std C++ in what we interpret as a boolean
1664 : template<>
1665 : inline bool
1666 : GetPot::_convert_to_type_no_default<bool>(const char* VarName, const std::string& String, const bool &) const
1667 : {
1668 : std::string newstring(String);
1669 : //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
1670 : for (unsigned int i=0; i<newstring.length(); ++i)
1671 : {
1672 : newstring[i]=getpot_cast_int<char>(toupper(newstring[i]));
1673 : }
1674 :
1675 : // "true"/"True"/"TRUE" should work
1676 : if (newstring.find("TRUE")!=std::string::npos)
1677 : return true;
1678 :
1679 : if (newstring.find("FALSE")!=std::string::npos)
1680 : return false;
1681 :
1682 : // And if we don't find that, let's search for an integer and use C unsigned
1683 : // int->bool conversion before giving up; i.e. a user could specify "0" for
1684 : // false or "1" for true
1685 : std::istringstream in_string(String);
1686 : unsigned int retval;
1687 : in_string >> retval;
1688 : if (in_string.fail())
1689 : {
1690 : getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl;
1691 : getpot_cerr <<" value = "<<String<<" expected type = "<<typeid(bool).name()<<std::endl;
1692 : getpot_error();
1693 : }
1694 :
1695 : return retval;
1696 : }
1697 :
1698 :
1699 :
1700 : inline const char*
1701 462 : GetPot::_internal_managed_copy(const std::string& Arg) const
1702 : {
1703 462 : const char* arg = Arg.c_str();
1704 :
1705 : // Get a lock before touching anything mutable
1706 24 : SCOPED_MUTEX;
1707 :
1708 : // See if there's already an identical string saved
1709 : // If so, return it
1710 462 : if (auto it = _internal_string_container.find(arg);
1711 12 : it != _internal_string_container.end())
1712 0 : return it->get();
1713 :
1714 : // Otherwise, create a new one
1715 474 : auto newcopy = std::make_unique<char[]>(strlen(arg)+1);
1716 : // Note: strcpy() is safe here because we allocated enough space and
1717 : // "arg" is guaranteed to be null-terminated.
1718 462 : strcpy(newcopy.get(), arg);
1719 868 : auto pr = _internal_string_container.insert(std::move(newcopy));
1720 12 : return pr.first->get();
1721 : }
1722 :
1723 :
1724 :
1725 : //////////////////////////////////////////////////////////////////////////////
1726 : // (*) cursor oriented functions
1727 : //.............................................................................
1728 :
1729 : // Checks if 'String' begins with 'Start' and returns the remaining String.
1730 : // Returns None if String does not begin with Start.
1731 : inline const std::string
1732 12916 : GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const
1733 : {
1734 12916 : if (Start == "")
1735 12442 : return String;
1736 :
1737 : // note: java.lang.String: substring(a,b) = from a to b-1
1738 : // C++ string: substr(a,b) = from a to a + b
1739 0 : if (String.find(Start) == 0)
1740 0 : return String.substr(Start.length());
1741 :
1742 : else
1743 0 : return "";
1744 : }
1745 :
1746 :
1747 :
1748 : // -- search for a certain argument and set cursor to position
1749 : inline bool
1750 364522 : GetPot::search(const std::string &Option)
1751 : {
1752 14021503 : return search(Option.c_str());
1753 : }
1754 :
1755 :
1756 :
1757 : // -- search for a certain argument and set cursor to position
1758 : inline bool
1759 13158606 : GetPot::search(const char* Option)
1760 : {
1761 13158606 : unsigned OldCursor = cursor;
1762 13493040 : const std::string SearchTerm = prefix + Option;
1763 :
1764 : // (*) record requested arguments for later ufo detection
1765 13158606 : _record_argument_request(SearchTerm);
1766 :
1767 13492920 : if (OldCursor >= argv.size())
1768 0 : OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
1769 13158606 : search_failed_f = true;
1770 :
1771 : // (*) first loop from cursor position until end
1772 213248782 : for (unsigned c = cursor; c < argv.size(); c++)
1773 : {
1774 198967346 : if (argv[c] == SearchTerm)
1775 : {
1776 7588 : cursor = c;
1777 7588 : search_failed_f = false;
1778 7588 : return true;
1779 : }
1780 : }
1781 13151018 : if (!search_loop_f)
1782 0 : return false;
1783 :
1784 : // (*) second loop from 0 to old cursor position
1785 44193406 : for (unsigned c = 1; c <= OldCursor; c++)
1786 : {
1787 31050747 : if (argv[c] == SearchTerm)
1788 : {
1789 8359 : cursor = c;
1790 8359 : search_failed_f = false;
1791 8359 : return true;
1792 : }
1793 : }
1794 :
1795 : // in case nothing is found the cursor stays where it was
1796 333870 : return false;
1797 : }
1798 :
1799 :
1800 :
1801 : inline bool
1802 0 : GetPot::search(unsigned No, const char* P, ...)
1803 : {
1804 : // (*) recording the requested arguments happens in subroutine 'search'
1805 0 : if (No == 0)
1806 0 : return false;
1807 :
1808 : // search for the first argument
1809 0 : if (search(P) == true)
1810 0 : return true;
1811 :
1812 : // start interpreting variable argument list
1813 : va_list ap;
1814 0 : va_start(ap, P);
1815 0 : unsigned i = 1;
1816 0 : for (; i < No; i++)
1817 : {
1818 0 : char* Opt = va_arg(ap, char *);
1819 : // (*) search records itself for later ufo detection
1820 0 : if (search(Opt) == true)
1821 0 : break;
1822 : }
1823 :
1824 0 : if (i < No)
1825 : {
1826 0 : i++;
1827 : // loop was left before end of array --> hit but
1828 : // make sure that the rest of the search terms is marked
1829 : // as requested.
1830 0 : for (; i < No; i++)
1831 : {
1832 0 : char* Opt = va_arg(ap, char *);
1833 : // (*) record requested arguments for later ufo detection
1834 0 : _record_argument_request(Opt);
1835 : }
1836 0 : va_end(ap);
1837 0 : return true;
1838 : }
1839 :
1840 0 : va_end(ap);
1841 : // loop was left normally --> no hit
1842 0 : return false;
1843 : }
1844 :
1845 :
1846 :
1847 : inline void
1848 0 : GetPot::reset_cursor()
1849 : {
1850 0 : search_failed_f = false;
1851 0 : cursor = 0;
1852 0 : }
1853 :
1854 :
1855 :
1856 : inline void
1857 : GetPot::init_multiple_occurrence()
1858 : {
1859 : disable_loop();
1860 : reset_cursor();
1861 : }
1862 :
1863 :
1864 :
1865 : ///////////////////////////////////////////////////////////////////////////////
1866 : // (*) direct access to command line arguments
1867 : //.............................................................................
1868 : //
1869 : inline const char*
1870 : GetPot::operator[](unsigned idx) const
1871 : {
1872 : return idx<argv.size() ? argv[idx].c_str() : 0;
1873 : }
1874 :
1875 :
1876 :
1877 : template <typename T>
1878 : inline T
1879 : GetPot::get(unsigned int Idx, const T& Default) const
1880 : {
1881 : if (Idx >= argv.size())
1882 : return Default;
1883 : return _convert_to_type(argv[Idx], Default);
1884 : }
1885 :
1886 :
1887 :
1888 : inline const char*
1889 : GetPot::get(unsigned int Idx, const char* Default) const
1890 : {
1891 : if (Idx >= argv.size())
1892 : return Default;
1893 : return argv[Idx].c_str();
1894 : }
1895 :
1896 :
1897 :
1898 : inline unsigned
1899 : GetPot::size() const
1900 : {
1901 : return getpot_cast_int<unsigned>(argv.size());
1902 : }
1903 :
1904 :
1905 :
1906 : // -- next() function group
1907 : template <typename T>
1908 : inline T
1909 12920 : GetPot::next(const T& Default)
1910 : {
1911 12920 : if (search_failed_f)
1912 0 : return Default;
1913 12920 : cursor++;
1914 13394 : if (cursor >= argv.size())
1915 : {
1916 0 : cursor = getpot_cast_int<unsigned>(argv.size());
1917 0 : return Default;
1918 : }
1919 :
1920 : // (*) record requested argument for later ufo detection
1921 12920 : _record_argument_request(argv[cursor]);
1922 :
1923 13428 : const std::string Remain = _get_remaining_string(argv[cursor], prefix);
1924 :
1925 12954 : return Remain != "" ? _convert_to_type(Remain, Default) : Default;
1926 : }
1927 :
1928 :
1929 :
1930 : inline const char*
1931 0 : GetPot::next(const char* Default)
1932 : {
1933 0 : return _internal_managed_copy(next(std::string(Default)));
1934 : }
1935 :
1936 :
1937 :
1938 : // -- follow() function group
1939 : // distinct option to be searched for
1940 : template <typename T>
1941 : inline T
1942 0 : GetPot::follow(const T& Default, const char* Option)
1943 : {
1944 : // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1945 0 : if (search(Option) == false)
1946 0 : return Default;
1947 :
1948 0 : return next(Default);
1949 : }
1950 :
1951 :
1952 :
1953 : inline const char*
1954 : GetPot::follow(const char* Default, const char* Option)
1955 : {
1956 : return _internal_managed_copy(follow(std::string(Default), Option));
1957 : }
1958 :
1959 :
1960 :
1961 : // -- second follow() function group
1962 : // multiple option to be searched for
1963 : template <typename T>
1964 : inline T
1965 : GetPot::follow(const T& Default, unsigned int No, const char* P, ...)
1966 : {
1967 : // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1968 : if (No == 0)
1969 : return Default;
1970 :
1971 : if (search(P) == true)
1972 : return next(Default);
1973 :
1974 : va_list ap;
1975 : va_start(ap, P);
1976 : for (unsigned i=1; i<No; i++)
1977 : {
1978 : char* Opt = va_arg(ap, char *);
1979 : if (search(Opt) == true)
1980 : {
1981 : va_end(ap);
1982 : return next(Default);
1983 : }
1984 : }
1985 : va_end(ap);
1986 : return Default;
1987 : }
1988 :
1989 :
1990 :
1991 : inline const char*
1992 : GetPot::follow(const char* Default, unsigned No, const char* P, ...)
1993 : {
1994 : // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1995 : if (No == 0)
1996 : return Default;
1997 :
1998 : if (search(P) == true)
1999 : return next(Default);
2000 :
2001 : va_list ap;
2002 : va_start(ap, P);
2003 : for (unsigned i=1; i<No; i++)
2004 : {
2005 : char* Opt = va_arg(ap, char *);
2006 : if (search(Opt) == true)
2007 : {
2008 : va_end(ap);
2009 : return next(Default);
2010 : }
2011 : }
2012 : va_end(ap);
2013 : return Default;
2014 : }
2015 :
2016 :
2017 :
2018 : ///////////////////////////////////////////////////////////////////////////////
2019 : // (*) directly connected options
2020 : //.............................................................................
2021 : //
2022 : template <typename T>
2023 : inline T
2024 : GetPot::direct_follow(const T& Default, const char* Option)
2025 : {
2026 : const char* FollowStr = _match_starting_string(Option);
2027 :
2028 : // (*) record requested of argument for later ufo-detection
2029 : _record_argument_request(std::string(Option) + FollowStr);
2030 :
2031 : if (FollowStr == 0)
2032 : return Default;
2033 :
2034 : if (++cursor >= argv.size())
2035 : cursor = getpot_cast_int<unsigned>(argv.size());
2036 : return _convert_to_type(FollowStr, Default);
2037 : }
2038 :
2039 :
2040 :
2041 : inline const char*
2042 : GetPot::direct_follow(const char* Default, const char* Option)
2043 : {
2044 : return _internal_managed_copy(direct_follow(std::string(Default), Option));
2045 : }
2046 :
2047 :
2048 :
2049 : // pointer to the place where the string after
2050 : // the match inside the found argument starts.
2051 : // 0 no argument matches the starting string.
2052 : inline const char*
2053 : GetPot::_match_starting_string(const char* StartString)
2054 : {
2055 : const unsigned N =
2056 : getpot_cast_int<unsigned>(strlen(StartString));
2057 : unsigned OldCursor = cursor;
2058 :
2059 : if (OldCursor >= argv.size())
2060 : OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
2061 : search_failed_f = true;
2062 :
2063 : // (*) first loop from cursor position until end
2064 : for (unsigned c = cursor; c < argv.size(); c++)
2065 : {
2066 : if (strncmp(StartString, argv[c].c_str(), N) == 0)
2067 : {
2068 : cursor = c;
2069 : search_failed_f = false;
2070 : return &(argv[c].c_str()[N]);
2071 : }
2072 : }
2073 :
2074 : if (!search_loop_f)
2075 : return NULL;
2076 :
2077 : // (*) second loop from 0 to old cursor position
2078 : for (unsigned c = 1; c < OldCursor; c++)
2079 : {
2080 : if (strncmp(StartString, argv[c].c_str(), N) == 0)
2081 : {
2082 : cursor = c;
2083 : search_failed_f = false;
2084 : return &(argv[c].c_str()[N]);
2085 : }
2086 : }
2087 : return 0;
2088 : }
2089 :
2090 :
2091 :
2092 : ///////////////////////////////////////////////////////////////////////////////
2093 : // (*) search for flags
2094 : //.............................................................................
2095 : //
2096 : inline bool
2097 : GetPot::options_contain(const char* FlagList) const
2098 : {
2099 : // go through all arguments that start with a '-' (but not '--')
2100 : std::string str;
2101 : STRING_VECTOR::const_iterator it = argv.begin();
2102 : for (; it != argv.end(); ++it)
2103 : {
2104 : str = _get_remaining_string(*it, prefix);
2105 :
2106 : if (str.length() >= 2 && str[0] == '-' && str[1] != '-')
2107 : if (_check_flags(str, FlagList))
2108 : return true;
2109 : }
2110 : return false;
2111 : }
2112 :
2113 :
2114 :
2115 : inline bool
2116 : GetPot::argument_contains(unsigned Idx, const char* FlagList) const
2117 : {
2118 : if (Idx >= argv.size())
2119 : return false;
2120 :
2121 : // (*) record requested of argument for later ufo-detection
2122 : // an argument that is checked for flags is considered to be 'requested'
2123 : _record_argument_request(argv[Idx]);
2124 :
2125 : if (prefix == "")
2126 : // search argument for any flag in flag list
2127 : return _check_flags(argv[Idx], FlagList);
2128 :
2129 : // if a prefix is set, then the argument index is the index
2130 : // inside the 'namespace'
2131 : // => only check list of arguments that start with prefix
2132 : unsigned no_matches = 0;
2133 : for (unsigned i=0; i<argv.size(); i++)
2134 : {
2135 : const std::string Remain = _get_remaining_string(argv[i], prefix);
2136 : if (Remain != "")
2137 : {
2138 : no_matches += 1;
2139 : if (no_matches == Idx)
2140 : return _check_flags(Remain, FlagList);
2141 : }
2142 : }
2143 :
2144 : // no argument in this namespace
2145 : return false;
2146 : }
2147 :
2148 :
2149 :
2150 : inline bool
2151 : GetPot::_check_flags(const std::string& Str, const char* FlagList) const
2152 : {
2153 : for (const char* p=FlagList; *p != '\0' ; p++)
2154 : if (Str.find(*p) != std::string::npos)
2155 : return true; // found something
2156 : return false;
2157 : }
2158 :
2159 :
2160 :
2161 : ///////////////////////////////////////////////////////////////////////////////
2162 : // (*) nominus arguments
2163 :
2164 : // return vector of nominus arguments
2165 : inline STRING_VECTOR
2166 : GetPot::nominus_vector() const
2167 : {
2168 : STRING_VECTOR nv;
2169 : std::vector<unsigned>::const_iterator it = idx_nominus.begin();
2170 : for (; it != idx_nominus.end(); ++it)
2171 : {
2172 : nv.push_back(argv[*it]);
2173 :
2174 : // (*) record for later ufo-detection
2175 : // when a nominus vector is requested, the entire set of nominus arguments are
2176 : // tagged as 'requested'
2177 : _record_argument_request(argv[*it]);
2178 : }
2179 : return nv;
2180 : }
2181 :
2182 :
2183 :
2184 : inline const char*
2185 : GetPot::next_nominus()
2186 : {
2187 : if (nominus_cursor < int(idx_nominus.size()) - 1)
2188 : {
2189 : const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
2190 :
2191 : // (*) record for later ufo-detection
2192 : _record_argument_request(Tmp);
2193 :
2194 : return _internal_managed_copy(Tmp);
2195 : }
2196 :
2197 : return 0;
2198 : }
2199 :
2200 :
2201 : inline std::string
2202 : GetPot::next_nominus_string()
2203 : {
2204 : if (nominus_cursor < int(idx_nominus.size()) - 1)
2205 : {
2206 : const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
2207 :
2208 : // (*) record for later ufo-detection
2209 : _record_argument_request(Tmp);
2210 :
2211 : return Tmp;
2212 : }
2213 :
2214 : return "";
2215 : }
2216 :
2217 :
2218 :
2219 : inline void
2220 : GetPot::reset_nominus_cursor()
2221 : {
2222 : nominus_cursor = -1;
2223 : }
2224 :
2225 :
2226 :
2227 : ///////////////////////////////////////////////////////////////////////////////
2228 : // (*) variables
2229 : //.............................................................................
2230 : //
2231 : inline bool
2232 2582 : GetPot::have_variable(const char* VarName) const
2233 : {
2234 409383 : const variable* sv = _request_variable(VarName);
2235 :
2236 409383 : if (sv == 0)
2237 2174 : return false;
2238 :
2239 408 : return true;
2240 : }
2241 :
2242 :
2243 :
2244 : inline bool
2245 11768 : GetPot::have_variable(const std::string& VarName) const
2246 : {
2247 11768 : return have_variable(VarName.c_str());
2248 : }
2249 :
2250 : inline bool
2251 : GetPot::have_section(const char* section_name) const
2252 : {
2253 : std::string s = std::string(section_name);
2254 : return this->have_section(s);
2255 : }
2256 :
2257 : inline bool
2258 : GetPot::have_section(const std::string& section_name) const
2259 : {
2260 : const char slash('/');
2261 :
2262 : std::string::const_reverse_iterator it = section_name.rbegin();
2263 :
2264 : bool found_section = false;
2265 :
2266 : // Check if section_name ends with a "/". If not, append it for the search since
2267 : // the section names are stored with a "/" at the end.
2268 : if( (*it) != slash )
2269 : // We need to use a linear search because we can't sort section_list
2270 : // without violating some assumptions. See libMesh #481 for more discussion.
2271 : found_section = ( std::find(section_list.begin(), section_list.end(), section_name+slash) != section_list.end() );
2272 : else
2273 : found_section = ( std::find(section_list.begin(), section_list.end(), section_name) != section_list.end() );
2274 :
2275 : return found_section;
2276 : }
2277 :
2278 : template <typename T>
2279 : inline T
2280 40970 : GetPot::operator()(const char* VarName, const T& Default) const
2281 : {
2282 : // (*) recording of requested variables happens in '_request_variable()'
2283 40970 : const variable* sv = _request_variable(VarName);
2284 :
2285 40970 : if (sv == 0)
2286 32738 : return Default;
2287 :
2288 7214 : return _convert_to_type(sv->original, Default);
2289 : }
2290 :
2291 :
2292 :
2293 : template <typename T>
2294 : inline T
2295 1302 : GetPot::operator()(const std::string& VarName, const T& Default) const
2296 : {
2297 37096 : return operator()(VarName.c_str(), Default);
2298 : }
2299 :
2300 :
2301 :
2302 : inline const char*
2303 146 : GetPot::operator()(const char* VarName, const char* Default) const
2304 : {
2305 288 : return _internal_managed_copy(operator()(VarName, std::string(Default)));
2306 : }
2307 :
2308 :
2309 :
2310 : inline const char*
2311 : GetPot::operator()(const std::string& VarName, const char* Default) const
2312 : {
2313 : return operator()(VarName.c_str(), Default);
2314 : }
2315 :
2316 :
2317 :
2318 : template <typename T>
2319 : inline T
2320 4129 : GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const
2321 : {
2322 : // (*) recording of requested variables happens in '_request_variable()'
2323 4129 : const variable* sv = _request_variable(VarName);
2324 4129 : if (sv == 0)
2325 3 : return Default;
2326 :
2327 116 : const std::string* element = sv->get_element(Idx);
2328 4126 : if (element == 0)
2329 0 : return Default;
2330 2880 : return _convert_to_type(*element, Default);
2331 : }
2332 :
2333 :
2334 :
2335 : template <typename T>
2336 : inline T
2337 80 : GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const
2338 : {
2339 2844 : return operator()(VarName.c_str(), Default, Idx);
2340 : }
2341 :
2342 :
2343 :
2344 : inline const char*
2345 1282 : GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const
2346 : {
2347 2528 : return _internal_managed_copy(operator()(VarName, std::string(Default), Idx));
2348 : }
2349 :
2350 :
2351 :
2352 : inline const char*
2353 : GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const
2354 : {
2355 : return operator()(VarName.c_str(), Default, Idx);
2356 : }
2357 :
2358 :
2359 :
2360 : template <typename T>
2361 : inline T
2362 : GetPot::get_value_no_default(const char* VarName, const T& Default) const
2363 : {
2364 : // (*) recording of requested variables happens in '_request_variable()'
2365 : const variable* sv = _request_variable(VarName);
2366 : if (sv == 0)
2367 : {
2368 : getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
2369 : getpot_error();
2370 : }
2371 : return _convert_to_type_no_default(VarName, sv->original, Default);
2372 : }
2373 :
2374 :
2375 :
2376 : template <typename T>
2377 : inline T
2378 : GetPot::get_value_no_default(const std::string& VarName, const T& Default) const
2379 : {
2380 : return get_value_no_default(VarName.c_str(),Default);
2381 : }
2382 :
2383 :
2384 :
2385 : inline const char*
2386 : GetPot::get_value_no_default(const char* VarName, const char* Default) const
2387 : {
2388 : return _internal_managed_copy(get_value_no_default(VarName, std::string(Default)));
2389 : }
2390 :
2391 :
2392 :
2393 : inline const char*
2394 : GetPot::get_value_no_default(const std::string& VarName, const char* Default) const
2395 : {
2396 : return get_value_no_default(VarName.c_str(),Default);
2397 : }
2398 :
2399 :
2400 :
2401 : template <typename T>
2402 : inline T
2403 : GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const
2404 : {
2405 : // (*) recording of requested variables happens in '_request_variable()'
2406 : const variable* sv = _request_variable(VarName);
2407 : if (sv == 0)
2408 : {
2409 : getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
2410 : getpot_error();
2411 : }
2412 :
2413 : const std::string* element = sv->get_element(Idx);
2414 : if (element == 0)
2415 : {
2416 : getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl;
2417 : getpot_error();
2418 : }
2419 : return _convert_to_type_no_default(VarName, *element, Default);
2420 : }
2421 :
2422 :
2423 :
2424 : template <typename T>
2425 : inline T
2426 : GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const
2427 : {
2428 : return get_value_no_default(VarName.c_str(), Default, Idx);
2429 : }
2430 :
2431 :
2432 :
2433 : inline const char*
2434 : GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const
2435 : {
2436 : return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx));
2437 : }
2438 :
2439 :
2440 :
2441 : inline const char*
2442 : GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const
2443 : {
2444 : return get_value_no_default(VarName.c_str(), Default, Idx);
2445 : }
2446 :
2447 :
2448 :
2449 : inline void
2450 13171526 : GetPot::_record_argument_request(const std::string& Name) const
2451 : {
2452 13171526 : if (!request_recording_f)
2453 0 : return;
2454 :
2455 : // Get a lock before touching anything mutable
2456 669816 : SCOPED_MUTEX;
2457 :
2458 : // (*) record requested variable for later ufo detection
2459 12836738 : _requested_arguments.insert(Name);
2460 :
2461 : // (*) record considered section for ufo detection
2462 13841222 : STRING_VECTOR STree = _get_section_tree(Name);
2463 13171536 : victorate(std::string, STree, it)
2464 10 : if (_requested_sections.find(*it) == _requested_sections.end())
2465 10 : if (section.length() != 0)
2466 0 : _requested_sections.insert(*it);
2467 12501830 : }
2468 :
2469 :
2470 :
2471 : inline void
2472 45488 : GetPot::_record_variable_request(const std::string& Name) const
2473 : {
2474 45488 : if (!request_recording_f)
2475 0 : return;
2476 :
2477 : // Get a lock before touching anything mutable
2478 2608 : SCOPED_MUTEX;
2479 :
2480 : // (*) record requested variable for later ufo detection
2481 44184 : _requested_variables.insert(Name);
2482 :
2483 : // (*) record considered section for ufo detection
2484 48096 : STRING_VECTOR STree = _get_section_tree(Name);
2485 45488 : victorate(std::string, STree, it)
2486 0 : if (_requested_sections.find(*it) == _requested_sections.end())
2487 0 : if (section.length() != 0)
2488 0 : _requested_sections.insert(*it);
2489 42880 : }
2490 :
2491 :
2492 :
2493 : // (*) following functions are to be used from 'outside', after getpot has parsed its
2494 : // arguments => append an argument in the argument vector that reflects the addition
2495 : inline void
2496 4760 : GetPot::_set_variable(const std::string& VarName,
2497 : const std::string& Value, const bool Requested /* = true */)
2498 : {
2499 4760 : const GetPot::variable* Var = Requested ?
2500 0 : _request_variable(VarName.c_str()) :
2501 4760 : _find_variable(VarName.c_str());
2502 4760 : if (Var == 0)
2503 9520 : variables.push_back(variable(VarName.c_str(), Value.c_str(), _field_separator.c_str()));
2504 : else
2505 : {
2506 0 : overridden_vars.insert(VarName.c_str());
2507 0 : (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str());
2508 : }
2509 4760 : }
2510 :
2511 :
2512 :
2513 : template <typename T>
2514 : inline void
2515 : GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */)
2516 : {
2517 : std::ostringstream string_value;
2518 : string_value << Value;
2519 : _set_variable(VarName, string_value.str().c_str(), Requested);
2520 : }
2521 :
2522 :
2523 :
2524 : template <typename T>
2525 : inline void
2526 : GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */)
2527 : {
2528 : set(VarName.c_str(), Value, Requested);
2529 : }
2530 :
2531 :
2532 :
2533 : inline void
2534 : GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */)
2535 : {
2536 : _set_variable(VarName, Value, Requested);
2537 : }
2538 :
2539 :
2540 :
2541 : inline void
2542 : GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */)
2543 : {
2544 : set(VarName.c_str(), Value, Requested);
2545 : }
2546 :
2547 :
2548 :
2549 : inline unsigned
2550 826 : GetPot::vector_variable_size(const char* VarName) const
2551 : {
2552 850 : const variable* sv = _request_variable(VarName);
2553 850 : if (sv == 0)
2554 8 : return 0;
2555 581 : return (unsigned)(sv->value.size());
2556 : }
2557 :
2558 :
2559 :
2560 : inline unsigned
2561 8 : GetPot::vector_variable_size(const std::string& VarName) const
2562 : {
2563 272 : return vector_variable_size(VarName.c_str());
2564 : }
2565 :
2566 :
2567 :
2568 : inline STRING_VECTOR
2569 : GetPot::get_variable_names() const
2570 : {
2571 : STRING_VECTOR result;
2572 : std::vector<GetPot::variable>::const_iterator it = variables.begin();
2573 : for (; it != variables.end(); ++it)
2574 : {
2575 : const std::string Tmp = _get_remaining_string((*it).name, prefix);
2576 : if (Tmp != "")
2577 : result.push_back(Tmp);
2578 : }
2579 : return result;
2580 : }
2581 :
2582 :
2583 :
2584 : inline STRING_VECTOR
2585 : GetPot::get_section_names() const
2586 : {
2587 : return section_list;
2588 : }
2589 :
2590 :
2591 :
2592 : inline STRING_VECTOR
2593 : GetPot::get_subsection_names(const std::string & sec_prefix) const
2594 : {
2595 : // GetPot functions should understand user-provided section names
2596 : // either with or without a trailing slash.
2597 : const std::string full_prefix =
2598 : *sec_prefix.rbegin() == '/' ? sec_prefix : sec_prefix + '/';
2599 :
2600 : const std::size_t full_prefix_len = full_prefix.size();
2601 :
2602 : // Subsections-of-subsections are in the section_list, so we'll be
2603 : // adding subsections multiple times. Using std::set as an
2604 : // intermediate data structure helps us check for duplicates with
2605 : // O(N log N) rather than O(N^2) cost.
2606 : std::set<std::string> subsections;
2607 :
2608 : STRING_VECTOR returnval;
2609 :
2610 : for (STRING_VECTOR::const_iterator it = section_list.begin();
2611 : it != section_list.end(); ++it)
2612 : {
2613 : const std::string & section_name = *it;
2614 :
2615 : // If this section name begins with the prefix
2616 : if (section_name.compare(0, full_prefix_len, full_prefix) == 0)
2617 : {
2618 : const std::size_t next_slash_len =
2619 : section_name.find('/', full_prefix_len);
2620 :
2621 : const std::string subsection_name =
2622 : section_name.substr(full_prefix_len,
2623 : next_slash_len - full_prefix_len);
2624 :
2625 : // If there is a subsection, and if this is the first time
2626 : // we've seen it, add the prefix-less, postfix-less
2627 : // subsection name.
2628 : if (!subsection_name.empty() &&
2629 : !subsections.count(subsection_name))
2630 : {
2631 : returnval.push_back(subsection_name);
2632 : subsections.insert(subsection_name);
2633 : }
2634 : }
2635 : }
2636 :
2637 : return returnval;
2638 : }
2639 :
2640 :
2641 :
2642 : inline std::set<std::string>
2643 : GetPot::get_overridden_variables() const
2644 : {
2645 : return overridden_vars;
2646 : }
2647 :
2648 :
2649 :
2650 : inline const GetPot::variable*
2651 50248 : GetPot::_find_variable(const char* VarName) const
2652 : {
2653 51880 : const std::string Name = prefix + VarName;
2654 :
2655 3264 : std::vector<variable>::const_iterator it = variables.begin();
2656 116042 : for (; it != variables.end(); ++it)
2657 : {
2658 70428 : if ((*it).name == Name)
2659 516 : return &(*it);
2660 : }
2661 1116 : return 0;
2662 : }
2663 :
2664 :
2665 :
2666 : inline const GetPot::variable*
2667 45488 : GetPot::_request_variable(const char* VarName) const
2668 : {
2669 : // (*) record requested variable for later ufo detection
2670 45488 : this->_record_variable_request(VarName);
2671 :
2672 45488 : return this->_find_variable(VarName);
2673 : }
2674 :
2675 :
2676 :
2677 : ///////////////////////////////////////////////////////////////////////////////
2678 : // (*) output (basically for debugging reasons
2679 : //.............................................................................
2680 : //
2681 : inline int
2682 : GetPot::print(std::ostream &out_stream) const
2683 : {
2684 : out_stream << "argc = " << argv.size() << std::endl;
2685 : STRING_VECTOR::const_iterator it = argv.begin();
2686 : for (; it != argv.end(); ++it)
2687 : out_stream << *it << std::endl;
2688 : out_stream << std::endl;
2689 : return 1;
2690 : }
2691 :
2692 :
2693 :
2694 : // PECOS/HPCT Addition - add option to prepend output with a delimiter
2695 : // while also disabling argc print and skipping first print (the name
2696 : // of the input file)
2697 : //
2698 : // PECOS Development Team: (ks. 4/16/09)
2699 : inline int
2700 0 : GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const
2701 : {
2702 0 : STRING_VECTOR::const_iterator it = argv.begin();
2703 0 : it += skip_count;
2704 0 : for (; it != argv.end(); ++it)
2705 : {
2706 0 : out_stream << custom_prefix;
2707 0 : out_stream << *it << std::endl;
2708 : }
2709 0 : out_stream << std::endl;
2710 0 : return 1;
2711 : }
2712 :
2713 :
2714 :
2715 : // (*) dollar bracket expressions (DBEs) ------------------------------------
2716 : //
2717 : // 1) Entry Function: _DBE_expand_string()
2718 : // Takes a string such as
2719 : //
2720 : // "${+ ${x} ${y}} Subject-${& ${section} ${subsection}}: ${title}"
2721 : //
2722 : // calls _DBE_expand() for each of the expressions
2723 : //
2724 : // ${+ ${x} ${y}}
2725 : // ${& ${section} ${subsection}}
2726 : // ${Title}
2727 : //
2728 : // and returns the string
2729 : //
2730 : // "4711 Subject-1.01: Mit den Clowns kamen die Schwaene"
2731 : //
2732 : // assuming that
2733 : // x = "4699"
2734 : // y = "12"
2735 : // section = "1."
2736 : // subsection = "01"
2737 : // title = "Mit den Clowns kamen die Schwaene"
2738 : //
2739 : // 2) _DBE_expand():
2740 : //
2741 : // checks for the command, i.e. the 'sign' that follows '${'
2742 : // divides the argument list into sub-expressions using
2743 : // _DBE_get_expr_list()
2744 : //
2745 : // ${+ ${x} ${y}} -> "${x}" "${y}"
2746 : // ${& ${section} ${subsection}} -> "${section}" "${subsection}"
2747 : // ${Title} -> Nothing, variable expansion
2748 : //
2749 : // 3) _DBE_expression_list():
2750 : //
2751 : // builds a vector of unbracketed whitespace separated strings, i.e.
2752 : //
2753 : // " ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
2754 : //
2755 : // is split into a vector
2756 : //
2757 : // [0] ${Number}.a
2758 : // [1] ${: Das Marmorbild}
2759 : // [2] AB-${& Author= ${Eichendorf}}-1870
2760 : //
2761 : // Each sub-expression is expanded using expand().
2762 : //---------------------------------------------------------------------------
2763 : inline std::string
2764 140920 : GetPot::_DBE_expand_string(const std::string& str)
2765 : {
2766 : // Parses for closing operators '${ }' and expands them letting
2767 : // white spaces and other letters as they are.
2768 140920 : std::string new_string = "";
2769 1192 : unsigned open_brackets = 0;
2770 1192 : unsigned first = 0;
2771 1651900 : for (unsigned i = 0; i<str.size(); i++)
2772 : {
2773 4002752 : if (i + 2 < str.size() && str.substr(i, 2) == "${")
2774 : {
2775 0 : if (open_brackets == 0)
2776 0 : first = i+2;
2777 0 : open_brackets++;
2778 : }
2779 1510980 : else if (str[i] == '}' && open_brackets > 0)
2780 : {
2781 0 : open_brackets -= 1;
2782 0 : if (open_brackets == 0)
2783 : {
2784 0 : const std::string Replacement = _DBE_expand(str.substr(first, i - first));
2785 0 : new_string += Replacement;
2786 : }
2787 : }
2788 1510980 : else if (open_brackets == 0)
2789 1510980 : new_string += str[i];
2790 : }
2791 140920 : return new_string;
2792 : }
2793 :
2794 :
2795 :
2796 : inline STRING_VECTOR
2797 0 : GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber)
2798 : {
2799 : // ensures that the resulting vector has the expected number
2800 : // of arguments, but they may contain an error message
2801 0 : std::string str = str_;
2802 : // Separates expressions by non-bracketed whitespaces, expands them
2803 : // and puts them into a list.
2804 :
2805 0 : unsigned i=0;
2806 : // (1) eat initial whitespaces
2807 0 : for (; i < str.size(); i++)
2808 0 : if (!std::isspace(str[i]))
2809 0 : break;
2810 :
2811 0 : STRING_VECTOR expr_list;
2812 0 : unsigned open_brackets = 0;
2813 0 : std::vector<unsigned> start_idx;
2814 0 : unsigned start_new_string = i;
2815 0 : unsigned l = (unsigned)(str.size());
2816 :
2817 : // (2) search for ${ } expressions ...
2818 0 : while (i < l)
2819 : {
2820 0 : const char letter = str[i];
2821 : // whitespace -> end of expression
2822 0 : if (std::isspace(letter) && open_brackets == 0)
2823 : {
2824 0 : expr_list.push_back(str.substr(start_new_string, i - start_new_string));
2825 0 : bool no_breakout_f = true;
2826 0 : for (i++; i < l ; i++)
2827 : {
2828 0 : if (!std::isspace(str[i]))
2829 : {
2830 0 : no_breakout_f = false;
2831 0 : start_new_string = i;
2832 0 : break;
2833 : }
2834 : }
2835 :
2836 0 : if (no_breakout_f)
2837 : {
2838 : // end of expression list
2839 0 : if (expr_list.size() < ExpectedNumber)
2840 : {
2841 0 : const std::string pre_tmp("<< ${ }: missing arguments>>");
2842 0 : STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
2843 0 : expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
2844 0 : }
2845 0 : return expr_list;
2846 : }
2847 : }
2848 :
2849 : // dollar-bracket expression
2850 0 : if (str.length() >= i+2 && str.substr(i, 2) == "${")
2851 : {
2852 0 : open_brackets++;
2853 0 : start_idx.push_back(i+2);
2854 : }
2855 :
2856 0 : else if (letter == '}' && open_brackets > 0)
2857 : {
2858 0 : int start = start_idx[start_idx.size()-1];
2859 0 : start_idx.pop_back();
2860 0 : const std::string Replacement = _DBE_expand(str.substr(start, i-start));
2861 0 : if (start - 3 < (int)0)
2862 0 : str = Replacement + str.substr(i+1);
2863 : else
2864 0 : str = str.substr(0, start-2) + Replacement + str.substr(i+1);
2865 0 : l = (int)(str.size());
2866 0 : i = start + (int)(Replacement.size()) - 3;
2867 0 : open_brackets--;
2868 : }
2869 0 : i++;
2870 : }
2871 :
2872 : // end of expression list
2873 0 : expr_list.push_back(str.substr(start_new_string, i-start_new_string));
2874 :
2875 0 : if (expr_list.size() < ExpectedNumber)
2876 : {
2877 0 : const std::string pre_tmp("<< ${ }: missing arguments>>");
2878 0 : STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
2879 0 : expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
2880 0 : }
2881 :
2882 0 : return expr_list;
2883 0 : }
2884 :
2885 :
2886 :
2887 : inline const GetPot::variable*
2888 0 : GetPot::_DBE_get_variable(const std::string& VarName)
2889 : {
2890 0 : static GetPot::variable ev;
2891 0 : std::string secure_Prefix = prefix;
2892 :
2893 0 : prefix = section;
2894 : // (1) first search in currently active section
2895 0 : const GetPot::variable* var = _request_variable(VarName.c_str());
2896 0 : if (var != 0)
2897 : {
2898 0 : prefix = secure_Prefix;
2899 0 : return var;
2900 : }
2901 :
2902 : // (2) search in root name space
2903 0 : prefix = "";
2904 0 : var = _request_variable(VarName.c_str());
2905 0 : if (var != 0)
2906 : {
2907 0 : prefix = secure_Prefix;
2908 0 : return var;
2909 : }
2910 :
2911 0 : prefix = secure_Prefix;
2912 :
2913 : // error occurred => variable name == ""
2914 0 : ev.original = "<<${ } variable '";
2915 0 : ev.original += VarName + "' undefined>>";
2916 0 : return &ev;
2917 : }
2918 :
2919 :
2920 :
2921 : inline std::string
2922 0 : GetPot::_DBE_expand(const std::string& expr)
2923 : {
2924 : // ${: } pure text
2925 0 : if (expr[0] == ':')
2926 0 : return expr.substr(1);
2927 :
2928 : // ${& expr expr ... } text concatenation
2929 0 : else if (expr[0] == '&')
2930 : {
2931 0 : const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1);
2932 :
2933 0 : STRING_VECTOR::const_iterator it = A.begin();
2934 0 : std::string result = *it++;
2935 0 : for (; it != A.end(); ++it) result += *it;
2936 :
2937 0 : return result;
2938 0 : }
2939 :
2940 : // ${<-> expr expr expr} text replacement
2941 0 : else if (expr.length() >= 3 && expr.substr(0, 3) == "<->")
2942 : {
2943 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3);
2944 0 : size_t tmp = 0;
2945 0 : const size_t L = A[1].length();
2946 :
2947 0 : while ((tmp = A[0].find(A[1])) != std::string::npos)
2948 0 : A[0].replace(tmp, L, A[2]);
2949 :
2950 0 : return A[0];
2951 0 : }
2952 :
2953 : // ${=func [expr...] } function evaluation
2954 0 : else if (expr.length() >= 2 &&
2955 0 : expr.substr(0, 1) == "=" &&
2956 0 : expr.substr(0, 2) != "==")
2957 : {
2958 0 : size_t funcnamestart = expr.find_first_not_of(" \t", 1);
2959 0 : if (funcnamestart != std::string::npos)
2960 : {
2961 0 : size_t funcnameend = expr.find_first_of(" \t",funcnamestart);
2962 : std::string funcname = expr.substr(funcnamestart,
2963 0 : funcnameend-funcnamestart);
2964 0 : if (funcname == "log")
2965 : {
2966 : STRING_VECTOR A =
2967 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2968 0 : double arg = _convert_to_type(A[0], 0.0);
2969 0 : return _convert_from_type(std::log(arg));
2970 0 : }
2971 0 : else if (funcname == "log10")
2972 : {
2973 : STRING_VECTOR A =
2974 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2975 0 : double arg = _convert_to_type(A[0], 0.0);
2976 0 : return _convert_from_type(std::log10(arg));
2977 0 : }
2978 0 : else if (funcname == "exp")
2979 : {
2980 : STRING_VECTOR A =
2981 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2982 0 : double arg = _convert_to_type(A[0], 0.0);
2983 0 : return _convert_from_type(std::exp(arg));
2984 0 : }
2985 0 : else if (funcname == "sin")
2986 : {
2987 : STRING_VECTOR A =
2988 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2989 0 : double arg = _convert_to_type(A[0], 0.0);
2990 0 : return _convert_from_type(std::sin(arg));
2991 0 : }
2992 0 : else if (funcname == "cos")
2993 : {
2994 : STRING_VECTOR A =
2995 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2996 0 : double arg = _convert_to_type(A[0], 0.0);
2997 0 : return _convert_from_type(std::cos(arg));
2998 0 : }
2999 0 : else if (funcname == "tan")
3000 : {
3001 : STRING_VECTOR A =
3002 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3003 0 : double arg = _convert_to_type(A[0], 0.0);
3004 0 : return _convert_from_type(std::tan(arg));
3005 0 : }
3006 0 : else if (funcname == "asin")
3007 : {
3008 : STRING_VECTOR A =
3009 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3010 0 : double arg = _convert_to_type(A[0], 0.0);
3011 0 : return _convert_from_type(std::asin(arg));
3012 0 : }
3013 0 : else if (funcname == "acos")
3014 : {
3015 : STRING_VECTOR A =
3016 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3017 0 : double arg = _convert_to_type(A[0], 0.0);
3018 0 : return _convert_from_type(std::acos(arg));
3019 0 : }
3020 0 : else if (funcname == "atan")
3021 : {
3022 : STRING_VECTOR A =
3023 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3024 0 : double arg = _convert_to_type(A[0], 0.0);
3025 0 : return _convert_from_type(std::atan(arg));
3026 0 : }
3027 0 : else if (funcname == "atan2")
3028 : {
3029 : STRING_VECTOR A =
3030 0 : _DBE_get_expr_list(expr.substr(funcnameend), 2);
3031 0 : double arg1 = _convert_to_type(A[0], 0.0);
3032 0 : double arg2 = _convert_to_type(A[1], 0.0);
3033 0 : return _convert_from_type(std::atan2(arg1, arg2));
3034 0 : }
3035 0 : else if (funcname == "sinh")
3036 : {
3037 : STRING_VECTOR A =
3038 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3039 0 : double arg = _convert_to_type(A[0], 0.0);
3040 0 : return _convert_from_type(std::sinh(arg));
3041 0 : }
3042 0 : else if (funcname == "cosh")
3043 : {
3044 : STRING_VECTOR A =
3045 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3046 0 : double arg = _convert_to_type(A[0], 0.0);
3047 0 : return _convert_from_type(std::cosh(arg));
3048 0 : }
3049 0 : else if (funcname == "tanh")
3050 : {
3051 : STRING_VECTOR A =
3052 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3053 0 : double arg = _convert_to_type(A[0], 0.0);
3054 0 : return _convert_from_type(std::tanh(arg));
3055 0 : }
3056 : #ifdef HAVE_INVERSE_HYPERBOLIC_SINE
3057 0 : else if (funcname == "asinh")
3058 : {
3059 : STRING_VECTOR A =
3060 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3061 0 : double arg = _convert_to_type(A[0], 0.0);
3062 0 : return _convert_from_type(std::asinh(arg));
3063 0 : }
3064 : #endif
3065 : #ifdef HAVE_INVERSE_HYPERBOLIC_COSINE
3066 0 : else if (funcname == "acosh")
3067 : {
3068 : STRING_VECTOR A =
3069 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3070 0 : double arg = _convert_to_type(A[0], 0.0);
3071 0 : return _convert_from_type(std::acosh(arg));
3072 0 : }
3073 : #endif
3074 : #ifdef HAVE_INVERSE_HYPERBOLIC_TANGENT
3075 0 : else if (funcname == "atanh")
3076 : {
3077 : STRING_VECTOR A =
3078 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3079 0 : double arg = _convert_to_type(A[0], 0.0);
3080 0 : return _convert_from_type(std::atanh(arg));
3081 0 : }
3082 : #endif
3083 0 : else if (funcname == "sqrt")
3084 : {
3085 : STRING_VECTOR A =
3086 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3087 0 : double arg = _convert_to_type(A[0], 0.0);
3088 0 : return _convert_from_type(std::sqrt(arg));
3089 0 : }
3090 0 : else if (funcname == "abs")
3091 : {
3092 : STRING_VECTOR A =
3093 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3094 0 : double arg = _convert_to_type(A[0], 0.0);
3095 0 : return _convert_from_type(std::abs(arg));
3096 0 : }
3097 0 : else if (funcname == "max")
3098 : {
3099 : STRING_VECTOR A =
3100 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3101 0 : STRING_VECTOR::const_iterator it = A.begin();
3102 0 : double result = _convert_to_type(*it++, 0.0);
3103 0 : for (; it != A.end(); ++it)
3104 0 : result = std::max(result, _convert_to_type(*it, 0.0));
3105 0 : return _convert_from_type(result);
3106 0 : }
3107 0 : else if (funcname == "min")
3108 : {
3109 : STRING_VECTOR A =
3110 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3111 0 : STRING_VECTOR::const_iterator it = A.begin();
3112 0 : double result = _convert_to_type(*it++, 0.0);
3113 0 : for (; it != A.end(); ++it)
3114 0 : result = std::min(result, _convert_to_type(*it, 0.0));
3115 0 : return _convert_from_type(result);
3116 0 : }
3117 0 : else if (funcname == "ceil")
3118 : {
3119 : STRING_VECTOR A =
3120 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3121 0 : double arg = _convert_to_type(A[0], 0.0);
3122 0 : return _convert_from_type(std::ceil(arg));
3123 0 : }
3124 0 : else if (funcname == "floor")
3125 : {
3126 : STRING_VECTOR A =
3127 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3128 0 : double arg = _convert_to_type(A[0], 0.0);
3129 0 : return _convert_from_type(std::floor(arg));
3130 0 : }
3131 0 : else if (funcname == "fmod")
3132 : {
3133 : STRING_VECTOR A =
3134 0 : _DBE_get_expr_list(expr.substr(funcnameend), 2);
3135 0 : double arg1 = _convert_to_type(A[0], 0.0);
3136 0 : double arg2 = _convert_to_type(A[1], 0.0);
3137 0 : return _convert_from_type(std::fmod(arg1, arg2));
3138 0 : }
3139 0 : else if (funcname == "srand")
3140 : {
3141 : STRING_VECTOR A =
3142 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3143 0 : unsigned int arg = _convert_to_type(A[0], 0u);
3144 0 : std::srand(arg);
3145 0 : return A[0];
3146 0 : }
3147 : // ${=rand range} with default range==RAND_MAX
3148 0 : else if (funcname == "rand")
3149 : {
3150 0 : if (funcnameend >= expr.length() ||
3151 0 : expr.find_first_not_of(" \t", funcnameend) == std::string::npos)
3152 0 : return _convert_from_type(std::rand());
3153 :
3154 : STRING_VECTOR A =
3155 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3156 0 : unsigned int range = _convert_to_type(A[0],0u);
3157 0 : if (!range)
3158 0 : return _convert_from_type(0);
3159 0 : const unsigned int x = (RAND_MAX + 1u) / range;
3160 0 : const unsigned int y = x * range;
3161 : unsigned int returnval;
3162 0 : do
3163 : {
3164 0 : returnval = rand();
3165 0 : } while (returnval >= y);
3166 0 : return _convert_from_type(returnval / x);
3167 0 : }
3168 0 : else if (funcname == "time")
3169 0 : return _convert_from_type(std::time(NULL));
3170 : else
3171 : {
3172 0 : getpot_cerr << "ERROR: unrecognized function "
3173 0 : << funcname << std::endl;
3174 0 : getpot_error();
3175 : }
3176 : }
3177 : }
3178 :
3179 : // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
3180 0 : else if (expr[0] == '+')
3181 : {
3182 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3183 0 : STRING_VECTOR::const_iterator it = A.begin();
3184 0 : double result = _convert_to_type(*it++, 0.0);
3185 0 : for (; it != A.end(); ++it)
3186 0 : result += _convert_to_type(*it, 0.0);
3187 :
3188 0 : return _convert_from_type(result);
3189 0 : }
3190 0 : else if (expr[0] == '-')
3191 : {
3192 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3193 0 : STRING_VECTOR::const_iterator it = A.begin();
3194 0 : double result = _convert_to_type(*it++, 0.0);
3195 0 : for (; it != A.end(); ++it)
3196 0 : result -= _convert_to_type(*it, 0.0);
3197 :
3198 0 : return _convert_from_type(result);
3199 0 : }
3200 0 : else if (expr[0] == '*')
3201 : {
3202 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3203 0 : STRING_VECTOR::const_iterator it = A.begin();
3204 0 : double result = _convert_to_type(*it++, 0.0);
3205 0 : for (; it != A.end(); ++it)
3206 0 : result *= _convert_to_type(*it, 0.0);
3207 :
3208 0 : return _convert_from_type(result);
3209 0 : }
3210 0 : else if (expr[0] == '/')
3211 : {
3212 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3213 0 : STRING_VECTOR::const_iterator it = A.begin();
3214 0 : double result = _convert_to_type(*it++, 0.0);
3215 0 : if (result == 0)
3216 0 : return "0.0";
3217 :
3218 0 : for (; it != A.end(); ++it)
3219 : {
3220 0 : const double Q = _convert_to_type(*it, 0.0);
3221 0 : result /= Q;
3222 : }
3223 0 : return _convert_from_type(result);
3224 0 : }
3225 :
3226 : // ${^ ... } power expressions
3227 0 : else if (expr[0] == '^')
3228 : {
3229 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3230 0 : STRING_VECTOR::const_iterator it = A.begin();
3231 0 : double result = _convert_to_type(*it++, 0.0);
3232 0 : for (; it != A.end(); ++it)
3233 0 : result = pow(result, _convert_to_type(*it, 0.0));
3234 0 : return _convert_from_type(result);
3235 0 : }
3236 :
3237 : // ${== } ${<= } ${>= } comparisons (return the number of the first 'match'
3238 0 : else if (expr.length() >= 2 &&
3239 0 : (expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
3240 0 : expr.substr(0,2) == "<=" || expr[0] == '>' || expr[0] == '<'))
3241 : {
3242 : // differentiate between two and one sign operators
3243 0 : unsigned op = 0;
3244 : enum { EQ, GEQ, LEQ, GT, LT };
3245 :
3246 0 : if (expr.substr(0, 2) == "==")
3247 0 : op = EQ;
3248 :
3249 0 : else if (expr.substr(0, 2) == ">=")
3250 0 : op = GEQ;
3251 :
3252 0 : else if (expr.substr(0, 2) == "<=")
3253 0 : op = LEQ;
3254 :
3255 0 : else if (expr[0] == '>')
3256 0 : op = GT;
3257 :
3258 : else
3259 0 : op = LT;
3260 :
3261 0 : STRING_VECTOR a;
3262 0 : if (op == GT || op == LT)
3263 0 : a = _DBE_get_expr_list(expr.substr(1), 2);
3264 :
3265 : else
3266 0 : a = _DBE_get_expr_list(expr.substr(2), 2);
3267 :
3268 0 : std::string x_orig = a[0];
3269 0 : double x = _convert_to_type(x_orig, 1e37);
3270 0 : unsigned i = 1;
3271 :
3272 0 : STRING_VECTOR::const_iterator y_orig = a.begin();
3273 0 : for (y_orig++; y_orig != a.end(); ++y_orig)
3274 : {
3275 0 : double y = _convert_to_type(*y_orig, 1e37);
3276 :
3277 : // set the strings as reference if one wasn't a number
3278 0 : if (x == 1e37 || y == 1e37)
3279 : {
3280 : // it's a string comparison
3281 0 : if ((op == EQ && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
3282 0 : (op == LEQ && x_orig <= *y_orig) || (op == GT && x_orig > *y_orig) ||
3283 0 : (op == LT && x_orig < *y_orig))
3284 0 : return _convert_from_type(i);
3285 : }
3286 : else
3287 : {
3288 : // it's a number comparison
3289 0 : if ((op == EQ && x == y) || (op == GEQ && x >= y) ||
3290 0 : (op == LEQ && x <= y) || (op == GT && x > y) ||
3291 0 : (op == LT && x < y))
3292 0 : return _convert_from_type(i);
3293 : }
3294 0 : i++;
3295 : }
3296 :
3297 : // nothing fulfills the condition => return 0
3298 0 : return "0";
3299 0 : }
3300 :
3301 : // ${?? expr expr} select
3302 0 : else if (expr.length() >= 2 && expr.substr(0, 2) == "??")
3303 : {
3304 0 : STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2);
3305 0 : double x = _convert_to_type(a[0], 1e37);
3306 :
3307 : // last element is always the default argument
3308 0 : if (x == 1e37 || x < 0 || x >= double(a.size() - 1))
3309 0 : return a[a.size()-1];
3310 :
3311 : // round x to closest integer
3312 0 : return a[int(x+0.5)];
3313 0 : }
3314 :
3315 : // ${? expr expr expr} if then else conditions
3316 0 : else if (expr[0] == '?')
3317 : {
3318 0 : STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2);
3319 :
3320 0 : if (_convert_to_type(a[0], 0.0) == 1.0)
3321 0 : return a[1];
3322 :
3323 0 : else if (a.size() > 2)
3324 0 : return a[2];
3325 0 : }
3326 : // ${! expr} maxro expansion
3327 0 : else if (expr[0] == '!')
3328 : {
3329 0 : const GetPot::variable* Var = _DBE_get_variable(expr.substr(1));
3330 : // error
3331 0 : if (Var->name == "")
3332 0 : return std::string(Var->original);
3333 :
3334 0 : const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2);
3335 0 : return A[0];
3336 0 : }
3337 : // ${@: } - string subscription
3338 0 : else if (expr.length() >= 2 && expr.substr(0,2) == "@:")
3339 : {
3340 0 : const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2);
3341 0 : double x = _convert_to_type(A[1], 1e37);
3342 :
3343 : // last element is always the default argument
3344 0 : if (x == 1e37 || x < 0 || x >= double(A[0].size() - 1))
3345 0 : return "<<1st index out of range>>";
3346 :
3347 0 : if (A.size() > 2)
3348 : {
3349 0 : double y = _convert_to_type(A[2], 1e37);
3350 0 : if (y != 1e37 && y > 0 && y <= double(A[0].size() - 1) && y > x)
3351 0 : return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
3352 :
3353 0 : else if (y == -1)
3354 0 : return A[0].substr(int(x+0.5));
3355 :
3356 0 : return "<<2nd index out of range>>";
3357 : }
3358 : else
3359 : {
3360 0 : char* tmp = new char[2];
3361 0 : tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
3362 0 : std::string result(tmp);
3363 0 : delete [] tmp;
3364 0 : return result;
3365 : }
3366 0 : }
3367 : // ${@ } - vector subscription
3368 0 : else if (expr[0] == '@')
3369 : {
3370 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3371 0 : const GetPot::variable* Var = _DBE_get_variable(A[0]);
3372 : // error
3373 0 : if (Var->name == "")
3374 : {
3375 : // make a copy of the string if an error occurred
3376 : // (since the error variable is a static variable inside get_variable())
3377 0 : return std::string(Var->original);
3378 : }
3379 :
3380 0 : double x = _convert_to_type(A[1], 1e37);
3381 :
3382 : // last element is always the default argument
3383 0 : if (x == 1e37 || x < 0 || x >= double(Var->value.size()))
3384 0 : return "<<1st index out of range>>";
3385 :
3386 0 : if (A.size() > 2)
3387 : {
3388 0 : double y = _convert_to_type(A[2], 1e37);
3389 0 : int begin = int(x+0.5);
3390 0 : int end = 0;
3391 0 : if (y != 1e37 && y > 0 && y <= double(Var->value.size()) && y > x)
3392 0 : end = int(y+1.5);
3393 0 : else if (y == -1)
3394 0 : end = int(Var->value.size());
3395 : else
3396 0 : return "<<2nd index out of range>>";
3397 :
3398 0 : std::string result = *(Var->get_element(begin));
3399 0 : for (int i = begin+1; i < end; i++)
3400 0 : result += std::string(" ") + *(Var->get_element(i));
3401 0 : return result;
3402 : }
3403 : else
3404 0 : return *(Var->get_element(int(x+0.5)));
3405 0 : }
3406 :
3407 0 : const STRING_VECTOR A = _DBE_get_expr_list(expr, 1);
3408 0 : const GetPot::variable* B = _DBE_get_variable(A[0]);
3409 :
3410 : // make a copy of the string if an error occurred
3411 : // (since the error variable is a static variable inside get_variable())
3412 0 : if (B->name == "")
3413 0 : return std::string(B->original);
3414 :
3415 : // ([email protected] mentioned to me the warning MSVC++6.0 produces
3416 : // with: else return B->original (thanks))
3417 0 : return B->original;
3418 0 : }
3419 :
3420 :
3421 :
3422 : ///////////////////////////////////////////////////////////////////////////////
3423 : // (*) unidentified flying objects
3424 : //.............................................................................
3425 : //
3426 : inline bool
3427 : GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
3428 : {
3429 : victorate(std::string, VecStr, itk)
3430 : {
3431 : if (*itk == Str)
3432 : return true;
3433 : }
3434 : return false;
3435 : }
3436 :
3437 :
3438 :
3439 : inline STRING_VECTOR
3440 : GetPot::unidentified_arguments(unsigned Number,
3441 : const char* KnownArgument1, ...) const
3442 : {
3443 : std::set<std::string> known_arguments;
3444 :
3445 : // (1) create a vector of known arguments
3446 : if (Number == 0)
3447 : return STRING_VECTOR();
3448 :
3449 : va_list ap;
3450 : va_start(ap, KnownArgument1);
3451 : known_arguments.insert(std::string(KnownArgument1));
3452 : for (unsigned i=1; i<Number; i++)
3453 : known_arguments.insert(std::string(va_arg(ap, char *)));
3454 : va_end(ap);
3455 :
3456 : return unidentified_arguments(known_arguments);
3457 : }
3458 :
3459 :
3460 :
3461 : inline STRING_VECTOR
3462 : GetPot::unidentified_arguments() const
3463 : {
3464 : return unidentified_arguments(_requested_arguments);
3465 : }
3466 :
3467 :
3468 :
3469 : inline STRING_VECTOR
3470 : GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const
3471 : {
3472 : // We use set for efficiency, but want to support vector inputs for
3473 : // backwards compatibility.
3474 : return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end()));
3475 : }
3476 :
3477 :
3478 :
3479 : inline STRING_VECTOR
3480 : GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const
3481 : {
3482 : STRING_VECTOR ufos;
3483 : STRING_VECTOR::const_iterator it = argv.begin();
3484 : ++it; // forget about argv[0] (application or filename)
3485 : for (; it != argv.end(); ++it)
3486 : {
3487 : // -- argument belongs to prefixed section ?
3488 : const std::string arg = _get_remaining_string(*it, prefix);
3489 : if (arg == "")
3490 : continue;
3491 :
3492 : // -- check if in list
3493 : if (Knowns.find(arg) == Knowns.end())
3494 : ufos.push_back(*it);
3495 : }
3496 : return ufos;
3497 : }
3498 :
3499 :
3500 :
3501 : inline STRING_VECTOR
3502 : GetPot::unidentified_options(unsigned Number,
3503 : const char* KnownOption1, ...) const
3504 : {
3505 : std::set<std::string> known_options;
3506 :
3507 : // (1) create a vector of known arguments
3508 : if (Number == 0)
3509 : return STRING_VECTOR();
3510 :
3511 : va_list ap;
3512 : va_start(ap, KnownOption1);
3513 : known_options.insert(std::string(KnownOption1));
3514 : for (unsigned i=1; i<Number; i++)
3515 : known_options.insert(std::string(va_arg(ap, char *)));
3516 : va_end(ap);
3517 :
3518 : return unidentified_options(known_options);
3519 : }
3520 :
3521 :
3522 :
3523 : inline STRING_VECTOR
3524 : GetPot::unidentified_options() const
3525 : {
3526 : // -- every option is an argument.
3527 : // -- the set of requested arguments contains the set of requested options.
3528 : // -- IF the set of requested arguments contains unrequested options,
3529 : // THEN they were requested as 'follow' and 'next' arguments and not as real options.
3530 : //
3531 : // => it is not necessary to separate requested options from the list
3532 : return unidentified_arguments(_requested_arguments);
3533 : }
3534 :
3535 :
3536 :
3537 : inline STRING_VECTOR
3538 : GetPot::unidentified_options(const std::vector<std::string>& Knowns) const
3539 : {
3540 : // We use set for efficiency, but want to support vector inputs for
3541 : // backwards compatibility.
3542 : return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end()));
3543 : }
3544 :
3545 :
3546 :
3547 : inline STRING_VECTOR
3548 : GetPot::unidentified_options(const std::set<std::string>& Knowns) const
3549 : {
3550 : STRING_VECTOR ufos;
3551 : STRING_VECTOR::const_iterator it = argv.begin();
3552 : ++it; // forget about argv[0] (application or filename)
3553 : for (; it != argv.end(); ++it)
3554 : {
3555 : // -- argument belongs to prefixed section ?
3556 : const std::string arg = _get_remaining_string(*it, prefix);
3557 : if (arg == "")
3558 : continue;
3559 :
3560 : // is argument really an option (starting with '-') ?
3561 : if (arg.length() < 1 || arg[0] != '-')
3562 : continue;
3563 :
3564 : if (Knowns.find(arg) == Knowns.end())
3565 : ufos.push_back(*it);
3566 : }
3567 :
3568 : return ufos;
3569 : }
3570 :
3571 :
3572 :
3573 : // Two modes:
3574 : // ArgumentNumber >= 0 check specific argument
3575 : // ArgumentNumber == -1 check all options starting with one '-'
3576 : // for flags
3577 : inline std::string
3578 : GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
3579 : {
3580 : std::string ufos;
3581 : // STRING_VECTOR known_arguments;
3582 : std::string KFL(KnownFlagList);
3583 :
3584 : // (2) iteration over '-' arguments (options)
3585 : if (ArgumentNumber == -1)
3586 : {
3587 : STRING_VECTOR::const_iterator it = argv.begin();
3588 : ++it; // forget about argv[0] (application or filename)
3589 : for (; it != argv.end(); ++it)
3590 : {
3591 : // -- argument belongs to prefixed section ?
3592 : const std::string arg = _get_remaining_string(*it, prefix);
3593 : if (arg == "") continue;
3594 :
3595 : // -- does arguments start with '-' (but not '--')
3596 : if (arg.length() < 2)
3597 : continue;
3598 :
3599 : else if (arg[0] != '-')
3600 : continue;
3601 :
3602 : else if (arg[1] == '-')
3603 : continue;
3604 :
3605 : // -- check out if flags inside option are contained in KnownFlagList
3606 : const char* p=arg.c_str();
3607 : p++; // skip starting minus
3608 : for (; *p != '\0' ; p++)
3609 : if (KFL.find(*p) == std::string::npos) ufos += *p;
3610 : }
3611 : }
3612 : // (1) check specific argument
3613 : else
3614 : {
3615 : // -- only check arguments that start with prefix
3616 : int no_matches = 0;
3617 : for (unsigned i=1; i<argv.size(); i++)
3618 : {
3619 : const std::string Remain = _get_remaining_string(argv[i], prefix);
3620 : if (Remain != "")
3621 : {
3622 : no_matches++;
3623 : if (no_matches == ArgumentNumber)
3624 : {
3625 : // -- the right argument number inside the section is found
3626 : // => check it for flags
3627 : const char* p = Remain.c_str();
3628 : p++; // skip starting minus
3629 : for (; *p != '\0' ; p++)
3630 : if (KFL.find(*p) == std::string::npos) ufos += *p;
3631 : return ufos;
3632 : }
3633 : }
3634 : }
3635 : }
3636 : return ufos;
3637 : }
3638 :
3639 :
3640 :
3641 : inline STRING_VECTOR
3642 : GetPot::unidentified_variables(unsigned Number,
3643 : const char* KnownVariable1, ...) const
3644 : {
3645 : std::set<std::string> known_variables;
3646 :
3647 : // create vector of known arguments
3648 : if (Number == 0)
3649 : return STRING_VECTOR();
3650 :
3651 : va_list ap;
3652 : va_start(ap, KnownVariable1);
3653 : known_variables.insert(std::string(KnownVariable1));
3654 : for (unsigned i=1; i<Number; i++)
3655 : known_variables.insert(std::string(va_arg(ap, char *)));
3656 : va_end(ap);
3657 :
3658 : return unidentified_variables(known_variables);
3659 : }
3660 :
3661 :
3662 :
3663 : inline STRING_VECTOR
3664 : GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const
3665 : {
3666 : // We use set for efficiency, but want to support vector inputs for
3667 : // backwards compatibility.
3668 : return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end()));
3669 : }
3670 :
3671 :
3672 :
3673 : inline STRING_VECTOR
3674 : GetPot::unidentified_variables(const std::set<std::string>& Knowns) const
3675 : {
3676 : STRING_VECTOR ufos;
3677 :
3678 : victorate(GetPot::variable, variables, it)
3679 : {
3680 : // -- check if variable has specific prefix
3681 : const std::string var_name = _get_remaining_string((*it).name, prefix);
3682 : if (var_name == "")
3683 : continue;
3684 :
3685 : // -- check if variable is known
3686 : if (Knowns.find(var_name) == Knowns.end())
3687 : ufos.push_back((*it).name);
3688 : }
3689 : return ufos;
3690 : }
3691 :
3692 :
3693 :
3694 : inline STRING_VECTOR
3695 : GetPot::unidentified_variables() const
3696 : {
3697 : return unidentified_variables(_requested_variables);
3698 : }
3699 :
3700 :
3701 :
3702 : inline STRING_VECTOR
3703 : GetPot::unidentified_sections(unsigned Number,
3704 : const char* KnownSection1, ...) const
3705 : {
3706 : std::set<std::string> known_sections;
3707 :
3708 : // (1) create a vector of known arguments
3709 : if (Number == 0)
3710 : return STRING_VECTOR();
3711 :
3712 : va_list ap;
3713 : va_start(ap, KnownSection1);
3714 : known_sections.insert(std::string(KnownSection1));
3715 : for (unsigned i=1; i<Number; i++)
3716 : {
3717 : std::string tmp = std::string(va_arg(ap, char *));
3718 :
3719 : if (tmp.length() == 0)
3720 : continue;
3721 :
3722 : if (tmp[tmp.length()-1] != '/')
3723 : tmp += '/';
3724 :
3725 : known_sections.insert(tmp);
3726 : }
3727 : va_end(ap);
3728 :
3729 : return unidentified_sections(known_sections);
3730 : }
3731 :
3732 :
3733 :
3734 : inline STRING_VECTOR
3735 : GetPot::unidentified_sections() const
3736 : {
3737 : return unidentified_sections(_requested_sections);
3738 : }
3739 :
3740 :
3741 :
3742 : inline STRING_VECTOR
3743 : GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const
3744 : {
3745 : // We use set for efficiency, but want to support vector inputs for
3746 : // backwards compatibility.
3747 : return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end()));
3748 : }
3749 :
3750 :
3751 :
3752 : inline STRING_VECTOR
3753 : GetPot::unidentified_sections(const std::set<std::string>& Knowns) const
3754 : {
3755 : STRING_VECTOR ufos;
3756 :
3757 : victorate(std::string, section_list, it)
3758 : {
3759 : // -- check if section conform to prefix
3760 : const std::string sec_name = _get_remaining_string(*it, prefix);
3761 : if (sec_name == "")
3762 : continue;
3763 :
3764 : // -- check if section is known
3765 : if (Knowns.find(sec_name) == Knowns.end())
3766 : ufos.push_back(*it);
3767 : }
3768 :
3769 : return ufos;
3770 : }
3771 :
3772 :
3773 :
3774 : inline STRING_VECTOR
3775 : GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
3776 : {
3777 : std::set<std::string> known_nominuses;
3778 :
3779 : // create vector of known arguments
3780 : if (Number == 0)
3781 : return STRING_VECTOR();
3782 :
3783 : va_list ap;
3784 : va_start(ap, Known);
3785 : known_nominuses.insert(std::string(Known));
3786 : for (unsigned i=1; i<Number; i++)
3787 : {
3788 : std::string tmp = std::string(va_arg(ap, char *));
3789 : if (tmp.length() == 0)
3790 : continue;
3791 : known_nominuses.insert(tmp);
3792 : }
3793 : va_end(ap);
3794 :
3795 : return unidentified_nominuses(known_nominuses);
3796 : }
3797 :
3798 :
3799 :
3800 : inline STRING_VECTOR
3801 : GetPot::unidentified_nominuses() const
3802 : {
3803 : // -- every nominus is an argument.
3804 : // -- the set of requested arguments contains the set of requested nominuss.
3805 : // -- IF the set of requested arguments contains unrequested nominuss,
3806 : // THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
3807 : //
3808 : // => it is not necessary to separate requested nominus from the list
3809 :
3810 : return unidentified_nominuses(_requested_arguments);
3811 : }
3812 :
3813 :
3814 :
3815 : inline STRING_VECTOR
3816 : GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const
3817 : {
3818 : // We use set for efficiency, but want to support vector inputs for
3819 : // backwards compatibility.
3820 : return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end()));
3821 : }
3822 :
3823 :
3824 :
3825 : inline STRING_VECTOR
3826 : GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const
3827 : {
3828 : STRING_VECTOR ufos;
3829 :
3830 : // (2) iterate over all arguments
3831 : STRING_VECTOR::const_iterator it = argv.begin();
3832 : ++it; // forget about argv[0] (application or filename)
3833 : for (; it != argv.end(); ++it)
3834 : {
3835 : // -- check if nominus part of prefix
3836 : const std::string arg = _get_remaining_string(*it, prefix);
3837 : if (arg == "")
3838 : continue;
3839 :
3840 : if (arg.length() < 1)
3841 : continue;
3842 :
3843 : // option ? --> not a nomius
3844 : if (arg[0] == '-')
3845 : continue;
3846 :
3847 : // section ? --> not a real nominus
3848 : if (arg[0] == '[' && arg[arg.length()-1] == ']')
3849 : continue;
3850 :
3851 : // variable definition ? --> not a real nominus
3852 : bool continue_f = false;
3853 : for (unsigned i=0; i<arg.length() ; i++)
3854 : if (arg[i] == '=')
3855 : {
3856 : continue_f = true;
3857 : break;
3858 : }
3859 :
3860 : if (continue_f)
3861 : continue;
3862 :
3863 : // real nominuses are compared with the given list
3864 : if (Knowns.find(arg) == Knowns.end())
3865 : ufos.push_back(*it);
3866 : }
3867 : return ufos;
3868 : }
3869 :
3870 :
3871 : ///////////////////////////////////////////////////////////////////////////////
3872 : // (*) Accessors for requested types
3873 : //.............................................................................
3874 :
3875 : inline
3876 : std::set<std::string>
3877 71 : GetPot::get_requested_arguments() const
3878 : {
3879 71 : return _requested_arguments;
3880 : }
3881 :
3882 :
3883 :
3884 : inline
3885 : std::set<std::string>
3886 71 : GetPot::get_requested_variables() const
3887 : {
3888 71 : return _requested_variables;
3889 : }
3890 :
3891 :
3892 :
3893 : inline
3894 : std::set<std::string>
3895 71 : GetPot::get_requested_sections() const
3896 : {
3897 71 : return _requested_sections;
3898 : }
3899 :
3900 :
3901 :
3902 : ///////////////////////////////////////////////////////////////////////////////
3903 : // (*) variable class
3904 : //.............................................................................
3905 : //
3906 : inline
3907 0 : GetPot::variable::variable()
3908 : : name(),
3909 : value(),
3910 0 : original()
3911 0 : {}
3912 :
3913 :
3914 :
3915 : inline
3916 9180 : GetPot::variable::variable(const variable& Other)
3917 : {
3918 : #ifdef WIN32
3919 : operator=(Other);
3920 : #else
3921 8740 : GetPot::variable::operator=(Other);
3922 : #endif
3923 8740 : }
3924 :
3925 :
3926 :
3927 : inline
3928 4760 : GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
3929 4760 : : name(Name)
3930 : {
3931 : // make a copy of the 'Value'
3932 4760 : take(Value, FieldSeparator);
3933 4760 : }
3934 :
3935 :
3936 :
3937 : inline const std::string*
3938 8 : GetPot::variable::get_element(unsigned Idx) const
3939 : {
3940 4134 : if (Idx >= value.size())
3941 0 : return 0;
3942 : else
3943 8 : return &(value[Idx]);
3944 : }
3945 :
3946 :
3947 :
3948 : inline void
3949 4760 : GetPot::variable::take(const char* Value, const char* FieldSeparator)
3950 : {
3951 5088 : original = std::string(Value); // string member var
3952 4432 : value.clear(); // vector<string> member var
3953 :
3954 : /*
3955 : // separate string by white space delimiters using 'strtok'
3956 : // thread safe usage of strtok (no static members)
3957 : char* spt = 0;
3958 : // make a copy of the 'Value'
3959 : char* copy = new char[strlen(Value)+1];
3960 : strcpy(copy, Value);
3961 : char* follow_token = strtok_r(copy, FieldSeparator, &spt);
3962 : while (follow_token != 0)
3963 : {
3964 : value.push_back(std::string(follow_token));
3965 : follow_token = strtok_r(NULL, FieldSeparator, &spt);
3966 : }
3967 :
3968 : delete [] copy;
3969 : */
3970 :
3971 : // Don't use strtok, instead tokenize the input char "Value" using std::string operations so
3972 : // that the results end up in the local "value" member
3973 :
3974 : // Construct std::string objects from the input char*s. I think the only
3975 : // FieldSeparator recognized by GetPot is whitespace?
3976 5088 : std::string Value_str = std::string(Value);
3977 5088 : std::string delimiters = std::string(FieldSeparator);
3978 :
3979 : // Skip delimiters at beginning.
3980 656 : std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0);
3981 :
3982 : // Find first "non-delimiter".
3983 328 : std::string::size_type pos = Value_str.find_first_of(delimiters, lastPos);
3984 :
3985 : // Loop over the input string until all the tokens have been pushed back
3986 : // into the local "value" member.
3987 9520 : while (std::string::npos != pos || std::string::npos != lastPos)
3988 : {
3989 : // Found a token, add it to the vector.
3990 8864 : value.push_back(Value_str.substr(lastPos, pos - lastPos));
3991 :
3992 : // Skip delimiters. Note the "not_of"
3993 656 : lastPos = Value_str.find_first_not_of(delimiters, pos);
3994 :
3995 : // Find next "non-delimiter"
3996 328 : pos = Value_str.find_first_of(delimiters, lastPos);
3997 : }
3998 :
3999 : // We're done, all the tokens should now be in the vector<string>
4000 4760 : }
4001 :
4002 : inline
4003 15836 : GetPot::variable::~variable()
4004 15808 : {}
4005 :
4006 :
4007 :
4008 : inline GetPot::variable&
4009 8740 : GetPot::variable::operator=(const GetPot::variable& Other)
4010 : {
4011 8740 : if (&Other != this)
4012 : {
4013 8740 : name = Other.name;
4014 8740 : value = Other.value;
4015 8740 : original = Other.original;
4016 : }
4017 8740 : return *this;
4018 : }
4019 :
4020 : #ifdef GETPOT_NAMESPACE
4021 : }
4022 : #endif
4023 :
4024 : #undef victorate
4025 :
4026 : #endif // LIBMESH_GETPOT_H
|