|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621 |
- #pragma once
-
- #include <set>
- #include <map>
- #include <list>
- #include <vector>
-
- #include "Nullable.h"
- #include "Exception.h"
- #include "MetaProgramming.h"
-
- // #define LINQ_DEBUG
-
- #ifdef LINQ_DEBUG
- #include "Misc.h"
- #define LINQ_TYPE_NAME() utl::TypeHelper<decltype(*this)>::name()
- #define LINQ_CTOR() do { std::cout << "CTOR(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0)
- #define LINQ_COPY_CTOR() do { std::cout << "COPY(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0)
- #define LINQ_MOVE_CTOR() do { std::cout << "MOVE(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0)
- #define LINQ_DTOR() do { std::cout << "DTOR(this=" << this << ")" << LINQ_TYPE_NAME() << std::endl; } while(0)
- #else
- #define LINQ_TYPE_NAME() while(0)
- #define LINQ_CTOR() while(0)
- #define LINQ_COPY_CTOR() while(0)
- #define LINQ_MOVE_CTOR() while(0)
- #define LINQ_DTOR() while(0)
- #endif
-
- namespace linq
- {
- namespace __impl
- {
- struct tag_range { };
- struct tag_builder { };
-
- /* meta programming **********************************************************************/
- template<class TArray>
- struct mp_array_properties;
-
- template<class T, size_t N>
- struct mp_array_properties<T[N]>
- {
- using size = std::integral_constant<size_t, N>;
- using value_type = T;
- using iterator_type = T*;
- };
-
- template<class T>
- using mp_range_value_type = typename utl::mp_remove_ref<T>::value_type;
-
- /* helper types **************************************************************************/
- template<class T>
- struct wrapper
- {
- using value_type = T;
-
- value_type value;
-
- inline value_type operator*() const
- { return value; }
-
- inline wrapper& operator=(const wrapper& other)
- {
- value = other.value;
- return *this;
- }
-
- inline wrapper& operator=(wrapper&& other)
- {
- value = std::move(other).value;
- return *this;
- }
-
- template<class X>
- inline wrapper(X&& v) :
- value(std::forward<X>(v))
- { }
-
- inline wrapper(const value_type& v) :
- value(v)
- { }
-
- inline wrapper(const wrapper& other) :
- value(other.value)
- { }
-
- inline wrapper(wrapper&& other) :
- value(std::move(other.value))
- { }
- };
-
- template<class T>
- struct wrapper<T&>
- {
- using value_type = T&;
- using storage_type = T*;
-
- storage_type value;
-
- inline value_type operator*() const
- { return *value; }
-
- inline wrapper& operator=(const wrapper& other)
- {
- value = other.value;
- return *this;
- }
-
- inline wrapper& operator=(wrapper&& other)
- {
- value = std::move(other.value);
- return *this;
- }
-
- inline wrapper(value_type v) :
- value(&v)
- { }
-
- inline wrapper(const wrapper& other) :
- value(other.value)
- { }
-
- inline wrapper(wrapper&& other) :
- value(std::move(other.value))
- { }
- };
-
- template<class T, class TPredicate>
- struct op_wrapper_less
- {
- using predicate_type = TPredicate;
- using value_type = wrapper<T>;
-
- predicate_type predicate;
-
- inline bool operator()(const value_type& l, const value_type& r)
- { return predicate(*l, *r); }
-
- inline op_wrapper_less(const predicate_type& lp) :
- predicate(lp)
- { }
-
- inline op_wrapper_less(const op_wrapper_less& other) :
- predicate(other.predicate)
- { }
-
- inline op_wrapper_less(op_wrapper_less&& other) :
- predicate(std::move(other.predicate))
- { }
- };
-
- template<class TRange>
- struct range_wrapper
- {
- using range_type = TRange;
- using this_type = range_wrapper<range_type>;
- using value_type = mp_range_value_type<range_type>;
-
- range_type range;
-
- inline value_type& front()
- { return range.front(); }
-
- inline bool next()
- { return range.next(); }
-
- template<class TBuilder>
- inline auto operator >> (TBuilder&& builder) &
- { return builder.build(range); }
-
- template<class TBuilder>
- inline auto operator >> (TBuilder&& builder) &&
- { return builder.build(std::move(range)); }
-
- template<class... Args>
- range_wrapper(Args&&... args) :
- range(std::forward<Args>(args)...)
- { }
-
- range_wrapper(const this_type& other) :
- range(other.range)
- { }
-
- range_wrapper(this_type&& other) :
- range(std::move(other.range))
- { }
- };
-
- template<class TKey, class TValue>
- struct lookup
- {
- public:
- using key_type = TKey;
- using clean_key_type = utl::mp_remove_ref<key_type>;
- using value_type = TValue;
- using this_type = lookup<key_type, value_type>;
- using wrapped_key_type = wrapper<key_type>;
- using wrapped_value_type = wrapper<value_type>;
- using keys_value_type = std::pair<wrapped_key_type, size_t>;
- using keys_type = std::vector<keys_value_type>;
- using values_type = std::vector<wrapped_value_type>;
- using range_indices_type = std::pair<size_t, size_t>;
-
- private:
- struct lookup_range;
- struct lookup_key_value_range;
-
- using lookup_range_wrapper = range_wrapper<lookup_range>;
- using lookup_key_value_range_wrapper = range_wrapper<lookup_key_value_range>;
-
- public:
- using range_type = lookup_key_value_range_wrapper;
-
- private:
- struct lookup_range : public tag_range
- {
- using value_type = lookup::value_type;
-
- enum class State
- {
- Initialize,
- Iterating,
- Finished,
- };
-
- const values_type& values;
- size_t current;
- size_t end;
- State state;
-
- inline value_type& front()
- {
- assert(state == State::Iterating);
- assert(current < end);
- return *values[current];
- }
-
- inline bool next()
- {
- switch (state)
- {
- case State::Iterating:
- {
- ++current;
- }
-
- case State::Initialize:
- {
- auto hasElements = (current < end);
- state = (hasElements ? State::Iterating : State::Finished);
- return hasElements;
- }
-
- default:
- {
- return false;
- }
- }
- }
-
- inline lookup_range(const values_type& v, size_t c, size_t e) :
- values (v),
- current (c),
- end (e),
- state (State::Initialize)
- { LINQ_CTOR(); }
-
- inline lookup_range(const lookup_range& other) :
- values (other.values),
- current (other.current),
- end (other.end),
- state (other.state)
- { LINQ_COPY_CTOR(); }
-
- inline lookup_range(lookup_range&& other) :
- values (std::move(other.values)),
- current (std::move(other.current)),
- end (std::move(other.end)),
- state (std::move(other.state))
- { LINQ_MOVE_CTOR(); }
-
- inline ~lookup_range()
- { LINQ_DTOR(); }
- };
-
- struct lookup_key_value_range : public tag_range
- {
- using value_type = std::pair<key_type, lookup_range_wrapper>;
- using iterator_type = typename keys_type::const_iterator;
-
- lookup container;
- bool initialized;
- range_indices_type range_indices;
- iterator_type current;
- iterator_type end;
-
- inline value_type front()
- {
- assert(initialized);
- assert(current != end);
- return value_type(
- *current->first,
- std::move(container.createRange(range_indices)));
- }
-
- inline bool next()
- {
- if (!initialized)
- {
- initialized = true;
- current = container._keys.begin();
- end = container._keys.end();
- if (current == end)
- return false;
- }
- else
- {
- if (current == end)
- return false;
- ++current;
- if (current == end)
- return false;
- }
- range_indices = container.findKey(*current->first);
- return true;
- }
-
- template<class C>
- lookup_key_value_range(C&& c) :
- container (std::forward<C>(c)),
- initialized (false)
- { LINQ_CTOR(); }
-
- lookup_key_value_range(const lookup_key_value_range& other) :
- container (other.container),
- initialized (other.initialized),
- range_indices (other.range_indices),
- current (other.current),
- end (other.end)
- { LINQ_COPY_CTOR(); }
-
- lookup_key_value_range(lookup_key_value_range&& other) :
- container (std::move(other).container),
- initialized (std::move(other).initialized),
- range_indices (std::move(other).range_indices),
- current (std::move(other).current),
- end (std::move(other).end)
- { LINQ_MOVE_CTOR(); }
-
- ~lookup_key_value_range()
- { LINQ_DTOR(); }
- };
-
- struct op_compare_keys
- {
- bool operator()(
- const keys_value_type& l,
- const keys_value_type& r)
- { return *l.first < *r.first; }
- };
-
- private:
- keys_type _keys;
- values_type _values;
-
- inline range_indices_type findKey(const clean_key_type& key)
- {
- if (_values.empty())
- return std::make_pair<size_t, size_t>(0, 0);
-
- auto it = std::lower_bound(
- _keys.begin(),
- _keys.end(),
- typename keys_type::value_type (const_cast<clean_key_type&>(key), 0),
- op_compare_keys());
- if ( it == _keys.end()
- || *it->first != const_cast<clean_key_type&>(key))
- return std::make_pair<size_t, size_t>(0, 0);
-
- auto next = it + 1;
- range_indices_type ret;
- ret.first = it->second;
- ret.second = next == _keys.end()
- ? _values.size()
- : next->second;
- return ret;
- }
-
- inline lookup_range_wrapper createRange(const range_indices_type& indices)
- { return lookup_range_wrapper(_values, indices.first, indices.second); }
-
- public:
- inline lookup_range_wrapper operator[](const clean_key_type& key)
- { return createRange(findKey(key)); }
-
- template<class TBuilder>
- inline auto operator >> (TBuilder&& builder) &
- { return builder.build(std::move(lookup_key_value_range(*this))); }
-
- template<class TBuilder>
- inline auto operator >> (TBuilder&& builder) &&
- { return builder.build(std::move(lookup_key_value_range(std::move(*this)))); }
-
- private:
- inline lookup(keys_type&& k, values_type&& v) :
- _keys (k),
- _values (v)
- { LINQ_CTOR(); }
-
- public:
- inline lookup()
- { LINQ_CTOR(); }
-
- inline lookup(const lookup& other) :
- _keys (other._keys),
- _values (other._values)
- { LINQ_COPY_CTOR(); }
-
- inline lookup(lookup&& other) :
- _keys (std::move(other)._keys),
- _values (std::move(other)._values)
- { LINQ_MOVE_CTOR(); }
-
- inline ~lookup()
- { LINQ_DTOR(); }
-
- public:
- template<class TRange, class TKeyPredicate, class TValuePredicate>
- static inline auto build(TRange& range, TKeyPredicate& kp, TValuePredicate& vp)
- {
- keys_type k;
- values_type v;
-
- size_t index = 0;
- while (range.next())
- {
- k.emplace_back(kp(range.front()), index);
- v.emplace_back(vp(range.front()));
- ++index;
- }
- if (v.empty())
- return lookup();
-
- std::sort(k.begin(), k.end(), op_compare_keys());
-
- keys_type keys;
- values_type values;
-
- keys.reserve (k.size());
- values.reserve(k.size());
-
- auto it = k.begin();
- auto end = k.end();
- index = 0;
-
- if (it != end)
- {
- keys.emplace_back(it->first, index);
- values.push_back(v.at(it->second));
- }
-
- auto prev = it;
- ++it;
- ++index;
- while (it != end)
- {
- values.push_back(v.at(it->second));
- if (*prev->first < *it->first)
- keys.push_back(std::make_pair(it->first, index));
- prev = it;
- ++it;
- ++index;
- }
-
- return lookup(std::move(keys), std::move(values));
- }
- };
-
- /* ranges ********************************************************************************/
- template<class TIterator>
- struct iterator_range : public tag_range
- {
- using iterator_type = TIterator;
- using this_type = iterator_range<iterator_type>;
- using value_type = decltype(*std::declval<iterator_type>());
-
- bool initialized;
- iterator_type current;
- iterator_type end;
-
- inline value_type& front()
- {
- assert(initialized);
- assert(current != end);
- return *current;
- }
-
- inline bool next()
- {
- if (!initialized)
- initialized = true;
- else if (current != end)
- ++current;
- return (current != end);
- }
-
- inline iterator_range(iterator_type beg, iterator_type end) :
- initialized (false),
- current (beg),
- end (end)
- { LINQ_CTOR(); }
-
- inline iterator_range(const this_type& other) :
- initialized (other.initialized),
- current (other.current),
- end (other.end)
- { LINQ_COPY_CTOR(); }
-
- inline iterator_range(this_type&& other) :
- initialized (std::move(other).initialized),
- current (std::move(other).current),
- end (std::move(other).end)
- { LINQ_MOVE_CTOR(); }
-
- inline ~iterator_range()
- { LINQ_DTOR(); }
- };
-
- template<class TIterator>
- using iterator_range_wrapper = range_wrapper<iterator_range<TIterator>>;
-
- template<class TContainer>
- struct container_range : public tag_range
- {
- using container_type = TContainer;
- using this_type = container_range<container_type>;
- using iterator_type = decltype(std::begin(std::declval<container_type>()));
- using value_type = decltype(*std::declval<iterator_type>());
-
- TContainer container;
- bool initialized;
- iterator_type current;
-
- inline value_type& front()
- {
- assert(initialized);
- assert(current != std::end(container));
- return *current;
- }
-
- inline bool next()
- {
- if (!initialized)
- {
- initialized = true;
- current = std::begin(container);
- }
- else if (current != std::end(container))
- {
- ++current;
- }
- return (current != std::end(container));
- }
-
- inline container_range(container_type& c) noexcept :
- container (c),
- initialized (false)
- { LINQ_CTOR(); }
-
- inline container_range(const this_type& other) noexcept :
- container (other.container),
- initialized (other.initialized),
- current (other.current)
- { LINQ_COPY_CTOR(); }
-
- inline container_range(this_type&& other) noexcept :
- container (std::move(other).container),
- initialized (std::move(other).initialized),
- current (std::move(other).current)
- { LINQ_MOVE_CTOR(); }
-
- inline ~container_range()
- { LINQ_DTOR(); }
- };
-
- template<class TContainer>
- using container_range_wrapper = range_wrapper<container_range<TContainer>>;
-
- template<class TPredicate>
- struct generator_range : public tag_range
- {
- using predicate_type = TPredicate;
- using this_type = generator_range<predicate_type>;
- using predicate_value_type = decltype(std::declval<predicate_type>()());
- using value_type = decltype(*std::declval<predicate_value_type>());
-
- predicate_type predicate;
- predicate_value_type value;
-
- inline value_type& front()
- {
- assert(static_cast<bool>(value));
- return *value;
- }
-
- inline bool next()
- {
- value = predicate();
- return static_cast<bool>(value);
- }
-
- inline generator_range(predicate_type p) :
- predicate (p)
- { LINQ_CTOR(); }
-
- inline generator_range(const this_type& other) :
- predicate (other.predicate),
- value (other.value)
- { LINQ_COPY_CTOR(); }
-
- inline generator_range(this_type&& other) :
- predicate (std::move(other).predicate),
- value (std::move(other).value)
- { LINQ_MOVE_CTOR(); }
-
- inline ~generator_range()
- { LINQ_DTOR(); }
- };
-
- template<class TPredicate>
- using generator_range_wrapper = range_wrapper<generator_range<TPredicate>>;
-
- template<class TRange, class TPredicate>
- struct where_range : public tag_range
- {
- using range_type = TRange;
- using predicate_type = TPredicate;
- using this_type = where_range<range_type, predicate_type>;
- using value_type = mp_range_value_type<range_type>;
-
- range_type range;
- predicate_type predicate;
-
- inline value_type& front()
- { return range.front(); }
-
- inline bool next()
- {
- while (range.next())
- {
- if (predicate(range.front()))
- return true;
- }
- return false;
- }
-
- template<class R, class P>
- inline where_range(R&& r, P&& p) :
- range (std::forward<R>(r)),
- predicate (std::forward<P>(p))
- { LINQ_CTOR(); }
-
- inline where_range(const this_type& other) :
- range (other.range),
- predicate (other.predicate)
- { LINQ_COPY_CTOR(); }
-
- inline where_range(this_type&& other) :
- range (std::move(other).range),
- predicate (std::move(other).predicate)
- { LINQ_MOVE_CTOR(); }
-
- inline ~where_range()
- { LINQ_DTOR(); }
- };
-
- template<class TRange, class TPredicate>
- using where_range_wrapper = range_wrapper<where_range<TRange, TPredicate>>;
-
- template<class TRange, class TPredicate>
- struct select_range : public tag_range
- {
- using range_type = TRange;
- using predicate_type = TPredicate;
- using this_type = select_range<range_type, predicate_type>;
- using range_value_type = mp_range_value_type<range_type>;
- using value_type = decltype(std::declval<predicate_type>()(std::declval<range_value_type>()));
- using cache_type = utl::Nullable<value_type>;
-
- predicate_type predicate;
- range_type range;
- cache_type cache;
-
- inline value_type& front()
- {
- assert(static_cast<bool>(cache));
- return *cache;
- }
-
- inline bool next()
- {
- if (range.next())
- {
- cache = predicate(range.front());
- return true;
- }
- cache.reset();
- return false;
- }
-
- template<class R, class P>
- inline select_range(R&& r, P&& p) :
- range (std::forward<R>(r)),
- predicate (std::forward<P>(p))
- { LINQ_CTOR(); }
-
- inline select_range(const this_type& other) :
- range (other.range),
- predicate (other.predicate)
- { LINQ_COPY_CTOR(); }
-
- inline select_range(this_type&& other) :
- range (std::move(other).range),
- predicate (std::move(other).predicate)
- { LINQ_MOVE_CTOR(); }
-
- inline ~select_range()
- { LINQ_DTOR(); }
- };
-
- template<class TRange, class TPredicate>
- using select_range_wrapper = range_wrapper<select_range<TRange, TPredicate>>;
-
- template<class TRange, class TPredicate>
- struct select_many_range : public tag_range
- {
- template<class T>
- struct __impl_make_inner_range
- {
- using iterator_type = decltype(std::begin(std::declval<T>()));
- using type = iterator_range<iterator_type>;
- };
-
- template<class T>
- using mp_make_inner_range = typename __impl_make_inner_range<T>::type;
-
- using range_type = TRange;
- using predicate_type = TPredicate;
- using this_type = where_range<range_type, predicate_type>;
- using range_value_type = mp_range_value_type<range_type>;
- using predicate_return_type = decltype(std::declval<predicate_type>()(std::declval<range_value_type>()));
- using inner_range_type = utl::mp_eval_if<
- std::is_base_of<tag_range, predicate_return_type>,
- predicate_return_type,
- mp_make_inner_range, predicate_return_type>;
- using value_type = mp_range_value_type<inner_range_type>;
- using inner_range_cache_type = utl::Nullable<inner_range_type>;
-
- predicate_type predicate;
- range_type range;
- inner_range_cache_type inner_range;
-
- template<class T>
- inline typename std::enable_if<std::is_base_of<tag_range, T>::value>::type
- build_inner_range(T value)
- { inner_range = value; }
-
- template<class T>
- inline typename std::enable_if<!std::is_base_of<tag_range, T>::value>::type
- build_inner_range(T value)
- { inner_range = inner_range_type(std::begin(value), std::end(value)); }
-
- inline value_type& front()
- {
- assert(inner_range);
- return inner_range->front();
- }
-
- inline bool next()
- {
- if (inner_range && inner_range->next())
- return true;
- while (range.next())
- {
- inner_range.reset();
- build_inner_range<predicate_return_type>(predicate(range.front()));
- if (inner_range && inner_range->next())
- return true;
- }
- inner_range.reset();
- return false;
- }
-
- template<class R, class P>
- inline select_many_range(R&& r, P&& p) :
- range (std::forward<R>(r)),
- predicate (std::forward<P>(p))
- { LINQ_CTOR(); }
-
- inline select_many_range(const this_type& other) :
- range (other.range),
- predicate (other.predicate),
- inner_range (other.inner_range)
- { LINQ_COPY_CTOR(); }
-
- inline select_many_range(this_type&& other) :
- range (std::move(other).range),
- predicate (std::move(other).predicate),
- inner_range (std::move(other).inner_range)
- { LINQ_MOVE_CTOR(); }
-
- inline ~select_many_range()
- { LINQ_DTOR(); }
- };
-
- template<class TRange, class TPredicate>
- using select_many_range_wrapper = range_wrapper<select_many_range<TRange, TPredicate>>;
-
- template<class TRange, class TSelectPredicate, class TLessPredicate>
- struct order_by_range : public tag_range
- {
- using range_type = TRange;
- using select_predicate_type = TSelectPredicate;
- using less_predicate_type = TLessPredicate;
- using this_type = order_by_range<range_type, select_predicate_type, less_predicate_type>;
- using value_type = mp_range_value_type<range_type>;
- using vector_value_type = utl::mp_if<
- std::is_reference<value_type>,
- utl::mp_remove_ref<value_type>*,
- value_type>;
- using vector_type = std::vector<vector_value_type>;
-
- range_type range;
- select_predicate_type select_predicate;
- less_predicate_type less_predicate;
- ssize_t current;
- vector_type values;
-
- template<class X>
- inline utl::mp_enable_if_c<std::is_reference<X>::value, X>
- front_impl()
- {
- assert(current >= 0);
- assert(current < static_cast<ssize_t>(values.size()));
- return *values.at(current);
- }
-
- template<class X>
- inline utl::mp_enable_if_c<!std::is_reference<X>::value, X>
- front_impl()
- {
- assert(current >= 0);
- assert(current < static_cast<ssize_t>(values.size()));
- return values.at(current);
- }
-
- template<class X>
- inline utl::mp_enable_if_c<std::is_reference<X>::value>
- storeValue(X x)
- { values.emplace_back(&x); }
-
- template<class X>
- inline utl::mp_enable_if_c<!std::is_reference<X>::value>
- storeValue(X x)
- { values.emplace_back(x); }
-
- template<class X>
- inline utl::mp_enable_if_c<std::is_reference<X>::value>
- sortValues()
- {
- std::sort(
- values.begin(),
- values.end(),
- [this](vector_value_type& l, vector_value_type& r) {
- return this->less_predicate(
- this->select_predicate(*l),
- this->select_predicate(*r));
- });
- }
-
- template<class X>
- inline utl::mp_enable_if_c<!std::is_reference<X>::value>
- sortValues()
- {
- std::sort(
- values.begin(),
- values.end(),
- [this](vector_value_type& l, vector_value_type& r) {
- return this->less_predicate(
- this->select_predicate(l),
- this->select_predicate(r));
- });
- }
-
- inline value_type& front()
- { return front_impl<value_type>(); }
-
- inline bool next()
- {
- if (current < 0)
- {
- values.clear();
- while (range.next())
- storeValue<value_type>(range.front());
-
- if (values.empty())
- return false;
-
- sortValues<value_type>();
- current = 0;
- return true;
- }
-
- if (current < static_cast<ssize_t>(values.size()))
- ++current;
- return (current < static_cast<ssize_t>(values.size()));
- }
-
- template<class R, class SP, class LP>
- inline order_by_range(R&& r, SP&& sp, LP&& lp) :
- range (std::forward<R>(r)),
- select_predicate(std::forward<SP>(sp)),
- less_predicate (std::forward<LP>(lp)),
- current (-1)
- { LINQ_CTOR(); }
-
- inline order_by_range(const this_type& other) :
- range (other.range),
- select_predicate(other.select_predicate),
- less_predicate (other.less_predicate),
- current (other.current)
- { LINQ_COPY_CTOR(); }
-
- inline order_by_range(this_type&& other) :
- range (std::move(other).range),
- select_predicate(std::move(other).select_predicate),
- less_predicate (std::move(other).less_predicate),
- current (std::move(other).current)
- { LINQ_MOVE_CTOR(); }
-
- inline ~order_by_range()
- { LINQ_DTOR(); }
- };
-
- template<class TRange, class TSelectPredicate, class TLessPredicate>
- using order_by_range_wrapper = range_wrapper<order_by_range<TRange, TSelectPredicate, TLessPredicate>>;
-
- template<class TRange, class TLessPredicate>
- struct distinct_range : public tag_range
- {
- using range_type = TRange;
- using less_predicate_type = TLessPredicate;
- using this_type = distinct_range<range_type, less_predicate_type>;
- using value_type = mp_range_value_type<range_type>;
- using set_value_type = wrapper<value_type>;
- using set_less_type = op_wrapper_less<value_type, less_predicate_type>;
- using set_type = std::set<set_value_type, set_less_type>;
-
- range_type range;
- set_type set;
-
- inline value_type& front()
- { return range.front(); }
-
- inline bool next()
- {
- while(range.next())
- {
- if (set.emplace(range.front()).second)
- return true;
- }
- return false;
- }
-
- template<class R, class LP>
- inline distinct_range(R&& r, LP&& lp) :
- range (std::forward<R>(r)),
- set (std::forward<LP>(lp))
- { LINQ_CTOR(); }
-
- inline distinct_range(const this_type& other) :
- range (other.range),
- set (other.set)
- { LINQ_COPY_CTOR(); }
-
- inline distinct_range(this_type&& other) :
- range (std::move(other).range),
- set (std::move(other).set)
- { LINQ_MOVE_CTOR(); }
-
- inline ~distinct_range()
- { LINQ_DTOR(); }
- };
-
- template<class TRange, class TLessPredicate>
- using distinct_range_wrapper = range_wrapper<distinct_range<TRange, TLessPredicate>>;
-
- /* builder *******************************************************************************/
- template<template<class> class TOuterRange>
- struct builder : public tag_builder
- {
- template<class R>
- using outer_range_type = TOuterRange<R>;
- using this_type = builder<outer_range_type>;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- // CAUTION: we want no reference to a range here, because the passed range may be destroyed before used in outer_range_type
- using range_type = utl::mp_remove_ref<TRange>;
- return outer_range_type<range_type>(std::forward<TRange>(range));
- }
-
- inline builder()
- { LINQ_CTOR(); }
-
- inline builder(this_type&& other)
- { LINQ_MOVE_CTOR(); }
-
- inline builder(const this_type&) = delete;
-
- inline ~builder()
- { LINQ_DTOR(); }
- };
-
- template<class TPredicate, template<class, class> class TOuterRange>
- struct predicate_builder : public tag_builder
- {
- template<class R, class P>
- using outer_range_type = TOuterRange<R, P>;
- using predicate_type = TPredicate;
- using this_type = predicate_builder<predicate_type, outer_range_type>;
-
- predicate_type predicate;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- // CAUTION: we want no reference to a range here, because the passed range may be destroyed before used in outer_range_type
- using range_type = utl::mp_remove_ref<TRange>;
- return outer_range_type<range_type, predicate_type>(std::forward<TRange>(range), std::move(predicate));
- }
-
- inline predicate_builder(const predicate_type& p) :
- predicate(p)
- { LINQ_CTOR(); }
-
- inline predicate_builder(this_type&& other) :
- predicate(std::move(other).predicate)
- { LINQ_MOVE_CTOR(); }
-
- inline predicate_builder(const this_type&) = delete;
-
- inline ~predicate_builder()
- { LINQ_DTOR(); }
- };
-
- template<class TPredicate0, class TPredicate1, template<class, class, class> class TOuterRange>
- struct dual_predicate_builder : public tag_builder
- {
- template<class R, class P0, class P1>
- using outer_range_type = TOuterRange<R, P0, P1>;
- using predicate_0_type = TPredicate0;
- using predicate_1_type = TPredicate1;
- using this_type = dual_predicate_builder<predicate_0_type, predicate_1_type, outer_range_type>;
-
- predicate_0_type predicate0;
- predicate_1_type predicate1;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- // CAUTION: we want no reference to a range here, because the passed range may be destroyed before used in outer_range_type
- using range_type = utl::mp_remove_ref<TRange>;
- return outer_range_type<range_type, predicate_0_type, predicate_1_type>(std::forward<range_type>(range), std::move(predicate0), std::move(predicate1));
- }
-
- inline dual_predicate_builder(const predicate_0_type& p0, const predicate_1_type& p1) :
- predicate0(p0),
- predicate1(p1)
- { LINQ_CTOR(); }
-
- inline dual_predicate_builder(this_type&& other) :
- predicate0(std::move(other).predicate0),
- predicate1(std::move(other).predicate1)
- { LINQ_MOVE_CTOR(); }
-
- inline dual_predicate_builder(const this_type&) = delete;
-
- inline ~dual_predicate_builder()
- { LINQ_DTOR(); }
- };
-
- struct count_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- size_t ret = 0;
- while (range.next())
- ++ret;
- return ret;
- }
- };
-
- struct sum_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using value_type = mp_range_value_type<TRange>;
- using return_type = utl::mp_clean_type<value_type>;
-
- return_type sum = return_type();
- while (range.next())
- sum += range.front();
- return sum;
- }
- };
-
- struct min_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using value_type = mp_range_value_type<TRange>;
- using return_type = utl::mp_clean_type<value_type>;
-
- return_type ret = std::numeric_limits<return_type>::max();
- while (range.next())
- {
- if (ret > range.front())
- ret = range.front();
- }
- return ret;
- }
- };
-
- struct max_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using value_type = mp_range_value_type<TRange>;
- using return_type = utl::mp_clean_type<value_type>;
-
- return_type ret = std::numeric_limits<return_type>::min();
- while (range.next())
- {
- if (ret < range.front())
- ret = range.front();
- }
- return ret;
- }
- };
-
- struct any_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- { return range.next(); }
- };
-
- template <class T, class TPredicate>
- struct contains_builder : public tag_builder
- {
- using comperator_type = T;
- using predicate_type = TPredicate;
- using this_type = contains_builder<comperator_type, predicate_type>;
-
- comperator_type comperator;
- predicate_type predicate;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- while(range.next())
- {
- if (predicate(comperator, range.front()))
- return true;
- }
- return false;
- }
-
- inline contains_builder(comperator_type&& c, predicate_type&& p) :
- comperator(c),
- predicate (p)
- { }
- };
-
- struct single_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- if (!range.next())
- throw utl::Exception("range is empty");
- auto ret = std::move(range.front());
- if (range.next())
- throw utl::Exception("range contains more than one value");
- return ret;
- }
- };
-
- struct single_or_default_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_value_type = mp_range_value_type<TRange>;
- using value_type = utl::mp_remove_ref<range_value_type>;
- if (!range.next())
- return value_type();
- auto ret = std::move(range.front());
- if (range.next())
- return value_type();
- return ret;
- }
- };
-
- struct first_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- if (!range.next())
- throw utl::Exception("range is empty");
- return std::move(range.front());
- }
- };
-
- struct first_or_default_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_value_type = mp_range_value_type<TRange>;
- using value_type = utl::mp_remove_ref<range_value_type>;
- if (!range.next())
- return value_type();
- return std::move(range.front());
- }
- };
-
- struct last_builder_base
- {
- template<class T>
- struct cache
- {
- std::unique_ptr<T> value;
-
- inline cache& operator=(T& t)
- { value.reset(new T(std::move(t))); return *this; }
-
- inline T& operator*()
- { return *value; }
-
- inline operator bool()
- { return static_cast<bool>(value); }
-
- inline cache()
- { }
- };
-
- template<class T>
- struct cache<T&>
- {
- T* value;
-
- inline cache& operator=(T& t)
- { value = &t; return *this; }
-
- inline T& operator*()
- { return *value; }
-
- inline operator bool()
- { return static_cast<bool>(value); }
-
- inline cache() :
- value(nullptr)
- { }
- };
- };
-
- struct last_builder : public tag_builder, public last_builder_base
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using value_type = mp_range_value_type<TRange>;
- using cache_type = cache<value_type>;
-
- cache_type cache;
- while(range.next())
- cache = range.front();
- if (!static_cast<bool>(cache))
- throw utl::Exception("range is empty");
- return std::move(*cache);
- }
- };
-
- struct last_or_default_builder : public tag_builder, public last_builder_base
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_value_type = mp_range_value_type<TRange>;
- using value_type = utl::mp_remove_ref<range_value_type>;
- using cache_type = cache<value_type>;
-
- cache_type cache;
- while(range.next())
- cache = range.front();
- if (!static_cast<bool>(cache))
- return value_type();
- return std::move(*cache);
- }
- };
-
- struct to_vector_builder : public tag_builder
- {
- size_t capacity;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_value_type = mp_range_value_type<TRange>;
- using value_type = utl::mp_remove_ref<range_value_type>;
- using vector_type = std::vector<value_type>;
-
- vector_type ret;
- ret.reserve(capacity);
- while (range.next())
- ret.emplace_back(std::move(range.front()));
- return ret;
- }
-
- inline to_vector_builder(size_t cap = 16) :
- capacity(cap)
- { }
- };
-
- struct to_list_builder : public tag_builder
- {
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_value_type = mp_range_value_type<TRange>;
- using value_type = utl::mp_remove_ref<range_value_type>;
- using list_type = std::list<value_type>;
-
- list_type ret;
- while (range.next())
- ret.emplace_back(std::move(range.front()));
- return ret;
- }
- };
-
- template<class TKeyPredicate, class TValuePredicate>
- struct to_map_builder : public tag_builder
- {
- using key_predicate_type = TKeyPredicate;
- using value_predicate_type = TValuePredicate;
- using this_type = to_map_builder<key_predicate_type, value_predicate_type>;
-
- key_predicate_type key_predicate;
- value_predicate_type value_predicate;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_type = TRange;
- using range_value_type = mp_range_value_type<range_type>;
- using key_type = decltype(std::declval<key_predicate_type>()(std::declval<range_value_type&>()));
- using value_type = decltype(std::declval<value_predicate_type>()(std::declval<range_value_type&>()));
- using map_type = std::map<utl::mp_remove_ref<key_type>, value_type>;
-
- map_type map;
- while (range.next())
- {
- auto ret = map.emplace(
- key_predicate(range.front()),
- value_predicate(range.front()));
- if (!ret.second)
- throw utl::Exception("duplicate key in range");
- }
- return map;
- }
-
- inline to_map_builder(const key_predicate_type& kp, const value_predicate_type& vp) :
- key_predicate (kp),
- value_predicate (vp)
- { LINQ_CTOR(); }
- };
-
- template<class TPredicate>
- struct for_each_builder : public tag_builder
- {
- using predicate_type = TPredicate;
- using this_type = for_each_builder<predicate_type>;
-
- predicate_type predicate;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- while(range.next())
- predicate(range.front());
- }
-
- inline for_each_builder(const predicate_type& p) :
- predicate(p)
- { }
- };
-
- template<class TKeyPredicate, class TValuePredicate>
- struct to_lookup_builder : public tag_builder
- {
- using key_predicate_type = TKeyPredicate;
- using value_predicate_type = TValuePredicate;
- using this_type = to_lookup_builder<key_predicate_type, value_predicate_type>;
-
- key_predicate_type key_predicate;
- value_predicate_type value_predicate;
-
- template<class TRange>
- inline auto build(TRange&& range)
- {
- using range_type = TRange;
- using range_value_type = mp_range_value_type<range_type>;
- using key_type = decltype(std::declval<key_predicate_type>()(std::declval<range_value_type>()));
- using value_type = decltype(std::declval<value_predicate_type>()(std::declval<range_value_type>()));
- using lookup_type = lookup<key_type, value_type>;
- return lookup_type::build(range, key_predicate, value_predicate);
- }
-
- inline to_lookup_builder(const key_predicate_type& kp, const value_predicate_type& vp) :
- key_predicate (kp),
- value_predicate (vp)
- { LINQ_CTOR(); }
- };
- }
-
- /* default operations ********************************************************************/
- struct op_select_default
- {
- template<class T>
- inline T operator()(T t)
- { return t; }
- };
-
- struct op_less_default
- {
- template<class L, class R>
- inline bool operator()(L&& l, R&& r) const
- { return (l < r); }
- };
-
- struct op_compare_default
- {
- template<class L, class R>
- inline bool operator()(L&& l, R&& r) const
- { return (l == r); }
- };
-
- struct op_select_key_default
- {
- template<class TKey, class TValue>
- inline auto operator()(std::pair<TKey, TValue>& p)
- { return p.first; }
-
- template<class TKey, class TValue>
- inline auto operator()(std::tuple<TKey, TValue>& t)
- { return std::get<0>(t); }
-
- template<class T>
- inline auto operator()(T& t)
- { return t; }
- };
-
- struct op_select_value_default
- {
- template<class TKey, class TValue>
- inline auto operator()(std::pair<TKey, TValue>& p)
- { return p.second; }
-
- template<class TKey, class TValue>
- inline auto operator()(std::tuple<TKey, TValue>& t)
- { return std::get<1>(t); }
-
- template<class T>
- inline auto operator()(T&& t)
- { return std::forward<T>(t); }
- };
-
- /* constructors ******************************************************************************/
- template<class TIterator>
- inline auto from_iterator(TIterator&& beg, TIterator&& end)
- { return __impl::iterator_range_wrapper<TIterator>(std::forward<TIterator>(beg), std::forward<TIterator>(end)); }
-
- template<class TContainer>
- inline auto from_container(TContainer&& container)
- { return __impl::container_range_wrapper<TContainer>(std::forward<TContainer>(container)); }
-
- template<class TPredicate>
- inline auto from_generator(TPredicate&& predicate)
- { return __impl::generator_range_wrapper<TPredicate>(std::forward<TPredicate>(predicate)); }
-
- template<class TArray>
- inline auto from_array(TArray&& array)
- {
- using array_type = typename std::remove_reference<TArray>::type;
- using array_size = typename __impl::mp_array_properties<array_type>::size;
- return from_iterator(&array[0], &array[array_size::value]);
- }
-
- /* filter ************************************************************************************/
- template<class TPredicate>
- inline auto where(TPredicate&& predicate)
- { return __impl::predicate_builder<TPredicate, __impl::where_range_wrapper>(std::forward<TPredicate>(predicate)); }
-
- template<class TPredicate>
- inline auto select(TPredicate&& predicate)
- { return __impl::predicate_builder<TPredicate, __impl::select_range_wrapper>(std::forward<TPredicate>(predicate)); }
-
- template<class TPredicate>
- inline auto select_many(TPredicate&& predicate)
- { return __impl::predicate_builder<TPredicate, __impl::select_many_range_wrapper>(std::forward<TPredicate>(predicate)); }
-
- template<class TSelectPredicate, class TLessPredicate>
- inline auto order_by(TSelectPredicate&& sp, TLessPredicate&& lp)
- { return __impl::dual_predicate_builder<TSelectPredicate, TLessPredicate, __impl::order_by_range_wrapper>(std::forward<TSelectPredicate>(sp), std::forward<TLessPredicate>(lp)); }
-
- template<class TSelectPredicate>
- inline auto order_by(TSelectPredicate&& sp)
- { return order_by(std::forward(sp), op_less_default()); }
-
- inline auto order_by()
- { return order_by(op_select_default(), op_less_default()); }
-
- template<class TLessPredicate>
- inline auto distinct(TLessPredicate&& lp)
- { return __impl::predicate_builder<TLessPredicate, __impl::distinct_range_wrapper>(std::forward<TLessPredicate>(lp)); }
-
- inline auto distinct()
- { return distinct(op_less_default()); }
-
- /* result generators */
- inline auto count()
- { return __impl::count_builder(); }
-
- inline auto sum()
- { return __impl::sum_builder(); }
-
- inline auto min()
- { return __impl::min_builder(); }
-
- inline auto max()
- { return __impl::max_builder(); }
-
- inline auto any()
- { return __impl::any_builder(); }
-
- template<class T, class TPredicate>
- inline auto contains(T&& t, TPredicate&& p)
- { return __impl::contains_builder<T, TPredicate>(std::forward<T>(t), std::forward<TPredicate>(p)); }
-
- template<class T>
- inline auto contains(T&& t)
- { return contains(std::forward<T>(t), op_compare_default()); }
-
- inline auto single()
- { return __impl::single_builder(); }
-
- inline auto single_or_default()
- { return __impl::single_or_default_builder(); }
-
- inline auto first()
- { return __impl::first_builder(); }
-
- inline auto first_or_default()
- { return __impl::first_or_default_builder(); }
-
- inline auto last()
- { return __impl::last_builder(); }
-
- inline auto last_or_default()
- { return __impl::last_or_default_builder(); }
-
- inline auto to_vector(size_t capacity = 16)
- { return __impl::to_vector_builder(capacity); }
-
- inline auto to_list()
- { return __impl::to_list_builder(); }
-
- template<class TKeyPredicate, class TValuePredicate>
- inline auto to_map(TKeyPredicate&& kp, TValuePredicate&& vp)
- { return __impl::to_map_builder<TKeyPredicate, TValuePredicate>(std::forward<TKeyPredicate>(kp), std::forward<TValuePredicate>(vp)); }
-
- template<class TKeyPredicate>
- inline auto to_map(TKeyPredicate&& kp)
- { return to_map(std::forward<TKeyPredicate>(kp), std::move(op_select_value_default())); }
-
- inline auto to_map()
- { return to_map(std::move(op_select_key_default()), std::move(op_select_value_default())); }
-
- template<class TPredicate>
- inline auto for_each(TPredicate&& p)
- { return __impl::for_each_builder<TPredicate>(std::forward<TPredicate>(p)); }
-
- template<class TKeyPredicate, class TValuePredicate>
- inline auto to_lookup(TKeyPredicate&& kp, TValuePredicate&& vp)
- { return __impl::to_lookup_builder<TKeyPredicate, TValuePredicate>(std::forward<TKeyPredicate>(kp), std::forward<TValuePredicate>(vp)); }
-
- template<class TKeyPredicate>
- inline auto to_lookup(TKeyPredicate&& kp)
- { return to_lookup(std::forward<TKeyPredicate>(kp), std::move(op_select_value_default())); }
-
- inline auto to_lookup()
- { return to_lookup(std::move(op_select_key_default()), std::move(op_select_value_default())); }
- }
|