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, typename Element = Source>
599class GroupEnumerable final : public IEnumerable<SharedPtr<System::Linq::IGrouping<Key, Element>>>
600{
601public:
602 GroupEnumerable(SharedPtr<IEnumerable<Source>> sourceEnumerable, const Func<Source, Key>& keyPredicate,
603 const System::Func<Source, Element>& elementSelector =
604 System::Func<Source, Element>([](const Source& s) { return s; }))
605 : m_sourceEnumerable(sourceEnumerable)
606 , m_keyPredicate(keyPredicate)
607 , m_elementSelector(elementSelector)
608 {
609 groups = System::MakeObject<System::Collections::Generic::Dictionary<Key, System::SharedPtr<Grouping<Key, Element>>>>();
610 m_sourceEnumerator = m_sourceEnumerable->GetEnumerator();
611
612 System::Func<bool> hasNext = [&]() { return FindNextGroup(); };
613 groupsCachedEnumerable = System::MakeObject<System::Linq::Details::CachedEnumerable<System::SharedPtr<System::Linq::IGrouping<Key, Element>>>>(hasNext);
614 }
615
616 SharedPtr<IEnumerator<SharedPtr<System::Linq::IGrouping<Key, Element>>>> GetEnumerator() override
617 {
618 return groupsCachedEnumerable->GetEnumerator();
619 }
620
621private:
622
623 bool FindNextGroup()
624 {
625 while (true)
626 {
627 if (!m_sourceEnumerator->MoveNext())
628 {
629 return false;
630 }
631 auto current = m_sourceEnumerator->get_Current();
632 auto key = m_keyPredicate(current);
633 bool isNewGroup = !groups->ContainsKey(key);
634 group = isNewGroup ? System::MakeObject<Grouping<Key, Element>>(key, [this, key]() { return FindNextForKey(key); }) : groups->idx_get(key);
635
636 if (isNewGroup)
637 {
638 groups->Add(key, group);
639 groupsCachedEnumerable->Add(group);
640 }
641 group->Add(m_elementSelector(current));
642 if (isNewGroup)
643 {
644 return true;
645 }
646 }
647 return false;
648 }
649
650 bool FindNextForKey(Key groupKey)
651 {
652 while (true)
653 {
654 if (!m_sourceEnumerator->MoveNext())
655 {
656 return false;
657 }
658 auto current = m_sourceEnumerator->get_Current();
659 auto key = m_keyPredicate(current);
660 bool isNewGroup = !groups->ContainsKey(key);
661 group = isNewGroup ? System::MakeObject<Grouping<Key, Element>>(key, [this, key]() { return FindNextForKey(key); }) : groups->idx_get(key);
662
663 if (isNewGroup)
664 {
665 groups->Add(key, group);
666 groupsCachedEnumerable->Add(group);
667 }
668 group->Add(m_elementSelector(current));
669 if (Equals(groupKey, key))
670 {
671 return true;
672 }
673 }
674 return false;
675 }
676
678
681 SharedPtr<IEnumerable<Source>> m_sourceEnumerable;
682 SharedPtr<IEnumerator<Source>> m_sourceEnumerator;
683 Func<Source, Key> m_keyPredicate;
684 Func<Source, Element> m_elementSelector;
685};
686
687
688} // namespace Details
689
690template <typename T>
692{
693 auto enumerator = GetEnumerator();
694 if (!enumerator->MoveNext())
695 {
696 throw InvalidOperationException(u"The source sequence is empty");
697 }
698 auto result = enumerator->Current();
699 while (enumerator->MoveNext())
700 {
701 result = func(result, enumerator->Current());
702 }
703
704 return result;
705}
706
707template<typename T>
709{
710 if (index >= 0)
711 {
712 auto enumerator = GetEnumerator();
713 while (enumerator->MoveNext())
714 {
715 if (index == 0)
716 {
717 return enumerator->Current();
718 }
719 index--;
720 }
721 }
722
723 throw ArgumentOutOfRangeException(u"index");
724}
725
726template <typename T>
728{
729 if (index >= 0)
730 {
731 auto enumerator = GetEnumerator();
732 while (enumerator->MoveNext())
733 {
734 if (index == 0)
735 {
736 return enumerator->Current();
737 }
738 index--;
739 }
740 }
741
742 return System::Default<T>();
743}
744
745template<typename T>
747{
748 bool found = false;
749 T first = Details::TryGetFirst(*this, found);
750 if (!found)
751 throw InvalidOperationException(u"The source sequence is empty");
752
753 return first;
754}
755
756template<typename T>
758{
759 bool found = false;
760 T first = Details::TryGetFirst(*this, predicate, found);
761 if (!found)
762 throw InvalidOperationException(u"No element satisfies the specified condition");
763
764 return first;
765}
766
767template<typename T>
769{
770 bool found = false;
771 return Details::TryGetFirst(*this, found);
772}
773
774template<typename T>
776{
777 bool found = false;
778 T last = Details::TryGetLast(*this, found);
779 if (!found)
780 throw InvalidOperationException(u"The source sequence is empty.");
781
782 return last;
783}
784
785template<typename T>
787{
788 bool found = false;
789 return Details::TryGetLast(*this, found);
790}
791
792template<typename T>
794{
795 //return System::MakeObject<Collections::Generic::List<T>>(GetEnumerator());
796 auto list = System::MakeObject<Collections::Generic::List<T>>();
797 auto enumerator = GetEnumerator();
798 while (enumerator->MoveNext())
799 {
800 list->Add(enumerator->Current());
801 }
802 return list;
803}
804
805template<typename T>
807{
808 int count = 0;
809 auto enumerator = GetEnumerator();
810 while (enumerator->MoveNext())
811 {
812 count++;
813 }
814 return count;
815}
816
817template<typename T>
819{
820 if (predicate == nullptr)
821 throw ArgumentNullException(u"predicate");
822
823 int count = 0;
824 auto enumerator = GetEnumerator();
825 while (enumerator->MoveNext())
826 {
827 if (predicate(enumerator->get_Current()))
828 {
829 count++;
830 }
831 }
832 return count;
833}
834
835template<typename T>
837{
838 return LINQ_ToList()->ToArray();
839}
840
841template <typename T>
842bool IEnumerable<T>::LINQ_All(std::function<bool(T)> predicate)
843{
844 if (!predicate)
845 throw ArgumentNullException(u"predicate");
846
847 auto enumerator = GetEnumerator();
848 while (enumerator->MoveNext())
849 if (!predicate(enumerator->Current()))
850 return false;
851 return true;
852}
853
854template <typename T>
856{
857 auto enumerator = GetEnumerator();
858 if (enumerator->MoveNext())
859 return true;
860 return false;
861}
862
863template <typename T>
864bool IEnumerable<T>::LINQ_Any(std::function<bool(T)> predicate)
865{
866 if (!predicate)
867 throw ArgumentNullException(u"predicate");
868
869 auto enumerator = GetEnumerator();
870 while (enumerator->MoveNext())
871 if (predicate(enumerator->Current()))
872 return true;
873 return false;
874}
875
876template <typename T>
877T IEnumerable<T>::LINQ_FirstOrDefault(std::function<bool(T)> predicate)
878{
879 if (!predicate)
880 throw ArgumentNullException(u"predicate");
881
882 auto enumerator = GetEnumerator();
883 while (enumerator->MoveNext())
884 {
885 T val = enumerator->Current();
886 if (predicate(val))
887 return val;
888 }
889 return T();
890}
891
892template <typename T>
893SharedPtr<IEnumerable<T>> IEnumerable<T>::LINQ_Where(std::function<bool(T)> predicate)
894{
895 if (!predicate)
896 throw ArgumentNullException(u"predicate");
897
898 auto list = System::MakeObject<Collections::Generic::List<T>>();
899 auto enumerator = GetEnumerator();
900 while (enumerator->MoveNext())
901 {
902 T val = enumerator->Current();
903 if (predicate(val))
904 list->Add(val);
905 }
906 return static_cast<SharedPtr<IEnumerable<T>>>(list);
907}
908
909template <typename T>
911{
912 const auto enumerator = GetEnumerator();
913 while (enumerator->MoveNext())
914 {
915 if (System::Details::AreEqual(value, enumerator->get_Current()))
916 return true;
917 }
918 return false;
919}
920
921template <typename Source>
922template <typename Result>
924{
925 using EnumeratorAdapter = Details::EnumeratorCastAdapter<Source, Result>;
926 using EnumerableAdapter = Details::EnumerableAdapter<Source, Result, EnumeratorAdapter>;
927 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this));
928}
929
930template <typename Source>
931template <typename Result>
933{
934 using EnumeratorAdapter = Details::EnumeratorOfTypeAdapter<Source, Result>;
935 using EnumerableAdapter = Details::EnumerableAdapter<Source, Result, EnumeratorAdapter>;
936 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this));
937}
938
939template <typename Source>
940template <typename Result>
942{
943 if (selector == nullptr)
944 throw ArgumentNullException(u"selector");
945
946 using EnumerableAdapter = Details::EnumerableSelectAdapter<Source, Result>;
947 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), selector);
948}
949
950template <typename Source>
951template <typename Result>
953{
954 if (selector == nullptr)
955 throw ArgumentNullException(u"selector");
956
957 using EnumerableAdapter = Details::EnumerableSelectIndexAdapter<Source, Result>;
958 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), selector);
959}
960
961
962template <typename Source>
963template <typename Key>
965{
966 auto keys = LINQ_Select(keySelector)->LINQ_ToArray();
967 auto items = LINQ_ToArray();
968 items->Sort(keys, items);
969 return System::MakeObject<Linq::IOrderedEnumerable<Source>>(
970 items,
971 [keySelector](const Source& left, const Source& right) { return keySelector(left) == keySelector(right); });
972}
973
974template <typename Source>
975template <typename Key>
977{
978 auto keys = LINQ_Select(keySelector)->LINQ_ToArray();
979 auto items = LINQ_ToArray();
980 items->Sort(keys, items);
981 std::reverse(items->begin(), items->end());
982 return System::MakeObject<Linq::IOrderedEnumerable<Source>>(
983 items,
984 [keySelector](const Source& left, const Source& right) { return keySelector(left) == keySelector(right); });
985}
986
987template <typename Source>
989{
990 auto first = LINQ_ToList();
991 auto second = sequence->LINQ_ToList();
992
993 first->AddRange(second);
994
995 return first;
996}
997
998template <typename Source>
1000{
1001 auto items = LINQ_ToArray();
1002 std::reverse(items->begin(), items->end());
1003 return items;
1004}
1005
1006template <typename Source>
1007template <typename Key>
1010{
1011 if (keyPredicate == nullptr)
1012 throw ArgumentNullException(u"keyPredicate");
1013
1014 using EnumerableAdapter = Details::GroupEnumerable<Source, Key>;
1015 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), keyPredicate);
1016}
1017
1018template <typename Source>
1019template <typename Key, typename Element>
1022 System::Func<Source, Element> elementSelector)
1023{
1024 if (keyPredicate == nullptr)
1025 throw ArgumentNullException(u"keyPredicate");
1026 if (elementSelector == nullptr)
1027 throw ArgumentNullException(u"elementSelector");
1028
1029 using EnumerableAdapter = Details::GroupEnumerable<Source, Key, Element>;
1030 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), keyPredicate, elementSelector);
1031}
1032
1033template <typename Source>
1034template <typename Result>
1037{
1038 if (selector == nullptr)
1039 throw ArgumentNullException(u"selector");
1040
1041 using EnumerableAdapter = Details::EnumerableSelectManyAdapter<Source, Result>;
1042 return MakeObject<EnumerableAdapter>(MakeSharedPtr(this), selector);
1043}
1044
1045template <typename Source>
1047{
1048 auto result = LINQ_ToList();
1049 auto currentCount = result->get_Count();
1050 if (currentCount > count)
1051 {
1052 result->RemoveRange(count, currentCount - count);
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
1076template <typename Source>
1077template <typename ResultType>
1079{
1080 auto enumerator = GetEnumerator();
1081 if (!enumerator->MoveNext())
1082 throw InvalidOperationException(u"Collection is empty");
1083
1084 auto result = selector(enumerator->get_Current());
1085 while (enumerator->MoveNext())
1086 {
1087 auto candidate = selector(enumerator->get_Current());
1088 if (candidate > result)
1089 result = candidate;
1090 }
1091
1092 return result;
1093}
1094
1095}}} // namespace System::Collections::Generic
1096
1097namespace System { namespace Linq {
1098
1099template <typename Source>
1100template <typename Key>
1102{
1103 auto items = m_root->LINQ_ToArray();
1104
1105 auto begin = items->begin();
1106 while (begin != items->end())
1107 {
1108 auto end = std::next(begin);
1109 while (end != items->end() && m_comparator(*begin, *end))
1110 {
1111 ++end;
1112 }
1113
1114 std::stable_sort(begin, end, [&](const Source& left, const Source& right){return keySelector(left) < keySelector(right);});
1115
1116 begin = end;
1117 }
1118
1119 return System::MakeObject<IOrderedEnumerable<Source>>(
1120 items,
1121 [comp = m_comparator, keySelector](const Source& left, const Source& right)
1122 {
1123 return comp(left, right) && keySelector(left) == keySelector(right);
1124 });
1125}
1126
1127}} // 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:910
T LINQ_ElementAtOrDefault(int index)
Returns the element at a specified index in a sequence.
Definition: enumerable.h:727
bool LINQ_All(std::function< bool(T)> predicate)
Determines whether all elements of a sequence satisfy a condition.
Definition: enumerable.h:842
SharedPtr< IEnumerable< T > > LINQ_Where(std::function< bool(T)> predicate)
Filters a sequence based on the specified predicate.
Definition: enumerable.h:893
T LINQ_LastOrDefault()
Returns the last element of a sequence, or a default value if the sequence is empty.
Definition: enumerable.h:786
bool LINQ_Any()
Determines whether a sequence contains any elements.
Definition: enumerable.h:855
System::ArrayPtr< T > LINQ_ToArray()
Creates an array from a sequence.
Definition: enumerable.h:836
T LINQ_ElementAt(int index)
Returns the element at a specified index in a sequence.
Definition: enumerable.h:708
T LINQ_Aggregate(const Func< T, T, T > &func)
Applies an accumulator function over a sequence.
Definition: enumerable.h:691
T LINQ_FirstOrDefault()
Returns the first element of a sequence, or a default value if the sequence is empty.
Definition: enumerable.h:768
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:746
SharedPtr< List< T > > LINQ_ToList()
Creates a List<T> from a sequence.
Definition: enumerable.h:793
virtual SharedPtr< IEnumerator< Result > > GetEnumerator()=0
Gets enumerator.
T LINQ_Last()
Returns the last element of a sequence.
Definition: enumerable.h:775
int LINQ_Count()
Returns the number of elements in the sequence (calculated via direct counting).
Definition: enumerable.h:806
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