summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2025-07-25 22:59:30 +0200
committerFelix Morgner <felix.morgner@gmail.com>2025-07-25 22:59:30 +0200
commitd734f1e7803a756822524e0580ec8e9c93b821c6 (patch)
tree28daa14da0ec330adaa87f1316167cf18274cfe4 /lib
parentfb2fbeca028d7a854df1c4b23bd0395d11e1f724 (diff)
downloadturns-d734f1e7803a756822524e0580ec8e9c93b821c6.tar.xz
turns-d734f1e7803a756822524e0580ec8e9c93b821c6.zip
lib: make Turns.Participant comparablemain
Diffstat (limited to 'lib')
-rw-r--r--lib/include/turns-participant.h14
-rw-r--r--lib/include/turnsmm/participant.hpp10
-rw-r--r--lib/src/turns-participant.c17
-rw-r--r--lib/src/turns-turn-order.c37
-rw-r--r--lib/src/turnsmm/participant.cpp12
-rw-r--r--lib/tests/turns-participant.cpp47
-rw-r--r--lib/tests/turnsmm/participant.cpp47
7 files changed, 162 insertions, 22 deletions
diff --git a/lib/include/turns-participant.h b/lib/include/turns-participant.h
index 28588a7..695d029 100644
--- a/lib/include/turns-participant.h
+++ b/lib/include/turns-participant.h
@@ -8,6 +8,7 @@
#include <glib-object.h>
#include <glib.h>
+#include <glibconfig.h>
G_BEGIN_DECLS
@@ -66,6 +67,19 @@ TurnsParticipant * turns_participant_new(void);
G_GNUC_WARN_UNUSED_RESULT
TurnsParticipant * turns_participant_new_with(gchar const * name, gfloat priority, TurnsParticipantDisposition disposition);
+
+/**
+ * turns_participant_compare:
+ * @self: A #TurnsParticipant
+ * @other: A #TurnsParticipant
+ *
+ * Compares two participants by priority.
+ *
+ * Returns: a new `TurnsParticipant`
+ */
+G_GNUC_WARN_UNUSED_RESULT
+gint turns_participant_compare(TurnsParticipant const * self, TurnsParticipant const * other);
+
/**
* turns_participant_get_active: (get-property active)
* @self: a participant
diff --git a/lib/include/turnsmm/participant.hpp b/lib/include/turnsmm/participant.hpp
index d7956ab..29ea1fa 100644
--- a/lib/include/turnsmm/participant.hpp
+++ b/lib/include/turnsmm/participant.hpp
@@ -17,6 +17,8 @@
#include <glibmm/refptr.h>
#include <glibmm/ustring.h>
+#include <compare>
+
namespace Turns
{
@@ -45,6 +47,9 @@ namespace Turns
Participant();
Participant(Glib::ustring const & name, float priority, Disposition disposition);
+ auto operator<=>(Participant const & other) const noexcept -> std::strong_ordering;
+ auto operator==(Participant const & other) const noexcept -> bool;
+
[[nodiscard]] auto gobj() noexcept -> BaseObjectType *;
[[nodiscard]] auto gobj() const -> BaseObjectType const *;
[[nodiscard]] auto gobj_copy() noexcept -> BaseObjectType *;
@@ -79,6 +84,11 @@ namespace Turns
explicit Participant(BaseObjectType * gobj);
};
+ auto inline operator<=>(Glib::RefPtr<Participant> const & lhs, Glib::RefPtr<Participant> const & rhs) noexcept -> std::strong_ordering
+ {
+ return *lhs <=> *rhs;
+ }
+
} // namespace Turns
namespace Glib
diff --git a/lib/src/turns-participant.c b/lib/src/turns-participant.c
index c18ae69..38ba0cd 100644
--- a/lib/src/turns-participant.c
+++ b/lib/src/turns-participant.c
@@ -163,6 +163,23 @@ TurnsParticipant * turns_participant_new_with(gchar const * name, gfloat priorit
return TURNS_PARTICIPANT(g_object_new(TURNS_TYPE_PARTICIPANT, "name", name, "priority", priority, "disposition", disposition, nullptr));
}
+gint turns_participant_compare(TurnsParticipant const * self, TurnsParticipant const * other)
+{
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT((GObject *)self), 0);
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT((GObject *)other), 0);
+
+ if (self->priority < other->priority)
+ {
+ return -1;
+ }
+ else if (self->priority > other->priority)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
gboolean turns_participant_get_active(TurnsParticipant const * self)
{
g_return_val_if_fail(TURNS_IS_PARTICIPANT((TurnsParticipant *)self), false);
diff --git a/lib/src/turns-turn-order.c b/lib/src/turns-turn-order.c
index 6a68145..3c04247 100644
--- a/lib/src/turns-turn-order.c
+++ b/lib/src/turns-turn-order.c
@@ -44,35 +44,28 @@ G_DEFINE_FINAL_TYPE_WITH_CODE(TurnsTurnOrder,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL, turns_turn_order_list_model_init))
-static gint compare_participant(void const * lhs, void const * rhs, void * sort_mode)
+static gint compare_participant(void const * lhs, void const * rhs, void * data)
{
- auto left_priority = turns_participant_get_priority(lhs);
- auto right_priority = turns_participant_get_priority(rhs);
+ g_return_val_if_fail(TURNS_IS_TURN_ORDER(data), 0);
- auto result = 0;
+ auto turn_order = TURNS_TURN_ORDER(data);
- if (left_priority < right_priority)
+ switch (turn_order->sort_mode)
{
- result = -1;
- }
- else if (left_priority > right_priority)
- {
- result = 1;
- }
-
- if ((TurnsTurnOrderSortMode)(long long)sort_mode == TURNS_TURN_ORDER_SORT_MODE_DESCENDING)
- {
- return result * -1;
+ case TURNS_TURN_ORDER_SORT_MODE_DESCENDING:
+ return -turns_participant_compare(lhs, rhs);
+ case TURNS_TURN_ORDER_SORT_MODE_ASCENDING:
+ return turns_participant_compare(lhs, rhs);
+ default:
+ g_warning("Invalid sort mode: %d", turn_order->sort_mode);
+ return 0;
}
-
- return result;
}
static void sort_participants(TurnsTurnOrder * self, bool inserting)
{
- auto const sort_mode = turns_turn_order_get_sort_mode(self);
-
- g_ptr_array_sort_values_with_data(self->participants, &compare_participant, (gpointer)sort_mode);
+ g_return_if_fail(TURNS_IS_TURN_ORDER(self));
+ g_ptr_array_sort_values_with_data(self->participants, &compare_participant, self);
if (!inserting)
{
@@ -104,7 +97,7 @@ static void set_running(TurnsTurnOrder * self, gboolean value)
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_RUNNING]);
}
-static void handle_participant_property_changed(TurnsParticipant const *, GParamSpec *, TurnsTurnOrder * self)
+static void handle_priority_changed(TurnsParticipant const *, GParamSpec *, TurnsTurnOrder * self)
{
sort_participants(self, false);
}
@@ -245,7 +238,7 @@ void turns_turn_order_add(TurnsTurnOrder * self, TurnsParticipant * participant)
{
g_return_if_fail(participant != nullptr);
- g_signal_connect(participant, "notify::priority", (GCallback)&handle_participant_property_changed, self);
+ g_signal_connect(participant, "notify::priority", (GCallback)&handle_priority_changed, self);
auto was_empty = turns_turn_order_get_empty(self);
diff --git a/lib/src/turnsmm/participant.cpp b/lib/src/turnsmm/participant.cpp
index 758f062..81b2777 100644
--- a/lib/src/turnsmm/participant.cpp
+++ b/lib/src/turnsmm/participant.cpp
@@ -22,6 +22,7 @@
#include <glibmm/wrap.h>
#include <bit>
+#include <compare>
namespace Turns
{
@@ -84,6 +85,17 @@ namespace Turns
{
}
+ auto Participant::operator<=>(Participant const & other) const noexcept -> std::strong_ordering
+ {
+ auto result = turns_participant_compare(unwrap(this), other.gobj());
+ return result == 0 ? std::strong_ordering::equivalent : (result < 0 ? std::strong_ordering::less : std::strong_ordering::greater);
+ }
+
+ auto Participant::operator==(Participant const & other) const noexcept -> bool
+ {
+ return (*this <=> other) == std::strong_ordering::equivalent;
+ }
+
auto Participant::gobj() noexcept -> BaseObjectType *
{
return std::bit_cast<BaseObjectType *>(gobject_);
diff --git a/lib/tests/turns-participant.cpp b/lib/tests/turns-participant.cpp
index e9cc62e..fc76c4b 100644
--- a/lib/tests/turns-participant.cpp
+++ b/lib/tests/turns-participant.cpp
@@ -550,4 +550,51 @@ SCENARIO("Reading a participant", "[lib][object][data]")
}
}
}
+}
+
+SCENARIO("Comparing two participants", "[lib][object][logic]")
+{
+ auto name_lhs = "LHS";
+ auto name_rhs = "RHS";
+ auto disposition = TurnsParticipantDisposition::TURNS_PARTICIPANT_DISPOSITION_NEUTRAL;
+
+ GIVEN("A participant with priority 0")
+ {
+ g_autoptr(TurnsParticipant) lhs = turns_participant_new_with(name_lhs, 0.0f, disposition);
+
+ THEN("the it compares equal to itself")
+ {
+ REQUIRE(turns_participant_compare(lhs, lhs) == 0);
+ }
+
+ AND_GIVEN("A participant with priority 10")
+ {
+ g_autoptr(TurnsParticipant) rhs = turns_participant_new_with(name_rhs, 10.0f, disposition);
+
+ THEN("the first compares less than the second")
+ {
+ REQUIRE(turns_participant_compare(lhs, rhs) < 0);
+ }
+
+ THEN("the second compares greater than the first")
+ {
+ REQUIRE(turns_participant_compare(rhs, lhs) > 0);
+ }
+ }
+
+ AND_GIVEN("A participant with priority -10")
+ {
+ g_autoptr(TurnsParticipant) rhs = turns_participant_new_with(name_rhs, -10.0f, disposition);
+
+ THEN("the first compares greater than the second")
+ {
+ REQUIRE(turns_participant_compare(lhs, rhs) > 0);
+ }
+
+ THEN("the second compares less than the first")
+ {
+ REQUIRE(turns_participant_compare(rhs, lhs) < 0);
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/lib/tests/turnsmm/participant.cpp b/lib/tests/turnsmm/participant.cpp
index 47cf867..0cac20d 100644
--- a/lib/tests/turnsmm/participant.cpp
+++ b/lib/tests/turnsmm/participant.cpp
@@ -523,3 +523,50 @@ SCENARIO("Modifying a participant", "[lib][object][data]")
}
}
}
+
+SCENARIO("Comparing two participants", "[lib][object][logic]")
+{
+ auto name_lhs = "LHS";
+ auto name_rhs = "RHS";
+ auto disposition = Turns::Participant::Disposition::Neutral;
+
+ GIVEN("A participant with priority 0")
+ {
+ auto lhs = Turns::Participant{name_lhs, 0.0f, disposition};
+
+ THEN("the it compares equal to itself")
+ {
+ REQUIRE(lhs == lhs);
+ }
+
+ AND_GIVEN("A participant with priority 10")
+ {
+ auto rhs = Turns::Participant{name_rhs, 10.0f, disposition};
+
+ THEN("the first compares less than the second")
+ {
+ REQUIRE(lhs < rhs);
+ }
+
+ THEN("the second compares greater than the first")
+ {
+ REQUIRE(rhs > lhs);
+ }
+ }
+
+ AND_GIVEN("A participant with priority -10")
+ {
+ auto rhs = Turns::Participant{name_rhs, -10.0f, disposition};
+
+ THEN("the first compares greater than the second")
+ {
+ REQUIRE(lhs > rhs);
+ }
+
+ THEN("the second compares less than the first")
+ {
+ REQUIRE(rhs < lhs);
+ }
+ }
+ }
+} \ No newline at end of file