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 block_graph the block graph being transformed.
46 : // @param block the block to process.
47 : // @returns true on success, false otherwise.
48 : virtual bool TransformBlockGraph(BlockGraph* block_graph,
49 : BlockGraph::Block* header_block) OVERRIDE;
50 :
51 : protected:
52 : // This function is called prior to the iterative portion of the transform.
53 : // If it fails, the rest of the transform will not run. A default
54 : // implementation is provided but it may be overridden.
55 : //
56 : // @param block_graph the block graph being transformed.
57 : // @param header_block the header block.
58 : // @returns true on success, false otherwise.
59 : bool PreBlockGraphIteration(BlockGraph* block_graph,
60 E : BlockGraph::Block* header_block) {
61 E : return true;
62 E : }
63 :
64 : // This function is called for every block returned by the iterator. If it
65 : // returns false the transform will be aborted and is considered to have
66 : // failed. This function must be implemented by the derived class. This will
67 : // not be called if PreBlockGraphIteration fails.
68 : //
69 : // @param block_graph the block graph being transformed.
70 : // @param block the block to process.
71 : // @returns true on success, false otherwise.
72 : bool OnBlock(BlockGraph* block_graph,
73 : BlockGraph::Block* block);
74 :
75 : // This function is called after the iterative portion of the transform. If
76 : // it fails, the transform is considered to have failed. A default
77 : // implementation is provided but it may be overridden. This will not be
78 : // called if PreBlockGraphIteration fails or any call to OnBlock fails.
79 : //
80 : // @param block_graph the block graph being transformed.
81 : // @param header_block the header block.
82 : // @returns true on success, false otherwise.
83 : bool PostBlockGraphIteration(BlockGraph* block_graph,
84 E : BlockGraph::Block* header_block) {
85 E : return true;
86 E : }
87 : };
88 :
89 : template <class DerivedType>
90 : bool IterativeTransformImpl<DerivedType>::TransformBlockGraph(
91 E : BlockGraph* block_graph, BlockGraph::Block* header_block) {
92 E : DerivedType* self = static_cast<DerivedType*>(this);
93 :
94 E : if (!self->PreBlockGraphIteration(block_graph, header_block)) {
95 E : LOG(ERROR) << "PreBlockGraphIteration failed for \"" << name()
96 : << "\" transform.";
97 E : return false;
98 : }
99 :
100 : bool result = IterateBlockGraph(
101 : base::Bind(&DerivedType::OnBlock,
102 : base::Unretained(self)),
103 E : block_graph);
104 E : if (!result) {
105 E : LOG(ERROR) << "Iteration failed for \"" << name() << "\" transform.";
106 E : return false;
107 : }
108 :
109 E : if (!self->PostBlockGraphIteration(block_graph, header_block)) {
110 E : LOG(ERROR) << "PostBlockGraphIteration failed for \"" << name()
111 : << "\" transform.";
112 E : return false;
113 : }
114 :
115 E : return true;
116 E : }
117 :
118 : } // namespace transforms
119 : } // namespace block_graph
120 :
121 : #endif // SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_
|