Source: lib/util/multi_map.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.util.MultiMap');
  7. /**
  8. * @summary A simple multimap template.
  9. * @template T
  10. */
  11. shaka.util.MultiMap = class {
  12. /** */
  13. constructor() {
  14. /** @private {!Map<string, !Array<T>>} */
  15. this.map_ = new Map();
  16. }
  17. /**
  18. * Add a key, value pair to the map.
  19. * @param {string} key
  20. * @param {T} value
  21. */
  22. push(key, value) {
  23. if (this.map_.has(key)) {
  24. this.map_.get(key).push(value);
  25. } else {
  26. this.map_.set(key, [value]);
  27. }
  28. }
  29. /**
  30. * Get a list of values by key.
  31. * @param {string} key
  32. * @return {Array<T>} or null if no such key exists.
  33. */
  34. get(key) {
  35. if (!this.map_.has(key)) {
  36. return null;
  37. }
  38. // slice() clones the list so that it and the map can each be modified
  39. // without affecting the other.
  40. return this.map_.get(key).slice();
  41. }
  42. /**
  43. * Get a list of all values.
  44. * @return {!Array<T>}
  45. */
  46. getAll() {
  47. const list = [];
  48. for (const value of this.map_.values()) {
  49. list.push(...value);
  50. }
  51. return list;
  52. }
  53. /**
  54. * Remove a specific value, if it exists.
  55. * @param {string} key
  56. * @param {T} value
  57. */
  58. remove(key, value) {
  59. if (!this.map_.has(key)) {
  60. return;
  61. }
  62. const newValue = this.map_.get(key).filter((i) => i != value);
  63. this.map_.set(key, newValue);
  64. if (!newValue.length) {
  65. // Delete the array if it's empty, so that |get| will reliably return null
  66. // "if no such key exists", instead of sometimes returning an empty array.
  67. this.map_.delete(key);
  68. }
  69. }
  70. /**
  71. * Clear all keys and values from the multimap.
  72. */
  73. clear() {
  74. this.map_.clear();
  75. }
  76. /**
  77. * @param {function(string, !Array<T>)} callback
  78. */
  79. forEach(callback) {
  80. this.map_.forEach((value, key) => {
  81. callback(key, value);
  82. });
  83. }
  84. /**
  85. * Returns the number of elements in the multimap.
  86. * @return {number}
  87. */
  88. size() {
  89. return this.map_.size;
  90. }
  91. /**
  92. * Get a list of all the keys.
  93. * @return {!Array<string>}
  94. */
  95. keys() {
  96. return Array.from(this.map_.keys());
  97. }
  98. };