[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master d385546 10/12: Serialize associative-pair con
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master d385546 10/12: Serialize associative-pair containers to and from xml |
Date: |
Sat, 24 Oct 2020 16:51:36 -0400 (EDT) |
branch: master
commit d385546a4cebf2424a3f47b0bbbdf859947613d6
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Serialize associative-pair containers to and from xml
---
xml_serialize.hpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++++--
xml_serialize_test.cpp | 38 +++++++++++++++++++++++---
2 files changed, 106 insertions(+), 5 deletions(-)
diff --git a/xml_serialize.hpp b/xml_serialize.hpp
index 49d1822..7b1e36e 100644
--- a/xml_serialize.hpp
+++ b/xml_serialize.hpp
@@ -31,8 +31,10 @@
#include <xmlwrapp/nodes_view.h>
+#include <map>
#include <string>
#include <type_traits>
+#include <unordered_map>
#include <utility> // pair
#include <vector>
@@ -122,8 +124,8 @@ struct xml_io<std::pair<T1,T2>>
/// (and non-element nodes) that might have been added manually,
/// e.g., as documentation.
///
-/// C++11 has no way to assert that C is a Sequence; for the nonce,
-/// no other Sequence being used, assert that it's a vector.
+/// C++17 has no assertable "SequenceContainer" concept; for the
+/// nonce, no other Sequence being used, assert that C is a vector.
template<typename C>
struct xml_sequence_io
@@ -162,6 +164,73 @@ struct xml_io<std::vector<T>>
:public xml_sequence_io<std::vector<T>>
{};
+/// Serialization for associative-pair containers.
+///
+/// Derive publicly from this to use its implementation when
+/// specializing class template xml_io for a particular sequence.
+///
+/// from_xml() reads only <item> elements, ignoring other elements
+/// (and non-element nodes) that might have been added manually,
+/// e.g., as documentation.
+///
+/// C++ calls std::set and its brethren "associative", even though
+/// they associate a key with...nothing. This implementation is for
+/// containers that associate a key with something. C++20 has no
+/// Concept for this; for the nonce, assert that it's a std::map or
+/// a std::unordered_map.
+
+template<typename C>
+struct xml_pair_container_io
+{
+ using K = typename C::key_type;
+ using T = typename C::mapped_type;
+ // A key value cannot be read into 'K const'; therefore,
+ // 'V' is not the same as 'C::value_type', which is:
+ // std::pair<K const, T>
+ using V = std::pair<K,T>;
+
+ static_assert
+ ( std::is_same<C,std::map<K,T>>::value
+ || std::is_same<C,std::unordered_map<K,T>>::value
+ );
+
+ static void to_xml(xml::element& parent, C const& c)
+ {
+ parent.clear();
+ for(auto const& i : c)
+ {
+ // This is not equivalent to calling set_element():
+ // multiple <item> elements are expressly permitted.
+ xml::element e("item");
+ xml_io<V>::to_xml(e, i);
+ parent.push_back(e);
+ }
+ }
+
+ static void from_xml(xml::element const& parent, C& c)
+ {
+ c.clear();
+ // It would be good to call std::unordered_map::reserve()
+ // upstream if the number of elements is known.
+ for(auto const& i : parent.elements("item"))
+ {
+ V v;
+ xml_io<V>::from_xml(i, v);
+ c.insert(v);
+ }
+ }
+};
+
+template<typename K, typename T>
+struct xml_io<std::map<K,T>>
+ :public xml_pair_container_io<std::map<K,T>>
+{};
+
+template<typename K, typename T>
+struct xml_io<std::unordered_map<K,T>>
+ :public xml_pair_container_io<std::unordered_map<K,T>>
+{};
+
/// Serialize a datum into a subelement of the given xml element.
///
/// Precondition: parent has no element with the given tagname.
diff --git a/xml_serialize_test.cpp b/xml_serialize_test.cpp
index d5f79fe..cb66919 100644
--- a/xml_serialize_test.cpp
+++ b/xml_serialize_test.cpp
@@ -27,11 +27,14 @@
#include "test_tools.hpp"
#include "timer.hpp"
+#include <map>
#include <string>
+#include <unordered_map>
#include <utility> // pair
#include <vector>
-// All /write.*/ functions save xml to this string.
+// All /write.*/ functions save xml to this string, and
+// all /read.*/ functions read from it.
std::string dom_string;
@@ -39,18 +42,25 @@ std::string dom_string;
int const number_of_elements = 20;
-// /[dsv]0/: constant values for /write.*/ functions.
-// /[dsv]1/: variables for /read.*/ functions.
+using omap = std:: map<std::string, float>;
+using umap = std::unordered_map<int , float>;
+
+// /[dspvou]0/: constant values for /write.*/ functions.
+// /[dspvou]1/: variables for /read.*/ functions.
double const d0(2.718281828459045235360);
std::string const s0("string with ampersand & embedded spaces");
std::pair<int,int> const p0 {17, 19};
std::vector<int> const v0 {10, 2, 4}; // Be a pepper...
+omap const o0 {{"a", 1.1f}, {"b", 2.2f}, {"c", 3.3f}};
+umap const u0 {{1, 101.01f}, {2, 202.02f}, {3, 303.03f}};
double d1;
std::string s1;
std::pair<int,int> p1;
std::vector<int> v1;
+omap o1;
+umap u1;
void write()
{
@@ -60,6 +70,8 @@ void write()
xml_serialize::set_element(root, "s", s0);
xml_serialize::set_element(root, "p", p0);
xml_serialize::set_element(root, "v", v0);
+ xml_serialize::set_element(root, "o", o0);
+ xml_serialize::set_element(root, "u", u0);
dom_string = document.str();
}
@@ -71,6 +83,8 @@ void read()
xml_serialize::get_element(root, "s", s1);
xml_serialize::get_element(root, "p", p1);
xml_serialize::get_element(root, "v", v1);
+ xml_serialize::get_element(root, "o", o1);
+ xml_serialize::get_element(root, "u", u1);
}
void write_erroneous()
@@ -91,6 +105,8 @@ void read_erroneous()
xml_serialize::get_element(root, "s", s1);
xml_serialize::get_element(root, "p", p1);
xml_serialize::get_element(root, "v", v1);
+ xml_serialize::get_element(root, "o", o1);
+ xml_serialize::get_element(root, "u", u1);
xml_serialize::get_element(root, "f", f1); // Error: no <f> element.
}
@@ -152,6 +168,12 @@ void mete_read_p() {mete_read ("p", p1);}
void mete_write_v() {mete_write("v", v0);}
void mete_read_v() {mete_read ("v", v1);}
+void mete_write_o() {mete_write("o", o0);}
+void mete_read_o() {mete_read ("o", o1);}
+
+void mete_write_u() {mete_write("u", u0);}
+void mete_read_u() {mete_read ("u", u1);}
+
int test_main(int, char*[])
{
write();
@@ -179,6 +201,12 @@ int test_main(int, char*[])
BOOST_TEST(v0 == v1);
BOOST_TEST_EQUAL(v0.size(), v1.size());
+ BOOST_TEST(o0 == o1);
+ BOOST_TEST_EQUAL(o0.size(), o1.size());
+
+ BOOST_TEST(u0 == u1);
+ BOOST_TEST_EQUAL(u0.size(), u1.size());
+
std::string found
("Assertion 'parent.end() == parent.find(name.c_str())' failed."
);
@@ -198,6 +226,10 @@ int test_main(int, char*[])
std::cout << " Read p : " << TimeAnAliquot(mete_read_p ) << '\n';
std::cout << " Write v : " << TimeAnAliquot(mete_write_v) << '\n';
std::cout << " Read v : " << TimeAnAliquot(mete_read_v ) << '\n';
+ std::cout << " Write o : " << TimeAnAliquot(mete_write_o) << '\n';
+ std::cout << " Read o : " << TimeAnAliquot(mete_read_o ) << '\n';
+ std::cout << " Write u : " << TimeAnAliquot(mete_write_u) << '\n';
+ std::cout << " Read u : " << TimeAnAliquot(mete_read_u ) << '\n';
std::cout << std::endl;
return 0;
- [lmi-commits] [lmi] master updated (61277aa -> 4427d76), Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master 65f92f3 06/12: Refactor, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master 75399fe 01/12: Improve documentation, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master be4c0fd 05/12: Rename 'mete_*' functions for concinnity, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master d71f9e8 02/12: Improve parameter names, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master 9671a72 03/12: Rearrange for concinnity, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master 195d544 07/12: Improve explanation of certain unit tests, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master fdb2a62 04/12: Clarify unit-test output, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master 75cf29b 08/12: Rename local variables, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master fb65723 09/12: Serialize pairs to and from xml, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master d385546 10/12: Serialize associative-pair containers to and from xml,
Greg Chicares <=
- [lmi-commits] [lmi] master 2ba9033 11/12: Improve a variable's name, Greg Chicares, 2020/10/24
- [lmi-commits] [lmi] master 4427d76 12/12: C++17-ize, Greg Chicares, 2020/10/24