cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
String.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2013-2024 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdio.h>
20#include <unistd.h>
21
22#include <codecvt>
23#include <cstdint>
24#include <locale>
25#include <unordered_set>
26
29#include "CepGen/Utils/String.h"
30
31#ifndef __APPLE__
32#include <cstring>
33#endif
34#ifdef __GNUG__
35#include <cxxabi.h>
36
37#include <cstdlib>
38#include <memory>
39#endif
40
41namespace cepgen {
42 namespace utils {
43 std::regex kFloatRegex("[+-]?[0-9]*\\.?[0-9]+([eEdD][+-]?[0-9]+)?", std::regex_constants::extended);
44
45 std::string yesno(bool test) { return test ? colourise("true", Colour::green) : colourise("false", Colour::red); }
46
48 template <>
49 std::string boldify(std::string str) {
51 }
52
54 template <>
55 std::string boldify(const char* str) {
56 return boldify(std::string(str));
57 }
58
60 template <>
61 std::string boldify(unsigned long ui) {
62 return boldify(std::to_string(ui));
63 }
64
65 Modifier operator|(const Modifier& lhs, const Modifier& rhs) {
66 std::bitset<7> mod1((int)lhs), mod2((int)rhs);
67 return (Modifier)(mod1 | mod2).to_ulong();
68 }
69
70 std::string colourise(const std::string& str, const Colour& col, const Modifier& mod) {
71 if (!Logger::get().isTTY())
72 return str;
73 std::string out;
74 auto get_mod_str = [](const Colour& col, const Modifier& mod) -> std::string {
75 std::string mod_str("\033[");
76 if (col != Colour::none)
77 mod_str += std::to_string((int)col);
78 if (mod > Modifier::reset)
79 for (size_t i = 0; i < 7; ++i)
80 if (((uint16_t)mod >> i) & 0x1)
81 mod_str += ";" + std::to_string(i + 1);
82 return mod_str + "m";
83 };
84 out = get_mod_str(col, mod);
85 out += str;
86 out += get_mod_str(Colour::reset, Modifier::reset);
87 return out;
88 }
89
90 std::string parseSpecialChars(const std::string& str) {
91 return replaceAll(
92 str, {{"Α", "\\Alpha"}, {"Β", "\\Beta"}, {"Χ", "\\Chi"}, {"Δ", "\\Delta"}, {"Ε", "\\Epsilon"},
93 {"Φ", "\\Phi"}, {"Γ", "\\Gamma"}, {"Η", "\\Eta"}, {"Ι", "\\Iota"}, {"Κ", "\\Kappa"},
94 {"Λ", "\\Lambda"}, {"Μ", "\\Mu"}, {"Ν", "\\Nu"}, {"Ο", "\\Omicron"}, {"Π", "\\Pi"},
95 {"Θ", "\\Theta"}, {"Ρ", "\\Rho"}, {"Σ", "\\Sigma"}, {"Τ", "\\Tau"}, {"Υ", "\\Upsilon"},
96 {"Ω", "\\Omega"}, {"Ξ", "\\Xi"}, {"Ψ", "\\Psi"}, {"Ζ", "\\Zeta"}, {"α", "\\alpha"},
97 {"β", "\\beta"}, {"χ", "\\Chi"}, {"δ", "\\delta"}, {"ε", "\\epsilon"}, {"ɸ", "\\phi"},
98 {"γ", "\\gamma"}, {"η", "\\eta"}, {"ι", "\\iota"}, {"κ", "\\kappa"}, {"λ", "\\lambda"},
99 {"μ", "\\mu"}, {"ν", "\\nu"}, {"ο", "\\omicron"}, {"π", "\\pi"}, {"θ", "\\theta"},
100 {"ρ", "\\rho"}, {"σ", "\\sigma"}, {"τ", "\\tau"}, {"υ", "\\upsilon"}, {"ω", "\\omega"},
101 {"ξ", "\\xi"}, {"ψ", "\\psi"}, {"ζ", "\\zeta"}, {"⁺", "^{+}"}, {"¯", "^{-}"},
102 {"→", "\\rightarrow"}, {"←", "\\leftarrow"}, {"↝ ", "\\leadsto"}});
103 }
104
105 std::string sanitise(const std::string& str) {
106 return toLower(
107 replaceAll(str, {{")", ""}, {"(", "_"}, {"{", "_"}, {".", ""}, {",", "_"}, {":", "_"}, {"-", ""}}));
108 }
109
110 std::string timeAs(const std::string& fmt) {
111 auto now = std::time(nullptr);
112 auto tm = *std::localtime(&now);
113 char out_str[50];
114 strftime(out_str, 50, fmt.c_str(), &tm);
115 return std::string(out_str);
116 }
117
118 size_t replaceAll(std::string& str, const std::string& from, const std::string& to) {
119 size_t count = 0, pos = 0;
120 while ((pos = str.find(from, pos)) != std::string::npos) {
121 str.replace(pos, from.length(), to);
122 pos += to.length();
123 ++count;
124 }
125 return count;
126 }
127
128 std::string replaceAll(const std::string& str, const std::string& from, const std::string& to) {
129 auto out{str};
130 if (replaceAll(out, from, to) == 0)
131 CG_DEBUG_LOOP("replaceAll") << "No occurrence of {"
132 << replaceAll(from, {{"\n", "\\n"}, {"\t", "\\t"}, {"\r", "\\r"}})
133 << "} found in input string.";
134 return out;
135 }
136
137 std::string replaceAll(const std::string& str, const std::vector<std::pair<std::string, std::string> >& keys) {
138 auto out{str};
139 for (const auto& key : keys)
140 replaceAll(out, key.first, key.second);
141 CG_DEBUG_LOOP("replaceAll").log([&keys, &out](auto& log) {
142 log << "Values to be replaced: ";
143 for (const auto& key : keys)
144 log << "\n\t{\"" << key.first << "\" -> \"" << key.second << "\"}";
145 log << "\n-> output: \"" << out << "\".";
146 });
147 return out;
148 }
149
150 template <>
151 std::string toString(const std::wstring& str) {
152 typedef std::codecvt_utf8_utf16<wchar_t> convert_type;
153 std::wstring_convert<convert_type, wchar_t> converter;
154 return converter.to_bytes(str);
155 }
156
157 template <>
158 std::string toString(const ParametersList& params) {
159 std::ostringstream os;
160 os << params;
161 return os.str();
162 }
163
164 template <>
165 std::string toString(const Limits& lim) {
166 std::ostringstream os;
167 os << lim;
168 return os.str();
169 }
170
171 std::wstring toWstring(const std::string& str) {
172 typedef std::codecvt_utf8_utf16<wchar_t> convert_type;
173 std::wstring_convert<convert_type, wchar_t> converter;
174 return converter.from_bytes(str);
175 }
176
177 template <>
178 std::string toString(const double& val) {
179 auto out = format("%.16g", val);
180 if (out.find('.') == std::string::npos && out.find('e') == std::string::npos &&
181 out.find('E') == std::string::npos)
182 out += ".0";
183 return out;
184 }
185
186 std::string toCamelCase(const std::string& in, bool lower) {
187 auto out = in;
188 if (in.size() < 2 || (in.find('_') == std::string::npos && in.find('-') == std::string::npos &&
189 in.find(' ') == std::string::npos)) {
190 if (!std::isupper(in[0]))
191 return in;
192 for (size_t i = 1; i < out.size(); ++i) { // convert "weird" CAMELCase string
193 if (std::islower(out[i])) {
194 out[i - 1] = std::toupper(out[i - 1]);
195 break;
196 }
197 out[i] = std::tolower(out[i]);
198 }
199 } else {
200 bool tail = true; // start from lowercase "tail-like" characters
201 size_t n = 0;
202 for (const auto& c : out) {
203 if (c == '-' || c == '_' || c == ' ') {
204 tail = false;
205 continue; // skip this character to concentrate on the following ones (head+tail)
206 }
207 if (tail)
208 out[n++] = std::tolower(c);
209 else { // head (uppercase letter)
210 out[n++] = std::toupper(c);
211 tail = true;
212 }
213 }
214 out.resize(n);
215 }
216 if (lower)
217 out[0] = std::tolower(out[0]);
218 return out;
219 }
220
221 std::string randomString(size_t size) {
222 std::stringstream out;
223 for (size_t i = 0; i < size; ++i)
224 out << (char)('a' + rand() % (('z' - 'a') + 1));
225 return out.str();
226 }
227
228 std::string s(const std::string& word, float num, bool show_number) {
229 return show_number ? (num == 0 ? "no" : format("%g", num)) + format(" %s%s", word.c_str(), num > 1. ? "s" : "")
230 : format("%s%s", word.c_str(), num > 1. ? "s" : "");
231 }
232
233 std::vector<std::string> split(const std::string& str, char delim, bool trim) {
234 std::vector<std::string> out;
235 if (str.empty())
236 return out;
237 std::string token;
238 std::istringstream iss(str);
239 while (std::getline(iss, token, delim)) {
240 const auto tok = trim ? ltrim(rtrim(token)) : token;
241 if (!trim || !tok.empty())
242 out.emplace_back(tok);
243 }
244 return out;
245 }
246
247 template <typename T>
248 std::string merge(const std::vector<T>& vec, const std::string& delim) {
249 if (vec.empty())
250 return std::string();
251 std::ostringstream oss;
252 std::for_each(vec.begin(), vec.end(), [&oss, &delim, sep = std::string()](const auto& val) mutable {
253 oss << sep << val;
254 sep = delim;
255 });
256 return oss.str();
257 }
258
259 template std::string merge<std::string>(const std::vector<std::string>&, const std::string&);
260 template std::string merge<Limits>(const std::vector<Limits>&, const std::string&);
261 template std::string merge<unsigned short>(const std::vector<unsigned short>&, const std::string&);
262 template std::string merge<int>(const std::vector<int>&, const std::string&);
263 template std::string merge<unsigned long long>(const std::vector<unsigned long long>&, const std::string&);
264 template std::string merge<double>(const std::vector<double>&, const std::string&);
265 template std::string merge<ParametersList>(const std::vector<ParametersList>&, const std::string&);
266
267 template <typename T>
268 std::string merge(const std::vector<std::vector<T> >& vec, const std::string& delim) {
269 if (vec.empty())
270 return std::string();
271 std::ostringstream oss;
272 std::for_each(vec.begin(), vec.end(), [&oss, &delim, sep = std::string()](const auto& val) mutable {
273 const auto mrg = merge(val, delim);
274 oss << sep << mrg;
275 sep = delim;
276 });
277 return oss.str();
278 }
279
280 template std::string merge<double>(const std::vector<std::vector<double> >&, const std::string&);
281
282 std::string merge(const ParametersList& plist, const std::string&) { return plist.print(); }
283
284 std::string merge(const Limits& lim, const std::string&) {
285 std::ostringstream os;
286 os << lim;
287 return os.str();
288 }
289
290 bool isInt(const std::string& str) {
291 return !str.empty() &&
292 std::find_if(str.begin(), str.end(), [](unsigned char c) { return !std::isdigit(c); }) == str.end();
293 }
294
295 bool isFloat(const std::string& str) { return std::regex_match(str, kFloatRegex); }
296
297 std::string toUpper(const std::string& str) {
298 std::string out;
299 out.resize(str.size());
300 std::transform(str.begin(), str.end(), out.begin(), ::toupper);
301 return out;
302 }
303
304 std::string toLower(const std::string& str) {
305 std::string out;
306 out.resize(str.size());
307 std::transform(str.begin(), str.end(), out.begin(), ::tolower);
308 return out;
309 }
310
311 template <typename T>
312 void normalise(std::vector<T>& coll) {
313 std::unordered_set<T> set;
314 for (const auto& it : coll)
315 set.insert(it);
316 coll.assign(set.begin(), set.end());
317 std::sort(coll.begin(), coll.end());
318 }
319 template void normalise(std::vector<std::string>&);
320
321 std::string ltrim(const std::string& str) {
322 auto out{str};
323 out.erase(out.begin(), std::find_if(out.begin(), out.end(), [](unsigned char ch) { return !std::isspace(ch); }));
324 return out;
325 }
326
327 std::string rtrim(const std::string& str) {
328 auto out{str};
329 out.erase(std::find_if(out.rbegin(), out.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(),
330 out.end());
331 return out;
332 }
333
334 std::string strip(const std::string& str) {
335 auto out{str};
336 out.resize(std::remove_if(out.begin(), out.end(), [](char x) { return !std::isalnum(x) && !std::isspace(x); }) -
337 out.begin());
338 return out;
339 }
340
341 std::string demangle(const char* name) {
342#ifdef __GNUG__
343 int status = 0; // some arbitrary value to eliminate the compiler warning
344 std::unique_ptr<char, void (*)(void*)> res{abi::__cxa_demangle(name, NULL, NULL, &status), std::free};
345 return status == 0 ? res.get() : name;
346#else
347 return name;
348#endif
349 }
350
351 std::vector<std::string> between(const std::string& str, const std::string& beg, const std::string& end) {
352 size_t ptr = 0;
353 std::vector<std::string> out;
354 while (ptr < str.size()) {
355 const auto beg_delim_pos = str.find_first_of(beg, ptr);
356 if (beg_delim_pos == std::string::npos)
357 break;
358 const auto beg_pos = beg_delim_pos + beg.size(), end_delim_pos = str.find_first_of(end, beg_pos);
359 out.emplace_back(str.substr(beg_pos, end_delim_pos - beg_pos));
360 ptr = end_delim_pos;
361 }
362 return out;
363 }
364
365 bool startsWith(const std::string& str, const std::string& beg) { return ltrim(str).rfind(beg, 0) == 0; }
366
367 bool endsWith(const std::string& str, const std::string& end) {
368 if (end.size() > str.size())
369 return false;
370 return std::equal(end.rbegin(), end.rend(), str.rbegin());
371 }
372
373 std::string describeError(int errnum) {
374#ifdef __APPLE__
375 return std::to_string(errnum);
376#else
377 char* error = strerror(errnum);
378 return std::to_string(errnum) + " (" + std::string(error, strlen(error)) + ")";
379#endif
380 }
381
382#define STRINGIFY(x) #x
383#define TOSTRING(x) STRINGIFY(x)
384#define DEF_COLOUR(col) \
385 case Colour::col: \
386 return os << colourise(TOSTRING(col), Colour::col);
387#define DEF_MODIFIER(mod) \
388 case Modifier::mod: \
389 return os << colourise(TOSTRING(mod), Colour::none, Modifier::mod);
390
391 std::ostream& operator<<(std::ostream& os, const Colour& col) {
392 switch (col) {
402 default:
404 }
405 }
406
407 std::ostream& operator<<(std::ostream& os, const Modifier& mod) {
408 switch (mod) {
416 default:
418 }
419 }
420
421#undef DEF_COLOUR
422#undef DEF_MODIFIER
423 } // namespace utils
424} // namespace cepgen
#define CG_DEBUG_LOOP(mod)
Definition Message.h:224
#define DEF_MODIFIER(mod)
Definition String.cpp:387
#define DEF_COLOUR(col)
Definition String.cpp:384
Validity interval for a variable.
Definition Limits.h:28
const ParametersList & print(std::ostream &) const
Debugging-like printout of a parameters container.
static Logger & get(std::ostream *=nullptr)
Retrieve the running instance of the logger.
Definition Logger.cpp:31
std::ostream & operator<<(std::ostream &os, const Drawer::Mode &mode)
Definition Drawer.cpp:37
std::string format(const std::string &fmt, Args... args)
Format a string using a printf style format descriptor.
Definition String.h:61
std::string yesno(bool test)
Human-readable boolean printout Boldify a string for TTY-type output streams.
Definition String.cpp:45
std::string timeAs(const std::string &fmt)
Return the formatted date/time now.
Definition String.cpp:110
std::string describeError(int errnum)
Describe an error code.
Definition String.cpp:373
std::string s(const std::string &word, float num, bool show_number)
Add a trailing "s" when needed.
Definition String.cpp:228
template std::string merge< unsigned short >(const std::vector< unsigned short > &, const std::string &)
std::string strip(const std::string &str)
Strip all special characters from string.
Definition String.cpp:334
void normalise(std::vector< T > &coll)
Remove duplicates and sort a collection.
Definition Collections.h:63
std::string parseSpecialChars(const std::string &str)
Transform all emoji-like special characters into their LaTeX representation.
Definition String.cpp:90
std::vector< K > keys(const std::map< K, T > &coll)
Retrieve all keys from a map.
Definition Collections.h:33
std::string boldify(std::string str)
String implementation of the boldification procedure.
Definition String.cpp:49
std::vector< std::string > between(const std::string &str, const std::string &beg, const std::string &end)
Get a (list of) substring(s) between two characters chains.
Definition String.cpp:351
std::string toLower(const std::string &str)
Lowercase version of a string.
Definition String.cpp:304
std::string trim(const std::string &str)
Trim leading and trailing spaces.
Definition String.h:174
std::string toString(const std::wstring &str)
Convert a wide characters to a standard characters string.
Definition String.cpp:151
template std::string merge< unsigned long long >(const std::vector< unsigned long long > &, const std::string &)
Colour
TTY-type enumeration of colours.
Definition String.h:83
std::string sanitise(const std::string &str)
Replace all unsafe characters to build a computer-readable (and filename-safe) string.
Definition String.cpp:105
std::string toCamelCase(const std::string &in, bool lower)
Convert any case into a camelCase string.
Definition String.cpp:186
std::string ltrim(const std::string &str)
Trim leading spaces.
Definition String.cpp:321
template std::string merge< Limits >(const std::vector< Limits > &, const std::string &)
bool endsWith(const std::string &str, const std::string &end)
Check if a string ends with a given token.
Definition String.cpp:367
bool isFloat(const std::string &str)
Check if a string is also a floating point number.
Definition String.cpp:295
std::regex kFloatRegex("[+-]?[0-9]*\\.?[0-9]+([eEdD][+-]?[0-9]+)?", std::regex_constants::extended)
bool startsWith(const std::string &str, const std::string &beg)
Check if a string starts with a given token.
Definition String.cpp:365
std::string toUpper(const std::string &str)
Capitalise a string.
Definition String.cpp:297
std::string colourise(const std::string &str, const Colour &col, const Modifier &mod)
Colourise a string for TTY-type output streams.
Definition String.cpp:70
Drawer::Mode operator|(const Drawer::Mode &lhs, const Drawer::Mode::value_t &rhs)
Definition Drawer.cpp:32
std::string randomString(size_t size)
Generate a random string of a given size.
Definition String.cpp:221
template std::string merge< int >(const std::vector< int > &, const std::string &)
size_t replaceAll(std::string &str, const std::string &from, const std::string &to)
Replace all occurrences of a text by another.
Definition String.cpp:118
std::string merge(const std::vector< T > &vec, const std::string &delim)
Merge a collection of a printable type in a single string.
Definition String.cpp:248
std::vector< std::string > split(const std::string &str, char delim, bool trim)
Split a string according to a separation character.
Definition String.cpp:233
template std::string merge< ParametersList >(const std::vector< ParametersList > &, const std::string &)
std::string demangle(const char *name)
Demangle a type id if possible.
Definition String.cpp:341
std::string rtrim(const std::string &str)
Trim trailing spaces.
Definition String.cpp:327
std::wstring toWstring(const std::string &str)
Convert a standard characters to a wide characters string.
Definition String.cpp:171
template std::string merge< double >(const std::vector< double > &, const std::string &)
bool isInt(const std::string &str)
Check if a string is also an integer.
Definition String.cpp:290
template std::string merge< std::string >(const std::vector< std::string > &, const std::string &)
Common namespace for this Monte Carlo generator.