#ifndef FUNDAMENTAL_LIB_LINQ_H #define FUNDAMENTAL_LIB_LINQ_H #include "List.h" namespace CoreLib { namespace Basic { template T ConstructT(); template class RemoveReference { public: typedef T Type; }; template class RemoveReference { public: typedef T Type; }; template class RemoveReference { public: typedef T Type; }; template struct RemovePointer { typedef T Type; }; template struct RemovePointer { typedef T Type; }; template class ConcatQuery { private: TQueryable1 items1; TQueryable2 items2; public: ConcatQuery(const TQueryable1 & queryable1, const TQueryable2 & queryable2) : items1(queryable1), items2(queryable2) {} class Enumerator { private: TEnumerator1 ptr1; TEnumerator1 end1; TEnumerator2 ptr2; TEnumerator2 end2; public: Enumerator(const Enumerator &) = default; Enumerator(TEnumerator1 pptr, TEnumerator1 pend, TEnumerator2 pptr2, TEnumerator2 pend2) : ptr1(pptr), end1(pend), ptr2(pptr2), end2(pend2) {} T operator *() const { if (ptr1 != end1) return *(ptr1); else return *(ptr2); } Enumerator& operator ++() { if (ptr1 != end1) ++ptr1; else ++ptr2; return *this; } Enumerator operator ++(int) { Enumerator rs = *this; ++rs; return rs; } bool operator != (const Enumerator & iter) const { return ptr1 != iter.ptr1 || ptr2 != iter.ptr2; } bool operator == (const Enumerator & iter) const { return ptr1 == iter.ptr1 && ptr2 == iter.ptr2; } }; Enumerator begin() const { return Enumerator(items1.begin(), items1.end(), items2.begin(), items2.end()); } Enumerator end() const { return Enumerator(items1.end(), items1.end(), items2.end(), items2.end()); } }; template class WhereQuery { private: TQueryable items; TFunc func; public: WhereQuery(const TQueryable & queryable, const TFunc & f) : items(queryable), func(f) {} class Enumerator { private: TEnumerator ptr; TEnumerator end; const TFunc * func; public: Enumerator(const Enumerator &) = default; Enumerator(TEnumerator ptr, TEnumerator end, const TFunc & f) : ptr(ptr), end(end), func(&f) {} T operator *() const { return *(ptr); } Enumerator& operator ++() { ++ptr; while (ptr != end) { if ((*func)(*ptr)) break; else ++ptr; } return *this; } Enumerator operator ++(int) { Enumerator rs = *this; while (rs.ptr != end) { if ((*func)(*rs.ptr)) break; ++rs.ptr; } return rs; } bool operator != (const Enumerator & iter) const { return ptr != iter.ptr; } bool operator == (const Enumerator & iter) const { return ptr == iter.ptr; } }; Enumerator begin() const { auto ptr = items.begin(); auto end = items.end(); while (ptr != end) { if (func(*ptr)) break; ++ptr; } return Enumerator(ptr, end, func); } Enumerator end() const { return Enumerator(items.end(), items.end(), func); } }; template class SkipQuery { private: TQueryable items; int count = 0; public: SkipQuery(const TQueryable & queryable, int pCount) : items(queryable), count(pCount) {} class Enumerator { private: TEnumerator ptr; TEnumerator end; public: Enumerator(const Enumerator &) = default; Enumerator(TEnumerator pptr, TEnumerator pend) : ptr(pptr), end(pend) { } T operator *() const { return *(ptr); } Enumerator& operator ++() { ++ptr; return *this; } Enumerator operator ++(int) { Enumerator rs = *this; ++ptr; return rs; } bool operator != (const Enumerator & iter) const { return ptr != iter.ptr; } bool operator == (const Enumerator & iter) const { return ptr == iter.ptr; } }; Enumerator begin() const { auto ptr = items.begin(); auto end = items.end(); for (int i = 0; i < count; i++) if (ptr != end) ++ptr; return Enumerator(ptr, end); } Enumerator end() const { return Enumerator(items.end(), items.end()); } }; template class SelectQuery { private: TQueryable items; TFunc func; public: SelectQuery(const TQueryable & queryable, const TFunc & f) : items(queryable), func(f) {} class Enumerator { private: TEnumerator ptr; TEnumerator end; const TFunc * func; public: Enumerator(const Enumerator &) = default; Enumerator(TEnumerator ptr, TEnumerator end, const TFunc & f) : ptr(ptr), end(end), func(&f) {} auto operator *() const -> decltype((*func)(*ptr)) { return (*func)(*ptr); } Enumerator& operator ++() { ++ptr; return *this; } Enumerator operator ++(int) { Enumerator rs = *this; ++rs; return rs; } bool operator != (const Enumerator & iter) const { return !(ptr == iter.ptr); } bool operator == (const Enumerator & iter) const { return ptr == iter.ptr; } }; Enumerator begin() const { return Enumerator(items.begin(), items.end(), func); } Enumerator end() const { return Enumerator(items.end(), items.end(), func); } }; template class SelectManyQuery { private: TQueryable items; TFunc func; SelectManyQuery() {} public: SelectManyQuery(const TQueryable & queryable, const TFunc & f) : items(queryable), func(f) {} template class Enumerator { private: TEnumerator ptr; TEnumerator end; const TFunc * func; TItems items; TItemPtr subPtr; public: Enumerator(const Enumerator &) = default; Enumerator(TEnumerator ptr, TEnumerator end, const TFunc & f) : ptr(ptr), end(end), func(&f) { if (ptr != end) { items = f(*ptr); subPtr = items.begin(); } } auto operator *() const -> decltype(*subPtr) { return *subPtr; } Enumerator& operator ++() { ++subPtr; while (subPtr == items.end() && ptr != end) { ++ptr; if (ptr != end) { items = (*func)(*ptr); subPtr = items.begin(); } else break; } return *this; } Enumerator operator ++(int) { Enumerator rs = *this; ++rs; return rs; } bool operator != (const Enumerator & iter) const { return !operator==(iter); } bool operator == (const Enumerator & iter) const { if (ptr == iter.ptr) { if (ptr == end) return true; else return subPtr == iter.subPtr; } else return false; } }; auto begin() const ->Enumerator())), decltype(func(ConstructT()).begin())> { return Enumerator())), decltype(func(ConstructT()).begin())>(items.begin(), items.end(), func); } auto end() const ->Enumerator())), decltype(func(ConstructT()).begin())> { return Enumerator())), decltype(func(ConstructT()).begin())>(items.end(), items.end(), func); } }; template struct EnumeratorType { typedef decltype(ConstructT().begin()) Type; }; template class ExtractReturnType { public: static TFunc * f; static TArg ConstructArg() {}; typedef decltype((*f)(ConstructArg())) ReturnType; }; template class ExtractItemType { public: typedef typename RemovePointer().begin())>::Type Type; }; template class Queryable { private: TQueryable items; public: auto begin() const -> decltype(items.begin()) { return items.begin(); } auto end() const -> decltype(items.end()) { return items.end(); } public: const TQueryable & GetItems() const { return items; } Queryable(const TQueryable & items) : items(items) {} Queryable, typename SkipQuery::Enumerator, T> Skip(int count) const { return Queryable, typename SkipQuery::Enumerator, T>(SkipQuery(items, count)); } template Queryable, typename ConcatQuery::Enumerator, T> Concat(const Queryable & other) const { return Queryable, typename ConcatQuery::Enumerator, T>(ConcatQuery(this->items, other.GetItems())); } template Queryable, typename WhereQuery::Enumerator, T> Where(const TFunc & f) const { return Queryable, typename WhereQuery::Enumerator, T>(WhereQuery(items, f)); } template Queryable, typename SelectQuery::Enumerator, typename RemoveReference::ReturnType>::Type> Select(const TFunc & f) const { return Queryable, typename SelectQuery::Enumerator, typename RemoveReference::ReturnType>::Type>(SelectQuery(items, f)); } template auto SelectMany(const TFunc & f) const ->Queryable, typename EnumeratorType>::Type, typename ExtractItemType()))>::Type> { return Queryable, typename EnumeratorType>::Type, typename ExtractItemType()))>::Type>(SelectManyQuery(items, f)); } template auto Aggregate(const TAggregateResult & initial, const TFunc & f) const -> decltype(f(initial, *items.begin())) { TAggregateResult rs = initial; for (auto && x : items) rs = f(rs, x); return rs; } template bool Any(const TFunc & condition) const { for (auto && x : items) if (condition(x)) return true; return false; } template T & First(const TFunc & condition) const { for (auto && x : items) if (condition(x)) return x; } template T Max(const TFunc & selector) const { return Aggregate(*items.begin(), [&](const T & v0, const T & v1) { return selector(v0) > selector(v1) ? v0 : v1; }); } template T Min(const TFunc & selector) const { return Aggregate(*items.begin(), [&](const T & v0, const T & v1) { return selector(v0) < selector(v1) ? v0 : v1; }); } template auto Sum(const TFunc & selector) const -> decltype(selector(ConstructT())) { decltype(selector(ConstructT())) rs(0); for (auto && x : items) rs = rs + selector(x); return rs; } T Max() const { return Aggregate(*items.begin(), [](const T & v0, const T & v1) {return v0 > v1 ? v0 : v1; }); } T Min() const { return Aggregate(*items.begin(), [](const T & v0, const T & v1) {return v0 < v1 ? v0 : v1; }); } T Sum() const { T rs = T(0); for (auto && x : items) rs = rs + x; return rs; } T Avg() const { T rs = T(0); int count = 0; for (auto && x : items) { rs = rs + x; count++; } return rs / count; } int Count() const { int rs = 0; for (auto && x : items) rs++; return rs; } List ToList() const { List rs; for (auto && val : items) rs.Add(val); return rs; } }; template inline Queryable, T*, T> From(const List & list) { return Queryable, T*, T>(list.GetArrayView()); } template inline Queryable, T*, T> From(List && list) { return Queryable, T*, T>(_Move(list)); } template inline Queryable, T*, T> From(const ArrayView & list) { return Queryable, T*, T>(list); } template inline Queryable, T*, T> From(const Array & list) { return Queryable, T*, T>(list); } template inline auto From(const T & list) -> Queryable { return Queryable(list); } template inline Queryable, T*, T> FromSingle(const T & obj) { Array arr; arr.Add(obj); return From(arr); } template struct LinkedListView { typename LinkedList::Iterator start, last; typename LinkedList::Iterator begin() const { return start; } typename LinkedList::Iterator end() const { return last; } }; template inline Queryable, LinkedNode, T> From(const LinkedList & list) { LinkedListView view; view.start = list.begin(); view.last = list.end(); return Queryable, LinkedNode, T>(view); } template struct EnumerableDictView { typename EnumerableDictionary::Iterator start, last; typename EnumerableDictionary::Iterator begin() const { return start; } typename EnumerableDictionary::Iterator end() const { return last; } }; template inline Queryable, typename EnumerableDictionary::Iterator, KeyValuePair> From(const EnumerableDictionary & dict) { EnumerableDictView view; view.start = dict.begin(); view.last = dict.end(); return Queryable, typename EnumerableDictionary::Iterator, KeyValuePair>(view); } template struct EnumerableHashSetView { typename HashSetBase>::Iterator start, last; typename EnumerableHashSet::Iterator begin() const { return start; } typename EnumerableHashSet::Iterator end() const { return last; } }; template inline Queryable, typename HashSetBase>::Iterator, TKey> From(const EnumerableHashSet & dict) { EnumerableHashSetView view; view.start = dict.begin(); view.last = dict.end(); return Queryable, typename HashSetBase>::Iterator, TKey>(view); } } } #endif