1 : // Copyright 2011 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 : #include "syzygy/block_graph/iterate.h"
16 :
17 : namespace block_graph {
18 :
19 : bool IterateBlockGraph(const IterationCallback& callback,
20 E : BlockGraph* block_graph) {
21 E : DCHECK(block_graph != NULL);
22 :
23 E : if (block_graph->blocks().size() == 0)
24 i : return true;
25 :
26 : // Get the ID of the last existing block in iterator order.
27 : BlockGraph::BlockMap::iterator last_block_it =
28 E : block_graph->blocks_mutable().end();
29 E : --last_block_it;
30 E : BlockGraph::BlockId last_block_id = last_block_it->second.id();
31 :
32 : // Iterate through all blocks. We stop after having visited the last block
33 : // that was pre-existing prior to the iteration.
34 : BlockGraph::BlockMap::iterator block_it =
35 E : block_graph->blocks_mutable().begin();
36 E : BlockGraph::BlockId id = 0;
37 : do {
38 : // Get the block ID and the next block prior to invoking the callback.
39 : // This is because the callback is allowed to delete the current block, and
40 : // it may not be valid to use block_it after the callback completes.
41 E : id = block_it->second.id();
42 E : BlockGraph::BlockMap::iterator next_block_it = block_it;
43 E : ++next_block_it;
44 :
45 E : if (!callback.Run(block_graph, &block_it->second)) {
46 E : LOG(ERROR) << "IterateBlocks callback failed for block "
47 : << "\"" << block_it->second.name() << "\".";
48 E : return false;
49 : }
50 :
51 E : block_it = next_block_it;
52 E : } while (id != last_block_id);
53 :
54 E : return true;
55 E : }
56 :
57 : } // namespace block_graph
|