mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-26 17:46:26 +03:00
c1e817d1a9
According to the output documentation, |MultiMap.get| is supposed to return null "if no such key exists". However, in the case that an object is added to the map and then removed, |MultiMap.get| will return an empty array instead of null. This inconsistency could be relevant for code that tests based on the truthiness of the output, so this CL changes the remove method to delete the array for a given key if it becomes empty. This also adds unit tests for MultiMap. Change-Id: I049fece920883e1cb10c319a3f00156be4ee011b
106 lines
2.0 KiB
JavaScript
106 lines
2.0 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.util.MultiMap');
|
|
|
|
|
|
/**
|
|
* @summary A simple multimap template.
|
|
* @template T
|
|
*/
|
|
shaka.util.MultiMap = class {
|
|
/** */
|
|
constructor() {
|
|
/** @private {!Object.<string, !Array.<T>>} */
|
|
this.map_ = {};
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a key, value pair to the map.
|
|
* @param {string} key
|
|
* @param {T} value
|
|
*/
|
|
push(key, value) {
|
|
// eslint-disable-next-line no-prototype-builtins
|
|
if (this.map_.hasOwnProperty(key)) {
|
|
this.map_[key].push(value);
|
|
} else {
|
|
this.map_[key] = [value];
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a list of values by key.
|
|
* @param {string} key
|
|
* @return {Array.<T>} or null if no such key exists.
|
|
*/
|
|
get(key) {
|
|
const list = this.map_[key];
|
|
// slice() clones the list so that it and the map can each be modified
|
|
// without affecting the other.
|
|
return list ? list.slice() : null;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a list of all values.
|
|
* @return {!Array.<T>}
|
|
*/
|
|
getAll() {
|
|
const list = [];
|
|
for (const key in this.map_) {
|
|
list.push(...this.map_[key]);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
|
|
/**
|
|
* Remove a specific value, if it exists.
|
|
* @param {string} key
|
|
* @param {T} value
|
|
*/
|
|
remove(key, value) {
|
|
if (!(key in this.map_)) {
|
|
return;
|
|
}
|
|
this.map_[key] = this.map_[key].filter((i) => i != value);
|
|
if (this.map_[key].length == 0) {
|
|
// Delete the array if it's empty, so that |get| will reliably return null
|
|
// "if no such key exists", instead of sometimes returning an empty array.
|
|
delete this.map_[key];
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Clear all keys and values from the multimap.
|
|
*/
|
|
clear() {
|
|
this.map_ = {};
|
|
}
|
|
|
|
|
|
/**
|
|
* @param {function(string, !Array.<T>)} callback
|
|
*/
|
|
forEach(callback) {
|
|
for (const key in this.map_) {
|
|
callback(key, this.map_[key]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the number of elements in the multimap.
|
|
* @return {number}
|
|
*/
|
|
size() {
|
|
return Object.keys(this.map_).length;
|
|
}
|
|
};
|