Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
MultiSet_LinkedList.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/Containers/DataStructures/LinkedList.h"
5#include "Stroika/Foundation/Containers/Private/IteratorImplHelper.h"
8
10
11 /*
12 ********************************************************************************
13 ********************** MultiSet_LinkedList<T, TRAITS>::Rep_ ********************
14 ********************************************************************************
15 */
16 template <typename T, typename TRAITS>
17 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IEqualsComparer<T>) EQUALS_COMPARER>
18 class MultiSet_LinkedList<T, TRAITS>::Rep_ : public IImplRepBase_, public Memory::UseBlockAllocationIfAppropriate<Rep_<EQUALS_COMPARER>> {
19 private:
20 using inherited = IImplRepBase_;
21
22 public:
23 static_assert (not is_reference_v<EQUALS_COMPARER>);
24
25 public:
26 Rep_ (const EQUALS_COMPARER& equalsComparer)
27 : fEqualsComparer_{equalsComparer}
28 {
29 }
30 Rep_ (const Rep_& from) = default;
31
32 public:
33 nonvirtual Rep_& operator= (const Rep_&) = delete;
34
35 private:
36 [[no_unique_address]] const EQUALS_COMPARER fEqualsComparer_;
37
38 // Iterable<typename TRAITS::CountedValueType>::_IRep overrides
39 public:
40 virtual shared_ptr<typename Iterable<typename TRAITS::CountedValueType>::_IRep> Clone () const override
41 {
43 return Memory::MakeSharedPtr<Rep_> (*this);
44 }
45 virtual size_t size () const override
46 {
48 return fData_.size ();
49 }
50 virtual bool empty () const override
51 {
53 return fData_.empty ();
54 }
55 virtual Iterator<value_type> MakeIterator () const override
56 {
58 return Iterator<value_type>{make_unique<IteratorRep_> (&fData_, &fChangeCounts_)};
59 }
60 virtual void Apply (const function<void (ArgByValueType<value_type> item)>& doToElement, [[maybe_unused]] Execution::SequencePolicy seq) const override
61 {
63 fData_.Apply (doToElement);
64 }
65 virtual Iterator<value_type> Find (const function<bool (ArgByValueType<value_type> item)>& that,
66 [[maybe_unused]] Execution::SequencePolicy seq) const override
67 {
69 if (auto iLink = fData_.Find (that)) {
70 return Iterator<value_type>{make_unique<IteratorRep_> (&fData_, &fChangeCounts_, iLink)};
71 }
72 return nullptr;
73 }
74
75 // MultiSet<T, TRAITS>::_IRep overrides
76 public:
77 virtual ElementEqualityComparerType GetElementEqualsComparer () const override
78 {
80 return fEqualsComparer_;
81 }
82 virtual shared_ptr<typename MultiSet<T, TRAITS>::_IRep> CloneEmpty () const override
83 {
85 return Memory::MakeSharedPtr<Rep_> (fEqualsComparer_); // new rep with same comparer, but no data
86 }
87 virtual shared_ptr<typename MultiSet<T, TRAITS>::_IRep> CloneAndPatchIterator (Iterator<value_type>* i) const override
88 {
91 auto result = Memory::MakeSharedPtr<Rep_> (*this);
92 auto& mir = Debug::UncheckedDynamicCast<const IteratorRep_&> (i->ConstGetRep ());
93 result->fData_.MoveIteratorHereAfterClone (&mir.fIterator, &fData_);
94 i->Refresh (); // reflect updated rep
95 return result;
96 }
97 virtual bool Equals (const typename MultiSet<T, TRAITS>::_IRep& rhs) const override
98 {
100 return this->_Equals_Reference_Implementation (rhs);
101 }
102 virtual bool Contains (ArgByValueType<T> item) const override
103 {
105 for (typename DataStructureImplType_::ForwardIterator it{&fData_}; not it.Done (); ++it) {
106 if (fEqualsComparer_ (it->fValue, item)) {
107 Assert (it->fCount != 0);
108 return true;
109 }
110 }
111 return false;
112 }
113 virtual void Add (ArgByValueType<T> item, CounterType count) override
114 {
115 if (count != 0) {
117 for (typename DataStructureImplType_::ForwardIterator it{&fData_}; not it.Done (); ++it) {
118 auto current = *it;
119 if (fEqualsComparer_ (current.fValue, item)) {
120 current.fCount += count;
121 fData_.SetAt (it, current);
122 fChangeCounts_.PerformedChange ();
123 return;
124 }
125 }
126 fData_.push_front (value_type{item, count}); // order meaningless for collection, and prepend cheaper on linked list
127 fChangeCounts_.PerformedChange ();
128 }
129 }
130 virtual size_t RemoveIf (ArgByValueType<T> item, CounterType count) override
131 {
132 Require (count != 0);
134 for (typename DataStructureImplType_::ForwardIterator it{&fData_}; not it.Done (); ++it) {
135 auto current = *it;
136 if (fEqualsComparer_ (current.fValue, item)) {
137 size_t result; // intentionally uninitialized
138 if (current.fCount > count) {
139 current.fCount -= count;
140 fData_.SetAt (it, current);
141 result = count;
142 }
143 else {
144 result = current.fCount;
145 fData_.Remove (it);
146 }
147 fChangeCounts_.PerformedChange ();
148 return result;
149 }
150 }
151 return 0;
152 }
153 virtual void Remove (const Iterator<value_type>& i, Iterator<value_type>* nextI) override
154 {
156 auto& mir = Debug::UncheckedDynamicCast<const IteratorRep_&> (i.ConstGetRep ());
157 if (nextI == nullptr) {
158 fData_.Remove (mir.fIterator);
159 fChangeCounts_.PerformedChange ();
160 }
161 else {
162 auto ret = fData_.erase (mir.fIterator);
163 fChangeCounts_.PerformedChange ();
164 *nextI = Iterator<value_type>{make_unique<IteratorRep_> (&fChangeCounts_, ret)};
165 }
166 }
167 virtual void UpdateCount (const Iterator<value_type>& i, CounterType newCount, Iterator<value_type>* nextI) override
168 {
170 auto& mir = Debug::UncheckedDynamicCast<const IteratorRep_&> (i.ConstGetRep ());
171 if (newCount == 0) {
172 if (nextI != nullptr) {
173 *nextI = i;
174 ++(*nextI);
175 }
176 fData_.Remove (mir.fIterator);
177 }
178 else {
179 value_type c = *mir.fIterator;
180 c.fCount = newCount;
181 fData_.SetAt (mir.fIterator, c);
182 if (nextI != nullptr) {
183 *nextI = i;
184 }
185 }
186 fChangeCounts_.PerformedChange ();
187 if (nextI != nullptr) {
188 Debug::UncheckedDynamicCast<IteratorRep_&> (nextI->GetRep ()).UpdateChangeCount ();
189 nextI->Refresh (); // update to reflect changes made to rep
190 }
191 }
192 virtual CounterType OccurrencesOf (ArgByValueType<T> item) const override
193 {
195 for (typename DataStructureImplType_::ForwardIterator it{&fData_}; not it.Done (); ++it) {
196 auto current = *it;
197 if (fEqualsComparer_ (current.fValue, item)) {
198 Ensure (current.fCount != 0);
199 return current.fCount;
200 }
201 }
202 return 0;
203 }
204
205 private:
206 using DataStructureImplType_ = DataStructures::LinkedList<value_type>;
207 using IteratorRep_ = Private::IteratorImplHelper_<value_type, DataStructureImplType_>;
208
209 private:
210 DataStructureImplType_ fData_;
211 [[no_unique_address]] Private::ContainerDebugChangeCounts_ fChangeCounts_;
212 };
213
214 /*
215 ********************************************************************************
216 ************************ MultiSet_LinkedList<T, TRAITS> ************************
217 ********************************************************************************
218 */
219 template <typename T, typename TRAITS>
221 : MultiSet_LinkedList{equal_to<T>{}}
222 {
223 AssertRepValidType_ ();
224 }
225 template <typename T, typename TRAITS>
226 template <IEqualsComparer<T> EQUALS_COMPARER>
227 inline MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (EQUALS_COMPARER&& equalsComparer)
228 : inherited{Memory::MakeSharedPtr<Rep_<remove_cvref_t<EQUALS_COMPARER>>> (forward<EQUALS_COMPARER> (equalsComparer))}
229 {
230 AssertRepValidType_ ();
231 }
232#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
233 template <typename T, typename TRAITS>
234 template <IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
235 requires (not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, MultiSet_LinkedList<T, TRAITS>>)
236 inline MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (ITERABLE_OF_ADDABLE&& src)
237 : MultiSet_LinkedList{}
238 {
239 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
240 AssertRepValidType_ ();
241 }
242#endif
243 template <typename T, typename TRAITS>
244 template <IEqualsComparer<T> EQUALS_COMPARER, IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
245 inline MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (EQUALS_COMPARER&& equalsComparer, ITERABLE_OF_ADDABLE&& src)
246 : MultiSet_LinkedList{forward<EQUALS_COMPARER> (equalsComparer)}
247 {
248 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
249 AssertRepValidType_ ();
250 }
251 template <typename T, typename TRAITS>
252 MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (const initializer_list<T>& src)
253 : MultiSet_LinkedList{}
254 {
255 AddAll (src);
256 AssertRepValidType_ ();
257 }
258 template <typename T, typename TRAITS>
259 template <IEqualsComparer<T> EQUALS_COMPARER>
260 MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (EQUALS_COMPARER&& equalsComparer, const initializer_list<T>& src)
261 : MultiSet_LinkedList{forward<EQUALS_COMPARER> (equalsComparer)}
262 {
263 AddAll (src);
264 AssertRepValidType_ ();
265 }
266 template <typename T, typename TRAITS>
267 MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (const initializer_list<value_type>& src)
268 : MultiSet_LinkedList{}
269 {
270 AddAll (src);
271 AssertRepValidType_ ();
272 }
273 template <typename T, typename TRAITS>
274 template <IEqualsComparer<T> EQUALS_COMPARER>
275 MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (EQUALS_COMPARER&& equalsComparer, const initializer_list<value_type>& src)
276 : MultiSet_LinkedList{forward<EQUALS_COMPARER> (equalsComparer)}
277 {
278 AddAll (src);
279 AssertRepValidType_ ();
280 }
281 template <typename T, typename TRAITS>
282 template <IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE>
283 MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE&& end)
284 : MultiSet_LinkedList{}
285 {
286 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE> (end));
287 AssertRepValidType_ ();
288 }
289 template <typename T, typename TRAITS>
290 template <IEqualsComparer<T> EQUALS_COMPARER, IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE>
291 MultiSet_LinkedList<T, TRAITS>::MultiSet_LinkedList (EQUALS_COMPARER&& equalsComparer, ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE&& end)
292 : MultiSet_LinkedList{forward<EQUALS_COMPARER> (equalsComparer)}
293 {
294 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE> (end));
295 AssertRepValidType_ ();
296 }
297 template <typename T, typename TRAITS>
298 inline void MultiSet_LinkedList<T, TRAITS>::AssertRepValidType_ () const
299 {
301 typename inherited::template _SafeReadRepAccessor<IImplRepBase_> tmp{this}; // for side-effect of AssertMemeber
302 }
303 }
304
305}
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:48
#define RequireNotNull(p)
Definition Assertions.h:347
bool Equals(const T *lhs, const T *rhs)
strcmp or wsccmp() as appropriate == 0
nonvirtual void AddAll(ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end)
nonvirtual void Remove(ArgByValueType< T > item, CounterType count=1)
remove the argument data from the multiset. The data specified MUST exist (require) - else use Remove...
Definition MultiSet.inl:292
nonvirtual void UpdateCount(const Iterator< value_type > &i, CounterType newCount, Iterator< value_type > *nextI=nullptr)
Definition MultiSet.inl:309
nonvirtual void Add(ArgByValueType< T > item)
Definition MultiSet.inl:248
nonvirtual ElementEqualityComparerType GetElementEqualsComparer() const
Definition MultiSet.inl:225
nonvirtual bool Contains(ArgByValueType< T > item) const
Definition MultiSet.inl:230
nonvirtual CounterType OccurrencesOf(ArgByValueType< T > item) const
Definition MultiSet.inl:327
nonvirtual size_t RemoveIf(ArgByValueType< T > item, CounterType count=1)
remove the argument data from the multiset (can specify remove of more than are present) - returns nu...
Definition MultiSet.inl:304
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
nonvirtual void Apply(const function< void(ArgByValueType< T > item)> &doToElement, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
Run the argument function (or lambda) on each element of the container.
nonvirtual Iterator< T > Find(THAT_FUNCTION &&that, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
Run the argument bool-returning function (or lambda) on each element of the container,...
nonvirtual size_t size() const
Returns the number of items contained.
Definition Iterable.inl:300
nonvirtual bool empty() const
Returns true iff size() == 0.
Definition Iterable.inl:306
static constexpr default_sentinel_t end() noexcept
Support for ranged for, and STL syntax in general.
nonvirtual Iterator< T > MakeIterator() const
Create an iterator object which can be used to traverse the 'Iterable'.
Definition Iterable.inl:294
SequencePolicy
equivalent which of 4 types being used std::execution::sequenced_policy, parallel_policy,...