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

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:05 UTC

Hosted By:
SourceForge.net Logo