Simon Hunt

GUI: trie utility operations, and test code.

Change-Id: I7f41d84b880a8e2075cf1c983be9a4a2def01856
1 +<!DOCTYPE html>
2 +<!--
3 + ~ Copyright 2016 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +
18 +<!--
19 + ONOS -- Sample use of trie functions in fn.js
20 + -->
21 +
22 +<html>
23 +<head lang="en">
24 + <meta charset="UTF-8">
25 + <title>Test Trie Functions</title>
26 +
27 + <script type="text/javascript" src="../tp/angular.js"></script>
28 + <script type="text/javascript" src="../tp/angular-route.js"></script>
29 +
30 + <script type="text/javascript" src="../tp/d3.js"></script>
31 +
32 + <script type="text/javascript" src="../app/fw/util/util.js"></script>
33 + <script type="text/javascript" src="../app/fw/util/fn.js"></script>
34 +
35 + <script type="text/javascript" src="trie-test.js"></script>
36 +
37 + <link rel="stylesheet" href="../app/common.css">
38 +
39 + <style>
40 + html,
41 + body {
42 + background-color: #ddf;
43 + font-family: Arial, Helvetica, sans-serif;
44 + font-size: 9pt;
45 + }
46 +
47 + h2 {
48 + color: darkred;
49 + }
50 +
51 + #output div {
52 + font-family: monospace;
53 + white-space: pre;
54 + }
55 + </style>
56 +
57 +</head>
58 +
59 +<!-- outline for using a controller in Angular -->
60 +<body class="light" ng-app="trie" ng-controller="OvTrieTest as ctrl">
61 + <h2>Testing the Trie Functions</h2>
62 + <div id="output"></div>
63 +</body>
64 +</html>
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Test code illustrating use of trie functions
19 + */
20 +
21 +(function () {
22 + 'use strict';
23 +
24 + // injected refs
25 + var $log, fs;
26 +
27 + // internal state
28 + var out,
29 + trie = {},
30 + counter = 5000;
31 +
32 + function write(string) {
33 + out.append('div').text(string);
34 + }
35 +
36 + function lookup(word) {
37 + var result = fs.trieLookup(trie, word),
38 + f = fs.isF(result),
39 + show = f ? '{function}' : result;
40 +
41 +
42 + write('------> ' + word + ' ==> ' + show);
43 +
44 + f && f();
45 + }
46 +
47 + function add(word, data) {
48 + var result = fs.addToTrie(trie, word, data);
49 + write(' ADD> ' + word + ' [' + data + '] ==> ' + result);
50 + }
51 +
52 + function remove(word) {
53 + var result = fs.removeFromTrie(trie, word);
54 + write('REMOVE> ' + word + ' ==> ' + result);
55 + }
56 +
57 + function func1() {
58 + counter++;
59 + write('** function call ** ' + counter);
60 + }
61 +
62 + function func2() {
63 + counter += 11;
64 + write('** alternate call ** ' + counter);
65 + }
66 +
67 + function runTests() {
68 + lookup('cat');
69 +
70 + add('cat', 101);
71 +
72 + lookup('ca');
73 + lookup('cat');
74 + lookup('cats');
75 +
76 + add('cab', 103);
77 + add('cog', 105);
78 +
79 + lookup('cut');
80 + lookup('cab');
81 +
82 + remove('cab');
83 +
84 + lookup('cab');
85 + lookup('cat');
86 +
87 + add('fun', func1);
88 +
89 + lookup('fun');
90 + lookup('fun');
91 + lookup('fun');
92 + lookup('cat');
93 + lookup('fun');
94 +
95 + add('fun', func2);
96 +
97 + lookup('fun');
98 + lookup('fun');
99 + lookup('fun');
100 +
101 + remove('fun');
102 +
103 + lookup('fun');
104 + }
105 +
106 + angular.module('trie', ['onosUtil'])
107 + .controller('OvTrieTest', ['$log', 'FnService',
108 +
109 + function (_$log_, _fs_) {
110 + $log = _$log_;
111 + fs = _fs_;
112 + out = d3.select('#output');
113 +
114 + runTests();
115 + }]);
116 +}());
...@@ -287,11 +287,16 @@ ...@@ -287,11 +287,16 @@
287 } 287 }
288 } 288 }
289 289
290 - // generate a trie structure from the given array of strings 290 + // trie operation
291 - // if ignoreCase is true, all words are converted to uppercase first 291 + function _trieOp(op, trie, word, data) {
292 - // note: each letter in each string must be valid as an object property key 292 + var p = trie,
293 - function createTrie(words, ignoreCase) { 293 + w = word.toUpperCase(),
294 - var trie = {}; 294 + s = w.split(''),
295 + c = { p: p, s: s },
296 + t = [],
297 + x = 0,
298 + f1 = op === '+' ? add : probe,
299 + f2 = op === '+' ? insert : remove;
295 300
296 function add(c) { 301 function add(c) {
297 var q = c.s.shift(), 302 var q = c.s.shift(),
...@@ -300,30 +305,86 @@ ...@@ -300,30 +305,86 @@
300 if (!np) { 305 if (!np) {
301 c.p[q] = {}; 306 c.p[q] = {};
302 np = c.p[q]; 307 np = c.p[q];
308 + x = 1;
309 + }
310 + return { p: np, s: c.s }
303 } 311 }
304 312
305 - return { 313 + function probe(c) {
306 - p: np, 314 + var q = c.s.shift(),
307 - s: c.s 315 + k = Object.keys(c.p).length,
316 + np = c.p[q];
317 +
318 + t.push({ q:q, k:k, p:c.p });
319 + if (!np) {
320 + t = [];
321 + return { s: [] };
308 } 322 }
323 + return { p: np, s: c.s }
309 } 324 }
310 325
311 - words.forEach(function (word) { 326 + function insert() {
312 - var p = trie, 327 + c.p._data = data;
313 - w = ignoreCase ? word.toUpperCase() : word, 328 + return x ? 'added' : 'updated';
314 - s = w.split(''), 329 + }
315 - c = { 330 +
316 - p: p, 331 + function remove() {
317 - s: s 332 + if (t.length) {
318 - }; 333 + t = t.reverse();
334 + while (t.length) {
335 + c = t.shift();
336 + delete c.p[c.q];
337 + if (c.k > 1) {
338 + t = [];
339 + }
340 + }
341 + return 'removed';
342 + }
343 + return 'absent';
344 + }
319 345
320 while (c.s.length) { 346 while (c.s.length) {
321 - c = add(c); 347 + c = f1(c);
322 } 348 }
323 - }); 349 + return f2();
350 + }
351 +
352 + // add word to trie (word will be converted to uppercase)
353 + // data associated with the word
354 + // returns 'added' or 'updated'
355 + function addToTrie(trie, word, data) {
356 + return _trieOp('+', trie, word, data);
357 + }
358 +
359 + // remove word from trie (word will be converted to uppercase)
360 + // returns 'removed' or 'absent'
361 + function removeFromTrie(trie, word) {
362 + return _trieOp('-', trie, word);
363 + }
364 +
365 + // lookup word (converted to uppercase) in trie
366 + // returns:
367 + // undefined if the word is not in the trie
368 + // -1 for a partial match (word is a prefix to an existing word)
369 + // data for the word for an exact match
370 + function trieLookup(trie, word) {
371 + var s = word.toUpperCase().split(''),
372 + p = trie,
373 + n;
324 374
325 - return trie; 375 + while (s.length) {
376 + n = s.shift();
377 + p = p[n];
378 + if (!p) {
379 + return undefined;
380 + }
381 + }
382 + if (p._data) {
383 + return p._data;
326 } 384 }
385 + return -1;
386 + }
387 +
327 388
328 angular.module('onosUtil') 389 angular.module('onosUtil')
329 .factory('FnService', 390 .factory('FnService',
...@@ -360,7 +421,9 @@ ...@@ -360,7 +421,9 @@
360 noPxStyle: noPxStyle, 421 noPxStyle: noPxStyle,
361 endsWith: endsWith, 422 endsWith: endsWith,
362 parseBitRate: parseBitRate, 423 parseBitRate: parseBitRate,
363 - createTrie: createTrie 424 + addToTrie: addToTrie,
425 + removeFromTrie: removeFromTrie,
426 + trieLookup: trieLookup
364 }; 427 };
365 }]); 428 }]);
366 429
......