1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview
7 * LogGroupEntry is a wrapper around log entries, which makes it easier to
8 * find the corresponding start/end of events.
9 *
10 * This is used internally by the log and timeline views to pretty print
11 * collections of log entries.
12 */
13
14// TODO(eroman): document these methods!
15
16var LogGroupEntry = (function() {
17  'use strict';
18
19  function LogGroupEntry(origEntry, index) {
20    this.orig = origEntry;
21    this.index = index;
22  }
23
24  LogGroupEntry.prototype = {
25    isBegin: function() {
26      return this.orig.phase == EventPhase.PHASE_BEGIN;
27    },
28
29    isEnd: function() {
30      return this.orig.phase == EventPhase.PHASE_END;
31    },
32
33    getDepth: function() {
34      var depth = 0;
35      var p = this.parentEntry;
36      while (p) {
37        depth += 1;
38        p = p.parentEntry;
39      }
40      return depth;
41    }
42  };
43
44  function findParentIndex(parentStack, eventType) {
45    for (var i = parentStack.length - 1; i >= 0; --i) {
46      if (parentStack[i].orig.type == eventType)
47        return i;
48    }
49    return -1;
50  }
51
52  /**
53   * Returns a list of LogGroupEntrys. This basically wraps the original log
54   * entry, but makes it easier to find the start/end of the event.
55   */
56  LogGroupEntry.createArrayFrom = function(origEntries) {
57    var groupedEntries = [];
58
59    // Stack of enclosing PHASE_BEGIN elements.
60    var parentStack = [];
61
62    for (var i = 0; i < origEntries.length; ++i) {
63      var origEntry = origEntries[i];
64
65      var groupEntry = new LogGroupEntry(origEntry, i);
66      groupedEntries.push(groupEntry);
67
68      // If this is the end of an event, match it to the start.
69      if (groupEntry.isEnd()) {
70        // Walk up the parent stack to find the corresponding BEGIN for this
71        // END.
72        var parentIndex =
73            findParentIndex(parentStack, groupEntry.orig.type);
74
75        if (parentIndex == -1) {
76          // Unmatched end.
77        } else {
78          groupEntry.begin = parentStack[parentIndex];
79
80          // Consider this as the terminator for all open BEGINs up until
81          // parentIndex.
82          while (parentIndex < parentStack.length) {
83            var p = parentStack.pop();
84            p.end = groupEntry;
85          }
86        }
87      }
88
89      // Inherit the current parent.
90      if (parentStack.length > 0)
91        groupEntry.parentEntry = parentStack[parentStack.length - 1];
92
93      if (groupEntry.isBegin())
94        parentStack.push(groupEntry);
95    }
96
97    return groupedEntries;
98  };
99
100  return LogGroupEntry;
101})();
102