Allow reading and appending of more complex types

This commit makes sdbusplus compatible with most containers that meet
a few requirements.  This includes:
std::unordered_map
std::array
std::set
boost::flat_set
boost::flat_map

Read requires a container to support emplace or emplace_back methods.
Append requires a container to suport a const iterator

Tested: The top level OpenBMC compiles properly, and the sdbusplus
unit tests compile and pass, and unit tests have been updated with a
few new types to ensure we see any breakages.

Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Change-Id: I5eb1cf7dc07bacc7aca62d87844794223ad4de80
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/test/message/read.cpp b/test/message/read.cpp
index 8c2c4ea..cd31b61 100644
--- a/test/message/read.cpp
+++ b/test/message/read.cpp
@@ -2,6 +2,8 @@
 #include <cassert>
 #include <sdbusplus/message.hpp>
 #include <sdbusplus/bus.hpp>
+#include <unordered_map>
+#include <set>
 
 // Global to share the dbus type string between client and server.
 static std::string verifyTypeString;
@@ -304,6 +306,60 @@
         b.call_noreply(m);
     }
 
+    // Test unordered_map.
+    {
+        auto m = newMethodCall__test(b);
+        std::unordered_map<std::string, int> s = {{"asdf", 3}, {"jkl;", 4}};
+        m.append(1, s, 2);
+        verifyTypeString = "ia{si}i";
+
+        struct verify
+        {
+            static void op(sdbusplus::message::message& m)
+            {
+                int32_t a = 0, b = 0;
+                std::unordered_map<std::string, int> s{};
+
+                m.read(a, s, b);
+                assert(a == 1);
+                assert(s.size() == 2);
+                assert(s["asdf"] == 3);
+                assert(s["jkl;"] == 4);
+                assert(b == 2);
+            }
+        };
+        verifyCallback = &verify::op;
+
+        b.call_noreply(m);
+    }
+
+    // Test set.
+    {
+        auto m = newMethodCall__test(b);
+        std::set<std::string> s = {{"asdf"}, {"jkl;"}};
+        m.append(1, s, 2);
+        verifyTypeString = "iasi";
+
+        struct verify
+        {
+            static void op(sdbusplus::message::message& m)
+            {
+                int32_t a = 0, b = 0;
+                std::set<std::string> s{};
+
+                m.read(a, s, b);
+                assert(a == 1);
+                assert(s.size() == 2);
+                assert(s.find("asdf") != s.end());
+                assert(s.find("jkl;") != s.end());
+                assert(b == 2);
+            }
+        };
+        verifyCallback = &verify::op;
+
+        b.call_noreply(m);
+    }
+
     // Test tuple.
     {
         auto m = newMethodCall__test(b);