CommandLineArguments.cxx 24 KB

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