/** * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PANDA_LAZY_HPP #define PANDA_LAZY_HPP #include "callable.h" #include #include #include #include namespace ark::verifier { template struct IsLazyStreamValue { // NOLINTNEXTLINE(readability-identifier-naming) using type = Value; template (*(static_cast(nullptr)))) *> struct FS { }; template static char F(FS *); template static int F(...); template (nullptr)))))> *> struct GS { }; template static char G(GS *); template static int G(...); static constexpr bool VALUE = sizeof(F(nullptr)) == 1 && sizeof(G(nullptr)) == 1; }; template struct IsLazyStream { // NOLINTNEXTLINE(readability-identifier-naming) using type = Stream; static constexpr bool VALUE = IsLazyStreamValue(nullptr)))())>::VALUE; }; template struct LazyStreamValue { // NOLINTNEXTLINE(readability-identifier-naming) using type = V; // NOLINTNEXTLINE(readability-identifier-naming) using value_type = decltype(*(*(static_cast(nullptr)))); }; template using LazyStreamValueType = typename LazyStreamValue::value_type; template auto LazyFetch(C &c) { return [end = c.end(), it = c.begin()]() mutable -> std::optional> { if (it != end) { return *(it++); } return std::nullopt; }; } template auto LazyFetch(const C &c) { return [end = c.end(), it = c.begin()]() mutable -> std::optional> { if (it != end) { return *(it++); } return std::nullopt; }; } template auto ConstLazyFetch(const C &c) { return [cend = c.cend(), it = c.cbegin()]() mutable -> std::optional> { if (it != cend) { return *(it++); } return std::nullopt; }; } template auto RefLazyFetch(C &c) { return [end = c.end(), it = c.begin()]() mutable -> std::optional { if (it != end) { return {std::ref(*(it++))}; } return std::nullopt; }; } template auto RefConstLazyFetch(const C &c) { return [cend = c.cend(), it = c.cbegin()]() mutable -> std::optional { if (it != cend) { return {std::cref(*(it++))}; } return std::nullopt; }; } template ::VALUE, int> = 0> auto Transform(F fetcher, L converter) { return [fetcher, converter]() mutable -> std::optional { if (auto val = fetcher()) { return {converter(*val)}; } return std::nullopt; }; } template ::VALUE, int> = 0> auto Filter(F fetcher, L filter) { return [fetcher, filter]() mutable -> decltype(fetcher()) { while (auto val = fetcher()) { if (filter(*val)) { return val; } } return std::nullopt; }; } template ::VALUE, int> = 0> auto Enumerate(F fetcher, size_t from = 0) { return Transform(fetcher, [idx = from](auto v) mutable { return std::tuple {idx++, v}; }); } template auto IndicesOf(const C &c) { size_t from = 0; size_t to = c.size(); return [from, to]() mutable -> std::optional { if (from < to) { return {from++}; } return std::nullopt; }; } template ::VALUE, int> = 0> void ForEachCond(Fetcher fetcher, Func func) { while (auto val = fetcher()) { if (!func(*val)) { return; } } } template ::VALUE, int> = 0> void ForEach(Fetcher fetcher, Func func) { while (auto val = fetcher()) { func(*val); } } template ::VALUE, int> = 0> Accum FoldLeft(Fetcher fetcher, Accum accum, Func func) { while (auto val = fetcher()) { accum = func(accum, *val); } return accum; } template ::VALUE, int> = 0> auto Iterable(F fetcher) { class SomeClass { public: explicit SomeClass(F f) : fetcher_ {f} {}; class Iterator { public: explicit Iterator(std::optional f) : fetcher_ {std::move(f)} { if (fetcher_) { val_ = (*fetcher_)(); } } Iterator &operator++() { val_ = (*fetcher_)(); return *this; } bool operator==([[maybe_unused]] const Iterator &it) { return !static_cast(val_); } bool operator!=([[maybe_unused]] const Iterator &it) { return static_cast(val_); } auto operator*() { return *val_; } private: std::optional fetcher_; decltype((*fetcher_)()) val_; }; Iterator end() // NOLINT(readability-identifier-naming) { return Iterator {{}}; } Iterator begin() // NOLINT(readability-identifier-naming) { return Iterator {fetcher_}; } private: F fetcher_; }; return SomeClass {fetcher}; } template (nullptr))()), decltype((*static_cast(nullptr))())>::value, int> = 0, std::enable_if_t::VALUE, int> = 0> auto operator+(Prev prev, Next next) { return [prev, next, first = true]() mutable { if (first) { auto val = prev(); if (val) { return val; } first = false; } auto val = next(); return val; }; } template C ContainerOf(S stream, typename std::decay< decltype((*static_cast(nullptr)) .push_back(*static_cast(nullptr)))()))> *>( nullptr)))>::type *tmp = nullptr) { (void)tmp; C c; while (auto val = stream()) { c.push_back(*val); } return c; } template C ContainerOf(S stream, typename std::decay< decltype((*static_cast(nullptr)) .insert(*static_cast(nullptr)))()))> *>( nullptr)))>::type *tmp = nullptr) { (void)tmp; C c; while (auto val = stream()) { c.insert(*val); } return c; } template