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_DEPTH_FIRST_ITERATION_H
17 #define META_API_INTERNAL_DEPTH_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<template<typename> class InterableCallable, typename Iterable, typename Func>
25 IterationResult DepthFirstOrderIterate(const Iterable& i, Func& func, IterateStrategy is)
26 {
27 auto ite = interface_pointer_cast<IIterable>(i);
28 if (!ite) {
29 return IterationResult::CONTINUE;
30 }
31 auto f = [&](IterationForwardArgType<Func> arg) {
32 if (is.traversal == TraversalType::DEPTH_FIRST_PRE_ORDER && !func(arg)) {
33 return IterationResult::STOP;
34 }
35 if constexpr (IsInterfacePtr_v<PlainType_t<decltype(arg)>>) {
36 auto res = DepthFirstOrderIterate<InterableCallable>(arg, func, is);
37 if (res.value != IterationResult::CONTINUE) {
38 return res.value;
39 }
40 }
41 if (is.traversal == TraversalType::DEPTH_FIRST_POST_ORDER && !func(arg)) {
42 return IterationResult::STOP;
43 }
44 return IterationResult::CONTINUE;
45 };
46
47 IterationCallable<InterableCallable, decltype(f)> ff(BASE_NS::move(f));
48 InterfaceLock lock(is.lock, ite);
49 return ite->Iterate(IterationParameters { ff, is });
50 }
51
52 template<template<typename> class InterableCallable, typename Iterable>
53 IterationResult DepthFirstOrderIterate(const Iterable& i, ICallable& func, IterateStrategy is)
54 {
55 using CallableType = InterableCallable<IObject::Ptr>;
56 auto f = func.GetInterface<CallableType>();
57 if (!f) {
58 CORE_LOG_W("Incompatible function with Iterate");
59 return IterationResult::FAILED;
60 }
61 auto lf = [&](typename CallableType::ArgType obj) { return f->Invoke(obj); };
62 return DepthFirstOrderIterate<InterableCallable>(i, lf, is);
63 }
64
65 } // namespace Internal
66 META_END_NAMESPACE()
67
68 #endif
69