$extrastylesheet
00001 // -*- c++ -*- 00002 // GetPot Version libMeshHPCT_fork-1.2 Apr/14/2010 00003 // Based on "getpot-1.1.1.tgz" version from SourceForge 00004 // 00005 // New code (C) 2009-2013 Roy Stogner, Karl Schulz 00006 // 00007 // GetPot Version 1.0 Sept/13/2002 00008 // 00009 // WEBSITE: http://getpot.sourceforge.net 00010 // 00011 // This library is free software; you can redistribute it and/or modify 00012 // it under the terms of the GNU Lesser General Public License as 00013 // published by the Free Software Foundation; either version 2.1 of the 00014 // License, or (at your option) any later version. 00015 // 00016 // This library is distributed in the hope that it will be useful, but 00017 // WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 // Lesser General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU Lesser General Public 00022 // License along with this library; if not, write to the Free Software 00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00024 // USA 00025 // 00026 // (C) 2001-2002 Frank R. Schaefer 00027 //========================================================================== 00028 #ifndef LIBMESH_GETPOT_H 00029 #define LIBMESH_GETPOT_H 00030 00031 #if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC) 00032 #define strtok_r(a, b, c) strtok(a, b) 00033 #endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC 00034 00035 #include <algorithm> 00036 #include <cstddef> 00037 #include <fstream> 00038 #include <iostream> // not every compiler distribution includes <iostream> with <fstream> 00039 #include <set> 00040 #include <sstream> 00041 #include <stdexcept> 00042 #include <string> 00043 #include <typeinfo> 00044 #include <vector> 00045 00046 #include <cmath> 00047 #include <cstdlib> 00048 #include <ctime> 00049 00050 extern "C" { 00051 #include <stdarg.h> // --> va_list and friends 00052 #include <string.h> // --> strcmp, strncmp, strlen, strncpy 00053 } 00054 00055 // Undefine USE_LIBMESH to avoid libMesh-specific code 00056 00057 #define USE_LIBMESH 1 00058 00059 #ifdef USE_LIBMESH 00060 00061 #include "libmesh/libmesh_common.h" 00062 00063 // We need a mutex to keep const operations thread-safe in the 00064 // presence of mutable containers. Right now GetPot supports a 00065 // Threads::scoped_mutex wrapper around TBB, and we're assuming that 00066 // users aren't doing any threaded GetPot usage when TBB threads are 00067 // disabled. 00068 #if !defined(GETPOT_DISABLE_MUTEX) 00069 #include "libmesh/threads.h" 00070 #define SCOPED_MUTEX libMesh::Threads::spin_mutex::scoped_lock lock(_getpot_mtx) 00071 #else 00072 #define SCOPED_MUTEX 00073 #endif 00074 00075 #define getpot_cerr libMesh::err 00076 #define getpot_error() libmesh_error() 00077 #define getpot_file_error(filename) libmesh_file_error(filename) 00078 #define getpot_cast_int libMesh::cast_int 00079 00080 #else // USE_LIBMESH 00081 00082 // Currently threaded GetPot use is only supported via libMesh Threads 00083 #define SCOPED_MUTEX 00084 00085 #define getpot_cerr std::cerr 00086 #define getpot_error() throw std::runtime_error(std::string("GetPot Error")) 00087 #define getpot_file_error(filename) getpot_error() 00088 #define getpot_cast_int static_cast 00089 00090 #endif 00091 00092 // Clang provides the __has_builtin macro, we define it for compilers 00093 // that don't... 00094 #ifndef __has_builtin 00095 #define __has_builtin(x) 0 00096 #endif 00097 00098 // Fine-grained ifdefs for all three inverse hyperbolic trig 00099 // functions. This works for the two clang compilers I tried it 00100 // on... a hand-built one and one from Apple. 00101 #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(asinh)) 00102 #define HAVE_INVERSE_HYPERBOLIC_SINE 00103 #endif 00104 00105 #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(acosh)) 00106 #define HAVE_INVERSE_HYPERBOLIC_COSINE 00107 #endif 00108 00109 #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(atanh)) 00110 #define HAVE_INVERSE_HYPERBOLIC_TANGENT 00111 #endif 00112 00113 typedef std::vector<std::string> STRING_VECTOR; 00114 00115 #define victorate(TYPE, VARIABLE, ITERATOR) \ 00116 std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin(); \ 00117 for (; (ITERATOR) != (VARIABLE).end(); ++(ITERATOR)) 00118 00119 // We allow GETPOT_NAMESPACE to be defined before this file is 00120 // included; if libraries using two different versions of GetPot might 00121 // be linked together, the result may be unsafe unless they're put in 00122 // different namespaces. 00123 #ifdef GETPOT_NAMESPACE 00124 namespace GETPOT_NAMESPACE { 00125 #endif 00126 00133 class GetPot 00134 { 00135 inline void _basic_initialization(); 00136 00137 public: 00141 inline GetPot(); 00142 inline GetPot(const GetPot&); 00143 inline GetPot(const int argc_, const char* const* argv_, 00144 const char* FieldSeparator=0x0); 00145 inline GetPot(const char* FileName, 00146 const char* CommentStart=0x0, const char* CommentEnd=0x0, 00147 const char* FieldSeparator=0x0); 00148 inline GetPot(const std::string& FileName, 00149 const std::string& CommentStart = std::string("#"), 00150 const std::string& CommentEnd = std::string("\n"), 00151 const std::string& FieldSeparator = std::string(" \t\n")); 00152 inline ~GetPot(); 00153 inline GetPot& operator=(const GetPot&); 00154 00158 inline void parse_command_line(const int argc_, const char * const* argv_, 00159 const char* FieldSeparator =0x0); 00160 inline void parse_input_file(const std::string& FileName, 00161 const std::string& CommentStart=std::string("#"), 00162 const std::string& CommentEnd=std::string("\n"), 00163 const std::string& FieldSeparator=std::string(" \t\n")); 00164 00168 inline void absorb(const GetPot& Other); 00169 00173 inline void clear_requests(); 00174 inline void disable_request_recording() { request_recording_f = false; } 00175 inline void enable_request_recording() { request_recording_f = true; } 00176 00180 inline const char* operator[](unsigned Idx) const; 00181 00182 template <typename T> 00183 inline T get(unsigned Idx, const T& Default) const; 00184 00185 inline const char* get(unsigned Idx, const char* Default) const; 00186 inline unsigned size() const; 00187 00191 inline bool options_contain(const char* FlagList) const; 00192 inline bool argument_contains(unsigned Idx, const char* FlagList) const; 00193 00201 inline bool have_variable(const char* VarName) const; 00202 inline bool have_variable(const std::string& VarName) const; 00203 00213 bool have_section(const char* section_name) const; 00214 00224 bool have_section(const std::string& section_name) const; 00225 00229 template<typename T> 00230 inline T operator()(const char* VarName, const T& Default) const; 00231 00232 template<typename T> 00233 inline T operator()(const std::string& VarName, const T& Default) const; 00234 00235 inline const char* operator()(const char* VarName, const char* Default) const; 00236 inline const char* operator()(const std::string& VarName, const char* Default) const; 00237 00241 template<typename T> 00242 inline T operator()(const char* VarName, const T& Default, unsigned Idx) const; 00243 00244 template<typename T> 00245 inline T operator()(const std::string& VarName, const T& Default, unsigned Idx) const; 00246 00247 inline const char* operator()(const char* VarName, const char* Default, unsigned Idx) const; 00248 inline const char* operator()(const std::string& VarName, const char* Default, unsigned Idx) const; 00249 00254 template<typename T> 00255 inline T get_value_no_default(const char* VarName, const T& Default) const; 00256 00257 template<typename T> 00258 inline T get_value_no_default(const std::string& VarName, const T& Default) const; 00259 00260 inline const char* get_value_no_default(const char* VarName, const char* Default) const; 00261 inline const char* get_value_no_default(const std::string& VarName, const char* Default) const; 00262 00266 template<typename T> 00267 inline T get_value_no_default(const char* VarName, const T& Default, unsigned Idx) const; 00268 00269 template<typename T> 00270 inline T get_value_no_default(const std::string& VarName, const T& Default, unsigned Idx) const; 00271 00272 inline const char* get_value_no_default(const char* VarName, const char* Default, unsigned Idx) const; 00273 inline const char* get_value_no_default(const std::string& VarName, const char* Default, unsigned Idx) const; 00274 00280 template<typename T> 00281 inline void set(const char* VarName, const T& Value, const bool Requested = true); 00282 00283 template<typename T> 00284 inline void set(const std::string& VarName, const T& Value, const bool Requested = true); 00285 00286 inline void set(const char* VarName, const char* Value, const bool Requested = true); 00287 inline void set(const std::string& VarName, const char* Value, const bool Requested = true); 00288 00289 inline unsigned vector_variable_size(const char* VarName) const; 00290 inline unsigned vector_variable_size(const std::string& VarName) const; 00291 inline STRING_VECTOR get_variable_names() const; 00292 inline STRING_VECTOR get_section_names() const; 00293 inline std::set<std::string> get_overridden_variables() const; 00294 00298 inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); } 00299 inline bool search_failed() const { return search_failed_f; } 00300 00304 inline void disable_loop() { search_loop_f = false; } 00305 inline void enable_loop() { search_loop_f = true; } 00306 00310 inline void reset_cursor(); 00311 inline void init_multiple_occurrence(); 00312 00316 inline bool search(const char* option); 00317 inline bool search(const std::string& option); 00318 inline bool search(unsigned No, const char* P, ...); 00319 00323 template<typename T> 00324 inline T next(const T& Default); 00325 00326 inline const char* next(const char* Default); 00327 00331 template<typename T> 00332 inline T follow(const T& Default, const char* Option); 00333 00334 inline const char* follow(const char* Default, const char* Option); 00335 00339 template<typename T> 00340 inline T follow(const T& Default, unsigned No, const char* Option, ...); 00341 00342 inline const char* follow(const char* Default, unsigned No, const char* Option, ...); 00343 00347 template<typename T> 00348 inline T direct_follow(const T& Default, const char* Option); 00349 00350 inline const char* direct_follow(const char* Default, const char* Option); 00351 00355 inline void reset_nominus_cursor(); 00356 inline STRING_VECTOR nominus_vector() const; 00357 inline unsigned nominus_size() const { return getpot_cast_int<unsigned>(idx_nominus.size()); } 00358 inline const char* next_nominus(); 00359 inline std::string next_nominus_string(); 00360 00364 inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const; 00365 inline STRING_VECTOR unidentified_arguments(const std::set<std::string>& Knowns) const; 00366 inline STRING_VECTOR unidentified_arguments(const std::vector<std::string>& Knowns) const; 00367 inline STRING_VECTOR unidentified_arguments() const; 00368 00369 inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const; 00370 inline STRING_VECTOR unidentified_options(const std::set<std::string>& Knowns) const; 00371 inline STRING_VECTOR unidentified_options(const std::vector<std::string>& Knowns) const; 00372 inline STRING_VECTOR unidentified_options() const; 00373 00374 inline std::string unidentified_flags(const char* Known, int ArgumentNumber /* =-1 */) const; 00375 00376 inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const; 00377 inline STRING_VECTOR unidentified_variables(const std::set<std::string>& Knowns) const; 00378 inline STRING_VECTOR unidentified_variables(const std::vector<std::string>& Knowns) const; 00379 inline STRING_VECTOR unidentified_variables() const; 00380 00381 inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const; 00382 inline STRING_VECTOR unidentified_sections(const std::set<std::string>& Knowns) const; 00383 inline STRING_VECTOR unidentified_sections(const std::vector<std::string>& Knowns) const; 00384 inline STRING_VECTOR unidentified_sections() const; 00385 00386 inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const; 00387 inline STRING_VECTOR unidentified_nominuses(const std::set<std::string>& Knowns) const; 00388 inline STRING_VECTOR unidentified_nominuses(const std::vector<std::string>& Knowns) const; 00389 inline STRING_VECTOR unidentified_nominuses() const; 00390 00398 inline int print(std::ostream &out_stream = std::cout) const; 00399 00405 inline int print(const char *custom_prefix, 00406 std::ostream &out_stream = std::cout, 00407 unsigned int skip_count=1) const; 00408 00409 private: 00410 00415 struct variable 00416 { 00420 variable(); 00421 variable(const variable&); 00422 variable(const char* Name, const char* Value, const char* FieldSeparator); 00423 ~variable(); 00424 variable& operator=(const variable& Other); 00425 00426 void take(const char* Value, const char* FieldSeparator); 00427 00432 const std::string* get_element(unsigned Idx) const; 00433 00437 std::string name; // identifier of variable 00438 STRING_VECTOR value; // value of variable stored in vector 00439 std::string original; // value of variable as given on command line 00440 }; 00441 00445 std::string prefix; // prefix automatically added in queries 00446 std::string section; // (for dollar bracket parsing) 00447 STRING_VECTOR section_list; // list of all parsed sections 00448 00452 STRING_VECTOR argv; // vector of command line arguments stored as strings 00453 unsigned cursor; // cursor for argv 00454 bool search_loop_f; // shall search start at beginning after reaching end of arg array ? 00455 bool search_failed_f; // flag indicating a failed search() operation (e.g. next() functions react with 'missed') 00456 std::set<std::string> overridden_vars; // vector of variables that were supplied more than once during parsing 00457 00461 int nominus_cursor; // cursor for nominus_pointers 00462 std::vector<unsigned> idx_nominus; // indecies of 'no minus' arguments 00463 00467 std::vector<variable> variables; 00468 00472 std::string _comment_start; 00473 std::string _comment_end; 00474 00478 std::string _field_separator; 00479 00483 struct ltstr 00484 { 00485 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } 00486 }; 00487 00494 #if !defined(GETPOT_DISABLE_MUTEX) 00495 mutable libMesh::Threads::spin_mutex _getpot_mtx; 00496 #endif 00497 00506 mutable std::set<const char*, ltstr> _internal_string_container; 00507 00512 const char* _internal_managed_copy(const std::string& Arg) const; 00513 00518 mutable std::set<std::string> _requested_arguments; 00519 mutable std::set<std::string> _requested_variables; 00520 mutable std::set<std::string> _requested_sections; 00521 00522 bool request_recording_f; // speed: request recording can be turned off 00523 00530 void _record_argument_request(const std::string& Arg) const; 00531 void _record_variable_request(const std::string& Arg) const; 00532 00540 inline void _set_variable(const std::string& VarName, 00541 const std::string& Value, 00542 const bool Requested); 00543 00550 inline void _parse_argument_vector(const STRING_VECTOR& ARGV); 00551 00559 inline const variable* _find_variable(const char*) const; 00560 00564 inline const variable* _request_variable(const char*) const; 00565 00569 inline const char* _match_starting_string(const char* StartString); 00570 00574 inline bool _check_flags(const std::string& Str, const char* FlagList) const; 00575 00579 template<typename T> 00580 inline T _convert_to_type(const std::string& String, const T& Default) const; 00581 00582 inline std::string _convert_to_type(const std::string& String, const char* Default) const; 00583 00584 template<typename T> 00585 inline T _convert_to_type_no_default(const char* VarName, const std::string& String, const T& Default) const; 00586 00587 inline std::string _convert_to_type_no_default(const char* VarName, const std::string& String, const char* Default) const; 00588 00592 const std::string _get_remaining_string(const std::string& String, 00593 const std::string& Start) const; 00597 inline bool _search_string_vector(const STRING_VECTOR& Vec, 00598 const std::string& Str) const; 00599 00610 inline void _skip_whitespace(std::istream& istr); 00611 inline const std::string _get_next_token(std::istream& istr); 00612 inline const std::string _get_string(std::istream& istr); 00613 inline const std::string _get_until_closing_bracket(std::istream& istr); 00614 inline const std::string _get_until_closing_square_bracket(std::istream& istr); 00615 00616 inline STRING_VECTOR _read_in_stream(std::istream& istr); 00617 inline STRING_VECTOR _read_in_file(const std::string& FileName); 00618 inline std::string _process_section_label(const std::string& Section, 00619 STRING_VECTOR& section_stack); 00620 00624 std::string _DBE_expand_string(const std::string& str); 00625 std::string _DBE_expand(const std::string& str); 00626 const GetPot::variable* _DBE_get_variable(const std::string& str); 00627 STRING_VECTOR _DBE_get_expr_list(const std::string& str, const unsigned ExpectedNumber); 00628 00629 template <typename T> 00630 static std::string _convert_from_type(const T& Value) 00631 { 00632 std::ostringstream out_string; 00633 out_string << Value; 00634 return out_string.str(); 00635 } 00636 00641 static STRING_VECTOR _get_section_tree(const std::string& FullPath) 00642 { 00643 STRING_VECTOR result; 00644 for (std::size_t pos = 0; pos != FullPath.size(); ++pos) 00645 { 00646 if (FullPath[pos] == '/') 00647 result.push_back(FullPath.substr(0,pos)); 00648 } 00649 00650 return result; 00651 } 00652 }; 00653 00654 00656 // (*) constructors, destructor, assignment operator 00657 //............................................................................. 00658 // 00659 inline void 00660 GetPot::_basic_initialization() 00661 { 00662 cursor = 0; 00663 nominus_cursor = -1; 00664 search_failed_f = true; 00665 search_loop_f = true; 00666 prefix = ""; 00667 section = ""; 00668 00669 // automatic request recording for later ufo detection 00670 request_recording_f = true; 00671 00672 // comment start and end strings 00673 _comment_start = std::string("#"); 00674 _comment_end = std::string("\n"); 00675 00676 // default: separate vector elements by whitespaces 00677 _field_separator = " \t\n"; 00678 } 00679 00680 00681 00682 inline 00683 GetPot::GetPot() : 00684 prefix(), 00685 section(), 00686 section_list(), 00687 argv(), 00688 cursor(), 00689 search_loop_f(), 00690 search_failed_f(), 00691 nominus_cursor(), 00692 idx_nominus(), 00693 variables(), 00694 _comment_start(), 00695 _comment_end(), 00696 _field_separator(), 00697 #if !defined(GETPOT_DISABLE_MUTEX) 00698 _getpot_mtx(), 00699 #endif 00700 _internal_string_container(), 00701 _requested_arguments(), 00702 _requested_variables(), 00703 _requested_sections(), 00704 request_recording_f() 00705 { 00706 _basic_initialization(); 00707 } 00708 00709 00710 00711 inline 00712 GetPot::GetPot(const int argc_, const char * const * argv_, 00713 const char* FieldSeparator /* =0x0 */) : 00714 // leave 'char**' non-const to honor less capable compilers ... 00715 prefix(), 00716 section(), 00717 section_list(), 00718 argv(), 00719 cursor(), 00720 search_loop_f(), 00721 search_failed_f(), 00722 nominus_cursor(), 00723 idx_nominus(), 00724 variables(), 00725 _comment_start(), 00726 _comment_end(), 00727 _field_separator(), 00728 #if !defined(GETPOT_DISABLE_MUTEX) 00729 _getpot_mtx(), 00730 #endif 00731 _internal_string_container(), 00732 _requested_arguments(), 00733 _requested_variables(), 00734 _requested_sections(), 00735 request_recording_f() 00736 { 00737 this->parse_command_line(argc_, argv_, FieldSeparator); 00738 } 00739 00740 00741 00742 // leave 'char**' non-const to honor less capable compilers ... 00743 inline void 00744 GetPot::parse_command_line(const int argc_, const char * const * argv_, 00745 const char* FieldSeparator /* =0x0 */) 00746 { 00747 _basic_initialization(); 00748 00749 // if specified -> overwrite default string 00750 if (FieldSeparator) 00751 _field_separator = std::string(FieldSeparator); 00752 00753 // -- make an internal copy of the argument list: 00754 STRING_VECTOR _apriori_argv; 00755 // -- for the sake of clarity: we do want to include the first 00756 // argument of the first parsing source in the argument vector! 00757 // it will not be a nominus argument, though. This gives us a 00758 // minimum vector size of one which facilitates error checking 00759 // in many functions. Also the user will be able to retrieve 00760 // the name of his application or input file by "get[0]" 00761 _apriori_argv.push_back(std::string(argv_[0])); 00762 for (int i=1; i<argc_; i++) 00763 { 00764 std::string tmp(argv_[i]); // recall the problem with temporaries, 00765 _apriori_argv.push_back(tmp); // reference counting in arguement lists ... 00766 } 00767 _parse_argument_vector(_apriori_argv); 00768 } 00769 00770 00771 00772 inline 00773 GetPot::GetPot(const char* FileName, 00774 const char* CommentStart /* = 0x0 */, const char* CommentEnd /* = 0x0 */, 00775 const char* FieldSeparator/* = 0x0 */) : 00776 prefix(), 00777 section(), 00778 section_list(), 00779 argv(), 00780 cursor(), 00781 search_loop_f(), 00782 search_failed_f(), 00783 nominus_cursor(), 00784 idx_nominus(), 00785 variables(), 00786 _comment_start(), 00787 _comment_end(), 00788 _field_separator(), 00789 #if !defined(GETPOT_DISABLE_MUTEX) 00790 _getpot_mtx(), 00791 #endif 00792 _internal_string_container(), 00793 _requested_arguments(), 00794 _requested_variables(), 00795 _requested_sections(), 00796 request_recording_f() 00797 { 00798 const std::string& StrCommentStart = CommentStart ? CommentStart : std::string("#"); 00799 const std::string& StrCommentEnd = CommentEnd ? CommentEnd : std::string("\n"); 00800 const std::string& StrFieldSeparator = FieldSeparator ? FieldSeparator : std::string(" \t\n"); 00801 this->parse_input_file(FileName, StrCommentStart, StrCommentEnd, StrFieldSeparator); 00802 } 00803 00804 00805 00806 inline 00807 GetPot::GetPot(const std::string& FileName, 00808 const std::string& CommentStart, 00809 const std::string& CommentEnd, 00810 const std::string& FieldSeparator) : 00811 prefix(), 00812 section(), 00813 section_list(), 00814 argv(), 00815 cursor(), 00816 search_loop_f(), 00817 search_failed_f(), 00818 nominus_cursor(), 00819 idx_nominus(), 00820 variables(), 00821 _comment_start(), 00822 _comment_end(), 00823 _field_separator(), 00824 #if !defined(GETPOT_DISABLE_MUTEX) 00825 _getpot_mtx(), 00826 #endif 00827 _internal_string_container(), 00828 _requested_arguments(), 00829 _requested_variables(), 00830 _requested_sections(), 00831 request_recording_f() 00832 { 00833 this->parse_input_file(FileName, CommentStart, CommentEnd, FieldSeparator); 00834 } 00835 00836 00837 00838 inline void 00839 GetPot::parse_input_file(const std::string& FileName, 00840 const std::string& CommentStart, 00841 const std::string& CommentEnd, 00842 const std::string& FieldSeparator) 00843 { 00844 _basic_initialization(); 00845 00846 // overwrite default strings 00847 _comment_start = std::string(CommentStart); 00848 _comment_end = std::string(CommentEnd); 00849 _field_separator = FieldSeparator; 00850 00851 STRING_VECTOR _apriori_argv; 00852 // -- the first element of the argument vector stores the name of 00853 // the first parsing source; however, this element is not 00854 // parsed for variable assignments or nominuses. 00855 // 00856 // Regardless, we don't add more than one name to the argument 00857 // vector. 00858 _apriori_argv.push_back(FileName); 00859 00860 STRING_VECTOR args = _read_in_file(FileName); 00861 _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end()); 00862 _parse_argument_vector(_apriori_argv); 00863 } 00864 00865 00866 00867 inline 00868 GetPot::GetPot(const GetPot& Other) : 00869 prefix(Other.prefix), 00870 section(Other.section), 00871 section_list(Other.section_list), 00872 argv(Other.argv), 00873 cursor(Other.cursor), 00874 search_loop_f(Other.search_loop_f), 00875 search_failed_f(Other.search_failed_f), 00876 overridden_vars(), 00877 nominus_cursor(Other.nominus_cursor), 00878 idx_nominus(Other.idx_nominus), 00879 variables(Other.variables), 00880 _comment_start(Other._comment_start), 00881 _comment_end(Other._comment_end), 00882 _field_separator(Other._field_separator), 00883 // #if !defined(GETPOT_DISABLE_MUTEX) 00884 // _getpot_mtx(Other._getpot_mtx), 00885 // #endif 00886 _internal_string_container(), 00887 _requested_arguments(Other._requested_arguments), 00888 _requested_variables(Other._requested_variables), 00889 _requested_sections(Other._requested_sections), 00890 request_recording_f(Other.request_recording_f) 00891 { 00892 std::set<const char*,ltstr>::const_iterator it = 00893 Other._internal_string_container.begin(); 00894 00895 const std::set<const char*,ltstr>::const_iterator end = 00896 Other._internal_string_container.end(); 00897 00898 for (; it != end; ++it) 00899 { 00900 const char* otherstr = *it; 00901 char* newcopy = new char[strlen(otherstr)+1]; 00902 strncpy(newcopy, otherstr, strlen(otherstr)+1); 00903 this->_internal_string_container.insert(newcopy); 00904 } 00905 } 00906 00907 00908 00909 inline 00910 GetPot::~GetPot() 00911 { 00912 // may be some return strings had to be created, delete now ! 00913 std::set<const char*, ltstr>::const_iterator it = _internal_string_container.begin(); 00914 const std::set<const char*, ltstr>::const_iterator end = _internal_string_container.end(); 00915 for (; it != end; ++it) 00916 delete [] *it; 00917 } 00918 00919 00920 00921 inline GetPot& 00922 GetPot::operator=(const GetPot& Other) 00923 { 00924 if (&Other == this) 00925 return *this; 00926 00927 prefix = Other.prefix; 00928 section = Other.section; 00929 section_list = Other.section_list; 00930 argv = Other.argv; 00931 cursor = Other.cursor; 00932 search_loop_f = Other.search_loop_f; 00933 search_failed_f = Other.search_failed_f; 00934 nominus_cursor = Other.nominus_cursor; 00935 overridden_vars = Other.overridden_vars; 00936 idx_nominus = Other.idx_nominus; 00937 variables = Other.variables; 00938 _comment_start = Other._comment_start; 00939 _comment_end = Other._comment_end; 00940 _field_separator = Other._field_separator; 00941 // #if !defined(GETPOT_DISABLE_MUTEX) 00942 // _getpot_mtx = Other._getpot_mtx; 00943 // #endif 00944 _requested_arguments = Other._requested_arguments; 00945 _requested_variables = Other._requested_variables; 00946 _requested_sections = Other._requested_sections; 00947 request_recording_f = Other.request_recording_f; 00948 00949 std::set<const char*, ltstr>::const_iterator my_it = 00950 _internal_string_container.begin(); 00951 const std::set<const char*, ltstr>::const_iterator my_end = 00952 _internal_string_container.end(); 00953 00954 for (; my_it != my_end; ++my_it) 00955 delete [] *my_it; 00956 00957 _internal_string_container.clear(); 00958 00959 std::set<const char*,ltstr>::const_iterator it = 00960 Other._internal_string_container.begin(); 00961 const std::set<const char*,ltstr>::const_iterator end = 00962 Other._internal_string_container.end(); 00963 00964 for (; it != end; ++it) 00965 { 00966 const char* otherstr = *it; 00967 char* newcopy = new char[strlen(otherstr)+1]; 00968 strncpy(newcopy, otherstr, strlen(otherstr)+1); 00969 this->_internal_string_container.insert(newcopy); 00970 } 00971 00972 return *this; 00973 } 00974 00975 00976 00977 inline void 00978 GetPot::absorb(const GetPot& Other) 00979 { 00980 if (&Other == this) 00981 return; 00982 00983 // variables that are not influenced by absorption: 00984 // _comment_start 00985 // _comment_end 00986 // cursor 00987 // nominus_cursor 00988 // search_failed 00989 // idx_nominus 00990 // search_loop_f 00991 argv = Other.argv; 00992 variables = Other.variables; 00993 00994 if (request_recording_f) 00995 { 00996 // Get a lock before touching anything mutable 00997 SCOPED_MUTEX; 00998 00999 _requested_arguments.insert(Other._requested_arguments.begin(), Other._requested_arguments.end()); 01000 _requested_variables.insert(Other._requested_variables.begin(), Other._requested_variables.end()); 01001 _requested_sections.insert(Other._requested_sections.begin(), Other._requested_sections.end()); 01002 } 01003 } 01004 01005 01006 01007 inline void 01008 GetPot::clear_requests() 01009 { 01010 // Get a lock before touching anything mutable 01011 SCOPED_MUTEX; 01012 01013 _requested_arguments.clear(); 01014 _requested_variables.clear(); 01015 _requested_sections.clear(); 01016 } 01017 01018 01019 01020 inline void 01021 GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV) 01022 { 01023 if (ARGV.empty()) 01024 return; 01025 01026 // build internal databases: 01027 // 1) array with no-minus arguments (usually used as filenames) 01028 // 2) variable assignments: 01029 // 'variable name' '=' number | string 01030 STRING_VECTOR section_stack; 01031 STRING_VECTOR::const_iterator it = ARGV.begin(); 01032 01033 01034 section = ""; 01035 01036 // -- do not parse the first argument, so that this parsing source 01037 // name is not interpreted a s a nominus or so. If we already 01038 // have parsed arguments, don't bother adding another parsing 01039 // source name 01040 if (argv.empty()) 01041 argv.push_back(*it); 01042 ++it; 01043 01044 // -- loop over remaining arguments 01045 for (; it != ARGV.end(); ++it) 01046 { 01047 std::string arg = *it; 01048 01049 if (arg.length() == 0) 01050 continue; 01051 01052 // -- [section] labels and [include file] directives 01053 if (arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']') 01054 { 01055 01056 // Is this an include file directive? 01057 std::size_t include_pos = arg.find("include ", 1); 01058 if (include_pos != std::string::npos) 01059 { 01060 01061 const std::string includefile = 01062 _DBE_expand_string(arg.substr(9, arg.length()-9-include_pos)); 01063 01064 this->parse_input_file 01065 (includefile, _comment_start, _comment_end, _field_separator); 01066 } 01067 01068 else 01069 { 01070 // (*) sections are considered 'requested arguments' 01071 if (request_recording_f) 01072 { 01073 // Get a lock before touching anything mutable 01074 SCOPED_MUTEX; 01075 01076 _requested_arguments.insert(arg); 01077 } 01078 01079 const std::string Name = _DBE_expand_string(arg.substr(1, arg.length()-2)); 01080 section = _process_section_label(Name, section_stack); 01081 // new section --> append to list of sections 01082 if (find(section_list.begin(), section_list.end(), section) == section_list.end()) 01083 if (section.length() != 0) section_list.push_back(section); 01084 argv.push_back(arg); 01085 } 01086 } 01087 else 01088 { 01089 arg = section + _DBE_expand_string(arg); 01090 argv.push_back(arg); 01091 } 01092 01093 // -- separate array for nominus arguments 01094 if (arg[0] != '-') 01095 idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1)); 01096 01097 // -- variables: does arg contain a '=' operator ? 01098 const std::size_t equals_pos = arg.find_first_of('='); 01099 if (equals_pos != std::string::npos) 01100 { 01101 // (*) record for later ufo detection 01102 // arguments carriying variables are always treated as 'requested' arguments. 01103 // unrequested variables have to be detected with the ufo-variable 01104 // detection routine. 01105 if (request_recording_f) 01106 { 01107 // Get a lock before touching anything mutable 01108 SCOPED_MUTEX; 01109 01110 _requested_arguments.insert(arg); 01111 } 01112 01113 // => arg (from start to '=') = Name of variable 01114 // (from '=' to end) = value of variable 01115 _set_variable(arg.substr(0,equals_pos), 01116 arg.substr(equals_pos+1), false); 01117 } 01118 } 01119 } 01120 01121 01122 01123 inline STRING_VECTOR 01124 GetPot::_read_in_file(const std::string& FileName) 01125 { 01126 std::ifstream i(FileName.c_str()); 01127 01128 // if (!i) return STRING_VECTOR(); 01129 01130 if (!i) 01131 libmesh_file_error(FileName); 01132 01133 // argv[0] == the filename of the file that was read in 01134 return _read_in_stream(i); 01135 } 01136 01137 01138 01139 inline STRING_VECTOR 01140 GetPot::_read_in_stream(std::istream& istr) 01141 { 01142 STRING_VECTOR brute_tokens; 01143 while (istr) 01144 { 01145 _skip_whitespace(istr); 01146 const std::string Token = _get_next_token(istr); 01147 // Allow 'keyword =' to parse with an empty string as value. 01148 // Only break at EOF. 01149 // if (Token.length() == 0 || Token[0] == EOF) break; 01150 if (Token[0] == EOF) 01151 break; 01152 brute_tokens.push_back(Token); 01153 } 01154 01155 // -- reduce expressions of token1'='token2 to a single 01156 // string 'token1=token2' 01157 // -- copy everything into 'argv' 01158 // -- arguments preceded by something like '[' name ']' (section) 01159 // produce a second copy of each argument with a prefix '[name]argument' 01160 unsigned i1 = 0; 01161 unsigned i2 = 1; 01162 unsigned i3 = 2; 01163 01164 STRING_VECTOR arglist; 01165 while (i1 < brute_tokens.size()) 01166 { 01167 // 1) concatenate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef' 01168 // note: java.lang.String: substring(a,b) = from a to b-1 01169 // C++ string: substr(a,b) = from a to a + b 01170 std::string result; 01171 if (i2 < brute_tokens.size() && brute_tokens[i2] == "=") 01172 { 01173 if (i3 >= brute_tokens.size()) 01174 result = brute_tokens[i1] + brute_tokens[i2]; 01175 else 01176 result = brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3]; 01177 i1 = i3+1; i2 = i3+2; i3 = i3+3; 01178 } 01179 else if (i2 < brute_tokens.size() && 01180 brute_tokens[i2].length() > 0 && 01181 brute_tokens[i2][0] == '=') 01182 { 01183 // This case should not be hit if '=' at the beginning of a word 01184 // is always separated into its own word 01185 result = brute_tokens[i1] + brute_tokens[i2]; 01186 i1 = i3; i2 = i3+1; i3 = i3+2; 01187 } 01188 else if (i2 < brute_tokens.size() && brute_tokens[i1][brute_tokens[i1].size()-1] == '=') 01189 { 01190 result = brute_tokens[i1] + brute_tokens[i2]; 01191 i1 = i3; i2 = i3+1; i3 = i3+2; 01192 } 01193 else 01194 { 01195 result = brute_tokens[i1]; 01196 i1=i2; i2=i3; i3++; 01197 } 01198 01199 // Now strip out any comment 01200 size_t comment_start_loc = result.find(_comment_start, 0); 01201 if (comment_start_loc != std::string::npos) 01202 result = result.substr(0, comment_start_loc); 01203 01204 arglist.push_back(result); 01205 } 01206 return arglist; 01207 } 01208 01209 01210 01211 inline void 01212 GetPot::_skip_whitespace(std::istream& istr) 01213 { 01214 // find next non-whitespace while deleting comments 01215 int tmp = istr.get(); 01216 do { 01217 // -- search a non whitespace 01218 while (isspace(tmp)) 01219 { 01220 tmp = istr.get(); 01221 if (!istr) 01222 return; 01223 } 01224 01225 // -- look if characters match the comment starter string 01226 for (unsigned i=0; i<_comment_start.length() ; i++) 01227 { 01228 if (tmp != _comment_start[i]) 01229 { 01230 // -- one step more backwards, since 'tmp' already at non-whitespace 01231 istr.unget(); 01232 return; 01233 } 01234 01235 // RHS: Why is this here? It breaks on empty comments 01236 // tmp = istr.get(); 01237 // if (!istr) { istr.unget(); return; } 01238 } 01239 // 'tmp' contains last character of _comment_starter 01240 01241 // -- comment starter found -> search for comment ender 01242 unsigned match_no=0; 01243 while (true) 01244 { 01245 tmp = istr.get(); 01246 if (!istr) 01247 { 01248 istr.unget(); 01249 return; 01250 } 01251 01252 if (tmp == _comment_end[match_no]) 01253 { 01254 match_no++; 01255 if (match_no == _comment_end.length()) 01256 { 01257 istr.unget(); 01258 break; // shuffle more whitespace, end of comment found 01259 } 01260 } 01261 else 01262 match_no = 0; 01263 } 01264 01265 tmp = istr.get(); 01266 01267 } while (istr); 01268 istr.unget(); 01269 } 01270 01271 01272 01273 inline const std::string 01274 GetPot::_get_next_token(std::istream& istr) 01275 { 01276 // get next concatenates string token. consider quotes that embrace 01277 // whitespaces 01278 std::string token; 01279 int tmp = 0; 01280 while (true) 01281 { 01282 int last_letter = tmp; 01283 tmp = istr.get(); 01284 01285 if (tmp == '=') 01286 { 01287 // Always break at '='. 01288 // This separates '=' at the beginning of a word into its own word. 01289 token += getpot_cast_int<char>(tmp); 01290 return token; 01291 } 01292 01293 else if (tmp == EOF || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\')) 01294 return token; 01295 01296 else if (tmp == '\'' && last_letter != '\\') 01297 { 01298 // QUOTES: un-backslashed quotes => it's a string 01299 token += _get_string(istr); 01300 continue; 01301 } 01302 01303 else if (tmp == '{' && last_letter == '$') 01304 { 01305 token += '{' + _get_until_closing_bracket(istr); 01306 continue; 01307 } 01308 01309 else if (tmp == '[') 01310 { 01311 token += '[' + _get_until_closing_square_bracket(istr); 01312 continue; 01313 } 01314 01315 else if (tmp == '$' && last_letter == '\\') 01316 { 01317 token += getpot_cast_int<char>(tmp); tmp = 0; // so that last_letter will become = 0, not '$'; 01318 continue; 01319 } 01320 01321 else if (tmp == '\\' && last_letter != '\\') 01322 continue; // don't append un-backslashed backslashes 01323 01324 token += getpot_cast_int<char>(tmp); 01325 } 01326 } 01327 01328 01329 01330 inline const std::string 01331 GetPot::_get_string(std::istream& istr) 01332 { 01333 // parse input until next matching ' 01334 std::string str; 01335 int tmp = 0; 01336 while (true) 01337 { 01338 int last_letter = tmp; 01339 tmp = istr.get(); 01340 if (tmp == EOF) 01341 return str; 01342 01343 // un-backslashed quotes => it's the end of the string 01344 else if (tmp == '\'' && last_letter != '\\') 01345 return str; 01346 01347 else if (tmp == '\\' && last_letter != '\\') 01348 continue; // don't append 01349 01350 str += getpot_cast_int<char>(tmp); 01351 } 01352 } 01353 01354 01355 01356 inline const std::string 01357 GetPot::_get_until_closing_bracket(std::istream& istr) 01358 { 01359 // parse input until next matching } 01360 std::string str = ""; 01361 int tmp = 0; 01362 int brackets = 1; 01363 while (true) 01364 { 01365 int last_letter = tmp; 01366 tmp = istr.get(); 01367 if (tmp == EOF) 01368 return str; 01369 01370 else if (tmp == '{' && last_letter == '$') 01371 brackets += 1; 01372 01373 else if (tmp == '}') 01374 { 01375 brackets -= 1; 01376 // un-backslashed brackets => it's the end of the string 01377 if (brackets == 0) 01378 return str + '}'; 01379 01380 else if (tmp == '\\' && last_letter != '\\') 01381 continue; // do not append an unbackslashed backslash 01382 } 01383 str += getpot_cast_int<char>(tmp); 01384 } 01385 } 01386 01387 01388 01389 inline const std::string 01390 GetPot::_get_until_closing_square_bracket(std::istream& istr) 01391 { 01392 // parse input until next matching ] 01393 std::string str = ""; 01394 int brackets = 1; 01395 while (true) 01396 { 01397 int tmp = istr.get(); 01398 if (tmp == EOF) 01399 return str; 01400 01401 else if (tmp == '[') 01402 brackets += 1; 01403 01404 else if (tmp == ']') 01405 { 01406 brackets -= 1; 01407 if (brackets == 0) 01408 return str + ']'; 01409 } 01410 01411 str += getpot_cast_int<char>(tmp); 01412 } 01413 } 01414 01415 01416 01417 inline std::string 01418 GetPot::_process_section_label(const std::string& Section, 01419 STRING_VECTOR& section_stack) 01420 { 01421 std::string sname = Section; 01422 // 1) subsection of actual section ('./' prefix) 01423 if (sname.length() >= 2 && sname.substr(0, 2) == "./") 01424 sname = sname.substr(2); 01425 01426 // 2) subsection of parent section ('../' prefix) 01427 else if (sname.length() >= 3 && sname.substr(0, 3) == "../") 01428 { 01429 do 01430 { 01431 if (section_stack.end() != section_stack.begin()) 01432 section_stack.pop_back(); 01433 sname = sname.substr(3); 01434 } while (sname.substr(0, 3) == "../"); 01435 } 01436 01437 // 3) subsection of the root-section 01438 else 01439 // [] => back to root section 01440 section_stack.erase(section_stack.begin(), section_stack.end()); 01441 01442 if (sname != "") 01443 { 01444 // parse section name for 'slashes' 01445 unsigned i=0; 01446 while (i < sname.length()) 01447 { 01448 if (sname[i] == '/') 01449 { 01450 section_stack.push_back(sname.substr(0,i)); 01451 if (i+1 < sname.length()) 01452 sname = sname.substr(i+1); 01453 i = 0; 01454 } 01455 else 01456 i++; 01457 } 01458 section_stack.push_back(sname); 01459 } 01460 01461 std::string section_label = ""; 01462 if (!section_stack.empty()) 01463 { 01464 victorate(std::string, section_stack, it) 01465 section_label += *it + "/"; 01466 } 01467 return section_label; 01468 } 01469 01470 01471 01472 // Use C++ istream/ostream to handle most type conversions. 01473 template <typename T> 01474 inline T 01475 GetPot::_convert_to_type(const std::string& String, const T& Default) const 01476 { 01477 std::istringstream in_string(String); 01478 T retval; 01479 in_string >> retval; 01480 if (in_string.fail()) 01481 retval = Default; 01482 return retval; 01483 } 01484 01485 01486 01487 // copy string - operator>> would have stopped upon seeing whitespace! 01488 template <> 01489 inline std::string 01490 GetPot::_convert_to_type(const std::string& String, const std::string&) const 01491 { 01492 return String; 01493 } 01494 01495 01496 01497 // copy string 01498 inline std::string 01499 GetPot::_convert_to_type(const std::string& String, const char*) const 01500 { 01501 return String; 01502 } 01503 01504 01505 01506 // be more liberal than std C++ in what we interpret as a boolean 01507 template<> 01508 inline bool 01509 GetPot::_convert_to_type<bool>(const std::string& String, const bool& Default) const 01510 { 01511 std::string newstring(String); 01512 //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper); 01513 for (unsigned int i=0; i<newstring.length(); ++i) 01514 newstring[i] = getpot_cast_int<char>(toupper(newstring[i])); 01515 01516 // "true"/"True"/"TRUE" should work 01517 if (newstring.find("TRUE")!=std::string::npos) 01518 return true; 01519 01520 if (newstring.find("FALSE")!=std::string::npos) 01521 return false; 01522 01523 // And if we don't find that, let's search for an integer and use C unsigned 01524 // int->bool conversion before giving up; i.e. a user could specify "0" for 01525 // false or "1" for true 01526 std::istringstream in_string(String); 01527 unsigned int retval; 01528 in_string >> retval; 01529 if (in_string.fail()) 01530 return Default; 01531 01532 return retval; 01533 } 01534 01535 01536 01537 // Use C++ istream/ostream to handle most type conversions. 01538 template <typename T> 01539 inline T 01540 GetPot::_convert_to_type_no_default(const char* VarName, const std::string& String, const T&) const 01541 { 01542 std::istringstream in_string(String); 01543 T retval; 01544 in_string >> retval; 01545 if (in_string.fail()) 01546 { 01547 getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl; 01548 getpot_cerr <<" value = "<<String<<" expected type = "<<typeid(T).name()<<std::endl; 01549 getpot_error(); 01550 } 01551 return retval; 01552 } 01553 01554 01555 01556 // copy string - operator>> would have stopped upon seeing whitespace! 01557 template <> 01558 inline std::string 01559 GetPot::_convert_to_type_no_default(const char*, const std::string& String, const std::string&) const 01560 { 01561 return String; 01562 } 01563 01564 01565 01566 // copy string 01567 inline std::string 01568 GetPot::_convert_to_type_no_default(const char*, const std::string& String, const char*) const 01569 { 01570 return String; 01571 } 01572 01573 01574 01575 // be more liberal than std C++ in what we interpret as a boolean 01576 template<> 01577 inline bool 01578 GetPot::_convert_to_type_no_default<bool>(const char* VarName, const std::string& String, const bool&) const 01579 { 01580 std::string newstring(String); 01581 //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper); 01582 for (unsigned int i=0; i<newstring.length(); ++i) 01583 { 01584 newstring[i]=getpot_cast_int<char>(toupper(newstring[i])); 01585 } 01586 01587 // "true"/"True"/"TRUE" should work 01588 if (newstring.find("TRUE")!=std::string::npos) 01589 return true; 01590 01591 if (newstring.find("FALSE")!=std::string::npos) 01592 return false; 01593 01594 // And if we don't find that, let's search for an integer and use C unsigned 01595 // int->bool conversion before giving up; i.e. a user could specify "0" for 01596 // false or "1" for true 01597 std::istringstream in_string(String); 01598 unsigned int retval; 01599 in_string >> retval; 01600 if (in_string.fail()) 01601 { 01602 getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl; 01603 getpot_cerr <<" value = "<<String<<" expected type = "<<typeid(bool).name()<<std::endl; 01604 getpot_error(); 01605 } 01606 01607 return retval; 01608 } 01609 01610 01611 01612 inline const char* 01613 GetPot::_internal_managed_copy(const std::string& Arg) const 01614 { 01615 const char* arg = Arg.c_str(); 01616 01617 // Get a lock before touching anything mutable 01618 SCOPED_MUTEX; 01619 01620 // See if there's already an identical string saved 01621 std::set<const char*,ltstr>::const_iterator it = 01622 _internal_string_container.find(arg); 01623 01624 // If so, return it 01625 if (it != _internal_string_container.end()) 01626 return *it; 01627 01628 // Otherwise, create a new one 01629 char* newcopy = new char[strlen(arg)+1]; 01630 strncpy(newcopy, arg, strlen(arg)+1); 01631 _internal_string_container.insert(newcopy); 01632 return newcopy; 01633 } 01634 01635 01636 01638 // (*) cursor oriented functions 01639 //............................................................................. 01640 01641 // Checks if 'String' begins with 'Start' and returns the remaining String. 01642 // Returns None if String does not begin with Start. 01643 inline const std::string 01644 GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const 01645 { 01646 if (Start == "") 01647 return String; 01648 01649 // note: java.lang.String: substring(a,b) = from a to b-1 01650 // C++ string: substr(a,b) = from a to a + b 01651 if (String.find(Start) == 0) 01652 return String.substr(Start.length()); 01653 01654 else 01655 return ""; 01656 } 01657 01658 01659 01660 // -- search for a certain argument and set cursor to position 01661 inline bool 01662 GetPot::search(const std::string &Option) 01663 { 01664 return search(Option.c_str()); 01665 } 01666 01667 01668 01669 // -- search for a certain argument and set cursor to position 01670 inline bool 01671 GetPot::search(const char* Option) 01672 { 01673 unsigned OldCursor = cursor; 01674 const std::string SearchTerm = prefix + Option; 01675 01676 // (*) record requested arguments for later ufo detection 01677 _record_argument_request(SearchTerm); 01678 01679 if (OldCursor >= argv.size()) 01680 OldCursor = getpot_cast_int<unsigned>(argv.size() - 1); 01681 search_failed_f = true; 01682 01683 // (*) first loop from cursor position until end 01684 for (unsigned c = cursor; c < argv.size(); c++) 01685 { 01686 if (argv[c] == SearchTerm) 01687 { 01688 cursor = c; 01689 search_failed_f = false; 01690 return true; 01691 } 01692 } 01693 if (!search_loop_f) 01694 return false; 01695 01696 // (*) second loop from 0 to old cursor position 01697 for (unsigned c = 1; c < OldCursor; c++) 01698 { 01699 if (argv[c] == SearchTerm) 01700 { 01701 cursor = c; 01702 search_failed_f = false; 01703 return true; 01704 } 01705 } 01706 01707 // in case nothing is found the cursor stays where it was 01708 return false; 01709 } 01710 01711 01712 01713 inline bool 01714 GetPot::search(unsigned No, const char* P, ...) 01715 { 01716 // (*) recording the requested arguments happens in subroutine 'search' 01717 if (No == 0) 01718 return false; 01719 01720 // search for the first argument 01721 if (search(P) == true) 01722 return true; 01723 01724 // start interpreting variable argument list 01725 va_list ap; 01726 va_start(ap, P); 01727 unsigned i = 1; 01728 for (; i < No; i++) 01729 { 01730 char* Opt = va_arg(ap, char *); 01731 // (*) search records itself for later ufo detection 01732 if (search(Opt) == true) 01733 break; 01734 } 01735 01736 if (i < No) 01737 { 01738 i++; 01739 // loop was left before end of array --> hit but 01740 // make sure that the rest of the search terms is marked 01741 // as requested. 01742 for (; i < No; i++) 01743 { 01744 char* Opt = va_arg(ap, char *); 01745 // (*) record requested arguments for later ufo detection 01746 _record_argument_request(Opt); 01747 } 01748 va_end(ap); 01749 return true; 01750 } 01751 01752 va_end(ap); 01753 // loop was left normally --> no hit 01754 return false; 01755 } 01756 01757 01758 01759 inline void 01760 GetPot::reset_cursor() 01761 { 01762 search_failed_f = false; 01763 cursor = 0; 01764 } 01765 01766 01767 01768 inline void 01769 GetPot::init_multiple_occurrence() 01770 { 01771 disable_loop(); 01772 reset_cursor(); 01773 } 01774 01775 01776 01778 // (*) direct access to command line arguments 01779 //............................................................................. 01780 // 01781 inline const char* 01782 GetPot::operator[](unsigned idx) const 01783 { 01784 return idx<argv.size() ? argv[idx].c_str() : 0; 01785 } 01786 01787 01788 01789 template <typename T> 01790 inline T 01791 GetPot::get(unsigned int Idx, const T& Default) const 01792 { 01793 if (Idx >= argv.size()) 01794 return Default; 01795 return _convert_to_type(argv[Idx], Default); 01796 } 01797 01798 01799 01800 inline const char* 01801 GetPot::get(unsigned int Idx, const char* Default) const 01802 { 01803 if (Idx >= argv.size()) 01804 return Default; 01805 return argv[Idx].c_str(); 01806 } 01807 01808 01809 01810 inline unsigned 01811 GetPot::size() const 01812 { 01813 return getpot_cast_int<unsigned>(argv.size()); 01814 } 01815 01816 01817 01818 // -- next() function group 01819 template <typename T> 01820 inline T 01821 GetPot::next(const T& Default) 01822 { 01823 if (search_failed_f) 01824 return Default; 01825 cursor++; 01826 if (cursor >= argv.size()) 01827 { 01828 cursor = getpot_cast_int<unsigned>(argv.size()); 01829 return Default; 01830 } 01831 01832 // (*) record requested argument for later ufo detection 01833 _record_argument_request(argv[cursor]); 01834 01835 const std::string Remain = _get_remaining_string(argv[cursor], prefix); 01836 01837 return Remain != "" ? _convert_to_type(Remain, Default) : Default; 01838 } 01839 01840 01841 01842 inline const char* 01843 GetPot::next(const char* Default) 01844 { 01845 return _internal_managed_copy(next(std::string(Default))); 01846 } 01847 01848 01849 01850 // -- follow() function group 01851 // distinct option to be searched for 01852 template <typename T> 01853 inline T 01854 GetPot::follow(const T& Default, const char* Option) 01855 { 01856 // (*) record requested of argument is entirely handled in 'search()' and 'next()' 01857 if (search(Option) == false) 01858 return Default; 01859 01860 return next(Default); 01861 } 01862 01863 01864 01865 inline const char* 01866 GetPot::follow(const char* Default, const char* Option) 01867 { 01868 return _internal_managed_copy(follow(std::string(Default), Option)); 01869 } 01870 01871 01872 01873 // -- second follow() function group 01874 // multiple option to be searched for 01875 template <typename T> 01876 inline T 01877 GetPot::follow(const T& Default, unsigned int No, const char* P, ...) 01878 { 01879 // (*) record requested of argument is entirely handled in 'search()' and 'next()' 01880 if (No == 0) 01881 return Default; 01882 01883 if (search(P) == true) 01884 return next(Default); 01885 01886 va_list ap; 01887 va_start(ap, P); 01888 for (unsigned i=1; i<No; i++) 01889 { 01890 char* Opt = va_arg(ap, char *); 01891 if (search(Opt) == true) 01892 { 01893 va_end(ap); 01894 return next(Default); 01895 } 01896 } 01897 va_end(ap); 01898 return Default; 01899 } 01900 01901 01902 01903 inline const char* 01904 GetPot::follow(const char* Default, unsigned No, const char* P, ...) 01905 { 01906 // (*) record requested of argument is entirely handled in 'search()' and 'next()' 01907 if (No == 0) 01908 return Default; 01909 01910 if (search(P) == true) 01911 return next(Default); 01912 01913 va_list ap; 01914 va_start(ap, P); 01915 for (unsigned i=1; i<No; i++) 01916 { 01917 char* Opt = va_arg(ap, char *); 01918 if (search(Opt) == true) 01919 { 01920 va_end(ap); 01921 return next(Default); 01922 } 01923 } 01924 va_end(ap); 01925 return Default; 01926 } 01927 01928 01929 01931 // (*) directly connected options 01932 //............................................................................. 01933 // 01934 template <typename T> 01935 inline T 01936 GetPot::direct_follow(const T& Default, const char* Option) 01937 { 01938 const char* FollowStr = _match_starting_string(Option); 01939 01940 // (*) record requested of argument for later ufo-detection 01941 _record_argument_request(std::string(Option) + FollowStr); 01942 01943 if (FollowStr == 0) 01944 return Default; 01945 01946 if (++cursor >= argv.size()) 01947 cursor = getpot_cast_int<unsigned>(argv.size()); 01948 return _convert_to_type(FollowStr, Default); 01949 } 01950 01951 01952 01953 inline const char* 01954 GetPot::direct_follow(const char* Default, const char* Option) 01955 { 01956 return _internal_managed_copy(direct_follow(std::string(Default), Option)); 01957 } 01958 01959 01960 01961 // pointer to the place where the string after 01962 // the match inside the found argument starts. 01963 // 0 no argument matches the starting string. 01964 inline const char* 01965 GetPot::_match_starting_string(const char* StartString) 01966 { 01967 const unsigned N = 01968 getpot_cast_int<unsigned>(strlen(StartString)); 01969 unsigned OldCursor = cursor; 01970 01971 if (OldCursor >= argv.size()) 01972 OldCursor = getpot_cast_int<unsigned>(argv.size() - 1); 01973 search_failed_f = true; 01974 01975 // (*) first loop from cursor position until end 01976 for (unsigned c = cursor; c < argv.size(); c++) 01977 { 01978 if (strncmp(StartString, argv[c].c_str(), N) == 0) 01979 { 01980 cursor = c; 01981 search_failed_f = false; 01982 return &(argv[c].c_str()[N]); 01983 } 01984 } 01985 01986 if (!search_loop_f) 01987 return NULL; 01988 01989 // (*) second loop from 0 to old cursor position 01990 for (unsigned c = 1; c < OldCursor; c++) 01991 { 01992 if (strncmp(StartString, argv[c].c_str(), N) == 0) 01993 { 01994 cursor = c; 01995 search_failed_f = false; 01996 return &(argv[c].c_str()[N]); 01997 } 01998 } 01999 return 0; 02000 } 02001 02002 02003 02005 // (*) search for flags 02006 //............................................................................. 02007 // 02008 inline bool 02009 GetPot::options_contain(const char* FlagList) const 02010 { 02011 // go through all arguments that start with a '-' (but not '--') 02012 std::string str; 02013 STRING_VECTOR::const_iterator it = argv.begin(); 02014 for (; it != argv.end(); ++it) 02015 { 02016 str = _get_remaining_string(*it, prefix); 02017 02018 if (str.length() >= 2 && str[0] == '-' && str[1] != '-') 02019 if (_check_flags(str, FlagList)) 02020 return true; 02021 } 02022 return false; 02023 } 02024 02025 02026 02027 inline bool 02028 GetPot::argument_contains(unsigned Idx, const char* FlagList) const 02029 { 02030 if (Idx >= argv.size()) 02031 return false; 02032 02033 // (*) record requested of argument for later ufo-detection 02034 // an argument that is checked for flags is considered to be 'requested' 02035 _record_argument_request(argv[Idx]); 02036 02037 if (prefix == "") 02038 // search argument for any flag in flag list 02039 return _check_flags(argv[Idx], FlagList); 02040 02041 // if a prefix is set, then the argument index is the index 02042 // inside the 'namespace' 02043 // => only check list of arguments that start with prefix 02044 unsigned no_matches = 0; 02045 for (unsigned i=0; i<argv.size(); i++) 02046 { 02047 const std::string Remain = _get_remaining_string(argv[i], prefix); 02048 if (Remain != "") 02049 { 02050 no_matches += 1; 02051 if (no_matches == Idx) 02052 return _check_flags(Remain, FlagList); 02053 } 02054 } 02055 02056 // no argument in this namespace 02057 return false; 02058 } 02059 02060 02061 02062 inline bool 02063 GetPot::_check_flags(const std::string& Str, const char* FlagList) const 02064 { 02065 for (const char* p=FlagList; *p != '\0' ; p++) 02066 if (Str.find(*p) != std::string::npos) 02067 return true; // found something 02068 return false; 02069 } 02070 02071 02072 02074 // (*) nominus arguments 02075 02076 // return vector of nominus arguments 02077 inline STRING_VECTOR 02078 GetPot::nominus_vector() const 02079 { 02080 STRING_VECTOR nv; 02081 std::vector<unsigned>::const_iterator it = idx_nominus.begin(); 02082 for (; it != idx_nominus.end(); ++it) 02083 { 02084 nv.push_back(argv[*it]); 02085 02086 // (*) record for later ufo-detection 02087 // when a nominus vector is requested, the entire set of nominus arguments are 02088 // tagged as 'requested' 02089 _record_argument_request(argv[*it]); 02090 } 02091 return nv; 02092 } 02093 02094 02095 02096 inline const char* 02097 GetPot::next_nominus() 02098 { 02099 if (nominus_cursor < int(idx_nominus.size()) - 1) 02100 { 02101 const std::string Tmp = argv[idx_nominus[++nominus_cursor]]; 02102 02103 // (*) record for later ufo-detection 02104 _record_argument_request(Tmp); 02105 02106 return _internal_managed_copy(Tmp); 02107 } 02108 02109 return 0; 02110 } 02111 02112 02113 inline std::string 02114 GetPot::next_nominus_string() 02115 { 02116 if (nominus_cursor < int(idx_nominus.size()) - 1) 02117 { 02118 const std::string Tmp = argv[idx_nominus[++nominus_cursor]]; 02119 02120 // (*) record for later ufo-detection 02121 _record_argument_request(Tmp); 02122 02123 return Tmp; 02124 } 02125 02126 return ""; 02127 } 02128 02129 02130 02131 inline void 02132 GetPot::reset_nominus_cursor() 02133 { 02134 nominus_cursor = -1; 02135 } 02136 02137 02138 02140 // (*) variables 02141 //............................................................................. 02142 // 02143 inline bool 02144 GetPot::have_variable(const char* VarName) const 02145 { 02146 const variable* sv = _request_variable(VarName); 02147 02148 if (sv == 0) 02149 return false; 02150 02151 return true; 02152 } 02153 02154 02155 02156 inline bool 02157 GetPot::have_variable(const std::string& VarName) const 02158 { 02159 return have_variable(VarName.c_str()); 02160 } 02161 02162 inline bool 02163 GetPot::have_section(const char* section_name) const 02164 { 02165 std::string s = std::string(section_name); 02166 return this->have_section(s); 02167 } 02168 02169 inline bool 02170 GetPot::have_section(const std::string& section_name) const 02171 { 02172 const char slash('/'); 02173 02174 std::string::const_reverse_iterator it = section_name.rbegin(); 02175 02176 bool found_section = false; 02177 02178 /* Check if section_name ends with a "/". If not, append it for the search since 02179 the section names are stored with a "/" at the end.*/ 02180 if( (*it) != slash ) 02181 /* We need to use a linear search because we can't sort section_list 02182 without violating some assumptions. See libMesh #481 for more discussion. */ 02183 found_section = ( std::find(section_list.begin(), section_list.end(), section_name+slash) != section_list.end() ); 02184 else 02185 found_section = ( std::find(section_list.begin(), section_list.end(), section_name) != section_list.end() ); 02186 02187 return found_section; 02188 } 02189 02190 template <typename T> 02191 inline T 02192 GetPot::operator()(const char* VarName, const T& Default) const 02193 { 02194 // (*) recording of requested variables happens in '_request_variable()' 02195 const variable* sv = _request_variable(VarName); 02196 02197 if (sv == 0) 02198 return Default; 02199 02200 return _convert_to_type(sv->original, Default); 02201 } 02202 02203 02204 02205 template <typename T> 02206 inline T 02207 GetPot::operator()(const std::string& VarName, const T& Default) const 02208 { 02209 return operator()(VarName.c_str(), Default); 02210 } 02211 02212 02213 02214 inline const char* 02215 GetPot::operator()(const char* VarName, const char* Default) const 02216 { 02217 return _internal_managed_copy(operator()(VarName, std::string(Default))); 02218 } 02219 02220 02221 02222 inline const char* 02223 GetPot::operator()(const std::string& VarName, const char* Default) const 02224 { 02225 return operator()(VarName.c_str(), Default); 02226 } 02227 02228 02229 02230 template <typename T> 02231 inline T 02232 GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const 02233 { 02234 // (*) recording of requested variables happens in '_request_variable()' 02235 const variable* sv = _request_variable(VarName); 02236 if (sv == 0) 02237 return Default; 02238 02239 const std::string* element = sv->get_element(Idx); 02240 if (element == 0) 02241 return Default; 02242 return _convert_to_type(*element, Default); 02243 } 02244 02245 02246 02247 template <typename T> 02248 inline T 02249 GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const 02250 { 02251 return operator()(VarName.c_str(), Default, Idx); 02252 } 02253 02254 02255 02256 inline const char* 02257 GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const 02258 { 02259 return _internal_managed_copy(operator()(VarName, std::string(Default), Idx)); 02260 } 02261 02262 02263 02264 inline const char* 02265 GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const 02266 { 02267 return operator()(VarName.c_str(), Default, Idx); 02268 } 02269 02270 02271 02272 template <typename T> 02273 inline T 02274 GetPot::get_value_no_default(const char* VarName, const T& Default) const 02275 { 02276 // (*) recording of requested variables happens in '_request_variable()' 02277 const variable* sv = _request_variable(VarName); 02278 if (sv == 0) 02279 { 02280 getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl; 02281 getpot_error(); 02282 } 02283 return _convert_to_type_no_default(VarName, sv->original, Default); 02284 } 02285 02286 02287 02288 template <typename T> 02289 inline T 02290 GetPot::get_value_no_default(const std::string& VarName, const T& Default) const 02291 { 02292 return get_value_no_default(VarName.c_str(),Default); 02293 } 02294 02295 02296 02297 inline const char* 02298 GetPot::get_value_no_default(const char* VarName, const char* Default) const 02299 { 02300 return _internal_managed_copy(get_value_no_default(VarName, Default)); 02301 } 02302 02303 02304 02305 inline const char* 02306 GetPot::get_value_no_default(const std::string& VarName, const char* Default) const 02307 { 02308 return get_value_no_default(VarName.c_str(),Default); 02309 } 02310 02311 02312 02313 template <typename T> 02314 inline T 02315 GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const 02316 { 02317 // (*) recording of requested variables happens in '_request_variable()' 02318 const variable* sv = _request_variable(VarName); 02319 if (sv == 0) 02320 { 02321 getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl; 02322 getpot_error(); 02323 } 02324 02325 const std::string* element = sv->get_element(Idx); 02326 if (element == 0) 02327 { 02328 getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl; 02329 getpot_error(); 02330 } 02331 return _convert_to_type_no_default(VarName, *element, Default); 02332 } 02333 02334 02335 02336 template <typename T> 02337 inline T 02338 GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const 02339 { 02340 return get_value_no_default(VarName.c_str(), Default, Idx); 02341 } 02342 02343 02344 02345 inline const char* 02346 GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const 02347 { 02348 return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx)); 02349 } 02350 02351 02352 02353 inline const char* 02354 GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const 02355 { 02356 return get_value_no_default(VarName.c_str(), Default, Idx); 02357 } 02358 02359 02360 02361 inline void 02362 GetPot::_record_argument_request(const std::string& Name) const 02363 { 02364 if (!request_recording_f) 02365 return; 02366 02367 // Get a lock before touching anything mutable 02368 SCOPED_MUTEX; 02369 02370 // (*) record requested variable for later ufo detection 02371 _requested_arguments.insert(Name); 02372 02373 // (*) record considered section for ufo detection 02374 STRING_VECTOR STree = _get_section_tree(Name); 02375 victorate(std::string, STree, it) 02376 if (_requested_sections.find(*it) == _requested_sections.end()) 02377 if (section.length() != 0) 02378 _requested_sections.insert(*it); 02379 } 02380 02381 02382 02383 inline void 02384 GetPot::_record_variable_request(const std::string& Name) const 02385 { 02386 if (!request_recording_f) 02387 return; 02388 02389 // Get a lock before touching anything mutable 02390 SCOPED_MUTEX; 02391 02392 // (*) record requested variable for later ufo detection 02393 _requested_variables.insert(Name); 02394 02395 // (*) record considered section for ufo detection 02396 STRING_VECTOR STree = _get_section_tree(Name); 02397 victorate(std::string, STree, it) 02398 if (_requested_sections.find(*it) == _requested_sections.end()) 02399 if (section.length() != 0) 02400 _requested_sections.insert(*it); 02401 } 02402 02403 02404 02405 // (*) following functions are to be used from 'outside', after getpot has parsed its 02406 // arguments => append an argument in the argument vector that reflects the addition 02407 inline void 02408 GetPot::_set_variable(const std::string& VarName, 02409 const std::string& Value, const bool Requested /* = true */) 02410 { 02411 const GetPot::variable* Var = Requested ? 02412 _request_variable(VarName.c_str()) : 02413 _find_variable(VarName.c_str()); 02414 if (Var == 0) 02415 variables.push_back(variable(VarName.c_str(), Value.c_str(), _field_separator.c_str())); 02416 else 02417 { 02418 overridden_vars.insert(VarName.c_str()); 02419 (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str()); 02420 } 02421 } 02422 02423 02424 02425 template <typename T> 02426 inline void 02427 GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */) 02428 { 02429 std::ostringstream string_value; 02430 string_value << Value; 02431 _set_variable(VarName, string_value.str().c_str(), Requested); 02432 } 02433 02434 02435 02436 template <typename T> 02437 inline void 02438 GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */) 02439 { 02440 set(VarName.c_str(), Value, Requested); 02441 } 02442 02443 02444 02445 inline void 02446 GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */) 02447 { 02448 _set_variable(VarName, Value, Requested); 02449 } 02450 02451 02452 02453 inline void 02454 GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */) 02455 { 02456 set(VarName.c_str(), Value, Requested); 02457 } 02458 02459 02460 02461 inline unsigned 02462 GetPot::vector_variable_size(const char* VarName) const 02463 { 02464 const variable* sv = _request_variable(VarName); 02465 if (sv == 0) 02466 return 0; 02467 return (unsigned)(sv->value.size()); 02468 } 02469 02470 02471 02472 inline unsigned 02473 GetPot::vector_variable_size(const std::string& VarName) const 02474 { 02475 return vector_variable_size(VarName.c_str()); 02476 } 02477 02478 02479 02480 inline STRING_VECTOR 02481 GetPot::get_variable_names() const 02482 { 02483 STRING_VECTOR result; 02484 std::vector<GetPot::variable>::const_iterator it = variables.begin(); 02485 for (; it != variables.end(); ++it) 02486 { 02487 const std::string Tmp = _get_remaining_string((*it).name, prefix); 02488 if (Tmp != "") 02489 result.push_back(Tmp); 02490 } 02491 return result; 02492 } 02493 02494 02495 02496 inline STRING_VECTOR 02497 GetPot::get_section_names() const 02498 { 02499 return section_list; 02500 } 02501 02502 02503 02504 inline std::set<std::string> 02505 GetPot::get_overridden_variables() const 02506 { 02507 return overridden_vars; 02508 } 02509 02510 02511 02512 inline const GetPot::variable* 02513 GetPot::_find_variable(const char* VarName) const 02514 { 02515 const std::string Name = prefix + VarName; 02516 02517 std::vector<variable>::const_iterator it = variables.begin(); 02518 for (; it != variables.end(); ++it) 02519 { 02520 if ((*it).name == Name) 02521 return &(*it); 02522 } 02523 return 0; 02524 } 02525 02526 02527 02528 inline const GetPot::variable* 02529 GetPot::_request_variable(const char* VarName) const 02530 { 02531 // (*) record requested variable for later ufo detection 02532 this->_record_variable_request(VarName); 02533 02534 return this->_find_variable(VarName); 02535 } 02536 02537 02538 02540 // (*) ouput (basically for debugging reasons 02541 //............................................................................. 02542 // 02543 inline int 02544 GetPot::print(std::ostream &out_stream) const 02545 { 02546 out_stream << "argc = " << argv.size() << std::endl; 02547 STRING_VECTOR::const_iterator it = argv.begin(); 02548 for (; it != argv.end(); ++it) 02549 out_stream << *it << std::endl; 02550 out_stream << std::endl; 02551 return 1; 02552 } 02553 02554 02555 02556 // PECOS/HPCT Addition - add option to prepend output with a delimiter 02557 // while also disabling argc print and skipping first print (the name 02558 // of the input file) 02559 // 02560 // PECOS Development Team: (ks. 4/16/09) 02561 inline int 02562 GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const 02563 { 02564 STRING_VECTOR::const_iterator it = argv.begin(); 02565 it += skip_count; 02566 for (; it != argv.end(); ++it) 02567 { 02568 out_stream << custom_prefix; 02569 out_stream << *it << std::endl; 02570 } 02571 out_stream << std::endl; 02572 return 1; 02573 } 02574 02575 02576 02577 // (*) dollar bracket expressions (DBEs) ------------------------------------ 02578 // 02579 // 1) Entry Function: _DBE_expand_string() 02580 // Takes a string such as 02581 // 02582 // "${+ ${x} ${y}} Subject-${& ${section} ${subsection}}: ${title}" 02583 // 02584 // calls _DBE_expand() for each of the expressions 02585 // 02586 // ${+ ${x} ${y}} 02587 // ${& ${section} ${subsection}} 02588 // ${Title} 02589 // 02590 // and returns the string 02591 // 02592 // "4711 Subject-1.01: Mit den Clowns kamen die Schwaene" 02593 // 02594 // assuming that 02595 // x = "4699" 02596 // y = "12" 02597 // section = "1." 02598 // subsection = "01" 02599 // title = "Mit den Clowns kamen die Schwaene" 02600 // 02601 // 2) _DBE_expand(): 02602 // 02603 // checks for the command, i.e. the 'sign' that follows '${' 02604 // divides the argument list into sub-expressions using 02605 // _DBE_get_expr_list() 02606 // 02607 // ${+ ${x} ${y}} -> "${x}" "${y}" 02608 // ${& ${section} ${subsection}} -> "${section}" "${subsection}" 02609 // ${Title} -> Nothing, variable expansion 02610 // 02611 // 3) _DBE_expression_list(): 02612 // 02613 // builds a vector of unbracketed whitespace separated strings, i.e. 02614 // 02615 // " ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}" 02616 // 02617 // is split into a vector 02618 // 02619 // [0] ${Number}.a 02620 // [1] ${: Das Marmorbild} 02621 // [2] AB-${& Author= ${Eichendorf}}-1870 02622 // 02623 // Each sub-expression is expanded using expand(). 02624 //--------------------------------------------------------------------------- 02625 inline std::string 02626 GetPot::_DBE_expand_string(const std::string& str) 02627 { 02628 // Parses for closing operators '${ }' and expands them letting 02629 // white spaces and other letters as they are. 02630 std::string new_string = ""; 02631 unsigned open_brackets = 0; 02632 unsigned first = 0; 02633 for (unsigned i = 0; i<str.size(); i++) 02634 { 02635 if (i < str.size() - 2 && str.substr(i, 2) == "${") 02636 { 02637 if (open_brackets == 0) 02638 first = i+2; 02639 open_brackets++; 02640 } 02641 else if (str[i] == '}' && open_brackets > 0) 02642 { 02643 open_brackets -= 1; 02644 if (open_brackets == 0) 02645 { 02646 const std::string Replacement = _DBE_expand(str.substr(first, i - first)); 02647 new_string += Replacement; 02648 } 02649 } 02650 else if (open_brackets == 0) 02651 new_string += str[i]; 02652 } 02653 return new_string; 02654 } 02655 02656 02657 02658 inline STRING_VECTOR 02659 GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber) 02660 { 02661 // ensures that the resulting vector has the expected number 02662 // of arguments, but they may contain an error message 02663 std::string str = str_; 02664 // Separates expressions by non-bracketed whitespaces, expands them 02665 // and puts them into a list. 02666 02667 unsigned i=0; 02668 // (1) eat initial whitespaces 02669 for (; i < str.size(); i++) 02670 if (!isspace(str[i])) 02671 break; 02672 02673 STRING_VECTOR expr_list; 02674 unsigned open_brackets = 0; 02675 std::vector<unsigned> start_idx; 02676 unsigned start_new_string = i; 02677 unsigned l = (unsigned)(str.size()); 02678 02679 // (2) search for ${ } expressions ... 02680 while (i < l) 02681 { 02682 const char letter = str[i]; 02683 // whitespace -> end of expression 02684 if (isspace(letter) && open_brackets == 0) 02685 { 02686 expr_list.push_back(str.substr(start_new_string, i - start_new_string)); 02687 bool no_breakout_f = true; 02688 for (i++; i < l ; i++) 02689 { 02690 if (!isspace(str[i])) 02691 { 02692 no_breakout_f = false; 02693 start_new_string = i; 02694 break; 02695 } 02696 } 02697 02698 if (no_breakout_f) 02699 { 02700 // end of expression list 02701 if (expr_list.size() < ExpectedNumber) 02702 { 02703 const std::string pre_tmp("<< ${ }: missing arguments>>"); 02704 STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp); 02705 expr_list.insert(expr_list.end(), tmp.begin(), tmp.end()); 02706 } 02707 return expr_list; 02708 } 02709 } 02710 02711 // dollar-bracket expression 02712 if (str.length() >= i+2 && str.substr(i, 2) == "${") 02713 { 02714 open_brackets++; 02715 start_idx.push_back(i+2); 02716 } 02717 02718 else if (letter == '}' && open_brackets > 0) 02719 { 02720 int start = start_idx[start_idx.size()-1]; 02721 start_idx.pop_back(); 02722 const std::string Replacement = _DBE_expand(str.substr(start, i-start)); 02723 if (start - 3 < (int)0) 02724 str = Replacement + str.substr(i+1); 02725 else 02726 str = str.substr(0, start-2) + Replacement + str.substr(i+1); 02727 l = (int)(str.size()); 02728 i = start + (int)(Replacement.size()) - 3; 02729 open_brackets--; 02730 } 02731 i++; 02732 } 02733 02734 // end of expression list 02735 expr_list.push_back(str.substr(start_new_string, i-start_new_string)); 02736 02737 if (expr_list.size() < ExpectedNumber) 02738 { 02739 const std::string pre_tmp("<< ${ }: missing arguments>>"); 02740 STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp); 02741 expr_list.insert(expr_list.end(), tmp.begin(), tmp.end()); 02742 } 02743 02744 return expr_list; 02745 } 02746 02747 02748 02749 inline const GetPot::variable* 02750 GetPot::_DBE_get_variable(const std::string& VarName) 02751 { 02752 static GetPot::variable ev; 02753 std::string secure_Prefix = prefix; 02754 02755 prefix = section; 02756 // (1) first search in currently active section 02757 const GetPot::variable* var = _request_variable(VarName.c_str()); 02758 if (var != 0) 02759 { 02760 prefix = secure_Prefix; 02761 return var; 02762 } 02763 02764 // (2) search in root name space 02765 prefix = ""; 02766 var = _request_variable(VarName.c_str()); 02767 if (var != 0) 02768 { 02769 prefix = secure_Prefix; 02770 return var; 02771 } 02772 02773 prefix = secure_Prefix; 02774 02775 // error occured => variable name == "" 02776 ev.original = "<<${ } variable '"; 02777 ev.original += VarName + "' undefined>>"; 02778 return &ev; 02779 } 02780 02781 02782 02783 inline std::string 02784 GetPot::_DBE_expand(const std::string& expr) 02785 { 02786 // ${: } pure text 02787 if (expr[0] == ':') 02788 return expr.substr(1); 02789 02790 // ${& expr expr ... } text concatination 02791 else if (expr[0] == '&') 02792 { 02793 const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1); 02794 02795 STRING_VECTOR::const_iterator it = A.begin(); 02796 std::string result = *it++; 02797 for (; it != A.end(); ++it) result += *it; 02798 02799 return result; 02800 } 02801 02802 // ${<-> expr expr expr} text replacement 02803 else if (expr.length() >= 3 && expr.substr(0, 3) == "<->") 02804 { 02805 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3); 02806 size_t tmp = 0; 02807 const size_t L = A[1].length(); 02808 02809 while ((tmp = A[0].find(A[1])) != std::string::npos) 02810 A[0].replace(tmp, L, A[2]); 02811 02812 return A[0]; 02813 } 02814 02815 // ${=func [expr...] } function evaluation 02816 else if (expr.length() >= 2 && 02817 expr.substr(0, 1) == "=" && 02818 expr.substr(0, 2) != "==") 02819 { 02820 size_t funcnamestart = expr.find_first_not_of(" \t", 1); 02821 if (funcnamestart != std::string::npos) 02822 { 02823 size_t funcnameend = expr.find_first_of(" \t",funcnamestart); 02824 std::string funcname = expr.substr(funcnamestart, 02825 funcnameend-funcnamestart); 02826 if (funcname == "log") 02827 { 02828 STRING_VECTOR A = 02829 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02830 double arg = _convert_to_type(A[0], 0.0); 02831 return _convert_from_type(std::log(arg)); 02832 } 02833 else if (funcname == "log10") 02834 { 02835 STRING_VECTOR A = 02836 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02837 double arg = _convert_to_type(A[0], 0.0); 02838 return _convert_from_type(std::log10(arg)); 02839 } 02840 else if (funcname == "exp") 02841 { 02842 STRING_VECTOR A = 02843 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02844 double arg = _convert_to_type(A[0], 0.0); 02845 return _convert_from_type(std::exp(arg)); 02846 } 02847 else if (funcname == "sin") 02848 { 02849 STRING_VECTOR A = 02850 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02851 double arg = _convert_to_type(A[0], 0.0); 02852 return _convert_from_type(std::sin(arg)); 02853 } 02854 else if (funcname == "cos") 02855 { 02856 STRING_VECTOR A = 02857 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02858 double arg = _convert_to_type(A[0], 0.0); 02859 return _convert_from_type(std::cos(arg)); 02860 } 02861 else if (funcname == "tan") 02862 { 02863 STRING_VECTOR A = 02864 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02865 double arg = _convert_to_type(A[0], 0.0); 02866 return _convert_from_type(std::tan(arg)); 02867 } 02868 else if (funcname == "asin") 02869 { 02870 STRING_VECTOR A = 02871 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02872 double arg = _convert_to_type(A[0], 0.0); 02873 return _convert_from_type(std::asin(arg)); 02874 } 02875 else if (funcname == "acos") 02876 { 02877 STRING_VECTOR A = 02878 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02879 double arg = _convert_to_type(A[0], 0.0); 02880 return _convert_from_type(std::acos(arg)); 02881 } 02882 else if (funcname == "atan") 02883 { 02884 STRING_VECTOR A = 02885 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02886 double arg = _convert_to_type(A[0], 0.0); 02887 return _convert_from_type(std::atan(arg)); 02888 } 02889 else if (funcname == "atan2") 02890 { 02891 STRING_VECTOR A = 02892 _DBE_get_expr_list(expr.substr(funcnameend), 2); 02893 double arg1 = _convert_to_type(A[0], 0.0); 02894 double arg2 = _convert_to_type(A[1], 0.0); 02895 return _convert_from_type(std::atan2(arg1, arg2)); 02896 } 02897 else if (funcname == "sinh") 02898 { 02899 STRING_VECTOR A = 02900 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02901 double arg = _convert_to_type(A[0], 0.0); 02902 return _convert_from_type(std::sinh(arg)); 02903 } 02904 else if (funcname == "cosh") 02905 { 02906 STRING_VECTOR A = 02907 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02908 double arg = _convert_to_type(A[0], 0.0); 02909 return _convert_from_type(std::cosh(arg)); 02910 } 02911 else if (funcname == "tanh") 02912 { 02913 STRING_VECTOR A = 02914 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02915 double arg = _convert_to_type(A[0], 0.0); 02916 return _convert_from_type(std::tanh(arg)); 02917 } 02918 #ifdef HAVE_INVERSE_HYPERBOLIC_SINE 02919 else if (funcname == "asinh") 02920 { 02921 STRING_VECTOR A = 02922 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02923 double arg = _convert_to_type(A[0], 0.0); 02924 return _convert_from_type(std::asinh(arg)); 02925 } 02926 #endif 02927 #ifdef HAVE_INVERSE_HYPERBOLIC_COSINE 02928 else if (funcname == "acosh") 02929 { 02930 STRING_VECTOR A = 02931 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02932 double arg = _convert_to_type(A[0], 0.0); 02933 return _convert_from_type(std::acosh(arg)); 02934 } 02935 #endif 02936 #ifdef HAVE_INVERSE_HYPERBOLIC_TANGENT 02937 else if (funcname == "atanh") 02938 { 02939 STRING_VECTOR A = 02940 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02941 double arg = _convert_to_type(A[0], 0.0); 02942 return _convert_from_type(std::atanh(arg)); 02943 } 02944 #endif 02945 else if (funcname == "sqrt") 02946 { 02947 STRING_VECTOR A = 02948 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02949 double arg = _convert_to_type(A[0], 0.0); 02950 return _convert_from_type(std::sqrt(arg)); 02951 } 02952 else if (funcname == "abs") 02953 { 02954 STRING_VECTOR A = 02955 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02956 double arg = _convert_to_type(A[0], 0.0); 02957 return _convert_from_type(std::abs(arg)); 02958 } 02959 else if (funcname == "max") 02960 { 02961 STRING_VECTOR A = 02962 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02963 STRING_VECTOR::const_iterator it = A.begin(); 02964 double result = _convert_to_type(*it++, 0.0); 02965 for (; it != A.end(); ++it) 02966 result = std::max(result, _convert_to_type(*it, 0.0)); 02967 return _convert_from_type(result); 02968 } 02969 else if (funcname == "min") 02970 { 02971 STRING_VECTOR A = 02972 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02973 STRING_VECTOR::const_iterator it = A.begin(); 02974 double result = _convert_to_type(*it++, 0.0); 02975 for (; it != A.end(); ++it) 02976 result = std::min(result, _convert_to_type(*it, 0.0)); 02977 return _convert_from_type(result); 02978 } 02979 else if (funcname == "ceil") 02980 { 02981 STRING_VECTOR A = 02982 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02983 double arg = _convert_to_type(A[0], 0.0); 02984 return _convert_from_type(std::ceil(arg)); 02985 } 02986 else if (funcname == "floor") 02987 { 02988 STRING_VECTOR A = 02989 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02990 double arg = _convert_to_type(A[0], 0.0); 02991 return _convert_from_type(std::floor(arg)); 02992 } 02993 else if (funcname == "fmod") 02994 { 02995 STRING_VECTOR A = 02996 _DBE_get_expr_list(expr.substr(funcnameend), 2); 02997 double arg1 = _convert_to_type(A[0], 0.0); 02998 double arg2 = _convert_to_type(A[1], 0.0); 02999 return _convert_from_type(std::fmod(arg1, arg2)); 03000 } 03001 else if (funcname == "srand") 03002 { 03003 STRING_VECTOR A = 03004 _DBE_get_expr_list(expr.substr(funcnameend), 1); 03005 unsigned int arg = _convert_to_type(A[0], 0u); 03006 std::srand(arg); 03007 return A[0]; 03008 } 03009 // ${=rand range} with default range==RAND_MAX 03010 else if (funcname == "rand") 03011 { 03012 if (funcnameend >= expr.length() || 03013 expr.find_first_not_of(" \t", funcnameend) == std::string::npos) 03014 return _convert_from_type(std::rand()); 03015 03016 STRING_VECTOR A = 03017 _DBE_get_expr_list(expr.substr(funcnameend), 1); 03018 unsigned int range = _convert_to_type(A[0],0u); 03019 if (!range) 03020 return _convert_from_type(0); 03021 const unsigned int x = (RAND_MAX + 1u) / range; 03022 const unsigned int y = x * range; 03023 unsigned int returnval; 03024 do 03025 { 03026 returnval = rand(); 03027 } while (returnval >= y); 03028 return _convert_from_type(returnval / x); 03029 } 03030 else if (funcname == "time") 03031 return _convert_from_type(std::time(NULL)); 03032 else 03033 { 03034 getpot_cerr << "ERROR: unrecognized function " 03035 << funcname << std::endl; 03036 getpot_error(); 03037 } 03038 } 03039 } 03040 03041 // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions 03042 else if (expr[0] == '+') 03043 { 03044 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 03045 STRING_VECTOR::const_iterator it = A.begin(); 03046 double result = _convert_to_type(*it++, 0.0); 03047 for (; it != A.end(); ++it) 03048 result += _convert_to_type(*it, 0.0); 03049 03050 return _convert_from_type(result); 03051 } 03052 else if (expr[0] == '-') 03053 { 03054 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 03055 STRING_VECTOR::const_iterator it = A.begin(); 03056 double result = _convert_to_type(*it++, 0.0); 03057 for (; it != A.end(); ++it) 03058 result -= _convert_to_type(*it, 0.0); 03059 03060 return _convert_from_type(result); 03061 } 03062 else if (expr[0] == '*') 03063 { 03064 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 03065 STRING_VECTOR::const_iterator it = A.begin(); 03066 double result = _convert_to_type(*it++, 0.0); 03067 for (; it != A.end(); ++it) 03068 result *= _convert_to_type(*it, 0.0); 03069 03070 return _convert_from_type(result); 03071 } 03072 else if (expr[0] == '/') 03073 { 03074 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 03075 STRING_VECTOR::const_iterator it = A.begin(); 03076 double result = _convert_to_type(*it++, 0.0); 03077 if (result == 0) 03078 return "0.0"; 03079 03080 for (; it != A.end(); ++it) 03081 { 03082 const double Q = _convert_to_type(*it, 0.0); 03083 result /= Q; 03084 } 03085 return _convert_from_type(result); 03086 } 03087 03088 // ${^ ... } power expressions 03089 else if (expr[0] == '^') 03090 { 03091 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 03092 STRING_VECTOR::const_iterator it = A.begin(); 03093 double result = _convert_to_type(*it++, 0.0); 03094 for (; it != A.end(); ++it) 03095 result = pow(result, _convert_to_type(*it, 0.0)); 03096 return _convert_from_type(result); 03097 } 03098 03099 // ${== } ${<= } ${>= } comparisons (return the number of the first 'match' 03100 else if (expr.length() >= 2 && 03101 (expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" || 03102 expr.substr(0,2) == "<=" || expr[0] == '>' || expr[0] == '<')) 03103 { 03104 // differentiate between two and one sign operators 03105 unsigned op = 0; 03106 enum { EQ, GEQ, LEQ, GT, LT }; 03107 03108 if (expr.substr(0, 2) == "==") 03109 op = EQ; 03110 03111 else if (expr.substr(0, 2) == ">=") 03112 op = GEQ; 03113 03114 else if (expr.substr(0, 2) == "<=") 03115 op = LEQ; 03116 03117 else if (expr[0] == '>') 03118 op = GT; 03119 03120 else 03121 op = LT; 03122 03123 STRING_VECTOR a; 03124 if (op == GT || op == LT) 03125 a = _DBE_get_expr_list(expr.substr(1), 2); 03126 03127 else 03128 a = _DBE_get_expr_list(expr.substr(2), 2); 03129 03130 std::string x_orig = a[0]; 03131 double x = _convert_to_type(x_orig, 1e37); 03132 unsigned i = 1; 03133 03134 STRING_VECTOR::const_iterator y_orig = a.begin(); 03135 for (y_orig++; y_orig != a.end(); ++y_orig) 03136 { 03137 double y = _convert_to_type(*y_orig, 1e37); 03138 03139 // set the strings as reference if one wasn't a number 03140 if (x == 1e37 || y == 1e37) 03141 { 03142 // it's a string comparison 03143 if ((op == EQ && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) || 03144 (op == LEQ && x_orig <= *y_orig) || (op == GT && x_orig > *y_orig) || 03145 (op == LT && x_orig < *y_orig)) 03146 return _convert_from_type(i); 03147 } 03148 else 03149 { 03150 // it's a number comparison 03151 if ((op == EQ && x == y) || (op == GEQ && x >= y) || 03152 (op == LEQ && x <= y) || (op == GT && x > y) || 03153 (op == LT && x < y)) 03154 return _convert_from_type(i); 03155 } 03156 i++; 03157 } 03158 03159 // nothing fulfills the condition => return 0 03160 return "0"; 03161 } 03162 03163 // ${?? expr expr} select 03164 else if (expr.length() >= 2 && expr.substr(0, 2) == "??") 03165 { 03166 STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2); 03167 double x = _convert_to_type(a[0], 1e37); 03168 03169 // last element is always the default argument 03170 if (x == 1e37 || x < 0 || x >= a.size() - 1) 03171 return a[a.size()-1]; 03172 03173 // round x to closest integer 03174 return a[int(x+0.5)]; 03175 } 03176 03177 // ${? expr expr expr} if then else conditions 03178 else if (expr[0] == '?') 03179 { 03180 STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2); 03181 03182 if (_convert_to_type(a[0], 0.0) == 1.0) 03183 return a[1]; 03184 03185 else if (a.size() > 2) 03186 return a[2]; 03187 } 03188 // ${! expr} maxro expansion 03189 else if (expr[0] == '!') 03190 { 03191 const GetPot::variable* Var = _DBE_get_variable(expr.substr(1)); 03192 // error 03193 if (Var->name == "") 03194 return std::string(Var->original); 03195 03196 const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2); 03197 return A[0]; 03198 } 03199 // ${@: } - string subscription 03200 else if (expr.length() >= 2 && expr.substr(0,2) == "@:") 03201 { 03202 const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2); 03203 double x = _convert_to_type(A[1], 1e37); 03204 03205 // last element is always the default argument 03206 if (x == 1e37 || x < 0 || x >= A[0].size() - 1) 03207 return "<<1st index out of range>>"; 03208 03209 if (A.size() > 2) 03210 { 03211 double y = _convert_to_type(A[2], 1e37); 03212 if (y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x) 03213 return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5)); 03214 03215 else if (y == -1) 03216 return A[0].substr(int(x+0.5)); 03217 03218 return "<<2nd index out of range>>"; 03219 } 03220 else 03221 { 03222 char* tmp = new char[2]; 03223 tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0'; 03224 std::string result(tmp); 03225 delete [] tmp; 03226 return result; 03227 } 03228 } 03229 // ${@ } - vector subscription 03230 else if (expr[0] == '@') 03231 { 03232 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 03233 const GetPot::variable* Var = _DBE_get_variable(A[0]); 03234 // error 03235 if (Var->name == "") 03236 { 03237 // make a copy of the string if an error occured 03238 // (since the error variable is a static variable inside get_variable()) 03239 return std::string(Var->original); 03240 } 03241 03242 double x = _convert_to_type(A[1], 1e37); 03243 03244 // last element is always the default argument 03245 if (x == 1e37 || x < 0 || x >= Var->value.size()) 03246 return "<<1st index out of range>>"; 03247 03248 if (A.size() > 2) 03249 { 03250 double y = _convert_to_type(A[2], 1e37); 03251 int begin = int(x+0.5); 03252 int end = 0; 03253 if (y != 1e37 && y > 0 && y <= Var->value.size() && y > x) 03254 end = int(y+1.5); 03255 else if (y == -1) 03256 end = int(Var->value.size()); 03257 else 03258 return "<<2nd index out of range>>"; 03259 03260 std::string result = *(Var->get_element(begin)); 03261 for (int i = begin+1; i < end; i++) 03262 result += std::string(" ") + *(Var->get_element(i)); 03263 return result; 03264 } 03265 else 03266 return *(Var->get_element(int(x+0.5))); 03267 } 03268 03269 const STRING_VECTOR A = _DBE_get_expr_list(expr, 1); 03270 const GetPot::variable* B = _DBE_get_variable(A[0]); 03271 03272 // make a copy of the string if an error occured 03273 // (since the error variable is a static variable inside get_variable()) 03274 if (B->name == "") 03275 return std::string(B->original); 03276 03277 // (psuggs@pobox.com mentioned to me the warning MSVC++6.0 produces 03278 // with: else return B->original (thanks)) 03279 return B->original; 03280 } 03281 03282 03283 03285 // (*) unidentified flying objects 03286 //............................................................................. 03287 // 03288 inline bool 03289 GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const 03290 { 03291 victorate(std::string, VecStr, itk) 03292 { 03293 if (*itk == Str) 03294 return true; 03295 } 03296 return false; 03297 } 03298 03299 03300 03301 inline STRING_VECTOR 03302 GetPot::unidentified_arguments(unsigned Number, 03303 const char* KnownArgument1, ...) const 03304 { 03305 std::set<std::string> known_arguments; 03306 03307 // (1) create a vector of known arguments 03308 if (Number == 0) 03309 return STRING_VECTOR(); 03310 03311 va_list ap; 03312 va_start(ap, KnownArgument1); 03313 known_arguments.insert(std::string(KnownArgument1)); 03314 for (unsigned i=1; i<Number; i++) 03315 known_arguments.insert(std::string(va_arg(ap, char *))); 03316 va_end(ap); 03317 03318 return unidentified_arguments(known_arguments); 03319 } 03320 03321 03322 03323 inline STRING_VECTOR 03324 GetPot::unidentified_arguments() const 03325 { 03326 return unidentified_arguments(_requested_arguments); 03327 } 03328 03329 03330 03331 inline STRING_VECTOR 03332 GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const 03333 { 03334 // We use set for efficiency, but want to support vector inputs for 03335 // backwards compatibility. 03336 return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end())); 03337 } 03338 03339 03340 03341 inline STRING_VECTOR 03342 GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const 03343 { 03344 STRING_VECTOR ufos; 03345 STRING_VECTOR::const_iterator it = argv.begin(); 03346 ++it; // forget about argv[0] (application or filename) 03347 for (; it != argv.end(); ++it) 03348 { 03349 // -- argument belongs to prefixed section ? 03350 const std::string arg = _get_remaining_string(*it, prefix); 03351 if (arg == "") 03352 continue; 03353 03354 // -- check if in list 03355 if (Knowns.find(arg) == Knowns.end()) 03356 ufos.push_back(*it); 03357 } 03358 return ufos; 03359 } 03360 03361 03362 03363 inline STRING_VECTOR 03364 GetPot::unidentified_options(unsigned Number, 03365 const char* KnownOption1, ...) const 03366 { 03367 std::set<std::string> known_options; 03368 03369 // (1) create a vector of known arguments 03370 if (Number == 0) 03371 return STRING_VECTOR(); 03372 03373 va_list ap; 03374 va_start(ap, KnownOption1); 03375 known_options.insert(std::string(KnownOption1)); 03376 for (unsigned i=1; i<Number; i++) 03377 known_options.insert(std::string(va_arg(ap, char *))); 03378 va_end(ap); 03379 03380 return unidentified_options(known_options); 03381 } 03382 03383 03384 03385 inline STRING_VECTOR 03386 GetPot::unidentified_options() const 03387 { 03388 // -- every option is an argument. 03389 // -- the set of requested arguments contains the set of requested options. 03390 // -- IF the set of requested arguments contains unrequested options, 03391 // THEN they were requested as 'follow' and 'next' arguments and not as real options. 03392 // 03393 // => it is not necessary to separate requested options from the list 03394 return unidentified_arguments(_requested_arguments); 03395 } 03396 03397 03398 03399 inline STRING_VECTOR 03400 GetPot::unidentified_options(const std::vector<std::string>& Knowns) const 03401 { 03402 // We use set for efficiency, but want to support vector inputs for 03403 // backwards compatibility. 03404 return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end())); 03405 } 03406 03407 03408 03409 inline STRING_VECTOR 03410 GetPot::unidentified_options(const std::set<std::string>& Knowns) const 03411 { 03412 STRING_VECTOR ufos; 03413 STRING_VECTOR::const_iterator it = argv.begin(); 03414 ++it; // forget about argv[0] (application or filename) 03415 for (; it != argv.end(); ++it) 03416 { 03417 // -- argument belongs to prefixed section ? 03418 const std::string arg = _get_remaining_string(*it, prefix); 03419 if (arg == "") 03420 continue; 03421 03422 // is argument really an option (starting with '-') ? 03423 if (arg.length() < 1 || arg[0] != '-') 03424 continue; 03425 03426 if (Knowns.find(arg) == Knowns.end()) 03427 ufos.push_back(*it); 03428 } 03429 03430 return ufos; 03431 } 03432 03433 03434 03435 // Two modes: 03436 // ArgumentNumber >= 0 check specific argument 03437 // ArgumentNumber == -1 check all options starting with one '-' 03438 // for flags 03439 inline std::string 03440 GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const 03441 { 03442 std::string ufos; 03443 // STRING_VECTOR known_arguments; 03444 std::string KFL(KnownFlagList); 03445 03446 // (2) iteration over '-' arguments (options) 03447 if (ArgumentNumber == -1) 03448 { 03449 STRING_VECTOR::const_iterator it = argv.begin(); 03450 ++it; // forget about argv[0] (application or filename) 03451 for (; it != argv.end(); ++it) 03452 { 03453 // -- argument belongs to prefixed section ? 03454 const std::string arg = _get_remaining_string(*it, prefix); 03455 if (arg == "") continue; 03456 03457 // -- does arguments start with '-' (but not '--') 03458 if (arg.length() < 2) 03459 continue; 03460 03461 else if (arg[0] != '-') 03462 continue; 03463 03464 else if (arg[1] == '-') 03465 continue; 03466 03467 // -- check out if flags inside option are contained in KnownFlagList 03468 const char* p=arg.c_str(); 03469 p++; // skip starting minus 03470 for (; *p != '\0' ; p++) 03471 if (KFL.find(*p) == std::string::npos) ufos += *p; 03472 } 03473 } 03474 // (1) check specific argument 03475 else 03476 { 03477 // -- only check arguments that start with prefix 03478 int no_matches = 0; 03479 for (unsigned i=1; i<argv.size(); i++) 03480 { 03481 const std::string Remain = _get_remaining_string(argv[i], prefix); 03482 if (Remain != "") 03483 { 03484 no_matches++; 03485 if (no_matches == ArgumentNumber) 03486 { 03487 // -- the right argument number inside the section is found 03488 // => check it for flags 03489 const char* p = Remain.c_str(); 03490 p++; // skip starting minus 03491 for (; *p != '\0' ; p++) 03492 if (KFL.find(*p) == std::string::npos) ufos += *p; 03493 return ufos; 03494 } 03495 } 03496 } 03497 } 03498 return ufos; 03499 } 03500 03501 03502 03503 inline STRING_VECTOR 03504 GetPot::unidentified_variables(unsigned Number, 03505 const char* KnownVariable1, ...) const 03506 { 03507 std::set<std::string> known_variables; 03508 03509 // create vector of known arguments 03510 if (Number == 0) 03511 return STRING_VECTOR(); 03512 03513 va_list ap; 03514 va_start(ap, KnownVariable1); 03515 known_variables.insert(std::string(KnownVariable1)); 03516 for (unsigned i=1; i<Number; i++) 03517 known_variables.insert(std::string(va_arg(ap, char *))); 03518 va_end(ap); 03519 03520 return unidentified_variables(known_variables); 03521 } 03522 03523 03524 03525 inline STRING_VECTOR 03526 GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const 03527 { 03528 // We use set for efficiency, but want to support vector inputs for 03529 // backwards compatibility. 03530 return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end())); 03531 } 03532 03533 03534 03535 inline STRING_VECTOR 03536 GetPot::unidentified_variables(const std::set<std::string>& Knowns) const 03537 { 03538 STRING_VECTOR ufos; 03539 03540 victorate(GetPot::variable, variables, it) 03541 { 03542 // -- check if variable has specific prefix 03543 const std::string var_name = _get_remaining_string((*it).name, prefix); 03544 if (var_name == "") 03545 continue; 03546 03547 // -- check if variable is known 03548 if (Knowns.find(var_name) == Knowns.end()) 03549 ufos.push_back((*it).name); 03550 } 03551 return ufos; 03552 } 03553 03554 03555 03556 inline STRING_VECTOR 03557 GetPot::unidentified_variables() const 03558 { 03559 return unidentified_variables(_requested_variables); 03560 } 03561 03562 03563 03564 inline STRING_VECTOR 03565 GetPot::unidentified_sections(unsigned Number, 03566 const char* KnownSection1, ...) const 03567 { 03568 std::set<std::string> known_sections; 03569 03570 // (1) create a vector of known arguments 03571 if (Number == 0) 03572 return STRING_VECTOR(); 03573 03574 va_list ap; 03575 va_start(ap, KnownSection1); 03576 known_sections.insert(std::string(KnownSection1)); 03577 for (unsigned i=1; i<Number; i++) 03578 { 03579 std::string tmp = std::string(va_arg(ap, char *)); 03580 03581 if (tmp.length() == 0) 03582 continue; 03583 03584 if (tmp[tmp.length()-1] != '/') 03585 tmp += '/'; 03586 03587 known_sections.insert(tmp); 03588 } 03589 va_end(ap); 03590 03591 return unidentified_sections(known_sections); 03592 } 03593 03594 03595 03596 inline STRING_VECTOR 03597 GetPot::unidentified_sections() const 03598 { 03599 return unidentified_sections(_requested_sections); 03600 } 03601 03602 03603 03604 inline STRING_VECTOR 03605 GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const 03606 { 03607 // We use set for efficiency, but want to support vector inputs for 03608 // backwards compatibility. 03609 return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end())); 03610 } 03611 03612 03613 03614 inline STRING_VECTOR 03615 GetPot::unidentified_sections(const std::set<std::string>& Knowns) const 03616 { 03617 STRING_VECTOR ufos; 03618 03619 victorate(std::string, section_list, it) 03620 { 03621 // -- check if section conform to prefix 03622 const std::string sec_name = _get_remaining_string(*it, prefix); 03623 if (sec_name == "") 03624 continue; 03625 03626 // -- check if section is known 03627 if (Knowns.find(sec_name) == Knowns.end()) 03628 ufos.push_back(*it); 03629 } 03630 03631 return ufos; 03632 } 03633 03634 03635 03636 inline STRING_VECTOR 03637 GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const 03638 { 03639 std::set<std::string> known_nominuses; 03640 03641 // create vector of known arguments 03642 if (Number == 0) 03643 return STRING_VECTOR(); 03644 03645 va_list ap; 03646 va_start(ap, Known); 03647 known_nominuses.insert(std::string(Known)); 03648 for (unsigned i=1; i<Number; i++) 03649 { 03650 std::string tmp = std::string(va_arg(ap, char *)); 03651 if (tmp.length() == 0) 03652 continue; 03653 known_nominuses.insert(tmp); 03654 } 03655 va_end(ap); 03656 03657 return unidentified_nominuses(known_nominuses); 03658 } 03659 03660 03661 03662 inline STRING_VECTOR 03663 GetPot::unidentified_nominuses() const 03664 { 03665 // -- every nominus is an argument. 03666 // -- the set of requested arguments contains the set of requested nominuss. 03667 // -- IF the set of requested arguments contains unrequested nominuss, 03668 // THEN they were requested as 'follow' and 'next' arguments and not as real nominuses. 03669 // 03670 // => it is not necessary to separate requested nominus from the list 03671 03672 return unidentified_nominuses(_requested_arguments); 03673 } 03674 03675 03676 03677 inline STRING_VECTOR 03678 GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const 03679 { 03680 // We use set for efficiency, but want to support vector inputs for 03681 // backwards compatibility. 03682 return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end())); 03683 } 03684 03685 03686 03687 inline STRING_VECTOR 03688 GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const 03689 { 03690 STRING_VECTOR ufos; 03691 03692 // (2) iterate over all arguments 03693 STRING_VECTOR::const_iterator it = argv.begin(); 03694 ++it; // forget about argv[0] (application or filename) 03695 for (; it != argv.end(); ++it) 03696 { 03697 // -- check if nominus part of prefix 03698 const std::string arg = _get_remaining_string(*it, prefix); 03699 if (arg == "") 03700 continue; 03701 03702 if (arg.length() < 1) 03703 continue; 03704 03705 // option ? --> not a nomius 03706 if (arg[0] == '-') 03707 continue; 03708 03709 // section ? --> not a real nominus 03710 if (arg[0] == '[' && arg[arg.length()-1] == ']') 03711 continue; 03712 03713 // variable definition ? --> not a real nominus 03714 bool continue_f = false; 03715 for (unsigned i=0; i<arg.length() ; i++) 03716 if (arg[i] == '=') 03717 { 03718 continue_f = true; 03719 break; 03720 } 03721 03722 if (continue_f) 03723 continue; 03724 03725 // real nominuses are compared with the given list 03726 if (Knowns.find(arg) == Knowns.end()) 03727 ufos.push_back(*it); 03728 } 03729 return ufos; 03730 } 03731 03732 03733 03735 // (*) variable class 03736 //............................................................................. 03737 // 03738 inline 03739 GetPot::variable::variable() 03740 : name(), 03741 value(), 03742 original() 03743 {} 03744 03745 03746 03747 inline 03748 GetPot::variable::variable(const variable& Other) 03749 { 03750 #ifdef WIN32 03751 operator=(Other); 03752 #else 03753 GetPot::variable::operator=(Other); 03754 #endif 03755 } 03756 03757 03758 03759 inline 03760 GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator) 03761 : name(Name) 03762 { 03763 // make a copy of the 'Value' 03764 take(Value, FieldSeparator); 03765 } 03766 03767 03768 03769 inline const std::string* 03770 GetPot::variable::get_element(unsigned Idx) const 03771 { 03772 if (Idx >= value.size()) 03773 return 0; 03774 else 03775 return &(value[Idx]); 03776 } 03777 03778 03779 03780 inline void 03781 GetPot::variable::take(const char* Value, const char* FieldSeparator) 03782 { 03783 original = std::string(Value); // string member var 03784 value.clear(); // vector<string> member var 03785 03786 /* 03787 // separate string by white space delimiters using 'strtok' 03788 // thread safe usage of strtok (no static members) 03789 char* spt = 0; 03790 // make a copy of the 'Value' 03791 char* copy = new char[strlen(Value)+1]; 03792 strcpy(copy, Value); 03793 char* follow_token = strtok_r(copy, FieldSeparator, &spt); 03794 while (follow_token != 0) 03795 { 03796 value.push_back(std::string(follow_token)); 03797 follow_token = strtok_r(NULL, FieldSeparator, &spt); 03798 } 03799 03800 delete [] copy; 03801 */ 03802 03803 // Don't use strtok, instead tokenize the input char "Value" using std::string operations so 03804 // that the results end up in the local "value" member 03805 03806 // Construct std::string objects from the input char*s. I think the only 03807 // FieldSeparator recognized by GetPot is whitespace? 03808 std::string Value_str = std::string(Value); 03809 std::string delimiters = std::string(FieldSeparator); 03810 03811 // Skip delimiters at beginning. 03812 std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0); 03813 03814 // Find first "non-delimiter". 03815 std::string::size_type pos = Value_str.find_first_of(delimiters, lastPos); 03816 03817 // Loop over the input string until all the tokens have been pushed back 03818 // into the local "value" member. 03819 while (std::string::npos != pos || std::string::npos != lastPos) 03820 { 03821 // Found a token, add it to the vector. 03822 value.push_back(Value_str.substr(lastPos, pos - lastPos)); 03823 03824 // Skip delimiters. Note the "not_of" 03825 lastPos = Value_str.find_first_not_of(delimiters, pos); 03826 03827 // Find next "non-delimiter" 03828 pos = Value_str.find_first_of(delimiters, lastPos); 03829 } 03830 03831 // We're done, all the tokens should now be in the vector<string> 03832 } 03833 03834 inline 03835 GetPot::variable::~variable() 03836 {} 03837 03838 03839 03840 inline GetPot::variable& 03841 GetPot::variable::operator=(const GetPot::variable& Other) 03842 { 03843 if (&Other != this) 03844 { 03845 name = Other.name; 03846 value = Other.value; 03847 original = Other.original; 03848 } 03849 return *this; 03850 } 03851 03852 #ifdef GETPOT_NAMESPACE 03853 } 03854 #endif 03855 03856 #undef victorate 03857 03858 #endif // LIBMESH_GETPOT_H