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