mirror of https://github.com/djcb/mu.git
utils: improve split / join
This commit is contained in:
parent
056fecd6aa
commit
e0096c3dee
|
@ -30,6 +30,7 @@
|
|||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
@ -196,7 +197,61 @@ Mu::split(const std::string& str, const std::string& sepa)
|
|||
return vec;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
Mu::split(const std::string& str, char sepa)
|
||||
{
|
||||
|
||||
std::vector<std::string> vec;
|
||||
size_t b = 0, e = 0;
|
||||
|
||||
/* special case */
|
||||
if (str.empty())
|
||||
return vec;
|
||||
|
||||
while (true) {
|
||||
if (e = str.find(sepa, b); e != std::string::npos) {
|
||||
vec.emplace_back(str.substr(b, e - b));
|
||||
b = e + sizeof(sepa);
|
||||
} else {
|
||||
vec.emplace_back(str.substr(b));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
Mu::join(const std::vector<std::string>& svec, const std::string& sepa)
|
||||
{
|
||||
if (svec.empty())
|
||||
return {};
|
||||
|
||||
|
||||
/* calculate the overall size beforehand, to avoid re-allocations. */
|
||||
size_t value_len =
|
||||
std::accumulate(svec.cbegin(), svec.cend(), 0,
|
||||
[](size_t size, const std::string& s) {
|
||||
return size + s.size();
|
||||
}) + (svec.size() - 1) * sepa.length();
|
||||
|
||||
std::string value;
|
||||
value.reserve(value_len);
|
||||
|
||||
std::accumulate(svec.cbegin(), svec.cend(), std::ref(value),
|
||||
[&](std::string& s1, const std::string& s2)->std::string& {
|
||||
if (s1.empty())
|
||||
s1 = s2;
|
||||
else {
|
||||
s1.append(sepa);
|
||||
s1.append(s2);
|
||||
}
|
||||
return s1;
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string
|
||||
Mu::quote(const std::string& str)
|
||||
|
|
|
@ -79,6 +79,32 @@ std::string remove_ctrl(const std::string& str);
|
|||
*/
|
||||
std::vector<std::string> split(const std::string& str, const std::string& sepa);
|
||||
|
||||
|
||||
/**
|
||||
* Split a string in parts. As a special case, splitting an empty string
|
||||
* yields an empty vector (not a vector with a single empty element)
|
||||
*
|
||||
* @param str a string
|
||||
* @param sepa the separator
|
||||
*
|
||||
* @return the parts.
|
||||
*/
|
||||
std::vector<std::string> split(const std::string& str, char sepa);
|
||||
|
||||
|
||||
/**
|
||||
* Join the strings in svec into a string, separated by sepa
|
||||
*
|
||||
* @param svec a string vector
|
||||
* @param sepa separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
std::string join(const std::vector<std::string>& svec, const std::string& sepa);
|
||||
static inline std::string join(const std::vector<std::string>& svec, char sepa) {
|
||||
return join(svec, std::string(1, sepa));
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote & escape a string for " and \
|
||||
*
|
||||
|
|
|
@ -161,7 +161,6 @@ test_format()
|
|||
}
|
||||
|
||||
static void
|
||||
|
||||
test_split()
|
||||
{
|
||||
using svec = std::vector<std::string>;
|
||||
|
@ -178,8 +177,23 @@ test_split()
|
|||
assert_equal_svec(split("ayybyyc", "yy"), {"a", "b", "c"});
|
||||
assert_equal_svec(split("abc", ""), {"a", "b", "c"});
|
||||
assert_equal_svec(split("", "boo"), {});
|
||||
|
||||
|
||||
assert_equal_svec(split("axbxc", 'x'), {"a", "b", "c"});
|
||||
assert_equal_svec(split("axbxcx", 'x'), {"a", "b", "c", ""});
|
||||
assert_equal_svec(split("", "boo"), {});
|
||||
}
|
||||
|
||||
static void
|
||||
test_join()
|
||||
{
|
||||
assert_equal(join({"a", "b", "c"}, "x"), "axbxc");
|
||||
assert_equal(join({"a", "b", "c"}, ""), "abc");
|
||||
assert_equal(join({},"foo"), "");
|
||||
assert_equal(join({"d", "e", "f"}, "foo"), "dfooefoof");
|
||||
}
|
||||
|
||||
|
||||
enum struct Bits { None = 0, Bit1 = 1 << 0, Bit2 = 1 << 1 };
|
||||
MU_ENABLE_BITOPS(Bits);
|
||||
|
||||
|
@ -222,6 +236,7 @@ main(int argc, char* argv[])
|
|||
g_test_add_func("/utils/clean", test_clean);
|
||||
g_test_add_func("/utils/format", test_format);
|
||||
g_test_add_func("/utils/split", test_split);
|
||||
g_test_add_func("/utils/join", test_join);
|
||||
g_test_add_func("/utils/define-bitmap", test_define_bitmap);
|
||||
|
||||
return g_test_run();
|
||||
|
|
Loading…
Reference in New Issue