getpot.h
Go to the documentation of this file.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-2010 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> 00039 // // with <fstream> 00040 #include <set> 00041 #include <sstream> 00042 #include <stdexcept> 00043 #include <string> 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_cast_int libMesh::libmesh_cast_int 00078 00079 #else // USE_LIBMESH 00080 00081 // Currently threaded GetPot use is only supported via libMesh Threads 00082 #define SCOPED_MUTEX 00083 00084 #define getpot_cerr std::cerr 00085 #define getpot_error() throw std::runtime_error 00086 #define getpot_cast_int static_cast 00087 00088 #endif 00089 00090 00091 00092 typedef std::vector<std::string> STRING_VECTOR; 00093 00094 #define victorate(TYPE, VARIABLE, ITERATOR) \ 00095 std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin(); \ 00096 for(; (ITERATOR) != (VARIABLE).end(); (ITERATOR)++) 00097 00098 // We allow GETPOT_NAMESPACE to be defined before this file is 00099 // included; if libraries using two different versions of GetPot might 00100 // be linked together, the result may be unsafe unless they're put in 00101 // different namespaces. 00102 #ifdef GETPOT_NAMESPACE 00103 namespace GETPOT_NAMESPACE { 00104 #endif 00105 00106 class GetPot { 00107 //-------- 00108 inline void _basic_initialization(); 00109 public: 00110 // (*) constructors, destructor, assignment operator ----------------------- 00111 inline GetPot(); 00112 inline GetPot(const GetPot&); 00113 inline GetPot(const int argc_, char** argv_, 00114 const char* FieldSeparator=0x0); 00115 inline GetPot(const char* FileName, 00116 const char* CommentStart=0x0, const char* CommentEnd=0x0, 00117 const char* FieldSeparator=0x0); 00118 inline GetPot(const std::string& FileName, 00119 const std::string& CommentStart = std::string("#"), 00120 const std::string& CommentEnd = std::string("\n"), 00121 const std::string& FieldSeparator = std::string(" \t\n")); 00122 inline ~GetPot(); 00123 inline GetPot& operator=(const GetPot&); 00124 00125 // Re-initialization methods 00126 inline void parse_command_line(const int argc_, char ** argv_, 00127 const char* FieldSeparator =0x0); 00128 inline void parse_input_file(const std::string& FileName, 00129 const std::string& CommentStart=std::string("#"), 00130 const std::string& CommentEnd=std::string("\n"), 00131 const std::string& FieldSeparator=std::string(" \t\n")); 00132 00133 // (*) absorbing contents of another GetPot object 00134 inline void absorb(const GetPot& Other); 00135 // -- for ufo detection: recording requested arguments, options etc. 00136 inline void clear_requests(); 00137 inline void disable_request_recording() { request_recording_f = false; } 00138 inline void enable_request_recording() { request_recording_f = true; } 00139 00140 // (*) direct access to command line arguments ----------------------------- 00141 inline const char* operator[](unsigned Idx) const; 00142 template <typename T> 00143 inline T get(unsigned Idx, const T& Default) const; 00144 inline const char* get(unsigned Idx, const char* Default) const; 00145 inline unsigned size() const; 00146 00147 // (*) flags --------------------------------------------------------------- 00148 inline bool options_contain(const char* FlagList) const; 00149 inline bool argument_contains(unsigned Idx, const char* FlagList) const; 00150 00151 // (*) variables ----------------------------------------------------------- 00152 // -- check for a variable 00153 inline bool have_variable(const char* VarName) const; 00154 inline bool have_variable(const std::string& VarName) const; 00155 // -- scalar values 00156 template<typename T> 00157 inline T operator()(const char* VarName, const T& Default) const; 00158 template<typename T> 00159 inline T operator()(const std::string& VarName, const T& Default) const; 00160 inline const char* operator()(const char* VarName, const char* Default) const; 00161 inline const char* operator()(const std::string& VarName, const char* Default) const; 00162 // -- vectors 00163 template<typename T> 00164 inline T operator()(const char* VarName, const T& Default, unsigned Idx) const; 00165 template<typename T> 00166 inline T operator()(const std::string& VarName, const T& Default, unsigned Idx) const; 00167 inline const char* operator()(const char* VarName, const char* Default, unsigned Idx) const; 00168 inline const char* operator()(const std::string& VarName, const char* Default, unsigned Idx) const; 00169 // (*) access varibles, but error out if not present ----------------------- 00170 // -- scalar values 00171 template<typename T> 00172 inline T get_value_no_default(const char* VarName, const T& Default) const; 00173 template<typename T> 00174 inline T get_value_no_default(const std::string& VarName, const T& Default) const; 00175 inline const char* get_value_no_default(const char* VarName, const char* Default) const; 00176 inline const char* get_value_no_default(const std::string& VarName, const char* Default) const; 00177 // -- vectors 00178 template<typename T> 00179 inline T get_value_no_default(const char* VarName, const T& Default, unsigned Idx) const; 00180 template<typename T> 00181 inline T get_value_no_default(const std::string& VarName, const T& Default, unsigned Idx) const; 00182 inline const char* get_value_no_default(const char* VarName, const char* Default, unsigned Idx) const; 00183 inline const char* get_value_no_default(const std::string& VarName, const char* Default, unsigned Idx) const; 00184 00185 // -- setting variables 00186 // i) from outside of GetPot (considering prefix etc.) 00187 // ii) from inside, use '_set_variable()' below 00188 template<typename T> 00189 inline void set(const char* VarName, const T& Value, const bool Requested = true); 00190 template<typename T> 00191 inline void set(const std::string& VarName, const T& Value, const bool Requested = true); 00192 inline void set(const char* VarName, const char* Value, const bool Requested = true); 00193 inline void set(const std::string& VarName, const char* Value, const bool Requested = true); 00194 00195 inline unsigned vector_variable_size(const char* VarName) const; 00196 inline unsigned vector_variable_size(const std::string& VarName) const; 00197 inline STRING_VECTOR get_variable_names() const; 00198 inline STRING_VECTOR get_section_names() const; 00199 inline 00200 std::set<std::string> get_overridden_variables() const; 00201 00202 // (*) cursor oriented functions ------------------------------------------- 00203 inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); } 00204 inline bool search_failed() const { return search_failed_f; } 00205 00206 // -- enable/disable search for an option in loop 00207 inline void disable_loop() { search_loop_f = false; } 00208 inline void enable_loop() { search_loop_f = true; } 00209 00210 // -- reset cursor to position '1' 00211 inline void reset_cursor(); 00212 inline void init_multiple_occurrence(); 00213 00214 // -- search for a certain option and set cursor to position 00215 inline bool search(const char* option); 00216 inline bool search(const std::string& option); 00217 inline bool search(unsigned No, const char* P, ...); 00218 // -- get argument at cursor++ 00219 template<typename T> 00220 inline T next(const T& Default); 00221 inline const char* next(const char* Default); 00222 // -- search for option and get argument at cursor++ 00223 template<typename T> 00224 inline T follow(const T& Default, const char* Option); 00225 inline const char* follow(const char* Default, const char* Option); 00226 // -- search for one of the given options and get argument that follows it 00227 template<typename T> 00228 inline T follow(const T& Default, unsigned No, const char* Option, ...); 00229 inline const char* follow(const char* Default, unsigned No, const char* Option, ...); 00230 // -- directly followed arguments 00231 template<typename T> 00232 inline T direct_follow(const T& Default, const char* Option); 00233 inline const char* direct_follow(const char* Default, const char* Option); 00234 00235 // (*) nominus arguments --------------------------------------------------- 00236 inline void reset_nominus_cursor(); 00237 inline STRING_VECTOR nominus_vector() const; 00238 inline unsigned nominus_size() const { 00239 return getpot_cast_int<unsigned>(idx_nominus.size()); 00240 } 00241 inline const char* next_nominus(); 00242 00243 // (*) unidentified flying objects ----------------------------------------- 00244 inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const; 00245 inline STRING_VECTOR unidentified_arguments(const std::set<std::string>& Knowns) const; 00246 inline STRING_VECTOR unidentified_arguments(const std::vector<std::string>& Knowns) const; 00247 inline STRING_VECTOR unidentified_arguments() const; 00248 00249 inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const; 00250 inline STRING_VECTOR unidentified_options(const std::set<std::string>& Knowns) const; 00251 inline STRING_VECTOR unidentified_options(const std::vector<std::string>& Knowns) const; 00252 inline STRING_VECTOR unidentified_options() const; 00253 00254 inline std::string unidentified_flags(const char* Known, 00255 int ArgumentNumber /* =-1 */) const; 00256 00257 inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const; 00258 inline STRING_VECTOR unidentified_variables(const std::set<std::string>& Knowns) const; 00259 inline STRING_VECTOR unidentified_variables(const std::vector<std::string>& Knowns) const; 00260 inline STRING_VECTOR unidentified_variables() const; 00261 00262 inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const; 00263 inline STRING_VECTOR unidentified_sections(const std::set<std::string>& Knowns) const; 00264 inline STRING_VECTOR unidentified_sections(const std::vector<std::string>& Knowns) const; 00265 inline STRING_VECTOR unidentified_sections() const; 00266 00267 inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const; 00268 inline STRING_VECTOR unidentified_nominuses(const std::set<std::string>& Knowns) const; 00269 inline STRING_VECTOR unidentified_nominuses(const std::vector<std::string>& Knowns) const; 00270 inline STRING_VECTOR unidentified_nominuses() const; 00271 00272 // (*) output -------------------------------------------------------------- 00273 // Print everything 00274 inline int print(std::ostream &out_stream = std::cout) const; 00275 // Print everything after skipping skip_count arguments, with a 00276 // custom prefix. skip_count defaults to 1 to handle the common 00277 // "executable input_file" command line case. 00278 inline int print(const char *custom_prefix, 00279 std::ostream &out_stream = std::cout, 00280 unsigned int skip_count=1) const; 00281 00282 private: 00283 // (*) Type Declaration ---------------------------------------------------- 00284 struct variable { 00285 //----------- 00286 // Variable to be specified on the command line or in input files. 00287 // (i.e. of the form var='12 312 341') 00288 00289 // -- constructors, destructors, assignment operator 00290 variable(); 00291 variable(const variable&); 00292 variable(const char* Name, const char* Value, const char* FieldSeparator); 00293 ~variable(); 00294 variable& operator=(const variable& Other); 00295 00296 void take(const char* Value, const char* FieldSeparator); 00297 00298 // -- get a specific element in the string vector 00299 // (return 0 if not present) 00300 const std::string* get_element(unsigned Idx) const; 00301 00302 // -- data memebers 00303 std::string name; // identifier of variable 00304 STRING_VECTOR value; // value of variable stored in vector 00305 std::string original; // value of variable as given on command line 00306 }; 00307 00308 // (*) member variables -------------------------------------------------------------- 00309 std::string prefix; // prefix automatically added in queries 00310 std::string section; // (for dollar bracket parsing) 00311 STRING_VECTOR section_list; // list of all parsed sections 00312 // -- argument vector 00313 STRING_VECTOR argv; // vector of command line arguments stored as strings 00314 unsigned cursor; // cursor for argv 00315 bool search_loop_f; // shall search start at beginning after 00316 // // reaching end of arg array ? 00317 bool search_failed_f; // flag indicating a failed search() operation 00318 // // (e.g. next() functions react with 'missed') 00319 std::set<std::string> overridden_vars; // vector of variables that were supplied more than once during parsing 00320 00321 // -- nominus vector 00322 int nominus_cursor; // cursor for nominus_pointers 00323 std::vector<unsigned> idx_nominus; // indecies of 'no minus' arguments 00324 00325 // -- variables 00326 // (arguments of the form "variable=value") 00327 std::vector<variable> variables; 00328 00329 // -- comment delimiters 00330 std::string _comment_start; 00331 std::string _comment_end; 00332 00333 // -- field separator (separating elements of a vector) 00334 std::string _field_separator; 00335 00336 // -- helper functor for creating sets of C-style strings 00337 struct ltstr { 00338 bool operator()(const char* s1, const char* s2) const { 00339 return strcmp(s1, s2) < 0; 00340 } 00341 }; 00342 00343 // -- we have some mutable non-thread-safe members, but we 00344 // want to be able to call const member functions from 00345 // multiple threads at once, so we'll wrap access to 00346 // mutable objects in a mutex. 00347 #if !defined(GETPOT_DISABLE_MUTEX) 00348 mutable libMesh::Threads::spin_mutex _getpot_mtx; 00349 #endif 00350 00351 // -- some functions return a char pointer to a string created on the fly. 00352 // this container makes them 'available' until the getpot object is destroyed. 00353 // user codes are recommended to instead request std::string values. 00354 // We use char* here because c_str() results are only 00355 // guaranteed to remain valid until a non-const string 00356 // method is called 00357 mutable std::set<const char*, ltstr> _internal_string_container; 00358 00359 // -- some functions return a char pointer to a temporarily existing string 00360 // this function adds them to our container 00361 const char* _internal_managed_copy(const std::string& Arg) const; 00362 00363 // -- keeping track about arguments that are requested, so that the UFO detection 00364 // can be simplified 00365 mutable std::set<std::string> _requested_arguments; 00366 mutable std::set<std::string> _requested_variables; 00367 mutable std::set<std::string> _requested_sections; 00368 00369 bool request_recording_f; // speed: request recording can be turned off 00370 00371 // -- if an argument is requested record it and the 'tag' the section branch to which 00372 // it belongs. Caution: both functions mark the sections as 'tagged'. 00373 // These are "const" functions but they do modify the 00374 // mutable _requested_* members 00375 void _record_argument_request(const std::string& Arg) const; 00376 void _record_variable_request(const std::string& Arg) const; 00377 00378 // (*) helper functions ---------------------------------------------------- 00379 // set variable from inside GetPot (no prefix considered) 00380 inline void _set_variable(const std::string& VarName, 00381 const std::string& Value, 00382 const bool Requested); 00383 00384 // -- produce three basic data vectors: 00385 // - argument vector 00386 // - nominus vector 00387 // - variable dictionary 00388 inline void _parse_argument_vector(const STRING_VECTOR& ARGV); 00389 00390 // -- helpers for argument list processing 00391 // * search for a variable in 'variables' array 00392 inline const variable* _find_variable(const char*) const; 00393 // * search (and record request) for a variable in 'variables' array 00394 inline const variable* _request_variable(const char*) const; 00395 // * support finding directly followed arguments 00396 inline const char* _match_starting_string(const char* StartString); 00397 // * support search for flags in a specific argument 00398 inline bool _check_flags(const std::string& Str, const char* FlagList) const; 00399 // * type conversion if possible 00400 template<typename T> 00401 inline T _convert_to_type(const std::string& String, const T& Default) const; 00402 inline std::string _convert_to_type(const std::string& String, const char* Default) const; 00403 template<typename T> 00404 inline T _convert_to_type_no_default(const char* VarName, const std::string& String, const T& Default) const; 00405 inline std::string _convert_to_type_no_default(const char* VarName, const std::string& String, const char* Default) const; 00406 // * prefix extraction 00407 const std::string _get_remaining_string(const std::string& String, 00408 const std::string& Start) const; 00409 // * search for a specific string 00410 inline bool _search_string_vector(const STRING_VECTOR& Vec, 00411 const std::string& Str) const; 00412 00413 // -- helpers to parse input file 00414 // create an argument vector based on data found in an input file, i.e.: 00415 // 1) delete comments (in between '_comment_start' '_comment_end') 00416 // 2) contract assignment expressions, such as 00417 // my-variable = '007 J. B.' 00418 // into 00419 // my-variable='007 J. B.' 00420 // 3) interprete sections like '[../my-section]' etc. 00421 inline void _skip_whitespace(std::istream& istr); 00422 inline const std::string _get_next_token(std::istream& istr); 00423 inline const std::string _get_string(std::istream& istr); 00424 inline const std::string _get_until_closing_bracket(std::istream& istr); 00425 inline const std::string _get_until_closing_square_bracket(std::istream& istr); 00426 00427 inline STRING_VECTOR _read_in_stream(std::istream& istr); 00428 inline STRING_VECTOR _read_in_file(const std::string& FileName); 00429 inline std::string _process_section_label(const std::string& Section, 00430 STRING_VECTOR& section_stack); 00431 00432 // -- dollar bracket expressions 00433 std::string _DBE_expand_string(const std::string& str); 00434 std::string _DBE_expand(const std::string& str); 00435 const GetPot::variable* _DBE_get_variable(const std::string& str); 00436 STRING_VECTOR _DBE_get_expr_list(const std::string& str, const unsigned ExpectedNumber); 00437 00438 template <typename T> 00439 static std::string _convert_from_type(const T& Value) { 00440 std::ostringstream out_string; 00441 out_string << Value; 00442 return out_string.str(); 00443 } 00444 00445 static STRING_VECTOR _get_section_tree(const std::string& FullPath) { 00446 // -- cuts a variable name into a tree of sub-sections. this is requested for recording 00447 // requested sections when dealing with 'ufo' detection. 00448 STRING_VECTOR result; 00449 for (std::size_t pos = 0; pos != FullPath.size(); ++pos) { 00450 if( FullPath[pos] == '/' ) { 00451 result.push_back(FullPath.substr(0,pos)); 00452 } 00453 } 00454 00455 return result; 00456 } 00457 }; 00458 00459 00461 // (*) constructors, destructor, assignment operator 00462 //............................................................................. 00463 // 00464 inline void 00465 GetPot::_basic_initialization() 00466 { 00467 cursor = 0; nominus_cursor = -1; 00468 search_failed_f = true; search_loop_f = true; 00469 prefix = ""; section = ""; 00470 00471 // automatic request recording for later ufo detection 00472 request_recording_f = true; 00473 00474 // comment start and end strings 00475 _comment_start = std::string("#"); 00476 _comment_end = std::string("\n"); 00477 00478 // default: separate vector elements by whitespaces 00479 _field_separator = " \t\n"; 00480 } 00481 00482 inline 00483 GetPot::GetPot() : 00484 prefix(), 00485 section(), 00486 section_list(), 00487 argv(), 00488 cursor(), 00489 search_loop_f(), 00490 search_failed_f(), 00491 nominus_cursor(), 00492 idx_nominus(), 00493 variables(), 00494 _comment_start(), 00495 _comment_end(), 00496 _field_separator(), 00497 _getpot_mtx(), 00498 _internal_string_container(), 00499 _requested_arguments(), 00500 _requested_variables(), 00501 _requested_sections(), 00502 request_recording_f() 00503 { 00504 _basic_initialization(); 00505 } 00506 00507 inline 00508 GetPot::GetPot(const int argc_, char ** argv_, 00509 const char* FieldSeparator /* =0x0 */) : 00510 // leave 'char**' non-const to honor less capable compilers ... 00511 prefix(), 00512 section(), 00513 section_list(), 00514 argv(), 00515 cursor(), 00516 search_loop_f(), 00517 search_failed_f(), 00518 nominus_cursor(), 00519 idx_nominus(), 00520 variables(), 00521 _comment_start(), 00522 _comment_end(), 00523 _field_separator(), 00524 _getpot_mtx(), 00525 _internal_string_container(), 00526 _requested_arguments(), 00527 _requested_variables(), 00528 _requested_sections(), 00529 request_recording_f() 00530 { 00531 this->parse_command_line(argc_, argv_, FieldSeparator); 00532 } 00533 00534 00535 inline void 00536 GetPot::parse_command_line(const int argc_, char ** argv_, 00537 const char* FieldSeparator /* =0x0 */) 00538 // leave 'char**' non-const to honor less capable compilers ... 00539 { 00540 _basic_initialization(); 00541 00542 // if specified -> overwrite default string 00543 if( FieldSeparator ) _field_separator = std::string(FieldSeparator); 00544 00545 // -- make an internal copy of the argument list: 00546 STRING_VECTOR _apriori_argv; 00547 // -- for the sake of clarity: we do want to include the first 00548 // argument of the first parsing source in the argument vector! 00549 // it will not be a nominus argument, though. This gives us a 00550 // minimum vector size of one which facilitates error checking 00551 // in many functions. Also the user will be able to retrieve 00552 // the name of his application or input file by "get[0]" 00553 _apriori_argv.push_back(std::string(argv_[0])); 00554 int i=1; 00555 for(; i<argc_; i++) { 00556 std::string tmp(argv_[i]); // recall the problem with temporaries, 00557 _apriori_argv.push_back(tmp); // reference counting in arguement lists ... 00558 } 00559 _parse_argument_vector(_apriori_argv); 00560 } 00561 00562 00563 inline 00564 GetPot::GetPot(const char* FileName, 00565 const char* CommentStart /* = 0x0 */, const char* CommentEnd /* = 0x0 */, 00566 const char* FieldSeparator/* = 0x0 */) : 00567 prefix(), 00568 section(), 00569 section_list(), 00570 argv(), 00571 cursor(), 00572 search_loop_f(), 00573 search_failed_f(), 00574 nominus_cursor(), 00575 idx_nominus(), 00576 variables(), 00577 _comment_start(), 00578 _comment_end(), 00579 _field_separator(), 00580 _getpot_mtx(), 00581 _internal_string_container(), 00582 _requested_arguments(), 00583 _requested_variables(), 00584 _requested_sections(), 00585 request_recording_f() 00586 { 00587 const std::string& StrCommentStart = CommentStart ? CommentStart : std::string("#"); 00588 const std::string& StrCommentEnd = CommentEnd ? CommentEnd : std::string("\n"); 00589 const std::string& StrFieldSeparator = FieldSeparator ? FieldSeparator : std::string(" \t\n"); 00590 this->parse_input_file(FileName, StrCommentStart, StrCommentEnd, StrFieldSeparator); 00591 } 00592 00593 00594 00595 inline 00596 GetPot::GetPot(const std::string& FileName, 00597 const std::string& CommentStart, 00598 const std::string& CommentEnd, 00599 const std::string& FieldSeparator) : 00600 prefix(), 00601 section(), 00602 section_list(), 00603 argv(), 00604 cursor(), 00605 search_loop_f(), 00606 search_failed_f(), 00607 nominus_cursor(), 00608 idx_nominus(), 00609 variables(), 00610 _comment_start(), 00611 _comment_end(), 00612 _field_separator(), 00613 _getpot_mtx(), 00614 _internal_string_container(), 00615 _requested_arguments(), 00616 _requested_variables(), 00617 _requested_sections(), 00618 request_recording_f() 00619 { 00620 this->parse_input_file(FileName, CommentStart, CommentEnd, FieldSeparator); 00621 } 00622 00623 00624 00625 inline void 00626 GetPot::parse_input_file(const std::string& FileName, 00627 const std::string& CommentStart, 00628 const std::string& CommentEnd, 00629 const std::string& FieldSeparator) 00630 { 00631 _basic_initialization(); 00632 00633 // overwrite default strings 00634 _comment_start = std::string(CommentStart); 00635 _comment_end = std::string(CommentEnd); 00636 _field_separator = FieldSeparator; 00637 00638 STRING_VECTOR _apriori_argv; 00639 // -- the first element of the argument vector stores the name of 00640 // the first parsing source; however, this element is not 00641 // parsed for variable assignments or nominuses. 00642 // 00643 // Regardless, we don't add more than one name to the argument 00644 // vector. 00645 _apriori_argv.push_back(FileName); 00646 00647 STRING_VECTOR args = _read_in_file(FileName.c_str()); 00648 _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end()); 00649 _parse_argument_vector(_apriori_argv); 00650 } 00651 00652 inline 00653 GetPot::GetPot(const GetPot& Other) : 00654 prefix(Other.prefix), 00655 section(Other.section), 00656 section_list(Other.section_list), 00657 argv(Other.argv), 00658 cursor(Other.cursor), 00659 search_loop_f(Other.search_loop_f), 00660 search_failed_f(Other.search_failed_f), 00661 overridden_vars(), 00662 nominus_cursor(Other.nominus_cursor), 00663 idx_nominus(Other.idx_nominus), 00664 variables(Other.variables), 00665 _comment_start(Other._comment_start), 00666 _comment_end(Other._comment_end), 00667 _field_separator(Other._field_separator), 00668 _getpot_mtx(Other._getpot_mtx), 00669 _internal_string_container(), 00670 _requested_arguments(Other._requested_arguments), 00671 _requested_variables(Other._requested_variables), 00672 _requested_sections(Other._requested_sections), 00673 request_recording_f(Other.request_recording_f) 00674 { 00675 std::set<const char*,ltstr>::const_iterator it = 00676 Other._internal_string_container.begin(); 00677 00678 const std::set<const char*,ltstr>::const_iterator end = 00679 Other._internal_string_container.end(); 00680 00681 for (; it != end; ++it) { 00682 const char* otherstr = *it; 00683 char* newcopy = new char[strlen(otherstr)+1]; 00684 strncpy(newcopy, otherstr, strlen(otherstr)+1); 00685 this->_internal_string_container.insert(newcopy); 00686 } 00687 } 00688 00689 inline 00690 GetPot::~GetPot() 00691 { 00692 // // may be some return strings had to be created, delete now ! 00693 std::set<const char*, ltstr>::const_iterator it = _internal_string_container.begin(); 00694 const std::set<const char*, ltstr>::const_iterator end = _internal_string_container.end(); 00695 for(; it != end; ++it) 00696 delete [] *it; 00697 } 00698 00699 inline GetPot& 00700 GetPot::operator=(const GetPot& Other) 00701 { 00702 if (&Other == this) return *this; 00703 00704 prefix = Other.prefix; 00705 section = Other.section; 00706 section_list = Other.section_list; 00707 argv = Other.argv; 00708 cursor = Other.cursor; 00709 search_loop_f = Other.search_loop_f; 00710 search_failed_f = Other.search_failed_f; 00711 nominus_cursor = Other.nominus_cursor; 00712 overridden_vars = Other.overridden_vars; 00713 idx_nominus = Other.idx_nominus; 00714 variables = Other.variables; 00715 _comment_start = Other._comment_start; 00716 _comment_end = Other._comment_end; 00717 _field_separator = Other._field_separator; 00718 _getpot_mtx = Other._getpot_mtx; 00719 _requested_arguments = Other._requested_arguments; 00720 _requested_variables = Other._requested_variables; 00721 _requested_sections = Other._requested_sections; 00722 request_recording_f = Other.request_recording_f; 00723 00724 std::set<const char*, ltstr>::const_iterator my_it = 00725 _internal_string_container.begin(); 00726 const std::set<const char*, ltstr>::const_iterator my_end = 00727 _internal_string_container.end(); 00728 00729 for(; my_it != my_end; ++my_it) 00730 delete [] *my_it; 00731 00732 _internal_string_container.clear(); 00733 00734 std::set<const char*,ltstr>::const_iterator it = 00735 Other._internal_string_container.begin(); 00736 const std::set<const char*,ltstr>::const_iterator end = 00737 Other._internal_string_container.end(); 00738 00739 for (; it != end; ++it) { 00740 const char* otherstr = *it; 00741 char* newcopy = new char[strlen(otherstr)+1]; 00742 strncpy(newcopy, otherstr, strlen(otherstr)+1); 00743 this->_internal_string_container.insert(newcopy); 00744 } 00745 00746 return *this; 00747 } 00748 00749 00750 inline void 00751 GetPot::absorb(const GetPot& Other) 00752 { 00753 if (&Other == this) return; 00754 00755 // variables that are not influenced by absorption: 00756 // _comment_start 00757 // _comment_end 00758 // cursor 00759 // nominus_cursor 00760 // search_failed 00761 // idx_nominus 00762 // search_loop_f 00763 argv = Other.argv; 00764 variables = Other.variables; 00765 00766 if( request_recording_f ) { 00767 // Get a lock before touching anything mutable 00768 SCOPED_MUTEX; 00769 00770 _requested_arguments.insert(Other._requested_arguments.begin(), Other._requested_arguments.end()); 00771 _requested_variables.insert(Other._requested_variables.begin(), Other._requested_variables.end()); 00772 _requested_sections.insert(Other._requested_sections.begin(), Other._requested_sections.end()); 00773 } 00774 00775 } 00776 00777 inline void 00778 GetPot::clear_requests() 00779 { 00780 // Get a lock before touching anything mutable 00781 SCOPED_MUTEX; 00782 00783 _requested_arguments.clear(); 00784 _requested_variables.clear(); 00785 _requested_sections.clear(); 00786 } 00787 00788 inline void 00789 GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV) 00790 { 00791 if( ARGV.empty() ) return; 00792 00793 // build internal databases: 00794 // 1) array with no-minus arguments (usually used as filenames) 00795 // 2) variable assignments: 00796 // 'variable name' '=' number | string 00797 STRING_VECTOR section_stack; 00798 STRING_VECTOR::const_iterator it = ARGV.begin(); 00799 00800 00801 section = ""; 00802 00803 // -- do not parse the first argument, so that this parsing source 00804 // name is not interpreted a s a nominus or so. If we already 00805 // have parsed arguments, don't bother adding another parsing 00806 // source name 00807 if (argv.empty()) 00808 argv.push_back(*it); 00809 ++it; 00810 00811 // -- loop over remaining arguments 00812 for(; it != ARGV.end(); ++it) { 00813 std::string arg = *it; 00814 00815 if( arg.length() == 0 ) continue; 00816 00817 // -- [section] labels and [include file] directives 00818 if( arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']' ) { 00819 00820 // Is this an include file directive? 00821 std::size_t include_pos = arg.find("include ", 1); 00822 if (include_pos != std::string::npos) { 00823 00824 const std::string includefile = 00825 _DBE_expand_string(arg.substr(9, arg.length()-9-include_pos)); 00826 00827 this->parse_input_file 00828 (includefile, _comment_start, _comment_end, _field_separator); 00829 } else { 00830 00831 // (*) sections are considered 'requested arguments' 00832 if( request_recording_f ) { 00833 // Get a lock before touching anything mutable 00834 SCOPED_MUTEX; 00835 00836 _requested_arguments.insert(arg); 00837 } 00838 00839 const std::string Name = _DBE_expand_string(arg.substr(1, arg.length()-2)); 00840 section = _process_section_label(Name, section_stack); 00841 // new section --> append to list of sections 00842 if( find(section_list.begin(), section_list.end(), section) == section_list.end() ) 00843 if( section.length() != 0 ) section_list.push_back(section); 00844 argv.push_back(arg); 00845 } 00846 } 00847 else { 00848 arg = section + _DBE_expand_string(arg); 00849 argv.push_back(arg); 00850 } 00851 00852 // -- separate array for nominus arguments 00853 if( arg[0] != '-' ) 00854 idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1)); 00855 00856 // -- variables: does arg contain a '=' operator ? 00857 const std::size_t equals_pos = arg.find_first_of('='); 00858 if( equals_pos != std::string::npos ) { 00859 // (*) record for later ufo detection 00860 // arguments carriying variables are always treated as 'requested' arguments. 00861 // unrequested variables have to be detected with the ufo-variable 00862 // detection routine. 00863 if( request_recording_f ) { 00864 // Get a lock before touching anything mutable 00865 SCOPED_MUTEX; 00866 00867 _requested_arguments.insert(arg); 00868 } 00869 00870 // => arg (from start to '=') = Name of variable 00871 // (from '=' to end) = value of variable 00872 _set_variable(arg.substr(0,equals_pos), 00873 arg.substr(equals_pos+1), false); 00874 } 00875 } 00876 } 00877 00878 00879 inline STRING_VECTOR 00880 GetPot::_read_in_file(const std::string& FileName) 00881 { 00882 std::ifstream i(FileName.c_str()); 00883 if( ! i ) return STRING_VECTOR(); 00884 // argv[0] == the filename of the file that was read in 00885 return _read_in_stream(i); 00886 } 00887 00888 inline STRING_VECTOR 00889 GetPot::_read_in_stream(std::istream& istr) 00890 { 00891 STRING_VECTOR brute_tokens; 00892 while(istr) { 00893 _skip_whitespace(istr); 00894 const std::string Token = _get_next_token(istr); 00895 // Allow 'keyword =' to parse with an empty string as value. 00896 // Only break at EOF. 00897 // if( Token.length() == 0 || Token[0] == EOF) break; 00898 if( Token[0] == EOF) break; 00899 brute_tokens.push_back(Token); 00900 } 00901 00902 // -- reduce expressions of token1'='token2 to a single 00903 // string 'token1=token2' 00904 // -- copy everything into 'argv' 00905 // -- arguments preceded by something like '[' name ']' (section) 00906 // produce a second copy of each argument with a prefix '[name]argument' 00907 unsigned i1 = 0; 00908 unsigned i2 = 1; 00909 unsigned i3 = 2; 00910 00911 STRING_VECTOR arglist; 00912 while( i1 < brute_tokens.size() ) { 00913 // 1) concatenate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef' 00914 // note: java.lang.String: substring(a,b) = from a to b-1 00915 // C++ string: substr(a,b) = from a to a + b 00916 std::string result; 00917 if( i2 < brute_tokens.size() && brute_tokens[i2] == "=" ) { 00918 if( i3 >= brute_tokens.size() ) 00919 result = brute_tokens[i1] + brute_tokens[i2]; 00920 else 00921 result = brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3]; 00922 i1 = i3+1; i2 = i3+2; i3 = i3+3; 00923 } 00924 else if ( i2 < brute_tokens.size() && 00925 brute_tokens[i2].length() > 0 && 00926 brute_tokens[i2][0] == '=' ) { 00927 // This case should not be hit if '=' at the beginning of a word 00928 // is always separated into its own word 00929 result = brute_tokens[i1] + brute_tokens[i2]; 00930 i1 = i3; i2 = i3+1; i3 = i3+2; 00931 } 00932 else if ( i2 < brute_tokens.size() && brute_tokens[i1][brute_tokens[i1].size()-1] == '=' ) { 00933 result = brute_tokens[i1] + brute_tokens[i2]; 00934 i1 = i3; i2 = i3+1; i3 = i3+2; 00935 } 00936 else { 00937 result = brute_tokens[i1]; 00938 i1=i2; i2=i3; i3++; 00939 } 00940 // Now strip out any comment 00941 size_t comment_start_loc = result.find(_comment_start, 0); 00942 if (comment_start_loc != std::string::npos) 00943 { 00944 result = result.substr(0, comment_start_loc); 00945 } 00946 arglist.push_back(result); 00947 } 00948 return arglist; 00949 } 00950 00951 inline void 00952 GetPot::_skip_whitespace(std::istream& istr) 00953 // find next non-whitespace while deleting comments 00954 { 00955 int tmp = istr.get(); 00956 do { 00957 // -- search a non whitespace 00958 while( isspace(tmp) ) { 00959 tmp = istr.get(); 00960 if( ! istr ) return; 00961 } 00962 00963 // -- look if characters match the comment starter string 00964 const std::istream::pos_type Pos = istr.tellg(); 00965 unsigned i=0; 00966 for(; i<_comment_start.length() ; i++) { 00967 if( tmp != _comment_start[i] ) { 00968 istr.seekg(Pos); 00969 // -- one step more backwards, since 'tmp' already at non-whitespace 00970 istr.unget(); 00971 return; 00972 } 00973 00974 // RHS: Why is this here? It breaks on empty comments 00975 // tmp = istr.get(); 00976 // if( ! istr ) { istr.unget(); return; } 00977 } 00978 // 'tmp' contains last character of _comment_starter 00979 00980 // -- comment starter found -> search for comment ender 00981 unsigned match_no=0; 00982 while(1+1 == 2) { 00983 tmp = istr.get(); 00984 if( ! istr ) { istr.unget(); return; } 00985 00986 if( tmp == _comment_end[match_no] ) { 00987 match_no++; 00988 if( match_no == _comment_end.length() ) { 00989 istr.unget(); 00990 break; // shuffle more whitespace, end of comment found 00991 } 00992 } 00993 else 00994 match_no = 0; 00995 } 00996 00997 tmp = istr.get(); 00998 00999 } while( istr ); 01000 istr.unget(); 01001 } 01002 01003 inline const std::string 01004 GetPot::_get_next_token(std::istream& istr) 01005 // get next concatenates string token. consider quotes that embrace 01006 // whitespaces 01007 { 01008 std::string token; 01009 int tmp = 0; 01010 int last_letter = 0; 01011 while(1+1 == 2) { 01012 last_letter = tmp; tmp = istr.get(); 01013 if( tmp == '=' ) 01014 { 01015 // Always break at '='. 01016 // This separates '=' at the beginning of a word into its own word. 01017 token += getpot_cast_int<char>(tmp); 01018 return token; 01019 } 01020 else if( tmp == EOF 01021 || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\') ) { 01022 return token; 01023 } 01024 else if( tmp == '\'' && last_letter != '\\' ) { 01025 // QUOTES: un-backslashed quotes => it's a string 01026 token += _get_string(istr); 01027 continue; 01028 } 01029 else if( tmp == '{' && last_letter == '$') { 01030 token += '{' + _get_until_closing_bracket(istr); 01031 continue; 01032 } 01033 else if( tmp == '[') { 01034 token += '[' + _get_until_closing_square_bracket(istr); 01035 continue; 01036 } 01037 else if( tmp == '$' && last_letter == '\\') { 01038 token += getpot_cast_int<char>(tmp); tmp = 0; // so that last_letter will become = 0, not '$'; 01039 continue; 01040 } 01041 else if( tmp == '\\' && last_letter != '\\') 01042 continue; // don't append un-backslashed backslashes 01043 token += getpot_cast_int<char>(tmp); 01044 } 01045 } 01046 01047 inline const std::string 01048 GetPot::_get_string(std::istream& istr) 01049 // parse input until next matching ' 01050 { 01051 std::string str; 01052 int tmp = 0; 01053 int last_letter = 0; 01054 while(1 + 1 == 2) { 01055 last_letter = tmp; tmp = istr.get(); 01056 if( tmp == EOF) return str; 01057 // un-backslashed quotes => it's the end of the string 01058 else if( tmp == '\'' && last_letter != '\\') return str; 01059 else if( tmp == '\\' && last_letter != '\\') continue; // don't append 01060 01061 str += getpot_cast_int<char>(tmp); 01062 } 01063 } 01064 01065 inline const std::string 01066 GetPot::_get_until_closing_bracket(std::istream& istr) 01067 // parse input until next matching } 01068 { 01069 std::string str = ""; 01070 int tmp = 0; 01071 int last_letter = 0; 01072 int brackets = 1; 01073 while(1 + 1 == 2) { 01074 last_letter = tmp; tmp = istr.get(); 01075 if( tmp == EOF) return str; 01076 else if( tmp == '{' && last_letter == '$') brackets += 1; 01077 else if( tmp == '}') { 01078 brackets -= 1; 01079 // un-backslashed brackets => it's the end of the string 01080 if( brackets == 0) return str + '}'; 01081 else if( tmp == '\\' && last_letter != '\\') 01082 continue; // do not append an unbackslashed backslash 01083 } 01084 str += getpot_cast_int<char>(tmp); 01085 } 01086 } 01087 01088 01089 inline const std::string 01090 GetPot::_get_until_closing_square_bracket(std::istream& istr) 01091 // parse input until next matching ] 01092 { 01093 std::string str = ""; 01094 int tmp = 0; 01095 int brackets = 1; 01096 while(1 + 1 == 2) { 01097 tmp = istr.get(); 01098 if( tmp == EOF) return str; 01099 else if( tmp == '[') { 01100 brackets += 1; 01101 } 01102 else if( tmp == ']') { 01103 brackets -= 1; 01104 if( brackets == 0) return str + ']'; 01105 } 01106 str += getpot_cast_int<char>(tmp); 01107 } 01108 } 01109 01110 inline std::string 01111 GetPot::_process_section_label(const std::string& Section, 01112 STRING_VECTOR& section_stack) 01113 { 01114 std::string sname = Section; 01115 // 1) subsection of actual section ('./' prefix) 01116 if( sname.length() >= 2 && sname.substr(0, 2) == "./" ) { 01117 sname = sname.substr(2); 01118 } 01119 // 2) subsection of parent section ('../' prefix) 01120 else if( sname.length() >= 3 && sname.substr(0, 3) == "../" ) { 01121 do { 01122 if( section_stack.end() != section_stack.begin() ) 01123 section_stack.pop_back(); 01124 sname = sname.substr(3); 01125 } while( sname.substr(0, 3) == "../" ); 01126 } 01127 // 3) subsection of the root-section 01128 else { 01129 section_stack.erase(section_stack.begin(), section_stack.end()); 01130 // [] => back to root section 01131 } 01132 01133 if( sname != "" ) { 01134 // parse section name for 'slashes' 01135 unsigned i=0; 01136 while( i < sname.length() ) { 01137 if( sname[i] == '/' ) { 01138 section_stack.push_back(sname.substr(0,i)); 01139 if( i+1 < sname.length()-1 ) 01140 sname = sname.substr(i+1); 01141 i = 0; 01142 } 01143 else 01144 i++; 01145 } 01146 section_stack.push_back(sname); 01147 } 01148 std::string section_label = ""; 01149 if( !section_stack.empty() ) { 01150 victorate(std::string, section_stack, it) 01151 section_label += *it + "/"; 01152 } 01153 return section_label; 01154 } 01155 01156 // Use C++ istream/ostream to handle most type conversions. 01157 template <typename T> 01158 inline T 01159 GetPot::_convert_to_type(const std::string& String, const T& Default) const 01160 { 01161 std::istringstream in_string(String); 01162 T retval; 01163 in_string >> retval; 01164 if (in_string.fail()) 01165 retval = Default; 01166 return retval; 01167 } 01168 01169 // copy string - operator>> would have stopped upon seeing whitespace! 01170 template <> 01171 inline std::string 01172 GetPot::_convert_to_type(const std::string& String, const std::string&) const 01173 { 01174 return String; 01175 } 01176 01177 // copy string 01178 inline std::string 01179 GetPot::_convert_to_type(const std::string& String, const char*) const 01180 { 01181 return String; 01182 } 01183 01184 // be more liberal than std C++ in what we interpret as a boolean 01185 template<> 01186 inline bool 01187 GetPot::_convert_to_type<bool>(const std::string& String, const bool& Default) const 01188 { 01189 std::string newstring(String); 01190 //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper); 01191 for (unsigned int i=0; i<newstring.length(); ++i) 01192 { 01193 newstring[i]=getpot_cast_int<char>(toupper(newstring[i])); 01194 } 01195 01196 // "true"/"True"/"TRUE" should work 01197 if (newstring.find("TRUE")!=std::string::npos) return true; 01198 if (newstring.find("FALSE")!=std::string::npos) return false; 01199 01200 // And if we don't find that, let's search for an integer and use C unsigned 01201 // int->bool conversion before giving up; i.e. a user could specify "0" for 01202 // false or "1" for true 01203 std::istringstream in_string(String); 01204 unsigned int retval; 01205 in_string >> retval; 01206 if (in_string.fail()) 01207 return Default; 01208 01209 return retval; 01210 } 01211 01212 // Use C++ istream/ostream to handle most type conversions. 01213 template <typename T> 01214 inline T 01215 GetPot::_convert_to_type_no_default(const char* VarName, const std::string& String, const T&) const 01216 { 01217 std::istringstream in_string(String); 01218 T retval; 01219 in_string >> retval; 01220 if (in_string.fail()) 01221 { 01222 getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl; 01223 getpot_cerr <<" value = "<<String<<" expected type = "<<typeid(T).name()<<std::endl; 01224 getpot_error(); 01225 } 01226 return retval; 01227 } 01228 01229 // copy string - operator>> would have stopped upon seeing whitespace! 01230 template <> 01231 inline std::string 01232 GetPot::_convert_to_type_no_default(const char*, const std::string& String, const std::string&) const 01233 { 01234 return String; 01235 } 01236 01237 // copy string 01238 inline std::string 01239 GetPot::_convert_to_type_no_default(const char*, const std::string& String, const char*) const 01240 { 01241 return String; 01242 } 01243 01244 // be more liberal than std C++ in what we interpret as a boolean 01245 template<> 01246 inline bool 01247 GetPot::_convert_to_type_no_default<bool>(const char* VarName, const std::string& String, const bool&) const 01248 { 01249 std::string newstring(String); 01250 //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper); 01251 for (unsigned int i=0; i<newstring.length(); ++i) 01252 { 01253 newstring[i]=getpot_cast_int<char>(toupper(newstring[i])); 01254 } 01255 01256 // "true"/"True"/"TRUE" should work 01257 if (newstring.find("TRUE")!=std::string::npos) return true; 01258 if (newstring.find("FALSE")!=std::string::npos) return false; 01259 01260 // And if we don't find that, let's search for an integer and use C unsigned 01261 // int->bool conversion before giving up; i.e. a user could specify "0" for 01262 // false or "1" for true 01263 std::istringstream in_string(String); 01264 unsigned int retval; 01265 in_string >> retval; 01266 if (in_string.fail()) 01267 { 01268 getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl; 01269 getpot_cerr <<" value = "<<String<<" expected type = "<<typeid(bool).name()<<std::endl; 01270 getpot_error(); 01271 } 01272 01273 return retval; 01274 } 01275 01276 inline const char* 01277 GetPot::_internal_managed_copy(const std::string& Arg) const 01278 { 01279 const char* arg = Arg.c_str(); 01280 01281 // Get a lock before touching anything mutable 01282 SCOPED_MUTEX; 01283 01284 // See if there's already an identical string saved 01285 std::set<const char*,ltstr>::const_iterator it = 01286 _internal_string_container.find(arg); 01287 01288 // If so, return it 01289 if (it != _internal_string_container.end()) 01290 return *it; 01291 01292 // Otherwise, create a new one 01293 char* newcopy = new char[strlen(arg)+1]; 01294 strncpy(newcopy, arg, strlen(arg)+1); 01295 _internal_string_container.insert(newcopy); 01296 return newcopy; 01297 } 01298 01300 // (*) cursor oriented functions 01301 //............................................................................. 01302 inline const std::string 01303 GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const 01304 // Checks if 'String' begins with 'Start' and returns the remaining String. 01305 // Returns None if String does not begin with Start. 01306 { 01307 if( Start == "" ) return String; 01308 // note: java.lang.String: substring(a,b) = from a to b-1 01309 // C++ string: substr(a,b) = from a to a + b 01310 if( String.find(Start) == 0 ) return String.substr(Start.length()); 01311 else return ""; 01312 } 01313 01314 // -- search for a certain argument and set cursor to position 01315 inline bool 01316 GetPot::search(const std::string &Option) 01317 { 01318 return search(Option.c_str()); 01319 } 01320 01321 // -- search for a certain argument and set cursor to position 01322 inline bool 01323 GetPot::search(const char* Option) 01324 { 01325 unsigned OldCursor = cursor; 01326 const std::string SearchTerm = prefix + Option; 01327 01328 // (*) record requested arguments for later ufo detection 01329 _record_argument_request(SearchTerm); 01330 01331 if( OldCursor >= argv.size() ) 01332 OldCursor = getpot_cast_int<unsigned>(argv.size() - 1); 01333 search_failed_f = true; 01334 01335 // (*) first loop from cursor position until end 01336 unsigned c = cursor; 01337 for(; c < argv.size(); c++) { 01338 if( argv[c] == SearchTerm ) 01339 { cursor = c; search_failed_f = false; return true; } 01340 } 01341 if( ! search_loop_f ) return false; 01342 01343 // (*) second loop from 0 to old cursor position 01344 for(c = 1; c < OldCursor; c++) { 01345 if( argv[c] == SearchTerm ) 01346 { cursor = c; search_failed_f = false; return true; } 01347 } 01348 // in case nothing is found the cursor stays where it was 01349 return false; 01350 } 01351 01352 01353 inline bool 01354 GetPot::search(unsigned No, const char* P, ...) 01355 { 01356 // (*) recording the requested arguments happens in subroutine 'search' 01357 if( No == 0 ) return false; 01358 01359 // search for the first argument 01360 if( search(P) == true ) return true; 01361 01362 // start interpreting variable argument list 01363 va_list ap; 01364 va_start(ap, P); 01365 unsigned i = 1; 01366 for(; i < No; i++) { 01367 char* Opt = va_arg(ap, char *); 01368 // (*) search records itself for later ufo detection 01369 if( search(Opt) == true ) break; 01370 } 01371 01372 if( i < No ) { 01373 i++; 01374 // loop was left before end of array --> hit but 01375 // make sure that the rest of the search terms is marked 01376 // as requested. 01377 for(; i < No; i++) { 01378 char* Opt = va_arg(ap, char *); 01379 // (*) record requested arguments for later ufo detection 01380 _record_argument_request(Opt); 01381 } 01382 va_end(ap); 01383 return true; 01384 } 01385 01386 va_end(ap); 01387 // loop was left normally --> no hit 01388 return false; 01389 } 01390 01391 inline void 01392 GetPot::reset_cursor() 01393 { search_failed_f = false; cursor = 0; } 01394 01395 inline void 01396 GetPot::init_multiple_occurrence() 01397 { disable_loop(); reset_cursor(); } 01399 // (*) direct access to command line arguments 01400 //............................................................................. 01401 // 01402 inline const char* 01403 GetPot::operator[](unsigned idx) const 01404 { return idx<argv.size() ? argv[idx].c_str() : 0; } 01405 01406 template <typename T> 01407 inline T 01408 GetPot::get(unsigned int Idx, const T& Default) const 01409 { 01410 if( Idx >= argv.size() ) return Default; 01411 return _convert_to_type(argv[Idx], Default); 01412 } 01413 01414 inline const char* 01415 GetPot::get(unsigned int Idx, const char* Default) const 01416 { 01417 if( Idx >= argv.size() ) return Default; 01418 return argv[Idx].c_str(); 01419 } 01420 01421 inline unsigned 01422 GetPot::size() const 01423 { return getpot_cast_int<unsigned>(argv.size()); } 01424 01425 01426 // -- next() function group 01427 template <typename T> 01428 inline T 01429 GetPot::next(const T& Default) 01430 { 01431 if( search_failed_f ) return Default; 01432 cursor++; 01433 if( cursor >= argv.size() ) 01434 { cursor = getpot_cast_int<unsigned>(argv.size()); return Default; } 01435 01436 // (*) record requested argument for later ufo detection 01437 _record_argument_request(argv[cursor]); 01438 01439 const std::string Remain = _get_remaining_string(argv[cursor], prefix); 01440 01441 return Remain != "" ? _convert_to_type(Remain, Default) : Default; 01442 } 01443 01444 inline const char* 01445 GetPot::next(const char* Default) 01446 { 01447 return _internal_managed_copy(next(std::string(Default))); 01448 } 01449 01450 // -- follow() function group 01451 // distinct option to be searched for 01452 template <typename T> 01453 inline T 01454 GetPot::follow(const T& Default, const char* Option) 01455 { 01456 // (*) record requested of argument is entirely handled in 'search()' and 'next()' 01457 if( search(Option) == false ) return Default; 01458 return next(Default); 01459 } 01460 01461 inline const char* 01462 GetPot::follow(const char* Default, const char* Option) 01463 { 01464 return _internal_managed_copy(follow(std::string(Default), Option)); 01465 } 01466 01467 // -- second follow() function group 01468 // multiple option to be searched for 01469 template <typename T> 01470 inline T 01471 GetPot::follow(const T& Default, unsigned int No, const char* P, ...) 01472 { 01473 // (*) record requested of argument is entirely handled in 'search()' and 'next()' 01474 if( No == 0 ) return Default; 01475 if( search(P) == true ) return next(Default); 01476 01477 va_list ap; 01478 va_start(ap, P); 01479 unsigned i=1; 01480 for(; i<No; i++) { 01481 char* Opt = va_arg(ap, char *); 01482 if( search(Opt) == true ) { 01483 va_end(ap); 01484 return next(Default); 01485 } 01486 } 01487 va_end(ap); 01488 return Default; 01489 } 01490 01491 inline const char* 01492 GetPot::follow(const char* Default, unsigned No, const char* P, ...) 01493 { 01494 // (*) record requested of argument is entirely handled in 'search()' and 'next()' 01495 if( No == 0 ) return Default; 01496 if( search(P) == true ) return next(Default); 01497 01498 va_list ap; 01499 va_start(ap, P); 01500 unsigned i=1; 01501 for(; i<No; i++) { 01502 char* Opt = va_arg(ap, char *); 01503 if( search(Opt) == true ) { 01504 va_end(ap); 01505 return next(Default); 01506 } 01507 } 01508 va_end(ap); 01509 return Default; 01510 } 01511 01513 // (*) directly connected options 01514 //............................................................................. 01515 // 01516 template <typename T> 01517 inline T 01518 GetPot::direct_follow(const T& Default, const char* Option) 01519 { 01520 const char* FollowStr = _match_starting_string(Option); 01521 01522 // (*) record requested of argument for later ufo-detection 01523 _record_argument_request(std::string(Option) + FollowStr); 01524 01525 if( FollowStr == 0 ) return Default; 01526 if( ++cursor >= argv.size() ) 01527 cursor = getpot_cast_int<unsigned>(argv.size()); 01528 return _convert_to_type(FollowStr, Default); 01529 } 01530 01531 inline const char* 01532 GetPot::direct_follow(const char* Default, const char* Option) 01533 { 01534 return _internal_managed_copy(direct_follow(std::string(Default), Option)); 01535 } 01536 01537 inline const char* 01538 GetPot::_match_starting_string(const char* StartString) 01539 // pointer to the place where the string after 01540 // the match inside the found argument starts. 01541 // 0 no argument matches the starting string. 01542 { 01543 const unsigned N = 01544 getpot_cast_int<unsigned>(strlen(StartString)); 01545 unsigned OldCursor = cursor; 01546 01547 if( OldCursor >= argv.size() ) 01548 OldCursor = getpot_cast_int<unsigned>(argv.size() - 1); 01549 search_failed_f = true; 01550 01551 // (*) first loop from cursor position until end 01552 unsigned c = cursor; 01553 for(; c < argv.size(); c++) { 01554 if( strncmp(StartString, argv[c].c_str(), N) == 0) 01555 { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); } 01556 } 01557 01558 if( ! search_loop_f ) return NULL; 01559 01560 // (*) second loop from 0 to old cursor position 01561 for(c = 1; c < OldCursor; c++) { 01562 if( strncmp(StartString, argv[c].c_str(), N) == 0) 01563 { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); } 01564 } 01565 return 0; 01566 } 01567 01569 // (*) search for flags 01570 //............................................................................. 01571 // 01572 inline bool 01573 GetPot::options_contain(const char* FlagList) const 01574 { 01575 // go through all arguments that start with a '-' (but not '--') 01576 std::string str; 01577 STRING_VECTOR::const_iterator it = argv.begin(); 01578 for(; it != argv.end(); ++it) { 01579 str = _get_remaining_string(*it, prefix); 01580 01581 if( str.length() >= 2 && str[0] == '-' && str[1] != '-' ) 01582 if( _check_flags(str, FlagList) ) return true; 01583 } 01584 return false; 01585 } 01586 01587 inline bool 01588 GetPot::argument_contains(unsigned Idx, const char* FlagList) const 01589 { 01590 if( Idx >= argv.size() ) return false; 01591 01592 // (*) record requested of argument for later ufo-detection 01593 // an argument that is checked for flags is considered to be 'requested' 01594 _record_argument_request(argv[Idx]); 01595 01596 if( prefix == "" ) 01597 // search argument for any flag in flag list 01598 return _check_flags(argv[Idx], FlagList); 01599 01600 // if a prefix is set, then the argument index is the index 01601 // inside the 'namespace' 01602 // => only check list of arguments that start with prefix 01603 unsigned no_matches = 0; 01604 unsigned i=0; 01605 for(; i<argv.size(); i++) { 01606 const std::string Remain = _get_remaining_string(argv[i], prefix); 01607 if( Remain != "") { 01608 no_matches += 1; 01609 if( no_matches == Idx) 01610 return _check_flags(Remain, FlagList); 01611 } 01612 } 01613 // no argument in this namespace 01614 return false; 01615 } 01616 01617 inline bool 01618 GetPot::_check_flags(const std::string& Str, const char* FlagList) const 01619 { 01620 const char* p=FlagList; 01621 for(; *p != '\0' ; p++) 01622 if( Str.find(*p) != std::string::npos ) return true; // found something 01623 return false; 01624 } 01625 01627 // (*) nominus arguments 01628 inline STRING_VECTOR 01629 GetPot::nominus_vector() const 01630 // return vector of nominus arguments 01631 { 01632 STRING_VECTOR nv; 01633 std::vector<unsigned>::const_iterator it = idx_nominus.begin(); 01634 for(; it != idx_nominus.end(); ++it) { 01635 nv.push_back(argv[*it]); 01636 01637 // (*) record for later ufo-detection 01638 // when a nominus vector is requested, the entire set of nominus arguments are 01639 // tagged as 'requested' 01640 _record_argument_request(argv[*it]); 01641 } 01642 return nv; 01643 } 01644 01645 inline const char* 01646 GetPot::next_nominus() 01647 { 01648 if( nominus_cursor < int(idx_nominus.size()) - 1 ) { 01649 const std::string Tmp = argv[idx_nominus[++nominus_cursor]]; 01650 01651 // (*) record for later ufo-detection 01652 _record_argument_request(Tmp); 01653 01654 return Tmp.c_str(); 01655 } 01656 return 0; 01657 } 01658 01659 inline void 01660 GetPot::reset_nominus_cursor() 01661 { nominus_cursor = -1; } 01663 // (*) variables 01664 //............................................................................. 01665 // 01666 inline bool 01667 GetPot::have_variable(const char* VarName) const 01668 { 01669 const variable* sv = _request_variable(VarName); 01670 if (sv == 0) return false; 01671 return true; 01672 } 01673 01674 inline bool 01675 GetPot::have_variable(const std::string& VarName) const 01676 { 01677 return have_variable(VarName.c_str()); 01678 } 01679 01680 template <typename T> 01681 inline T 01682 GetPot::operator()(const char* VarName, const T& Default) const 01683 { 01684 // (*) recording of requested variables happens in '_request_variable()' 01685 const variable* sv = _request_variable(VarName); 01686 if( sv == 0 ) return Default; 01687 return _convert_to_type(sv->original, Default); 01688 } 01689 01690 template <typename T> 01691 inline T 01692 GetPot::operator()(const std::string& VarName, const T& Default) const 01693 { 01694 return operator()(VarName.c_str(), Default); 01695 } 01696 01697 inline const char* 01698 GetPot::operator()(const char* VarName, const char* Default) const 01699 { 01700 return _internal_managed_copy(operator()(VarName, std::string(Default))); 01701 } 01702 01703 inline const char* 01704 GetPot::operator()(const std::string& VarName, const char* Default) const 01705 { 01706 return operator()(VarName.c_str(), Default); 01707 } 01708 01709 template <typename T> 01710 inline T 01711 GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const 01712 { 01713 // (*) recording of requested variables happens in '_request_variable()' 01714 const variable* sv = _request_variable(VarName); 01715 if( sv == 0 ) return Default; 01716 const std::string* element = sv->get_element(Idx); 01717 if( element == 0 ) return Default; 01718 return _convert_to_type(*element, Default); 01719 } 01720 01721 template <typename T> 01722 inline T 01723 GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const 01724 { 01725 return operator()(VarName.c_str(), Default, Idx); 01726 } 01727 01728 inline const char* 01729 GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const 01730 { 01731 return _internal_managed_copy(operator()(VarName, std::string(Default), Idx)); 01732 } 01733 01734 inline const char* 01735 GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const 01736 { 01737 return operator()(VarName.c_str(), Default, Idx); 01738 } 01739 01740 template <typename T> 01741 inline T 01742 GetPot::get_value_no_default(const char* VarName, const T& Default ) const 01743 { 01744 // (*) recording of requested variables happens in '_request_variable()' 01745 const variable* sv = _request_variable(VarName); 01746 if( sv == 0 ) 01747 { 01748 getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl; 01749 getpot_error(); 01750 } 01751 return _convert_to_type_no_default(VarName, sv->original, Default); 01752 } 01753 01754 template <typename T> 01755 inline T 01756 GetPot::get_value_no_default(const std::string& VarName, const T& Default ) const 01757 { 01758 return get_value_no_default(VarName.c_str(),Default); 01759 } 01760 01761 inline const char* 01762 GetPot::get_value_no_default(const char* VarName, const char* Default) const 01763 { 01764 return _internal_managed_copy(get_value_no_default(VarName, Default)); 01765 } 01766 01767 inline const char* 01768 GetPot::get_value_no_default(const std::string& VarName, const char* Default ) const 01769 { 01770 return get_value_no_default(VarName.c_str(),Default); 01771 } 01772 01773 template <typename T> 01774 inline T 01775 GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const 01776 { 01777 // (*) recording of requested variables happens in '_request_variable()' 01778 const variable* sv = _request_variable(VarName); 01779 if( sv == 0 ){ 01780 getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl; 01781 getpot_error(); 01782 } 01783 const std::string* element = sv->get_element(Idx); 01784 if( element == 0 ){ 01785 getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl; 01786 getpot_error(); 01787 } 01788 return _convert_to_type_no_default(VarName, *element, Default); 01789 } 01790 01791 template <typename T> 01792 inline T 01793 GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const 01794 { 01795 return get_value_no_default(VarName.c_str(), Default, Idx); 01796 } 01797 01798 inline const char* 01799 GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const 01800 { 01801 return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx)); 01802 } 01803 01804 inline const char* 01805 GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const 01806 { 01807 return get_value_no_default(VarName.c_str(), Default, Idx); 01808 } 01809 01810 inline void 01811 GetPot::_record_argument_request(const std::string& Name) const 01812 { 01813 if( ! request_recording_f ) return; 01814 01815 // Get a lock before touching anything mutable 01816 SCOPED_MUTEX; 01817 01818 // (*) record requested variable for later ufo detection 01819 _requested_arguments.insert(Name); 01820 01821 // (*) record considered section for ufo detection 01822 STRING_VECTOR STree = _get_section_tree(Name); 01823 victorate(std::string, STree, it) 01824 if( _requested_sections.find(*it) == _requested_sections.end() ) 01825 if( section.length() != 0 ) _requested_sections.insert(*it); 01826 } 01827 01828 inline void 01829 GetPot::_record_variable_request(const std::string& Name) const 01830 { 01831 if( ! request_recording_f ) return; 01832 01833 // Get a lock before touching anything mutable 01834 SCOPED_MUTEX; 01835 01836 // (*) record requested variable for later ufo detection 01837 _requested_variables.insert(Name); 01838 01839 // (*) record considered section for ufo detection 01840 STRING_VECTOR STree = _get_section_tree(Name); 01841 victorate(std::string, STree, it) 01842 if( _requested_sections.find(*it) == _requested_sections.end() ) 01843 if( section.length() != 0 ) _requested_sections.insert(*it); 01844 } 01845 01846 // (*) following functions are to be used from 'outside', after getpot has parsed its 01847 // arguments => append an argument in the argument vector that reflects the addition 01848 inline void 01849 GetPot::_set_variable(const std::string& VarName, 01850 const std::string& Value, const bool Requested /* = true */) 01851 { 01852 const GetPot::variable* Var = Requested ? 01853 _request_variable(VarName.c_str()) : 01854 _find_variable(VarName.c_str()); 01855 if( Var == 0 ) variables.push_back(variable(VarName.c_str(), 01856 Value.c_str(), _field_separator.c_str())); 01857 else { 01858 overridden_vars.insert(VarName.c_str()); 01859 (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str()); 01860 } 01861 } 01862 01863 template <typename T> 01864 inline void 01865 GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */) 01866 { 01867 std::ostringstream string_value; 01868 string_value << Value; 01869 _set_variable(VarName, string_value.str().c_str(), Requested); 01870 } 01871 01872 template <typename T> 01873 inline void 01874 GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */) 01875 { 01876 set(VarName.c_str(), Value, Requested); 01877 } 01878 01879 inline void 01880 GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */) 01881 { 01882 _set_variable(VarName, Value, Requested); 01883 } 01884 01885 inline void 01886 GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */) 01887 { 01888 set(VarName.c_str(), Value, Requested); 01889 } 01890 01891 inline unsigned 01892 GetPot::vector_variable_size(const char* VarName) const 01893 { 01894 const variable* sv = _request_variable(VarName); 01895 if( sv == 0 ) return 0; 01896 return (unsigned)(sv->value.size()); 01897 } 01898 01899 inline unsigned 01900 GetPot::vector_variable_size(const std::string& VarName) const 01901 { 01902 return vector_variable_size(VarName.c_str()); 01903 } 01904 01905 inline STRING_VECTOR 01906 GetPot::get_variable_names() const 01907 { 01908 STRING_VECTOR result; 01909 std::vector<GetPot::variable>::const_iterator it = variables.begin(); 01910 for(; it != variables.end(); ++it) { 01911 const std::string Tmp = _get_remaining_string((*it).name, prefix); 01912 if( Tmp != "" ) result.push_back(Tmp); 01913 } 01914 return result; 01915 } 01916 01917 inline STRING_VECTOR 01918 GetPot::get_section_names() const 01919 { return section_list; } 01920 01921 inline std::set<std::string> 01922 GetPot::get_overridden_variables() const 01923 { return overridden_vars; } 01924 01925 inline const GetPot::variable* 01926 GetPot::_find_variable(const char* VarName) const 01927 { 01928 const std::string Name = prefix + VarName; 01929 01930 std::vector<variable>::const_iterator it = variables.begin(); 01931 for(; it != variables.end(); ++it) { 01932 if( (*it).name == Name ) return &(*it); 01933 } 01934 return 0; 01935 } 01936 01937 inline const GetPot::variable* 01938 GetPot::_request_variable(const char* VarName) const 01939 { 01940 // (*) record requested variable for later ufo detection 01941 this->_record_variable_request(VarName); 01942 01943 return this->_find_variable(VarName); 01944 } 01945 01947 // (*) ouput (basically for debugging reasons 01948 //............................................................................. 01949 // 01950 inline int 01951 GetPot::print(std::ostream &out_stream) const 01952 { 01953 out_stream << "argc = " << argv.size() << std::endl; 01954 STRING_VECTOR::const_iterator it = argv.begin(); 01955 for(; it != argv.end(); ++it) 01956 out_stream << *it << std::endl; 01957 out_stream << std::endl; 01958 return 1; 01959 } 01960 01961 // PECOS/HPCT Addition - add option to prepend output with a delimiter 01962 // while also disabling argc print and skipping first print (the name 01963 // of the input file) 01964 // 01965 // PECOS Development Team: (ks. 4/16/09) 01966 01967 inline int 01968 GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const 01969 { 01970 STRING_VECTOR::const_iterator it = argv.begin(); 01971 it += skip_count; 01972 for(; it != argv.end(); ++it) 01973 { 01974 out_stream << custom_prefix; 01975 out_stream << *it << std::endl; 01976 } 01977 out_stream << std::endl; 01978 return 1; 01979 } 01980 01981 01982 // (*) dollar bracket expressions (DBEs) ------------------------------------ 01983 // 01984 // 1) Entry Function: _DBE_expand_string() 01985 // Takes a string such as 01986 // 01987 // "${+ ${x} ${y}} Subject-${& ${section} ${subsection}}: ${title}" 01988 // 01989 // calls _DBE_expand() for each of the expressions 01990 // 01991 // ${+ ${x} ${y}} 01992 // ${& ${section} ${subsection}} 01993 // ${Title} 01994 // 01995 // and returns the string 01996 // 01997 // "4711 Subject-1.01: Mit den Clowns kamen die Schwaene" 01998 // 01999 // assuming that 02000 // x = "4699" 02001 // y = "12" 02002 // section = "1." 02003 // subsection = "01" 02004 // title = "Mit den Clowns kamen die Schwaene" 02005 // 02006 // 2) _DBE_expand(): 02007 // 02008 // checks for the command, i.e. the 'sign' that follows '${' 02009 // divides the argument list into sub-expressions using 02010 // _DBE_get_expr_list() 02011 // 02012 // ${+ ${x} ${y}} -> "${x}" "${y}" 02013 // ${& ${section} ${subsection}} -> "${section}" "${subsection}" 02014 // ${Title} -> Nothing, variable expansion 02015 // 02016 // 3) _DBE_expression_list(): 02017 // 02018 // builds a vector of unbracketed whitespace separated strings, i.e. 02019 // 02020 // " ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}" 02021 // 02022 // is split into a vector 02023 // 02024 // [0] ${Number}.a 02025 // [1] ${: Das Marmorbild} 02026 // [2] AB-${& Author= ${Eichendorf}}-1870 02027 // 02028 // Each sub-expression is expanded using expand(). 02029 //--------------------------------------------------------------------------- 02030 inline std::string 02031 GetPot::_DBE_expand_string(const std::string& str) 02032 { 02033 // Parses for closing operators '${ }' and expands them letting 02034 // white spaces and other letters as they are. 02035 std::string new_string = ""; 02036 unsigned open_brackets = 0; 02037 unsigned first = 0; 02038 unsigned i = 0; 02039 for(; i<str.size(); i++) { 02040 if( i < str.size() - 2 && str.substr(i, 2) == "${" ) { 02041 if( open_brackets == 0 ) first = i+2; 02042 open_brackets++; 02043 } 02044 else if( str[i] == '}' && open_brackets > 0) { 02045 open_brackets -= 1; 02046 if( open_brackets == 0 ) { 02047 const std::string Replacement = _DBE_expand(str.substr(first, i - first)); 02048 new_string += Replacement; 02049 } 02050 } 02051 else if( open_brackets == 0 ) 02052 new_string += str[i]; 02053 } 02054 return new_string; 02055 } 02056 02057 inline STRING_VECTOR 02058 GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber) 02059 // ensures that the resulting vector has the expected number 02060 // of arguments, but they may contain an error message 02061 { 02062 std::string str = str_; 02063 // Separates expressions by non-bracketed whitespaces, expands them 02064 // and puts them into a list. 02065 02066 unsigned i=0; 02067 // (1) eat initial whitespaces 02068 for(; i < str.size(); i++) 02069 if( ! isspace(str[i]) ) break; 02070 02071 STRING_VECTOR expr_list; 02072 unsigned open_brackets = 0; 02073 std::vector<unsigned> start_idx; 02074 unsigned start_new_string = i; 02075 unsigned l = (unsigned)(str.size()); 02076 02077 // (2) search for ${ } expressions ... 02078 while( i < l ) { 02079 const char letter = str[i]; 02080 // whitespace -> end of expression 02081 if( isspace(letter) && open_brackets == 0) { 02082 expr_list.push_back(str.substr(start_new_string, i - start_new_string)); 02083 bool no_breakout_f = true; 02084 for(i++; i < l ; i++) { 02085 if( ! isspace(str[i]) ) 02086 { no_breakout_f = false; start_new_string = i; break; } 02087 } 02088 if( no_breakout_f ) { 02089 // end of expression list 02090 if( expr_list.size() < ExpectedNumber ) { 02091 const std::string pre_tmp("<< ${ }: missing arguments>>"); 02092 STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp); 02093 expr_list.insert(expr_list.end(), tmp.begin(), tmp.end()); 02094 } 02095 return expr_list; 02096 } 02097 } 02098 02099 // dollar-bracket expression 02100 if( str.length() >= i+2 && str.substr(i, 2) == "${" ) { 02101 open_brackets++; 02102 start_idx.push_back(i+2); 02103 } 02104 else if( letter == '}' && open_brackets > 0) { 02105 int start = start_idx[start_idx.size()-1]; 02106 start_idx.pop_back(); 02107 const std::string Replacement = _DBE_expand(str.substr(start, i-start)); 02108 if( start - 3 < (int)0) 02109 str = Replacement + str.substr(i+1); 02110 else 02111 str = str.substr(0, start-2) + Replacement + str.substr(i+1); 02112 l = (int)(str.size()); 02113 i = start + (int)(Replacement.size()) - 3; 02114 open_brackets--; 02115 } 02116 i++; 02117 } 02118 02119 // end of expression list 02120 expr_list.push_back(str.substr(start_new_string, i-start_new_string)); 02121 02122 if( expr_list.size() < ExpectedNumber ) { 02123 const std::string pre_tmp("<< ${ }: missing arguments>>"); 02124 STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp); 02125 expr_list.insert(expr_list.end(), tmp.begin(), tmp.end()); 02126 } 02127 02128 return expr_list; 02129 } 02130 02131 inline const GetPot::variable* 02132 GetPot::_DBE_get_variable(const std::string& VarName) 02133 { 02134 static GetPot::variable ev; 02135 std::string secure_Prefix = prefix; 02136 02137 prefix = section; 02138 // (1) first search in currently active section 02139 const GetPot::variable* var = _request_variable(VarName.c_str()); 02140 if( var != 0 ) { prefix = secure_Prefix; return var; } 02141 02142 // (2) search in root name space 02143 prefix = ""; 02144 var = _request_variable(VarName.c_str()); 02145 if( var != 0 ) { prefix = secure_Prefix; return var; } 02146 02147 prefix = secure_Prefix; 02148 02149 // error occured => variable name == "" 02150 ev.original = "<<${ } variable '"; 02151 ev.original += VarName + "' undefined>>"; 02152 return &ev; 02153 } 02154 02155 inline std::string 02156 GetPot::_DBE_expand(const std::string& expr) 02157 { 02158 // ${: } pure text 02159 if( expr[0] == ':' ) 02160 return expr.substr(1); 02161 02162 // ${& expr expr ... } text concatination 02163 else if( expr[0] == '&' ) { 02164 const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1); 02165 02166 STRING_VECTOR::const_iterator it = A.begin(); 02167 std::string result = *it++; 02168 for(; it != A.end(); ++it) result += *it; 02169 02170 return result; 02171 } 02172 02173 // ${<-> expr expr expr} text replacement 02174 else if( expr.length() >= 3 && expr.substr(0, 3) == "<->" ) { 02175 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3); 02176 size_t tmp = 0; 02177 const size_t L = A[1].length(); 02178 while( (tmp = A[0].find(A[1])) != std::string::npos ) { 02179 A[0].replace(tmp, L, A[2]); 02180 } 02181 return A[0]; 02182 } 02183 02184 // ${=func [expr...] } function evaluation 02185 else if( expr.length() >= 2 && 02186 expr.substr(0, 1) == "=" && 02187 expr.substr(0, 2) != "==" ) { 02188 size_t funcnamestart = expr.find_first_not_of(" \t", 1); 02189 if (funcnamestart != std::string::npos) { 02190 size_t funcnameend = expr.find_first_of(" \t",funcnamestart); 02191 std::string funcname = expr.substr(funcnamestart, 02192 funcnameend-funcnamestart); 02193 if (funcname == "log") { 02194 STRING_VECTOR A = 02195 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02196 double arg = _convert_to_type(A[0], 0.0); 02197 return _convert_from_type(std::log(arg)); 02198 } 02199 else if (funcname == "log10") { 02200 STRING_VECTOR A = 02201 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02202 double arg = _convert_to_type(A[0], 0.0); 02203 return _convert_from_type(std::log10(arg)); 02204 } 02205 else if (funcname == "sin") { 02206 STRING_VECTOR A = 02207 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02208 double arg = _convert_to_type(A[0], 0.0); 02209 return _convert_from_type(std::sin(arg)); 02210 } 02211 else if (funcname == "cos") { 02212 STRING_VECTOR A = 02213 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02214 double arg = _convert_to_type(A[0], 0.0); 02215 return _convert_from_type(std::cos(arg)); 02216 } 02217 else if (funcname == "tan") { 02218 STRING_VECTOR A = 02219 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02220 double arg = _convert_to_type(A[0], 0.0); 02221 return _convert_from_type(std::tan(arg)); 02222 } 02223 else if (funcname == "asin") { 02224 STRING_VECTOR A = 02225 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02226 double arg = _convert_to_type(A[0], 0.0); 02227 return _convert_from_type(std::asin(arg)); 02228 } 02229 else if (funcname == "acos") { 02230 STRING_VECTOR A = 02231 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02232 double arg = _convert_to_type(A[0], 0.0); 02233 return _convert_from_type(std::acos(arg)); 02234 } 02235 else if (funcname == "atan") { 02236 STRING_VECTOR A = 02237 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02238 double arg = _convert_to_type(A[0], 0.0); 02239 return _convert_from_type(std::atan(arg)); 02240 } 02241 else if (funcname == "atan2") { 02242 STRING_VECTOR A = 02243 _DBE_get_expr_list(expr.substr(funcnameend), 2); 02244 double arg1 = _convert_to_type(A[0], 0.0); 02245 double arg2 = _convert_to_type(A[1], 0.0); 02246 return _convert_from_type(std::atan2(arg1, arg2)); 02247 } 02248 else if (funcname == "sinh") { 02249 STRING_VECTOR A = 02250 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02251 double arg = _convert_to_type(A[0], 0.0); 02252 return _convert_from_type(std::sinh(arg)); 02253 } 02254 else if (funcname == "cosh") { 02255 STRING_VECTOR A = 02256 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02257 double arg = _convert_to_type(A[0], 0.0); 02258 return _convert_from_type(std::cosh(arg)); 02259 } 02260 else if (funcname == "tanh") { 02261 STRING_VECTOR A = 02262 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02263 double arg = _convert_to_type(A[0], 0.0); 02264 return _convert_from_type(std::tanh(arg)); 02265 } 02266 else if (funcname == "sqrt") { 02267 STRING_VECTOR A = 02268 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02269 double arg = _convert_to_type(A[0], 0.0); 02270 return _convert_from_type(std::sqrt(arg)); 02271 } 02272 else if (funcname == "abs") { 02273 STRING_VECTOR A = 02274 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02275 double arg = _convert_to_type(A[0], 0.0); 02276 return _convert_from_type(std::abs(arg)); 02277 } 02278 else if (funcname == "max") { 02279 STRING_VECTOR A = 02280 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02281 STRING_VECTOR::const_iterator it = A.begin(); 02282 double result = _convert_to_type(*it++, 0.0); 02283 for(; it != A.end(); ++it) 02284 result = std::max(result, _convert_to_type(*it, 0.0)); 02285 return _convert_from_type(result); 02286 } 02287 else if (funcname == "min") { 02288 STRING_VECTOR A = 02289 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02290 STRING_VECTOR::const_iterator it = A.begin(); 02291 double result = _convert_to_type(*it++, 0.0); 02292 for(; it != A.end(); ++it) 02293 result = std::min(result, _convert_to_type(*it, 0.0)); 02294 return _convert_from_type(result); 02295 } 02296 else if (funcname == "ceil") { 02297 STRING_VECTOR A = 02298 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02299 double arg = _convert_to_type(A[0], 0.0); 02300 return _convert_from_type(std::ceil(arg)); 02301 } 02302 else if (funcname == "floor") { 02303 STRING_VECTOR A = 02304 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02305 double arg = _convert_to_type(A[0], 0.0); 02306 return _convert_from_type(std::floor(arg)); 02307 } 02308 else if (funcname == "fmod") { 02309 STRING_VECTOR A = 02310 _DBE_get_expr_list(expr.substr(funcnameend), 2); 02311 double arg1 = _convert_to_type(A[0], 0.0); 02312 double arg2 = _convert_to_type(A[1], 0.0); 02313 return _convert_from_type(std::fmod(arg1, arg2)); 02314 } 02315 else if (funcname == "srand") { 02316 STRING_VECTOR A = 02317 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02318 unsigned int arg = _convert_to_type(A[0], 0u); 02319 std::srand(arg); 02320 return A[0]; 02321 } 02322 // ${=rand range} with default range==RAND_MAX 02323 else if (funcname == "rand") { 02324 if (funcnameend >= expr.length() || 02325 expr.find_first_not_of(" \t", funcnameend) == std::string::npos) 02326 return _convert_from_type(std::rand()); 02327 02328 STRING_VECTOR A = 02329 _DBE_get_expr_list(expr.substr(funcnameend), 1); 02330 unsigned int range = _convert_to_type(A[0],0u); 02331 if (!range) 02332 return _convert_from_type(0); 02333 const unsigned int x = (RAND_MAX + 1u) / range; 02334 const unsigned int y = x * range; 02335 unsigned int returnval; 02336 do { 02337 returnval = rand(); 02338 } while(returnval >= y); 02339 return _convert_from_type(returnval / x); 02340 } 02341 else if (funcname == "time") { 02342 return _convert_from_type(std::time(NULL)); 02343 } 02344 } 02345 } 02346 02347 // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions 02348 else if( expr[0] == '+' ) { 02349 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 02350 STRING_VECTOR::const_iterator it = A.begin(); 02351 double result = _convert_to_type(*it++, 0.0); 02352 for(; it != A.end(); ++it) 02353 result += _convert_to_type(*it, 0.0); 02354 02355 return _convert_from_type(result); 02356 } 02357 else if( expr[0] == '-' ) { 02358 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 02359 STRING_VECTOR::const_iterator it = A.begin(); 02360 double result = _convert_to_type(*it++, 0.0); 02361 for(; it != A.end(); ++it) 02362 result -= _convert_to_type(*it, 0.0); 02363 02364 return _convert_from_type(result); 02365 } 02366 else if( expr[0] == '*' ) { 02367 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 02368 STRING_VECTOR::const_iterator it = A.begin(); 02369 double result = _convert_to_type(*it++, 0.0); 02370 for(; it != A.end(); ++it) 02371 result *= _convert_to_type(*it, 0.0); 02372 02373 return _convert_from_type(result); 02374 } 02375 else if( expr[0] == '/' ) { 02376 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 02377 STRING_VECTOR::const_iterator it = A.begin(); 02378 double result = _convert_to_type(*it++, 0.0); 02379 if( result == 0 ) { 02380 return "0.0"; 02381 } 02382 for(; it != A.end(); ++it) { 02383 const double Q = _convert_to_type(*it, 0.0); 02384 result /= Q; 02385 } 02386 return _convert_from_type(result); 02387 } 02388 02389 // ${^ ... } power expressions 02390 else if( expr[0] == '^' ) { 02391 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 02392 STRING_VECTOR::const_iterator it = A.begin(); 02393 double result = _convert_to_type(*it++, 0.0); 02394 for(; it != A.end(); ++it) 02395 result = pow(result, _convert_to_type(*it, 0.0)); 02396 return _convert_from_type(result); 02397 } 02398 02399 // ${== } ${<= } ${>= } comparisons (return the number of the first 'match' 02400 else if( expr.length() >= 2 && 02401 ( expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" || 02402 expr.substr(0,2) == "<=" || expr[0] == '>' || expr[0] == '<')) { 02403 // differentiate between two and one sign operators 02404 unsigned op = 0; 02405 enum { EQ, GEQ, LEQ, GT, LT }; 02406 if ( expr.substr(0, 2) == "==" ) op = EQ; 02407 else if ( expr.substr(0, 2) == ">=" ) op = GEQ; 02408 else if ( expr.substr(0, 2) == "<=" ) op = LEQ; 02409 else if ( expr[0] == '>' ) op = GT; 02410 else /* "<" */ op = LT; 02411 02412 STRING_VECTOR a; 02413 if ( op == GT || op == LT ) a = _DBE_get_expr_list(expr.substr(1), 2); 02414 else a = _DBE_get_expr_list(expr.substr(2), 2); 02415 02416 std::string x_orig = a[0]; 02417 double x = _convert_to_type(x_orig, 1e37); 02418 unsigned i = 1; 02419 02420 STRING_VECTOR::const_iterator y_orig = a.begin(); 02421 for(y_orig++; y_orig != a.end(); ++y_orig) { 02422 double y = _convert_to_type(*y_orig, 1e37); 02423 02424 // set the strings as reference if one wasn't a number 02425 if ( x == 1e37 || y == 1e37 ) { 02426 // it's a string comparison 02427 if( (op == EQ && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) || 02428 (op == LEQ && x_orig <= *y_orig) || (op == GT && x_orig > *y_orig) || 02429 (op == LT && x_orig < *y_orig) ) 02430 return _convert_from_type(i); 02431 } 02432 else { 02433 // it's a number comparison 02434 if( (op == EQ && x == y) || (op == GEQ && x >= y) || 02435 (op == LEQ && x <= y) || (op == GT && x > y) || 02436 (op == LT && x < y) ) 02437 return _convert_from_type(i); 02438 } 02439 i++; 02440 } 02441 02442 // nothing fulfills the condition => return 0 02443 return "0"; 02444 } 02445 // ${?? expr expr} select 02446 else if( expr.length() >= 2 && expr.substr(0, 2) == "??" ) { 02447 STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2); 02448 double x = _convert_to_type(a[0], 1e37); 02449 // last element is always the default argument 02450 if( x == 1e37 || x < 0 || x >= a.size() - 1 ) return a[a.size()-1]; 02451 02452 // round x to closest integer 02453 return a[int(x+0.5)]; 02454 } 02455 // ${? expr expr expr} if then else conditions 02456 else if( expr[0] == '?' ) { 02457 STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2); 02458 if( _convert_to_type(a[0], 0.0) == 1.0 ) return a[1]; 02459 else if( a.size() > 2 ) return a[2]; 02460 } 02461 // ${! expr} maxro expansion 02462 else if( expr[0] == '!' ) { 02463 const GetPot::variable* Var = _DBE_get_variable(expr.substr(1)); 02464 // error 02465 if( Var->name == "" ) return std::string(Var->original); 02466 02467 const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2); 02468 return A[0]; 02469 } 02470 // ${@: } - string subscription 02471 else if( expr.length() >= 2 && expr.substr(0,2) == "@:" ) { 02472 const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2); 02473 double x = _convert_to_type(A[1], 1e37); 02474 02475 // last element is always the default argument 02476 if( x == 1e37 || x < 0 || x >= A[0].size() - 1) 02477 return "<<1st index out of range>>"; 02478 02479 if( A.size() > 2 ) { 02480 double y = _convert_to_type(A[2], 1e37); 02481 if ( y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x ) 02482 return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5)); 02483 else if( y == -1 ) 02484 return A[0].substr(int(x+0.5)); 02485 return "<<2nd index out of range>>"; 02486 } 02487 else { 02488 char* tmp = new char[2]; 02489 tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0'; 02490 std::string result(tmp); 02491 delete [] tmp; 02492 return result; 02493 } 02494 } 02495 // ${@ } - vector subscription 02496 else if( expr[0] == '@' ) { 02497 STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2); 02498 const GetPot::variable* Var = _DBE_get_variable(A[0]); 02499 // error 02500 if( Var->name == "" ) { 02501 // make a copy of the string if an error occured 02502 // (since the error variable is a static variable inside get_variable()) 02503 return std::string(Var->original); 02504 } 02505 02506 double x = _convert_to_type(A[1], 1e37); 02507 02508 // last element is always the default argument 02509 if (x == 1e37 || x < 0 || x >= Var->value.size() ) 02510 return "<<1st index out of range>>"; 02511 02512 if ( A.size() > 2) { 02513 double y = _convert_to_type(A[2], 1e37); 02514 int begin = int(x+0.5); 02515 int end = 0; 02516 if ( y != 1e37 && y > 0 && y <= Var->value.size() && y > x) 02517 end = int(y+1.5); 02518 else if( y == -1 ) 02519 end = int(Var->value.size()); 02520 else 02521 return "<<2nd index out of range>>"; 02522 02523 std::string result = *(Var->get_element(begin)); 02524 int i = begin+1; 02525 for(; i < end; i++) 02526 result += std::string(" ") + *(Var->get_element(i)); 02527 return result; 02528 } 02529 else 02530 return *(Var->get_element(int(x+0.5))); 02531 } 02532 02533 const STRING_VECTOR A = _DBE_get_expr_list(expr, 1); 02534 const GetPot::variable* B = _DBE_get_variable(A[0]); 02535 02536 // make a copy of the string if an error occured 02537 // (since the error variable is a static variable inside get_variable()) 02538 if( B->name == "" ) return std::string(B->original); 02539 // (psuggs@pobox.com mentioned to me the warning MSVC++6.0 produces 02540 // with: else return B->original (thanks)) 02541 return B->original; 02542 } 02543 02544 02546 // (*) unidentified flying objects 02547 //............................................................................. 02548 // 02549 inline bool 02550 GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const 02551 { 02552 victorate(std::string, VecStr, itk) { 02553 if( *itk == Str ) return true; 02554 } 02555 return false; 02556 } 02557 02558 inline STRING_VECTOR 02559 GetPot::unidentified_arguments(unsigned Number, 02560 const char* KnownArgument1, ...) const 02561 { 02562 std::set<std::string> known_arguments; 02563 02564 // (1) create a vector of known arguments 02565 if( Number == 0 ) return STRING_VECTOR(); 02566 02567 va_list ap; 02568 va_start(ap, KnownArgument1); 02569 known_arguments.insert(std::string(KnownArgument1)); 02570 unsigned i=1; 02571 for(; i<Number; i++) 02572 known_arguments.insert(std::string(va_arg(ap, char *))); 02573 va_end(ap); 02574 02575 return unidentified_arguments(known_arguments); 02576 } 02577 02578 inline STRING_VECTOR 02579 GetPot::unidentified_arguments() const 02580 { return unidentified_arguments(_requested_arguments); } 02581 02582 inline STRING_VECTOR 02583 GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const 02584 { 02585 // We use set for efficiency, but want to support vector inputs for 02586 // backwards compatibility. 02587 return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end())); 02588 } 02589 02590 inline STRING_VECTOR 02591 GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const 02592 { 02593 STRING_VECTOR ufos; 02594 STRING_VECTOR::const_iterator it = argv.begin(); 02595 ++it; // forget about argv[0] (application or filename) 02596 for(; it != argv.end(); ++it) { 02597 // -- argument belongs to prefixed section ? 02598 const std::string arg = _get_remaining_string(*it, prefix); 02599 if( arg == "" ) continue; 02600 02601 // -- check if in list 02602 if( Knowns.find(arg) == Knowns.end() ) 02603 ufos.push_back(*it); 02604 } 02605 return ufos; 02606 } 02607 02608 inline STRING_VECTOR 02609 GetPot::unidentified_options(unsigned Number, 02610 const char* KnownOption1, ...) const 02611 { 02612 std::set<std::string> known_options; 02613 02614 // (1) create a vector of known arguments 02615 if( Number == 0 ) return STRING_VECTOR(); 02616 02617 va_list ap; 02618 va_start(ap, KnownOption1); 02619 known_options.insert(std::string(KnownOption1)); 02620 unsigned i=1; 02621 for(; i<Number; i++) 02622 known_options.insert(std::string(va_arg(ap, char *))); 02623 va_end(ap); 02624 02625 return unidentified_options(known_options); 02626 } 02627 02628 inline STRING_VECTOR 02629 GetPot::unidentified_options() const 02630 { 02631 // -- every option is an argument. 02632 // -- the set of requested arguments contains the set of requested options. 02633 // -- IF the set of requested arguments contains unrequested options, 02634 // THEN they were requested as 'follow' and 'next' arguments and not as real options. 02635 // 02636 // => it is not necessary to separate requested options from the list 02637 return unidentified_arguments(_requested_arguments); 02638 } 02639 02640 inline STRING_VECTOR 02641 GetPot::unidentified_options(const std::vector<std::string>& Knowns) const 02642 { 02643 // We use set for efficiency, but want to support vector inputs for 02644 // backwards compatibility. 02645 return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end())); 02646 } 02647 02648 inline STRING_VECTOR 02649 GetPot::unidentified_options(const std::set<std::string>& Knowns) const 02650 { 02651 STRING_VECTOR ufos; 02652 STRING_VECTOR::const_iterator it = argv.begin(); 02653 ++it; // forget about argv[0] (application or filename) 02654 for(; it != argv.end(); ++it) { 02655 // -- argument belongs to prefixed section ? 02656 const std::string arg = _get_remaining_string(*it, prefix); 02657 if( arg == "" ) continue; 02658 02659 // is argument really an option (starting with '-') ? 02660 if( arg.length() < 1 || arg[0] != '-' ) continue; 02661 02662 if( Knowns.find(arg) == Knowns.end() ) 02663 ufos.push_back(*it); 02664 } 02665 02666 return ufos; 02667 } 02668 02669 inline std::string 02670 GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const 02671 // Two modes: 02672 // ArgumentNumber >= 0 check specific argument 02673 // ArgumentNumber == -1 check all options starting with one '-' 02674 // for flags 02675 { 02676 std::string ufos; 02677 STRING_VECTOR known_arguments; 02678 std::string KFL(KnownFlagList); 02679 02680 // (2) iteration over '-' arguments (options) 02681 if( ArgumentNumber == -1 ) { 02682 STRING_VECTOR::const_iterator it = argv.begin(); 02683 it++; // forget about argv[0] (application or filename) 02684 for(; it != argv.end(); ++it) { 02685 // -- argument belongs to prefixed section ? 02686 const std::string arg = _get_remaining_string(*it, prefix); 02687 if( arg == "" ) continue; 02688 02689 // -- does arguments start with '-' (but not '--') 02690 if ( arg.length() < 2 ) continue; 02691 else if( arg[0] != '-' ) continue; 02692 else if( arg[1] == '-' ) continue; 02693 02694 // -- check out if flags inside option are contained in KnownFlagList 02695 const char* p=arg.c_str(); 02696 p++; // skip starting minus 02697 for(; *p != '\0' ; p++) 02698 if( KFL.find(*p) == std::string::npos ) ufos += *p; 02699 } 02700 } 02701 // (1) check specific argument 02702 else { 02703 // -- only check arguments that start with prefix 02704 int no_matches = 0; 02705 unsigned i=1; 02706 for(; i<argv.size(); i++) { 02707 const std::string Remain = _get_remaining_string(argv[i], prefix); 02708 if( Remain != "") { 02709 no_matches++; 02710 if( no_matches == ArgumentNumber) { 02711 // -- the right argument number inside the section is found 02712 // => check it for flags 02713 const char* p = Remain.c_str(); 02714 p++; // skip starting minus 02715 for(; *p != '\0' ; p++) 02716 if( KFL.find(*p) == std::string::npos ) ufos += *p; 02717 return ufos; 02718 } 02719 } 02720 } 02721 } 02722 return ufos; 02723 } 02724 02725 inline STRING_VECTOR 02726 GetPot::unidentified_variables(unsigned Number, 02727 const char* KnownVariable1, ...) const 02728 { 02729 std::set<std::string> known_variables; 02730 02731 // create vector of known arguments 02732 if( Number == 0 ) return STRING_VECTOR(); 02733 02734 va_list ap; 02735 va_start(ap, KnownVariable1); 02736 known_variables.insert(std::string(KnownVariable1)); 02737 unsigned i=1; 02738 for(; i<Number; i++) 02739 known_variables.insert(std::string(va_arg(ap, char *))); 02740 va_end(ap); 02741 02742 return unidentified_variables(known_variables); 02743 } 02744 02745 inline STRING_VECTOR 02746 GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const 02747 { 02748 // We use set for efficiency, but want to support vector inputs for 02749 // backwards compatibility. 02750 return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end())); 02751 } 02752 02753 inline STRING_VECTOR 02754 GetPot::unidentified_variables(const std::set<std::string>& Knowns) const 02755 { 02756 STRING_VECTOR ufos; 02757 02758 victorate(GetPot::variable, variables, it) { 02759 // -- check if variable has specific prefix 02760 const std::string var_name = _get_remaining_string((*it).name, prefix); 02761 if( var_name == "" ) continue; 02762 02763 // -- check if variable is known 02764 if( Knowns.find(var_name) == Knowns.end() ) 02765 ufos.push_back((*it).name); 02766 } 02767 return ufos; 02768 } 02769 02770 inline STRING_VECTOR 02771 GetPot::unidentified_variables() const 02772 { return unidentified_variables(_requested_variables); } 02773 02774 02775 inline STRING_VECTOR 02776 GetPot::unidentified_sections(unsigned Number, 02777 const char* KnownSection1, ...) const 02778 { 02779 std::set<std::string> known_sections; 02780 02781 // (1) create a vector of known arguments 02782 if( Number == 0 ) return STRING_VECTOR(); 02783 02784 va_list ap; 02785 va_start(ap, KnownSection1); 02786 known_sections.insert(std::string(KnownSection1)); 02787 unsigned i=1; 02788 for(; i<Number; i++) { 02789 std::string tmp = std::string(va_arg(ap, char *)); 02790 if( tmp.length() == 0 ) continue; 02791 if( tmp[tmp.length()-1] != '/' ) tmp += '/'; 02792 known_sections.insert(tmp); 02793 } 02794 va_end(ap); 02795 02796 return unidentified_sections(known_sections); 02797 } 02798 02799 inline STRING_VECTOR 02800 GetPot::unidentified_sections() const 02801 { return unidentified_sections(_requested_sections); } 02802 02803 inline STRING_VECTOR 02804 GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const 02805 { 02806 // We use set for efficiency, but want to support vector inputs for 02807 // backwards compatibility. 02808 return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end())); 02809 } 02810 02811 inline STRING_VECTOR 02812 GetPot::unidentified_sections(const std::set<std::string>& Knowns) const 02813 { 02814 STRING_VECTOR ufos; 02815 02816 victorate(std::string, section_list, it) { 02817 // -- check if section conform to prefix 02818 const std::string sec_name = _get_remaining_string(*it, prefix); 02819 if( sec_name == "" ) continue; 02820 02821 // -- check if section is known 02822 if( Knowns.find(sec_name) == Knowns.end() ) 02823 ufos.push_back(*it); 02824 } 02825 02826 return ufos; 02827 } 02828 02829 02830 inline STRING_VECTOR 02831 GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const 02832 { 02833 std::set<std::string> known_nominuses; 02834 02835 // create vector of known arguments 02836 if( Number == 0 ) return STRING_VECTOR(); 02837 02838 va_list ap; 02839 va_start(ap, Known); 02840 known_nominuses.insert(std::string(Known)); 02841 unsigned i=1; 02842 for(; i<Number; i++) { 02843 std::string tmp = std::string(va_arg(ap, char *)); 02844 if( tmp.length() == 0 ) continue; 02845 known_nominuses.insert(tmp); 02846 } 02847 va_end(ap); 02848 02849 return unidentified_nominuses(known_nominuses); 02850 } 02851 02852 inline STRING_VECTOR 02853 GetPot::unidentified_nominuses() const { 02854 // -- every nominus is an argument. 02855 // -- the set of requested arguments contains the set of requested nominuss. 02856 // -- IF the set of requested arguments contains unrequested nominuss, 02857 // THEN they were requested as 'follow' and 'next' arguments and not as real nominuses. 02858 // 02859 // => it is not necessary to separate requested nominus from the list 02860 02861 return unidentified_nominuses(_requested_arguments); 02862 } 02863 02864 inline STRING_VECTOR 02865 GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const 02866 { 02867 // We use set for efficiency, but want to support vector inputs for 02868 // backwards compatibility. 02869 return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end())); 02870 } 02871 02872 inline STRING_VECTOR 02873 GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const 02874 { 02875 STRING_VECTOR ufos; 02876 02877 // (2) iterate over all arguments 02878 STRING_VECTOR::const_iterator it = argv.begin(); 02879 ++it; // forget about argv[0] (application or filename) 02880 for(; it != argv.end(); ++it) { 02881 // -- check if nominus part of prefix 02882 const std::string arg = _get_remaining_string(*it, prefix); 02883 if( arg == "" ) continue; 02884 02885 if( arg.length() < 1 ) continue; 02886 // option ? --> not a nomius 02887 if( arg[0] == '-' ) continue; 02888 // section ? --> not a real nominus 02889 if( arg[0] == '[' && arg[arg.length()-1] == ']' ) continue; 02890 // variable definition ? --> not a real nominus 02891 bool continue_f = false; 02892 unsigned i=0; 02893 for(; i<arg.length() ; i++) 02894 if( arg[i] == '=' ) { continue_f = true; break; } 02895 if( continue_f ) continue; 02896 02897 // real nominuses are compared with the given list 02898 if( Knowns.find(arg) == Knowns.end() ) 02899 ufos.push_back(*it); 02900 } 02901 return ufos; 02902 } 02903 02904 02906 // (*) variable class 02907 //............................................................................. 02908 // 02909 inline 02910 GetPot::variable::variable() 02911 : name(), 02912 value(), 02913 original() 02914 {} 02915 02916 inline 02917 GetPot::variable::variable(const variable& Other) 02918 { 02919 #ifdef WIN32 02920 operator=(Other); 02921 #else 02922 GetPot::variable::operator=(Other); 02923 #endif 02924 } 02925 02926 02927 inline 02928 GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator) 02929 : name(Name) 02930 { 02931 // make a copy of the 'Value' 02932 take(Value, FieldSeparator); 02933 } 02934 02935 inline const std::string* 02936 GetPot::variable::get_element(unsigned Idx) const 02937 { if( Idx >= value.size() ) return 0; else return &(value[Idx]); } 02938 02939 inline void 02940 GetPot::variable::take(const char* Value, const char* FieldSeparator) 02941 { 02942 original = std::string(Value); // string member var 02943 value.clear(); // vector<string> member var 02944 02945 /* 02946 // separate string by white space delimiters using 'strtok' 02947 // thread safe usage of strtok (no static members) 02948 char* spt = 0; 02949 // make a copy of the 'Value' 02950 char* copy = new char[strlen(Value)+1]; 02951 strcpy(copy, Value); 02952 char* follow_token = strtok_r(copy, FieldSeparator, &spt); 02953 while(follow_token != 0) { 02954 value.push_back(std::string(follow_token)); 02955 follow_token = strtok_r(NULL, FieldSeparator, &spt); 02956 } 02957 02958 delete [] copy; 02959 */ 02960 02961 // Don't use strtok, instead tokenize the input char "Value" using std::string operations so 02962 // that the results end up in the local "value" member 02963 02964 // Construct std::string objects from the input char*s. I think the only 02965 // FieldSeparator recognized by GetPot is whitespace? 02966 std::string Value_str = std::string(Value); 02967 std::string delimiters = std::string(FieldSeparator); 02968 02969 // Skip delimiters at beginning. 02970 std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0); 02971 02972 // Find first "non-delimiter". 02973 std::string::size_type pos = Value_str.find_first_of(delimiters, lastPos); 02974 02975 // Loop over the input string until all the tokens have been pushed back 02976 // into the local "value" member. 02977 while (std::string::npos != pos || std::string::npos != lastPos) 02978 { 02979 // Found a token, add it to the vector. 02980 value.push_back(Value_str.substr(lastPos, pos - lastPos)); 02981 02982 // Skip delimiters. Note the "not_of" 02983 lastPos = Value_str.find_first_not_of(delimiters, pos); 02984 02985 // Find next "non-delimiter" 02986 pos = Value_str.find_first_of(delimiters, lastPos); 02987 } 02988 02989 // We're done, all the tokens should now be in the vector<string> 02990 02991 } 02992 02993 inline 02994 GetPot::variable::~variable() 02995 {} 02996 02997 inline GetPot::variable& 02998 GetPot::variable::operator=(const GetPot::variable& Other) 02999 { 03000 if( &Other != this) { 03001 name = Other.name; 03002 value = Other.value; 03003 original = Other.original; 03004 } 03005 return *this; 03006 } 03007 03008 #ifdef GETPOT_NAMESPACE 03009 } 03010 #endif 03011 03012 #undef victorate 03013 03014 #endif // LIBMESH_GETPOT_H 03015 03016
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: