2#include "fmt/color.hpp"
23inline std::string
fstring(
const std::string format, ...) {
24 constexpr std::size_t size = 256;
26 fmt_str.resize(size + 1);
32 va_start(args, format);
33 vsnprintf(&fmt_str[0], fmt_str.size(), format.c_str(), args);
37 fmt_str.erase(std::find(fmt_str.begin(), fmt_str.end(),
'\0'), fmt_str.end());
43inline std::string
fstring(
const std::size_t size,
const std::string format,
48 fmt_str.resize(size + 1);
54 va_start(args, format);
55 vsnprintf(&fmt_str[0], fmt_str.size(), format.c_str(), args);
59 fmt_str.erase(std::find(fmt_str.begin(), fmt_str.end(),
'\0'), fmt_str.end());
72 const auto wc = std::find(s2.cbegin(), s2.cend(),
'*');
76 const auto pos_wc = std::size_t(std::distance(s2.cbegin(), wc));
78 const auto s1_front = s1.substr(0, pos_wc);
79 const auto s2_front = s2.substr(0, pos_wc);
82 const auto len_back = std::size_t(std::distance(wc + 1, s2.cend()));
84 const auto pos_1_back = s1.length() > len_back ? s1.length() - len_back : 0;
85 const auto s1_back = s1.substr(pos_1_back, std::string::npos);
86 const auto s2_back = s2.substr(pos_wc + 1, std::string::npos);
88 return s1_front == s2_front && s1_back == s2_back;
96 return static_cast<char>(std::tolower(
static_cast<unsigned char>(ch)));
100inline std::string
tolower(std::string t_string) {
101 for (
auto &c : t_string) {
110inline bool contains(std::string_view the_string, std::string_view sub_string) {
111 return the_string.find(sub_string) != std::string::npos;
116 const std::string &sub_string) {
117 return tolower(the_string).find(
tolower(sub_string)) != std::string::npos;
122 const std::vector<std::string> &sub_strings) {
123 for (
const auto &substr : sub_strings) {
132 const std::vector<std::string> &sub_strings) {
133 for (
const auto &substr : sub_strings) {
143inline bool ci_compare(std::string_view s1, std::string_view s2) {
145 s1.cbegin(), s1.cend(), s2.cbegin(), s2.cend(),
146 [](
char c1,
char c2) { return qip::tolower(c1) == qip::tolower(c2); });
157 const auto wc = std::find(s2.cbegin(), s2.cend(),
'*');
161 const auto pos_wc = std::size_t(std::distance(s2.cbegin(), wc));
163 const auto s1_front = s1.substr(0, pos_wc);
164 const auto s2_front = s2.substr(0, pos_wc);
167 const auto len_back = std::size_t(std::distance(wc + 1, s2.cend()));
169 const auto pos_1_back = s1.length() > len_back ? s1.length() - len_back : 0;
170 const auto s1_back = s1.substr(pos_1_back, std::string::npos);
171 const auto s2_back = s2.substr(pos_wc + 1, std::string::npos);
179inline auto Levenstein(std::string_view a, std::string_view b) {
182 std::vector<size_t> d_t((a.size() + 1) * (b.size() + 1),
size_t(-1));
183 auto d = [&](
size_t ia,
size_t ib) ->
size_t & {
184 return d_t[ia * (b.size() + 1) + ib];
186 std::function<size_t(
size_t,
size_t)> LevensteinInt =
187 [&](
size_t ia,
size_t ib) ->
size_t {
188 if (d(ia, ib) != size_t(-1))
192 dist = a.size() - ia;
193 else if (ia >= a.size())
194 dist = b.size() - ib;
195 else if (a[ia] == b[ib])
196 dist = LevensteinInt(ia + 1, ib + 1);
198 dist = 1 + std::min(std::min(LevensteinInt(ia, ib + 1),
199 LevensteinInt(ia + 1, ib)),
200 LevensteinInt(ia + 1, ib + 1));
204 return LevensteinInt(0, 0);
209 std::vector<size_t> d_t((a.size() + 1) * (b.size() + 1),
size_t(-1));
210 auto d = [&](
size_t ia,
size_t ib) ->
size_t & {
211 return d_t[ia * (b.size() + 1) + ib];
213 std::function<size_t(
size_t,
size_t)> LevensteinInt =
214 [&](
size_t ia,
size_t ib) ->
size_t {
215 if (d(ia, ib) != size_t(-1))
219 dist = a.size() - ia;
220 else if (ia >= a.size())
221 dist = b.size() - ib;
223 dist = LevensteinInt(ia + 1, ib + 1);
225 dist = 1 + std::min(std::min(LevensteinInt(ia, ib + 1),
226 LevensteinInt(ia + 1, ib)),
227 LevensteinInt(ia + 1, ib + 1));
231 return LevensteinInt(0, 0);
237 const std::vector<std::string> &list) {
238 auto compare = [&test_string](
const auto &s1,
const auto &s2) {
241 return std::min_element(list.cbegin(), list.cend(),
compare);
247 const std::vector<std::string> &list) {
248 auto compare = [&test_string](
const auto &s1,
const auto &s2) {
252 using namespace std::string_literals;
253 return list.empty() ?
""s :
254 *std::min_element(list.cbegin(), list.cend(),
compare);
269 std::find_if(s.cbegin() + 1, s.cend(),
270 [](
auto c) { return !std::isdigit(c); }) == s.end() &&
272 (std::isdigit(s[0]) || ((s[0] ==
'-' || s[0] ==
'+') && s.size() > 1));
278inline std::vector<std::string>
split(
const std::string &s,
char delim =
' ') {
279 std::vector<std::string> out;
280 std::stringstream ss(s);
282 while (getline(ss, tmp, delim)) {
289inline std::string
concat(
const std::vector<std::string> &v,
290 const std::string &delim =
"") {
292 for (std::size_t i = 0; i < v.size(); ++i) {
294 if (i != v.size() - 1)
307inline std::string
wrap(
const std::string &input, std::size_t at = 80,
308 const std::string &prefix =
"") {
310 const auto length = at - prefix.size();
311 std::size_t ipos = 0;
312 std::size_t fpos = length;
313 while (ipos < input.length()) {
317 auto temp_pos_nl = input.find(
'\n', ipos);
318 if (temp_pos_nl > ipos && temp_pos_nl < fpos &&
319 temp_pos_nl != std::string::npos) {
320 output += prefix + input.substr(ipos, temp_pos_nl - ipos);
321 ipos = temp_pos_nl + 1;
322 fpos = ipos + length;
326 if (fpos >= input.length()) {
327 output += prefix + input.substr(ipos, fpos - ipos);
331 auto temp_pos = input.rfind(
' ', fpos);
332 if (temp_pos <= ipos || temp_pos == std::string::npos) {
333 output += prefix + input.substr(ipos, fpos - ipos);
335 fpos = ipos + length;
337 output += prefix + input.substr(ipos, temp_pos - ipos);
339 fpos = ipos + length;
352 return std::to_string(a);
353 static const std::string M[] = {
"",
"M",
"MM",
"MMM"};
354 static const std::string C[] = {
"",
"C",
"CC",
"CCC",
"CD",
355 "D",
"DC",
"DCC",
"DCCC",
"CM"};
356 static const std::string X[] = {
"",
"X",
"XX",
"XXX",
"XL",
357 "L",
"LX",
"LXX",
"LXXX",
"XC"};
358 static const std::string I[] = {
"",
"I",
"II",
"III",
"IV",
359 "V",
"VI",
"VII",
"VIII",
"IX"};
360 return M[a / 1000] + C[(a % 1000) / 100] + X[(a % 100) / 10] + I[(a % 10)];
General-purpose utility library.
Definition Array.hpp:23
auto closest_match(std::string_view test_string, const std::vector< std::string > &list)
Returns an iterator to the closest match to test_string in list, using Levenstein distance.
Definition String.hpp:236
std::string concat(const std::vector< std::string > &v, const std::string &delim="")
Concatenates a vector of strings into one, with an optional delimiter.
Definition String.hpp:289
auto Levenstein(std::string_view a, std::string_view b)
Returns the Levenshtein edit distance between strings a and b.
Definition String.hpp:179
std::string ci_closest_match(const std::string_view test_string, const std::vector< std::string > &list)
Returns the closest match (case insensitive) to test_string in list, using ci_Levenstein distance.
Definition String.hpp:246
bool string_is_integer(std::string_view s)
Returns true if the string represents an integer.
Definition String.hpp:266
std::vector< std::string > split(const std::string &s, char delim=' ')
Splits a string by delimiter into a vector of substrings.
Definition String.hpp:278
bool ci_contains(const std::string &the_string, const std::string &sub_string)
Returns true if the_string contains sub_string (case insensitive).
Definition String.hpp:115
auto ci_Levenstein(std::string_view a, std::string_view b)
Case-insensitive version of Levenstein.
Definition String.hpp:208
bool ci_wc_compare(std::string_view s1, std::string_view s2)
Case-insensitive version of wildcard_compare.
Definition String.hpp:155
std::string int_to_roman(int a)
Converts an integer to a Roman numeral string. Assumes |a| <= 3999.
Definition String.hpp:348
std::string fstring(const std::string format,...)
Returns a formatted string using printf-style format specifiers.
Definition String.hpp:23
bool ci_compare(std::string_view s1, std::string_view s2)
Case-insensitive string comparison; equivalent to tolower(s1) == tolower(s2).
Definition String.hpp:143
bool wildcard_compare(std::string_view s1, std::string_view s2)
Compares s1 against pattern s2, where s2 may contain one wildcard '*' that matches any substring.
Definition String.hpp:70
bool contains(std::string_view the_string, std::string_view sub_string)
Returns true if the_string contains sub_string.
Definition String.hpp:110
auto compare(const std::vector< T > &first, const std::vector< T > &second)
Compares two arithmetic vectors element-wise; returns {max_delta, iterator}.
Definition Vector.hpp:41
std::string wrap(const std::string &input, std::size_t at=80, const std::string &prefix="")
Word-wraps input at column at, optionally prefixing each line.
Definition String.hpp:307
char tolower(char ch)
Conversion of a single character to lowercase.
Definition String.hpp:94