CodePorting.Translator Cs2Cpp
CodePorting.Translator.Cs2Cpp.Framework
enumerable.h
1
2#pragma once
3
4#include <system/collections/ienumerable.h>
5#include <system/linq/iordered_enumerable.h>
6#include <system/collections/list.h>
7#include <system/collections/dictionary.h>
8#include <system/array.h>
9#include <system/constraints.h>
10#include <system/object_ext.h>
11#include <system/exceptions.h>
12#include <system/details/equality_helper.h>
13#include <system/details/cast_rules.h>
14#include <system/default.h>
15#include <type_traits>
16
17namespace System { namespace Linq {
18
19namespace Details {
20
23template <typename T>
25{
26public:
27 EmptyEnumerator() = default;
28
30 {
31 throw InvalidOperationException(u"Collection is empty");
32 }
33
34 bool MoveNext() override
35 {
36 return false;
37 }
38
39 void Reset() override
40 {
41 }
42
43 System::Details::VirtualizedIteratorBase<T>* CloneIterator() const override
44 {
45 return new EmptyEnumerator(*this);
46 }
47};
48
51template <typename T>
53{
54public:
55 EmptyEnumerable() = default;
58 {
59 static const auto enumerator = MakeObject<EmptyEnumerator<T>>();
60 return enumerator;
61 }
62};
63
67template<typename TItem>
69{
70private:
73 template<typename TEnumeratorItem>
74 class CachedEnumerator final : public System::Collections::Generic::IEnumerator<TEnumeratorItem>
75 {
76 public:
77 MakeConstRef_t<TEnumeratorItem> get_Current() const override
78 {
79 return cachedEnumerable->items->data()[position];
80 }
81
82 CachedEnumerator(System::SharedPtr<CachedEnumerable<TEnumeratorItem>> cachedEnumerable) : position(-1)
83 {
84 this->cachedEnumerable = cachedEnumerable;
85 }
86
87 void Dispose() override
88 {
89 position = -1;
90 }
92 bool MoveNext() override
93 {
94 position++;
95 return cachedEnumerable->items->get_Count() > position || cachedEnumerable->requestNext();
96 }
97
98 void Reset() override
99 {
100 position = -1;
101 }
102
103 System::Details::VirtualizedIteratorBase<TEnumeratorItem>* CloneIterator() const override
105 return new CachedEnumerator(*this);
106 }
107
108 private:
110 int32_t position;
111 };
112
113public:
116 CachedEnumerable(System::Func<bool> requestNext) : requestNext(requestNext)
117 {
118 items = System::MakeObject<System::Collections::Generic::List<TItem>>();
120
122 {
123 return System::MakeObject<CachedEnumerator<TItem>>(System::MakeSharedPtr(this));
125
126 void Add(TItem item)
127 {
128 items->Add(item);
130
131private:
132 System::Func<bool> requestNext;
134};
135
136} // namespace Details
137
140{
141public:
143 template <typename T>
145 {
146 static const auto enumerable = MakeObject<Details::EmptyEnumerable<T>>();
147 return enumerable;
148 }
149
154 ASPOSECPP_SHARED_API static SharedPtr<Collections::Generic::IEnumerable<int32_t>> Range(int32_t start, int32_t count);
155};
156
157}} // namespace System::Linq
158
159namespace System { namespace Collections { namespace Generic {
160
161namespace Details {
162
170template <typename T>
171T TryGetFirst(IEnumerable<T>& enumerable, bool& found)
172{
173 if (IList<T>* list = dynamic_cast<IList<T>*>(&enumerable))
174 {
175 const auto count = list->get_Count();
176 if (count > 0)
178 found = true;
179 return list->idx_get(0);
180 }
181 }
182 else
183 {
184 const auto enumerator = enumerable.GetEnumerator();
185 if (enumerator->MoveNext())
186 {
187 found = true;
188 return enumerator->get_Current();
189 }
190 }
191 found = false;
192 return T{};
193}
194
203template <typename T>
204T TryGetFirst(IEnumerable<T>& enumerable, const Func<T, bool>& predicate, bool& found)
205{
206 if (predicate == nullptr)
207 throw ArgumentNullException(u"predicate");
208
209 const auto enumerator = enumerable.GetEnumerator();
210 while (enumerator->MoveNext())
211 {
212 T value = enumerator->get_Current();
213 if (predicate(value))
214 {
215 found = true;
216 return value;
217 }
218 }
219 found = false;
220 return T{};
221}
222
230template <typename T>
231T TryGetLast(IEnumerable<T>& enumerable, bool& found)
232{
233 if (IList<T>* list = dynamic_cast<IList<T>*>(&enumerable))
234 {
235 const auto count = list->get_Count();
236 if (count > 0)
237 {
238 found = true;
239 return list->idx_get(count - 1);
240 }
241 }
242 else
243 {
244 const auto enumerator = enumerable.GetEnumerator();
245 if (enumerator->MoveNext())
246 {
247 T value;
248 do
249 {
250 value = enumerator->get_Current();
251 } while (enumerator->MoveNext());
252
253 found = true;
254 return value;
255 }
256 }
257 found = false;
258 return T{};
259}
260
264template <typename Source, typename Result>
265class EnumeratorCastAdapter final : public IEnumerator<Result>
266{
267public:
268 EnumeratorCastAdapter(SharedPtr<IEnumerator<Source>> sourceEnumerator)
269 : m_sourceEnumerator(sourceEnumerator)
270 {}
271
272 MakeConstRef_t<Result> get_Current() const override
273 {
274 m_current = CastRules::Cast<Source, Result>(m_sourceEnumerator->get_Current());
275 return m_current;
276 }
277
278 bool MoveNext() override
279 {
280 return m_sourceEnumerator->MoveNext();
281 }
282
283 void Reset() override
284 {
285 m_sourceEnumerator->Reset();
286 }
287
288 System::Details::VirtualizedIteratorBase<Result>* CloneIterator() const override
289 {
290 return new EnumeratorCastAdapter(*this);
291 }
292
293private:
294 SharedPtr<IEnumerator<Source>> m_sourceEnumerator;
295 mutable Result m_current;
296};
297
301template <typename Source, typename Result>
302class EnumeratorOfTypeAdapter final : public IEnumerator<Result>
303{
304public:
305 EnumeratorOfTypeAdapter(SharedPtr<IEnumerator<Source>> sourceEnumerator)
306 : m_sourceEnumerator(sourceEnumerator)
307 {}
308
309 MakeConstRef_t<Result> get_Current() const override
310 {
311 m_current = CastRules::Cast<Source, Result>(m_sourceEnumerator->get_Current());
312 return m_current;
313 }
314
315 bool MoveNext() override
316 {
317 while (m_sourceEnumerator->MoveNext())
318 {
319 if (CastRules::CanCast<Source, Result>(m_sourceEnumerator->get_Current()))
320 return true;
321 }
322
323 m_current = System::Default<Result>();
324 return false;
325 }
326
327 void Reset() override
328 {
329 m_sourceEnumerator->Reset();
330 }
331
332 System::Details::VirtualizedIteratorBase<Result>* CloneIterator() const override
333 {
334 return new EnumeratorOfTypeAdapter(*this);
335 }
336
337private:
338 SharedPtr<IEnumerator<Source>> m_sourceEnumerator;
339 mutable Result m_current;
340};
341
345template <typename Source, typename Result>
346class EnumeratorSelectAdapter final : public IEnumerator<Result>
347{
348public:
349 EnumeratorSelectAdapter(SharedPtr<IEnumerator<Source>> sourceEnumerator, const Func<Source, Result>& selector)
350 : m_sourceEnumerator(sourceEnumerator)
351 , m_selector(selector)
352 {}
353
354 MakeConstRef_t<Result> get_Current() const override
355 {
356 m_current = m_selector(m_sourceEnumerator->get_Current());
357 return m_current;
358 }
359
360 bool MoveNext() override
361 {
362 return m_sourceEnumerator->MoveNext();
363 }
364
365 void Reset() override
366 {
367 m_sourceEnumerator->Reset();
368 }
369
370 System::Details::VirtualizedIteratorBase<Result>* CloneIterator() const override
371 {
372 return new EnumeratorSelectAdapter(*this);
373 }
374
375private:
376 SharedPtr<IEnumerator<Source>> m_sourceEnumerator;
377 Func<Source, Result> m_selector;
378 mutable Result m_current;
379};
380
381template <typename Source, typename Result>
382class EnumeratorSelectIndexAdapter final : public IEnumerator<Result>
383{
384public:
385 EnumeratorSelectIndexAdapter(SharedPtr<IEnumerator<Source>> sourceEnumerator, const Func<Source, int32_t, Result>& selector)
386 : m_sourceEnumerator(sourceEnumerator), m_selector(selector), index(-1)
387 {}
388
389 MakeConstRef_t<Result> get_Current() const override
390 {
391 m_current = m_selector(m_sourceEnumerator->get_Current(), index);
392 return m_current;
393 }
394
395 bool MoveNext() override
396 {
397 index++;
398 return m_sourceEnumerator->MoveNext();
399 }
400
401 void Reset() override
402 {
403 index = -1;
404 m_sourceEnumerator->Reset();
405 }
406
407 System::Details::VirtualizedIteratorBase<Result>* CloneIterator() const override
408 {
409 return new EnumeratorSelectIndexAdapter(*this);
410 }
411
412private:
413 SharedPtr<IEnumerator<Source>> m_sourceEnumerator;
414 Func<Source, int32_t, Result> m_selector;
415 int index;
416 mutable Result m_current;
417};
418
419
424template <typename Source, typename Result, typename EnumeratorAdapter>
425class EnumerableAdapter final : public IEnumerable<Result>
426{
427public:
428 EnumerableAdapter(SharedPtr<IEnumerable<Source>> sourceEnumerable)
429 : m_sourceEnumerable(sourceEnumerable)
430 {}
431
432 SharedPtr<IEnumerator<Result>> GetEnumerator() override
433 {
434 return MakeObject<EnumeratorAdapter>(m_sourceEnumerable->GetEnumerator());
435 }
436
437private:
438 SharedPtr<IEnumerable<Source>> m_sourceEnumerable;
439};
440
444template <typename Source, typename Result>
445class EnumerableSelectAdapter final : public IEnumerable<Result>
446{
447public:
448 EnumerableSelectAdapter(SharedPtr<IEnumerable<Source>> sourceEnumerable, const Func<Source, Result>& selector)
449 : m_sourceEnumerable(sourceEnumerable)
450 , m_selector(selector)
451 {}
452
453 SharedPtr<IEnumerator<Result>> GetEnumerator() override
454 {
455 return MakeObject<EnumeratorSelectAdapter<Source, Result>>(m_sourceEnumerable->GetEnumerator(), m_selector);
456 }
457
458private:
459 SharedPtr<IEnumerable<Source>> m_sourceEnumerable;
460 Func<Source, Result> m_selector;
461};
462
463template <typename Source, typename Result>
464class EnumerableSelectIndexAdapter final : public IEnumerable<Result>
465{
466public:
467 EnumerableSelectIndexAdapter(SharedPtr<IEnumerable<Source>> sourceEnumerable, const Func<Source, int32_t, Result>& selector)
468 : m_sourceEnumerable(sourceEnumerable), m_selector(selector)
469 {}
470
471 SharedPtr<IEnumerator<Result>> GetEnumerator() override
472 {
473 return MakeObject<EnumeratorSelectIndexAdapter<Source, Result>>(m_sourceEnumerable->GetEnumerator(), m_selector);
474 }
475
476private:
477 SharedPtr<IEnumerable<Source>> m_sourceEnumerable;
478 Func<Source, int32_t, Result> m_selector;
479};
480
481template <typename Source, typename Result>
482class EnumeratorSelectManyAdapter final : public IEnumerator<Result>
483{
484public:
485 EnumeratorSelectManyAdapter(SharedPtr<IEnumerator<Source>> baseEnumerator,
486 const Func<Source, SharedPtr<IEnumerable<Result>>>& selector)
487 : m_baseEnumerator(baseEnumerator), m_selector(selector)
488 {}
489
490 MakeConstRef_t<Result> get_Current() const override
491 {
492 return m_nestedEnumerator->get_Current();
493 }
494
495 bool MoveNext() override
496 {
497 if (m_nestedEnumerator != nullptr)
498 {
499 if (m_nestedEnumerator->MoveNext())
500 {
501 return true;
502 }
503 }
504
505 while (m_baseEnumerator->MoveNext())
506 {
507 Source currentSource = m_baseEnumerator->get_Current();
508
509 m_nestedEnumerator = m_selector(currentSource)->GetEnumerator();
510
511 if (m_nestedEnumerator->MoveNext())
512 {
513 return true;
514 }
515 }
516 return false;
517
518 }
519
520 void Reset() override
521 {
522 m_baseEnumerator->Reset();
523 DisposeNestedEnumerator();
524 }
525
526 System::Details::VirtualizedIteratorBase<Result>* CloneIterator() const override
527 {
528 return new EnumeratorSelectManyAdapter(*this);
529 }
530
531private:
532
533 void DisposeNestedEnumerator()
534 {
535 if (m_nestedEnumerator == nullptr)
536 return;
537 m_nestedEnumerator->Dispose();
538 m_nestedEnumerator = nullptr;
539 }
540
541 SharedPtr<IEnumerator<Source>> m_baseEnumerator;
542 SharedPtr<IEnumerator<Result>> m_nestedEnumerator;
543 Func<Source, SharedPtr<IEnumerable<Result>>> m_selector;
544};
545
546
547template <typename Source, typename Result>
548class EnumerableSelectManyAdapter final : public IEnumerable<Result>
549{
550public:
551 EnumerableSelectManyAdapter(SharedPtr<IEnumerable<Source>> sourceEnumerable,
552 const Func<Source, SharedPtr<IEnumerable<Result>>>& selector)
553 : m_sourceEnumerable(sourceEnumerable), m_selector(selector)
554 {}
555
556 SharedPtr<IEnumerator<Result>> GetEnumerator() override
557 {
558 return MakeObject<EnumeratorSelectManyAdapter<Source, Result>>(m_sourceEnumerable->GetEnumerator(),
559 m_selector);
560 }
561
562private:
563 SharedPtr<IEnumerable<Source>> m_sourceEnumerable;
564 Func<Source, SharedPtr<IEnumerable<Result>>> m_selector;
565};
566
567
568template <typename Key, typename Source>
569class Grouping final : public System::Linq::IGrouping<Key, Source>
570{
571public:
572 Grouping(Key key, System::Func<bool> hasNext) : m_key(key)
573 {
574 groupCachedEnumerable = System::MakeObject<System::Linq::Details::CachedEnumerable<Source>>(hasNext);
575 }
576
577 virtual Key get_Key() override
578 {
579 return m_key;
580 }
581
582 SharedPtr<IEnumerator<Source>> GetEnumerator() override
583 {
584 return groupCachedEnumerable->GetEnumerator();
585 }
586
587 void Add(Source item)
588 {
589 groupCachedEnumerable->Add(item);
590 }
591
592private:
593 Key m_key;
595
596};
597
598template <typename Source, typename Key>
599class GroupEnumerable final : public IEnumerable<SharedPtr<System::Linq::IGrouping<Key, Source>>>
600{
601public:
602 GroupEnumerable(SharedPtr<IEnumerable<Source>> sourceEnumerable, const Func<Source, Key>& keyPredicate)
603 : m_sourceEnumerable(sourceEnumerable)
604 , m_keyPredicate(keyPredicate)
605 {
606 groups = System::MakeObject<System::Collections::Generic::Dictionary<Key, System::SharedPtr<Grouping<Key, Source>>>>();
607 m_sourceEnumerator = m_sourceEnumerable->GetEnumerator();
608
609 System::Func<bool> hasNext = [&]() { return FindNextGroup(); };
610 groupsCachedEnumerable = System::MakeObject<System::Linq::Details::CachedEnumerable<System::SharedPtr<System::Linq::IGrouping<Key, Source>>>>(hasNext);
611 }
612
613 SharedPtr<IEnumerator<SharedPtr<System::Linq::IGrouping<Key, Source>>>> GetEnumerator() override
614 {
615 return groupsCachedEnumerable->GetEnumerator();
616 }
617
618private:
619
620 bool FindNextGroup()
621 {
622 while (true)
623 {
624 if (!m_sourceEnumerator->MoveNext())
625 {
626 return false;
627 }
628 auto current = m_sourceEnumerator->get_Current();
629 auto key = m_keyPredicate(current);
630 bool isNewGroup = !groups->ContainsKey(key);
631 group = isNewGroup ? System::MakeObject<Grouping<Key, Source>>(key, [this, key]() { return FindNextForKey(key); }) : groups->idx_get(key);
632
633 if (isNewGroup)
634 {
635 groups->Add(key, group);
636 groupsCachedEnumerable->Add(group);
637 }
638 group->Add(current);
639 if (isNewGroup)
640 {
641 return true;
642 }
643 }
644 return false;
645 }
646
647 bool FindNextForKey(Key groupKey)
648 {
649 while (true)
650 {
651 if (!m_sourceEnumerator->MoveNext())
652 {
653 return false;
654 }
655 auto current = m_sourceEnumerator->get_Current();
656 auto key = m_keyPredicate(current);
657 bool isNewGroup = !groups->ContainsKey(key);
658 group = isNewGroup ? System::MakeObject<Grouping<Key, Source>>(key, [this, key]() { return FindNextForKey(key); }) : groups->idx_get(key);
659
660 if (isNewGroup)
661 {
662 groups->Add(key, group);
663 groupsCachedEnumerable->Add(group);
664 }
665 group->Add(current);
666 if (Equals(groupKey, key))
667 {
668 return true;
669 }
670 }
671 return false;
672 }
673
675
678 SharedPtr<IEnumerable<Source>> m_sourceEnumerable;
679 SharedPtr<IEnumerator<Source>> m_sourceEnumerator;
680 Func<Source, Key> m_keyPredicate;
681};
682
683
684} // namespace Details
685
686template <typename T>
688{
689 auto enumerator = GetEnumerator();
690 if (!enumerator->MoveNext())
691 {
692 throw InvalidOperationException(u"The source sequence is empty");
693 }
694 auto result = enumerator->Current();
695 while (enumerator->MoveNext())
696 {
697 result = func(result, enumerator->Current());
698 }
699
700 return result;
701}
702
703template<typename T>
705{
706 if (index >= 0)
707 {
708 auto enumerator = GetEnumerator();
709 while (enumerator->MoveNext())
710 {
711 if (index == 0)
712 {
713 return enumerator->Current();
714 }
715 index--;
716 }
717 }
718
719 throw ArgumentOutOfRangeException(u"index");
720}
721
722template <typename T>
724{
725 if (index >= 0)
726 {
727 auto enumerator = GetEnumerator();
728 while (enumerator->MoveNext())
729 {
730 if (index == 0)
731 {
732 return enumerator->Current();
733 }
734 index--;
735 }
736 }
737
738 return System::Default<T>();
739}
740
741template<typename T>
743{
744 bool found = false;
745 T first = Details::TryGetFirst(*this, found);
746 if (!found)
747 throw InvalidOperationException(u"The source sequence is empty");
748
749 return first;
750}
751
752template<typename T>
754{
755 bool found = false;
756 T first = Details::TryGetFirst(*this, predicate, found);
757 if (!found)
758 throw InvalidOperationException(u"No element satisfies the specified condition");
759
760 return first;
761}
762
763template<typename T>
765{
766 bool found = false;
767 return Details::TryGetFirst(*this, found);
768}
769
770template<typename T>
772{
773 bool found = false;
774 T last = Details::TryGetLast(*this, found);
775 if (!found)
776 throw InvalidOperationException(u"The source sequence is empty.");
777
778 return last;
779}
780
781template<typename T>
783{
784 bool found = false;
785 return Details::TryGetLast(*this, found);
786}
787
788template<typename T>
790{
791 //return System::MakeObject<Collections::Generic::List<T>>(GetEnumerator());
792 auto list = System::MakeObject<Collections::Generic::List<T>>();
793 auto enumerator = GetEnumerator();
794 while (enumerator->MoveNext())
795 {
796 list->Add(enumerator->Current());
797 }
798 return list;
799}
800
801template<typename T>
803{
804 int count = 0;
805 auto enumerator = GetEnumerator();
806 while (enumerator->MoveNext())
807 {
808 count++;
809 }
810 return count;
811}
812
813template<typename T>
815{
816 if (predicate == nullptr)
817 throw ArgumentNullException(u"predicate");
818
819 int count = 0;
820 auto enumerator = GetEnumerator();
821 while (enumerator->MoveNext())
822 {
823 if (predicate(enumerator->get_Current()))
824 {
825 count++;
826 }
827 }
828 return count;
829}
830
831template<typename T>
833{
834 return LINQ_ToList()->ToArray();
835}
836
837template <typename T>
838bool IEnumerable<T>::LINQ_All(std::function<bool(T)> predicate)
839{
840 if (!predicate)
841 throw ArgumentNullException(u"predicate");
842
843 auto enumerator = GetEnumerator();
844 while (enumerator->MoveNext())
845 if (!predicate(enumerator->Current()))
846 return false;
847 return true;
848}
849
850template <typename T>
852{
853 auto enumerator = GetEnumerator();
854 if (enumerator->MoveNext())
855 return true;
856 return false;
857}
858
859template <typename T>
860bool IEnumerable<T>::LINQ_Any(std::function<bool(T)> predicate)
861{
862 if (!predicate)
863 throw ArgumentNullException(u"predicate");
864
865 auto enumerator = GetEnumerator();
866 while (enumerator->MoveNext())
867 if (predicate(enumerator->Current()))
868 return true;
869 return false;
870}
871
872template <typename T>
873T IEnumerable<T>::LINQ_FirstOrDefault(std::function<bool(T)> predicate)
874{
875 if (!predicate)
876 throw ArgumentNullException(u"predicate");
877
878 auto enumerator = GetEnumerator();
879 while (enumerator->MoveNext())
880 {
881 T val = enumerator->Current();
882 if (predicate(val))
883 return val;
884 }
885 return T();
886}
887
888template <typename T>
889SharedPtr<IEnumerable<T>> IEnumerable<T>::LINQ_Where(std::function<bool(T)> predicate)
890{
891 if (!predicate)
892 throw ArgumentNullException(u"predicate");
893
894 auto list = System::MakeObject<Collections::Generic::List<T>>();
895 auto enumerator = GetEnumerator();
896 while (enumerator->MoveNext())
897 {
898 T val = enumerator->Current();
899 if (predicate(val))
900 list->Add(val);
901 }
902 return static_cast<SharedPtr<IEnumerable<T>>>(list);
903}
904
905template <typename T>
907{
908 const auto enumerator = GetEnumerator();
909 while (enumerator->MoveNext())
910 {
911 if (System::Details::AreEqual(value, enumerator->get_Current()))
912 return true;
913 }
914 return false;
915}
916
917template <typename Source>
918template <typename Result>
920{
921 using EnumeratorAdapter = Details::EnumeratorCastAdapter<Source, Result>;
922 using EnumerableAdapter = Details::EnumerableAdapter<Source, Result, EnumeratorAdapter>;
923 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this));
924}
925
926template <typename Source>
927template <typename Result>
929{
930 using EnumeratorAdapter = Details::EnumeratorOfTypeAdapter<Source, Result>;
931 using EnumerableAdapter = Details::EnumerableAdapter<Source, Result, EnumeratorAdapter>;
932 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this));
933}
934
935template <typename Source>
936template <typename Result>
938{
939 if (selector == nullptr)
940 throw ArgumentNullException(u"selector");
941
942 using EnumerableAdapter = Details::EnumerableSelectAdapter<Source, Result>;
943 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), selector);
944}
945
946template <typename Source>
947template <typename Result>
949{
950 if (selector == nullptr)
951 throw ArgumentNullException(u"selector");
952
953 using EnumerableAdapter = Details::EnumerableSelectIndexAdapter<Source, Result>;
954 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), selector);
955}
956
957
958template <typename Source>
959template <typename Key>
961{
962 auto keys = LINQ_Select(keySelector)->LINQ_ToArray();
963 auto items = LINQ_ToArray();
964 items->Sort(keys, items);
965 return System::MakeObject<Linq::IOrderedEnumerable<Source>>(
966 items,
967 [keySelector](const Source& left, const Source& right) { return keySelector(left) == keySelector(right); });
968}
969
970template <typename Source>
971template <typename Key>
973{
974 auto keys = LINQ_Select(keySelector)->LINQ_ToArray();
975 auto items = LINQ_ToArray();
976 items->Sort(keys, items);
977 std::reverse(items->begin(), items->end());
978 return System::MakeObject<Linq::IOrderedEnumerable<Source>>(
979 items,
980 [keySelector](const Source& left, const Source& right) { return keySelector(left) == keySelector(right); });
981}
982
983template <typename Source>
985{
986 auto first = LINQ_ToList();
987 auto second = sequence->LINQ_ToList();
988
989 first->AddRange(second);
990
991 return first;
992}
993
994template <typename Source>
996{
997 auto items = LINQ_ToArray();
998 std::reverse(items->begin(), items->end());
999 return items;
1000}
1001
1002template <typename Source>
1003template <typename Key>
1006{
1007 if (keyPredicate == nullptr)
1008 throw ArgumentNullException(u"keyPredicate");
1009
1010 using EnumerableAdapter = Details::GroupEnumerable<Source, Key>;
1011 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), keyPredicate);
1012}
1013
1014template <typename Source>
1015template <typename Result>
1018{
1019 if (selector == nullptr)
1020 throw ArgumentNullException(u"selector");
1021
1022 using EnumerableAdapter = Details::EnumerableSelectManyAdapter<Source, Result>;
1023 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), selector);
1024}
1025
1026template <typename Source>
1028{
1029 auto result = LINQ_ToList();
1030 auto currentCount = result->get_Count();
1031 if (currentCount > count)
1032 {
1033 result->RemoveRange(count, currentCount - count);
1034 }
1035 return result;
1036}
1037
1038template <typename Source>
1039template <typename ResultType>
1041{
1042 auto enumerator = GetEnumerator();
1043 if (!enumerator->MoveNext())
1044 throw InvalidOperationException(u"Collection is empty");
1045
1046 auto result = selector(enumerator->get_Current());
1047 while (enumerator->MoveNext())
1048 {
1049 auto candidate = selector(enumerator->get_Current());
1050 if (candidate < result)
1051 result = candidate;
1052 }
1053
1054 return result;
1055}
1056
1057template <typename Source>
1058template <typename ResultType>
1060{
1061 auto enumerator = GetEnumerator();
1062 if (!enumerator->MoveNext())
1063 throw InvalidOperationException(u"Collection is empty");
1064
1065 auto result = selector(enumerator->get_Current());
1066 while (enumerator->MoveNext())
1067 {
1068 auto candidate = selector(enumerator->get_Current());
1069 if (candidate > result)
1070 result = candidate;
1071 }
1072
1073 return result;
1074}
1075
1076}}} // namespace System::Collections::Generic
1077
1078namespace System { namespace Linq {
1079
1080template <typename Source>
1081template <typename Key>
1083{
1084 auto items = m_root->LINQ_ToArray();
1085
1086 auto begin = items->begin();
1087 while (begin != items->end())
1088 {
1089 auto end = std::next(begin);
1090 while (end != items->end() && m_comparator(*begin, *end))
1091 {
1092 ++end;
1093 }
1094
1095 std::stable_sort(begin, end, [&](const Source& left, const Source& right){return keySelector(left) < keySelector(right);});
1096
1097 begin = end;
1098 }
1099
1100 return System::MakeObject<IOrderedEnumerable<Source>>(
1101 items,
1102 [comp = m_comparator, keySelector](const Source& left, const Source& right)
1103 {
1104 return comp(left, right) && keySelector(left) == keySelector(right);
1105 });
1106}
1107
1108}} // namespace System::Linq
Interface of object providing enumerator on contained elements.
Definition: ienumerable.h:25
bool LINQ_Contains(T value)
Determines if a sequence contains a specified value.
Definition: enumerable.h:906
T LINQ_ElementAtOrDefault(int index)
Returns the element at a specified index in a sequence.
Definition: enumerable.h:723
bool LINQ_All(std::function< bool(T)> predicate)
Determines whether all elements of a sequence satisfy a condition.
Definition: enumerable.h:838
SharedPtr< IEnumerable< T > > LINQ_Where(std::function< bool(T)> predicate)
Filters a sequence based on the specified predicate.
Definition: enumerable.h:889
T LINQ_LastOrDefault()
Returns the last element of a sequence, or a default value if the sequence is empty.
Definition: enumerable.h:782
bool LINQ_Any()
Determines whether a sequence contains any elements.
Definition: enumerable.h:851
System::ArrayPtr< T > LINQ_ToArray()
Creates an array from a sequence.
Definition: enumerable.h:832
T LINQ_ElementAt(int index)
Returns the element at a specified index in a sequence.
Definition: enumerable.h:704
T LINQ_Aggregate(const Func< T, T, T > &func)
Applies an accumulator function over a sequence.
Definition: enumerable.h:687
T LINQ_FirstOrDefault()
Returns the first element of a sequence, or a default value if the sequence is empty.
Definition: enumerable.h:764
SharedPtr< IEnumerable< ResultType > > LINQ_Cast()
Casts the elements to the specified type.
T LINQ_First()
Returns the first element of a sequence.
Definition: enumerable.h:742
SharedPtr< List< T > > LINQ_ToList()
Creates a List<T> from a sequence.
Definition: enumerable.h:789
virtual SharedPtr< IEnumerator< Result > > GetEnumerator()=0
Gets enumerator.
T LINQ_Last()
Returns the last element of a sequence.
Definition: enumerable.h:771
int LINQ_Count()
Returns the number of elements in the sequence (calculated via direct counting).
Definition: enumerable.h:802
Interface of enumerator which can be used to iterate through some elements. Objects of this class sho...
Definition: ienumerator.h:63
virtual MakeConstRef_t< Result > get_Current() const=0
Gets current element.
virtual bool MoveNext()=0
Moves enumerator to the next element. If no element was referenced before, sets reference to the firs...
System::Details::VirtualizedIteratorBase< Result > * CloneIterator() const override
Clones current iterator.
Definition: ienumerator.h:129
virtual void Reset()
Resets enumerator to position before first element.
Definition: ienumerator.h:97
Interface of indexed container of elements. Objects of this class should only be allocated using Syst...
Definition: ilist.h:19
Internal utility class Implements IEnumerable over queue of items.
Definition: enumerable.h:69
void Add(TItem item)
Definition: enumerable.h:126
System::SharedPtr< System::Collections::Generic::IEnumerator< TItem > > GetEnumerator() override
Gets enumerator.
Definition: enumerable.h:121
CachedEnumerable(System::Func< bool > requestNext)
Definition: enumerable.h:116
Implements the IEnumerable interface for an empty generic collection.
Definition: enumerable.h:53
SharedPtr< Collections::Generic::IEnumerator< T > > GetEnumerator() override
Gets enumerator.
Definition: enumerable.h:57
Implements the IEnumerator interface for an empty generic collection.
Definition: enumerable.h:25
bool MoveNext() override
Moves enumerator to the next element. If no element was referenced before, sets reference to the firs...
Definition: enumerable.h:34
MakeConstRef_t< T > get_Current() const override
Gets current element.
Definition: enumerable.h:29
void Reset() override
Resets enumerator to position before first element.
Definition: enumerable.h:39
System::Details::VirtualizedIteratorBase< T > * CloneIterator() const override
Definition: enumerable.h:43
Provides static LINQ methods.
Definition: enumerable.h:140
static SharedPtr< Collections::Generic::IEnumerable< int32_t > > Range(int32_t start, int32_t count)
Generates a sequence of integral numbers within a specified range.
static SharedPtr< Collections::Generic::IEnumerable< T > > Empty()
Returns an empty IEnumerable object.
Definition: enumerable.h:144
Definition: igrouping.h:11
SharedPtr< IOrderedEnumerable< T > > LINQ_ThenBy(const Func< T, Key > &keySelector)
Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
Pointer class to wrap types being allocated on heap. Use it to manage memory for classes inheriting O...
Definition: smart_ptr.h:180
Definition: db_command.h:9
bool Equals(const TA &a, const TB &b)
Determines the equality of two values applying operator==() to them.
Definition: primitive_types.h:77
SmartPtr< X > MakeSharedPtr(X *p)
Converts raw pointer to smart pointer.
Definition: smart_ptr.h:1650
SmartPtr< T > SharedPtr
Alias for smart pointer widely used in the library.
Definition: smart_ptr.h:1779
typename MakeConstRef< T >::type MakeConstRef_t
Helper type for MakeConstRef modifier.
Definition: make_const_ref.h:20