common/str_map: reimplement get_str_list() using for_each_pair

to avoid creating a temporary list<string> and then dropping it
on the floor after iterating through it for collecting the kv
pairs in it.

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
This commit is contained in:
Kefu Chai 2021-12-19 12:25:50 +08:00
parent 7b7686df85
commit b5d638dc0f
2 changed files with 35 additions and 33 deletions

View File

@ -59,12 +59,15 @@ int get_json_str_map(
return 0;
}
string trim(const string& str) {
return boost::algorithm::trim_copy_if(
str,
[](unsigned char c) {
return std::isspace(c);
});
static std::string_view trim(std::string_view str)
{
static const char* whitespaces = "\t\n ";
auto beg = str.find_first_not_of(whitespaces);
if (beg == str.npos) {
return {};
}
auto end = str.find_last_not_of(whitespaces);
return str.substr(beg, end - beg + 1);
}
int get_str_map(
@ -72,18 +75,15 @@ int get_str_map(
str_map_t* str_map,
const char *delims)
{
auto pairs = get_str_list(str, delims);
for (const auto& pr : pairs) {
size_t equal = pr.find('=');
if (equal == string::npos)
(*str_map)[pr] = string();
else {
const string key = trim(pr.substr(0, equal));
equal++;
const string value = trim(pr.substr(equal));
(*str_map)[key] = value;
for_each_pair(str, delims, [str_map](std::string_view key,
std::string_view val) {
// is the format 'K=V' or just 'K'?
if (val.empty()) {
str_map->emplace(std::string(key), "");
} else {
str_map->emplace(std::string(trim(key)), std::string(trim(val)));
}
}
});
return 0;
}
@ -91,23 +91,8 @@ str_map_t get_str_map(
const string& str,
const char* delim)
{
auto pairs = get_str_list(str, delim);
str_map_t str_map;
for (const auto& pr : pairs) {
auto equal = pr.find('=');
// is the format 'K=V' or just 'K'?
if (equal == std::string::npos) {
str_map[pr] = std::string{};
} else {
const string key = trim(pr.substr(0, equal));
equal++;
const string value = trim(pr.substr(equal));
str_map[key] = value;
}
}
get_str_map(str, &str_map, delim);
return str_map;
}

View File

@ -23,6 +23,23 @@
#include <string>
#include <sstream>
template <typename Func>
void for_each_pair(std::string_view s, const char* delims, Func&& f)
{
auto pos = s.find_first_not_of(delims);
while (pos != s.npos) {
s.remove_prefix(pos); // trim delims from the front
auto end = s.find_first_of(delims);
auto kv = s.substr(0, end);
if (auto equal = kv.find('='); equal != kv.npos) {
f(kv.substr(0, equal), kv.substr(equal + 1));
} else {
f(kv.substr(0, equal), std::string_view());
}
pos = s.find_first_not_of(delims, end);
}
}
using str_map_t = std::map<std::string,std::string>;
/**