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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « netlog_viewer/source_entry.js ('k') | netlog_viewer/source_row.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: netlog_viewer/source_filter_parser.js
diff --git a/netlog_viewer/source_filter_parser.js b/netlog_viewer/source_filter_parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..e8e148e7d8e0b2beb92a299425fe05b6d85b5c98
--- /dev/null
+++ b/netlog_viewer/source_filter_parser.js
@@ -0,0 +1,221 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var SourceFilterParser = (function() {
+ 'use strict';
+
+ /**
+ * Parses |filterText|, extracting a sort method, a list of filters, and a
+ * copy of |filterText| with all sort parameters removed.
+ */
+ function SourceFilterParser(filterText) {
+ // Final output will be stored here.
+ this.filter = null;
+ this.sort = {};
+ this.filterTextWithoutSort = '';
+ var filterList = parseFilter_(filterText);
+
+ // Text filters are stored here as strings and then added as a function at
+ // the end, for performance reasons.
+ var textFilters = [];
+
+ // Filter functions are first created individually, and then merged.
+ var filterFunctions = [];
+
+ for (var i = 0; i < filterList.length; ++i) {
+ var filterElement = filterList[i].parsed;
+ var negated = filterList[i].negated;
+
+ var sort = parseSortDirective_(filterElement, negated);
+ if (sort) {
+ this.sort = sort;
+ continue;
+ }
+
+ this.filterTextWithoutSort += filterList[i].original;
+
+ var filter = parseRestrictDirective_(filterElement, negated);
+ if (!filter)
+ filter = parseStringDirective_(filterElement, negated);
+ if (filter) {
+ if (negated) {
+ filter = (function(func, sourceEntry) {
+ return !func(sourceEntry);
+ }).bind(null, filter);
+ }
+ filterFunctions.push(filter);
+ continue;
+ }
+ textFilters.push({ text: filterElement, negated: negated });
+ }
+
+ // Create a single filter for all text filters, so they can share a
+ // TabePrinter.
+ filterFunctions.push(textFilter_.bind(null, textFilters));
+
+ // Create function to go through all the filters.
+ this.filter = function(sourceEntry) {
+ for (var i = 0; i < filterFunctions.length; ++i) {
+ if (!filterFunctions[i](sourceEntry))
+ return false;
+ }
+ return true;
+ };
+ }
+
+ /**
+ * Parses a single "sort:" directive, and returns a dictionary containing
+ * the sort function and direction. Returns null on failure, including
+ * the case when no such sort function exists.
+ */
+ function parseSortDirective_(filterElement, backwards) {
+ var match = /^sort:(.*)$/.exec(filterElement);
+ if (!match)
+ return null;
+ return { method: match[1], backwards: backwards };
+ }
+
+ /**
+ * Tries to parses |filterElement| as a single "is:" directive, and returns a
+ * new filter function. Returns null on failure.
+ */
+ function parseRestrictDirective_(filterElement) {
+ var match = /^is:(.*)$/.exec(filterElement);
+ if (!match)
+ return null;
+ if (match[1] == 'active') {
+ return function(sourceEntry) { return !sourceEntry.isInactive(); };
+ }
+ if (match[1] == 'error') {
+ return function(sourceEntry) { return sourceEntry.isError(); };
+ }
+ return null;
+ }
+
+ /**
+ * Tries to parse |filterElement| as a single filter of a type that takes
+ * arbitrary strings as input, and returns a new filter function on success.
+ * Returns null on failure.
+ */
+ function parseStringDirective_(filterElement) {
+ var match = RegExp('^([^:]*):(.*)$').exec(filterElement);
+ if (!match)
+ return null;
+
+ // Split parameters around commas and remove empty elements.
+ var parameters = match[2].split(',');
+ parameters = parameters.filter(function(string) {
+ return string.length > 0;
+ });
+
+ if (match[1] == 'type') {
+ return function(sourceEntry) {
+ var i;
+ var sourceType = sourceEntry.getSourceTypeString().toLowerCase();
+ for (i = 0; i < parameters.length; ++i) {
+ if (sourceType.search(parameters[i]) != -1)
+ return true;
+ }
+ return false;
+ };
+ }
+
+ if (match[1] == 'id') {
+ return function(sourceEntry) {
+ return parameters.indexOf(sourceEntry.getSourceId() + '') != -1;
+ };
+ }
+
+ return null;
+ }
+
+ /**
+ * Takes in the text of a filter and returns a list of
+ * {parsed, original, negated} values that correspond to substrings of the
+ * filter before and after filtering, and whether or not it started with a
+ * '-'. Extra whitespace other than a single character after each element is
+ * ignored. Parsed strings are all lowercase.
+ */
+ function parseFilter_(filterText) {
+ // Assemble a list of quoted and unquoted strings in the filter.
+ var filterList = [];
+ var position = 0;
+ while (position < filterText.length) {
+ var inQuote = false;
+ var filterElement = '';
+ var negated = false;
+ var startPosition = position;
+ while (position < filterText.length) {
+ var nextCharacter = filterText[position];
+ ++position;
+ if (nextCharacter == '\\' &&
+ position < filterText.length) {
+ // If there's a backslash, skip the backslash and add the next
+ // character to the element.
+ filterElement += filterText[position];
+ ++position;
+ continue;
+ } else if (nextCharacter == '"') {
+ // If there's an unescaped quote character, toggle |inQuote| without
+ // modifying the element.
+ inQuote = !inQuote;
+ } else if (!inQuote && /\s/.test(nextCharacter)) {
+ // If not in a quote and have a whitespace character, that's the
+ // end of the element.
+ break;
+ } else if (nextCharacter == '-' && startPosition == position - 1) {
+ // If this is the first character, and it's a '-', this entry is
+ // negated.
+ negated = true;
+ } else {
+ // Otherwise, add the next character to the element.
+ filterElement += nextCharacter;
+ }
+ }
+
+ if (filterElement.length > 0) {
+ var filter = {
+ parsed: filterElement.toLowerCase(),
+ original: filterText.substring(startPosition, position),
+ negated: negated,
+ };
+ filterList.push(filter);
+ }
+ }
+ return filterList;
+ }
+
+ /**
+ * Takes in a list of text filters and a SourceEntry. Each filter has
+ * "text" and "negated" fields. Returns true if the SourceEntry matches all
+ * filters in the (possibly empty) list.
+ */
+ function textFilter_(textFilters, sourceEntry) {
+ var tablePrinter = null;
+ for (var i = 0; i < textFilters.length; ++i) {
+ var text = textFilters[i].text;
+ var negated = textFilters[i].negated;
+ var match = false;
+ // The description is often not contained in one of the log entries.
+ // The source type almost never is, so check for them directly.
+ var description = sourceEntry.getDescription().toLowerCase();
+ var type = sourceEntry.getSourceTypeString().toLowerCase();
+ if (description.indexOf(text) != -1 || type.indexOf(text) != -1) {
+ match = true;
+ } else {
+ if (!tablePrinter)
+ tablePrinter = sourceEntry.createTablePrinter();
+ match = tablePrinter.search(text);
+ }
+ if (negated)
+ match = !match;
+ if (!match)
+ return false;
+ }
+ return true;
+ }
+
+ return SourceFilterParser;
+})();
+
« 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