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 3020 : 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 11240433 : static STRING_VECTOR _get_section_tree(const std::string& FullPath)
723 : {
724 34720 : STRING_VECTOR result;
725 285516383 : for (std::size_t pos = 0; pos != FullPath.size(); ++pos)
726 : {
727 274275950 : if (FullPath[pos] == '/')
728 16 : result.push_back(FullPath.substr(0,pos));
729 : }
730 :
731 11240433 : return result;
732 0 : }
733 : };
734 :
735 :
736 : ///////////////////////////////////////////////////////////////////////////////
737 : // (*) constructors, destructor, assignment operator
738 : //.............................................................................
739 : //
740 : inline void
741 8936 : GetPot::_basic_initialization()
742 : {
743 8936 : cursor = 0;
744 8936 : nominus_cursor = -1;
745 8936 : search_failed_f = true;
746 8936 : search_loop_f = true;
747 8936 : prefix = "";
748 8936 : section = "";
749 :
750 : // automatic request recording for later ufo detection
751 8936 : request_recording_f = true;
752 :
753 : // comment start and end strings
754 8936 : _comment_start = std::string("#");
755 8936 : _comment_end = std::string("\n");
756 :
757 : // default: separate vector elements by whitespaces
758 8936 : _field_separator = " \t\n";
759 8936 : }
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 30692 : GetPot::GetPot(const int argc_, const char * const * argv_,
794 30692 : const char* FieldSeparator /* =0x0 */) :
795 : // leave 'char**' non-const to honor less capable compilers ...
796 28908 : prefix(),
797 28908 : section(),
798 28908 : section_list(),
799 28908 : argv(),
800 28908 : cursor(),
801 28908 : search_loop_f(),
802 28908 : search_failed_f(),
803 28908 : nominus_cursor(),
804 : idx_nominus(),
805 28908 : variables(),
806 28908 : _comment_start(),
807 28908 : _comment_end(),
808 28908 : _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 34388 : request_recording_f()
817 : {
818 30692 : this->parse_command_line(argc_, argv_, FieldSeparator);
819 30692 : }
820 :
821 :
822 :
823 : // leave 'char**' non-const to honor less capable compilers ...
824 : inline void
825 23712 : GetPot::parse_command_line(const int argc_, const char * const * argv_,
826 : const char* FieldSeparator /* =0x0 */)
827 : {
828 23712 : _basic_initialization();
829 :
830 : // if specified -> overwrite default string
831 23712 : if (FieldSeparator)
832 0 : _field_separator = std::string(FieldSeparator);
833 :
834 : // -- make an internal copy of the argument list:
835 1452 : 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 24636 : _apriori_argv.push_back(std::string(argv_[0]));
843 361562 : for (int i=1; i<argc_; i++)
844 : {
845 338990 : std::string tmp(argv_[i]); // recall the problem with temporaries,
846 337850 : _apriori_argv.push_back(tmp); // reference counting in argument lists ...
847 : }
848 23712 : _parse_argument_vector(_apriori_argv);
849 23712 : }
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 25284 : 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 8924 : GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV)
1126 : {
1127 8924 : 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 744 : STRING_VECTOR section_stack;
1135 248 : STRING_VECTOR::const_iterator it = ARGV.begin();
1136 :
1137 :
1138 8924 : 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 8924 : if (argv.empty())
1145 8924 : argv.push_back(*it);
1146 248 : ++it;
1147 :
1148 : // -- loop over remaining arguments
1149 145224 : for (; it != ARGV.end(); ++it)
1150 : {
1151 135240 : std::string arg = *it;
1152 :
1153 136300 : if (arg.length() == 0)
1154 0 : continue;
1155 :
1156 : // -- [section] labels and [include file] directives
1157 136300 : 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 137360 : arg = section + _DBE_expand_string(arg);
1194 136300 : argv.push_back(arg);
1195 : }
1196 :
1197 : // -- separate array for nominus arguments
1198 136300 : if (arg[0] != '-')
1199 67386 : idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1));
1200 :
1201 : // -- variables: does arg contain a '=' operator ?
1202 1060 : const std::size_t equals_pos = arg.find_first_of('=');
1203 136300 : 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 8428 : }
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 13090 : GetPot::_convert_to_type(const std::string& String, const T& Default) const
1564 : {
1565 13090 : std::istringstream in_string(String);
1566 : T retval;
1567 8008 : in_string >> retval;
1568 13090 : if (in_string.fail())
1569 0 : retval = Default;
1570 13560 : return retval;
1571 12620 : }
1572 :
1573 :
1574 :
1575 : // copy string - operator>> would have stopped upon seeing whitespace!
1576 : template <>
1577 : inline std::string
1578 274 : GetPot::_convert_to_type(const std::string& String, const std::string&) const
1579 : {
1580 2554 : 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 462 : const std::size_t bufsize = strlen(arg)+1;
1716 430 : auto newcopy = std::make_unique<char[]>(bufsize);
1717 462 : strncpy(newcopy.get(), arg, bufsize);
1718 868 : auto pr = _internal_string_container.insert(std::move(newcopy));
1719 12 : return pr.first->get();
1720 : }
1721 :
1722 :
1723 :
1724 : //////////////////////////////////////////////////////////////////////////////
1725 : // (*) cursor oriented functions
1726 : //.............................................................................
1727 :
1728 : // Checks if 'String' begins with 'Start' and returns the remaining String.
1729 : // Returns None if String does not begin with Start.
1730 : inline const std::string
1731 8786 : GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const
1732 : {
1733 8786 : if (Start == "")
1734 8430 : return String;
1735 :
1736 : // note: java.lang.String: substring(a,b) = from a to b-1
1737 : // C++ string: substr(a,b) = from a to a + b
1738 0 : if (String.find(Start) == 0)
1739 0 : return String.substr(Start.length());
1740 :
1741 : else
1742 0 : return "";
1743 : }
1744 :
1745 :
1746 :
1747 : // -- search for a certain argument and set cursor to position
1748 : inline bool
1749 339292 : GetPot::search(const std::string &Option)
1750 : {
1751 12891919 : return search(Option.c_str());
1752 : }
1753 :
1754 :
1755 :
1756 : // -- search for a certain argument and set cursor to position
1757 : inline bool
1758 12043414 : GetPot::search(const char* Option)
1759 : {
1760 12043414 : unsigned OldCursor = cursor;
1761 12358452 : const std::string SearchTerm = prefix + Option;
1762 :
1763 : // (*) record requested arguments for later ufo detection
1764 12043414 : _record_argument_request(SearchTerm);
1765 :
1766 12358428 : if (OldCursor >= argv.size())
1767 0 : OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
1768 12043414 : search_failed_f = true;
1769 :
1770 : // (*) first loop from cursor position until end
1771 196364221 : for (unsigned c = cursor; c < argv.size(); c++)
1772 : {
1773 183272569 : if (argv[c] == SearchTerm)
1774 : {
1775 6888 : cursor = c;
1776 6888 : search_failed_f = false;
1777 6888 : return true;
1778 : }
1779 : }
1780 12036526 : if (!search_loop_f)
1781 0 : return false;
1782 :
1783 : // (*) second loop from 0 to old cursor position
1784 39045941 : for (unsigned c = 1; c <= OldCursor; c++)
1785 : {
1786 27014064 : if (argv[c] == SearchTerm)
1787 : {
1788 4649 : cursor = c;
1789 4649 : search_failed_f = false;
1790 4649 : return true;
1791 : }
1792 : }
1793 :
1794 : // in case nothing is found the cursor stays where it was
1795 314600 : return false;
1796 : }
1797 :
1798 :
1799 :
1800 : inline bool
1801 0 : GetPot::search(unsigned No, const char* P, ...)
1802 : {
1803 : // (*) recording the requested arguments happens in subroutine 'search'
1804 0 : if (No == 0)
1805 0 : return false;
1806 :
1807 : // search for the first argument
1808 0 : if (search(P) == true)
1809 0 : return true;
1810 :
1811 : // start interpreting variable argument list
1812 : va_list ap;
1813 0 : va_start(ap, P);
1814 0 : unsigned i = 1;
1815 0 : for (; i < No; i++)
1816 : {
1817 0 : char* Opt = va_arg(ap, char *);
1818 : // (*) search records itself for later ufo detection
1819 0 : if (search(Opt) == true)
1820 0 : break;
1821 : }
1822 :
1823 0 : if (i < No)
1824 : {
1825 0 : i++;
1826 : // loop was left before end of array --> hit but
1827 : // make sure that the rest of the search terms is marked
1828 : // as requested.
1829 0 : for (; i < No; i++)
1830 : {
1831 0 : char* Opt = va_arg(ap, char *);
1832 : // (*) record requested arguments for later ufo detection
1833 0 : _record_argument_request(Opt);
1834 : }
1835 0 : va_end(ap);
1836 0 : return true;
1837 : }
1838 :
1839 0 : va_end(ap);
1840 : // loop was left normally --> no hit
1841 0 : return false;
1842 : }
1843 :
1844 :
1845 :
1846 : inline void
1847 0 : GetPot::reset_cursor()
1848 : {
1849 0 : search_failed_f = false;
1850 0 : cursor = 0;
1851 0 : }
1852 :
1853 :
1854 :
1855 : inline void
1856 : GetPot::init_multiple_occurrence()
1857 : {
1858 : disable_loop();
1859 : reset_cursor();
1860 : }
1861 :
1862 :
1863 :
1864 : ///////////////////////////////////////////////////////////////////////////////
1865 : // (*) direct access to command line arguments
1866 : //.............................................................................
1867 : //
1868 : inline const char*
1869 : GetPot::operator[](unsigned idx) const
1870 : {
1871 : return idx<argv.size() ? argv[idx].c_str() : 0;
1872 : }
1873 :
1874 :
1875 :
1876 : template <typename T>
1877 : inline T
1878 : GetPot::get(unsigned int Idx, const T& Default) const
1879 : {
1880 : if (Idx >= argv.size())
1881 : return Default;
1882 : return _convert_to_type(argv[Idx], Default);
1883 : }
1884 :
1885 :
1886 :
1887 : inline const char*
1888 : GetPot::get(unsigned int Idx, const char* Default) const
1889 : {
1890 : if (Idx >= argv.size())
1891 : return Default;
1892 : return argv[Idx].c_str();
1893 : }
1894 :
1895 :
1896 :
1897 : inline unsigned
1898 : GetPot::size() const
1899 : {
1900 : return getpot_cast_int<unsigned>(argv.size());
1901 : }
1902 :
1903 :
1904 :
1905 : // -- next() function group
1906 : template <typename T>
1907 : inline T
1908 8790 : GetPot::next(const T& Default)
1909 : {
1910 8790 : if (search_failed_f)
1911 0 : return Default;
1912 8790 : cursor++;
1913 9146 : if (cursor >= argv.size())
1914 : {
1915 0 : cursor = getpot_cast_int<unsigned>(argv.size());
1916 0 : return Default;
1917 : }
1918 :
1919 : // (*) record requested argument for later ufo detection
1920 8790 : _record_argument_request(argv[cursor]);
1921 :
1922 9180 : const std::string Remain = _get_remaining_string(argv[cursor], prefix);
1923 :
1924 8824 : return Remain != "" ? _convert_to_type(Remain, Default) : Default;
1925 : }
1926 :
1927 :
1928 :
1929 : inline const char*
1930 0 : GetPot::next(const char* Default)
1931 : {
1932 0 : return _internal_managed_copy(next(std::string(Default)));
1933 : }
1934 :
1935 :
1936 :
1937 : // -- follow() function group
1938 : // distinct option to be searched for
1939 : template <typename T>
1940 : inline T
1941 0 : GetPot::follow(const T& Default, const char* Option)
1942 : {
1943 : // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1944 0 : if (search(Option) == false)
1945 0 : return Default;
1946 :
1947 0 : return next(Default);
1948 : }
1949 :
1950 :
1951 :
1952 : inline const char*
1953 : GetPot::follow(const char* Default, const char* Option)
1954 : {
1955 : return _internal_managed_copy(follow(std::string(Default), Option));
1956 : }
1957 :
1958 :
1959 :
1960 : // -- second follow() function group
1961 : // multiple option to be searched for
1962 : template <typename T>
1963 : inline T
1964 : GetPot::follow(const T& Default, unsigned int No, const char* P, ...)
1965 : {
1966 : // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1967 : if (No == 0)
1968 : return Default;
1969 :
1970 : if (search(P) == true)
1971 : return next(Default);
1972 :
1973 : va_list ap;
1974 : va_start(ap, P);
1975 : for (unsigned i=1; i<No; i++)
1976 : {
1977 : char* Opt = va_arg(ap, char *);
1978 : if (search(Opt) == true)
1979 : {
1980 : va_end(ap);
1981 : return next(Default);
1982 : }
1983 : }
1984 : va_end(ap);
1985 : return Default;
1986 : }
1987 :
1988 :
1989 :
1990 : inline const char*
1991 : GetPot::follow(const char* Default, unsigned No, const char* P, ...)
1992 : {
1993 : // (*) record requested of argument is entirely handled in 'search()' and 'next()'
1994 : if (No == 0)
1995 : return Default;
1996 :
1997 : if (search(P) == true)
1998 : return next(Default);
1999 :
2000 : va_list ap;
2001 : va_start(ap, P);
2002 : for (unsigned i=1; i<No; i++)
2003 : {
2004 : char* Opt = va_arg(ap, char *);
2005 : if (search(Opt) == true)
2006 : {
2007 : va_end(ap);
2008 : return next(Default);
2009 : }
2010 : }
2011 : va_end(ap);
2012 : return Default;
2013 : }
2014 :
2015 :
2016 :
2017 : ///////////////////////////////////////////////////////////////////////////////
2018 : // (*) directly connected options
2019 : //.............................................................................
2020 : //
2021 : template <typename T>
2022 : inline T
2023 : GetPot::direct_follow(const T& Default, const char* Option)
2024 : {
2025 : const char* FollowStr = _match_starting_string(Option);
2026 :
2027 : // (*) record requested of argument for later ufo-detection
2028 : _record_argument_request(std::string(Option) + FollowStr);
2029 :
2030 : if (FollowStr == 0)
2031 : return Default;
2032 :
2033 : if (++cursor >= argv.size())
2034 : cursor = getpot_cast_int<unsigned>(argv.size());
2035 : return _convert_to_type(FollowStr, Default);
2036 : }
2037 :
2038 :
2039 :
2040 : inline const char*
2041 : GetPot::direct_follow(const char* Default, const char* Option)
2042 : {
2043 : return _internal_managed_copy(direct_follow(std::string(Default), Option));
2044 : }
2045 :
2046 :
2047 :
2048 : // pointer to the place where the string after
2049 : // the match inside the found argument starts.
2050 : // 0 no argument matches the starting string.
2051 : inline const char*
2052 : GetPot::_match_starting_string(const char* StartString)
2053 : {
2054 : const unsigned N =
2055 : getpot_cast_int<unsigned>(strlen(StartString));
2056 : unsigned OldCursor = cursor;
2057 :
2058 : if (OldCursor >= argv.size())
2059 : OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
2060 : search_failed_f = true;
2061 :
2062 : // (*) first loop from cursor position until end
2063 : for (unsigned c = cursor; c < argv.size(); c++)
2064 : {
2065 : if (strncmp(StartString, argv[c].c_str(), N) == 0)
2066 : {
2067 : cursor = c;
2068 : search_failed_f = false;
2069 : return &(argv[c].c_str()[N]);
2070 : }
2071 : }
2072 :
2073 : if (!search_loop_f)
2074 : return NULL;
2075 :
2076 : // (*) second loop from 0 to old cursor position
2077 : for (unsigned c = 1; c < OldCursor; c++)
2078 : {
2079 : if (strncmp(StartString, argv[c].c_str(), N) == 0)
2080 : {
2081 : cursor = c;
2082 : search_failed_f = false;
2083 : return &(argv[c].c_str()[N]);
2084 : }
2085 : }
2086 : return 0;
2087 : }
2088 :
2089 :
2090 :
2091 : ///////////////////////////////////////////////////////////////////////////////
2092 : // (*) search for flags
2093 : //.............................................................................
2094 : //
2095 : inline bool
2096 : GetPot::options_contain(const char* FlagList) const
2097 : {
2098 : // go through all arguments that start with a '-' (but not '--')
2099 : std::string str;
2100 : STRING_VECTOR::const_iterator it = argv.begin();
2101 : for (; it != argv.end(); ++it)
2102 : {
2103 : str = _get_remaining_string(*it, prefix);
2104 :
2105 : if (str.length() >= 2 && str[0] == '-' && str[1] != '-')
2106 : if (_check_flags(str, FlagList))
2107 : return true;
2108 : }
2109 : return false;
2110 : }
2111 :
2112 :
2113 :
2114 : inline bool
2115 : GetPot::argument_contains(unsigned Idx, const char* FlagList) const
2116 : {
2117 : if (Idx >= argv.size())
2118 : return false;
2119 :
2120 : // (*) record requested of argument for later ufo-detection
2121 : // an argument that is checked for flags is considered to be 'requested'
2122 : _record_argument_request(argv[Idx]);
2123 :
2124 : if (prefix == "")
2125 : // search argument for any flag in flag list
2126 : return _check_flags(argv[Idx], FlagList);
2127 :
2128 : // if a prefix is set, then the argument index is the index
2129 : // inside the 'namespace'
2130 : // => only check list of arguments that start with prefix
2131 : unsigned no_matches = 0;
2132 : for (unsigned i=0; i<argv.size(); i++)
2133 : {
2134 : const std::string Remain = _get_remaining_string(argv[i], prefix);
2135 : if (Remain != "")
2136 : {
2137 : no_matches += 1;
2138 : if (no_matches == Idx)
2139 : return _check_flags(Remain, FlagList);
2140 : }
2141 : }
2142 :
2143 : // no argument in this namespace
2144 : return false;
2145 : }
2146 :
2147 :
2148 :
2149 : inline bool
2150 : GetPot::_check_flags(const std::string& Str, const char* FlagList) const
2151 : {
2152 : for (const char* p=FlagList; *p != '\0' ; p++)
2153 : if (Str.find(*p) != std::string::npos)
2154 : return true; // found something
2155 : return false;
2156 : }
2157 :
2158 :
2159 :
2160 : ///////////////////////////////////////////////////////////////////////////////
2161 : // (*) nominus arguments
2162 :
2163 : // return vector of nominus arguments
2164 : inline STRING_VECTOR
2165 : GetPot::nominus_vector() const
2166 : {
2167 : STRING_VECTOR nv;
2168 : std::vector<unsigned>::const_iterator it = idx_nominus.begin();
2169 : for (; it != idx_nominus.end(); ++it)
2170 : {
2171 : nv.push_back(argv[*it]);
2172 :
2173 : // (*) record for later ufo-detection
2174 : // when a nominus vector is requested, the entire set of nominus arguments are
2175 : // tagged as 'requested'
2176 : _record_argument_request(argv[*it]);
2177 : }
2178 : return nv;
2179 : }
2180 :
2181 :
2182 :
2183 : inline const char*
2184 : GetPot::next_nominus()
2185 : {
2186 : if (nominus_cursor < int(idx_nominus.size()) - 1)
2187 : {
2188 : const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
2189 :
2190 : // (*) record for later ufo-detection
2191 : _record_argument_request(Tmp);
2192 :
2193 : return _internal_managed_copy(Tmp);
2194 : }
2195 :
2196 : return 0;
2197 : }
2198 :
2199 :
2200 : inline std::string
2201 : GetPot::next_nominus_string()
2202 : {
2203 : if (nominus_cursor < int(idx_nominus.size()) - 1)
2204 : {
2205 : const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
2206 :
2207 : // (*) record for later ufo-detection
2208 : _record_argument_request(Tmp);
2209 :
2210 : return Tmp;
2211 : }
2212 :
2213 : return "";
2214 : }
2215 :
2216 :
2217 :
2218 : inline void
2219 : GetPot::reset_nominus_cursor()
2220 : {
2221 : nominus_cursor = -1;
2222 : }
2223 :
2224 :
2225 :
2226 : ///////////////////////////////////////////////////////////////////////////////
2227 : // (*) variables
2228 : //.............................................................................
2229 : //
2230 : inline bool
2231 2112 : GetPot::have_variable(const char* VarName) const
2232 : {
2233 363267 : const variable* sv = _request_variable(VarName);
2234 :
2235 363267 : if (sv == 0)
2236 1702 : return false;
2237 :
2238 410 : return true;
2239 : }
2240 :
2241 :
2242 :
2243 : inline bool
2244 10470 : GetPot::have_variable(const std::string& VarName) const
2245 : {
2246 10470 : return have_variable(VarName.c_str());
2247 : }
2248 :
2249 : inline bool
2250 : GetPot::have_section(const char* section_name) const
2251 : {
2252 : std::string s = std::string(section_name);
2253 : return this->have_section(s);
2254 : }
2255 :
2256 : inline bool
2257 : GetPot::have_section(const std::string& section_name) const
2258 : {
2259 : const char slash('/');
2260 :
2261 : std::string::const_reverse_iterator it = section_name.rbegin();
2262 :
2263 : bool found_section = false;
2264 :
2265 : // Check if section_name ends with a "/". If not, append it for the search since
2266 : // the section names are stored with a "/" at the end.
2267 : if( (*it) != slash )
2268 : // We need to use a linear search because we can't sort section_list
2269 : // without violating some assumptions. See libMesh #481 for more discussion.
2270 : found_section = ( std::find(section_list.begin(), section_list.end(), section_name+slash) != section_list.end() );
2271 : else
2272 : found_section = ( std::find(section_list.begin(), section_list.end(), section_name) != section_list.end() );
2273 :
2274 : return found_section;
2275 : }
2276 :
2277 : template <typename T>
2278 : inline T
2279 40410 : GetPot::operator()(const char* VarName, const T& Default) const
2280 : {
2281 : // (*) recording of requested variables happens in '_request_variable()'
2282 40410 : const variable* sv = _request_variable(VarName);
2283 :
2284 40410 : if (sv == 0)
2285 32312 : return Default;
2286 :
2287 7088 : return _convert_to_type(sv->original, Default);
2288 : }
2289 :
2290 :
2291 :
2292 : template <typename T>
2293 : inline T
2294 1294 : GetPot::operator()(const std::string& VarName, const T& Default) const
2295 : {
2296 36536 : return operator()(VarName.c_str(), Default);
2297 : }
2298 :
2299 :
2300 :
2301 : inline const char*
2302 146 : GetPot::operator()(const char* VarName, const char* Default) const
2303 : {
2304 288 : return _internal_managed_copy(operator()(VarName, std::string(Default)));
2305 : }
2306 :
2307 :
2308 :
2309 : inline const char*
2310 : GetPot::operator()(const std::string& VarName, const char* Default) const
2311 : {
2312 : return operator()(VarName.c_str(), Default);
2313 : }
2314 :
2315 :
2316 :
2317 : template <typename T>
2318 : inline T
2319 4129 : GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const
2320 : {
2321 : // (*) recording of requested variables happens in '_request_variable()'
2322 4129 : const variable* sv = _request_variable(VarName);
2323 4129 : if (sv == 0)
2324 3 : return Default;
2325 :
2326 116 : const std::string* element = sv->get_element(Idx);
2327 4126 : if (element == 0)
2328 0 : return Default;
2329 2880 : return _convert_to_type(*element, Default);
2330 : }
2331 :
2332 :
2333 :
2334 : template <typename T>
2335 : inline T
2336 80 : GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const
2337 : {
2338 2844 : return operator()(VarName.c_str(), Default, Idx);
2339 : }
2340 :
2341 :
2342 :
2343 : inline const char*
2344 1282 : GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const
2345 : {
2346 2528 : return _internal_managed_copy(operator()(VarName, std::string(Default), Idx));
2347 : }
2348 :
2349 :
2350 :
2351 : inline const char*
2352 : GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const
2353 : {
2354 : return operator()(VarName.c_str(), Default, Idx);
2355 : }
2356 :
2357 :
2358 :
2359 : template <typename T>
2360 : inline T
2361 : GetPot::get_value_no_default(const char* VarName, const T& Default) const
2362 : {
2363 : // (*) recording of requested variables happens in '_request_variable()'
2364 : const variable* sv = _request_variable(VarName);
2365 : if (sv == 0)
2366 : {
2367 : getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
2368 : getpot_error();
2369 : }
2370 : return _convert_to_type_no_default(VarName, sv->original, Default);
2371 : }
2372 :
2373 :
2374 :
2375 : template <typename T>
2376 : inline T
2377 : GetPot::get_value_no_default(const std::string& VarName, const T& Default) const
2378 : {
2379 : return get_value_no_default(VarName.c_str(),Default);
2380 : }
2381 :
2382 :
2383 :
2384 : inline const char*
2385 : GetPot::get_value_no_default(const char* VarName, const char* Default) const
2386 : {
2387 : return _internal_managed_copy(get_value_no_default(VarName, std::string(Default)));
2388 : }
2389 :
2390 :
2391 :
2392 : inline const char*
2393 : GetPot::get_value_no_default(const std::string& VarName, const char* Default) const
2394 : {
2395 : return get_value_no_default(VarName.c_str(),Default);
2396 : }
2397 :
2398 :
2399 :
2400 : template <typename T>
2401 : inline T
2402 : GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const
2403 : {
2404 : // (*) recording of requested variables happens in '_request_variable()'
2405 : const variable* sv = _request_variable(VarName);
2406 : if (sv == 0)
2407 : {
2408 : getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
2409 : getpot_error();
2410 : }
2411 :
2412 : const std::string* element = sv->get_element(Idx);
2413 : if (element == 0)
2414 : {
2415 : getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl;
2416 : getpot_error();
2417 : }
2418 : return _convert_to_type_no_default(VarName, *element, Default);
2419 : }
2420 :
2421 :
2422 :
2423 : template <typename T>
2424 : inline T
2425 : GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const
2426 : {
2427 : return get_value_no_default(VarName.c_str(), Default, Idx);
2428 : }
2429 :
2430 :
2431 :
2432 : inline const char*
2433 : GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const
2434 : {
2435 : return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx));
2436 : }
2437 :
2438 :
2439 :
2440 : inline const char*
2441 : GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const
2442 : {
2443 : return get_value_no_default(VarName.c_str(), Default, Idx);
2444 : }
2445 :
2446 :
2447 :
2448 : inline void
2449 12052204 : GetPot::_record_argument_request(const std::string& Name) const
2450 : {
2451 12052204 : if (!request_recording_f)
2452 0 : return;
2453 :
2454 : // Get a lock before touching anything mutable
2455 630788 : SCOPED_MUTEX;
2456 :
2457 : // (*) record requested variable for later ufo detection
2458 11736834 : _requested_arguments.insert(Name);
2459 :
2460 : // (*) record considered section for ufo detection
2461 12682968 : STRING_VECTOR STree = _get_section_tree(Name);
2462 12052214 : victorate(std::string, STree, it)
2463 10 : if (_requested_sections.find(*it) == _requested_sections.end())
2464 10 : if (section.length() != 0)
2465 0 : _requested_sections.insert(*it);
2466 11421440 : }
2467 :
2468 :
2469 :
2470 : inline void
2471 39906 : GetPot::_record_variable_request(const std::string& Name) const
2472 : {
2473 39906 : if (!request_recording_f)
2474 0 : return;
2475 :
2476 : // Get a lock before touching anything mutable
2477 2296 : SCOPED_MUTEX;
2478 :
2479 : // (*) record requested variable for later ufo detection
2480 38758 : _requested_variables.insert(Name);
2481 :
2482 : // (*) record considered section for ufo detection
2483 42202 : STRING_VECTOR STree = _get_section_tree(Name);
2484 39906 : victorate(std::string, STree, it)
2485 0 : if (_requested_sections.find(*it) == _requested_sections.end())
2486 0 : if (section.length() != 0)
2487 0 : _requested_sections.insert(*it);
2488 37610 : }
2489 :
2490 :
2491 :
2492 : // (*) following functions are to be used from 'outside', after getpot has parsed its
2493 : // arguments => append an argument in the argument vector that reflects the addition
2494 : inline void
2495 4760 : GetPot::_set_variable(const std::string& VarName,
2496 : const std::string& Value, const bool Requested /* = true */)
2497 : {
2498 4760 : const GetPot::variable* Var = Requested ?
2499 0 : _request_variable(VarName.c_str()) :
2500 4760 : _find_variable(VarName.c_str());
2501 4760 : if (Var == 0)
2502 9520 : variables.push_back(variable(VarName.c_str(), Value.c_str(), _field_separator.c_str()));
2503 : else
2504 : {
2505 0 : overridden_vars.insert(VarName.c_str());
2506 0 : (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str());
2507 : }
2508 4760 : }
2509 :
2510 :
2511 :
2512 : template <typename T>
2513 : inline void
2514 : GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */)
2515 : {
2516 : std::ostringstream string_value;
2517 : string_value << Value;
2518 : _set_variable(VarName, string_value.str().c_str(), Requested);
2519 : }
2520 :
2521 :
2522 :
2523 : template <typename T>
2524 : inline void
2525 : GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */)
2526 : {
2527 : set(VarName.c_str(), Value, Requested);
2528 : }
2529 :
2530 :
2531 :
2532 : inline void
2533 : GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */)
2534 : {
2535 : _set_variable(VarName, Value, Requested);
2536 : }
2537 :
2538 :
2539 :
2540 : inline void
2541 : GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */)
2542 : {
2543 : set(VarName.c_str(), Value, Requested);
2544 : }
2545 :
2546 :
2547 :
2548 : inline unsigned
2549 826 : GetPot::vector_variable_size(const char* VarName) const
2550 : {
2551 850 : const variable* sv = _request_variable(VarName);
2552 850 : if (sv == 0)
2553 8 : return 0;
2554 581 : return (unsigned)(sv->value.size());
2555 : }
2556 :
2557 :
2558 :
2559 : inline unsigned
2560 8 : GetPot::vector_variable_size(const std::string& VarName) const
2561 : {
2562 272 : return vector_variable_size(VarName.c_str());
2563 : }
2564 :
2565 :
2566 :
2567 : inline STRING_VECTOR
2568 : GetPot::get_variable_names() const
2569 : {
2570 : STRING_VECTOR result;
2571 : std::vector<GetPot::variable>::const_iterator it = variables.begin();
2572 : for (; it != variables.end(); ++it)
2573 : {
2574 : const std::string Tmp = _get_remaining_string((*it).name, prefix);
2575 : if (Tmp != "")
2576 : result.push_back(Tmp);
2577 : }
2578 : return result;
2579 : }
2580 :
2581 :
2582 :
2583 : inline STRING_VECTOR
2584 : GetPot::get_section_names() const
2585 : {
2586 : return section_list;
2587 : }
2588 :
2589 :
2590 :
2591 : inline STRING_VECTOR
2592 : GetPot::get_subsection_names(const std::string & sec_prefix) const
2593 : {
2594 : // GetPot functions should understand user-provided section names
2595 : // either with or without a trailing slash.
2596 : const std::string full_prefix =
2597 : *sec_prefix.rbegin() == '/' ? sec_prefix : sec_prefix + '/';
2598 :
2599 : const std::size_t full_prefix_len = full_prefix.size();
2600 :
2601 : // Subsections-of-subsections are in the section_list, so we'll be
2602 : // adding subsections multiple times. Using std::set as an
2603 : // intermediate data structure helps us check for duplicates with
2604 : // O(N log N) rather than O(N^2) cost.
2605 : std::set<std::string> subsections;
2606 :
2607 : STRING_VECTOR returnval;
2608 :
2609 : for (STRING_VECTOR::const_iterator it = section_list.begin();
2610 : it != section_list.end(); ++it)
2611 : {
2612 : const std::string & section_name = *it;
2613 :
2614 : // If this section name begins with the prefix
2615 : if (section_name.compare(0, full_prefix_len, full_prefix) == 0)
2616 : {
2617 : const std::size_t next_slash_len =
2618 : section_name.find('/', full_prefix_len);
2619 :
2620 : const std::string subsection_name =
2621 : section_name.substr(full_prefix_len,
2622 : next_slash_len - full_prefix_len);
2623 :
2624 : // If there is a subsection, and if this is the first time
2625 : // we've seen it, add the prefix-less, postfix-less
2626 : // subsection name.
2627 : if (!subsection_name.empty() &&
2628 : !subsections.count(subsection_name))
2629 : {
2630 : returnval.push_back(subsection_name);
2631 : subsections.insert(subsection_name);
2632 : }
2633 : }
2634 : }
2635 :
2636 : return returnval;
2637 : }
2638 :
2639 :
2640 :
2641 : inline std::set<std::string>
2642 : GetPot::get_overridden_variables() const
2643 : {
2644 : return overridden_vars;
2645 : }
2646 :
2647 :
2648 :
2649 : inline const GetPot::variable*
2650 44666 : GetPot::_find_variable(const char* VarName) const
2651 : {
2652 46142 : const std::string Name = prefix + VarName;
2653 :
2654 2952 : std::vector<variable>::const_iterator it = variables.begin();
2655 108080 : for (; it != variables.end(); ++it)
2656 : {
2657 68212 : if ((*it).name == Name)
2658 516 : return &(*it);
2659 : }
2660 960 : return 0;
2661 : }
2662 :
2663 :
2664 :
2665 : inline const GetPot::variable*
2666 39906 : GetPot::_request_variable(const char* VarName) const
2667 : {
2668 : // (*) record requested variable for later ufo detection
2669 39906 : this->_record_variable_request(VarName);
2670 :
2671 39906 : return this->_find_variable(VarName);
2672 : }
2673 :
2674 :
2675 :
2676 : ///////////////////////////////////////////////////////////////////////////////
2677 : // (*) output (basically for debugging reasons
2678 : //.............................................................................
2679 : //
2680 : inline int
2681 : GetPot::print(std::ostream &out_stream) const
2682 : {
2683 : out_stream << "argc = " << argv.size() << std::endl;
2684 : STRING_VECTOR::const_iterator it = argv.begin();
2685 : for (; it != argv.end(); ++it)
2686 : out_stream << *it << std::endl;
2687 : out_stream << std::endl;
2688 : return 1;
2689 : }
2690 :
2691 :
2692 :
2693 : // PECOS/HPCT Addition - add option to prepend output with a delimiter
2694 : // while also disabling argc print and skipping first print (the name
2695 : // of the input file)
2696 : //
2697 : // PECOS Development Team: (ks. 4/16/09)
2698 : inline int
2699 0 : GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const
2700 : {
2701 0 : STRING_VECTOR::const_iterator it = argv.begin();
2702 0 : it += skip_count;
2703 0 : for (; it != argv.end(); ++it)
2704 : {
2705 0 : out_stream << custom_prefix;
2706 0 : out_stream << *it << std::endl;
2707 : }
2708 0 : out_stream << std::endl;
2709 0 : return 1;
2710 : }
2711 :
2712 :
2713 :
2714 : // (*) dollar bracket expressions (DBEs) ------------------------------------
2715 : //
2716 : // 1) Entry Function: _DBE_expand_string()
2717 : // Takes a string such as
2718 : //
2719 : // "${+ ${x} ${y}} Subject-${& ${section} ${subsection}}: ${title}"
2720 : //
2721 : // calls _DBE_expand() for each of the expressions
2722 : //
2723 : // ${+ ${x} ${y}}
2724 : // ${& ${section} ${subsection}}
2725 : // ${Title}
2726 : //
2727 : // and returns the string
2728 : //
2729 : // "4711 Subject-1.01: Mit den Clowns kamen die Schwaene"
2730 : //
2731 : // assuming that
2732 : // x = "4699"
2733 : // y = "12"
2734 : // section = "1."
2735 : // subsection = "01"
2736 : // title = "Mit den Clowns kamen die Schwaene"
2737 : //
2738 : // 2) _DBE_expand():
2739 : //
2740 : // checks for the command, i.e. the 'sign' that follows '${'
2741 : // divides the argument list into sub-expressions using
2742 : // _DBE_get_expr_list()
2743 : //
2744 : // ${+ ${x} ${y}} -> "${x}" "${y}"
2745 : // ${& ${section} ${subsection}} -> "${section}" "${subsection}"
2746 : // ${Title} -> Nothing, variable expansion
2747 : //
2748 : // 3) _DBE_expression_list():
2749 : //
2750 : // builds a vector of unbracketed whitespace separated strings, i.e.
2751 : //
2752 : // " ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
2753 : //
2754 : // is split into a vector
2755 : //
2756 : // [0] ${Number}.a
2757 : // [1] ${: Das Marmorbild}
2758 : // [2] AB-${& Author= ${Eichendorf}}-1870
2759 : //
2760 : // Each sub-expression is expanded using expand().
2761 : //---------------------------------------------------------------------------
2762 : inline std::string
2763 136300 : GetPot::_DBE_expand_string(const std::string& str)
2764 : {
2765 : // Parses for closing operators '${ }' and expands them letting
2766 : // white spaces and other letters as they are.
2767 136300 : std::string new_string = "";
2768 1060 : unsigned open_brackets = 0;
2769 1060 : unsigned first = 0;
2770 1593800 : for (unsigned i = 0; i<str.size(); i++)
2771 : {
2772 3862504 : if (i + 2 < str.size() && str.substr(i, 2) == "${")
2773 : {
2774 0 : if (open_brackets == 0)
2775 0 : first = i+2;
2776 0 : open_brackets++;
2777 : }
2778 1457500 : else if (str[i] == '}' && open_brackets > 0)
2779 : {
2780 0 : open_brackets -= 1;
2781 0 : if (open_brackets == 0)
2782 : {
2783 0 : const std::string Replacement = _DBE_expand(str.substr(first, i - first));
2784 0 : new_string += Replacement;
2785 : }
2786 : }
2787 1457500 : else if (open_brackets == 0)
2788 1457500 : new_string += str[i];
2789 : }
2790 136300 : return new_string;
2791 : }
2792 :
2793 :
2794 :
2795 : inline STRING_VECTOR
2796 0 : GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber)
2797 : {
2798 : // ensures that the resulting vector has the expected number
2799 : // of arguments, but they may contain an error message
2800 0 : std::string str = str_;
2801 : // Separates expressions by non-bracketed whitespaces, expands them
2802 : // and puts them into a list.
2803 :
2804 0 : unsigned i=0;
2805 : // (1) eat initial whitespaces
2806 0 : for (; i < str.size(); i++)
2807 0 : if (!std::isspace(str[i]))
2808 0 : break;
2809 :
2810 0 : STRING_VECTOR expr_list;
2811 0 : unsigned open_brackets = 0;
2812 0 : std::vector<unsigned> start_idx;
2813 0 : unsigned start_new_string = i;
2814 0 : unsigned l = (unsigned)(str.size());
2815 :
2816 : // (2) search for ${ } expressions ...
2817 0 : while (i < l)
2818 : {
2819 0 : const char letter = str[i];
2820 : // whitespace -> end of expression
2821 0 : if (std::isspace(letter) && open_brackets == 0)
2822 : {
2823 0 : expr_list.push_back(str.substr(start_new_string, i - start_new_string));
2824 0 : bool no_breakout_f = true;
2825 0 : for (i++; i < l ; i++)
2826 : {
2827 0 : if (!std::isspace(str[i]))
2828 : {
2829 0 : no_breakout_f = false;
2830 0 : start_new_string = i;
2831 0 : break;
2832 : }
2833 : }
2834 :
2835 0 : if (no_breakout_f)
2836 : {
2837 : // end of expression list
2838 0 : if (expr_list.size() < ExpectedNumber)
2839 : {
2840 0 : const std::string pre_tmp("<< ${ }: missing arguments>>");
2841 0 : STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
2842 0 : expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
2843 0 : }
2844 0 : return expr_list;
2845 : }
2846 : }
2847 :
2848 : // dollar-bracket expression
2849 0 : if (str.length() >= i+2 && str.substr(i, 2) == "${")
2850 : {
2851 0 : open_brackets++;
2852 0 : start_idx.push_back(i+2);
2853 : }
2854 :
2855 0 : else if (letter == '}' && open_brackets > 0)
2856 : {
2857 0 : int start = start_idx[start_idx.size()-1];
2858 0 : start_idx.pop_back();
2859 0 : const std::string Replacement = _DBE_expand(str.substr(start, i-start));
2860 0 : if (start - 3 < (int)0)
2861 0 : str = Replacement + str.substr(i+1);
2862 : else
2863 0 : str = str.substr(0, start-2) + Replacement + str.substr(i+1);
2864 0 : l = (int)(str.size());
2865 0 : i = start + (int)(Replacement.size()) - 3;
2866 0 : open_brackets--;
2867 : }
2868 0 : i++;
2869 : }
2870 :
2871 : // end of expression list
2872 0 : expr_list.push_back(str.substr(start_new_string, i-start_new_string));
2873 :
2874 0 : if (expr_list.size() < ExpectedNumber)
2875 : {
2876 0 : const std::string pre_tmp("<< ${ }: missing arguments>>");
2877 0 : STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
2878 0 : expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
2879 0 : }
2880 :
2881 0 : return expr_list;
2882 0 : }
2883 :
2884 :
2885 :
2886 : inline const GetPot::variable*
2887 0 : GetPot::_DBE_get_variable(const std::string& VarName)
2888 : {
2889 0 : static GetPot::variable ev;
2890 0 : std::string secure_Prefix = prefix;
2891 :
2892 0 : prefix = section;
2893 : // (1) first search in currently active section
2894 0 : const GetPot::variable* var = _request_variable(VarName.c_str());
2895 0 : if (var != 0)
2896 : {
2897 0 : prefix = secure_Prefix;
2898 0 : return var;
2899 : }
2900 :
2901 : // (2) search in root name space
2902 0 : prefix = "";
2903 0 : var = _request_variable(VarName.c_str());
2904 0 : if (var != 0)
2905 : {
2906 0 : prefix = secure_Prefix;
2907 0 : return var;
2908 : }
2909 :
2910 0 : prefix = secure_Prefix;
2911 :
2912 : // error occurred => variable name == ""
2913 0 : ev.original = "<<${ } variable '";
2914 0 : ev.original += VarName + "' undefined>>";
2915 0 : return &ev;
2916 : }
2917 :
2918 :
2919 :
2920 : inline std::string
2921 0 : GetPot::_DBE_expand(const std::string& expr)
2922 : {
2923 : // ${: } pure text
2924 0 : if (expr[0] == ':')
2925 0 : return expr.substr(1);
2926 :
2927 : // ${& expr expr ... } text concatenation
2928 0 : else if (expr[0] == '&')
2929 : {
2930 0 : const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1);
2931 :
2932 0 : STRING_VECTOR::const_iterator it = A.begin();
2933 0 : std::string result = *it++;
2934 0 : for (; it != A.end(); ++it) result += *it;
2935 :
2936 0 : return result;
2937 0 : }
2938 :
2939 : // ${<-> expr expr expr} text replacement
2940 0 : else if (expr.length() >= 3 && expr.substr(0, 3) == "<->")
2941 : {
2942 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3);
2943 0 : size_t tmp = 0;
2944 0 : const size_t L = A[1].length();
2945 :
2946 0 : while ((tmp = A[0].find(A[1])) != std::string::npos)
2947 0 : A[0].replace(tmp, L, A[2]);
2948 :
2949 0 : return A[0];
2950 0 : }
2951 :
2952 : // ${=func [expr...] } function evaluation
2953 0 : else if (expr.length() >= 2 &&
2954 0 : expr.substr(0, 1) == "=" &&
2955 0 : expr.substr(0, 2) != "==")
2956 : {
2957 0 : size_t funcnamestart = expr.find_first_not_of(" \t", 1);
2958 0 : if (funcnamestart != std::string::npos)
2959 : {
2960 0 : size_t funcnameend = expr.find_first_of(" \t",funcnamestart);
2961 : std::string funcname = expr.substr(funcnamestart,
2962 0 : funcnameend-funcnamestart);
2963 0 : if (funcname == "log")
2964 : {
2965 : STRING_VECTOR A =
2966 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2967 0 : double arg = _convert_to_type(A[0], 0.0);
2968 0 : return _convert_from_type(std::log(arg));
2969 0 : }
2970 0 : else if (funcname == "log10")
2971 : {
2972 : STRING_VECTOR A =
2973 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2974 0 : double arg = _convert_to_type(A[0], 0.0);
2975 0 : return _convert_from_type(std::log10(arg));
2976 0 : }
2977 0 : else if (funcname == "exp")
2978 : {
2979 : STRING_VECTOR A =
2980 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2981 0 : double arg = _convert_to_type(A[0], 0.0);
2982 0 : return _convert_from_type(std::exp(arg));
2983 0 : }
2984 0 : else if (funcname == "sin")
2985 : {
2986 : STRING_VECTOR A =
2987 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2988 0 : double arg = _convert_to_type(A[0], 0.0);
2989 0 : return _convert_from_type(std::sin(arg));
2990 0 : }
2991 0 : else if (funcname == "cos")
2992 : {
2993 : STRING_VECTOR A =
2994 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
2995 0 : double arg = _convert_to_type(A[0], 0.0);
2996 0 : return _convert_from_type(std::cos(arg));
2997 0 : }
2998 0 : else if (funcname == "tan")
2999 : {
3000 : STRING_VECTOR A =
3001 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3002 0 : double arg = _convert_to_type(A[0], 0.0);
3003 0 : return _convert_from_type(std::tan(arg));
3004 0 : }
3005 0 : else if (funcname == "asin")
3006 : {
3007 : STRING_VECTOR A =
3008 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3009 0 : double arg = _convert_to_type(A[0], 0.0);
3010 0 : return _convert_from_type(std::asin(arg));
3011 0 : }
3012 0 : else if (funcname == "acos")
3013 : {
3014 : STRING_VECTOR A =
3015 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3016 0 : double arg = _convert_to_type(A[0], 0.0);
3017 0 : return _convert_from_type(std::acos(arg));
3018 0 : }
3019 0 : else if (funcname == "atan")
3020 : {
3021 : STRING_VECTOR A =
3022 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3023 0 : double arg = _convert_to_type(A[0], 0.0);
3024 0 : return _convert_from_type(std::atan(arg));
3025 0 : }
3026 0 : else if (funcname == "atan2")
3027 : {
3028 : STRING_VECTOR A =
3029 0 : _DBE_get_expr_list(expr.substr(funcnameend), 2);
3030 0 : double arg1 = _convert_to_type(A[0], 0.0);
3031 0 : double arg2 = _convert_to_type(A[1], 0.0);
3032 0 : return _convert_from_type(std::atan2(arg1, arg2));
3033 0 : }
3034 0 : else if (funcname == "sinh")
3035 : {
3036 : STRING_VECTOR A =
3037 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3038 0 : double arg = _convert_to_type(A[0], 0.0);
3039 0 : return _convert_from_type(std::sinh(arg));
3040 0 : }
3041 0 : else if (funcname == "cosh")
3042 : {
3043 : STRING_VECTOR A =
3044 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3045 0 : double arg = _convert_to_type(A[0], 0.0);
3046 0 : return _convert_from_type(std::cosh(arg));
3047 0 : }
3048 0 : else if (funcname == "tanh")
3049 : {
3050 : STRING_VECTOR A =
3051 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3052 0 : double arg = _convert_to_type(A[0], 0.0);
3053 0 : return _convert_from_type(std::tanh(arg));
3054 0 : }
3055 : #ifdef HAVE_INVERSE_HYPERBOLIC_SINE
3056 0 : else if (funcname == "asinh")
3057 : {
3058 : STRING_VECTOR A =
3059 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3060 0 : double arg = _convert_to_type(A[0], 0.0);
3061 0 : return _convert_from_type(std::asinh(arg));
3062 0 : }
3063 : #endif
3064 : #ifdef HAVE_INVERSE_HYPERBOLIC_COSINE
3065 0 : else if (funcname == "acosh")
3066 : {
3067 : STRING_VECTOR A =
3068 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3069 0 : double arg = _convert_to_type(A[0], 0.0);
3070 0 : return _convert_from_type(std::acosh(arg));
3071 0 : }
3072 : #endif
3073 : #ifdef HAVE_INVERSE_HYPERBOLIC_TANGENT
3074 0 : else if (funcname == "atanh")
3075 : {
3076 : STRING_VECTOR A =
3077 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3078 0 : double arg = _convert_to_type(A[0], 0.0);
3079 0 : return _convert_from_type(std::atanh(arg));
3080 0 : }
3081 : #endif
3082 0 : else if (funcname == "sqrt")
3083 : {
3084 : STRING_VECTOR A =
3085 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3086 0 : double arg = _convert_to_type(A[0], 0.0);
3087 0 : return _convert_from_type(std::sqrt(arg));
3088 0 : }
3089 0 : else if (funcname == "abs")
3090 : {
3091 : STRING_VECTOR A =
3092 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3093 0 : double arg = _convert_to_type(A[0], 0.0);
3094 0 : return _convert_from_type(std::abs(arg));
3095 0 : }
3096 0 : else if (funcname == "max")
3097 : {
3098 : STRING_VECTOR A =
3099 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3100 0 : STRING_VECTOR::const_iterator it = A.begin();
3101 0 : double result = _convert_to_type(*it++, 0.0);
3102 0 : for (; it != A.end(); ++it)
3103 0 : result = std::max(result, _convert_to_type(*it, 0.0));
3104 0 : return _convert_from_type(result);
3105 0 : }
3106 0 : else if (funcname == "min")
3107 : {
3108 : STRING_VECTOR A =
3109 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3110 0 : STRING_VECTOR::const_iterator it = A.begin();
3111 0 : double result = _convert_to_type(*it++, 0.0);
3112 0 : for (; it != A.end(); ++it)
3113 0 : result = std::min(result, _convert_to_type(*it, 0.0));
3114 0 : return _convert_from_type(result);
3115 0 : }
3116 0 : else if (funcname == "ceil")
3117 : {
3118 : STRING_VECTOR A =
3119 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3120 0 : double arg = _convert_to_type(A[0], 0.0);
3121 0 : return _convert_from_type(std::ceil(arg));
3122 0 : }
3123 0 : else if (funcname == "floor")
3124 : {
3125 : STRING_VECTOR A =
3126 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3127 0 : double arg = _convert_to_type(A[0], 0.0);
3128 0 : return _convert_from_type(std::floor(arg));
3129 0 : }
3130 0 : else if (funcname == "fmod")
3131 : {
3132 : STRING_VECTOR A =
3133 0 : _DBE_get_expr_list(expr.substr(funcnameend), 2);
3134 0 : double arg1 = _convert_to_type(A[0], 0.0);
3135 0 : double arg2 = _convert_to_type(A[1], 0.0);
3136 0 : return _convert_from_type(std::fmod(arg1, arg2));
3137 0 : }
3138 0 : else if (funcname == "srand")
3139 : {
3140 : STRING_VECTOR A =
3141 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3142 0 : unsigned int arg = _convert_to_type(A[0], 0u);
3143 0 : std::srand(arg);
3144 0 : return A[0];
3145 0 : }
3146 : // ${=rand range} with default range==RAND_MAX
3147 0 : else if (funcname == "rand")
3148 : {
3149 0 : if (funcnameend >= expr.length() ||
3150 0 : expr.find_first_not_of(" \t", funcnameend) == std::string::npos)
3151 0 : return _convert_from_type(std::rand());
3152 :
3153 : STRING_VECTOR A =
3154 0 : _DBE_get_expr_list(expr.substr(funcnameend), 1);
3155 0 : unsigned int range = _convert_to_type(A[0],0u);
3156 0 : if (!range)
3157 0 : return _convert_from_type(0);
3158 0 : const unsigned int x = (RAND_MAX + 1u) / range;
3159 0 : const unsigned int y = x * range;
3160 : unsigned int returnval;
3161 0 : do
3162 : {
3163 0 : returnval = rand();
3164 0 : } while (returnval >= y);
3165 0 : return _convert_from_type(returnval / x);
3166 0 : }
3167 0 : else if (funcname == "time")
3168 0 : return _convert_from_type(std::time(NULL));
3169 : else
3170 : {
3171 0 : getpot_cerr << "ERROR: unrecognized function "
3172 0 : << funcname << std::endl;
3173 0 : getpot_error();
3174 : }
3175 : }
3176 : }
3177 :
3178 : // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
3179 0 : else if (expr[0] == '+')
3180 : {
3181 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3182 0 : STRING_VECTOR::const_iterator it = A.begin();
3183 0 : double result = _convert_to_type(*it++, 0.0);
3184 0 : for (; it != A.end(); ++it)
3185 0 : result += _convert_to_type(*it, 0.0);
3186 :
3187 0 : return _convert_from_type(result);
3188 0 : }
3189 0 : else if (expr[0] == '-')
3190 : {
3191 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3192 0 : STRING_VECTOR::const_iterator it = A.begin();
3193 0 : double result = _convert_to_type(*it++, 0.0);
3194 0 : for (; it != A.end(); ++it)
3195 0 : result -= _convert_to_type(*it, 0.0);
3196 :
3197 0 : return _convert_from_type(result);
3198 0 : }
3199 0 : else if (expr[0] == '*')
3200 : {
3201 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3202 0 : STRING_VECTOR::const_iterator it = A.begin();
3203 0 : double result = _convert_to_type(*it++, 0.0);
3204 0 : for (; it != A.end(); ++it)
3205 0 : result *= _convert_to_type(*it, 0.0);
3206 :
3207 0 : return _convert_from_type(result);
3208 0 : }
3209 0 : else if (expr[0] == '/')
3210 : {
3211 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3212 0 : STRING_VECTOR::const_iterator it = A.begin();
3213 0 : double result = _convert_to_type(*it++, 0.0);
3214 0 : if (result == 0)
3215 0 : return "0.0";
3216 :
3217 0 : for (; it != A.end(); ++it)
3218 : {
3219 0 : const double Q = _convert_to_type(*it, 0.0);
3220 0 : result /= Q;
3221 : }
3222 0 : return _convert_from_type(result);
3223 0 : }
3224 :
3225 : // ${^ ... } power expressions
3226 0 : else if (expr[0] == '^')
3227 : {
3228 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3229 0 : STRING_VECTOR::const_iterator it = A.begin();
3230 0 : double result = _convert_to_type(*it++, 0.0);
3231 0 : for (; it != A.end(); ++it)
3232 0 : result = pow(result, _convert_to_type(*it, 0.0));
3233 0 : return _convert_from_type(result);
3234 0 : }
3235 :
3236 : // ${== } ${<= } ${>= } comparisons (return the number of the first 'match'
3237 0 : else if (expr.length() >= 2 &&
3238 0 : (expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
3239 0 : expr.substr(0,2) == "<=" || expr[0] == '>' || expr[0] == '<'))
3240 : {
3241 : // differentiate between two and one sign operators
3242 0 : unsigned op = 0;
3243 : enum { EQ, GEQ, LEQ, GT, LT };
3244 :
3245 0 : if (expr.substr(0, 2) == "==")
3246 0 : op = EQ;
3247 :
3248 0 : else if (expr.substr(0, 2) == ">=")
3249 0 : op = GEQ;
3250 :
3251 0 : else if (expr.substr(0, 2) == "<=")
3252 0 : op = LEQ;
3253 :
3254 0 : else if (expr[0] == '>')
3255 0 : op = GT;
3256 :
3257 : else
3258 0 : op = LT;
3259 :
3260 0 : STRING_VECTOR a;
3261 0 : if (op == GT || op == LT)
3262 0 : a = _DBE_get_expr_list(expr.substr(1), 2);
3263 :
3264 : else
3265 0 : a = _DBE_get_expr_list(expr.substr(2), 2);
3266 :
3267 0 : std::string x_orig = a[0];
3268 0 : double x = _convert_to_type(x_orig, 1e37);
3269 0 : unsigned i = 1;
3270 :
3271 0 : STRING_VECTOR::const_iterator y_orig = a.begin();
3272 0 : for (y_orig++; y_orig != a.end(); ++y_orig)
3273 : {
3274 0 : double y = _convert_to_type(*y_orig, 1e37);
3275 :
3276 : // set the strings as reference if one wasn't a number
3277 0 : if (x == 1e37 || y == 1e37)
3278 : {
3279 : // it's a string comparison
3280 0 : if ((op == EQ && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
3281 0 : (op == LEQ && x_orig <= *y_orig) || (op == GT && x_orig > *y_orig) ||
3282 0 : (op == LT && x_orig < *y_orig))
3283 0 : return _convert_from_type(i);
3284 : }
3285 : else
3286 : {
3287 : // it's a number comparison
3288 0 : if ((op == EQ && x == y) || (op == GEQ && x >= y) ||
3289 0 : (op == LEQ && x <= y) || (op == GT && x > y) ||
3290 0 : (op == LT && x < y))
3291 0 : return _convert_from_type(i);
3292 : }
3293 0 : i++;
3294 : }
3295 :
3296 : // nothing fulfills the condition => return 0
3297 0 : return "0";
3298 0 : }
3299 :
3300 : // ${?? expr expr} select
3301 0 : else if (expr.length() >= 2 && expr.substr(0, 2) == "??")
3302 : {
3303 0 : STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2);
3304 0 : double x = _convert_to_type(a[0], 1e37);
3305 :
3306 : // last element is always the default argument
3307 0 : if (x == 1e37 || x < 0 || x >= double(a.size() - 1))
3308 0 : return a[a.size()-1];
3309 :
3310 : // round x to closest integer
3311 0 : return a[int(x+0.5)];
3312 0 : }
3313 :
3314 : // ${? expr expr expr} if then else conditions
3315 0 : else if (expr[0] == '?')
3316 : {
3317 0 : STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2);
3318 :
3319 0 : if (_convert_to_type(a[0], 0.0) == 1.0)
3320 0 : return a[1];
3321 :
3322 0 : else if (a.size() > 2)
3323 0 : return a[2];
3324 0 : }
3325 : // ${! expr} maxro expansion
3326 0 : else if (expr[0] == '!')
3327 : {
3328 0 : const GetPot::variable* Var = _DBE_get_variable(expr.substr(1));
3329 : // error
3330 0 : if (Var->name == "")
3331 0 : return std::string(Var->original);
3332 :
3333 0 : const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2);
3334 0 : return A[0];
3335 0 : }
3336 : // ${@: } - string subscription
3337 0 : else if (expr.length() >= 2 && expr.substr(0,2) == "@:")
3338 : {
3339 0 : const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2);
3340 0 : double x = _convert_to_type(A[1], 1e37);
3341 :
3342 : // last element is always the default argument
3343 0 : if (x == 1e37 || x < 0 || x >= double(A[0].size() - 1))
3344 0 : return "<<1st index out of range>>";
3345 :
3346 0 : if (A.size() > 2)
3347 : {
3348 0 : double y = _convert_to_type(A[2], 1e37);
3349 0 : if (y != 1e37 && y > 0 && y <= double(A[0].size() - 1) && y > x)
3350 0 : return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
3351 :
3352 0 : else if (y == -1)
3353 0 : return A[0].substr(int(x+0.5));
3354 :
3355 0 : return "<<2nd index out of range>>";
3356 : }
3357 : else
3358 : {
3359 0 : char* tmp = new char[2];
3360 0 : tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
3361 0 : std::string result(tmp);
3362 0 : delete [] tmp;
3363 0 : return result;
3364 : }
3365 0 : }
3366 : // ${@ } - vector subscription
3367 0 : else if (expr[0] == '@')
3368 : {
3369 0 : STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
3370 0 : const GetPot::variable* Var = _DBE_get_variable(A[0]);
3371 : // error
3372 0 : if (Var->name == "")
3373 : {
3374 : // make a copy of the string if an error occurred
3375 : // (since the error variable is a static variable inside get_variable())
3376 0 : return std::string(Var->original);
3377 : }
3378 :
3379 0 : double x = _convert_to_type(A[1], 1e37);
3380 :
3381 : // last element is always the default argument
3382 0 : if (x == 1e37 || x < 0 || x >= double(Var->value.size()))
3383 0 : return "<<1st index out of range>>";
3384 :
3385 0 : if (A.size() > 2)
3386 : {
3387 0 : double y = _convert_to_type(A[2], 1e37);
3388 0 : int begin = int(x+0.5);
3389 0 : int end = 0;
3390 0 : if (y != 1e37 && y > 0 && y <= double(Var->value.size()) && y > x)
3391 0 : end = int(y+1.5);
3392 0 : else if (y == -1)
3393 0 : end = int(Var->value.size());
3394 : else
3395 0 : return "<<2nd index out of range>>";
3396 :
3397 0 : std::string result = *(Var->get_element(begin));
3398 0 : for (int i = begin+1; i < end; i++)
3399 0 : result += std::string(" ") + *(Var->get_element(i));
3400 0 : return result;
3401 : }
3402 : else
3403 0 : return *(Var->get_element(int(x+0.5)));
3404 0 : }
3405 :
3406 0 : const STRING_VECTOR A = _DBE_get_expr_list(expr, 1);
3407 0 : const GetPot::variable* B = _DBE_get_variable(A[0]);
3408 :
3409 : // make a copy of the string if an error occurred
3410 : // (since the error variable is a static variable inside get_variable())
3411 0 : if (B->name == "")
3412 0 : return std::string(B->original);
3413 :
3414 : // ([email protected] mentioned to me the warning MSVC++6.0 produces
3415 : // with: else return B->original (thanks))
3416 0 : return B->original;
3417 0 : }
3418 :
3419 :
3420 :
3421 : ///////////////////////////////////////////////////////////////////////////////
3422 : // (*) unidentified flying objects
3423 : //.............................................................................
3424 : //
3425 : inline bool
3426 : GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
3427 : {
3428 : victorate(std::string, VecStr, itk)
3429 : {
3430 : if (*itk == Str)
3431 : return true;
3432 : }
3433 : return false;
3434 : }
3435 :
3436 :
3437 :
3438 : inline STRING_VECTOR
3439 : GetPot::unidentified_arguments(unsigned Number,
3440 : const char* KnownArgument1, ...) const
3441 : {
3442 : std::set<std::string> known_arguments;
3443 :
3444 : // (1) create a vector of known arguments
3445 : if (Number == 0)
3446 : return STRING_VECTOR();
3447 :
3448 : va_list ap;
3449 : va_start(ap, KnownArgument1);
3450 : known_arguments.insert(std::string(KnownArgument1));
3451 : for (unsigned i=1; i<Number; i++)
3452 : known_arguments.insert(std::string(va_arg(ap, char *)));
3453 : va_end(ap);
3454 :
3455 : return unidentified_arguments(known_arguments);
3456 : }
3457 :
3458 :
3459 :
3460 : inline STRING_VECTOR
3461 : GetPot::unidentified_arguments() const
3462 : {
3463 : return unidentified_arguments(_requested_arguments);
3464 : }
3465 :
3466 :
3467 :
3468 : inline STRING_VECTOR
3469 : GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const
3470 : {
3471 : // We use set for efficiency, but want to support vector inputs for
3472 : // backwards compatibility.
3473 : return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end()));
3474 : }
3475 :
3476 :
3477 :
3478 : inline STRING_VECTOR
3479 : GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const
3480 : {
3481 : STRING_VECTOR ufos;
3482 : STRING_VECTOR::const_iterator it = argv.begin();
3483 : ++it; // forget about argv[0] (application or filename)
3484 : for (; it != argv.end(); ++it)
3485 : {
3486 : // -- argument belongs to prefixed section ?
3487 : const std::string arg = _get_remaining_string(*it, prefix);
3488 : if (arg == "")
3489 : continue;
3490 :
3491 : // -- check if in list
3492 : if (Knowns.find(arg) == Knowns.end())
3493 : ufos.push_back(*it);
3494 : }
3495 : return ufos;
3496 : }
3497 :
3498 :
3499 :
3500 : inline STRING_VECTOR
3501 : GetPot::unidentified_options(unsigned Number,
3502 : const char* KnownOption1, ...) const
3503 : {
3504 : std::set<std::string> known_options;
3505 :
3506 : // (1) create a vector of known arguments
3507 : if (Number == 0)
3508 : return STRING_VECTOR();
3509 :
3510 : va_list ap;
3511 : va_start(ap, KnownOption1);
3512 : known_options.insert(std::string(KnownOption1));
3513 : for (unsigned i=1; i<Number; i++)
3514 : known_options.insert(std::string(va_arg(ap, char *)));
3515 : va_end(ap);
3516 :
3517 : return unidentified_options(known_options);
3518 : }
3519 :
3520 :
3521 :
3522 : inline STRING_VECTOR
3523 : GetPot::unidentified_options() const
3524 : {
3525 : // -- every option is an argument.
3526 : // -- the set of requested arguments contains the set of requested options.
3527 : // -- IF the set of requested arguments contains unrequested options,
3528 : // THEN they were requested as 'follow' and 'next' arguments and not as real options.
3529 : //
3530 : // => it is not necessary to separate requested options from the list
3531 : return unidentified_arguments(_requested_arguments);
3532 : }
3533 :
3534 :
3535 :
3536 : inline STRING_VECTOR
3537 : GetPot::unidentified_options(const std::vector<std::string>& Knowns) const
3538 : {
3539 : // We use set for efficiency, but want to support vector inputs for
3540 : // backwards compatibility.
3541 : return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end()));
3542 : }
3543 :
3544 :
3545 :
3546 : inline STRING_VECTOR
3547 : GetPot::unidentified_options(const std::set<std::string>& Knowns) const
3548 : {
3549 : STRING_VECTOR ufos;
3550 : STRING_VECTOR::const_iterator it = argv.begin();
3551 : ++it; // forget about argv[0] (application or filename)
3552 : for (; it != argv.end(); ++it)
3553 : {
3554 : // -- argument belongs to prefixed section ?
3555 : const std::string arg = _get_remaining_string(*it, prefix);
3556 : if (arg == "")
3557 : continue;
3558 :
3559 : // is argument really an option (starting with '-') ?
3560 : if (arg.length() < 1 || arg[0] != '-')
3561 : continue;
3562 :
3563 : if (Knowns.find(arg) == Knowns.end())
3564 : ufos.push_back(*it);
3565 : }
3566 :
3567 : return ufos;
3568 : }
3569 :
3570 :
3571 :
3572 : // Two modes:
3573 : // ArgumentNumber >= 0 check specific argument
3574 : // ArgumentNumber == -1 check all options starting with one '-'
3575 : // for flags
3576 : inline std::string
3577 : GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
3578 : {
3579 : std::string ufos;
3580 : // STRING_VECTOR known_arguments;
3581 : std::string KFL(KnownFlagList);
3582 :
3583 : // (2) iteration over '-' arguments (options)
3584 : if (ArgumentNumber == -1)
3585 : {
3586 : STRING_VECTOR::const_iterator it = argv.begin();
3587 : ++it; // forget about argv[0] (application or filename)
3588 : for (; it != argv.end(); ++it)
3589 : {
3590 : // -- argument belongs to prefixed section ?
3591 : const std::string arg = _get_remaining_string(*it, prefix);
3592 : if (arg == "") continue;
3593 :
3594 : // -- does arguments start with '-' (but not '--')
3595 : if (arg.length() < 2)
3596 : continue;
3597 :
3598 : else if (arg[0] != '-')
3599 : continue;
3600 :
3601 : else if (arg[1] == '-')
3602 : continue;
3603 :
3604 : // -- check out if flags inside option are contained in KnownFlagList
3605 : const char* p=arg.c_str();
3606 : p++; // skip starting minus
3607 : for (; *p != '\0' ; p++)
3608 : if (KFL.find(*p) == std::string::npos) ufos += *p;
3609 : }
3610 : }
3611 : // (1) check specific argument
3612 : else
3613 : {
3614 : // -- only check arguments that start with prefix
3615 : int no_matches = 0;
3616 : for (unsigned i=1; i<argv.size(); i++)
3617 : {
3618 : const std::string Remain = _get_remaining_string(argv[i], prefix);
3619 : if (Remain != "")
3620 : {
3621 : no_matches++;
3622 : if (no_matches == ArgumentNumber)
3623 : {
3624 : // -- the right argument number inside the section is found
3625 : // => check it for flags
3626 : const char* p = Remain.c_str();
3627 : p++; // skip starting minus
3628 : for (; *p != '\0' ; p++)
3629 : if (KFL.find(*p) == std::string::npos) ufos += *p;
3630 : return ufos;
3631 : }
3632 : }
3633 : }
3634 : }
3635 : return ufos;
3636 : }
3637 :
3638 :
3639 :
3640 : inline STRING_VECTOR
3641 : GetPot::unidentified_variables(unsigned Number,
3642 : const char* KnownVariable1, ...) const
3643 : {
3644 : std::set<std::string> known_variables;
3645 :
3646 : // create vector of known arguments
3647 : if (Number == 0)
3648 : return STRING_VECTOR();
3649 :
3650 : va_list ap;
3651 : va_start(ap, KnownVariable1);
3652 : known_variables.insert(std::string(KnownVariable1));
3653 : for (unsigned i=1; i<Number; i++)
3654 : known_variables.insert(std::string(va_arg(ap, char *)));
3655 : va_end(ap);
3656 :
3657 : return unidentified_variables(known_variables);
3658 : }
3659 :
3660 :
3661 :
3662 : inline STRING_VECTOR
3663 : GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const
3664 : {
3665 : // We use set for efficiency, but want to support vector inputs for
3666 : // backwards compatibility.
3667 : return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end()));
3668 : }
3669 :
3670 :
3671 :
3672 : inline STRING_VECTOR
3673 : GetPot::unidentified_variables(const std::set<std::string>& Knowns) const
3674 : {
3675 : STRING_VECTOR ufos;
3676 :
3677 : victorate(GetPot::variable, variables, it)
3678 : {
3679 : // -- check if variable has specific prefix
3680 : const std::string var_name = _get_remaining_string((*it).name, prefix);
3681 : if (var_name == "")
3682 : continue;
3683 :
3684 : // -- check if variable is known
3685 : if (Knowns.find(var_name) == Knowns.end())
3686 : ufos.push_back((*it).name);
3687 : }
3688 : return ufos;
3689 : }
3690 :
3691 :
3692 :
3693 : inline STRING_VECTOR
3694 : GetPot::unidentified_variables() const
3695 : {
3696 : return unidentified_variables(_requested_variables);
3697 : }
3698 :
3699 :
3700 :
3701 : inline STRING_VECTOR
3702 : GetPot::unidentified_sections(unsigned Number,
3703 : const char* KnownSection1, ...) const
3704 : {
3705 : std::set<std::string> known_sections;
3706 :
3707 : // (1) create a vector of known arguments
3708 : if (Number == 0)
3709 : return STRING_VECTOR();
3710 :
3711 : va_list ap;
3712 : va_start(ap, KnownSection1);
3713 : known_sections.insert(std::string(KnownSection1));
3714 : for (unsigned i=1; i<Number; i++)
3715 : {
3716 : std::string tmp = std::string(va_arg(ap, char *));
3717 :
3718 : if (tmp.length() == 0)
3719 : continue;
3720 :
3721 : if (tmp[tmp.length()-1] != '/')
3722 : tmp += '/';
3723 :
3724 : known_sections.insert(tmp);
3725 : }
3726 : va_end(ap);
3727 :
3728 : return unidentified_sections(known_sections);
3729 : }
3730 :
3731 :
3732 :
3733 : inline STRING_VECTOR
3734 : GetPot::unidentified_sections() const
3735 : {
3736 : return unidentified_sections(_requested_sections);
3737 : }
3738 :
3739 :
3740 :
3741 : inline STRING_VECTOR
3742 : GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const
3743 : {
3744 : // We use set for efficiency, but want to support vector inputs for
3745 : // backwards compatibility.
3746 : return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end()));
3747 : }
3748 :
3749 :
3750 :
3751 : inline STRING_VECTOR
3752 : GetPot::unidentified_sections(const std::set<std::string>& Knowns) const
3753 : {
3754 : STRING_VECTOR ufos;
3755 :
3756 : victorate(std::string, section_list, it)
3757 : {
3758 : // -- check if section conform to prefix
3759 : const std::string sec_name = _get_remaining_string(*it, prefix);
3760 : if (sec_name == "")
3761 : continue;
3762 :
3763 : // -- check if section is known
3764 : if (Knowns.find(sec_name) == Knowns.end())
3765 : ufos.push_back(*it);
3766 : }
3767 :
3768 : return ufos;
3769 : }
3770 :
3771 :
3772 :
3773 : inline STRING_VECTOR
3774 : GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
3775 : {
3776 : std::set<std::string> known_nominuses;
3777 :
3778 : // create vector of known arguments
3779 : if (Number == 0)
3780 : return STRING_VECTOR();
3781 :
3782 : va_list ap;
3783 : va_start(ap, Known);
3784 : known_nominuses.insert(std::string(Known));
3785 : for (unsigned i=1; i<Number; i++)
3786 : {
3787 : std::string tmp = std::string(va_arg(ap, char *));
3788 : if (tmp.length() == 0)
3789 : continue;
3790 : known_nominuses.insert(tmp);
3791 : }
3792 : va_end(ap);
3793 :
3794 : return unidentified_nominuses(known_nominuses);
3795 : }
3796 :
3797 :
3798 :
3799 : inline STRING_VECTOR
3800 : GetPot::unidentified_nominuses() const
3801 : {
3802 : // -- every nominus is an argument.
3803 : // -- the set of requested arguments contains the set of requested nominuss.
3804 : // -- IF the set of requested arguments contains unrequested nominuss,
3805 : // THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
3806 : //
3807 : // => it is not necessary to separate requested nominus from the list
3808 :
3809 : return unidentified_nominuses(_requested_arguments);
3810 : }
3811 :
3812 :
3813 :
3814 : inline STRING_VECTOR
3815 : GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const
3816 : {
3817 : // We use set for efficiency, but want to support vector inputs for
3818 : // backwards compatibility.
3819 : return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end()));
3820 : }
3821 :
3822 :
3823 :
3824 : inline STRING_VECTOR
3825 : GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const
3826 : {
3827 : STRING_VECTOR ufos;
3828 :
3829 : // (2) iterate over all arguments
3830 : STRING_VECTOR::const_iterator it = argv.begin();
3831 : ++it; // forget about argv[0] (application or filename)
3832 : for (; it != argv.end(); ++it)
3833 : {
3834 : // -- check if nominus part of prefix
3835 : const std::string arg = _get_remaining_string(*it, prefix);
3836 : if (arg == "")
3837 : continue;
3838 :
3839 : if (arg.length() < 1)
3840 : continue;
3841 :
3842 : // option ? --> not a nomius
3843 : if (arg[0] == '-')
3844 : continue;
3845 :
3846 : // section ? --> not a real nominus
3847 : if (arg[0] == '[' && arg[arg.length()-1] == ']')
3848 : continue;
3849 :
3850 : // variable definition ? --> not a real nominus
3851 : bool continue_f = false;
3852 : for (unsigned i=0; i<arg.length() ; i++)
3853 : if (arg[i] == '=')
3854 : {
3855 : continue_f = true;
3856 : break;
3857 : }
3858 :
3859 : if (continue_f)
3860 : continue;
3861 :
3862 : // real nominuses are compared with the given list
3863 : if (Knowns.find(arg) == Knowns.end())
3864 : ufos.push_back(*it);
3865 : }
3866 : return ufos;
3867 : }
3868 :
3869 :
3870 : ///////////////////////////////////////////////////////////////////////////////
3871 : // (*) Accessors for requested types
3872 : //.............................................................................
3873 :
3874 : inline
3875 : std::set<std::string>
3876 71 : GetPot::get_requested_arguments() const
3877 : {
3878 71 : return _requested_arguments;
3879 : }
3880 :
3881 :
3882 :
3883 : inline
3884 : std::set<std::string>
3885 71 : GetPot::get_requested_variables() const
3886 : {
3887 71 : return _requested_variables;
3888 : }
3889 :
3890 :
3891 :
3892 : inline
3893 : std::set<std::string>
3894 71 : GetPot::get_requested_sections() const
3895 : {
3896 71 : return _requested_sections;
3897 : }
3898 :
3899 :
3900 :
3901 : ///////////////////////////////////////////////////////////////////////////////
3902 : // (*) variable class
3903 : //.............................................................................
3904 : //
3905 : inline
3906 0 : GetPot::variable::variable()
3907 : : name(),
3908 : value(),
3909 0 : original()
3910 0 : {}
3911 :
3912 :
3913 :
3914 : inline
3915 9180 : GetPot::variable::variable(const variable& Other)
3916 : {
3917 : #ifdef WIN32
3918 : operator=(Other);
3919 : #else
3920 8740 : GetPot::variable::operator=(Other);
3921 : #endif
3922 8740 : }
3923 :
3924 :
3925 :
3926 : inline
3927 4760 : GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
3928 4760 : : name(Name)
3929 : {
3930 : // make a copy of the 'Value'
3931 4760 : take(Value, FieldSeparator);
3932 4760 : }
3933 :
3934 :
3935 :
3936 : inline const std::string*
3937 8 : GetPot::variable::get_element(unsigned Idx) const
3938 : {
3939 4134 : if (Idx >= value.size())
3940 0 : return 0;
3941 : else
3942 8 : return &(value[Idx]);
3943 : }
3944 :
3945 :
3946 :
3947 : inline void
3948 4760 : GetPot::variable::take(const char* Value, const char* FieldSeparator)
3949 : {
3950 5088 : original = std::string(Value); // string member var
3951 4432 : value.clear(); // vector<string> member var
3952 :
3953 : /*
3954 : // separate string by white space delimiters using 'strtok'
3955 : // thread safe usage of strtok (no static members)
3956 : char* spt = 0;
3957 : // make a copy of the 'Value'
3958 : char* copy = new char[strlen(Value)+1];
3959 : strcpy(copy, Value);
3960 : char* follow_token = strtok_r(copy, FieldSeparator, &spt);
3961 : while (follow_token != 0)
3962 : {
3963 : value.push_back(std::string(follow_token));
3964 : follow_token = strtok_r(NULL, FieldSeparator, &spt);
3965 : }
3966 :
3967 : delete [] copy;
3968 : */
3969 :
3970 : // Don't use strtok, instead tokenize the input char "Value" using std::string operations so
3971 : // that the results end up in the local "value" member
3972 :
3973 : // Construct std::string objects from the input char*s. I think the only
3974 : // FieldSeparator recognized by GetPot is whitespace?
3975 5088 : std::string Value_str = std::string(Value);
3976 5088 : std::string delimiters = std::string(FieldSeparator);
3977 :
3978 : // Skip delimiters at beginning.
3979 656 : std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0);
3980 :
3981 : // Find first "non-delimiter".
3982 328 : std::string::size_type pos = Value_str.find_first_of(delimiters, lastPos);
3983 :
3984 : // Loop over the input string until all the tokens have been pushed back
3985 : // into the local "value" member.
3986 9520 : while (std::string::npos != pos || std::string::npos != lastPos)
3987 : {
3988 : // Found a token, add it to the vector.
3989 8864 : value.push_back(Value_str.substr(lastPos, pos - lastPos));
3990 :
3991 : // Skip delimiters. Note the "not_of"
3992 656 : lastPos = Value_str.find_first_not_of(delimiters, pos);
3993 :
3994 : // Find next "non-delimiter"
3995 328 : pos = Value_str.find_first_of(delimiters, lastPos);
3996 : }
3997 :
3998 : // We're done, all the tokens should now be in the vector<string>
3999 4760 : }
4000 :
4001 : inline
4002 15832 : GetPot::variable::~variable()
4003 15804 : {}
4004 :
4005 :
4006 :
4007 : inline GetPot::variable&
4008 8740 : GetPot::variable::operator=(const GetPot::variable& Other)
4009 : {
4010 8740 : if (&Other != this)
4011 : {
4012 8740 : name = Other.name;
4013 8740 : value = Other.value;
4014 8740 : original = Other.original;
4015 : }
4016 8740 : return *this;
4017 : }
4018 :
4019 : #ifdef GETPOT_NAMESPACE
4020 : }
4021 : #endif
4022 :
4023 : #undef victorate
4024 :
4025 : #endif // LIBMESH_GETPOT_H
|