tagfile: Support mapped containers, similar to a sparse array
Note: This now treats vector<pair> as a mapped container as well – an ordered multimap, so to speak
This commit is contained in:
@@ -44,6 +44,12 @@ namespace detail {
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct is_container<std::string> : std::false_type {};
|
struct is_container<std::string> : std::false_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_pair : public std::false_type {};
|
||||||
|
|
||||||
|
template<typename A, typename B>
|
||||||
|
struct is_pair<std::pair<A, B>> : public std::true_type {};
|
||||||
}
|
}
|
||||||
|
|
||||||
class cTagFile;
|
class cTagFile;
|
||||||
@@ -286,7 +292,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
void extractSparse(Container& values, typename Container::value_type def = typename Container::value_type()) const {
|
typename std::enable_if<!detail::is_pair<typename Container::value_type>::value>::type
|
||||||
|
extractSparse(Container& values, typename Container::value_type def = typename Container::value_type()) const {
|
||||||
using T = typename Container::value_type;
|
using T = typename Container::value_type;
|
||||||
values.clear();
|
values.clear();
|
||||||
for(size_t n = 0; n < tags.size(); n++) {
|
for(size_t n = 0; n < tags.size(); n++) {
|
||||||
@@ -298,7 +305,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
void encodeSparse(const Container& values, typename Container::value_type def = typename Container::value_type()) {
|
typename std::enable_if<!detail::is_pair<typename Container::value_type>::value>::type
|
||||||
|
encodeSparse(const Container& values, typename Container::value_type def = typename Container::value_type()) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for(const auto& value : values) {
|
for(const auto& value : values) {
|
||||||
if(value != def) {
|
if(value != def) {
|
||||||
@@ -307,6 +315,29 @@ public:
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename Container>
|
||||||
|
typename std::enable_if<detail::is_pair<typename Container::value_type>::value>::type
|
||||||
|
extractSparse(Container& values) const {
|
||||||
|
using T = std::pair<
|
||||||
|
typename std::remove_cv<typename Container::value_type::first_type>::type,
|
||||||
|
typename Container::value_type::second_type
|
||||||
|
>;
|
||||||
|
values.clear();
|
||||||
|
for(size_t n = 0; n < tags.size(); n++) {
|
||||||
|
T value;
|
||||||
|
*this >> value.first >> value.second;
|
||||||
|
values.insert(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
typename std::enable_if<detail::is_pair<typename Container::value_type>::value>::type
|
||||||
|
encodeSparse(const Container& values, typename Container::value_type::second_type def = typename Container::value_type::second_type()) {
|
||||||
|
for(const auto& value : values) {
|
||||||
|
if(value.second != def) {
|
||||||
|
*this << value.first << value.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void extract(vector2d<T>& values) const {
|
void extract(vector2d<T>& values) const {
|
||||||
values.resize(0, tags.size());
|
values.resize(0, tags.size());
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ TEST_CASE("Complex tag file") {
|
|||||||
"SDF 0 0 12\n"
|
"SDF 0 0 12\n"
|
||||||
"SDF 1 3 52\n"
|
"SDF 1 3 52\n"
|
||||||
"SDF 5 9 81\n"
|
"SDF 5 9 81\n"
|
||||||
|
"DICT 'a b' 'c d'\n"
|
||||||
|
"DICT abc def\n"
|
||||||
|
"DICT blah blah\n"
|
||||||
|
"DICT foo bar\n"
|
||||||
// Page 4 and onward, a series of identical pages
|
// Page 4 and onward, a series of identical pages
|
||||||
"\f"
|
"\f"
|
||||||
"ID 12\n"
|
"ID 12\n"
|
||||||
@@ -145,6 +149,13 @@ TEST_CASE("Complex tag file") {
|
|||||||
sdf[1][3] = 52;
|
sdf[1][3] = 52;
|
||||||
sdf[5][9] = 81;
|
sdf[5][9] = 81;
|
||||||
p3["SDF"].encodeSparse(sdf);
|
p3["SDF"].encodeSparse(sdf);
|
||||||
|
std::map<std::string, std::string> dict{
|
||||||
|
{"foo", "bar"},
|
||||||
|
{"a b", "c d"},
|
||||||
|
{"abc", "def"},
|
||||||
|
{"blah", "blah"},
|
||||||
|
};
|
||||||
|
p3["DICT"].encodeSparse(dict);
|
||||||
auto& p4a = content.add();
|
auto& p4a = content.add();
|
||||||
p4a["ID"] << '\x0c';
|
p4a["ID"] << '\x0c';
|
||||||
p4a["VALUE"] << 400;
|
p4a["VALUE"] << 400;
|
||||||
@@ -274,6 +285,17 @@ TEST_CASE("Complex tag file") {
|
|||||||
CHECK(sdf[x][y] == 0);
|
CHECK(sdf[x][y] == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::map<std::string, std::string> dict;
|
||||||
|
page["DICT"].extractSparse(dict);
|
||||||
|
REQUIRE(dict.size() == 4);
|
||||||
|
CHECK(dict.count("foo") == 1);
|
||||||
|
CHECK(dict["foo"] == "bar");
|
||||||
|
CHECK(dict.count("a b") == 1);
|
||||||
|
CHECK(dict["a b"] == "c d");
|
||||||
|
CHECK(dict.count("abc") == 1);
|
||||||
|
CHECK(dict["abc"] == "def");
|
||||||
|
CHECK(dict.count("blah") == 1);
|
||||||
|
CHECK(dict["blah"] == "blah");
|
||||||
} else {
|
} else {
|
||||||
p4++;
|
p4++;
|
||||||
char id;
|
char id;
|
||||||
|
|||||||
Reference in New Issue
Block a user