guanaqo 1.0.0-alpha.27
Utilities for scientific software
Loading...
Searching...
No Matches
string-util.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @ingroup strings
5/// String utilities for splitting, joining, and sorting.
6
7#include <algorithm>
8#include <numeric>
9#include <ranges>
10#include <string>
11#include <string_view>
12#include <tuple>
13
14namespace guanaqo {
15
16/// @addtogroup strings
17/// @{
18
19/// Split the string @p full on the first occurrence of @p tok.
20/// Returns `(s, "")` if tok was not found.
21inline auto split(std::string_view full, std::string_view tok) {
22 auto tok_pos = full.find(tok);
23 if (tok_pos == full.npos) {
24 std::string_view key = full;
25 std::string_view rem{key.data() + key.size(), 0};
26 return std::make_tuple(key, rem);
27 } else {
28 auto tok_len = tok.size();
29 std::string_view key = full.substr(0, tok_pos);
30 std::string_view rem = full.substr(tok_pos + tok_len);
31 return std::make_tuple(key, rem);
32 }
33}
34
35/// Split the string @p s on the first occurrence of @p tok.
36/// Returns `("", s)` if tok was not found.
37inline auto split_second(std::string_view full, std::string_view tok) {
38 auto tok_pos = full.find(tok);
39 if (tok_pos == full.npos) {
40 std::string_view key{full.data(), 0};
41 std::string_view rem = full;
42 return std::make_tuple(key, rem);
43 } else {
44 auto tok_len = tok.size();
45 std::string_view key = full.substr(0, tok_pos);
46 std::string_view rem = full.substr(tok_pos + tok_len);
47 return std::make_tuple(key, rem);
48 }
49}
50
51/// @see @ref join
52struct join_opt {
53 std::string_view sep = ", ";
54 std::string_view empty = "∅";
55};
56
57/// Join the list of strings into a single string, using the separator given by
58/// @p opt.
59/// @see @ref join_opt
60std::string join(std::ranges::input_range auto strings, join_opt opt = {}) {
61 if (std::ranges::empty(strings))
62 return std::string(opt.empty);
63 auto combine = [&opt](std::string &&acc, const auto &e) {
64 acc += opt.sep;
65 acc += e;
66 return std::move(acc);
67 };
68 auto begin = std::ranges::begin(strings);
69 auto end = std::ranges::end(strings);
70 using std::ranges::next;
71 std::string first{*begin};
72 return std::accumulate(next(begin), end, std::move(first), combine);
73}
74
75/// @see @ref join_quote
77 std::string_view sep = ", ";
78 std::string_view empty = "∅";
79 std::string_view quote_left = "\"";
80 std::string_view quote_right = "\"";
81};
82
83/// Join the list of strings into a single string, using the separator given by
84/// @p opt. Each original string is quoted using the quote strings specified
85/// by @p opt
86/// @see @ref join_quote_opt
87std::string join_quote(std::ranges::input_range auto strings,
88 join_quote_opt opt = {}) {
89 if (std::ranges::empty(strings))
90 return std::string(opt.empty);
91 auto combine = [&opt](std::string &&acc, const auto &e) {
92 acc += opt.quote_right;
93 acc += opt.sep;
94 acc += opt.quote_left;
95 acc += e;
96 return std::move(acc);
97 };
98 auto begin = std::ranges::begin(strings);
99 auto end = std::ranges::end(strings);
100 std::string first{*begin};
101 first.insert(0, opt.quote_left);
102 using std::ranges::next;
103 auto result = std::accumulate(next(begin), end, std::move(first), combine);
104 result += opt.quote_right;
105 return result;
106}
107
108/// Sort the given range of strings in-place in a case-insensitive manner.
109void sort_case_insensitive(auto &range) {
110 auto cmp = [](const auto &a, const auto &b) {
111 auto toupper = [](unsigned char c) { return std::toupper(c); };
112 return std::ranges::lexicographical_compare(
113 std::views::transform(a, toupper),
114 std::views::transform(b, toupper));
115 };
116 std::ranges::sort(range, cmp);
117}
118
119/// @}
120
121} // namespace guanaqo
std::string_view sep
std::string_view quote_right
std::string_view sep
std::string_view quote_left
std::string_view empty
std::string_view empty
void sort_case_insensitive(auto &range)
Sort the given range of strings in-place in a case-insensitive manner.
std::string join_quote(std::ranges::input_range auto strings, join_quote_opt opt={})
Join the list of strings into a single string, using the separator given by opt.
std::string join(std::ranges::input_range auto strings, join_opt opt={})
Join the list of strings into a single string, using the separator given by opt.
auto split_second(std::string_view full, std::string_view tok)
Split the string s on the first occurrence of tok.
auto split(std::string_view full, std::string_view tok)
Split the string full on the first occurrence of tok.