strutil.h 7.2 KB

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