Anklang-0.3.0.dev956+gd75ac925 anklang-0.3.0.dev956+gd75ac925
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
eventlist.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#pragma once
3
4#include <ase/utils.hh>
5#include <algorithm>
6#include <any>
7
8namespace Ase {
9
11template<class Event, class CompareOrder>
15 explicit OrderedEventList (const std::vector<Event> &ve);
16 const Event* lookup (const Event &event) const;
17 const Event* lookup_after (const Event &event) const;
18private:
19 CompareOrder compare_;
20};
21
23template<class Event, class Compare>
24class EventList final {
26public:
27 using Notify = std::function<void (const Event &event, int mod)>;
28 using CIter = typename EventVector::const_iterator;
29 explicit EventList (const Notify &n = {}, const Compare &c = {});
30 bool insert (const Event &event, Event *replaced = nullptr);
31 bool replace (const Event &event, Event *replaced = nullptr);
32 bool remove (const Event &event, Event *removed = nullptr);
33 const Event* lookup (const Event &event) const;
34 const Event* lookup_after (const Event &event) const;
35 const Event* first () const;
36 const Event* last () const;
37 size_t size () const;
38 void clear_silently ();
39 template<class OrderedEventList> typename OrderedEventList::ConstP
40 inline ordered_events ();
41 CIter begin () const { return events_.begin(); }
42 CIter end () const { return events_.end(); }
43 EventVector copy () const { return events_; }
44 bool equals (const EventVector &ev) const { return ev == events_; }
45private:
46 EventVector events_;
47 Compare compare_;
48 Notify notify_;
49 std::any ordered_;
50 static_assert (std::is_signed<decltype (std::declval<Compare>() (std::declval<Event>(), std::declval<Event>()))>::value, "REQUIRE: int Compare (const&, const&);");
51 void uncache ();
52 static void nop (const Event&, int) {}
53};
54
55// == Implementation Details ==
56template<class Event, class Compare> inline
57EventList<Event,Compare>::EventList (const Notify &n, const Compare &c) :
58 compare_ (c), notify_ (n)
59{
60 if (!notify_)
61 notify_ = nop;
62}
63
64template<class Event, class Compare> inline void
66{
67 events_.clear();
68 ordered_.reset();
69}
70
71template<class Event, class Compare> inline void
73{
74 ordered_.reset();
75}
76
77template<class Event, class Compare> inline bool
78EventList<Event,Compare>::insert (const Event &event, Event *replaced)
79{
80 uncache();
81 if (events_.size() && compare_ (event, events_.back()) > 0)
82 {
83 events_.push_back (event);
84 notify_ (event, +1); // notify insertion
85 return false; // O(1) fast path for append
86 }
87 auto insmatch = Aux::binary_lookup_insertion_pos (events_.begin(), events_.end(), compare_, event);
88 auto it = insmatch.first;
89 if (insmatch.second == true) // exact match
90 {
91 if (replaced)
92 *replaced = *it;
93 *it = event;
94 notify_ (event, 0); // notify change
95 return true;
96 }
97 else
98 {
99 events_.insert (it, event);
100 notify_ (event, +1); // notify insertion
101 return false;
102 }
103}
104
105template<class Event, class Compare> inline bool
107{
108 auto insmatch = Aux::binary_lookup_insertion_pos (events_.begin(), events_.end(), compare_, event);
109 if (insmatch.second == true) // exact match
110 {
111 uncache();
112 auto it = insmatch.first;
113 if (replaced)
114 *replaced = *it;
115 *it = event;
116 notify_ (event, 0); // notify change
117 return true;
118 }
119 return false;
120}
121
122template<class Event, class Compare> inline bool
124{
125 uncache();
126 const int cmp = events_.empty() ? +1 : compare_ (event, events_.back());
127 if (cmp == 0)
128 {
129 if (removed)
130 *removed = events_.back();
131 events_.pop_back(); // O(1) fast path for tail removal
132 notify_ (event, -1); // notify removal
133 return true; // found and removed
134 }
135 if (cmp < 0)
136 {
137 auto it = Aux::binary_lookup (events_.begin(), events_.end() - 1, compare_, event);
138 if (it != events_.end())
139 {
140 if (removed)
141 *removed = *it;
142 events_.erase (it);
143 notify_ (event, -1); // notify removal
144 return true; // found and removed
145 }
146 }
147 return false; // none removed
148}
149
150template<class Event, class Compare> inline const Event*
152{
153 return events_.empty() ? nullptr : &events_.front();
154}
155
156template<class Event, class Compare> inline const Event*
158{
159 return events_.empty() ? nullptr : &events_.back();
160}
161
162template<class Event, class Compare> inline size_t
164{
165 return events_.size();
166}
167
168template<class Event, class Compare> inline const Event*
170{
171 auto it = Aux::binary_lookup (events_.begin(), events_.end(), compare_, event);
172 return it != events_.end() ? &*it : nullptr;
173}
174
175template<class Event, class Compare> inline const Event*
177{
178 auto it = Aux::binary_lookup_insertion_pos (events_.begin(), events_.end(), compare_, event).first;
179 return it != events_.end() ? &*it : nullptr;
180}
181
182template<class Event, class Compare>
183template<class OrderedEventList> inline typename OrderedEventList::ConstP
185{
186 using OrderedEventListP = typename OrderedEventList::ConstP;
187 OrderedEventListP *oepp = std::any_cast<OrderedEventListP> (&ordered_);
188 if (!oepp)
189 {
190 ordered_ = std::make_shared<const OrderedEventList> (events_);
191 oepp = std::any_cast<OrderedEventListP> (&ordered_);
192 ASE_ASSERT_RETURN (oepp, nullptr);
193 }
194 return *oepp;
195}
196
197template<class Event, class CompareOrder>
199 Base (ve)
200{
201 auto lesser = [this] (const Event &a, const Event &b) {
202 return compare_ (a, b) < 0;
203 };
204 std::stable_sort (this->begin(), this->end(), lesser);
205}
206
207template<class Event, class CompareOrder> inline const Event*
208OrderedEventList<Event,CompareOrder>::lookup (const Event &event) const
209{
210 auto it = Aux::binary_lookup (this->begin(), this->end(), compare_, event);
211 return it != this->end() ? &*it : nullptr;
212}
213
214template<class Event, class CompareOrder> inline const Event*
215OrderedEventList<Event,CompareOrder>::lookup_after (const Event &event) const
216{
217 auto it = Aux::binary_lookup_insertion_pos (this->begin(), this->end(), compare_, event).first;
218 return it != this->end() ? &*it : nullptr;
219}
220
221} // Ase
222
T back(T... args)
T begin(T... args)
Maintain an array of unique Event structures with change notification.
Definition eventlist.hh:24
bool remove(const Event &event, Event *removed=nullptr)
Only replace event, notifies.
Definition eventlist.hh:123
CIter end() const
Const iterator that points to the first element.
Definition eventlist.hh:42
void clear_silently()
Return the numberof elements.
Definition eventlist.hh:65
OrderedEventList::ConstP ordered_events()
Clear list without notification.
Definition eventlist.hh:184
bool replace(const Event &event, Event *replaced=nullptr)
Insert or replace event, notifies.
Definition eventlist.hh:106
CIter begin() const
Create a read-only copy of this EventList (possibly cached).
Definition eventlist.hh:41
const Event * lookup(const Event &event) const
Return true if event was removed, notifies.
Definition eventlist.hh:169
size_t size() const
Return last element or nullptr.
Definition eventlist.hh:163
EventVector copy() const
Const iterator that points one past the last element.
Definition eventlist.hh:43
const Event * lookup_after(const Event &event) const
Return pointer to matching event or nullptr.
Definition eventlist.hh:176
const Event * first() const
Return pointer to element that is >= event or nullptr.
Definition eventlist.hh:151
const Event * last() const
Return first element or nullptr.
Definition eventlist.hh:157
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
Definition cxxaux.hh:81
T empty(T... args)
T end(T... args)
T erase(T... args)
RandIter binary_lookup(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Perform binary lookup and yield exact match or end.
Definition utils.hh:243
std::pair< RandIter, bool > binary_lookup_insertion_pos(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Perform a binary lookup to find the insertion position for a new element.
Definition utils.hh:219
The Anklang C++ API namespace.
Definition api.hh:8
T stable_sort(T... args)
Structure for callback based notifications.
Definition value.hh:112
Container for a sorted array of opaque Event structures with binary lookup.
Definition eventlist.hh:12