CPUnit 0.95 (beta)
The REAL C++ port of JUnit.
|
00001 /* 00002 Copyright (c) 2011 Daniel Bakkelund. 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions 00007 are met: 00008 1. Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 2. Redistributions in binary form must reproduce the above copyright 00011 notice, this list of conditions and the following disclaimer in the 00012 documentation and/or other materials provided with the distribution. 00013 3. Neither the name of the copyright holders nor the names of its 00014 contributors may be used to endorse or promote products derived from 00015 this software without specific prior written permission. 00016 00017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 00027 THE POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 #include "cpunit_CmdLineParser.hpp" 00031 #include "cpunit_IllegalArgumentException.hpp" 00032 #include <sstream> 00033 #include "cpunit_trace.hpp" 00034 00035 const std::string 00036 cpunit::CmdLineParser::BLANKS(" \t\n"); 00037 00038 cpunit::CmdLineParser::CmdLineParser() : 00039 legal_args(), 00040 args(), 00041 input() 00042 {} 00043 00044 cpunit::CmdLineParser::CmdLineParser(const CmdLineParser &p) : 00045 legal_args(p.legal_args), 00046 args(p.args), 00047 input(p.input) 00048 {} 00049 00050 cpunit::CmdLineParser::~CmdLineParser() 00051 {} 00052 00053 cpunit::CmdLineParser& 00054 cpunit::CmdLineParser::operator = (const CmdLineParser &p) { 00055 if (this != &p) { 00056 legal_args = p.legal_args; 00057 args = p.args; 00058 input = p.input; 00059 } 00060 return *this; 00061 } 00062 00063 void 00064 cpunit::CmdLineParser::add_legal(const std::string &argnames) { 00065 std::size_t end = 0; 00066 for (std::size_t pos=0; pos<argnames.length(); pos = argnames.find_first_not_of(BLANKS, end)) { 00067 end = argnames.find_first_of(BLANKS, pos); 00068 const std::string s = argnames.substr(pos, end - pos); 00069 if (s.find_first_of(BLANKS) != std::string::npos) { 00070 std::ostringstream oss; 00071 oss<<"Option names cannot contain blank characters, was '"<<s<<'\''; 00072 throw IllegalArgumentException(oss.str()); 00073 } 00074 if (s.length() < 2 || s[0] != '-' || (s.length() == 2 && s[1] == '-')) { 00075 std::ostringstream oss; 00076 oss<<"Option names cannot be empty and must be prepended by '-' or '--', was '"<<s<<'\''; 00077 throw IllegalArgumentException(oss.str()); 00078 } 00079 if (s[1] != '-' && s.length() > 2) { 00080 std::ostringstream oss; 00081 oss<<"Options prepended by '-' can be single character only. Was '"<<s<<'\''; 00082 throw IllegalArgumentException(oss.str()); 00083 } 00084 legal_args.insert(s); 00085 } 00086 } 00087 00088 void 00089 cpunit::CmdLineParser::parse(const int argc, const char ** cmdline) { 00090 for (int i=0; i<argc; ++i) { 00091 std::string arg(cmdline[i]); 00092 const std::size_t start = arg.find_first_not_of(BLANKS); 00093 arg = arg.substr(start); 00094 if (arg.length() > 0) { 00095 if (arg[0] == '-') { 00096 if (arg.length() == 1) { 00097 throw IllegalArgumentException("Illegal option: '-'"); 00098 } 00099 if (arg[1] != '-') { 00100 parse_short_token(arg); 00101 } else { 00102 parse_long_token(arg); 00103 } 00104 } else { 00105 input.push_back(cmdline[i]); 00106 } 00107 } 00108 } 00109 } 00110 00111 void 00112 cpunit::CmdLineParser::parse_short_token(const std::string &token) { 00113 const std::size_t end = token.find_first_of(" ="); 00114 const std::string name = token.substr(0, end); 00115 std::string arg; 00116 for (std::size_t i=1; i<name.length(); ++i) { 00117 arg = std::string("-") + name[i]; 00118 if (legal_args.find(arg) == legal_args.end()) { 00119 std::ostringstream oss; 00120 oss<<"Unknown option '"<<arg<<'\''; 00121 if (token.length() > 2) { 00122 oss<<" (specified in '"<<token<<"')"; 00123 } 00124 throw IllegalArgumentException(oss.str()); 00125 } 00126 args.insert(std::make_pair(arg, std::string(""))); 00127 CPUNIT_ITRACE("CmdLineParser - Registered '"<<arg<<"' --> '' from '"<<token<<'\''); 00128 } 00129 if (end != std::string::npos) { 00130 const std::size_t start = token.find_first_not_of(" =", end); 00131 if (start != std::string::npos) { 00132 const std::string val = token.substr(start); 00133 args.erase(arg); 00134 args.insert(std::make_pair(arg, val)); 00135 CPUNIT_ITRACE("CmdLineParser - Re-registered '"<<arg<<"' --> '"<<val<<"' from '"<<token<<'\''); 00136 } 00137 } 00138 } 00139 00140 void 00141 cpunit::CmdLineParser::parse_long_token(const std::string &token) { 00142 const std::size_t end = token.find_first_of("= ", 0); 00143 const std::size_t arg_start = token.find_first_not_of("= ", end); 00144 const std::string name = token.substr(0, end); 00145 00146 if (legal_args.find(name) == legal_args.end()) { 00147 CPUNIT_ERRTRACE("CmdLineParser - Unknown option '"<<name<<"' extracted from '"<<token<<'\''); 00148 std::ostringstream oss; 00149 oss<<"Unknown option: '"<<token<<'\''; 00150 throw IllegalArgumentException(oss.str()); 00151 } 00152 std::string value = ""; 00153 if (arg_start != std::string::npos) { 00154 value = token.substr(arg_start); 00155 } 00156 args.erase(name); 00157 args.insert(std::make_pair(name, value)); 00158 CPUNIT_ITRACE("CmdLineParser - Registered '"<<name<<"' --> '"<<value<<"' from '"<<token<<'\''); 00159 } 00160 00161 bool 00162 cpunit::CmdLineParser::has(const std::string &arg) const { 00163 CPUNIT_DTRACE("CmdLineParser - CmdLineParser::has("<<arg<<')'); 00164 if (legal_args.find(arg) == legal_args.end()) { 00165 std::ostringstream oss; 00166 oss<<"Invalid argument passed to has: '"<<arg<<'\''; 00167 throw IllegalArgumentException(oss.str()); 00168 } 00169 return args.find(arg) != args.end(); 00170 } 00171 00172 bool 00173 cpunit::CmdLineParser::has_one_of(const std::string &s) const { 00174 bool result = false; 00175 for (std::size_t pos=s.find_first_not_of(BLANKS, 0); pos<s.length(); pos = s.find_first_not_of(BLANKS, pos)) { 00176 const std::size_t end = s.find_first_of(BLANKS, pos); 00177 const std::string arg = s.substr(pos, end - pos); 00178 if (has(arg)) { 00179 result = true; 00180 } 00181 pos = end; 00182 } 00183 return result; 00184 } 00185 00186 template<> 00187 std::string 00188 cpunit::CmdLineParser::value_of<std::string>(const std::string &arg) const { 00189 if (!has(arg)) { 00190 std::ostringstream oss; 00191 oss<<"Unknown argument: '"<<arg<<'\''; 00192 throw IllegalArgumentException(oss.str()); 00193 } 00194 return args.find(arg)->second; 00195 } 00196 00197 const std::vector<std::string>& 00198 cpunit::CmdLineParser::program_input() const { 00199 return input; 00200 } 00201 00202 std::string 00203 cpunit::CmdLineParser::to_string() const { 00204 std::ostringstream oss; 00205 std::set<std::string>::const_iterator lit = legal_args.begin(); 00206 oss<<"Legal arguments:"<<std::endl; 00207 while (lit != legal_args.end()) { 00208 oss<<'\''<<*lit<<'\''<<std::endl; 00209 ++lit; 00210 } 00211 00212 std::map<std::string,std::string>::const_iterator ait = args.begin(); 00213 oss<<"Arguments:"<<std::endl; 00214 while (ait != args.end()) { 00215 oss<<'\''<<ait->first<<'\''<<" --> "<<'\''<<ait->second<<'\''<<std::endl; 00216 ++ait; 00217 } 00218 return oss.str(); 00219 }