1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef META_API_INTERNAL_BREADTH_FIRST_ITERATION_H
17 #define META_API_INTERNAL_BREADTH_FIRST_ITERATION_H
18 
19 #include <meta/api/internal/iteration_types.h>
20 
META_BEGIN_NAMESPACE()21 META_BEGIN_NAMESPACE()
22 namespace Internal {
23 
24 template<typename Type>
25 void AddToQueue(BASE_NS::vector<IIterable::ConstPtr>& vec, const Type& t)
26 {
27     if constexpr (IsInterfacePtr_v<PlainType_t<Type>>) {
28         if (auto i = interface_pointer_cast<IIterable>(t)) {
29             vec.push_back(i);
30         }
31     }
32 }
33 
34 template<template<typename> class InterableCallable, typename Iterable, typename Func>
35 IterationResult BreadthFirstOrderIterate(const Iterable& i, Func& func, IterateStrategy is)
36 {
37     auto ite = interface_pointer_cast<IIterable>(i);
38     if (!ite) {
39         return IterationResult::CONTINUE;
40     }
41     using ParamType = IterationForwardArgType<Func>;
42 
43     BASE_NS::vector<IIterable::ConstPtr> queue;
44     auto f = [&](ParamType arg) {
45         if (!func(arg)) {
46             return IterationResult::STOP;
47         }
48         AddToQueue(queue, arg);
49         return IterationResult::CONTINUE;
50     };
51     IterationCallable<InterableCallable, decltype(f)> ff(BASE_NS::move(f));
52     InterfaceLock lock(is.lock, ite);
53 
54     IterationResult res;
55 
56     queue.push_back(ite);
57     while (!queue.empty()) {
58         auto i = queue[0];
59         queue.erase(queue.begin());
60         res = i->Iterate(IterationParameters { ff, is });
61         if (res.value != IterationResult::CONTINUE) {
62             return res;
63         }
64     }
65     return res;
66 }
67 
68 template<template<typename> class InterableCallable, typename Iterable>
69 IterationResult BreadthFirstOrderIterate(const Iterable& i, ICallable& func, IterateStrategy is)
70 {
71     using CallableType = InterableCallable<IObject::Ptr>;
72     auto f = func.GetInterface<CallableType>();
73     if (!f) {
74         CORE_LOG_W("Incompatible function with Iterate");
75         return IterationResult::FAILED;
76     }
77     auto lf = [&](typename CallableType::ArgType obj) { return f->Invoke(obj); };
78     return BreadthFirstOrderIterate<InterableCallable>(i, lf, is);
79 }
80 
81 } // namespace Internal
82 META_END_NAMESPACE()
83 
84 #endif
85