command_options_helper.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef __COMMAND_OPTIONS_HELPER_H
  15. #define __COMMAND_OPTIONS_HELPER_H
  16. #include <string>
  17. #include <vector>
  18. #include <exceptions/exceptions.h>
  19. #include "../command_options.h"
  20. namespace isc {
  21. namespace perfdhcp {
  22. /// \brief Command Options Helper class.
  23. ///
  24. /// This helper class can be shared between unit tests that
  25. /// need to initialize CommandOptions objects and feed it with
  26. /// specific command line. The command line can be given as a
  27. /// string representing program name, options and arguments.
  28. /// The static method exposed by this class can be used to
  29. /// tokenize this string into array of C-strings that are later
  30. /// consumed by \ref CommandOptions::parse. The state of the
  31. /// CommandOptions object is reset every time the process
  32. /// function is invoked. Also, when command line parsing is
  33. /// ended the array of C-string is freed from the memory.
  34. class CommandOptionsHelper {
  35. public:
  36. /// \brief Wrapper class for allocated argv[] array.
  37. ///
  38. /// This class wraps allocated char** array and ensures that memory
  39. /// allocated for this array is freed at the end o the scope.
  40. class ArgvPtr {
  41. public:
  42. /// \brief Constructor.
  43. ///
  44. /// \param argv array of C-strings.
  45. /// \param number of C-strings in the array.
  46. ArgvPtr(char** argv, int argc) : argv_(argv), argc_(argc) { }
  47. /// \brief Destructor.
  48. ///
  49. /// Dealocates wrapped array of C-strings.
  50. ~ArgvPtr() {
  51. if (argv_ != NULL) {
  52. for(int i = 0; i < argc_; ++i) {
  53. delete[] (argv_[i]);
  54. argv_[i] = NULL;
  55. }
  56. delete[] (argv_);
  57. }
  58. }
  59. /// \brief Return the array of C-strings.
  60. ///
  61. /// \return array of C-strings.
  62. char** getArgv() const { return (argv_); }
  63. /// \brief Return C-strings counter.
  64. ///
  65. /// \return C-strings counter.
  66. int getArgc() const { return(argc_); }
  67. public:
  68. char** argv_; ///< array of C-strings being wrapped.
  69. int argc_; ///< number of C-strings.
  70. };
  71. /// \brief Parse command line provided as string.
  72. ///
  73. /// Method transforms the string representing command line
  74. /// to the array of C-strings consumed by the
  75. /// \ref CommandOptions::parse function and performs
  76. /// parsing.
  77. ///
  78. /// \param cmdline command line provided as single string.
  79. static void process(const std::string& cmdline) {
  80. CommandOptions& opt = CommandOptions::instance();
  81. int argc = 0;
  82. char** argv = tokenizeString(cmdline, argc);
  83. ArgvPtr args(argv, argc);
  84. opt.reset();
  85. opt.parse(args.getArgc(), args.getArgv());
  86. }
  87. private:
  88. /// \brief Split string to the array of C-strings.
  89. ///
  90. /// \param text_to_split string to be splited.
  91. /// \param [out] num number of substrings returned.
  92. /// \return array of C-strings created from split.
  93. static char** tokenizeString(const std::string& text_to_split, int& num) {
  94. char** results = NULL;
  95. // Tokenization with std streams
  96. std::stringstream text_stream(text_to_split);
  97. // Iterators to be used for tokenization
  98. std::istream_iterator<std::string> text_iterator(text_stream);
  99. std::istream_iterator<std::string> text_end;
  100. // Tokenize string (space is a separator) using begin and end iteratos
  101. std::vector<std::string> tokens(text_iterator, text_end);
  102. if (tokens.size() > 0) {
  103. // Allocate array of C-strings where we will store tokens
  104. results = new (std::nothrow) char*[tokens.size()];
  105. assert(results != NULL);
  106. // Store tokens in C-strings array
  107. for (int i = 0; i < tokens.size(); ++i) {
  108. size_t cs_size = tokens[i].length() + 1;
  109. char* cs = new (std::nothrow) char[cs_size];
  110. assert (cs != NULL);
  111. strncpy(cs, tokens[i].c_str(), cs_size);
  112. assert(cs[cs_size - 1] == '\0');
  113. results[i] = cs;
  114. }
  115. // Return number of tokens to calling function
  116. num = tokens.size();
  117. }
  118. return results;
  119. }
  120. };
  121. } // namespace isc::perfdhcp
  122. } // namespace isc
  123. #endif // __COMMAND_OPTIONS_HELPER_H