mirror of
https://github.com/fmang/opustags.git
synced 2025-03-14 08:30:08 +01:00
Handlers: implement import tags handler
This commit is contained in:
parent
e60f7f84a0
commit
a210d1229e
@ -1,27 +1,74 @@
|
||||
#include <regex>
|
||||
#include "tags_handlers/import_tags_handler.h"
|
||||
|
||||
using namespace opustags;
|
||||
|
||||
ImportTagsHandler::ImportTagsHandler(std::istream &input_stream)
|
||||
: input_stream(input_stream)
|
||||
: parsed(false), input_stream(input_stream)
|
||||
{
|
||||
}
|
||||
|
||||
bool ImportTagsHandler::relevant(const int streamno)
|
||||
bool ImportTagsHandler::relevant(const int)
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImportTagsHandler::list(const int streamno, const Tags &)
|
||||
void ImportTagsHandler::list(const int, const Tags &)
|
||||
{
|
||||
}
|
||||
|
||||
bool ImportTagsHandler::edit(const int streamno, Tags &)
|
||||
bool ImportTagsHandler::edit(const int streamno, Tags &tags)
|
||||
{
|
||||
return false;
|
||||
// the reason why we do it this way is because the tests indirectly create
|
||||
// this handler with std::cin, and we do not want the constructor to block!
|
||||
parse_input_stream_if_needed();
|
||||
|
||||
const auto old_tags = tags;
|
||||
tags.clear();
|
||||
|
||||
if (tag_map.find(streamno) != tag_map.end())
|
||||
{
|
||||
const auto &source_tags = tag_map.at(streamno);
|
||||
for (const auto &source_tag : source_tags.get_all())
|
||||
tags.add(source_tag.key, source_tag.value);
|
||||
}
|
||||
|
||||
return old_tags != tags;
|
||||
}
|
||||
|
||||
bool ImportTagsHandler::done()
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImportTagsHandler::parse_input_stream_if_needed()
|
||||
{
|
||||
if (parsed)
|
||||
return;
|
||||
parsed = true;
|
||||
|
||||
const std::regex whitespace_regex("^\\s*$");
|
||||
const std::regex stream_header_regex(
|
||||
"^\\s*\\[stream\\s+(\\d+)\\]\\s*$", std::regex_constants::icase);
|
||||
const std::regex tag_regex(
|
||||
"^\\s*([a-z0-9]+)\\s*=\\s*(.*?)\\s*$", std::regex_constants::icase);
|
||||
|
||||
int current_stream_number = 1;
|
||||
std::string line;
|
||||
while (std::getline(input_stream, line))
|
||||
{
|
||||
std::smatch match;
|
||||
if (std::regex_match(line, match, stream_header_regex))
|
||||
{
|
||||
current_stream_number = std::atoi(match[1].str().c_str());
|
||||
}
|
||||
else if (std::regex_match(line, match, tag_regex))
|
||||
{
|
||||
tag_map[current_stream_number].add(match[1], match[2]);
|
||||
}
|
||||
else if (!std::regex_match(line, match, whitespace_regex))
|
||||
{
|
||||
throw std::runtime_error("Malformed input data near line " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include "tags_handler.h"
|
||||
|
||||
namespace opustags {
|
||||
@ -16,7 +17,11 @@ namespace opustags {
|
||||
bool done() override;
|
||||
|
||||
private:
|
||||
void parse_input_stream_if_needed();
|
||||
|
||||
bool parsed;
|
||||
std::istream &input_stream;
|
||||
std::map<int, Tags> tag_map;
|
||||
};
|
||||
|
||||
}
|
||||
|
142
tests/tags_handlers/import_tags_handler_test.cc
Normal file
142
tests/tags_handlers/import_tags_handler_test.cc
Normal file
@ -0,0 +1,142 @@
|
||||
#include "tags_handlers/import_tags_handler.h"
|
||||
#include "catch.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace opustags;
|
||||
|
||||
TEST_CASE("import tags handler", "[tags_handlers]")
|
||||
{
|
||||
SECTION("tags for streams not mentioned in import get emptied")
|
||||
{
|
||||
Tags tags = {{{"remove", "me"}}};
|
||||
std::stringstream ss;
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().empty());
|
||||
}
|
||||
|
||||
SECTION("streams that do not exist in the input file are ignored")
|
||||
{
|
||||
// TODO: rather than ignoring, at least print a warning
|
||||
// requires #6
|
||||
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "[Stream 5]\nkey = value\n";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(!handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().empty());
|
||||
}
|
||||
|
||||
SECTION("adding unique tags")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "[Stream 1]\nkey = value\nkey2 = value2\n";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().size() == 2);
|
||||
REQUIRE(tags.get("key") == "value");
|
||||
REQUIRE(tags.get("key2") == "value2");
|
||||
}
|
||||
|
||||
SECTION("adding tags with the same key")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "[Stream 1]\nkey = value1\nkey = value2\n";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().size() == 2);
|
||||
REQUIRE(tags.get_all().at(0).key == "key");
|
||||
REQUIRE(tags.get_all().at(1).key == "key");
|
||||
REQUIRE(tags.get_all().at(0).value == "value1");
|
||||
REQUIRE(tags.get_all().at(1).value == "value2");
|
||||
}
|
||||
|
||||
SECTION("overwriting existing tags")
|
||||
{
|
||||
Tags tags = {{{"remove", "me"}}};
|
||||
std::stringstream ss;
|
||||
ss << "[Stream 1]\nkey = value\nkey2 = value2\n";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().size() == 2);
|
||||
REQUIRE(tags.get("key") == "value");
|
||||
REQUIRE(tags.get("key2") == "value2");
|
||||
}
|
||||
|
||||
SECTION("various whitespace issues are worked around")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << " [StrEaM 1] \n\n key = value \nkey2=value2\n";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().size() == 2);
|
||||
REQUIRE(tags.get("key") == "value");
|
||||
REQUIRE(tags.get("key2") == "value2");
|
||||
}
|
||||
|
||||
SECTION("not specifying stream assumes first stream")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "key=value";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().size() == 1);
|
||||
REQUIRE(tags.get("key") == "value");
|
||||
}
|
||||
|
||||
SECTION("multiple streams")
|
||||
{
|
||||
Tags tags1;
|
||||
Tags tags2;
|
||||
std::stringstream ss;
|
||||
ss << "[stream 1]\nkey=value\n[stream 2]\nkey2=value2";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags1));
|
||||
REQUIRE(handler.edit(2, tags2));
|
||||
REQUIRE(tags1.get_all().size() == 1);
|
||||
REQUIRE(tags2.get_all().size() == 1);
|
||||
REQUIRE(tags1.get("key") == "value");
|
||||
REQUIRE(tags2.get("key2") == "value2");
|
||||
}
|
||||
|
||||
SECTION("sections listed twice are concatenated")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "[stream 1]\nkey=value\n"
|
||||
"[stream 2]\nkey=irrelevant\n"
|
||||
"[Stream 1]\nkey2=value2";
|
||||
ImportTagsHandler handler(ss);
|
||||
REQUIRE(handler.edit(1, tags));
|
||||
REQUIRE(tags.get_all().size() == 2);
|
||||
REQUIRE(tags.get("key") == "value");
|
||||
REQUIRE(tags.get("key2") == "value2");
|
||||
}
|
||||
|
||||
SECTION("weird input throws errors - malformed section headers")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "[stream huh]\n";
|
||||
REQUIRE_THROWS({
|
||||
ImportTagsHandler handler(ss);
|
||||
handler.edit(1, tags);
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("weird input throws errors - malformed lines")
|
||||
{
|
||||
Tags tags;
|
||||
std::stringstream ss;
|
||||
ss << "tag huh\n";
|
||||
REQUIRE_THROWS({
|
||||
ImportTagsHandler handler(ss);
|
||||
handler.edit(1, tags);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user