Source: delegation-set.js

  1. /**
  2. * Copyright (C) 2016 Regents of the University of California.
  3. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. * A copy of the GNU Lesser General Public License is in the file COPYING.
  18. */
  19. /** @ignore */
  20. var Name = require('./name.js').Name; /** @ignore */
  21. var Blob = require('./util/blob.js').Blob; /** @ignore */
  22. var WireFormat = require('./encoding/wire-format.js').WireFormat;
  23. /**
  24. * A DelegationSet holds a list of DelegationSet.Delegation entries which is
  25. * used as the content of a Link instance. If you add elements with add(), then
  26. * the list is a set sorted by preference number then by name. But wireDecode
  27. * will add the elements from the wire encoding, preserving the given order and
  28. * possible duplicates (in which case a DelegationSet really holds a "list" and
  29. * not necessarily a "set").
  30. *
  31. * Create a new DelegationSet object, possibly copying values from another
  32. * object.
  33. *
  34. * @param {DelegationSet} value (optional) If value is a DelegationSet, copy its
  35. * values.
  36. * @constructor
  37. */
  38. var DelegationSet = function DelegationSet(value)
  39. {
  40. if (typeof value === 'object' && value instanceof DelegationSet)
  41. // Copy the list.
  42. this.delegations_ = value.delegations_.slice(0);
  43. else
  44. this.delegations_ = []; // of DelegationSet.Delegation.
  45. };
  46. exports.DelegationSet = DelegationSet;
  47. /**
  48. * A DelegationSet.Delegation holds a preference number and delegation name.
  49. * Create a new DelegationSet.Delegation with the given values.
  50. * @param {number} preference The preference number.
  51. * @param {Name} name The delegation name. This makes a copy of the name.
  52. * @constructor
  53. */
  54. DelegationSet.Delegation = function DelegationSetDelegation(preference, name)
  55. {
  56. this.preference_ = preference;
  57. this.name_ = new Name(name);
  58. };
  59. /**
  60. * Get the preference number.
  61. * @return {number} The preference number.
  62. */
  63. DelegationSet.Delegation.prototype.getPreference = function()
  64. {
  65. return this.preference_;
  66. };
  67. /**
  68. * Get the delegation name.
  69. * @return {Name} The delegation name. NOTE: You must not change the name object -
  70. * if you need to change it then make a copy.
  71. */
  72. DelegationSet.Delegation.prototype.getName = function()
  73. {
  74. return this.name_;
  75. };
  76. /**
  77. * Compare this Delegation with other according to the ordering, based first
  78. * on the preference number, then on the delegation name.
  79. * @param {DelegationSet.Delegation} other The other Delegation to compare with.
  80. * @return {number} 0 If they compare equal, -1 if this Delegation comes before
  81. * other in the ordering, or 1 if this Delegation comes after.
  82. */
  83. DelegationSet.Delegation.prototype.compare = function(other)
  84. {
  85. if (this.preference_ < other.preference_)
  86. return -1;
  87. if (this.preference_ > other.preference_)
  88. return 1;
  89. return this.name_.compare(other.name_);
  90. };
  91. /**
  92. * Add a new DelegationSet.Delegation to the list of delegations, sorted by
  93. * preference number then by name. If there is already a delegation with the
  94. * same name, update its preference, and remove any extra delegations with the
  95. * same name.
  96. * @param {number} preference The preference number.
  97. * @param {Name} name The delegation name. This makes a copy of the name.
  98. */
  99. DelegationSet.prototype.add = function(preference, name)
  100. {
  101. this.remove(name);
  102. var newDelegation = new DelegationSet.Delegation(preference, name);
  103. // Find the index of the first entry where it is not less than newDelegation.
  104. var i = 0;
  105. while (i < this.delegations_.length) {
  106. if (this.delegations_[i].compare(newDelegation) >= 0)
  107. break;
  108. ++i;
  109. }
  110. this.delegations_.splice(i, 0, newDelegation);
  111. };
  112. /**
  113. * Add a new DelegationSet.Delegation to the end of the list of delegations,
  114. * without sorting or updating any existing entries. This is useful for adding
  115. * preferences from a wire encoding, preserving the supplied ordering and
  116. * possible duplicates.
  117. * @param {number} preference The preference number.
  118. * @param {Name} name The delegation name. This makes a copy of the name.
  119. */
  120. DelegationSet.prototype.addUnsorted = function(preference, name)
  121. {
  122. this.delegations_.push(new DelegationSet.Delegation(preference, name));
  123. };
  124. /**
  125. * Remove every DelegationSet.Delegation with the given name.
  126. * @param {Name} name The name to match the name of the delegation(s) to be
  127. * removed.
  128. * @return {boolean} True if a DelegationSet.Delegation was removed, otherwise
  129. * false.
  130. */
  131. DelegationSet.prototype.remove = function(name)
  132. {
  133. var wasRemoved = false;
  134. // Go backwards through the list so we can remove entries.
  135. for (var i = this.delegations_.length - 1; i >= 0; --i) {
  136. if (this.delegations_[i].getName().equals(name)) {
  137. wasRemoved = true;
  138. this.delegations_.splice(i, 1);
  139. }
  140. }
  141. return wasRemoved;
  142. };
  143. /**
  144. * Clear the list of delegations.
  145. */
  146. DelegationSet.prototype.clear = function() { this.delegations_ = []; };
  147. /**
  148. * Get the number of delegation entries.
  149. * @return {number} The number of delegation entries.
  150. */
  151. DelegationSet.prototype.size = function() { return this.delegations_.length; };
  152. /**
  153. * Get the delegation at the given index, according to the ordering described
  154. * in add().
  155. * @param {number} i The index of the component, starting from 0.
  156. * @return {DelegationSet.Delegation} The delegation at the index.
  157. */
  158. DelegationSet.prototype.get = function(i) { return this.delegations_[i]; };
  159. /**
  160. * Find the first delegation with the given name and return its index.
  161. * @param {Name} name Then name of the delegation to find.
  162. * @return {number} The index of the delegation, or -1 if not found.
  163. */
  164. DelegationSet.prototype.find = function(name)
  165. {
  166. for (var i = 0; i < this.delegations_.length; ++i) {
  167. if (this.delegations_[i].getName().equals(name))
  168. return i;
  169. }
  170. return -1;
  171. };
  172. /**
  173. * Encode this DelegationSet for a particular wire format.
  174. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  175. * this object. If omitted, use WireFormat.getDefaultWireFormat().
  176. * @returns {Blob} The encoded buffer in a Blob object.
  177. */
  178. DelegationSet.prototype.wireEncode = function(wireFormat)
  179. {
  180. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  181. return wireFormat.encodeDelegationSet(this);
  182. };
  183. /**
  184. * Decode the input using a particular wire format and update this DelegationSet.
  185. * @param {Blob|Buffer} input The buffer with the bytes to decode.
  186. * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
  187. * this object. If omitted, use WireFormat.getDefaultWireFormat().
  188. */
  189. DelegationSet.prototype.wireDecode = function(input, wireFormat)
  190. {
  191. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  192. // If input is a blob, get its buf().
  193. var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
  194. input.buf() : input;
  195. wireFormat.decodeDelegationSet(this, decodeBuffer);
  196. };