CommandLineArguments.cxx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
  3. #include "kwsysPrivate.h"
  4. #include KWSYS_HEADER(CommandLineArguments.hxx)
  5. #include KWSYS_HEADER(Configure.hxx)
  6. // Work-around CMake dependency scanning limitation. This must
  7. // duplicate the above list of headers.
  8. #if 0
  9. # include "CommandLineArguments.hxx.in"
  10. # include "Configure.hxx.in"
  11. #endif
  12. #include <iostream>
  13. #include <map>
  14. #include <set>
  15. #include <sstream>
  16. #include <string>
  17. #include <vector>
  18. #include <cstdio>
  19. #include <cstdlib>
  20. #include <cstring>
  21. #ifdef _MSC_VER
  22. # pragma warning(disable : 4786)
  23. #endif
  24. #if defined(__sgi) && !defined(__GNUC__)
  25. # pragma set woff 1375 /* base class destructor not virtual */
  26. #endif
  27. #if 0
  28. # define CommandLineArguments_DEBUG(x) \
  29. std::cout << __LINE__ << " CLA: " << x << std::endl
  30. #else
  31. # define CommandLineArguments_DEBUG(x)
  32. #endif
  33. namespace KWSYS_NAMESPACE {
  34. struct CommandLineArgumentsCallbackStructure
  35. {
  36. char const* Argument;
  37. int ArgumentType;
  38. CommandLineArguments::CallbackType Callback;
  39. void* CallData;
  40. void* Variable;
  41. int VariableType;
  42. char const* Help;
  43. };
  44. class CommandLineArgumentsVectorOfStrings : public std::vector<std::string>
  45. {
  46. };
  47. class CommandLineArgumentsSetOfStrings : public std::set<std::string>
  48. {
  49. };
  50. class CommandLineArgumentsMapOfStrucs
  51. : public std::map<std::string, CommandLineArgumentsCallbackStructure>
  52. {
  53. };
  54. class CommandLineArgumentsInternal
  55. {
  56. public:
  57. CommandLineArgumentsInternal() = default;
  58. using VectorOfStrings = CommandLineArgumentsVectorOfStrings;
  59. using CallbacksMap = CommandLineArgumentsMapOfStrucs;
  60. using String = std::string;
  61. using SetOfStrings = CommandLineArgumentsSetOfStrings;
  62. VectorOfStrings Argv;
  63. String Argv0;
  64. CallbacksMap Callbacks;
  65. CommandLineArguments::ErrorCallbackType UnknownArgumentCallback{ nullptr };
  66. void* ClientData{ nullptr };
  67. VectorOfStrings::size_type LastArgument{ 0 };
  68. VectorOfStrings UnusedArguments;
  69. };
  70. CommandLineArguments::CommandLineArguments()
  71. {
  72. this->Internals = new CommandLineArguments::Internal;
  73. this->Help = "";
  74. this->LineLength = 80;
  75. this->StoreUnusedArgumentsFlag = false;
  76. }
  77. CommandLineArguments::~CommandLineArguments()
  78. {
  79. delete this->Internals;
  80. }
  81. void CommandLineArguments::Initialize(int argc, char const* const argv[])
  82. {
  83. int cc;
  84. this->Initialize();
  85. this->Internals->Argv0 = argv[0];
  86. for (cc = 1; cc < argc; cc++) {
  87. this->ProcessArgument(argv[cc]);
  88. }
  89. }
  90. void CommandLineArguments::Initialize(int argc, char* argv[])
  91. {
  92. this->Initialize(argc, static_cast<char const* const*>(argv));
  93. }
  94. void CommandLineArguments::Initialize()
  95. {
  96. this->Internals->Argv.clear();
  97. this->Internals->LastArgument = 0;
  98. }
  99. void CommandLineArguments::ProcessArgument(char const* arg)
  100. {
  101. this->Internals->Argv.push_back(arg);
  102. }
  103. bool CommandLineArguments::GetMatchedArguments(
  104. std::vector<std::string>* matches, std::string const& arg)
  105. {
  106. matches->clear();
  107. CommandLineArguments::Internal::CallbacksMap::iterator it;
  108. // Does the argument match to any we know about?
  109. for (it = this->Internals->Callbacks.begin();
  110. it != this->Internals->Callbacks.end(); ++it) {
  111. CommandLineArguments::Internal::String const& parg = it->first;
  112. CommandLineArgumentsCallbackStructure* cs = &it->second;
  113. if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT ||
  114. cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT) {
  115. if (arg == parg) {
  116. matches->push_back(parg);
  117. }
  118. } else if (arg.find(parg) == 0) {
  119. matches->push_back(parg);
  120. }
  121. }
  122. return !matches->empty();
  123. }
  124. int CommandLineArguments::Parse()
  125. {
  126. std::vector<std::string>::size_type cc;
  127. std::vector<std::string> matches;
  128. if (this->StoreUnusedArgumentsFlag) {
  129. this->Internals->UnusedArguments.clear();
  130. }
  131. for (cc = 0; cc < this->Internals->Argv.size(); cc++) {
  132. std::string const& arg = this->Internals->Argv[cc];
  133. CommandLineArguments_DEBUG("Process argument: " << arg);
  134. this->Internals->LastArgument = cc;
  135. if (this->GetMatchedArguments(&matches, arg)) {
  136. // Ok, we found one or more arguments that match what user specified.
  137. // Let's find the longest one.
  138. CommandLineArguments::Internal::VectorOfStrings::size_type kk;
  139. CommandLineArguments::Internal::VectorOfStrings::size_type maxidx = 0;
  140. CommandLineArguments::Internal::String::size_type maxlen = 0;
  141. for (kk = 0; kk < matches.size(); kk++) {
  142. if (matches[kk].size() > maxlen) {
  143. maxlen = matches[kk].size();
  144. maxidx = kk;
  145. }
  146. }
  147. // So, the longest one is probably the right one. Now see if it has any
  148. // additional value
  149. CommandLineArgumentsCallbackStructure* cs =
  150. &this->Internals->Callbacks[matches[maxidx]];
  151. std::string const& sarg = matches[maxidx];
  152. if (cs->Argument != sarg) {
  153. abort();
  154. }
  155. switch (cs->ArgumentType) {
  156. case NO_ARGUMENT:
  157. // No value
  158. if (!this->PopulateVariable(cs, nullptr)) {
  159. return 0;
  160. }
  161. break;
  162. case SPACE_ARGUMENT:
  163. if (cc == this->Internals->Argv.size() - 1) {
  164. this->Internals->LastArgument--;
  165. return 0;
  166. }
  167. CommandLineArguments_DEBUG("This is a space argument: "
  168. << arg << " value: "
  169. << this->Internals->Argv[cc + 1]);
  170. // Value is the next argument
  171. if (!this->PopulateVariable(cs,
  172. this->Internals->Argv[cc + 1].c_str())) {
  173. return 0;
  174. }
  175. cc++;
  176. break;
  177. case EQUAL_ARGUMENT:
  178. if (arg.size() == sarg.size() || arg.at(sarg.size()) != '=') {
  179. this->Internals->LastArgument--;
  180. return 0;
  181. }
  182. // Value is everythng followed the '=' sign
  183. if (!this->PopulateVariable(cs, arg.c_str() + sarg.size() + 1)) {
  184. return 0;
  185. }
  186. break;
  187. case CONCAT_ARGUMENT:
  188. // Value is whatever follows the argument
  189. if (!this->PopulateVariable(cs, arg.c_str() + sarg.size())) {
  190. return 0;
  191. }
  192. break;
  193. case MULTI_ARGUMENT:
  194. // Suck in all the rest of the arguments
  195. CommandLineArguments_DEBUG("This is a multi argument: " << arg);
  196. for (cc++; cc < this->Internals->Argv.size(); ++cc) {
  197. std::string const& marg = this->Internals->Argv[cc];
  198. CommandLineArguments_DEBUG(
  199. " check multi argument value: " << marg);
  200. if (this->GetMatchedArguments(&matches, marg)) {
  201. CommandLineArguments_DEBUG("End of multi argument "
  202. << arg << " with value: " << marg);
  203. break;
  204. }
  205. CommandLineArguments_DEBUG(
  206. " populate multi argument value: " << marg);
  207. if (!this->PopulateVariable(cs, marg.c_str())) {
  208. return 0;
  209. }
  210. }
  211. if (cc != this->Internals->Argv.size()) {
  212. CommandLineArguments_DEBUG("Again End of multi argument " << arg);
  213. cc--;
  214. continue;
  215. }
  216. break;
  217. default:
  218. std::cerr << "Got unknown argument type: \"" << cs->ArgumentType
  219. << "\"" << std::endl;
  220. this->Internals->LastArgument--;
  221. return 0;
  222. }
  223. } else {
  224. // Handle unknown arguments
  225. if (this->Internals->UnknownArgumentCallback) {
  226. if (!this->Internals->UnknownArgumentCallback(
  227. arg.c_str(), this->Internals->ClientData)) {
  228. this->Internals->LastArgument--;
  229. return 0;
  230. }
  231. return 1;
  232. } else if (this->StoreUnusedArgumentsFlag) {
  233. CommandLineArguments_DEBUG("Store unused argument " << arg);
  234. this->Internals->UnusedArguments.push_back(arg);
  235. } else {
  236. std::cerr << "Got unknown argument: \"" << arg << "\"" << std::endl;
  237. this->Internals->LastArgument--;
  238. return 0;
  239. }
  240. }
  241. }
  242. return 1;
  243. }
  244. void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv)
  245. {
  246. CommandLineArguments::Internal::VectorOfStrings::size_type size =
  247. this->Internals->Argv.size() - this->Internals->LastArgument + 1;
  248. CommandLineArguments::Internal::VectorOfStrings::size_type cc;
  249. // Copy Argv0 as the first argument
  250. char** args = new char*[size];
  251. args[0] = new char[this->Internals->Argv0.size() + 1];
  252. strcpy(args[0], this->Internals->Argv0.c_str());
  253. int cnt = 1;
  254. // Copy everything after the LastArgument, since that was not parsed.
  255. for (cc = this->Internals->LastArgument + 1;
  256. cc < this->Internals->Argv.size(); cc++) {
  257. args[cnt] = new char[this->Internals->Argv[cc].size() + 1];
  258. strcpy(args[cnt], this->Internals->Argv[cc].c_str());
  259. cnt++;
  260. }
  261. *argc = cnt;
  262. *argv = args;
  263. }
  264. void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv)
  265. {
  266. CommandLineArguments::Internal::VectorOfStrings::size_type size =
  267. this->Internals->UnusedArguments.size() + 1;
  268. CommandLineArguments::Internal::VectorOfStrings::size_type cc;
  269. // Copy Argv0 as the first argument
  270. char** args = new char*[size];
  271. args[0] = new char[this->Internals->Argv0.size() + 1];
  272. strcpy(args[0], this->Internals->Argv0.c_str());
  273. int cnt = 1;
  274. // Copy everything after the LastArgument, since that was not parsed.
  275. for (cc = 0; cc < this->Internals->UnusedArguments.size(); cc++) {
  276. std::string& str = this->Internals->UnusedArguments[cc];
  277. args[cnt] = new char[str.size() + 1];
  278. strcpy(args[cnt], str.c_str());
  279. cnt++;
  280. }
  281. *argc = cnt;
  282. *argv = args;
  283. }
  284. void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv)
  285. {
  286. int cc;
  287. for (cc = 0; cc < argc; ++cc) {
  288. delete[] (*argv)[cc];
  289. }
  290. delete[] *argv;
  291. }
  292. void CommandLineArguments::AddCallback(char const* argument,
  293. ArgumentTypeEnum type,
  294. CallbackType callback, void* call_data,
  295. char const* help)
  296. {
  297. CommandLineArgumentsCallbackStructure s;
  298. s.Argument = argument;
  299. s.ArgumentType = type;
  300. s.Callback = callback;
  301. s.CallData = call_data;
  302. s.VariableType = CommandLineArguments::NO_VARIABLE_TYPE;
  303. s.Variable = nullptr;
  304. s.Help = help;
  305. this->Internals->Callbacks[argument] = s;
  306. this->GenerateHelp();
  307. }
  308. void CommandLineArguments::AddArgument(char const* argument,
  309. ArgumentTypeEnum type,
  310. VariableTypeEnum vtype, void* variable,
  311. char const* help)
  312. {
  313. CommandLineArgumentsCallbackStructure s;
  314. s.Argument = argument;
  315. s.ArgumentType = type;
  316. s.Callback = nullptr;
  317. s.CallData = nullptr;
  318. s.VariableType = vtype;
  319. s.Variable = variable;
  320. s.Help = help;
  321. this->Internals->Callbacks[argument] = s;
  322. this->GenerateHelp();
  323. }
  324. #define CommandLineArgumentsAddArgumentMacro(type, ctype) \
  325. void CommandLineArguments::AddArgument(const char* argument, \
  326. ArgumentTypeEnum type, \
  327. ctype* variable, const char* help) \
  328. { \
  329. this->AddArgument(argument, type, CommandLineArguments::type##_TYPE, \
  330. variable, help); \
  331. }
  332. /* clang-format off */
  333. CommandLineArgumentsAddArgumentMacro(BOOL, bool)
  334. CommandLineArgumentsAddArgumentMacro(INT, int)
  335. CommandLineArgumentsAddArgumentMacro(DOUBLE, double)
  336. CommandLineArgumentsAddArgumentMacro(STRING, char*)
  337. CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string)
  338. CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector<bool>)
  339. CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector<int>)
  340. CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, std::vector<double>)
  341. CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, std::vector<char*>)
  342. CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING,
  343. std::vector<std::string>)
  344. #ifdef HELP_CLANG_FORMAT
  345. ;
  346. #endif
  347. /* clang-format on */
  348. #define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype) \
  349. void CommandLineArguments::AddBooleanArgument( \
  350. const char* argument, ctype* variable, const char* help) \
  351. { \
  352. this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, \
  353. CommandLineArguments::type##_TYPE, variable, help); \
  354. }
  355. /* clang-format off */
  356. CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool)
  357. CommandLineArgumentsAddBooleanArgumentMacro(INT, int)
  358. CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double)
  359. CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*)
  360. CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, std::string)
  361. #ifdef HELP_CLANG_FORMAT
  362. ;
  363. #endif
  364. /* clang-format on */
  365. void CommandLineArguments::SetClientData(void* client_data)
  366. {
  367. this->Internals->ClientData = client_data;
  368. }
  369. void CommandLineArguments::SetUnknownArgumentCallback(
  370. CommandLineArguments::ErrorCallbackType callback)
  371. {
  372. this->Internals->UnknownArgumentCallback = callback;
  373. }
  374. char const* CommandLineArguments::GetHelp(char const* arg)
  375. {
  376. auto it = this->Internals->Callbacks.find(arg);
  377. if (it == this->Internals->Callbacks.end()) {
  378. return nullptr;
  379. }
  380. // Since several arguments may point to the same argument, find the one this
  381. // one point to if this one is pointing to another argument.
  382. CommandLineArgumentsCallbackStructure* cs = &(it->second);
  383. for (;;) {
  384. auto hit = this->Internals->Callbacks.find(cs->Help);
  385. if (hit == this->Internals->Callbacks.end()) {
  386. break;
  387. }
  388. cs = &(hit->second);
  389. }
  390. return cs->Help;
  391. }
  392. void CommandLineArguments::SetLineLength(unsigned int ll)
  393. {
  394. if (ll < 9 || ll > 1000) {
  395. return;
  396. }
  397. this->LineLength = ll;
  398. this->GenerateHelp();
  399. }
  400. char const* CommandLineArguments::GetArgv0()
  401. {
  402. return this->Internals->Argv0.c_str();
  403. }
  404. unsigned int CommandLineArguments::GetLastArgument()
  405. {
  406. return static_cast<unsigned int>(this->Internals->LastArgument + 1);
  407. }
  408. void CommandLineArguments::GenerateHelp()
  409. {
  410. std::ostringstream str;
  411. // Collapse all arguments into the map of vectors of all arguments that do
  412. // the same thing.
  413. CommandLineArguments::Internal::CallbacksMap::iterator it;
  414. using MapArgs = std::map<CommandLineArguments::Internal::String,
  415. CommandLineArguments::Internal::SetOfStrings>;
  416. MapArgs mp;
  417. MapArgs::iterator mpit, smpit;
  418. for (it = this->Internals->Callbacks.begin();
  419. it != this->Internals->Callbacks.end(); ++it) {
  420. CommandLineArgumentsCallbackStructure* cs = &(it->second);
  421. mpit = mp.find(cs->Help);
  422. if (mpit != mp.end()) {
  423. mpit->second.insert(it->first);
  424. mp[it->first].insert(it->first);
  425. } else {
  426. mp[it->first].insert(it->first);
  427. }
  428. }
  429. for (it = this->Internals->Callbacks.begin();
  430. it != this->Internals->Callbacks.end(); ++it) {
  431. CommandLineArgumentsCallbackStructure* cs = &(it->second);
  432. mpit = mp.find(cs->Help);
  433. if (mpit != mp.end()) {
  434. mpit->second.insert(it->first);
  435. smpit = mp.find(it->first);
  436. CommandLineArguments::Internal::SetOfStrings::iterator sit;
  437. for (sit = smpit->second.begin(); sit != smpit->second.end(); ++sit) {
  438. mpit->second.insert(*sit);
  439. }
  440. mp.erase(smpit);
  441. } else {
  442. mp[it->first].insert(it->first);
  443. }
  444. }
  445. // Find the length of the longest string
  446. CommandLineArguments::Internal::String::size_type maxlen = 0;
  447. for (mpit = mp.begin(); mpit != mp.end(); ++mpit) {
  448. CommandLineArguments::Internal::SetOfStrings::iterator sit;
  449. for (sit = mpit->second.begin(); sit != mpit->second.end(); ++sit) {
  450. CommandLineArguments::Internal::String::size_type clen = sit->size();
  451. switch (this->Internals->Callbacks[*sit].ArgumentType) {
  452. case CommandLineArguments::NO_ARGUMENT:
  453. clen += 0;
  454. break;
  455. case CommandLineArguments::CONCAT_ARGUMENT:
  456. clen += 3;
  457. break;
  458. case CommandLineArguments::SPACE_ARGUMENT:
  459. clen += 4;
  460. break;
  461. case CommandLineArguments::EQUAL_ARGUMENT:
  462. clen += 4;
  463. break;
  464. default:
  465. break;
  466. }
  467. if (clen > maxlen) {
  468. maxlen = clen;
  469. }
  470. }
  471. }
  472. CommandLineArguments::Internal::String::size_type maxstrlen = maxlen;
  473. maxlen += 4; // For the space before and after the option
  474. // Print help for each option
  475. for (mpit = mp.begin(); mpit != mp.end(); ++mpit) {
  476. CommandLineArguments::Internal::SetOfStrings::iterator sit;
  477. for (sit = mpit->second.begin(); sit != mpit->second.end(); ++sit) {
  478. str << std::endl;
  479. std::string argument = *sit;
  480. switch (this->Internals->Callbacks[*sit].ArgumentType) {
  481. case CommandLineArguments::NO_ARGUMENT:
  482. break;
  483. case CommandLineArguments::CONCAT_ARGUMENT:
  484. argument += "opt";
  485. break;
  486. case CommandLineArguments::SPACE_ARGUMENT:
  487. argument += " opt";
  488. break;
  489. case CommandLineArguments::EQUAL_ARGUMENT:
  490. argument += "=opt";
  491. break;
  492. case CommandLineArguments::MULTI_ARGUMENT:
  493. argument += " opt opt ...";
  494. break;
  495. default:
  496. break;
  497. }
  498. str << " " << argument.substr(0, maxstrlen) << " ";
  499. }
  500. char const* ptr = this->Internals->Callbacks[mpit->first].Help;
  501. size_t len = strlen(ptr);
  502. int cnt = 0;
  503. while (len > 0) {
  504. // If argument with help is longer than line length, split it on previous
  505. // space (or tab) and continue on the next line
  506. CommandLineArguments::Internal::String::size_type cc;
  507. for (cc = 0; ptr[cc]; cc++) {
  508. if (*ptr == ' ' || *ptr == '\t') {
  509. ptr++;
  510. len--;
  511. }
  512. }
  513. if (cnt > 0) {
  514. for (cc = 0; cc < maxlen; cc++) {
  515. str << " ";
  516. }
  517. }
  518. CommandLineArguments::Internal::String::size_type skip = len;
  519. if (skip > this->LineLength - maxlen) {
  520. skip = this->LineLength - maxlen;
  521. for (cc = skip - 1; cc > 0; cc--) {
  522. if (ptr[cc] == ' ' || ptr[cc] == '\t') {
  523. break;
  524. }
  525. }
  526. if (cc != 0) {
  527. skip = cc;
  528. }
  529. }
  530. str.write(ptr, static_cast<std::streamsize>(skip));
  531. str << std::endl;
  532. ptr += skip;
  533. len -= skip;
  534. cnt++;
  535. }
  536. }
  537. /*
  538. // This can help debugging help string
  539. str << endl;
  540. unsigned int cc;
  541. for ( cc = 0; cc < this->LineLength; cc ++ )
  542. {
  543. str << cc % 10;
  544. }
  545. str << endl;
  546. */
  547. this->Help = str.str();
  548. }
  549. void CommandLineArguments::PopulateVariable(bool* variable,
  550. std::string const& value)
  551. {
  552. if (value == "1" || value == "ON" || value == "on" || value == "On" ||
  553. value == "TRUE" || value == "true" || value == "True" ||
  554. value == "yes" || value == "Yes" || value == "YES") {
  555. *variable = true;
  556. } else {
  557. *variable = false;
  558. }
  559. }
  560. void CommandLineArguments::PopulateVariable(int* variable,
  561. std::string const& value)
  562. {
  563. char* res = nullptr;
  564. *variable = static_cast<int>(strtol(value.c_str(), &res, 10));
  565. // if ( res && *res )
  566. // {
  567. // Can handle non-int
  568. // }
  569. }
  570. void CommandLineArguments::PopulateVariable(double* variable,
  571. std::string const& value)
  572. {
  573. char* res = nullptr;
  574. *variable = strtod(value.c_str(), &res);
  575. // if ( res && *res )
  576. // {
  577. // Can handle non-double
  578. // }
  579. }
  580. void CommandLineArguments::PopulateVariable(char** variable,
  581. std::string const& value)
  582. {
  583. delete[] *variable;
  584. *variable = new char[value.size() + 1];
  585. strcpy(*variable, value.c_str());
  586. }
  587. void CommandLineArguments::PopulateVariable(std::string* variable,
  588. std::string const& value)
  589. {
  590. *variable = value;
  591. }
  592. void CommandLineArguments::PopulateVariable(std::vector<bool>* variable,
  593. std::string const& value)
  594. {
  595. bool val = false;
  596. if (value == "1" || value == "ON" || value == "on" || value == "On" ||
  597. value == "TRUE" || value == "true" || value == "True" ||
  598. value == "yes" || value == "Yes" || value == "YES") {
  599. val = true;
  600. }
  601. variable->push_back(val);
  602. }
  603. void CommandLineArguments::PopulateVariable(std::vector<int>* variable,
  604. std::string const& value)
  605. {
  606. char* res = nullptr;
  607. variable->push_back(static_cast<int>(strtol(value.c_str(), &res, 10)));
  608. // if ( res && *res )
  609. // {
  610. // Can handle non-int
  611. // }
  612. }
  613. void CommandLineArguments::PopulateVariable(std::vector<double>* variable,
  614. std::string const& value)
  615. {
  616. char* res = nullptr;
  617. variable->push_back(strtod(value.c_str(), &res));
  618. // if ( res && *res )
  619. // {
  620. // Can handle non-int
  621. // }
  622. }
  623. void CommandLineArguments::PopulateVariable(std::vector<char*>* variable,
  624. std::string const& value)
  625. {
  626. char* var = new char[value.size() + 1];
  627. strcpy(var, value.c_str());
  628. variable->push_back(var);
  629. }
  630. void CommandLineArguments::PopulateVariable(std::vector<std::string>* variable,
  631. std::string const& value)
  632. {
  633. variable->push_back(value);
  634. }
  635. bool CommandLineArguments::PopulateVariable(
  636. CommandLineArgumentsCallbackStructure* cs, char const* value)
  637. {
  638. // Call the callback
  639. if (cs->Callback) {
  640. if (!cs->Callback(cs->Argument, value, cs->CallData)) {
  641. this->Internals->LastArgument--;
  642. return false;
  643. }
  644. }
  645. CommandLineArguments_DEBUG("Set argument: " << cs->Argument << " to "
  646. << value);
  647. if (cs->Variable) {
  648. std::string var = "1";
  649. if (value) {
  650. var = value;
  651. }
  652. switch (cs->VariableType) {
  653. case CommandLineArguments::INT_TYPE:
  654. this->PopulateVariable(static_cast<int*>(cs->Variable), var);
  655. break;
  656. case CommandLineArguments::DOUBLE_TYPE:
  657. this->PopulateVariable(static_cast<double*>(cs->Variable), var);
  658. break;
  659. case CommandLineArguments::STRING_TYPE:
  660. this->PopulateVariable(static_cast<char**>(cs->Variable), var);
  661. break;
  662. case CommandLineArguments::STL_STRING_TYPE:
  663. this->PopulateVariable(static_cast<std::string*>(cs->Variable), var);
  664. break;
  665. case CommandLineArguments::BOOL_TYPE:
  666. this->PopulateVariable(static_cast<bool*>(cs->Variable), var);
  667. break;
  668. case CommandLineArguments::VECTOR_BOOL_TYPE:
  669. this->PopulateVariable(static_cast<std::vector<bool>*>(cs->Variable),
  670. var);
  671. break;
  672. case CommandLineArguments::VECTOR_INT_TYPE:
  673. this->PopulateVariable(static_cast<std::vector<int>*>(cs->Variable),
  674. var);
  675. break;
  676. case CommandLineArguments::VECTOR_DOUBLE_TYPE:
  677. this->PopulateVariable(static_cast<std::vector<double>*>(cs->Variable),
  678. var);
  679. break;
  680. case CommandLineArguments::VECTOR_STRING_TYPE:
  681. this->PopulateVariable(static_cast<std::vector<char*>*>(cs->Variable),
  682. var);
  683. break;
  684. case CommandLineArguments::VECTOR_STL_STRING_TYPE:
  685. this->PopulateVariable(
  686. static_cast<std::vector<std::string>*>(cs->Variable), var);
  687. break;
  688. default:
  689. std::cerr << "Got unknown variable type: \"" << cs->VariableType
  690. << "\"" << std::endl;
  691. this->Internals->LastArgument--;
  692. return false;
  693. }
  694. }
  695. return true;
  696. }
  697. } // namespace KWSYS_NAMESPACE