sdbus++: events: generate exception constructors
Generate constructors for exceptions using the listed metadata.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I99dc912e4ad0746a14d3053a5653327ae12440dd
diff --git a/include/sdbusplus/utility/consteval_string.hpp b/include/sdbusplus/utility/consteval_string.hpp
new file mode 100644
index 0000000..fbb67b4
--- /dev/null
+++ b/include/sdbusplus/utility/consteval_string.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <algorithm>
+#include <cstdint>
+
+namespace sdbusplus::utility
+{
+namespace details
+{
+
+template <std::size_t N>
+struct consteval_string_holder
+{
+ char value[N] = {};
+
+ consteval consteval_string_holder(const char (&str)[N])
+ {
+ std::ranges::copy(str, value);
+ }
+};
+
+} // namespace details
+
+/** Type to allow compile-time parameter string comparisons.
+ *
+ * Example:
+ * void foo(consteval_string<"FOO">);
+ *
+ * If the function is not called with foo("FOO"), it will be a compile error.
+ */
+template <details::consteval_string_holder V>
+struct consteval_string
+{
+ std::string_view value;
+
+ template <typename T>
+ consteval consteval_string(const T& s) : value(s)
+ {
+ if (value != V.value)
+ {
+ report_error("String mismatch; check parameter name.");
+ }
+ }
+
+ // This is not a real function but used to trigger compile errors due to
+ // calling a non-constexpr function in a constexpr context.
+ static void report_error(const char*);
+};
+
+} // namespace sdbusplus::utility
diff --git a/tools/sdbusplus/event.py b/tools/sdbusplus/event.py
index 84fda77..03137c5 100644
--- a/tools/sdbusplus/event.py
+++ b/tools/sdbusplus/event.py
@@ -4,12 +4,12 @@
import yaml
from .namedelement import NamedElement
+from .property import Property
from .renderer import Renderer
-class EventMetadata(NamedElement):
+class EventMetadata(Property):
def __init__(self, **kwargs):
- self.type = kwargs.pop("type")
self.primary = kwargs.pop("primary", False)
super(EventMetadata, self).__init__(**kwargs)
@@ -47,6 +47,12 @@
super(EventElement, self).__init__(**kwargs)
+ def cpp_includes(self, interface):
+ includes = []
+ for m in self.metadata:
+ includes.extend(m.enum_headers(interface))
+ return sorted(set(includes))
+
def __getattribute__(self, name):
lam = {"description": lambda: self.__description()}.get(name)
@@ -115,6 +121,14 @@
super(Event, self).__init__(**kwargs)
+ def cpp_includes(self):
+ includes = []
+ for e in self.errors:
+ includes.extend(e.cpp_includes(self.name))
+ for e in self.events:
+ includes.extend(e.cpp_includes(self.name))
+ return sorted(set(includes))
+
def markdown(self, loader):
return self.render(loader, "events.md.mako", events=self)
diff --git a/tools/sdbusplus/interface.py b/tools/sdbusplus/interface.py
index eade1de..0e3d3e5 100644
--- a/tools/sdbusplus/interface.py
+++ b/tools/sdbusplus/interface.py
@@ -65,7 +65,7 @@
def enum_includes(self, inc_list):
includes = []
for e in inc_list:
- includes.extend(e.enum_headers(self.name))
+ includes.extend(e.enum_headers())
return sorted(set(includes))
def markdown(self, loader):
diff --git a/tools/sdbusplus/property.py b/tools/sdbusplus/property.py
index 63d7282..898aa28 100644
--- a/tools/sdbusplus/property.py
+++ b/tools/sdbusplus/property.py
@@ -112,19 +112,22 @@
""" Determine the C++ header of an enumeration-type property.
"""
- def enum_headers(self, interface):
+ def enum_headers(self, interface=None):
typeTuple = self.__type_tuple()
- return self.__enum_headers(interface, typeTuple)
+ return self.__enum_headers(typeTuple, interface)
- def __enum_headers(self, interface, typeTuple):
+ def __enum_headers(self, typeTuple, interface=None):
# Enums can be processed directly.
if "enum" == typeTuple[0]:
# Get enum type from typeTuple.
enumType = typeTuple[1][0][0]
- # Local enums don't need a header.
+ # Local enums don't need a header, unless interface is provided.
if "self." in enumType:
- return []
+ if interface:
+ enumType = enumType.replace("self.", interface + ".")
+ else:
+ return []
enumType = ".".join(enumType.split(".")[0:-1])
return [NamedElement(name=enumType).headerFile()]
@@ -138,7 +141,7 @@
# them recursively.
r = []
for t in typeTuple[1]:
- r.extend(self.__enum_headers(interface, t))
+ r.extend(self.__enum_headers(t, interface))
return r
""" Convert the property type into a C++ type.
diff --git a/tools/sdbusplus/templates/event.hpp.mako b/tools/sdbusplus/templates/event.hpp.mako
index 78a31d9..674c9dc 100644
--- a/tools/sdbusplus/templates/event.hpp.mako
+++ b/tools/sdbusplus/templates/event.hpp.mako
@@ -9,4 +9,19 @@
"${events.name}.${event.name}: ${event.description}";
static constexpr auto errErrno = ${event.errno};
+
+%if len(event.metadata) > 0:
+ ${event.CamelCase}() = delete;
+ ${event.CamelCase}(
+ ${", ".join([
+ f"utility::consteval_string<\"{m.SNAKE_CASE}\">, {m.cppTypeParam(events.name)} {m.camelCase}_"
+ for m in event.metadata ])}) :
+ ${", ".join([
+ f"{m.camelCase}({m.camelCase}_)" for m in event.metadata ])}
+ {}
+
+%for m in event.metadata:
+ ${m.cppTypeParam(events.name)} ${m.camelCase};
+%endfor
+%endif
};
diff --git a/tools/sdbusplus/templates/event.md.mako b/tools/sdbusplus/templates/event.md.mako
index de6a69b..9cbf44d 100644
--- a/tools/sdbusplus/templates/event.md.mako
+++ b/tools/sdbusplus/templates/event.md.mako
@@ -15,7 +15,7 @@
% if event.metadata:
- metadata:
% for m in event.metadata:
- - `${m.SNAKE_CASE}` as `${m.type}` \
+ - `${m.SNAKE_CASE}` as `${m.typeName}` \
% if m.primary:
**[PRIMARY]**
% else:
diff --git a/tools/sdbusplus/templates/events.hpp.mako b/tools/sdbusplus/templates/events.hpp.mako
index 434cc0b..c2e945c 100644
--- a/tools/sdbusplus/templates/events.hpp.mako
+++ b/tools/sdbusplus/templates/events.hpp.mako
@@ -3,9 +3,13 @@
*/
#pragma once
#include <sdbusplus/exception.hpp>
+#include <sdbusplus/utility/consteval_string.hpp>
#include <cerrno>
+% for h in events.cpp_includes():
+#include <${h}>
+% endfor
%if events.errors:
namespace sdbusplus::error::${events.cppNamespacedClass()}