Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
5 : * Author: Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 : */
21 :
22 : #pragma once
23 :
24 : #include <cstdint>
25 : #include <string>
26 : #include <vector>
27 : #include <set>
28 : #include <algorithm>
29 : #include <regex>
30 : #include <iterator>
31 : #include <charconv>
32 :
33 : #ifdef _WIN32
34 : #include <WTypes.h>
35 : #endif
36 :
37 : namespace jami {
38 :
39 : constexpr static const char TRUE_STR[] = "true";
40 : constexpr static const char FALSE_STR[] = "false";
41 :
42 : constexpr static const char*
43 1187 : bool_to_str(bool b) noexcept
44 : {
45 1187 : return b ? TRUE_STR : FALSE_STR;
46 : }
47 :
48 : std::string to_string(double value);
49 :
50 : #ifdef _WIN32
51 : std::wstring to_wstring(const std::string& str, int codePage = CP_UTF8);
52 : std::string to_string(const std::wstring& wstr, int codePage = CP_UTF8);
53 : #endif
54 :
55 : std::string to_hex_string(uint64_t id);
56 : uint64_t from_hex_string(const std::string& str);
57 :
58 : template<typename T>
59 : T
60 1592 : to_int(std::string_view str, T defaultValue)
61 : {
62 : T result;
63 1592 : auto [p, ec] = std::from_chars(str.data(), str.data()+str.size(), result);
64 1592 : if (ec == std::errc())
65 1592 : return result;
66 : else
67 0 : return defaultValue;
68 : }
69 :
70 : template<typename T>
71 : T
72 5102 : to_int(std::string_view str)
73 : {
74 : T result;
75 5102 : auto [p, ec] = std::from_chars(str.data(), str.data()+str.size(), result);
76 5102 : if (ec == std::errc())
77 5102 : return result;
78 0 : if (ec == std::errc::invalid_argument)
79 0 : throw std::invalid_argument("Can't parse integer: invalid_argument");
80 0 : else if (ec == std::errc::result_out_of_range)
81 0 : throw std::out_of_range("Can't parse integer: out of range");
82 0 : throw std::system_error(std::make_error_code(ec));
83 : }
84 :
85 : static inline int
86 1 : stoi(const std::string& str)
87 : {
88 1 : return std::stoi(str);
89 : }
90 :
91 : static inline double
92 69 : stod(const std::string& str)
93 : {
94 69 : return std::stod(str);
95 : }
96 :
97 : template<typename... Args>
98 129542 : std::string concat(Args &&... args){
99 : static_assert((std::is_constructible_v<std::string_view, Args&&> && ...));
100 129542 : std::string s;
101 129541 : s.reserve((std::string_view{ args }.size() + ...));
102 129557 : (s.append(std::forward<Args>(args)), ...);
103 129537 : return s;
104 0 : }
105 :
106 : std::string_view trim(std::string_view s);
107 :
108 : /**
109 : * Split a string_view with an API similar to std::getline.
110 : * @param str The input string stream to iterate on, trimed of line during iteration.
111 : * @param line The output substring.
112 : * @param delim The delimiter.
113 : * @return True if line was set, false if the end of the input was reached.
114 : */
115 : inline bool
116 13567 : getline_full(std::string_view& str, std::string_view& line, char delim = '\n')
117 : {
118 13567 : if (str.empty())
119 3962 : return false;
120 9603 : auto pos = str.find(delim);
121 9602 : line = str.substr(0, pos);
122 9606 : str.remove_prefix(pos < str.size() ? pos + 1 : str.size());
123 9605 : return true;
124 : }
125 :
126 : /**
127 : * Similar to @getline_full but skips empty results.
128 : */
129 : inline bool
130 12544 : getline(std::string_view& str, std::string_view& line, char delim = '\n')
131 : {
132 : do {
133 12544 : if (!getline_full(str, line, delim))
134 3590 : return false;
135 8954 : } while (line.empty());
136 8910 : return true;
137 : }
138 :
139 : inline std::vector<std::string_view>
140 3235 : split_string(std::string_view str, char delim)
141 : {
142 3235 : std::vector<std::string_view> output;
143 3235 : for (auto first = str.data(), second = str.data(), last = first + str.size();
144 9021 : second != last && first != last;
145 5786 : first = second + 1) {
146 5786 : second = std::find(first, last, delim);
147 5786 : if (first != second)
148 5784 : output.emplace_back(first, second - first);
149 : }
150 3235 : return output;
151 0 : }
152 :
153 : inline std::vector<std::string_view>
154 : split_string(std::string_view str, std::string_view delims = " ")
155 : {
156 : std::vector<std::string_view> output;
157 : for (auto first = str.data(), second = str.data(), last = first + str.size();
158 : second != last && first != last;
159 : first = second + 1) {
160 : second = std::find_first_of(first, last, std::cbegin(delims), std::cend(delims));
161 : if (first != second)
162 : output.emplace_back(first, second - first);
163 : }
164 : return output;
165 : }
166 :
167 : std::vector<unsigned> split_string_to_unsigned(std::string_view s, char sep);
168 :
169 : void string_replace(std::string& str, const std::string& from, const std::string& to);
170 :
171 : std::string_view string_remove_suffix(std::string_view str, char separator);
172 :
173 : std::string string_join(const std::set<std::string>& set, std::string_view separator = "/");
174 :
175 : std::set<std::string> string_split_set(std::string& str, std::string_view separator = "/");
176 :
177 : } // namespace jami
178 :
179 : // Add string operators crucially missing from standard
180 : // see https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/1RcShRhrmRc
181 : namespace std {
182 : inline string
183 64868 : operator+(const string& s, const string_view& sv)
184 : {
185 64868 : return jami::concat(s, sv);
186 : }
187 : inline string
188 64673 : operator+(const string_view& sv, const string& s)
189 : {
190 64673 : return jami::concat(sv, s);
191 : }
192 : using svmatch = match_results<string_view::const_iterator>;
193 : using svsub_match = sub_match<string_view::const_iterator>;
194 50 : constexpr string_view svsub_match_view(const svsub_match& submatch) noexcept {
195 50 : return string_view(&*submatch.first, submatch.second - submatch.first);
196 : }
197 : inline bool
198 13 : regex_match(string_view sv,
199 : svmatch& m,
200 : const regex& e,
201 : regex_constants::match_flag_type flags = regex_constants::match_default)
202 : {
203 13 : return regex_match(sv.begin(), sv.end(), m, e, flags);
204 : }
205 : inline bool
206 : regex_match(string_view sv,
207 : const regex& e,
208 : regex_constants::match_flag_type flags = regex_constants::match_default)
209 : {
210 : return regex_match(sv.begin(), sv.end(), e, flags);
211 : }
212 : inline bool
213 8444 : regex_search(string_view sv,
214 : svmatch& m,
215 : const regex& e,
216 : regex_constants::match_flag_type flags = regex_constants::match_default)
217 : {
218 8444 : return regex_search(sv.begin(), sv.end(), m, e, flags);
219 : }
220 : } // namespace std
|