From 14c7f45cdae826f88dc539c8c38dd95caf305731 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 11 Jul 2008 15:50:46 +0000 Subject: Add zook's ZenUtils to SVN git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18010 a1c6a512-1295-4272-9138-f99709370657 --- .../libraries/getpot-c++-1.1.17/getpot/getpot.hpp | 2435 ++++++++++++++++++++ 1 file changed, 2435 insertions(+) create mode 100755 utils/zenutils/libraries/getpot-c++-1.1.17/getpot/getpot.hpp (limited to 'utils/zenutils/libraries/getpot-c++-1.1.17/getpot/getpot.hpp') diff --git a/utils/zenutils/libraries/getpot-c++-1.1.17/getpot/getpot.hpp b/utils/zenutils/libraries/getpot-c++-1.1.17/getpot/getpot.hpp new file mode 100755 index 0000000000..fe820c91a2 --- /dev/null +++ b/utils/zenutils/libraries/getpot-c++-1.1.17/getpot/getpot.hpp @@ -0,0 +1,2435 @@ +// -*- c++ -*- +// GetPot Version $$Version$$ $$Date$$ +// +// WEBSITE: http://getpot.sourceforge.net +// +// NOTE: The LPGL License for this library is only valid in case that +// it is not used for the production or development of applications +// dedicated to military industry. This is what the author calls +// the 'unofficial peace version of the LPGL'. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// +// (C) 2001-2005 Frank R. Schaefer +//========================================================================== + +#ifndef __include_guard_GETPOT_H__ +#define __include_guard_GETPOT_H__ + +#if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC) +#define strtok_r(a, b, c) strtok(a, b) +#endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC + +extern "C" { +// leave the 'extern C' to make it 100% sure to work - +// expecially with older distributions of header files. +#ifndef WIN32 +// this is necessary (depending on OS) +#include +#endif +#include +#include +#include +} +#include +#include +#include +#include + +#include +#include // not every compiler distribution includes +// // with + +typedef std::vector STRING_VECTOR; + +#define victorate(TYPE, VARIABLE, ITERATOR) \ + std::vector::const_iterator ITERATOR = (VARIABLE).begin(); \ + for(; (ITERATOR) != (VARIABLE).end(); (ITERATOR)++) + + +class GetPot { + //-------- + inline void __basic_initialization(); +public: + // (*) constructors, destructor, assignment operator ----------------------- + inline GetPot(); + inline GetPot(const GetPot&); + inline GetPot(const int argc_, char** argv_, + const char* FieldSeparator=0x0); + inline GetPot(const char* FileName, + const char* CommentStart=0x0, const char* CommentEnd=0x0, + const char* FieldSeparator=0x0); + inline ~GetPot(); + inline GetPot& operator=(const GetPot&); + + + // (*) absorbing contents of another GetPot object + inline void absorb(const GetPot& That); + // -- for ufo detection: recording requested arguments, options etc. + inline void clear_requests(); + inline void disable_request_recording() { __request_recording_f = false; } + inline void enable_request_recording() { __request_recording_f = true; } + + // (*) direct access to command line arguments ----------------------------- + inline const std::string operator[](unsigned Idx) const; + inline int get(unsigned Idx, int Default) const; + inline double get(unsigned Idx, const double& Default) const; + inline const std::string get(unsigned Idx, const char* Default) const; + inline unsigned size() const; + + // (*) flags --------------------------------------------------------------- + inline bool options_contain(const char* FlagList) const; + inline bool argument_contains(unsigned Idx, const char* FlagList) const; + + // (*) variables ----------------------------------------------------------- + // -- scalar values + inline int operator()(const char* VarName, int Default) const; + inline double operator()(const char* VarName, const double& Default) const; + inline const std::string operator()(const char* VarName, const char* Default) const; + // -- vectors + inline int operator()(const char* VarName, int Default, unsigned Idx) const; + inline double operator()(const char* VarName, const double& Default, unsigned Idx) const; + inline const std::string operator()(const char* VarName, const char* Default, unsigned Idx) const; + + // -- setting variables + // i) from outside of GetPot (considering prefix etc.) + // ii) from inside, use '__set_variable()' below + inline void set(const char* VarName, const char* Value, const bool Requested = true); + inline void set(const char* VarName, const double& Value, const bool Requested = true); + inline void set(const char* VarName, const int Value, const bool Requested = true); + + inline unsigned vector_variable_size(const char* VarName) const; + inline STRING_VECTOR get_variable_names() const; + inline STRING_VECTOR get_section_names() const; + + + // (*) cursor oriented functions ------------------------------------------- + inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); } + inline bool search_failed() const { return search_failed_f; } + + // -- enable/disable search for an option in loop + inline void disable_loop() { search_loop_f = false; } + inline void enable_loop() { search_loop_f = true; } + + // -- reset cursor to position '1' + inline void reset_cursor(); + inline void init_multiple_occurrence(); + + // -- search for a certain option and set cursor to position + inline bool search(const char* option); + inline bool search(unsigned No, const char* P, ...); + // -- get argument at cursor++ + inline int next(int Default); + inline double next(const double& Default); + inline const std::string next(const char* Default); + // -- search for option and get argument at cursor++ + inline int follow(int Default, const char* Option); + inline double follow(const double& Default, const char* Option); + inline const std::string follow(const char* Default, const char* Option); + // -- search for one of the given options and get argument that follows it + inline int follow(int Default, unsigned No, const char* Option, ...); + inline double follow(const double& Default, unsigned No, const char* Option, ...); + inline const std::string follow(const char* Default, unsigned No, const char* Option, ...); + // -- lists of nominuses following an option + inline std::vector nominus_followers(const char* Option); + inline std::vector nominus_followers(unsigned No, ...); + + // -- directly followed arguments + inline int direct_follow(int Default, const char* Option); + inline double direct_follow(const double& Default, const char* Option); + inline const std::string direct_follow(const char* Default, const char* Option); + + inline std::vector string_tails(const char* StartString); + inline std::vector int_tails(const char* StartString, const int Default = 1); + inline std::vector double_tails(const char* StartString, const double Default = 1.0); + + // (*) nominus arguments --------------------------------------------------- + inline STRING_VECTOR nominus_vector() const; + inline unsigned nominus_size() const { return static_cast(idx_nominus.size()); } + inline std::string next_nominus(); + + // (*) unidentified flying objects ----------------------------------------- + inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const; + inline STRING_VECTOR unidentified_arguments(const STRING_VECTOR& Knowns) const; + inline STRING_VECTOR unidentified_arguments() const; + + inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const; + inline STRING_VECTOR unidentified_options(const STRING_VECTOR& Knowns) const; + inline STRING_VECTOR unidentified_options() const; + + inline std::string unidentified_flags(const char* Known, + int ArgumentNumber /* =-1 */) const; + + inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const; + inline STRING_VECTOR unidentified_variables(const STRING_VECTOR& Knowns) const; + inline STRING_VECTOR unidentified_variables() const; + + inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const; + inline STRING_VECTOR unidentified_sections(const STRING_VECTOR& Knowns) const; + inline STRING_VECTOR unidentified_sections() const; + + inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const; + inline STRING_VECTOR unidentified_nominuses(const STRING_VECTOR& Knowns) const; + inline STRING_VECTOR unidentified_nominuses() const; + + // (*) output -------------------------------------------------------------- + inline int print() const; + +private: + // (*) Type Declaration ---------------------------------------------------- + struct variable { + //----------- + // Variable to be specified on the command line or in input files. + // (i.e. of the form var='12 312 341') + + // -- constructors, destructors, assignment operator + variable(); + variable(const variable&); + variable(const char* Name, const char* Value, const char* FieldSeparator); + ~variable(); + variable& operator=(const variable& That); + + void take(const char* Value, const char* FieldSeparator); + + // -- get a specific element in the string vector + // (return 0 if not present) + const std::string* get_element(unsigned Idx) const; + + // -- data memebers + std::string name; // identifier of variable + STRING_VECTOR value; // value of variable stored in vector + std::string original; // value of variable as given on command line + }; + + // (*) member variables -------------------------------------------------------------- + std::string prefix; // prefix automatically added in queries + std::string section; // (for dollar bracket parsing) + STRING_VECTOR section_list; // list of all parsed sections + // -- argument vector + STRING_VECTOR argv; // vector of command line arguments stored as strings + unsigned cursor; // cursor for argv + bool search_loop_f; // shall search start at beginning after + // // reaching end of arg array ? + bool search_failed_f; // flag indicating a failed search() operation + // // (e.g. next() functions react with 'missed') + + // -- nominus vector + int nominus_cursor; // cursor for nominus_pointers + std::vector idx_nominus; // indecies of 'no minus' arguments + + // -- variables + // (arguments of the form "variable=value") + std::vector variables; + + // -- comment delimiters + std::string _comment_start; + std::string _comment_end; + + // -- field separator (separating elements of a vector) + std::string _field_separator; + + // -- some functions return a char pointer to a temporarily existing string + // this container makes them 'available' until the getpot object is destroyed. + std::vector __internal_string_container; + + // -- keeping track about arguments that are requested, so that the UFO detection + // can be simplified + STRING_VECTOR _requested_arguments; + STRING_VECTOR _requested_variables; + STRING_VECTOR _requested_sections; + + bool __request_recording_f; // speed: request recording can be turned off + + // -- if an argument is requested record it and the 'tag' the section branch to which + // it belongs. Caution: both functions mark the sections as 'tagged'. + void __record_argument_request(const std::string& Arg); + void __record_variable_request(const std::string& Arg); + + // (*) helper functions ---------------------------------------------------- + // set variable from inside GetPot (no prefix considered) + inline void __set_variable(const char* VarName, const char* Value); + + // -- produce three basic data vectors: + // - argument vector + // - nominus vector + // - variable dictionary + inline void __parse_argument_vector(const STRING_VECTOR& ARGV); + + // -- helpers for argument list processing + // * search for a variable in 'variables' array + inline const variable* __find_variable(const char*) const; + // * support finding directly followed arguments + inline const char* __match_starting_string(const char* StartString); + // * support search for flags in a specific argument + inline bool __check_flags(const std::string& Str, const char* FlagList) const; + // * type conversion if possible + inline int __convert_to_type(const std::string& String, int Default) const; + inline double __convert_to_type(const std::string& String, double Default) const; + // * prefix extraction + const std::string __get_remaining_string(const std::string& String, + const std::string& Start) const; + // * search for a specific string + inline bool __search_string_vector(const STRING_VECTOR& Vec, + const std::string& Str) const; + + // -- helpers to parse input file + // create an argument vector based on data found in an input file, i.e.: + // 1) delete comments (in between '_comment_start' '_comment_end') + // 2) contract assignment expressions, such as + // my-variable = '007 J. B.' + // into + // my-variable='007 J. B.' + // 3) interprete sections like '[../my-section]' etc. + inline void __skip_whitespace(std::istream& istr); + inline const std::string __get_next_token(std::istream& istr); + inline const std::string __get_string(std::istream& istr); + inline const std::string __get_until_closing_bracket(std::istream& istr); + + inline STRING_VECTOR __read_in_stream(std::istream& istr); + inline STRING_VECTOR __read_in_file(const char* FileName); + inline std::string __process_section_label(const std::string& Section, + STRING_VECTOR& section_stack); + + // -- dollar bracket expressions + std::string __DBE_expand_string(const std::string str); + std::string __DBE_expand(const std::string str); + const GetPot::variable* __DBE_get_variable(const std::string str); + STRING_VECTOR __DBE_get_expr_list(const std::string str, const unsigned ExpectedNumber); + + std::string __double2string(const double& Value) const { + // -- converts a double integer into a string + char* tmp = new char[128]; +#ifndef WIN32 + snprintf(tmp, (int)sizeof(char)*128, "%e", Value); +#else + _snprintf(tmp, sizeof(char)*128, "%e", Value); +#endif + std::string result(tmp); + delete [] tmp; + return result; + } + + std::string __int2string(const int& Value) const { + // -- converts an integer into a string + char* tmp = new char[128]; +#ifndef WIN32 + snprintf(tmp, (int)sizeof(char)*128, "%i", Value); +#else + _snprintf(tmp, sizeof(char)*128, "%i", Value); +#endif + std::string result(tmp); + delete [] tmp; + return result; + } + + STRING_VECTOR __get_section_tree(const std::string& FullPath) { + // -- cuts a variable name into a tree of sub-sections. this is requested for recording + // requested sections when dealing with 'ufo' detection. + STRING_VECTOR result; + const char* Start = FullPath.c_str(); + + for(char *p = (char*)Start; *p ; p++) { + if( *p == '/' ) { + *p = '\0'; // set terminating zero for convinience + const std::string Section = Start; + *p = '/'; // reset slash at place + result.push_back(Section); + } + } + + return result; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// (*) constructors, destructor, assignment operator +//............................................................................. +// +inline void +GetPot::__basic_initialization() +{ + cursor = 0; nominus_cursor = -1; + search_failed_f = true; search_loop_f = true; + prefix = ""; section = ""; + + // automatic request recording for later ufo detection + __request_recording_f = true; + + // comment start and end strings + _comment_start = std::string("#"); + _comment_end = std::string("\n"); + + // default: separate vector elements by whitespaces + _field_separator = " \t\n"; +} + +inline +GetPot::GetPot() +{ + __basic_initialization(); + + STRING_VECTOR _apriori_argv; + _apriori_argv.push_back(std::string("Empty")); + __parse_argument_vector(_apriori_argv); +} + +inline +GetPot::GetPot(const int argc_, char ** argv_, + const char* FieldSeparator /* =0x0 */) + // leave 'char**' non-const to honor less capable compilers ... +{ + // TODO: Ponder over the problem when the argument list is of size = 0. + // This is 'sabotage', but it can still occur if the user specifies + // it himself. + assert(argc_ >= 1); + __basic_initialization(); + + // if specified -> overwrite default string + if( FieldSeparator ) _field_separator = std::string(FieldSeparator); + + // -- make an internal copy of the argument list: + STRING_VECTOR _apriori_argv; + // -- for the sake of clarity: we do want to include the first argument in the argument vector ! + // it will not be a nominus argument, though. This gives us a minimun vector size of one + // which facilitates error checking in many functions. Also the user will be able to + // retrieve the name of his application by "get[0]" + _apriori_argv.push_back(std::string(argv_[0])); + int i=1; + for(; i overwrite default strings + if( CommentStart ) _comment_start = std::string(CommentStart); + if( CommentEnd ) _comment_end = std::string(CommentEnd); + if( FieldSeparator ) _field_separator = FieldSeparator; + + STRING_VECTOR _apriori_argv; + // -- file name is element of argument vector, however, it is not parsed for + // variable assignments or nominuses. + _apriori_argv.push_back(std::string(FileName)); + + STRING_VECTOR args = __read_in_file(FileName); + _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end()); + __parse_argument_vector(_apriori_argv); +} + +inline +GetPot::GetPot(const GetPot& That) +{ GetPot::operator=(That); } + +inline +GetPot::~GetPot() +{ + // may be some return strings had to be created, delete now ! + victorate(char*, __internal_string_container, it) + delete [] *it; +} + +inline GetPot& +GetPot::operator=(const GetPot& That) +{ + if (&That == this) return *this; + + _comment_start = That._comment_start; + _comment_end = That._comment_end; + argv = That.argv; + variables = That.variables; + prefix = That.prefix; + + cursor = That.cursor; + nominus_cursor = That.nominus_cursor; + search_failed_f = That.search_failed_f; + + idx_nominus = That.idx_nominus; + search_loop_f = That.search_loop_f; + + return *this; +} + + +inline void +GetPot::absorb(const GetPot& That) +{ + if (&That == this) return; + + STRING_VECTOR __tmp(That.argv); + + __tmp.erase(__tmp.begin()); + + __parse_argument_vector(__tmp); +} + +inline void +GetPot::clear_requests() +{ + _requested_arguments.erase(_requested_arguments.begin(), _requested_arguments.end()); + _requested_variables.erase(_requested_variables.begin(), _requested_variables.end()); + _requested_sections.erase(_requested_sections.begin(), _requested_sections.end()); +} + +inline void +GetPot::__parse_argument_vector(const STRING_VECTOR& ARGV) +{ + if( ARGV.size() == 0 ) return; + + // build internal databases: + // 1) array with no-minus arguments (usually used as filenames) + // 2) variable assignments: + // 'variable name' '=' number | string + STRING_VECTOR section_stack; + STRING_VECTOR::const_iterator it = ARGV.begin(); + + + section = ""; + + // -- do not parse the first argument, so that it is not interpreted a s a nominus or so. + argv.push_back(*it); + ++it; + + // -- loop over remaining arguments + unsigned i=1; + for(; it != ARGV.end(); ++it, ++i) { + std::string arg = *it; + + if( arg.length() == 0 ) continue; + + // -- [section] labels + if( arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']' ) { + + // (*) sections are considered 'requested arguments' + if( __request_recording_f ) _requested_arguments.push_back(arg); + + const std::string Name = __DBE_expand_string(arg.substr(1, arg.length()-2)); + section = __process_section_label(Name, section_stack); + // new section --> append to list of sections + if( find(section_list.begin(), section_list.end(), section) == section_list.end() ) + if( section.length() != 0 ) section_list.push_back(section); + argv.push_back(arg); + } + else { + arg = section + __DBE_expand_string(arg); + argv.push_back(arg); + } + + // -- separate array for nominus arguments + if( arg[0] != '-' ) idx_nominus.push_back(unsigned(i)); + + // -- variables: does arg contain a '=' operator ? + const char* p = arg.c_str(); + for(; *p ; p++) { + if( *p == '=' ) { + // (*) record for later ufo detection + // arguments carriying variables are always treated as 'requested' arguments. + // as a whole! That is 'x=4712' is considered a requested argument. + // + // unrequested variables have to be detected with the ufo-variable + // detection routine. + if( __request_recording_f ) _requested_arguments.push_back(arg); + + // set terminating 'zero' to treat first part as single string + // => arg (from start to 'p') = Name of variable + // p+1 (until terminating zero) = value of variable + char* o = (char*)p++; + *o = '\0'; // set temporary terminating zero + // __set_variable(...) + // calls __find_variable(...) which registers the search + // temporarily disable this + const bool tmp = __request_recording_f; + __request_recording_f = false; + __set_variable(arg.c_str(), p); // v-name = c_str() bis 'p', value = rest + __request_recording_f = tmp; + *o = '='; // reset the original '=' + break; + } + } + } +} + + +inline STRING_VECTOR +GetPot::__read_in_file(const char* FileName) +{ + std::ifstream i(FileName); + if( ! i ) return STRING_VECTOR(); + // argv[0] == the filename of the file that was read in + return __read_in_stream(i); +} + +inline STRING_VECTOR +GetPot::__read_in_stream(std::istream& istr) +{ + STRING_VECTOR brute_tokens; + while(istr) { + __skip_whitespace(istr); + + const std::string Token = __get_next_token(istr); + if( Token.length() == 0 || Token[0] == EOF) break; + brute_tokens.push_back(Token); + } + + // -- reduce expressions of token1'='token2 to a single + // string 'token1=token2' + // -- copy everything into 'argv' + // -- arguments preceded by something like '[' name ']' (section) + // produce a second copy of each argument with a prefix '[name]argument' + unsigned i1 = 0; + unsigned i2 = 1; + unsigned i3 = 2; + + STRING_VECTOR arglist; + while( i1 < brute_tokens.size() ) { + const std::string& SRef = brute_tokens[i1]; + // 1) concatinate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef' + // note: java.lang.String: substring(a,b) = from a to b-1 + // C++ string: substr(a,b) = from a to a + b + if( i2 < brute_tokens.size() && brute_tokens[i2] == "=" ) { + if( i3 >= brute_tokens.size() ) + arglist.push_back(brute_tokens[i1] + brute_tokens[i2]); + else + arglist.push_back(brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3]); + i1 = i3+1; i2 = i3+2; i3 = i3+3; + continue; + } + else { + arglist.push_back(SRef); + i1=i2; i2=i3; i3++; + } + } + return arglist; +} + +inline void +GetPot::__skip_whitespace(std::istream& istr) + // find next non-whitespace while deleting comments +{ + int tmp = istr.get(); + do { + // -- search a non whitespace + while( isspace(tmp) ) { + tmp = istr.get(); + if( ! istr ) return; + } + + // -- look if characters match the comment starter string + const std::istream::pos_type Pos = istr.tellg(); + unsigned i=0; + for(; i<_comment_start.length() ; ++i) { + if( tmp != _comment_start[i] ) { +// HACK: The following line throws off msvc8: +// istr.seekg(Pos); + // -- one step more backwards, since 'tmp' already at non-whitespace + istr.unget(); + return; + } + tmp = istr.get(); + if( ! istr ) { istr.unget(); return; } + } + // 'tmp' contains last character of _comment_starter + + // -- comment starter found -> search for comment ender + unsigned match_no=0; + while(1+1 == 2) { + tmp = istr.get(); + if( ! istr ) { istr.unget(); return; } + + if( tmp == _comment_end[match_no] ) { + match_no++; + if( match_no == _comment_end.length() ) { + istr.unget(); + break; // shuffle more whitespace, end of comment found + } + } + else + match_no = 0; + } + + tmp = istr.get(); + + } while( istr ); + istr.unget(); +} + +inline const std::string +GetPot::__get_next_token(std::istream& istr) + // get next concatinates string token. consider quotes that embrace + // whitespaces +{ + std::string token; + int tmp = 0; + int last_letter = 0; + while(1+1 == 2) { + last_letter = tmp; tmp = istr.get(); + if( tmp == EOF + || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\') ) { + return token; + } + else if( tmp == '\'' && last_letter != '\\' ) { + // QUOTES: un-backslashed quotes => it's a string + token += __get_string(istr); + continue; + } + else if( tmp == '{' && last_letter == '$') { + token += '{' + __get_until_closing_bracket(istr); + continue; + } + else if( tmp == '$' && last_letter == '\\') { + token += tmp; tmp = 0; // so that last_letter will become = 0, not '$'; + continue; + } + else if( tmp == '\\' && last_letter != '\\') + continue; // don't append un-backslashed backslashes + token += tmp; + } +} + +inline const std::string +GetPot::__get_string(std::istream& istr) + // parse input until next matching ' +{ + std::string str; + int tmp = 0; + int last_letter = 0; + while(1 + 1 == 2) { + last_letter = tmp; tmp = istr.get(); + if( tmp == EOF) return str; + // un-backslashed quotes => it's the end of the string + else if( tmp == '\'' && last_letter != '\\') return str; + else if( tmp == '\\' && last_letter != '\\') continue; // don't append + + str += tmp; + } +} + +inline const std::string +GetPot::__get_until_closing_bracket(std::istream& istr) + // parse input until next matching } +{ + std::string str = ""; + int tmp = 0; + int last_letter = 0; + int brackets = 1; + while(1 + 1 == 2) { + last_letter = tmp; tmp = istr.get(); + if( tmp == EOF) return str; + else if( tmp == '{' && last_letter == '$') brackets += 1; + else if( tmp == '}') { + brackets -= 1; + // un-backslashed brackets => it's the end of the string + if( brackets == 0) return str + '}'; + else if( tmp == '\\' && last_letter != '\\') + continue; // do not append an unbackslashed backslash + } + str += tmp; + } +} + +inline std::string +GetPot::__process_section_label(const std::string& Section, + STRING_VECTOR& section_stack) +{ + std::string sname = Section; + // 1) subsection of actual section ('./' prefix) + if( sname.length() >= 2 && sname.substr(0, 2) == "./" ) { + sname = sname.substr(2); + } + // 2) subsection of parent section ('../' prefix) + else if( sname.length() >= 3 && sname.substr(0, 3) == "../" ) { + do { + if( section_stack.end() != section_stack.begin() ) + section_stack.pop_back(); + sname = sname.substr(3); + } while( sname.substr(0, 3) == "../" ); + } + // 3) subsection of the root-section + else { + section_stack.erase(section_stack.begin(), section_stack.end()); + // [] => back to root section + } + + if( sname != "" ) { + // parse section name for 'slashes' + unsigned i=0; + while( i < sname.length() ) { + if( sname[i] == '/' ) { + section_stack.push_back(sname.substr(0,i)); + if( i+1 < sname.length()-1 ) + sname = sname.substr(i+1); + i = 0; + } + else + ++i; + } + section_stack.push_back(sname); + } + std::string section = ""; + if( section_stack.size() != 0 ) { + victorate(std::string, section_stack, it) + section += *it + "/"; + } + return section; +} + + +// convert string to DOUBLE, if not possible return Default +inline double +GetPot::__convert_to_type(const std::string& String, double Default) const +{ + double tmp; + if( sscanf(String.c_str(),"%lf", &tmp) != 1 ) return Default; + return tmp; +} + +// convert string to INT, if not possible return Default +inline int +GetPot::__convert_to_type(const std::string& String, int Default) const +{ + // NOTE: intermediate results may be floating points, so that the string + // may look like 2.0e1 (i.e. float format) => use float conversion + // in any case. + return (int)__convert_to_type(String, (double)Default); +} + +////////////////////////////////////////////////////////////////////////////// +// (*) cursor oriented functions +//............................................................................. +inline const std::string +GetPot::__get_remaining_string(const std::string& String, const std::string& Start) const + // Checks if 'String' begins with 'Start' and returns the remaining String. + // Returns None if String does not begin with Start. +{ + if( Start == "" ) return String; + // note: java.lang.String: substring(a,b) = from a to b-1 + // C++ string: substr(a,b) = from a to a + b + if( String.find(Start) == 0 ) return String.substr(Start.length()); + else return ""; +} + +// -- search for a certain argument and set cursor to position +inline bool +GetPot::search(const char* Option) +{ + unsigned OldCursor = cursor; + const std::string SearchTerm = prefix + Option; + + // (*) record requested arguments for later ufo detection + __record_argument_request(SearchTerm); + + if( OldCursor >= argv.size() ) OldCursor = static_cast(argv.size()) - 1; + search_failed_f = true; + + // (*) first loop from cursor position until end + unsigned c = cursor; + for(; c < argv.size(); c++) { + if( argv[c] == SearchTerm ) + { cursor = c; search_failed_f = false; return true; } + } + if( ! search_loop_f ) return false; + + // (*) second loop from 0 to old cursor position + for(c = 1; c < OldCursor; c++) { + if( argv[c] == SearchTerm ) + { cursor = c; search_failed_f = false; return true; } + } + // in case nothing is found the cursor stays where it was + return false; +} + + +inline bool +GetPot::search(unsigned No, const char* P, ...) +{ + // (*) recording the requested arguments happens in subroutine 'search' + if( No == 0 ) return false; + + // search for the first argument + if( search(P) == true ) return true; + + // start interpreting variable argument list + va_list ap; + va_start(ap, P); + unsigned i = 1; + for(; i < No; ++i) { + char* Opt = va_arg(ap, char *); + if( search(Opt) == true ) break; + } + + if( i < No ) { + ++i; + // loop was left before end of array --> hit but + // make sure that the rest of the search terms is marked + // as requested. + for(; i < No; ++i) { + char* Opt = va_arg(ap, char *); + // (*) record requested arguments for later ufo detection + __record_argument_request(Opt); + } + va_end(ap); + return true; + } + + va_end(ap); + // loop was left normally --> no hit + return false; +} + +inline void +GetPot::reset_cursor() +{ search_failed_f = false; cursor = 0; } + +inline void +GetPot::init_multiple_occurrence() +{ disable_loop(); reset_cursor(); } +/////////////////////////////////////////////////////////////////////////////// +// (*) direct access to command line arguments +//............................................................................. +// +inline const std::string +GetPot::operator[](unsigned idx) const +{ return idx < argv.size() ? argv[idx] : ""; } + +inline int +GetPot::get(unsigned Idx, int Default) const +{ + if( Idx >= argv.size() ) return Default; + return __convert_to_type(argv[Idx], Default); +} + +inline double +GetPot::get(unsigned Idx, const double& Default) const +{ + if( Idx >= argv.size() ) return Default; + return __convert_to_type(argv[Idx], Default); +} + +inline const std::string +GetPot::get(unsigned Idx, const char* Default) const +{ + if( Idx >= argv.size() ) return Default; + else return argv[Idx]; +} + +inline unsigned +GetPot::size() const +{ return static_cast(argv.size()); } + + +// -- next() function group +inline int +GetPot::next(int Default) +{ + if( search_failed_f ) return Default; + cursor++; + if( cursor >= argv.size() ) + { cursor = static_cast(argv.size()); return Default; } + + // (*) record requested argument for later ufo detection + __record_argument_request(argv[cursor]); + + const std::string Remain = __get_remaining_string(argv[cursor], prefix); + + return Remain != "" ? __convert_to_type(Remain, Default) : Default; +} + +inline double +GetPot::next(const double& Default) +{ + if( search_failed_f ) return Default; + cursor++; + + if( cursor >= argv.size() ) + { cursor = static_cast(argv.size()); return Default; } + + // (*) record requested argument for later ufo detection + __record_argument_request(argv[cursor]); + + std::string Remain = __get_remaining_string(argv[cursor], prefix); + + return Remain != "" ? __convert_to_type(Remain, Default) : Default; +} + +inline const std::string +GetPot::next(const char* Default) +{ + if( search_failed_f ) return Default; + cursor++; + + if( cursor >= argv.size() ) + { cursor = static_cast(argv.size()); return Default; } + + // (*) record requested argument for later ufo detection + __record_argument_request(argv[cursor]); + + const std::string Remain = __get_remaining_string(argv[cursor], prefix); + + if( Remain == "" ) return Default; + + + // (*) function returns a pointer to a char array (inside Remain) + // this array will be deleted, though after this function call. + // To ensure propper functioning, create a copy inside *this + // object and only delete it, when *this is deleted. + char* result = new char[Remain.length()+1]; + strncpy(result, Remain.c_str(), Remain.length()+1); + + // store the created string internally, delete if when object deleted + __internal_string_container.push_back(result); + + return result; +} + +// -- follow() function group +// distinct option to be searched for +inline int +GetPot::follow(int Default, const char* Option) +{ + // (*) record requested of argument is entirely handled in 'search()' and 'next()' + if( search(Option) == false ) return Default; + return next(Default); +} + +inline double +GetPot::follow(const double& Default, const char* Option) +{ + // (*) record requested of argument is entirely handled in 'search()' and 'next()' + if( search(Option) == false ) return Default; + return next(Default); +} + +inline const std::string +GetPot::follow(const char* Default, const char* Option) +{ + // (*) record requested of argument is entirely handled in 'search()' and 'next()' + if( search(Option) == false ) return Default; + return next(Default); +} + +// -- second follow() function group +// multiple option to be searched for +inline int +GetPot::follow(int Default, unsigned No, const char* P, ...) +{ + // (*) record requested of argument is entirely handled in 'search()' and 'next()' + if( No == 0 ) return Default; + if( search(P) == true ) return next(Default); + + va_list ap; + va_start(ap, P); + unsigned i=1; + for(; i +GetPot::nominus_followers(const char* Option) +{ + std::vector result_list; + if( search(Option) == false ) return result_list; + while( 1 + 1 == 2 ) { + ++cursor; + if( cursor >= argv.size() ) { + cursor = argv.size() - 1; + return result_list; + } + if( argv[cursor].length() >= 1 ) { + if( argv[cursor][0] == '-' ) { + return result_list; + } + // -- record for later ufo-detection + __record_argument_request(argv[cursor]); + // -- append to the result list + result_list.push_back(argv[cursor]); + } + } +} + +inline std::vector +GetPot::nominus_followers(unsigned No, ...) +{ + std::vector result_list; + // (*) record requested of argument is entirely handled in 'search()' + // and 'nominus_followers()' + if( No == 0 ) return result_list; + + va_list ap; + va_start(ap, No); + for(unsigned i=0; i tmp = nominus_followers(Option); + result_list.insert(result_list.end(), tmp.begin(), tmp.end()); + + // std::cerr << "option = '" << Option << "'" << std::endl; + // std::cerr << "length = " << tmp.size() << std::endl; + // std::cerr << "new result list = <"; + // for(std::vector::const_iterator it = result_list.begin(); + // it != result_list.end(); ++it) + // std::cerr << *it << ", "; + // std::cerr << ">\n"; + } + va_end(ap); + return result_list; +} + + +/////////////////////////////////////////////////////////////////////////////// +// (*) directly connected options +//............................................................................. +// +inline int +GetPot::direct_follow(int Default, const char* Option) +{ + const char* FollowStr = __match_starting_string(Option); + if( FollowStr == 0x0 ) return Default; + + // (*) record requested of argument for later ufo-detection + __record_argument_request(std::string(Option) + FollowStr); + + if( ++cursor >= static_cast(argv.size()) ) cursor = static_cast(argv.size()); + return __convert_to_type(FollowStr, Default); +} + +inline double +GetPot::direct_follow(const double& Default, const char* Option) +{ + const char* FollowStr = __match_starting_string(Option); + if( FollowStr == 0 ) return Default; + + // (*) record requested of argument for later ufo-detection + __record_argument_request(std::string(Option) + FollowStr); + + if( ++cursor >= static_cast(argv.size()) ) cursor = static_cast(argv.size()); + return __convert_to_type(FollowStr, Default); +} + +inline const std::string +GetPot::direct_follow(const char* Default, const char* Option) +{ + if( search_failed_f ) return Default; + const char* FollowStr = __match_starting_string(Option); + if( FollowStr == 0 ) return Default; + + // (*) record requested of argument for later ufo-detection + if( FollowStr ) __record_argument_request(std::string(Option) + FollowStr); + + if( ++cursor >= static_cast(argv.size()) ) cursor = static_cast(argv.size()); + return std::string(FollowStr); +} + +inline std::vector +GetPot::string_tails(const char* StartString) +{ + std::vector result; + const unsigned N = static_cast(strlen(StartString)); + + std::vector::iterator it = argv.begin(); + + unsigned idx = 0; + while( it != argv.end() ) { + // (*) does start string match the given option? + // NO -> goto next option + if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; } + + // append the found tail to the result vector + result.push_back((*it).substr(N)); + + // adapt the nominus vector + std::vector::iterator nit = idx_nominus.begin(); + for(; nit != idx_nominus.end(); ++nit) { + if( *nit == idx ) { + idx_nominus.erase(nit); + for(; nit != idx_nominus.end(); ++nit) *nit -= 1; + break; + } + } + + // erase the found option + argv.erase(it); + + // 100% safe solution: set iterator back to the beginning. + // (normally, 'it--' would be enough, but who knows how the + // iterator is implemented and .erase() definitely invalidates + // the current iterator position. + if( argv.empty() ) break; + it = argv.begin(); + } + cursor = 0; + nominus_cursor = -1; + return result; +} + +inline std::vector +GetPot::int_tails(const char* StartString, const int Default /* = -1 */) +{ + std::vector result; + const unsigned N = static_cast(strlen(StartString)); + + std::vector::iterator it = argv.begin(); + + unsigned idx = 0; + while( it != argv.end() ) { + // (*) does start string match the given option? + // NO -> goto next option + if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; } + + // append the found tail to the result vector + result.push_back(__convert_to_type((*it).substr(N), Default)); + + // adapt the nominus vector + std::vector::iterator nit = idx_nominus.begin(); + for(; nit != idx_nominus.end(); ++nit) { + if( *nit == idx ) { + idx_nominus.erase(nit); + for(; nit != idx_nominus.end(); ++nit) *nit -= 1; + break; + } + } + + // erase the found option + argv.erase(it); + + // 100% safe solution: set iterator back to the beginning. + // (normally, 'it--' would be enough, but who knows how the + // iterator is implemented and .erase() definitely invalidates + // the current iterator position. + if( argv.empty() ) break; + it = argv.begin(); + } + cursor = 0; + nominus_cursor = -1; + return result; +} + +inline std::vector +GetPot::double_tails(const char* StartString, + const double Default /* = -1.0 */) +{ + std::vector result; + const unsigned N = static_cast(strlen(StartString)); + + std::vector::iterator it = argv.begin(); + unsigned idx = 0; + while( it != argv.end() ) { + // (*) does start string match the given option? + // NO -> goto next option + if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; } + + // append the found tail to the result vector + result.push_back(__convert_to_type((*it).substr(N), Default)); + + // adapt the nominus vector + std::vector::iterator nit = idx_nominus.begin(); + for(; nit != idx_nominus.end(); ++nit) { + if( *nit == idx ) { + idx_nominus.erase(nit); + for(; nit != idx_nominus.end(); ++nit) *nit -= 1; + break; + } + } + + // erase the found option + argv.erase(it); + + // 100% safe solution: set iterator back to the beginning. + // (normally, 'it--' would be enough, but who knows how the + // iterator is implemented and .erase() definitely invalidates + // the current iterator position. + if( argv.empty() ) break; + it = argv.begin(); + } + cursor = 0; + nominus_cursor = -1; + return result; +} + + + + + +inline const char* +GetPot::__match_starting_string(const char* StartString) + // pointer to the place where the string after + // the match inside the found argument starts. + // 0 no argument matches the starting string. +{ + const unsigned N = static_cast(strlen(StartString)); + unsigned OldCursor = cursor; + + if( OldCursor >= static_cast(argv.size()) ) OldCursor = static_cast(argv.size()) - 1; + search_failed_f = true; + + // (*) first loop from cursor position until end + unsigned c = cursor; + for(; c < argv.size(); c++) { + if( strncmp(StartString, argv[c].c_str(), N) == 0) + { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); } + } + + if( ! search_loop_f ) return false; + + // (*) second loop from 0 to old cursor position + for(c = 1; c < OldCursor; c++) { + if( strncmp(StartString, argv[c].c_str(), N) == 0) + { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); } + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// (*) search for flags +//............................................................................. +// +inline bool +GetPot::options_contain(const char* FlagList) const +{ + // go through all arguments that start with a '-' (but not '--') + std::string str; + STRING_VECTOR::const_iterator it = argv.begin(); + for(; it != argv.end(); ++it) { + str = __get_remaining_string(*it, prefix); + + if( str.length() >= 2 && str[0] == '-' && str[1] != '-' ) + if( __check_flags(str, FlagList) ) return true; + } + return false; +} + +inline bool +GetPot::argument_contains(unsigned Idx, const char* FlagList) const +{ + if( Idx >= argv.size() ) return false; + + // (*) record requested of argument for later ufo-detection + // an argument that is checked for flags is considered to be 'requested' + ((GetPot*)this)->__record_argument_request(argv[Idx]); + + if( prefix == "" ) + // search argument for any flag in flag list + return __check_flags(argv[Idx], FlagList); + + // if a prefix is set, then the argument index is the index + // inside the 'namespace' + // => only check list of arguments that start with prefix + unsigned no_matches = 0; + unsigned i=0; + for(; i::const_iterator it = idx_nominus.begin(); + for(; it != idx_nominus.end(); ++it) { + nv.push_back(argv[*it]); + + // (*) record for later ufo-detection + // when a nominus vector is requested, the entire set of nominus arguments are + // tagged as 'requested' + ((GetPot*)this)->__record_argument_request(argv[*it]); + } + return nv; +} + +inline std::string +GetPot::next_nominus() +{ + if( nominus_cursor < int(idx_nominus.size()) - 1 ) { + const std::string Tmp = argv[idx_nominus[++nominus_cursor]]; + + // (*) record for later ufo-detection + __record_argument_request(Tmp); + + // -- cannot use the Tmp variable, since it is temporary and c_str() will return a pointer + // to something that does no longer exist. + return Tmp; + } + return std::string(""); +} + +/////////////////////////////////////////////////////////////////////////////// +// (*) variables +//............................................................................. +// +inline int +GetPot::operator()(const char* VarName, int Default) const +{ + // (*) recording of requested variables happens in '__find_variable()' + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return Default; + return __convert_to_type(sv->original, Default); +} + +inline double +GetPot::operator()(const char* VarName, const double& Default) const +{ + // (*) recording of requested variables happens in '__find_variable()' + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return Default; + return __convert_to_type(sv->original, Default); +} + +inline const std::string +GetPot::operator()(const char* VarName, const char* Default) const +{ + // (*) recording of requested variables happens in '__find_variable()' + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return Default; + // -- returning a c_str() pointer is OK here, since the variable remains existant, + // while 'sv' of course is delete at the end of the function. + return sv->original; +} + +inline int +GetPot::operator()(const char* VarName, int Default, unsigned Idx) const +{ + // (*) recording of requested variables happens in '__find_variable()' + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return Default; + const std::string* element = sv->get_element(Idx); + if( element == 0 ) return Default; + return __convert_to_type(*element, Default); +} + +inline double +GetPot::operator()(const char* VarName, const double& Default, unsigned Idx) const +{ + // (*) recording of requested variables happens in '__find_variable()' + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return Default; + const std::string* element = sv->get_element(Idx); + if( element == 0 ) return Default; + return __convert_to_type(*element, Default); +} + +inline const std::string +GetPot::operator()(const char* VarName, const char* Default, unsigned Idx) const +{ + // (*) recording of requested variables happens in '__find_variable()' + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return Default; + const std::string* element = sv->get_element(Idx); + if( element == 0 ) return Default; + return *element; +} + +inline void +GetPot::__record_argument_request(const std::string& Name) +{ + if( ! __request_recording_f ) return; + + // (*) record requested variable for later ufo detection + _requested_arguments.push_back(Name); + + // (*) record considered section for ufo detection + STRING_VECTOR STree = __get_section_tree(Name); + victorate(std::string, STree, it) + if( find(_requested_sections.begin(), _requested_sections.end(), *it) == _requested_sections.end() ) + if( section.length() != 0 ) _requested_sections.push_back(*it); +} + +inline void +GetPot::__record_variable_request(const std::string& Name) +{ + if( ! __request_recording_f ) return; + + // (*) record requested variable for later ufo detection + _requested_variables.push_back(Name); + + // (*) record considered section for ufo detection + STRING_VECTOR STree = __get_section_tree(Name); + victorate(std::string, STree, it) + if( find(_requested_sections.begin(), _requested_sections.end(), *it) == _requested_sections.end() ) + if( section.length() != 0 ) _requested_sections.push_back(*it); +} + +// (*) following functions are to be used from 'outside', after getpot has parsed its +// arguments => append an argument in the argument vector that reflects the addition +inline void +GetPot::__set_variable(const char* VarName, const char* Value) +{ + const GetPot::variable* Var = __find_variable(VarName); + if( Var == 0 ) variables.push_back(variable(VarName, Value, _field_separator.c_str())); + else ((GetPot::variable*)Var)->take(Value, _field_separator.c_str()); +} + +inline void +GetPot::set(const char* VarName, const char* Value, const bool Requested /* = yes */) +{ + const std::string Arg = prefix + std::string(VarName) + std::string("=") + std::string(Value); + argv.push_back(Arg); + __set_variable(VarName, Value); + + // if user does not specify the variable as 'not being requested' it will be + // considered amongst the requested variables + if( Requested ) __record_variable_request(Arg); +} + +inline void +GetPot::set(const char* VarName, const double& Value, const bool Requested /* = yes */) +{ __set_variable(VarName, __double2string(Value).c_str()); } + +inline void +GetPot::set(const char* VarName, const int Value, const bool Requested /* = yes */) +{ __set_variable(VarName, __int2string(Value).c_str()); } + + +inline unsigned +GetPot::vector_variable_size(const char* VarName) const +{ + const variable* sv = __find_variable(VarName); + if( sv == 0 ) return 0; + return static_cast(sv->value.size()); +} + +inline STRING_VECTOR +GetPot::get_variable_names() const +{ + STRING_VECTOR result; + std::vector::const_iterator it = variables.begin(); + for(; it != variables.end(); ++it) { + const std::string Tmp = __get_remaining_string((*it).name, prefix); + if( Tmp != "" ) result.push_back(Tmp); + } + return result; +} + +inline STRING_VECTOR +GetPot::get_section_names() const +{ return section_list; } + +inline const GetPot::variable* +GetPot::__find_variable(const char* VarName) const +{ + const std::string Name = prefix + VarName; + + // (*) record requested variable for later ufo detection + ((GetPot*)this)->__record_variable_request(Name); + + std::vector::const_iterator it = variables.begin(); + for(; it != variables.end(); ++it) { + if( (*it).name == Name ) return &(*it); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// (*) ouput (basically for debugging reasons +//............................................................................. +// +inline int +GetPot::print() const +{ + std::cout << "argc = " << static_cast(argv.size()) << std::endl; + STRING_VECTOR::const_iterator it = argv.begin(); + for(; it != argv.end(); ++it) + std::cout << *it << std::endl; + std::cout << std::endl; + return 1; +} + +// (*) dollar bracket expressions (DBEs) ------------------------------------ +// +// 1) Entry Function: __DBE_expand_string() +// Takes a string such as +// +// "${+ ${x} ${y}} Subject-${& ${section} ${subsection}}: ${title}" +// +// calls __DBE_expand() for each of the expressions +// +// ${+ ${x} ${y}} +// ${& ${section} ${subsection}} +// ${Title} +// +// and returns the string +// +// "4711 Subject-1.01: Mit den Clowns kamen die Schwaene" +// +// assuming that +// x = "4699" +// y = "12" +// section = "1." +// subsection = "01" +// title = "Mit den Clowns kamen die Schwaene" +// +// 2) __DBE_expand(): +// +// checks for the command, i.e. the 'sign' that follows '${' +// divides the argument list into sub-expressions using +// __DBE_get_expr_list() +// +// ${+ ${x} ${y}} -> "${x}" "${y}" +// ${& ${section} ${subsection}} -> "${section}" "${subsection}" +// ${Title} -> Nothing, variable expansion +// +// 3) __DBE_expression_list(): +// +// builds a vector of unbracketed whitespace separated strings, i.e. +// +// " ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}" +// +// is split into a vector +// +// [0] ${Number}.a +// [1] ${: Das Marmorbild} +// [2] AB-${& Author= ${Eichendorf}}-1870 +// +// Each sub-expression is expanded using expand(). +//--------------------------------------------------------------------------- +inline std::string +GetPot::__DBE_expand_string(const std::string str) +{ + // Parses for closing operators '${ }' and expands them letting + // white spaces and other letters as they are. + std::string new_string = ""; + unsigned open_brackets = 0; + unsigned first = 0; + unsigned i = 0; + for(; i 0) { + open_brackets -= 1; + if( open_brackets == 0 ) { + const std::string Replacement = __DBE_expand(str.substr(first, i - first)); + new_string += Replacement; + } + } + else if( open_brackets == 0 ) + new_string += str[i]; + } + return new_string; +} + +inline STRING_VECTOR +GetPot::__DBE_get_expr_list(const std::string str_, const unsigned ExpectedNumber) + // ensures that the resulting vector has the expected number + // of arguments, but they may contain an error message +{ + std::string str = str_; + // Separates expressions by non-bracketed whitespaces, expands them + // and puts them into a list. + + unsigned i=0; + // (1) eat initial whitespaces + for(; i < str.size(); ++i) + if( ! isspace(str[i]) ) break; + + STRING_VECTOR expr_list; + unsigned open_brackets = 0; + std::vector start_idx; + unsigned start_new_string = i; + unsigned l = static_cast(str.size()); + + // (2) search for ${ } expressions ... + while( i < l ) { + const char letter = str[i]; + // whitespace -> end of expression + if( isspace(letter) && open_brackets == 0) { + expr_list.push_back(str.substr(start_new_string, i - start_new_string)); + bool no_breakout_f = true; + for(++i; i < l ; ++i) { + if( ! isspace(str[i]) ) + { no_breakout_f = false; start_new_string = i; break; } + } + if( no_breakout_f ) { + // end of expression list + if( expr_list.size() < ExpectedNumber ) { + const std::string pre_tmp("<< ${ }: missing arguments>>"); + STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp); + expr_list.insert(expr_list.end(), tmp.begin(), tmp.end()); + } + return expr_list; + } + } + + // dollar-bracket expression + if( str.length() >= i+2 && str.substr(i, 2) == "${" ) { + open_brackets++; + start_idx.push_back(i+2); + } + else if( letter == '}' && open_brackets > 0) { + int start = start_idx[start_idx.size()-1]; + start_idx.pop_back(); + const std::string Replacement = __DBE_expand(str.substr(start, i-start)); + if( start - 3 < (int)0) + str = Replacement + str.substr(i+1); + else + str = str.substr(0, start-2) + Replacement + str.substr(i+1); + l = static_cast(str.size()); + i = start + static_cast(Replacement.size()) - 3; + open_brackets--; + } + ++i; + } + + // end of expression list + expr_list.push_back(str.substr(start_new_string, i-start_new_string)); + + if( expr_list.size() < ExpectedNumber ) { + const std::string pre_tmp("<< ${ }: missing arguments>>"); + STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp); + expr_list.insert(expr_list.end(), tmp.begin(), tmp.end()); + } + + return expr_list; +} + +inline const GetPot::variable* +GetPot::__DBE_get_variable(std::string VarName) +{ + static GetPot::variable ev; + std::string secure_Prefix = prefix; + + prefix = section; + // (1) first search in currently active section + const GetPot::variable* var = __find_variable(VarName.c_str()); + if( var != 0 ) { prefix = secure_Prefix; return var; } + + // (2) search in root name space + prefix = ""; + var = __find_variable(VarName.c_str()); + if( var != 0 ) { prefix = secure_Prefix; return var; } + + prefix = secure_Prefix; + + // error occured => variable name == "" + char* tmp = new char[VarName.length() + 25]; +#ifndef WIN32 + snprintf(tmp, (int)sizeof(char)*(VarName.length() + 25), +#else + _snprintf(tmp, sizeof(char)*(VarName.length() + 25), +#endif + "<<${ } variable '%s' undefined>>", VarName.c_str()); + ev.name = ""; + ev.original = std::string(tmp); + delete [] tmp; + return &ev; +} + +inline std::string +GetPot::__DBE_expand(const std::string expr) +{ + // ${: } pure text + if( expr[0] == ':' ) + return expr.substr(1); + + // ${& expr expr ... } text concatination + else if( expr[0] == '&' ) { + const STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 1); + + STRING_VECTOR::const_iterator it = A.begin(); + std::string result = *it++; + for(; it != A.end(); ++it) result += *it; + + return result; + } + + // ${<-> expr expr expr} text replacement + else if( expr.length() >= 3 && expr.substr(0, 3) == "<->" ) { + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(3), 3); + std::string::size_type tmp = 0; + const std::string::size_type L = A[1].length(); + while( (tmp = A[0].find(A[1])) != std::string::npos ) { + A[0].replace(tmp, L, A[2]); + } + return A[0]; + } + // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions + else if( expr[0] == '+' ) { + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2); + STRING_VECTOR::const_iterator it = A.begin(); + double result = __convert_to_type(*it++, 0.0); + for(; it != A.end(); ++it) + result += __convert_to_type(*it, 0.0); + + return __double2string(result); + } + else if( expr[0] == '-' ) { + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2); + STRING_VECTOR::const_iterator it = A.begin(); + double result = __convert_to_type(*it++, 0.0); + for(; it != A.end(); ++it) + result -= __convert_to_type(*it, 0.0); + + return __double2string(result); + } + else if( expr[0] == '*' ) { + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2); + STRING_VECTOR::const_iterator it = A.begin(); + double result = __convert_to_type(*it++, 0.0); + for(; it != A.end(); ++it) + result *= __convert_to_type(*it, 0.0); + + return __double2string(result); + } + else if( expr[0] == '/' ) { + + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2); + STRING_VECTOR::const_iterator it = A.begin(); + double result = __convert_to_type(*it++, 0.0); + if( result == 0 ) return "0.0"; + for(; it != A.end(); ++it) { + const double Q = __convert_to_type(*it, 0.0); + if( Q == 0.0 ) return "0.0"; + result /= Q; + } + return __double2string(result); + } + + // ${^ ... } power expressions + else if( expr[0] == '^' ) { + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2); + STRING_VECTOR::const_iterator it = A.begin(); + double result = __convert_to_type(*it++, 0.0); + for(; it != A.end(); ++it) + result = pow(result, __convert_to_type(*it, 0.0)); + return __double2string(result); + } + + // ${== } ${<= } ${>= } comparisons (return the number of the first 'match' + else if( expr.length() >= 2 && + ( expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" || + expr.substr(0,2) == "<=" || expr[0] == '>' || expr[0] == '<')) { + // differentiate between two and one sign operators + unsigned op = 0; + enum { EQ, GEQ, LEQ, GT, LT }; + if ( expr.substr(0, 2) == "==" ) op = EQ; + else if ( expr.substr(0, 2) == ">=" ) op = GEQ; + else if ( expr.substr(0, 2) == "<=" ) op = LEQ; + else if ( expr[0] == '>' ) op = GT; + else /* "<" */ op = LT; + + STRING_VECTOR a; + if ( op == GT || op == LT ) a = __DBE_get_expr_list(expr.substr(1), 2); + else a = __DBE_get_expr_list(expr.substr(2), 2); + + std::string x_orig = a[0]; + double x = __convert_to_type(x_orig, 1e37); + unsigned i = 1; + + STRING_VECTOR::const_iterator y_orig = a.begin(); + for(y_orig++; y_orig != a.end(); y_orig++) { + double y = __convert_to_type(*y_orig, 1e37); + + // set the strings as reference if one wasn't a number + if ( x == 1e37 || y == 1e37 ) { + // it's a string comparison + if( (op == EQ && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) || + (op == LEQ && x_orig <= *y_orig) || (op == GT && x_orig > *y_orig) || + (op == LT && x_orig < *y_orig) ) + return __int2string(i); + } + else { + // it's a number comparison + if( (op == EQ && x == y) || (op == GEQ && x >= y) || + (op == LEQ && x <= y) || (op == GT && x > y) || + (op == LT && x < y) ) + return __int2string(i); + } + ++i; + } + + // nothing fulfills the condition => return 0 + return "0"; + } + // ${?? expr expr} select + else if( expr.length() >= 2 && expr.substr(0, 2) == "??" ) { + STRING_VECTOR a = __DBE_get_expr_list(expr.substr(2), 2); + double x = __convert_to_type(a[0], 1e37); + // last element is always the default argument + if( x == 1e37 || x < 0 || x >= a.size() - 1 ) return a[a.size()-1]; + + // round x to closest integer + return a[int(x+0.5)]; + } + // ${? expr expr expr} if then else conditions + else if( expr[0] == '?' ) { + STRING_VECTOR a = __DBE_get_expr_list(expr.substr(1), 2); + if( __convert_to_type(a[0], 0.0) == 1.0 ) return a[1]; + else if( a.size() > 2 ) return a[2]; + } + // ${! expr} maxro expansion + else if( expr[0] == '!' ) { + const GetPot::variable* Var = __DBE_get_variable(expr.substr(1)); + // error + if( Var->name == "" ) return std::string(Var->original); + + const STRING_VECTOR A = __DBE_get_expr_list(Var->original, 2); + return A[0]; + } + // ${@: } - string subscription + else if( expr.length() >= 2 && expr.substr(0,2) == "@:" ) { + const STRING_VECTOR A = __DBE_get_expr_list(expr.substr(2), 2); + double x = __convert_to_type(A[1], 1e37); + + // last element is always the default argument + if( x == 1e37 || x < 0 || x >= A[0].size() - 1) + return "<<1st index out of range>>"; + + if( A.size() > 2 ) { + double y = __convert_to_type(A[2], 1e37); + if ( y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x ) + return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5)); + else if( y == -1 ) + return A[0].substr(int(x+0.5)); + return "<<2nd index out of range>>"; + } + else { + char* tmp = new char[2]; + tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0'; + std::string result(tmp); + delete [] tmp; + return result; + } + } + // ${@ } - vector subscription + else if( expr[0] == '@' ) { + STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2); + const GetPot::variable* Var = __DBE_get_variable(A[0]); + // error + if( Var->name == "" ) { + // make a copy of the string if an error occured + // (since the error variable is a static variable inside get_variable()) + return std::string(Var->original); + } + + double x = __convert_to_type(A[1], 1e37); + + // last element is always the default argument + if (x == 1e37 || x < 0 || x >= Var->value.size() ) + return "<<1st index out of range>>"; + + if ( A.size() > 2) { + double y = __convert_to_type(A[2], 1e37); + int begin = int(x+0.5); + int end = 0; + if ( y != 1e37 && y > 0 && y <= Var->value.size() && y > x) + end = int(y+1.5); + else if( y == -1 ) + end = static_cast(Var->value.size()); + else + return "<<2nd index out of range>>"; + + std::string result = *(Var->get_element(begin)); + int i = begin+1; + for(; i < end; ++i) + result += std::string(" ") + *(Var->get_element(i)); + return result; + } + else + return *(Var->get_element(int(x+0.5))); + } + + const STRING_VECTOR A = __DBE_get_expr_list(expr, 1); + const GetPot::variable* B = __DBE_get_variable(A[0]); + + // make a copy of the string if an error occured + // (since the error variable is a static variable inside get_variable()) + if( B->name == "" ) return std::string(B->original); + // (psuggs@pobox.com mentioned to me the warning MSVC++6.0 produces + // with: else return B->original (thanks)) + return B->original; +} + + +/////////////////////////////////////////////////////////////////////////////// +// (*) unidentified flying objects +//............................................................................. +// +inline bool +GetPot::__search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const +{ + victorate(std::string, VecStr, itk) { + if( *itk == Str ) return true; + } + return false; +} + +inline STRING_VECTOR +GetPot::unidentified_arguments(unsigned Number, + const char* KnownArgument1, ...) const +{ + STRING_VECTOR known_arguments; + + // (1) create a vector of known arguments + if( Number == 0 ) return STRING_VECTOR(); + + va_list ap; + va_start(ap, KnownArgument1); + known_arguments.push_back(std::string(KnownArgument1)); + unsigned i=1; + for(; i it is not necessary to separate requested options from the list + STRING_VECTOR option_list; + victorate(std::string, _requested_arguments, it) { + const std::string arg = *it; + if( arg.length() == 0 ) continue; + if( arg[0] == '-' ) option_list.push_back(arg); + } + return unidentified_options(option_list); +} + +inline STRING_VECTOR +GetPot::unidentified_options(const STRING_VECTOR& Knowns) const +{ + STRING_VECTOR ufos; + STRING_VECTOR::const_iterator it = argv.begin(); + ++it; // forget about argv[0] (application or filename) + for(; it != argv.end(); ++it) { + // -- argument belongs to prefixed section ? + const std::string arg = __get_remaining_string(*it, prefix); + if( arg == "" ) continue; + + // is argument really an option (starting with '-') ? + if( arg.length() < 1 || arg[0] != '-' ) continue; + + if( __search_string_vector(Knowns, arg) == false) + ufos.push_back(*it); + } + + return ufos; +} + +inline std::string +GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const + // Two modes: + // ArgumentNumber >= 0 check specific argument + // ArgumentNumber == -1 check all options starting with one '-' + // for flags +{ + std::string ufos; + STRING_VECTOR known_arguments; + std::string KFL(KnownFlagList); + + // (2) iteration over '-' arguments (options) + if( ArgumentNumber == -1 ) { + STRING_VECTOR::const_iterator it = argv.begin(); + ++it; // forget about argv[0] (application or filename) + for(; it != argv.end(); ++it) { + // -- argument belongs to prefixed section ? + const std::string arg = __get_remaining_string(*it, prefix); + if( arg == "" ) continue; + + // -- does arguments start with '-' (but not '--') + if ( arg.length() < 2 ) continue; + else if( arg[0] != '-' ) continue; + else if( arg[1] == '-' ) continue; + + // -- check out if flags inside option are contained in KnownFlagList + const char* p=arg.c_str(); + p++; // skip starting minus + for(; *p != '\0' ; p++) + if( KFL.find(*p) == std::string::npos ) ufos += *p; + } + } + // (1) check specific argument + else { + // -- only check arguments that start with prefix + int no_matches = 0; + unsigned i=1; + for(; i check it for flags + const char* p = Remain.c_str(); + p++; // skip starting minus + for(; *p != '\0' ; p++) + if( KFL.find(*p) == std::string::npos ) ufos += *p; + return ufos; + } + } + } + } + return ufos; +} + +inline STRING_VECTOR +GetPot::unidentified_variables(unsigned Number, + const char* KnownVariable1, ...) const +{ + STRING_VECTOR known_variables; + + // create vector of known arguments + if( Number == 0 ) return STRING_VECTOR(); + + va_list ap; + va_start(ap, KnownVariable1); + known_variables.push_back(std::string(KnownVariable1)); + unsigned i=1; + for(; i it is not necessary to separate requested nominus from the list + + return unidentified_nominuses(_requested_arguments); +} + +inline STRING_VECTOR +GetPot::unidentified_nominuses(const STRING_VECTOR& Knowns) const +{ + STRING_VECTOR ufos; + + // (2) iterate over all arguments + STRING_VECTOR::const_iterator it = argv.begin(); + ++it; // forget about argv[0] (application or filename) + for(; it != argv.end(); ++it) { + // -- check if nominus part of prefix + const std::string arg = __get_remaining_string(*it, prefix); + if( arg == "" ) continue; + + if( arg.length() < 1 ) continue; + // option ? --> not a nomius + if( arg[0] == '-' ) continue; + // section ? --> not a real nominus + if( arg[0] == '[' && arg[arg.length()-1] == ']' ) continue; + // variable definition ? --> not a real nominus + bool continue_f = false; + unsigned i=0; + for(; i= value.size() ) return 0; else return &(value[Idx]); } + +inline void +GetPot::variable::take(const char* Value, const char* FieldSeparator) +{ + original = std::string(Value); + + // separate string by white space delimiters using 'strtok' + // thread safe usage of strtok (no static members) + char* spt = 0; + // make a copy of the 'Value' + char* copy = new char[strlen(Value)+1]; + strcpy(copy, Value); + char* follow_token = strtok_r(copy, FieldSeparator, &spt); + if( value.size() != 0 ) value.erase(value.begin(), value.end()); + while(follow_token != 0) { + value.push_back(std::string(follow_token)); + follow_token = strtok_r(NULL, FieldSeparator, &spt); + } + + delete [] copy; +} + +inline +GetPot::variable::~variable() +{} + +inline GetPot::variable& +GetPot::variable::operator=(const GetPot::variable& That) +{ + if( &That != this) { + name = That.name; + value = That.value; + original = That.original; + } + return *this; +} + +#undef victorate + + +#endif // __include_guard_GETPOT_H__ + + + -- cgit v1.2.3