Simon Hunt

GUI: trie utility operations, and test code.

Change-Id: I7f41d84b880a8e2075cf1c983be9a4a2def01856
<!DOCTYPE html>
<!--
~ Copyright 2016 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!--
ONOS -- Sample use of trie functions in fn.js
-->
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Test Trie Functions</title>
<script type="text/javascript" src="../tp/angular.js"></script>
<script type="text/javascript" src="../tp/angular-route.js"></script>
<script type="text/javascript" src="../tp/d3.js"></script>
<script type="text/javascript" src="../app/fw/util/util.js"></script>
<script type="text/javascript" src="../app/fw/util/fn.js"></script>
<script type="text/javascript" src="trie-test.js"></script>
<link rel="stylesheet" href="../app/common.css">
<style>
html,
body {
background-color: #ddf;
font-family: Arial, Helvetica, sans-serif;
font-size: 9pt;
}
h2 {
color: darkred;
}
#output div {
font-family: monospace;
white-space: pre;
}
</style>
</head>
<!-- outline for using a controller in Angular -->
<body class="light" ng-app="trie" ng-controller="OvTrieTest as ctrl">
<h2>Testing the Trie Functions</h2>
<div id="output"></div>
</body>
</html>
\ No newline at end of file
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
ONOS GUI -- Test code illustrating use of trie functions
*/
(function () {
'use strict';
// injected refs
var $log, fs;
// internal state
var out,
trie = {},
counter = 5000;
function write(string) {
out.append('div').text(string);
}
function lookup(word) {
var result = fs.trieLookup(trie, word),
f = fs.isF(result),
show = f ? '{function}' : result;
write('------> ' + word + ' ==> ' + show);
f && f();
}
function add(word, data) {
var result = fs.addToTrie(trie, word, data);
write(' ADD> ' + word + ' [' + data + '] ==> ' + result);
}
function remove(word) {
var result = fs.removeFromTrie(trie, word);
write('REMOVE> ' + word + ' ==> ' + result);
}
function func1() {
counter++;
write('** function call ** ' + counter);
}
function func2() {
counter += 11;
write('** alternate call ** ' + counter);
}
function runTests() {
lookup('cat');
add('cat', 101);
lookup('ca');
lookup('cat');
lookup('cats');
add('cab', 103);
add('cog', 105);
lookup('cut');
lookup('cab');
remove('cab');
lookup('cab');
lookup('cat');
add('fun', func1);
lookup('fun');
lookup('fun');
lookup('fun');
lookup('cat');
lookup('fun');
add('fun', func2);
lookup('fun');
lookup('fun');
lookup('fun');
remove('fun');
lookup('fun');
}
angular.module('trie', ['onosUtil'])
.controller('OvTrieTest', ['$log', 'FnService',
function (_$log_, _fs_) {
$log = _$log_;
fs = _fs_;
out = d3.select('#output');
runTests();
}]);
}());
......@@ -287,11 +287,16 @@
}
}
// generate a trie structure from the given array of strings
// if ignoreCase is true, all words are converted to uppercase first
// note: each letter in each string must be valid as an object property key
function createTrie(words, ignoreCase) {
var trie = {};
// trie operation
function _trieOp(op, trie, word, data) {
var p = trie,
w = word.toUpperCase(),
s = w.split(''),
c = { p: p, s: s },
t = [],
x = 0,
f1 = op === '+' ? add : probe,
f2 = op === '+' ? insert : remove;
function add(c) {
var q = c.s.shift(),
......@@ -300,30 +305,86 @@
if (!np) {
c.p[q] = {};
np = c.p[q];
x = 1;
}
return { p: np, s: c.s }
}
return {
p: np,
s: c.s
function probe(c) {
var q = c.s.shift(),
k = Object.keys(c.p).length,
np = c.p[q];
t.push({ q:q, k:k, p:c.p });
if (!np) {
t = [];
return { s: [] };
}
return { p: np, s: c.s }
}
words.forEach(function (word) {
var p = trie,
w = ignoreCase ? word.toUpperCase() : word,
s = w.split(''),
c = {
p: p,
s: s
};
function insert() {
c.p._data = data;
return x ? 'added' : 'updated';
}
function remove() {
if (t.length) {
t = t.reverse();
while (t.length) {
c = t.shift();
delete c.p[c.q];
if (c.k > 1) {
t = [];
}
}
return 'removed';
}
return 'absent';
}
while (c.s.length) {
c = add(c);
c = f1(c);
}
});
return f2();
}
// add word to trie (word will be converted to uppercase)
// data associated with the word
// returns 'added' or 'updated'
function addToTrie(trie, word, data) {
return _trieOp('+', trie, word, data);
}
// remove word from trie (word will be converted to uppercase)
// returns 'removed' or 'absent'
function removeFromTrie(trie, word) {
return _trieOp('-', trie, word);
}
// lookup word (converted to uppercase) in trie
// returns:
// undefined if the word is not in the trie
// -1 for a partial match (word is a prefix to an existing word)
// data for the word for an exact match
function trieLookup(trie, word) {
var s = word.toUpperCase().split(''),
p = trie,
n;
return trie;
while (s.length) {
n = s.shift();
p = p[n];
if (!p) {
return undefined;
}
}
if (p._data) {
return p._data;
}
return -1;
}
angular.module('onosUtil')
.factory('FnService',
......@@ -360,7 +421,9 @@
noPxStyle: noPxStyle,
endsWith: endsWith,
parseBitRate: parseBitRate,
createTrie: createTrie
addToTrie: addToTrie,
removeFromTrie: removeFromTrie,
trieLookup: trieLookup
};
}]);
......