blob: 54f00290d0ca0ed3ef7fdedf54132d2fb29c90c0 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.
//
// Declares a BlockGraphTransform implementation wrapping the common transform
// that iterates over each block in the image.
#ifndef SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_
#define SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_
#include "base/bind.h"
#include "syzygy/block_graph/iterate.h"
#include "syzygy/block_graph/transforms/named_transform.h"
namespace block_graph {
namespace transforms {
// An implementation of a BlockGraph transform encapsulating the simple pattern
// of Pre, per-block, and Post functions. The derived class is responsible for
// implementing 'OnBlock' and 'name', and may optionally override Pre and
// Post. The derived type needs to also define the static public member
// variable:
//
// static const char DerivedType::kTransformName[];
//
// @tparam DerivedType the type of the derived class.
template<class DerivedType>
class IterativeTransformImpl
: public NamedBlockGraphTransformImpl<DerivedType> {
public:
// This is the main body of the transform. This takes care of calling Pre,
// iterating through the blocks and calling OnBlock for each one, and finally
// calling Post. If any step fails the entire transform fails.
//
// @param policy The policy object restricting how the transform is applied.
// @param block_graph the block graph being transformed.
// @param block the block to process.
// @returns true on success, false otherwise.
virtual bool TransformBlockGraph(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* header_block) OVERRIDE;
protected:
// This function is called prior to the iterative portion of the transform.
// If it fails, the rest of the transform will not run. A default
// implementation is provided but it may be overridden.
//
// @param policy The policy object restricting how the transform is applied.
// @param block_graph the block graph being transformed.
// @param header_block the header block.
// @returns true on success, false otherwise.
bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* header_block) {
return true;
}
// This function is called for every block returned by the iterator. If it
// returns false the transform will be aborted and is considered to have
// failed. This function must be implemented by the derived class. This will
// not be called if PreBlockGraphIteration fails.
//
// @param policy The policy object restricting how the transform is applied.
// @param block_graph the block graph being transformed.
// @param block the block to process.
// @returns true on success, false otherwise.
bool OnBlock(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* block);
// This function is called after the iterative portion of the transform. If
// it fails, the transform is considered to have failed. A default
// implementation is provided but it may be overridden. This will not be
// called if PreBlockGraphIteration fails or any call to OnBlock fails.
//
// @param policy The policy object restricting how the transform is applied.
// @param block_graph the block graph being transformed.
// @param header_block the header block.
// @returns true on success, false otherwise.
bool PostBlockGraphIteration(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* header_block) {
return true;
}
};
template <class DerivedType>
bool IterativeTransformImpl<DerivedType>::TransformBlockGraph(
const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* header_block) {
DCHECK(policy != NULL);
DCHECK(block_graph != NULL);
DCHECK(header_block != NULL);
DerivedType* self = static_cast<DerivedType*>(this);
if (!self->PreBlockGraphIteration(policy, block_graph, header_block)) {
LOG(ERROR) << "PreBlockGraphIteration failed for \"" << name()
<< "\" transform.";
return false;
}
bool result = IterateBlockGraph(
base::Bind(&DerivedType::OnBlock,
base::Unretained(self),
base::Unretained(policy)),
block_graph);
if (!result) {
LOG(ERROR) << "Iteration failed for \"" << name() << "\" transform.";
return false;
}
if (!self->PostBlockGraphIteration(policy, block_graph, header_block)) {
LOG(ERROR) << "PostBlockGraphIteration failed for \"" << name()
<< "\" transform.";
return false;
}
return true;
}
} // namespace transforms
} // namespace block_graph
#endif // SYZYGY_BLOCK_GRAPH_TRANSFORMS_ITERATIVE_TRANSFORM_H_