Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
MultiSet_Array.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/Containers//Private/IteratorImplHelper.h"
5#include "Stroika/Foundation/Containers/DataStructures/Array.h"
9
11
12 /*
13 ********************************************************************************
14 ************************** MultiSet_Array<T, TRAITS>::Rep_ *********************
15 ********************************************************************************
16 */
17 template <typename T, typename TRAITS>
18 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IEqualsComparer<T>) EQUALS_COMPARER>
19 class MultiSet_Array<T, TRAITS>::Rep_ : public Private::ArrayBasedContainerRepImpl<Rep_<EQUALS_COMPARER>, IImplRepBase_>,
20 public Memory::UseBlockAllocationIfAppropriate<Rep_<EQUALS_COMPARER>> {
21 private:
22 using inherited = Private::ArrayBasedContainerRepImpl<Rep_<EQUALS_COMPARER>, IImplRepBase_>;
23
24 public:
25 static_assert (not is_reference_v<EQUALS_COMPARER>);
26
27 public:
28 Rep_ (const EQUALS_COMPARER& equalsComparer)
29 : fEqualsComparer_{equalsComparer}
30 {
31 }
32 Rep_ (const Rep_& from) = default;
33
34 public:
35 nonvirtual Rep_& operator= (const Rep_&) = delete;
36
37 private:
38 [[no_unique_address]] const EQUALS_COMPARER fEqualsComparer_;
39
40 // Iterable<typename TRAITS::CountedValueType>::_IRep overrides
41 public:
42 virtual shared_ptr<typename Iterable<typename TRAITS::CountedValueType>::_IRep> Clone () const override
43 {
45 return Memory::MakeSharedPtr<Rep_> (*this);
46 }
47 virtual size_t size () const override
48 {
50 return fData_.size ();
51 }
52 virtual bool empty () const override
53 {
55 return fData_.empty ();
56 }
57 virtual Iterator<value_type> MakeIterator () const override
58 {
60 return Iterator<value_type>{make_unique<IteratorRep_> (&fData_, &fChangeCounts_)};
61 }
62 virtual void Apply (const function<void (ArgByValueType<value_type> item)>& doToElement, Execution::SequencePolicy seq) const override
63 {
65 fData_.Apply (doToElement, seq);
66 }
67 virtual Iterator<value_type> Find (const function<bool (ArgByValueType<value_type> item)>& that,
68 [[maybe_unused]] Execution::SequencePolicy seq) const override
69 {
71 if (auto i = fData_.Find (that)) {
72 return Iterator<value_type>{make_unique<IteratorRep_> (&fChangeCounts_, i)};
73 }
74 return nullptr;
75 }
76
77 // MultiSet<T, TRAITS>::_IRep overrides
78 public:
79 virtual ElementEqualityComparerType GetElementEqualsComparer () const override
80 {
82 return fEqualsComparer_;
83 }
84 virtual shared_ptr<typename MultiSet<T, TRAITS>::_IRep> CloneEmpty () const override
85 {
87 return Memory::MakeSharedPtr<Rep_> (fEqualsComparer_); // keep same comparer, but no data
88 }
89 virtual shared_ptr<typename MultiSet<T, TRAITS>::_IRep> CloneAndPatchIterator (Iterator<value_type>* i) const override
90 {
93 auto result = Memory::MakeSharedPtr<Rep_> (*this);
94 auto& mir = Debug::UncheckedDynamicCast<const IteratorRep_&> (i->ConstGetRep ());
95 result->fData_.MoveIteratorHereAfterClone (&mir.fIterator, &fData_);
96 i->Refresh (); // reflect updated rep
97 return result;
98 }
99 virtual bool Equals (const typename MultiSet<T, TRAITS>::_IRep& rhs) const override
100 {
102 return this->_Equals_Reference_Implementation (rhs);
103 }
104 virtual bool Contains (ArgByValueType<T> item) const override
105 {
107 value_type tmp{item};
108 return Find_ (tmp) != kNotFound_;
109 }
110 virtual void Add (ArgByValueType<T> item, CounterType count) override
111 {
113 value_type tmp{item, count};
114 size_t index = Find_ (tmp);
115 if (index == kNotFound_) {
116 fData_.push_back (tmp);
117 }
118 else {
119 tmp.fCount += count;
120 fData_.SetAt (index, tmp);
121 }
122 fChangeCounts_.PerformedChange ();
123 }
124 virtual size_t RemoveIf (ArgByValueType<T> item, CounterType count) override
125 {
126 Require (count > 0);
128 value_type tmp{item};
129 size_t index = Find_ (tmp);
130 if (index != kNotFound_) {
131 Assert (index < fData_.size ());
132 size_t result; // intentionally uninitialized
133 if (tmp.fCount > count) {
134 tmp.fCount -= count;
135 Assert (tmp.fCount > 0);
136 fData_.SetAt (index, tmp);
137 result = count;
138 }
139 else {
140 fData_.RemoveAt (index);
141 result = tmp.fCount;
142 }
143 fChangeCounts_.PerformedChange ();
144 return result;
145 }
146 return 0;
147 }
148 virtual void Remove (const Iterator<value_type>& i, Iterator<value_type>* nextI) override
149 {
151 auto& mir = Debug::UncheckedDynamicCast<const IteratorRep_&> (i.ConstGetRep ());
152 if (nextI == nullptr) {
153 fData_.Remove (mir.fIterator);
154 fChangeCounts_.PerformedChange ();
155 }
156 else {
157 auto retI = fData_.erase (mir.fIterator);
158 fChangeCounts_.PerformedChange ();
159 *nextI = Iterator<value_type>{make_unique<IteratorRep_> (&fChangeCounts_, retI)};
160 }
161 }
162 virtual void UpdateCount (const Iterator<value_type>& i, CounterType newCount, Iterator<value_type>* nextI) override
163 {
165 auto& mir = Debug::UncheckedDynamicCast<const IteratorRep_&> (i.ConstGetRep ());
166 if (newCount == 0) {
167 if (nextI != nullptr) {
168 *nextI = i;
169 ++(*nextI);
170 }
171 fData_.Remove (mir.fIterator);
172 }
173 else {
174 value_type c = *mir.fIterator;
175 c.fCount = newCount;
176 fData_.SetAt (mir.fIterator, c);
177 if (nextI != nullptr) {
178 *nextI = i;
179 }
180 }
181 fChangeCounts_.PerformedChange ();
182 if (nextI != nullptr) {
183 Debug::UncheckedDynamicCast<IteratorRep_&> (nextI->GetRep ()).UpdateChangeCount ();
184 nextI->Refresh (); // update to reflect changes made to rep
185 }
186 }
187 virtual CounterType OccurrencesOf (ArgByValueType<T> item) const override
188 {
190 value_type tmp{item};
191 size_t index = Find_ (tmp);
192 if (index == kNotFound_) {
193 return 0;
194 }
195 Assert (index >= 0);
196 Assert (index < fData_.size ());
197 return fData_[index].fCount;
198 }
199
200 private:
201 using DataStructureImplType_ = DataStructures::Array<value_type>;
202 using IteratorRep_ = Private::IteratorImplHelper_<value_type, DataStructureImplType_>;
203
204 private:
205 DataStructureImplType_ fData_;
206 [[no_unique_address]] Private::ContainerDebugChangeCounts_ fChangeCounts_;
207
208 private:
209 static constexpr size_t kNotFound_ = (size_t)-1;
210
211 private:
212 nonvirtual size_t Find_ (value_type& item) const
213 {
214 // this code assumes locking done by callers
215 size_t length = fData_.size ();
216 for (size_t i = 0; i < length; ++i) {
217 if (fEqualsComparer_ (fData_.GetAt (i).fValue, item.fValue)) {
218 item = fData_.GetAt (i);
219 return i;
220 }
221 }
222 return kNotFound_;
223 }
224
225 private:
226 friend inherited;
227 };
228
229 /*
230 ********************************************************************************
231 ***************************** MultiSet_Array<T, TRAITS> ************************
232 ********************************************************************************
233 */
234 template <typename T, typename TRAITS>
236 : MultiSet_Array{equal_to<T>{}}
237 {
238 AssertRepValidType_ ();
239 }
240 template <typename T, typename TRAITS>
241 template <IEqualsComparer<T> EQUALS_COMPARER>
242 inline MultiSet_Array<T, TRAITS>::MultiSet_Array (EQUALS_COMPARER&& equalsComparer)
243 : inherited{Memory::MakeSharedPtr<Rep_<remove_cvref_t<EQUALS_COMPARER>>> (forward<EQUALS_COMPARER> (equalsComparer))}
244 {
245 AssertRepValidType_ ();
246 }
247#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
248 template <typename T, typename TRAITS>
249 template <IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
250 requires (not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, MultiSet_Array<T, TRAITS>>)
251 inline MultiSet_Array<T, TRAITS>::MultiSet_Array (ITERABLE_OF_ADDABLE&& src)
252 : MultiSet_Array{}
253 {
254 if constexpr (Common::IHasSizeMethod<ITERABLE_OF_ADDABLE>) {
255 this->reserve (src.size ());
256 }
257 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
258 AssertRepValidType_ ();
259 }
260#endif
261 template <typename T, typename TRAITS>
262 template <IEqualsComparer<T> EQUALS_COMPARER, IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
263 inline MultiSet_Array<T, TRAITS>::MultiSet_Array (EQUALS_COMPARER&& equalsComparer, ITERABLE_OF_ADDABLE&& src)
264 : MultiSet_Array{forward<EQUALS_COMPARER> (equalsComparer)}
265 {
266 this->reserve (src.size ());
267 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
268 AssertRepValidType_ ();
269 }
270 template <typename T, typename TRAITS>
271 MultiSet_Array<T, TRAITS>::MultiSet_Array (const initializer_list<T>& src)
272 : MultiSet_Array{}
273 {
274 this->reserve (src.size ());
275 AddAll (src);
276 AssertRepValidType_ ();
277 }
278 template <typename T, typename TRAITS>
279 template <IEqualsComparer<T> EQUALS_COMPARER>
280 MultiSet_Array<T, TRAITS>::MultiSet_Array (EQUALS_COMPARER&& equalsComparer, const initializer_list<T>& src)
281 : MultiSet_Array{forward<EQUALS_COMPARER> (equalsComparer)}
282 {
283 this->reserve (src.size ());
284 AddAll (src);
285 AssertRepValidType_ ();
286 }
287 template <typename T, typename TRAITS>
288 MultiSet_Array<T, TRAITS>::MultiSet_Array (const initializer_list<value_type>& src)
289 : MultiSet_Array{}
290 {
291 this->reserve (src.size ());
292 AddAll (src);
293 AssertRepValidType_ ();
294 }
295 template <typename T, typename TRAITS>
296 template <IEqualsComparer<T> EQUALS_COMPARER>
297 MultiSet_Array<T, TRAITS>::MultiSet_Array (EQUALS_COMPARER&& equalsComparer, const initializer_list<value_type>& src)
298 : MultiSet_Array{forward<EQUALS_COMPARER> (equalsComparer)}
299 {
300 this->reserve (src.size ());
301 this->AddAll (src);
302 AssertRepValidType_ ();
303 }
304 template <typename T, typename TRAITS>
305 template <IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE>
306 MultiSet_Array<T, TRAITS>::MultiSet_Array (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE&& end)
307 : MultiSet_Array{}
308 {
309 if constexpr (Common::has_minus_v<ITERATOR_OF_ADDABLE>) {
310 if (start != end) {
311 this->reserve (end - start);
312 }
313 }
314 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE> (end));
315 AssertRepValidType_ ();
316 }
317 template <typename T, typename TRAITS>
318 template <IEqualsComparer<T> EQUALS_COMPARER, IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE>
319 MultiSet_Array<T, TRAITS>::MultiSet_Array (EQUALS_COMPARER&& equalsComparer, ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE&& end)
320 : MultiSet_Array{forward<EQUALS_COMPARER> (equalsComparer)}
321 {
322 if constexpr (random_access_iterator<ITERATOR_OF_ADDABLE>) {
323 if (start != end) {
324 this->reserve (end - start);
325 }
326 }
327 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE> (end));
328 AssertRepValidType_ ();
329 }
330 template <typename T, typename TRAITS>
331 inline void MultiSet_Array<T, TRAITS>::AssertRepValidType_ () const
332 {
334 typename inherited::template _SafeReadRepAccessor<IImplRepBase_> tmp{this}; // for side-effect of AssertMemeber
335 }
336 }
337
338}
#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
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...
SequencePolicy
equivalent which of 4 types being used std::execution::sequenced_policy, parallel_policy,...