mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-02 18:11:04 +08:00
The unrestricted annotation is Closure-specific and can be removed. This patch removes all comments with only the unrestricted annotation in them. R=szuend@chromium.org No-Presubmit: True Bug: 1011811 Change-Id: Iba0723644f53f5307c3077d341271af86becc32a Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2569758 Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Auto-Submit: Tim van der Lippe <tvanderlippe@chromium.org>
155 lines
3.6 KiB
JavaScript
155 lines
3.6 KiB
JavaScript
// Copyright 2016 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.
|
|
|
|
export class Trie {
|
|
constructor() {
|
|
/** @type {number} */
|
|
this._size;
|
|
/** @type {number} */
|
|
this._root = 0;
|
|
/** @type {!Array<!Object<string, number>>} */
|
|
this._edges;
|
|
/** @type {!Array<boolean>} */
|
|
this._isWord;
|
|
/** @type {!Array<number>} */
|
|
this._wordsInSubtree;
|
|
/** @type {!Array<number>} */
|
|
this._freeNodes;
|
|
|
|
this.clear();
|
|
}
|
|
|
|
/**
|
|
* @param {string} word
|
|
*/
|
|
add(word) {
|
|
let node = this._root;
|
|
++this._wordsInSubtree[this._root];
|
|
for (let i = 0; i < word.length; ++i) {
|
|
const edge = word[i];
|
|
let next = this._edges[node][edge];
|
|
if (!next) {
|
|
if (this._freeNodes.length) {
|
|
// No need to reset any fields since they were properly cleaned up in remove().
|
|
next = /** @type {number} */ (this._freeNodes.pop());
|
|
} else {
|
|
next = this._size++;
|
|
this._isWord.push(false);
|
|
this._wordsInSubtree.push(0);
|
|
this._edges.push(/** @type {?} */ ({__proto__: null}));
|
|
}
|
|
this._edges[node][edge] = next;
|
|
}
|
|
++this._wordsInSubtree[next];
|
|
node = next;
|
|
}
|
|
this._isWord[node] = true;
|
|
}
|
|
|
|
/**
|
|
* @param {string} word
|
|
* @return {boolean}
|
|
*/
|
|
remove(word) {
|
|
if (!this.has(word)) {
|
|
return false;
|
|
}
|
|
let node = this._root;
|
|
--this._wordsInSubtree[this._root];
|
|
for (let i = 0; i < word.length; ++i) {
|
|
const edge = word[i];
|
|
const next = this._edges[node][edge];
|
|
if (!--this._wordsInSubtree[next]) {
|
|
delete this._edges[node][edge];
|
|
this._freeNodes.push(next);
|
|
}
|
|
node = next;
|
|
}
|
|
this._isWord[node] = false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param {string} word
|
|
* @return {boolean}
|
|
*/
|
|
has(word) {
|
|
let node = this._root;
|
|
for (let i = 0; i < word.length; ++i) {
|
|
node = this._edges[node][word[i]];
|
|
if (!node) {
|
|
return false;
|
|
}
|
|
}
|
|
return this._isWord[node];
|
|
}
|
|
|
|
/**
|
|
* @param {string=} prefix
|
|
* @return {!Array<string>}
|
|
*/
|
|
words(prefix) {
|
|
prefix = prefix || '';
|
|
let node = this._root;
|
|
for (let i = 0; i < prefix.length; ++i) {
|
|
node = this._edges[node][prefix[i]];
|
|
if (!node) {
|
|
return [];
|
|
}
|
|
}
|
|
/** @type {!Array<string>} */
|
|
const results = [];
|
|
this._dfs(node, prefix, results);
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* @param {number} node
|
|
* @param {string} prefix
|
|
* @param {!Array<string>} results
|
|
*/
|
|
_dfs(node, prefix, results) {
|
|
if (this._isWord[node]) {
|
|
results.push(prefix);
|
|
}
|
|
const edges = this._edges[node];
|
|
for (const edge in edges) {
|
|
this._dfs(edges[edge], prefix + edge, results);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} word
|
|
* @param {boolean} fullWordOnly
|
|
* @return {string}
|
|
*/
|
|
longestPrefix(word, fullWordOnly) {
|
|
let node = this._root;
|
|
let wordIndex = 0;
|
|
for (let i = 0; i < word.length; ++i) {
|
|
node = this._edges[node][word[i]];
|
|
if (!node) {
|
|
break;
|
|
}
|
|
if (!fullWordOnly || this._isWord[node]) {
|
|
wordIndex = i + 1;
|
|
}
|
|
}
|
|
return word.substring(0, wordIndex);
|
|
}
|
|
|
|
clear() {
|
|
this._size = 1;
|
|
this._root = 0;
|
|
/** @type {!Array<!Object<string, number>>} */
|
|
this._edges = [/** @type {?} */ ({__proto__: null})];
|
|
/** @type {!Array<boolean>} */
|
|
this._isWord = [false];
|
|
/** @type {!Array<number>} */
|
|
this._wordsInSubtree = [0];
|
|
/** @type {!Array<number>} */
|
|
this._freeNodes = [];
|
|
}
|
|
}
|