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/append.cpp b/test/message/append.cpp
index 7782f02..c56402a 100644
--- a/test/message/append.cpp
+++ b/test/message/append.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;
@@ -384,6 +386,139 @@
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(sd_bus_message* m)
+ {
+ int32_t a = 0;
+ sd_bus_message_read(m, "i", &a);
+ assert(a == 1);
+
+ auto rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY,
+ "{si}");
+ assert(0 <= rc);
+
+ rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY,
+ "si");
+ assert(0 <= rc);
+
+ const char* s = nullptr;
+ sd_bus_message_read_basic(m, 's', &s);
+ sd_bus_message_read_basic(m, 'i', &a);
+ assert((0 == strcmp("asdf", s) && a == 3) ||
+ (a = 4 && 0 == strcmp("jkl;", s)));
+
+ assert(1 == sd_bus_message_at_end(m, false));
+ sd_bus_message_exit_container(m);
+
+ rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY,
+ "si");
+ assert(0 <= rc);
+
+ sd_bus_message_read_basic(m, 's', &s);
+ sd_bus_message_read_basic(m, 'i', &a);
+ assert((0 == strcmp("asdf", s) && a == 3) ||
+ (a = 4 && 0 == strcmp("jkl;", s)));
+
+ assert(1 == sd_bus_message_at_end(m, false));
+ sd_bus_message_exit_container(m);
+
+ assert(1 == sd_bus_message_at_end(m, false));
+ sd_bus_message_exit_container(m);
+
+ sd_bus_message_read(m, "i", &a);
+ assert(a == 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(sd_bus_message* m)
+ {
+ int32_t a = 0;
+ sd_bus_message_read(m, "i", &a);
+ assert(a == 1);
+
+ auto rc =
+ sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
+ assert(0 <= rc);
+
+ const char* s = nullptr;
+ sd_bus_message_read_basic(m, 's', &s);
+ assert(0 == strcmp("asdf", s));
+
+ sd_bus_message_read_basic(m, 's', &s);
+ assert(0 == strcmp("jkl;", s));
+
+ assert(1 == sd_bus_message_at_end(m, false));
+ sd_bus_message_exit_container(m);
+
+ sd_bus_message_read(m, "i", &a);
+ assert(a == 2);
+ }
+ };
+ verifyCallback = &verify::op;
+
+ b.call_noreply(m);
+ }
+
+ // Test array.
+ {
+ auto m = newMethodCall__test(b);
+ std::array<std::string, 3> s{"1", "2", "3"};
+ m.append(1, s, 2);
+ verifyTypeString = "iasi";
+
+ struct verify
+ {
+ static void op(sd_bus_message* m)
+ {
+ int32_t a = 0;
+ sd_bus_message_read(m, "i", &a);
+ assert(a == 1);
+
+ auto rc =
+ sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
+ assert(0 <= rc);
+
+ const char* s = nullptr;
+ sd_bus_message_read_basic(m, 's', &s);
+ assert(0 == strcmp("1", s));
+ sd_bus_message_read_basic(m, 's', &s);
+ assert(0 == strcmp("2", s));
+ sd_bus_message_read_basic(m, 's', &s);
+ assert(0 == strcmp("3", s));
+ assert(1 == sd_bus_message_at_end(m, false));
+
+ sd_bus_message_exit_container(m);
+
+ sd_bus_message_read(m, "i", &a);
+ assert(a == 2);
+ }
+ };
+ verifyCallback = &verify::op;
+
+ b.call_noreply(m);
+ }
+
// Test tuple.
{
auto m = newMethodCall__test(b);
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);