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 : : #include <numeric>
16 : :
17 : : #include <string.h>
18 : : #include <util/strutil.h>
19 : :
20 : : using namespace std;
21 : :
22 : : namespace isc {
23 : : namespace util {
24 : : namespace str {
25 : :
26 : : // Normalize slashes
27 : :
28 : : void
29 : 3 : normalizeSlash(std::string& name) {
30 [ + + ]: 3 : if (!name.empty()) {
31 : : size_t pos = 0;
32 [ + + ]: 6 : while ((pos = name.find('\\', pos)) != std::string::npos) {
33 : 4 : name[pos] = '/';
34 : : }
35 : : }
36 : 3 : }
37 : :
38 : : // Trim String
39 : :
40 : : string
41 : 711 : trim(const string& instring) {
42 : : static const char* blanks = " \t\n";
43 : :
44 : 711 : string retstring = "";
45 [ + + ]: 711 : if (!instring.empty()) {
46 : :
47 : : // Search for first non-blank character in the string
48 [ + - ]: 700 : size_t first = instring.find_first_not_of(blanks);
49 [ + + ]: 700 : if (first != string::npos) {
50 : :
51 : : // String not all blanks, so look for last character
52 [ + - ]: 697 : size_t last = instring.find_last_not_of(blanks);
53 : :
54 : : // Extract the trimmed substring
55 [ + - ]: 1394 : retstring = instring.substr(first, (last - first + 1));
56 : : }
57 : : }
58 : :
59 : 711 : return (retstring);
60 : : }
61 : :
62 : : // Tokenise string. As noted in the header, this is locally written to avoid
63 : : // another dependency on a Boost library.
64 : :
65 : : vector<string>
66 : 124 : tokens(const std::string& text, const std::string& delim) {
67 : : vector<string> result;
68 : :
69 : : // Search for the first non-delimiter character
70 [ + - ]: 124 : size_t start = text.find_first_not_of(delim);
71 [ + + ]: 316 : while (start != string::npos) {
72 : :
73 : : // Non-delimiter found, look for next delimiter
74 [ + - ]: 192 : size_t end = text.find_first_of(delim, start);
75 [ + + ]: 192 : if (end != string::npos) {
76 : :
77 : : // Delimiter found, so extract string & search for start of next
78 : : // non-delimiter segment.
79 [ + - ][ + - ]: 76 : result.push_back(text.substr(start, (end - start)));
80 [ + - ]: 76 : start = text.find_first_not_of(delim, end);
81 : :
82 : : } else {
83 : :
84 : : // End of string found, extract rest of string and flag to exit
85 [ + - ][ + - ]: 116 : result.push_back(text.substr(start));
86 : 192 : start = string::npos;
87 : : }
88 : : }
89 : :
90 : 124 : return (result);
91 : : }
92 : :
93 : : // Local function to pass to accumulate() for summing up string lengths.
94 : :
95 : : namespace {
96 : :
97 : : size_t
98 : 0 : lengthSum(string::size_type curlen, const string& cur_string) {
99 : 0 : return (curlen + cur_string.size());
100 : : }
101 : :
102 : : }
103 : :
104 : : // Provide printf-style formatting.
105 : :
106 : : std::string
107 : 9 : format(const std::string& format, const std::vector<std::string>& args) {
108 : :
109 [ + + ][ + - ]: 9 : static const string flag = "%s";
[ + - ]
110 : :
111 : : // Initialize return string. To speed things up, we'll reserve an
112 : : // appropriate amount of space - current string size, plus length of all
113 : : // the argument strings, less two characters for each argument (the %s in
114 : : // the format string is being replaced).
115 : 0 : string result;
116 : : size_t length = accumulate(args.begin(), args.end(), format.size(),
117 : 18 : lengthSum) - (args.size() * flag.size());
118 [ + - ]: 9 : result.reserve(length);
119 : :
120 : : // Iterate through replacing all tokens
121 : : result = format;
122 : : size_t tokenpos = 0; // Position of last token replaced
123 : : std::vector<std::string>::size_type i = 0; // Index into argument array
124 : :
125 [ + + ][ + + ]: 25 : while ((i < args.size()) && (tokenpos != string::npos)) {
[ + + ]
126 [ + - ]: 16 : tokenpos = result.find(flag, tokenpos);
127 [ + + ]: 16 : if (tokenpos != string::npos) {
128 [ + - ]: 16 : result.replace(tokenpos, flag.size(), args[i++]);
129 : : }
130 : : }
131 : :
132 : 9 : return (result);
133 : : }
134 : :
135 : : std::string
136 : 642 : getToken(std::istringstream& iss) {
137 : 3 : string token;
138 [ + - ]: 642 : iss >> token;
139 [ + - ][ + + ]: 642 : if (iss.bad() || iss.fail()) {
[ + + ]
140 [ + - ][ + - ]: 6 : isc_throw(StringTokenError, "could not read token from string");
141 : : }
142 : 639 : return (token);
143 : : }
144 : :
145 : :
146 : : } // namespace str
147 : : } // namespace util
148 : 9 : } // namespace isc
|