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