#ifndef LTTNG_ACTION_LIST_INTERNAL_H
#define LTTNG_ACTION_LIST_INTERNAL_H
+#include <common/container-wrapper.hpp>
+#include <common/exception.hpp>
+#include <common/format.hpp>
#include <common/macros.hpp>
-#include <lttng/lttng-error.h>
+#include <lttng/lttng.h>
#include <assert.h>
#include <sys/types.h>
const struct mi_lttng_error_query_callbacks *error_query_callbacks,
struct lttng_dynamic_array *action_path_indexes);
-#define for_each_action_const(__action_element, __action_list) \
- assert(lttng_action_get_type(__action_list) == LTTNG_ACTION_TYPE_LIST); \
- \
- for (unsigned int __action_idx = 0; \
- (__action_element = lttng_action_list_get_at_index(__action_list, __action_idx)); \
- __action_idx++)
-
-#define for_each_action_mutable(__action_element, __action_list) \
- assert(lttng_action_get_type(__action_list) == LTTNG_ACTION_TYPE_LIST); \
- \
- for (unsigned int __action_idx = 0; \
- (__action_element = \
- lttng_action_list_borrow_mutable_at_index(__action_list, __action_idx)); \
- __action_idx++)
+namespace lttng {
+namespace ctl {
+namespace details {
+class action_list_operations {
+public:
+ static lttng_action *get(const lttng_action *list, std::size_t index) noexcept
+ {
+ return lttng_action_list_borrow_mutable_at_index(list, index);
+ }
+
+ static std::size_t size(const lttng_action *list)
+ {
+ unsigned int count;
+ const auto status = lttng_action_list_get_count(list, &count);
+
+ if (status != LTTNG_ACTION_STATUS_OK) {
+ LTTNG_THROW_INVALID_ARGUMENT_ERROR(
+ "Failed to get action list element count");
+ }
+
+ return count;
+ }
+};
+
+class const_action_list_operations {
+public:
+ static const lttng_action *get(const lttng_action *list, std::size_t index) noexcept
+ {
+ return lttng_action_list_get_at_index(list, index);
+ }
+
+ static std::size_t size(const lttng_action *list)
+ {
+ return action_list_operations::size(list);
+ }
+};
+} /* namespace details */
+
+using action_list_view = utils::random_access_container_wrapper<const lttng_action *,
+ lttng_action *,
+ details::action_list_operations>;
+
+using const_action_list_view =
+ utils::random_access_container_wrapper<const lttng_action *,
+ const lttng_action *,
+ details::const_action_list_operations>;
+
+} /* namespace ctl */
+} /* namespace lttng */
#endif /* LTTNG_ACTION_LIST_INTERNAL_H */
LTTNG_ASSERT(subitems);
if (type == LTTNG_ACTION_TYPE_LIST) {
- struct lttng_action *inner_action = NULL;
-
- for_each_action_mutable (inner_action, action) {
+ for (auto inner_action : lttng::ctl::action_list_view(action)) {
LTTNG_ASSERT(inner_action);
ret = add_action_to_subitem_array(inner_action, subitems);
{
bool is_notify = false;
const struct lttng_action *action = lttng_trigger_get_const_action(trigger);
- const struct lttng_action *inner_action;
enum lttng_action_type action_type;
LTTNG_ASSERT(action);
goto end;
}
- for_each_action_const (inner_action, action) {
+ for (auto inner_action : lttng::ctl::const_action_list_view(action)) {
if (lttng_action_get_type(inner_action) == LTTNG_ACTION_TYPE_NOTIFY) {
is_notify = true;
goto end;
action = lttng_trigger_get_const_action(trigger);
action_type = lttng_action_get_type(action);
if (action_type == LTTNG_ACTION_TYPE_LIST) {
- const struct lttng_action *subaction;
uint64_t action_path_index = 0;
MSG(" actions:");
- for_each_action_const (subaction, action) {
+ for (auto subaction : lttng::ctl::const_action_list_view(action)) {
_MSG(" ");
print_one_action(trigger, subaction, &action_path_index, 1);
action_path_index++;
conditions/event-rule-matches.cpp \
conditions/session-consumed-size.cpp \
conditions/session-rotation.cpp \
+ container-wrapper.hpp \
credentials.cpp credentials.hpp \
defaults.cpp \
domain.cpp \
--- /dev/null
+/*
+ * Copyright (C) 2023 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_CONTAINER_WRAPPER_H
+#define LTTNG_CONTAINER_WRAPPER_H
+
+#include <common/macros.hpp>
+
+#include <cstddef>
+#include <iterator>
+
+namespace lttng {
+namespace utils {
+
+/*
+ * random_access_container_wrapper is a helper to provide an idiomatic C++ interface
+ * from a C container API. ElementAccessorCallable and ElementCountAccessorCallable
+ * are two functors which must be provided to allow access to the underlying elements
+ * of the container and to its size.
+ */
+template <typename ContainerType, typename ElementType, typename ContainerOperations>
+class random_access_container_wrapper {
+ class _iterator : public std::iterator<std::random_access_iterator_tag, std::size_t> {
+ public:
+ explicit _iterator(const random_access_container_wrapper& container,
+ std::size_t start_index = 0) :
+ _container(container), _index(start_index)
+ {
+ }
+
+ _iterator& operator++() noexcept
+ {
+ ++_index;
+ return *this;
+ }
+
+ _iterator& operator--() noexcept
+ {
+ --_index;
+ return *this;
+ }
+
+ _iterator& operator++(int) noexcept
+ {
+ auto this_before_increment = *this;
+
+ _index++;
+ return this_before_increment;
+ }
+
+ _iterator& operator--(int) noexcept
+ {
+ _index--;
+ return *this;
+ }
+
+ bool operator==(const _iterator& other) const noexcept
+ {
+ return _index == other._index;
+ }
+
+ bool operator!=(const _iterator& other) const noexcept
+ {
+ return !(*this == other);
+ }
+
+ typename std::conditional<std::is_pointer<ElementType>::value,
+ ElementType,
+ ElementType&>::type
+ operator*() const noexcept
+ {
+ return _container[_index];
+ }
+
+ private:
+ const random_access_container_wrapper& _container;
+ std::size_t _index;
+ };
+
+ using iterator = _iterator;
+
+public:
+ explicit random_access_container_wrapper(ContainerType container) : _container{ container }
+ {
+ }
+
+ iterator begin() noexcept
+ {
+ return iterator(*this);
+ }
+
+ iterator end() noexcept
+ {
+ return iterator(*this, ContainerOperations::size(_container));
+ }
+
+ std::size_t size() const noexcept
+ {
+ return ContainerOperations::size(_container);
+ }
+
+ typename std::conditional<std::is_pointer<ElementType>::value, ElementType, ElementType&>::type
+ operator[](std::size_t index)
+ {
+ LTTNG_ASSERT(index < ContainerOperations::size(_container));
+ return ContainerOperations::get(_container, index);
+ }
+
+ typename std::conditional<std::is_pointer<ElementType>::value,
+ const ElementType,
+ const ElementType&>::type
+ operator[](std::size_t index) const
+ {
+ LTTNG_ASSERT(index < ContainerOperations::size(_container));
+ return ContainerOperations::get(_container, index);
+ }
+
+private:
+ ContainerType _container;
+};
+} /* namespace utils */
+} /* namespace lttng */
+
+#endif /* LTTNG_CONTAINER_WRAPPER_H */
AM_CPPFLAGS += -I$(srcdir) -I$(top_srcdir)/tests/utils
LIBLTTNG_CTL=$(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la
+LIBCOMMON_LGPL=$(top_builddir)/src/common/libcommon-lgpl.la
noinst_PROGRAMS = \
notification-client \
register-some-triggers
notification_client_SOURCES = notification-client.cpp
-notification_client_LDADD = $(LIBLTTNG_CTL) \
+notification_client_LDADD = $(LIBLTTNG_CTL) $(LIBCOMMON_LGPL) \
$(top_builddir)/tests/utils/libtestutils.la
register_some_triggers_SOURCES = register-some-triggers.cpp
static bool action_list_contains_notify(const struct lttng_action *action_list)
{
- const struct lttng_action *sub_action;
-
- for_each_action_const (sub_action, action_list) {
+ for (auto sub_action : lttng::ctl::const_action_list_view(action_list)) {
if (lttng_action_get_type(sub_action) == LTTNG_ACTION_TYPE_NOTIFY) {
return true;
}
}
+
return false;
}
{
int ret, action_idx;
struct lttng_action *list_action = NULL, *list_action_from_buffer = NULL,
- *mut_inner_action = NULL, *stop_session_action = NULL,
- *notify_action = NULL, *start_session_action = NULL;
- const struct lttng_action *const_inner_action;
+ *stop_session_action = NULL, *notify_action = NULL,
+ *start_session_action = NULL;
struct lttng_payload payload;
lttng_payload_init(&payload);
"Serialized and de-serialized list action are equal");
action_idx = 0;
- for_each_action_const (const_inner_action, list_action) {
- enum lttng_action_type inner_action_type =
- lttng_action_get_type(const_inner_action);
+ for (auto action : lttng::ctl::const_action_list_view(list_action)) {
+ enum lttng_action_type inner_action_type = lttng_action_get_type(action);
switch (action_idx) {
case 0:
ok(inner_action_type == LTTNG_ACTION_TYPE_START_SESSION,
}
action_idx = 0;
- for_each_action_mutable (mut_inner_action, list_action) {
- enum lttng_action_type inner_action_type = lttng_action_get_type(mut_inner_action);
+ for (auto action : lttng::ctl::action_list_view(list_action)) {
+ enum lttng_action_type inner_action_type = lttng_action_get_type(action);
switch (action_idx) {
case 0:
ok(inner_action_type == LTTNG_ACTION_TYPE_START_SESSION,