1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
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 : // Declares a BlockGraphTransform implementation wrapping the common transform
16 : // that iterates over each block in the image.
17 :
18 : #ifndef SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_
19 : #define SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_
20 :
21 : #include "base/bind.h"
22 : #include "syzygy/block_graph/iterate.h"
23 : #include "syzygy/block_graph/transforms/named_transform.h"
24 :
25 : namespace block_graph {
26 : namespace transforms {
27 :
28 : // An implementation of a BlockGraph transform encapsulating the simple pattern
29 : // of Pre, per-block, and Post functions. The derived class is responsible for
30 : // implementing 'OnBlock' and 'name', and may optionally override Pre and
31 : // Post. The derived type needs to also define the static public member
32 : // variable:
33 : //
34 : // static const char DerivedType::kTransformName[];
35 : //
36 : // @tparam DerivedType the type of the derived class.
37 : template<class DerivedType>
38 : class IterativeTransformImpl
39 : : public NamedBlockGraphTransformImpl<DerivedType> {
40 : public:
41 : // This is the main body of the transform. This takes care of calling Pre,
42 : // iterating through the blocks and calling OnBlock for each one, and finally
43 : // calling Post. If any step fails the entire transform fails.
44 : //
45 : // @param policy The policy object restricting how the transform is applied.
46 : // @param block_graph the block graph being transformed.
47 : // @param block the block to process.
48 : // @returns true on success, false otherwise.
49 : virtual bool TransformBlockGraph(const TransformPolicyInterface* policy,
50 : BlockGraph* block_graph,
51 : BlockGraph::Block* header_block) override;
52 :
53 : protected:
54 : // This function is called prior to the iterative portion of the transform.
55 : // If it fails, the rest of the transform will not run. A default
56 : // implementation is provided but it may be overridden.
57 : //
58 : // @param policy The policy object restricting how the transform is applied.
59 : // @param block_graph the block graph being transformed.
60 : // @param header_block the header block.
61 : // @returns true on success, false otherwise.
62 : bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
63 : BlockGraph* block_graph,
64 E : BlockGraph::Block* header_block) {
65 E : return true;
66 E : }
67 :
68 : // This function is called for every block returned by the iterator. If it
69 : // returns false the transform will be aborted and is considered to have
70 : // failed. This function must be implemented by the derived class. This will
71 : // not be called if PreBlockGraphIteration fails.
72 : //
73 : // @param policy The policy object restricting how the transform is applied.
74 : // @param block_graph the block graph being transformed.
75 : // @param block the block to process.
76 : // @returns true on success, false otherwise.
77 : bool OnBlock(const TransformPolicyInterface* policy,
78 : BlockGraph* block_graph,
79 : BlockGraph::Block* block);
80 :
81 : // This function is called after the iterative portion of the transform. If
82 : // it fails, the transform is considered to have failed. A default
83 : // implementation is provided but it may be overridden. This will not be
84 : // called if PreBlockGraphIteration fails or any call to OnBlock fails.
85 : //
86 : // @param policy The policy object restricting how the transform is applied.
87 : // @param block_graph the block graph being transformed.
88 : // @param header_block the header block.
89 : // @returns true on success, false otherwise.
90 : bool PostBlockGraphIteration(const TransformPolicyInterface* policy,
91 : BlockGraph* block_graph,
92 E : BlockGraph::Block* header_block) {
93 E : return true;
94 E : }
95 : };
96 :
97 : template <class DerivedType>
98 : bool IterativeTransformImpl<DerivedType>::TransformBlockGraph(
99 : const TransformPolicyInterface* policy,
100 : BlockGraph* block_graph,
101 E : BlockGraph::Block* header_block) {
102 E : DCHECK(policy != NULL);
103 E : DCHECK(block_graph != NULL);
104 E : DCHECK(header_block != NULL);
105 :
106 E : DerivedType* self = static_cast<DerivedType*>(this);
107 :
108 E : if (!self->PreBlockGraphIteration(policy, block_graph, header_block)) {
109 E : LOG(ERROR) << "PreBlockGraphIteration failed for \"" << name()
110 : << "\" transform.";
111 E : return false;
112 : }
113 :
114 : bool result = IterateBlockGraph(
115 : base::Bind(&DerivedType::OnBlock,
116 : base::Unretained(self),
117 : base::Unretained(policy)),
118 E : block_graph);
119 E : if (!result) {
120 E : LOG(ERROR) << "Iteration failed for \"" << name() << "\" transform.";
121 E : return false;
122 : }
123 :
124 E : if (!self->PostBlockGraphIteration(policy, block_graph, header_block)) {
125 E : LOG(ERROR) << "PostBlockGraphIteration failed for \"" << name()
126 : << "\" transform.";
127 E : return false;
128 : }
129 :
130 E : return true;
131 E : }
132 :
133 : } // namespace transforms
134 : } // namespace block_graph
135 :
136 : #endif // SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_
|