Browse Source

Parsing lines containing nested key-value pairs

default_compile_flags
vector-of-bool 5 years ago
parent
commit
675f8d365a
3 changed files with 79 additions and 0 deletions
  1. +29
    -0
      src/libman/parse.cpp
  2. +7
    -0
      src/libman/parse.hpp
  3. +43
    -0
      src/libman/parse.test.cpp

+ 29
- 0
src/libman/parse.cpp View File

@@ -81,4 +81,33 @@ void lm::write_pairs(fs::path fpath, const std::vector<pair>& pairs) {
for (auto& pair : pairs) {
fstream << pair.key() << ": " << pair.value() << '\n';
}
}

nested_kvlist nested_kvlist::parse(const std::string_view line_) {
const auto line = trim(line_);
const auto semi_pos = line.find(';');
const auto primary = trim(line.substr(0, semi_pos));
auto tail = semi_pos == line.npos ? ""sv : trim(line.substr(semi_pos + 1));

std::vector<pair> pairs;
while (!tail.empty()) {
const auto space_pos = tail.find(' ');
const auto item = tail.substr(0, space_pos);

const auto eq_pos = item.find('=');
if (eq_pos == item.npos) {
pairs.emplace_back(item, ""sv);
} else {
const auto key = item.substr(0, eq_pos);
const auto value = item.substr(eq_pos + 1);
pairs.emplace_back(key, value);
}

if (space_pos == tail.npos) {
break;
}
tail = trim(tail.substr(space_pos + 1));
}

return nested_kvlist{std::string(primary), pair_list{std::move(pairs)}};
}

+ 7
- 0
src/libman/parse.hpp View File

@@ -125,6 +125,13 @@ inline void write_pairs(const std::filesystem::path& fpath, const pair_list& pai
write_pairs(fpath, pairs.items());
}

struct nested_kvlist {
std::string primary;
pair_list pairs;

static nested_kvlist parse(std::string_view s);
};

template <typename What>
class read_required {
std::string_view _key;

+ 43
- 0
src/libman/parse.test.cpp View File

@@ -80,9 +80,52 @@ void test_multi() {
CHECK(!iter);
}

void test_nested_kvlist() {
auto check_1 = [](auto str) {
auto result = nested_kvlist::parse(str);
CHECK(result.primary == "Foo");
CHECK(result.pairs.size() == 1);
REQUIRE(result.pairs.find("bar"));
CHECK(result.pairs.find("bar")->value() == "baz");
};
check_1("Foo; bar=baz");
check_1("Foo ; bar=baz");
check_1("Foo ; bar=baz");
check_1("Foo ; bar=baz ");
check_1("Foo;bar=baz ");
check_1("Foo;bar=baz");

auto check_2 = [](auto str) {
auto result = nested_kvlist::parse(str);
CHECK(result.primary == "Foo");
CHECK(result.pairs.size() == 0);
};
check_2("Foo");
check_2("Foo;");
check_2("Foo ;");
check_2("Foo ; ");
check_2("Foo; ");

auto check_3 = [](auto str) {
auto result = nested_kvlist::parse(str);
CHECK(result.primary == "Foo bar");
CHECK(result.pairs.size() == 2);
REQUIRE(result.pairs.find("baz"));
CHECK(result.pairs.find("baz")->value() == "meow");
REQUIRE(result.pairs.find("quux"));
CHECK(result.pairs.find("quux")->value() == "");
};

check_3("Foo bar; baz=meow quux");
check_3("Foo bar ; baz=meow quux=");
check_3("Foo bar ; quux= baz=meow");
check_3("Foo bar ;quux= baz=meow");
}

void run_tests() {
test_simple();
test_multi();
test_nested_kvlist();
}

DDS_TEST_MAIN;

Loading…
Cancel
Save