strutil.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright (C) 2011 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 __STRUTIL_H
  15. #define __STRUTIL_H
  16. #include <algorithm>
  17. #include <cctype>
  18. #include <string>
  19. #include <sstream>
  20. #include <vector>
  21. #include <exceptions/exceptions.h>
  22. #include <boost/lexical_cast.hpp>
  23. namespace isc {
  24. namespace util {
  25. namespace str {
  26. /// \brief A Set of C++ Utilities for Manipulating Strings
  27. ///
  28. /// \brief A standard string util exception that is thrown if getToken or
  29. /// numToToken are called with bad input data
  30. ///
  31. class StringTokenError : public Exception {
  32. public:
  33. StringTokenError(const char* file, size_t line, const char* what) :
  34. isc::Exception(file, line, what) {}
  35. };
  36. /// \brief Normalize Backslash
  37. ///
  38. /// Only relevant to Windows, this replaces all "\" in a string with "/" and
  39. /// returns the result. On other systems it is a no-op. Note that Windows does
  40. /// recognise file names with the "\" replaced by "/" (at least in system calls,
  41. /// if not the command line).
  42. ///
  43. /// \param name Name to be substituted
  44. void normalizeSlash(std::string& name);
  45. /// \brief Trim Leading and Trailing Spaces
  46. ///
  47. /// Returns a copy of the input string but with any leading or trailing spaces
  48. /// or tabs removed.
  49. ///
  50. /// \param instring Input string to modify
  51. ///
  52. /// \return String with leading and trailing spaces removed
  53. std::string trim(const std::string& instring);
  54. /// \brief Split String into Tokens
  55. ///
  56. /// Splits a string into tokens (the tokens being delimited by one or more of
  57. /// the delimiter characters) and returns the tokens in a vector array. Note
  58. /// that adjacent delimiters are considered to be a single delimiter.
  59. ///
  60. /// Special cases are:
  61. /// -# The empty string is considered to be zero tokens.
  62. /// -# A string comprising nothing but delimiters is considered to be zero
  63. /// tokens.
  64. ///
  65. /// The reasoning behind this is that the string can be thought of as having
  66. /// invisible leading and trailing delimiter characters. Therefore both cases
  67. /// reduce to a set of contiguous delimiters, which are considered a single
  68. /// delimiter (so getting rid of the string).
  69. ///
  70. /// We could use Boost for this, but this (simple) function eliminates one
  71. /// dependency in the code.
  72. ///
  73. /// \param text String to be split. Passed by value as the internal copy is
  74. /// altered during the processing.
  75. /// \param delim Delimiter characters
  76. ///
  77. /// \return Vector of tokens.
  78. std::vector<std::string> tokens(const std::string& text,
  79. const std::string& delim = std::string(" \t\n"));
  80. /// \brief Uppercase Character
  81. ///
  82. /// Used in uppercase() to pass as an argument to std::transform(). The
  83. /// function std::toupper() can't be used as it takes an "int" as its argument;
  84. /// this confuses the template expansion mechanism because dereferencing a
  85. /// string::iterator returns a char.
  86. ///
  87. /// \param chr Character to be upper-cased.
  88. ///
  89. /// \return Uppercase version of the argument
  90. inline char toUpper(char chr) {
  91. return (static_cast<char>(std::toupper(static_cast<int>(chr))));
  92. }
  93. /// \brief Uppercase String
  94. ///
  95. /// A convenience function to uppercase a string.
  96. ///
  97. /// \param text String to be upper-cased.
  98. inline void uppercase(std::string& text) {
  99. std::transform(text.begin(), text.end(), text.begin(),
  100. isc::util::str::toUpper);
  101. }
  102. /// \brief Lowercase Character
  103. ///
  104. /// Used in lowercase() to pass as an argument to std::transform(). The
  105. /// function std::tolower() can't be used as it takes an "int" as its argument;
  106. /// this confuses the template expansion mechanism because dereferencing a
  107. /// string::iterator returns a char.
  108. ///
  109. /// \param chr Character to be lower-cased.
  110. ///
  111. /// \return Lowercase version of the argument
  112. inline char toLower(char chr) {
  113. return (static_cast<char>(std::tolower(static_cast<int>(chr))));
  114. }
  115. /// \brief Lowercase String
  116. ///
  117. /// A convenience function to lowercase a string
  118. ///
  119. /// \param text String to be lower-cased.
  120. inline void lowercase(std::string& text) {
  121. std::transform(text.begin(), text.end(), text.begin(),
  122. isc::util::str::toLower);
  123. }
  124. /// \brief Apply Formatting
  125. ///
  126. /// Given a printf-style format string containing only "%s" place holders
  127. /// (others are ignored) and a vector of strings, this produces a single string
  128. /// with the placeholders replaced.
  129. ///
  130. /// \param format Format string
  131. /// \param args Vector of argument strings
  132. ///
  133. /// \return Resultant string
  134. std::string format(const std::string& format,
  135. const std::vector<std::string>& args);
  136. /// \brief Returns one token from the given stringstream
  137. ///
  138. /// Using the >> operator, with basic error checking
  139. ///
  140. /// \exception StringTokenError if the token cannot be read from the stream
  141. ///
  142. /// \param iss stringstream to read one token from
  143. ///
  144. /// \return the first token read from the stringstream
  145. std::string getToken(std::istringstream& iss);
  146. /// \brief Converts a string token to an *unsigned* integer.
  147. ///
  148. /// The value is converted using a lexical cast, with error and bounds
  149. /// checking.
  150. ///
  151. /// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
  152. /// wide to store resulting integers.
  153. ///
  154. /// BitSize is the maximum number of bits that the resulting integer can take.
  155. /// This function first checks whether the given token can be converted to
  156. /// an integer of NumType type. It then confirms the conversion result is
  157. /// within the valid range, i.e., [0, 2^BitSize - 1]. The second check is
  158. /// necessary because lexical_cast<T> where T is an unsigned integer type
  159. /// doesn't correctly reject negative numbers when compiled with SunStudio.
  160. ///
  161. /// \exception StringTokenError if the value is out of range, or if it
  162. /// could not be converted
  163. ///
  164. /// \param num_token the string token to convert
  165. ///
  166. /// \return the converted value, of type NumType
  167. template <typename NumType, int BitSize>
  168. NumType
  169. tokenToNum(const std::string& num_token) {
  170. NumType num;
  171. try {
  172. num = boost::lexical_cast<NumType>(num_token);
  173. } catch (const boost::bad_lexical_cast&) {
  174. isc_throw(StringTokenError, "Invalid SRV numeric parameter: " <<
  175. num_token);
  176. }
  177. if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
  178. isc_throw(StringTokenError, "Numeric SRV parameter out of range: " <<
  179. num);
  180. }
  181. return (num);
  182. }
  183. } // namespace str
  184. } // namespace util
  185. } // namespace isc
  186. #endif // __STRUTIL_H