Source: encrypt/interval.js

  1. /**
  2. * Copyright (C) 2015-2016 Regents of the University of California.
  3. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  4. * @author: From ndn-group-encrypt src/interval https://github.com/named-data/ndn-group-encrypt
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. * A copy of the GNU Lesser General Public License is in the file COPYING.
  19. */
  20. /**
  21. * An Interval defines a time duration which contains a start timestamp and an
  22. * end timestamp. Create an Interval with one of these forms:
  23. * Interval(isValid).
  24. * Interval(startTime, endTime).
  25. * Interval(interval).
  26. * @param {boolean} isValid True to create a valid empty interval, false to
  27. * create an invalid interval.
  28. * @param {number} startTime The start time as milliseconds since Jan 1, 1970 UTC.
  29. * The start time must be less than the end time. To create an empty interval
  30. * (start time equals end time), use the constructor Interval(true).
  31. * @param {number} endTime The end time as milliseconds since Jan 1, 1970 UTC.
  32. * @param {Interval} interval The other interval with values to copy.
  33. * @note This class is an experimental feature. The API may change.
  34. * @constructor
  35. */
  36. var Interval = function Interval(value, endTime)
  37. {
  38. if (typeof value === 'object' && value instanceof Interval) {
  39. // Make a copy.
  40. this.startTime_ = value.startTime_;
  41. this.endTime_ = value.endTime_;
  42. this.isValid_ = value.isValid_;
  43. }
  44. else if (typeof value === 'number') {
  45. var startTime = value;
  46. if (!(startTime < endTime))
  47. throw new Error("Interval start time must be less than the end time");
  48. this.startTime_ = startTime;
  49. this.endTime_ = endTime;
  50. this.isValid_ = true;
  51. }
  52. else {
  53. var isValid = (value ? true : false);
  54. this.startTime_ = -Number.MAX_VALUE;
  55. this.endTime_ = -Number.MAX_VALUE;
  56. this.isValid_ = isValid;
  57. }
  58. };
  59. exports.Interval = Interval;
  60. /**
  61. * Set this interval to have the same values as the other interval.
  62. * @param {Interval} other The other Interval with values to copy.
  63. */
  64. Interval.prototype.set = function(other)
  65. {
  66. this.startTime_ = other.startTime_;
  67. this.endTime_ = other.endTime_;
  68. this.isValid_ = other.isValid_;
  69. };
  70. /**
  71. * Check if the time point is in this interval.
  72. * @param {number} timePoint The time point to check as milliseconds since
  73. * Jan 1, 1970 UTC.
  74. * @return {boolean} True if timePoint is in this interval.
  75. * @throws Error if this Interval is invalid.
  76. */
  77. Interval.prototype.covers = function(timePoint)
  78. {
  79. if (!this.isValid_)
  80. throw new Error("Interval.covers: This Interval is invalid");
  81. if (this.isEmpty())
  82. return false;
  83. else
  84. return this.startTime_ <= timePoint && timePoint < this.endTime_;
  85. };
  86. /**
  87. * Set this Interval to the intersection of this and the other interval.
  88. * This and the other interval should be valid but either can be empty.
  89. * @param {Interval} interval The other Interval to intersect with.
  90. * @return {Interval} This Interval.
  91. * @throws Error if this Interval or the other interval is invalid.
  92. */
  93. Interval.prototype.intersectWith = function(interval)
  94. {
  95. if (!this.isValid_)
  96. throw new Error("Interval.intersectWith: This Interval is invalid");
  97. if (!interval.isValid_)
  98. throw new Error("Interval.intersectWith: The other Interval is invalid");
  99. if (this.isEmpty() || interval.isEmpty()) {
  100. // If either is empty, the result is empty.
  101. this.startTime_ = this.endTime_;
  102. return this;
  103. }
  104. if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_) {
  105. // The two intervals don't have an intersection, so the result is empty.
  106. this.startTime_ = this.endTime_;
  107. return this;
  108. }
  109. // Get the start time.
  110. if (this.startTime_ <= interval.startTime_)
  111. this.startTime_ = interval.startTime_;
  112. // Get the end time.
  113. if (this.endTime_ > interval.endTime_)
  114. this.endTime_ = interval.endTime_;
  115. return this;
  116. };
  117. /**
  118. * Set this Interval to the union of this and the other interval.
  119. * This and the other interval should be valid but either can be empty.
  120. * This and the other interval should have an intersection. (Contiguous
  121. * intervals are not allowed.)
  122. * @param {Interval} interval The other Interval to union with.
  123. * @return {Interval} This Interval.
  124. * @throws Error if this Interval or the other interval is invalid, or if the
  125. * two intervals do not have an intersection.
  126. */
  127. Interval.prototype.unionWith = function(interval)
  128. {
  129. if (!this.isValid_)
  130. throw new Error("Interval.intersectWith: This Interval is invalid");
  131. if (!interval.isValid_)
  132. throw new Error("Interval.intersectWith: The other Interval is invalid");
  133. if (this.isEmpty()) {
  134. // This interval is empty, so use the other.
  135. this.startTime_ = interval.startTime_;
  136. this.endTime_ = interval.endTime_;
  137. return this;
  138. }
  139. if (interval.isEmpty())
  140. // The other interval is empty, so keep using this one.
  141. return this;
  142. if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_)
  143. throw new Error
  144. ("Interval.unionWith: The two intervals do not have an intersection");
  145. // Get the start time.
  146. if (this.startTime_ > interval.startTime_)
  147. this.startTime_ = interval.startTime_;
  148. // Get the end time.
  149. if (this.endTime_ < interval.endTime_)
  150. this.endTime_ = interval.endTime_;
  151. return this;
  152. };
  153. /**
  154. * Get the start time.
  155. * @return {number} The start time as milliseconds since Jan 1, 1970 UTC.
  156. * @throws Error if this Interval is invalid.
  157. */
  158. Interval.prototype.getStartTime = function()
  159. {
  160. if (!this.isValid_)
  161. throw new Error("Interval.getStartTime: This Interval is invalid");
  162. return this.startTime_;
  163. };
  164. /**
  165. * Get the end time.
  166. * @return {number} The end time as milliseconds since Jan 1, 1970 UTC.
  167. * @throws Error if this Interval is invalid.
  168. */
  169. Interval.prototype.getEndTime = function()
  170. {
  171. if (!this.isValid_)
  172. throw new Error("Interval.getEndTime: This Interval is invalid");
  173. return this.endTime_;
  174. };
  175. /**
  176. * Check if this Interval is valid.
  177. * @return {boolean} True if this interval is valid, false if invalid.
  178. */
  179. Interval.prototype.isValid = function() { return this.isValid_; };
  180. /**
  181. * Check if this Interval is empty.
  182. * @return {boolean} True if this Interval is empty (start time equals end time),
  183. * false if not.
  184. * @throws Error if this Interval is invalid.
  185. */
  186. Interval.prototype.isEmpty = function()
  187. {
  188. if (!this.isValid_)
  189. throw new Error("Interval.isEmpty: This Interval is invalid");
  190. return this.startTime_ == this.endTime_;
  191. };