array-set.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* -*- Mode: js; js-indent-level: 2; -*- */
  2. /*
  3. * Copyright 2011 Mozilla Foundation and contributors
  4. * Licensed under the New BSD license. See LICENSE or:
  5. * http://opensource.org/licenses/BSD-3-Clause
  6. */
  7. var util = require('./util');
  8. var has = Object.prototype.hasOwnProperty;
  9. /**
  10. * A data structure which is a combination of an array and a set. Adding a new
  11. * member is O(1), testing for membership is O(1), and finding the index of an
  12. * element is O(1). Removing elements from the set is not supported. Only
  13. * strings are supported for membership.
  14. */
  15. function ArraySet() {
  16. this._array = [];
  17. this._set = Object.create(null);
  18. }
  19. /**
  20. * Static method for creating ArraySet instances from an existing array.
  21. */
  22. ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
  23. var set = new ArraySet();
  24. for (var i = 0, len = aArray.length; i < len; i++) {
  25. set.add(aArray[i], aAllowDuplicates);
  26. }
  27. return set;
  28. };
  29. /**
  30. * Return how many unique items are in this ArraySet. If duplicates have been
  31. * added, than those do not count towards the size.
  32. *
  33. * @returns Number
  34. */
  35. ArraySet.prototype.size = function ArraySet_size() {
  36. return Object.getOwnPropertyNames(this._set).length;
  37. };
  38. /**
  39. * Add the given string to this set.
  40. *
  41. * @param String aStr
  42. */
  43. ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
  44. var sStr = util.toSetString(aStr);
  45. var isDuplicate = has.call(this._set, sStr);
  46. var idx = this._array.length;
  47. if (!isDuplicate || aAllowDuplicates) {
  48. this._array.push(aStr);
  49. }
  50. if (!isDuplicate) {
  51. this._set[sStr] = idx;
  52. }
  53. };
  54. /**
  55. * Is the given string a member of this set?
  56. *
  57. * @param String aStr
  58. */
  59. ArraySet.prototype.has = function ArraySet_has(aStr) {
  60. var sStr = util.toSetString(aStr);
  61. return has.call(this._set, sStr);
  62. };
  63. /**
  64. * What is the index of the given string in the array?
  65. *
  66. * @param String aStr
  67. */
  68. ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
  69. var sStr = util.toSetString(aStr);
  70. if (has.call(this._set, sStr)) {
  71. return this._set[sStr];
  72. }
  73. throw new Error('"' + aStr + '" is not in the set.');
  74. };
  75. /**
  76. * What is the element at the given index?
  77. *
  78. * @param Number aIdx
  79. */
  80. ArraySet.prototype.at = function ArraySet_at(aIdx) {
  81. if (aIdx >= 0 && aIdx < this._array.length) {
  82. return this._array[aIdx];
  83. }
  84. throw new Error('No element indexed by ' + aIdx);
  85. };
  86. /**
  87. * Returns the array representation of this set (which has the proper indices
  88. * indicated by indexOf). Note that this is a copy of the internal array used
  89. * for storing the members so that no one can mess with internal state.
  90. */
  91. ArraySet.prototype.toArray = function ArraySet_toArray() {
  92. return this._array.slice();
  93. };
  94. exports.ArraySet = ArraySet;