Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Side by Side Diff: netlog_viewer/source_filter_parser.js

Issue 2162963002: [polymer] Merge of master into polymer10-migration (Closed) Base URL: git@github.com:catapult-project/catapult.git@polymer10-migration
Patch Set: Merge polymer10-migration int polymer10-merge Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « netlog_viewer/source_entry.js ('k') | netlog_viewer/source_row.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 var SourceFilterParser = (function() {
6 'use strict';
7
8 /**
9 * Parses |filterText|, extracting a sort method, a list of filters, and a
10 * copy of |filterText| with all sort parameters removed.
11 */
12 function SourceFilterParser(filterText) {
13 // Final output will be stored here.
14 this.filter = null;
15 this.sort = {};
16 this.filterTextWithoutSort = '';
17 var filterList = parseFilter_(filterText);
18
19 // Text filters are stored here as strings and then added as a function at
20 // the end, for performance reasons.
21 var textFilters = [];
22
23 // Filter functions are first created individually, and then merged.
24 var filterFunctions = [];
25
26 for (var i = 0; i < filterList.length; ++i) {
27 var filterElement = filterList[i].parsed;
28 var negated = filterList[i].negated;
29
30 var sort = parseSortDirective_(filterElement, negated);
31 if (sort) {
32 this.sort = sort;
33 continue;
34 }
35
36 this.filterTextWithoutSort += filterList[i].original;
37
38 var filter = parseRestrictDirective_(filterElement, negated);
39 if (!filter)
40 filter = parseStringDirective_(filterElement, negated);
41 if (filter) {
42 if (negated) {
43 filter = (function(func, sourceEntry) {
44 return !func(sourceEntry);
45 }).bind(null, filter);
46 }
47 filterFunctions.push(filter);
48 continue;
49 }
50 textFilters.push({ text: filterElement, negated: negated });
51 }
52
53 // Create a single filter for all text filters, so they can share a
54 // TabePrinter.
55 filterFunctions.push(textFilter_.bind(null, textFilters));
56
57 // Create function to go through all the filters.
58 this.filter = function(sourceEntry) {
59 for (var i = 0; i < filterFunctions.length; ++i) {
60 if (!filterFunctions[i](sourceEntry))
61 return false;
62 }
63 return true;
64 };
65 }
66
67 /**
68 * Parses a single "sort:" directive, and returns a dictionary containing
69 * the sort function and direction. Returns null on failure, including
70 * the case when no such sort function exists.
71 */
72 function parseSortDirective_(filterElement, backwards) {
73 var match = /^sort:(.*)$/.exec(filterElement);
74 if (!match)
75 return null;
76 return { method: match[1], backwards: backwards };
77 }
78
79 /**
80 * Tries to parses |filterElement| as a single "is:" directive, and returns a
81 * new filter function. Returns null on failure.
82 */
83 function parseRestrictDirective_(filterElement) {
84 var match = /^is:(.*)$/.exec(filterElement);
85 if (!match)
86 return null;
87 if (match[1] == 'active') {
88 return function(sourceEntry) { return !sourceEntry.isInactive(); };
89 }
90 if (match[1] == 'error') {
91 return function(sourceEntry) { return sourceEntry.isError(); };
92 }
93 return null;
94 }
95
96 /**
97 * Tries to parse |filterElement| as a single filter of a type that takes
98 * arbitrary strings as input, and returns a new filter function on success.
99 * Returns null on failure.
100 */
101 function parseStringDirective_(filterElement) {
102 var match = RegExp('^([^:]*):(.*)$').exec(filterElement);
103 if (!match)
104 return null;
105
106 // Split parameters around commas and remove empty elements.
107 var parameters = match[2].split(',');
108 parameters = parameters.filter(function(string) {
109 return string.length > 0;
110 });
111
112 if (match[1] == 'type') {
113 return function(sourceEntry) {
114 var i;
115 var sourceType = sourceEntry.getSourceTypeString().toLowerCase();
116 for (i = 0; i < parameters.length; ++i) {
117 if (sourceType.search(parameters[i]) != -1)
118 return true;
119 }
120 return false;
121 };
122 }
123
124 if (match[1] == 'id') {
125 return function(sourceEntry) {
126 return parameters.indexOf(sourceEntry.getSourceId() + '') != -1;
127 };
128 }
129
130 return null;
131 }
132
133 /**
134 * Takes in the text of a filter and returns a list of
135 * {parsed, original, negated} values that correspond to substrings of the
136 * filter before and after filtering, and whether or not it started with a
137 * '-'. Extra whitespace other than a single character after each element is
138 * ignored. Parsed strings are all lowercase.
139 */
140 function parseFilter_(filterText) {
141 // Assemble a list of quoted and unquoted strings in the filter.
142 var filterList = [];
143 var position = 0;
144 while (position < filterText.length) {
145 var inQuote = false;
146 var filterElement = '';
147 var negated = false;
148 var startPosition = position;
149 while (position < filterText.length) {
150 var nextCharacter = filterText[position];
151 ++position;
152 if (nextCharacter == '\\' &&
153 position < filterText.length) {
154 // If there's a backslash, skip the backslash and add the next
155 // character to the element.
156 filterElement += filterText[position];
157 ++position;
158 continue;
159 } else if (nextCharacter == '"') {
160 // If there's an unescaped quote character, toggle |inQuote| without
161 // modifying the element.
162 inQuote = !inQuote;
163 } else if (!inQuote && /\s/.test(nextCharacter)) {
164 // If not in a quote and have a whitespace character, that's the
165 // end of the element.
166 break;
167 } else if (nextCharacter == '-' && startPosition == position - 1) {
168 // If this is the first character, and it's a '-', this entry is
169 // negated.
170 negated = true;
171 } else {
172 // Otherwise, add the next character to the element.
173 filterElement += nextCharacter;
174 }
175 }
176
177 if (filterElement.length > 0) {
178 var filter = {
179 parsed: filterElement.toLowerCase(),
180 original: filterText.substring(startPosition, position),
181 negated: negated,
182 };
183 filterList.push(filter);
184 }
185 }
186 return filterList;
187 }
188
189 /**
190 * Takes in a list of text filters and a SourceEntry. Each filter has
191 * "text" and "negated" fields. Returns true if the SourceEntry matches all
192 * filters in the (possibly empty) list.
193 */
194 function textFilter_(textFilters, sourceEntry) {
195 var tablePrinter = null;
196 for (var i = 0; i < textFilters.length; ++i) {
197 var text = textFilters[i].text;
198 var negated = textFilters[i].negated;
199 var match = false;
200 // The description is often not contained in one of the log entries.
201 // The source type almost never is, so check for them directly.
202 var description = sourceEntry.getDescription().toLowerCase();
203 var type = sourceEntry.getSourceTypeString().toLowerCase();
204 if (description.indexOf(text) != -1 || type.indexOf(text) != -1) {
205 match = true;
206 } else {
207 if (!tablePrinter)
208 tablePrinter = sourceEntry.createTablePrinter();
209 match = tablePrinter.search(text);
210 }
211 if (negated)
212 match = !match;
213 if (!match)
214 return false;
215 }
216 return true;
217 }
218
219 return SourceFilterParser;
220 })();
221
OLDNEW
« no previous file with comments | « netlog_viewer/source_entry.js ('k') | netlog_viewer/source_row.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698