blob: d7beb9888f31a48ee400c70723510143df1e7d7e [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2014 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.
-->
<link rel="import" href="/tracing/base/base.html">
<script>
'use strict';
tr.exportTo('tr.b', function() {
function asArray(arrayish) {
var values = [];
for (var i = 0; i < arrayish.length; i++)
values.push(arrayish[i]);
return values;
}
function compareArrays(x, y, elementCmp) {
var minLength = Math.min(x.length, y.length);
for (var i = 0; i < minLength; i++) {
var tmp = elementCmp(x[i], y[i]);
if (tmp)
return tmp;
}
if (x.length == y.length)
return 0;
if (x[i] === undefined)
return -1;
return 1;
}
/**
* Compares two values when one or both might be undefined. Undefined
* values are sorted after defined.
*/
function comparePossiblyUndefinedValues(x, y, cmp, opt_this) {
if (x !== undefined && y !== undefined)
return cmp.call(opt_this, x, y);
if (x !== undefined)
return -1;
if (y !== undefined)
return 1;
return 0;
}
/**
* Compares two numeric values when one or both might be undefined or NaNs.
* Undefined / NaN values are sorted after others.
*/
function compareNumericWithNaNs(x, y) {
if (!isNaN(x) && !isNaN(y))
return x - y;
if (isNaN(x))
return 1;
if (isNaN(y))
return -1;
return 0;
}
function concatenateArrays(/*arguments*/) {
var values = [];
for (var i = 0; i < arguments.length; i++) {
if (!(arguments[i] instanceof Array))
throw new Error('Arguments ' + i + 'is not an array');
values.push.apply(values, arguments[i]);
}
return values;
}
function concatenateObjects(/*arguments*/) {
var result = {};
for (var i = 0; i < arguments.length; i++) {
var object = arguments[i];
for (var j in object) {
result[j] = object[j];
}
}
return result;
}
function dictionaryKeys(dict) {
var keys = [];
for (var key in dict)
keys.push(key);
return keys;
}
function dictionaryValues(dict) {
var values = [];
for (var key in dict)
values.push(dict[key]);
return values;
}
function dictionaryLength(dict) {
var n = 0;
for (var key in dict)
n++;
return n;
}
function dictionaryContainsValue(dict, value) {
for (var key in dict)
if (dict[key] === value)
return true;
return false;
}
/**
* Returns a new dictionary with items grouped by the return value of the
* specified function being called on each item.
* @param {!Array.<Object>} ary The array being iterated through
* @param {!Function} fn The mapping function between the array value and the
* map key.
*/
function group(ary, fn) {
return ary.reduce(function(accumulator, curr) {
var key = fn(curr);
if (key in accumulator)
accumulator[key].push(curr);
else
accumulator[key] = [curr];
return accumulator;
}, {});
}
function iterItems(dict, fn, opt_this) {
opt_this = opt_this || this;
var keys = Object.keys(dict);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
fn.call(opt_this, key, dict[key]);
}
}
/**
* Create a new dictionary with the same keys as the original dictionary
* mapped to the results of the provided function called on the corresponding
* entries in the original dictionary, i.e. result[key] = fn(key, dict[key])
* for all keys in dict (own enumerable properties only).
*
* Example:
* var srcDict = {a: 10, b: 15};
* var dstDict = mapItems(srcDict, function(k, v) { return 2 * v; });
* // srcDict is unmodified and dstDict is now equal to {a: 20, b: 30}.
*/
function mapItems(dict, fn, opt_this) {
opt_this = opt_this || this;
var result = {};
var keys = Object.keys(dict);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
result[key] = fn.call(opt_this, key, dict[key]);
}
return result;
}
function filterItems(dict, predicate, opt_this) {
opt_this = opt_this || this;
var result = {};
var keys = Object.keys(dict);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = dict[key];
if (predicate.call(opt_this, key, value))
result[key] = value;
}
return result;
}
function iterObjectFieldsRecursively(object, func) {
if (!(object instanceof Object))
return;
if (object instanceof Array) {
for (var i = 0; i < object.length; i++) {
func(object, i, object[i]);
iterObjectFieldsRecursively(object[i], func);
}
return;
}
for (var key in object) {
var value = object[key];
func(object, key, value);
iterObjectFieldsRecursively(value, func);
}
}
/**
* Convert an array of dictionaries to a dictionary of arrays.
*
* The keys of the resulting dictionary are a union of the keys of all
* dictionaries in the provided array. Each array in the resulting dictionary
* has the same length as the provided array and contains the values of its
* key in the dictionaries in the provided array. Example:
*
* INPUT:
*
* [
* {a: 6, b: 5 },
* undefined,
* {a: 4, b: 3, c: 2},
* { b: 1, c: 0}
* ]
*
* OUTPUT:
*
* {
* a: [6, undefined, 4, undefined],
* b: [5, undefined, 3, 1 ],
* c: [undefined, undefined, 2, 0 ]
* }
*
* @param {!Array} array Array of items to be inverted. If opt_dictGetter
* is not provided, all elements of the array must be either undefined,
* or dictionaries.
* @param {?(function(*): (!Object|undefined))=} opt_dictGetter Optional
* function mapping defined elements of array to dictionaries.
* @param {*=} opt_this Optional 'this' context for opt_dictGetter.
*/
function invertArrayOfDicts(array, opt_dictGetter, opt_this) {
opt_this = opt_this || this;
var result = {};
for (var i = 0; i < array.length; i++) {
var item = array[i];
if (item === undefined)
continue;
var dict = opt_dictGetter ? opt_dictGetter.call(opt_this, item) : item;
if (dict === undefined)
continue;
for (var key in dict) {
var valueList = result[key];
if (valueList === undefined)
result[key] = valueList = new Array(array.length);
valueList[i] = dict[key];
}
}
return result;
}
/**
* Convert an array to a dictionary.
*
* Every element in the array is mapped in the dictionary to the key returned
* by the provided function:
*
* dictionary[valueToKeyFn(element)] = element;
*
* @param {!Array} array Arbitrary array.
* @param {function(*): string} valueToKeyFn Function mapping array elements
* to dictionary keys.
* @param {*=} opt_this Optional 'this' context for valueToKeyFn.
*/
function arrayToDict(array, valueToKeyFn, opt_this) {
opt_this = opt_this || this;
var result = {};
var length = array.length;
for (var i = 0; i < length; i++) {
var value = array[i];
var key = valueToKeyFn.call(opt_this, value);
result[key] = value;
}
return result;
}
function identity(d) {
return d;
}
function findFirstIndexInArray(ary, opt_func, opt_this) {
var func = opt_func || identity;
for (var i = 0; i < ary.length; i++) {
if (func.call(opt_this, ary[i], i))
return i;
}
return -1;
}
function findFirstInArray(ary, opt_func, opt_this) {
var i = findFirstIndexInArray(ary, opt_func, opt_func);
if (i === -1)
return undefined;
return ary[i];
}
function findFirstKeyInDictMatching(dict, opt_func, opt_this) {
var func = opt_func || identity;
for (var key in dict) {
if (func.call(opt_this, key, dict[key]))
return key;
}
return undefined;
}
function mapValues(map) {
var values = [];
for (var value of map.values())
values.push(value);
return values;
}
function iterMapItems(map, fn, opt_this) {
opt_this = opt_this || this;
for (var key of map.keys())
fn.call(opt_this, key, map.get(key));
}
return {
asArray: asArray,
concatenateArrays: concatenateArrays,
concatenateObjects: concatenateObjects,
compareArrays: compareArrays,
comparePossiblyUndefinedValues: comparePossiblyUndefinedValues,
compareNumericWithNaNs: compareNumericWithNaNs,
dictionaryLength: dictionaryLength,
dictionaryKeys: dictionaryKeys,
dictionaryValues: dictionaryValues,
dictionaryContainsValue: dictionaryContainsValue,
group: group,
iterItems: iterItems,
mapItems: mapItems,
filterItems: filterItems,
iterObjectFieldsRecursively: iterObjectFieldsRecursively,
invertArrayOfDicts: invertArrayOfDicts,
arrayToDict: arrayToDict,
identity: identity,
findFirstIndexInArray: findFirstIndexInArray,
findFirstInArray: findFirstInArray,
findFirstKeyInDictMatching: findFirstKeyInDictMatching,
mapValues: mapValues,
iterMapItems: iterMapItems
};
});
</script>