1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #include <cstdarg>
19 #include <cstddef>
20 #include <sstream>
21 #include <stdexcept>
22 
23 #include "string_utils.h"
24 
25 namespace phosphor {
26     namespace utils {
27 
format_string(const char* fmt...)28         std::string format_string(const char* fmt...) {
29             std::vector<char> buffer;
30 
31             va_list args, cpy;
32             va_start(args, fmt);
33             va_copy(cpy, args);
34 
35             int len = vsnprintf(nullptr, 0, fmt, cpy) + 1;
36             if (len < 0) {
37                 throw std::runtime_error(
38                     "phosphor::utils::format_string "
39                     "failed: vsnprintf returned < 0");
40             }
41             buffer.resize(len);
42             len = vsnprintf(buffer.data(), buffer.size(), fmt, args);
43             if (len < 0 || unsigned(len) > buffer.size()) {
44                 throw std::runtime_error(
45                     "phosphor::utils::format_string "
46                     "failed: vsnprintf returned < 0 or "
47                     "larger than the buffer.");
48             }
49 
50             va_end(args);
51             va_end(cpy);
52             return buffer.data();
53         }
54 
escape_json(const std::string& input)55         std::string escape_json(const std::string& input) {
56             std::string output;
57             output.reserve(input.length());
58 
59             for (std::string::size_type i = 0; i < input.length(); ++i) {
60                 switch (input[i]) {
61                 case '"':
62                     output += "\\\"";
63                     break;
64                 case '/':
65                     output += "\\/";
66                     break;
67                 case '\b':
68                     output += "\\b";
69                     break;
70                 case '\f':
71                     output += "\\f";
72                     break;
73                 case '\n':
74                     output += "\\n";
75                     break;
76                 case '\r':
77                     output += "\\r";
78                     break;
79                 case '\t':
80                     output += "\\t";
81                     break;
82                 case '\\':
83                     output += "\\\\";
84                     break;
85                 default:
86                     output += input[i];
87                     break;
88                 }
89             }
90 
91             return output;
92         }
93 
to_json(const std::string& str)94         std::string to_json(const std::string& str) {
95             return "\"" + escape_json(str) + "\"";
96         }
97 
split_string(const std::string& str, const char delim)98         std::vector<std::string> split_string(const std::string& str,
99                                               const char delim) {
100             if (str == "") {
101                 return {""};
102             }
103             std::vector<std::string> elems;
104             std::stringstream ss(str);
105             std::string item;
106             while (std::getline(ss, item, delim)) {
107                 elems.push_back(item);
108             }
109             return elems;
110         }
111 
join_string(const std::vector<std::string>& strs, const char delim)112         std::string join_string(const std::vector<std::string>& strs,
113                                 const char delim) {
114             std::string result;
115             if (strs.size() == 0) {
116                 return result;
117             }
118 
119             for(const auto& str : strs) {
120                 result += str + delim;
121             }
122             result.resize(result.size() - 1); // Remove last delimiter
123             return result;
124         }
125 
string_replace(std::string& str, const std::string& from, const std::string& to)126         std::string& string_replace(std::string& str,
127                                     const std::string& from,
128                                     const std::string& to) {
129             if (from == "") {
130                 return str;
131             }
132             size_t start_pos = str.find(from);
133             if (start_pos != std::string::npos) {
134                 str.replace(start_pos, from.length(), to);
135             }
136 
137             return str;
138         }
139 
glob_match(const std::string& glob, const std::string& match)140         bool glob_match(const std::string& glob, const std::string& match) {
141             auto iter = match.begin();
142             bool star = false;
143 
144             for (const auto& c : glob) {
145                 if (star) {
146                     while (iter != match.end() && c != *iter) {
147                         ++iter;
148                     }
149                     if (iter == match.end())
150                         return false;
151                 }
152 
153                 switch (c) {
154                 case '?':
155                     if (iter == match.end())
156                         return false;
157                     ++iter;
158                     break;
159                 case '*':
160                     star = true;
161                     break;
162                 case '+':
163                     if (iter == match.end())
164                         return false;
165                     ++iter;
166                     star = true;
167                     break;
168                 default:
169                     if (iter == match.end())
170                         return false;
171                     if (c != *iter)
172                         return false;
173                     ++iter;
174                 }
175             }
176 
177             return iter == match.end() || star;
178         }
179 
strnlen_s(const char *s, size_t maxsize)180         size_t strnlen_s(const char *s, size_t maxsize) {
181             if (s == NULL) {
182                 return 0;
183             }
184 
185             size_t count = 0;
186 
187             while (*s++ && maxsize--) {
188                 count++;
189             }
190 
191             return count;
192         }
193     }
194 }
195