14template <
typename T,
typename S>
16 std::function<const std::optional<T>(S &)> lambda;
18 std::optional<T> current_yield;
27 explicit generatorIter(std::function<
const std::optional<T>(S &)> lambda,
const S &state,
bool dummy =
false) : lambda(lambda), state(state), current_yield(T()) {
38 return current_yield.value();
46 current_yield = lambda(state);
56 return current_yield.has_value();
70template <
typename T,
typename S>
77 std::function<const std::optional<T>(S &)>
lambda;
118 inline virtual std::optional<T>
next() {
129 for (
auto _ : *
this) {
142 for (
auto i : *
this) {
168 for (
int i = 0; i <
count; i++) {
170 if (!item.has_value()) {
173 result.
push(item.value());
189 template <
typename U>
195 if (!item.has_value()) {
198 return mapLambda(item.value());
218 while (val.has_value()) {
219 if (filterLambda(val.value())) {
242 T
reduce(std::function<T(
const T &,
const T &)> reduceLambda,
const T &defaultValue = {}) {
245 if (!result.has_value()) {
249 auto value = result.value();
253 if (!result.has_value()) {
256 value = reduceLambda(value, result.value());
277 if (item.has_value()) {
278 newLambda(item.value());
300 for (
long i = 0; i <
state.count; i++) {
302 if (!item.has_value()) {
322 if (
state.count <= 0) {
323 return std::optional<T>();
327 if (!item.has_value()) {
346 template <
typename U,
typename S2>
348 typedef std::pair<T, U> pair_type;
352 if (!item1.has_value()) {
353 return std::optional<pair_type>();
356 auto item2 = otherGen.next();
357 if (!item2.has_value()) {
358 return std::optional<pair_type>();
361 return std::optional<pair_type>({item1.value(), item2.value()});
382 if (item.has_value()) {
385 return state.second.next();
389 auto item =
state.second.next();
390 if (item.has_value()) {
406 return generator<std::pair<long, T>, std::pair<long, generator<T, S>>>({0, *
this}, [](std::pair<long, generator<T, S>> &
state) -> std::optional<std::pair<long, T>> {
407 auto item =
state.second.next();
408 if (!item.has_value()) {
411 return std::pair<long, T>{
state.first++, item.value()};
436 if (!item1.has_value()) {
440 if (!
state.second.has_value()) {
441 return item1.value();
444 if (item1.value() !=
state.second.value()) {
445 return item1.value();
467 for (
long i = 0; i < chunkSize; i++) {
468 auto item =
state.next();
469 if (!item.has_value()) {
470 if (
chunk.length() == 0) {
475 chunk.push(item.value());
486 template <typename U = T, typename std::enable_if<is_iterator<U>::value,
int>::type = 0>
489 std::optional<T> data;
490 std::optional<iterator_value<T>> iter;
500 auto chunkData =
state.gen.next();
505 auto &val = chunkData.value();
507 if (val.begin() == val.end()) {
511 state.data = chunkData;
518 return *
state.iter.value()++;
535 const auto prevValue =
state.first;
536 auto &gen =
state.second;
538 if (!prevValue.has_value()) {
542 auto nextValue = gen.next();
543 state.first = nextValue;
545 return std::pair<T, std::optional<T>>(prevValue.value(), nextValue);
564 template <
typename U>
568 auto item =
state.first.next();
569 if (!item.has_value()) {
583 template <
typename U>
585 return generator<T, std::pair<std::pair<generator, bool>,
generator<T, U>>>({{*
this,
false}, other}, [&other](std::pair<std::pair<generator, bool>,
generator<T, U>> &
state) {
586 if (!
state.first.second) {
587 auto item =
state.first.first.next();
588 if (!item.has_value()) {
589 state.first.second =
true;
595 return state.second.next();
613 if (val.has_value() && predicate(val.value())) {
614 return std::optional<T>{};
633 if (val.has_value() && val.value() ==
sentinel) {
634 return std::optional<T>{};
645 template <
typename U>
655 template <
typename U>
657 return generator<T, std::pair<std::pair<generator, bool>,
generator<T, U>>>({{*
this,
false}, other}, [&other](std::pair<std::pair<generator, bool>,
generator<T, U>> &
state) {
658 if (!
state.first.second) {
659 auto item =
state.first.first.next();
660 if (!item.has_value()) {
661 state.first.second =
true;
667 return state.second.next();
676 template <
typename U>
686 template <
typename U>
697 return filter(filterLambda);
714 inline T
operator>>(std::function<T(
const T &,
const T &)> reduceLambda) {
715 return reduce(reduceLambda);
724 return until(predicate);
746 if (iter != list.end()) {
764 return generator<dereference<T>, std::pair<T, iterator_value<T>>>({list, list.begin()}, [](std::pair<T, iterator_value<T>> &state) -> std::optional<dereference<T>> {
765 if (state.second != state.first.end()) {
766 auto ret = *state.second;
784 if (state.second < state.first.length()) {
785 return state.first[state.second++];
799template <
typename K,
typename V>
801 return generator<std::pair<K, V>,
typename std::map<K, V>::const_iterator>(map.begin(), [&map](
auto &iter) -> std::optional<std::pair<K, V>> {
802 if (iter != map.end()) {
819template <
typename K,
typename V>
821 return generator<std::pair<K, V>, std::pair<typename std::map<K, V>::const_iterator, std::map<K, V>>>({map.begin(), map}, [](
auto &state) -> std::optional<std::pair<K, V>> {
822 if (state.first != state.second.end()) {
823 auto ret = *state.first;
A wrapper for std::vector.
Definition array.hpp:38
void increase(int newSize) noexcept
Increase the space allocated for this array.
Definition array.hpp:155
int push(const T &object) noexcept
Add an object to the array.
Definition array.hpp:205
Custom iterator for generators to allow for range-based for loops.
Definition generator.hpp:15
bool operator!=(const generatorIter &other) const
Check if the generator can get more data.
Definition generator.hpp:54
generatorIter(std::function< const std::optional< T >(S &)> lambda, const S &state, bool dummy=false)
Constructor.
Definition generator.hpp:27
generatorIter & operator++()
Generate the next value.
Definition generator.hpp:45
const T & operator*() const
Get the current value from the generator.
Definition generator.hpp:37
An arbitrary generator for producing sequential results on-the-fly.
Definition generator.hpp:71
generator< array< T >, generator > chunk(long chunkSize) noexcept
Get chunks of items from the generator.
Definition generator.hpp:464
generator< T, std::pair< generator, bool > > chain(generator< T, U > &other) noexcept
Chains two generators together.
Definition generator.hpp:565
virtual std::optional< T > next()
Get the next item from the generator.
Definition generator.hpp:118
T reduce(std::function< T(const T &, const T &)> reduceLambda, const T &defaultValue={})
Reduces the generator to a single value by applying a binary operation cumulatively to all yielded va...
Definition generator.hpp:242
generator & forEach(std::function< void(const T &)> newLambda) noexcept
Binds a function to run each time an item comes out of the generator.
Definition generator.hpp:273
generator(const S &initial, std::function< const std::optional< T >(S &)> lambda)
Constructor with an initial state.
Definition generator.hpp:93
array< T > collect()
Concatenate all generator elements into an array.
Definition generator.hpp:140
generator< U, S > operator|(std::function< U(T)> mapLambda) noexcept
Definition generator.hpp:677
generator< T, std::pair< generator, std::optional< T > > > diff(generator &other) noexcept
List the items in this generator which differ from another generator.
Definition generator.hpp:432
T operator>>(std::function< T(const T &, const T &)> reduceLambda)
Reduces the generator to a single value by applying a binary operation cumulatively to all yielded va...
Definition generator.hpp:714
generator< T, std::pair< generator, bool > > operator+(generator< T, U > &other) noexcept
Definition generator.hpp:646
generator operator&&(std::function< T(const T &)> filterLambda) noexcept
Definition generator.hpp:696
generator< T, countedState > skip(long count) noexcept
Skips a certain number of items from the generator.
Definition generator.hpp:296
generator filter(std::function< bool(const T &)> filterLambda) noexcept
Filters the generatred items based on a predicate and returns a new generator that yields only the it...
Definition generator.hpp:213
S state
The state data of this generator.
Definition generator.hpp:74
generator< T, std::pair< std::pair< generator, bool >, generator< T, U > > > chain(generator< T, U > &&other) noexcept
Chains two generators together.
Definition generator.hpp:584
long count()
Consume and discard all items from the generator, getting only the number of items generated.
Definition generator.hpp:127
generator< U, S > operator|(U(*mapLambda)(T)) noexcept
Definition generator.hpp:687
generator< U, S > map(std::function< U(const T &)> mapLambda) noexcept
Applies a transformation function to each item that comes out of the generator.
Definition generator.hpp:190
long consume()
Definition generator.hpp:152
generator< T, std::pair< std::pair< generator, bool >, generator< T, U > > > operator+(generator< T, U > &&other) noexcept
Definition generator.hpp:656
generator< T, std::pair< bool, generator & > > zip(generator &other) noexcept
Zip this generator with another generator.
Definition generator.hpp:375
generatorIter< T, S > end() const noexcept override
End iterator (end of the range).
Definition generator.hpp:107
auto flatten() noexcept
Break up a chunked generator into its constituent generated items.
Definition generator.hpp:487
generator until(const T &sentinel) noexcept
End the generator when the given value is yielded from the generator.
Definition generator.hpp:628
generatorIter< T, S > begin() const noexcept override
Begin iterator (start of the range).
Definition generator.hpp:99
generator until(std::function< bool(T)> predicate) noexcept
End the generator when the given predicate returns true.
Definition generator.hpp:608
generator operator!=(const T &sentinel)
Definition generator.hpp:732
generator operator!=(std::function< bool(T)> predicate)
Definition generator.hpp:723
generator< T, countedState > limit(long count) noexcept
Limits the number of items that the generator will std::optional.
Definition generator.hpp:318
generator< std::pair< long, T >, std::pair< long, generator< T, S > > > enumerate() noexcept
Enumerate the items in this generator.
Definition generator.hpp:405
std::function< const std::optional< T >(S &)> lambda
The function that gets run every time an item is generated.
Definition generator.hpp:77
array< T > take(int count)
Take a certain number of items from the generator.
Definition generator.hpp:164
generator< std::pair< T, std::optional< T > >, std::pair< std::optional< T >, generator > > peek() noexcept
Allow peeking at the next item in the generator as items are generated.
Definition generator.hpp:533
generator< std::pair< T, U >, generator< U, S2 > > pair(generator< U, S2 > &other) noexcept
Pair items from this generator with those of another generator.
Definition generator.hpp:347
A base interface for all objects that can be iterated over.
Definition iterable.hpp:10
A sentinel that stops a numeric generator when the value reaches a certain point.
Definition sentinel.hpp:10
Section containing core functions and classes.
generator< dereference< T >, const_iterator_value< T > > generatorFrom(const T &list)
Create a generator from an arbitrary iterable.
Definition generator.hpp:744
decltype(std::declval< const T & >().begin()) const_iterator_value
The type of a const iterator from a const reference to a container. This is used when iterating over ...
Definition templates.hpp:34
std::remove_const_t< std::remove_reference_t< decltype(*std::declval< decltype(std::declval< T >().begin())>())> > dereference
The type of the dereferenced value from an iterable. This is used to determine the type of value that...
Definition templates.hpp:18
A specialized state for generator::enumerate().
Definition generator.hpp:80
long count
The current index.
Definition generator.hpp:82
S state
The state data of the original generator.
Definition generator.hpp:84
Utility template definitions to allow for simpler type restrictions.