You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
7.7 KiB

4 years ago
  1. /**
  2. * Copyright (c) 2013 Petka Antonov
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:</p>
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. "use strict";
  23. function Deque(capacity) {
  24. this._capacity = getCapacity(capacity);
  25. this._length = 0;
  26. this._front = 0;
  27. if (isArray(capacity)) {
  28. var len = capacity.length;
  29. for (var i = 0; i < len; ++i) {
  30. this[i] = capacity[i];
  31. }
  32. this._length = len;
  33. }
  34. }
  35. Deque.prototype.toArray = function Deque$toArray() {
  36. var len = this._length;
  37. var ret = new Array(len);
  38. var front = this._front;
  39. var capacity = this._capacity;
  40. for (var j = 0; j < len; ++j) {
  41. ret[j] = this[(front + j) & (capacity - 1)];
  42. }
  43. return ret;
  44. };
  45. Deque.prototype.push = function Deque$push(item) {
  46. var argsLength = arguments.length;
  47. var length = this._length;
  48. if (argsLength > 1) {
  49. var capacity = this._capacity;
  50. if (length + argsLength > capacity) {
  51. for (var i = 0; i < argsLength; ++i) {
  52. this._checkCapacity(length + 1);
  53. var j = (this._front + length) & (this._capacity - 1);
  54. this[j] = arguments[i];
  55. length++;
  56. this._length = length;
  57. }
  58. return length;
  59. }
  60. else {
  61. var j = this._front;
  62. for (var i = 0; i < argsLength; ++i) {
  63. this[(j + length) & (capacity - 1)] = arguments[i];
  64. j++;
  65. }
  66. this._length = length + argsLength;
  67. return length + argsLength;
  68. }
  69. }
  70. if (argsLength === 0) return length;
  71. this._checkCapacity(length + 1);
  72. var i = (this._front + length) & (this._capacity - 1);
  73. this[i] = item;
  74. this._length = length + 1;
  75. return length + 1;
  76. };
  77. Deque.prototype.pop = function Deque$pop() {
  78. var length = this._length;
  79. if (length === 0) {
  80. return void 0;
  81. }
  82. var i = (this._front + length - 1) & (this._capacity - 1);
  83. var ret = this[i];
  84. this[i] = void 0;
  85. this._length = length - 1;
  86. return ret;
  87. };
  88. Deque.prototype.shift = function Deque$shift() {
  89. var length = this._length;
  90. if (length === 0) {
  91. return void 0;
  92. }
  93. var front = this._front;
  94. var ret = this[front];
  95. this[front] = void 0;
  96. this._front = (front + 1) & (this._capacity - 1);
  97. this._length = length - 1;
  98. return ret;
  99. };
  100. Deque.prototype.unshift = function Deque$unshift(item) {
  101. var length = this._length;
  102. var argsLength = arguments.length;
  103. if (argsLength > 1) {
  104. var capacity = this._capacity;
  105. if (length + argsLength > capacity) {
  106. for (var i = argsLength - 1; i >= 0; i--) {
  107. this._checkCapacity(length + 1);
  108. var capacity = this._capacity;
  109. var j = (((( this._front - 1 ) &
  110. ( capacity - 1) ) ^ capacity ) - capacity );
  111. this[j] = arguments[i];
  112. length++;
  113. this._length = length;
  114. this._front = j;
  115. }
  116. return length;
  117. }
  118. else {
  119. var front = this._front;
  120. for (var i = argsLength - 1; i >= 0; i--) {
  121. var j = (((( front - 1 ) &
  122. ( capacity - 1) ) ^ capacity ) - capacity );
  123. this[j] = arguments[i];
  124. front = j;
  125. }
  126. this._front = front;
  127. this._length = length + argsLength;
  128. return length + argsLength;
  129. }
  130. }
  131. if (argsLength === 0) return length;
  132. this._checkCapacity(length + 1);
  133. var capacity = this._capacity;
  134. var i = (((( this._front - 1 ) &
  135. ( capacity - 1) ) ^ capacity ) - capacity );
  136. this[i] = item;
  137. this._length = length + 1;
  138. this._front = i;
  139. return length + 1;
  140. };
  141. Deque.prototype.peekBack = function Deque$peekBack() {
  142. var length = this._length;
  143. if (length === 0) {
  144. return void 0;
  145. }
  146. var index = (this._front + length - 1) & (this._capacity - 1);
  147. return this[index];
  148. };
  149. Deque.prototype.peekFront = function Deque$peekFront() {
  150. if (this._length === 0) {
  151. return void 0;
  152. }
  153. return this[this._front];
  154. };
  155. Deque.prototype.get = function Deque$get(index) {
  156. var i = index;
  157. if ((i !== (i | 0))) {
  158. return void 0;
  159. }
  160. var len = this._length;
  161. if (i < 0) {
  162. i = i + len;
  163. }
  164. if (i < 0 || i >= len) {
  165. return void 0;
  166. }
  167. return this[(this._front + i) & (this._capacity - 1)];
  168. };
  169. Deque.prototype.isEmpty = function Deque$isEmpty() {
  170. return this._length === 0;
  171. };
  172. Deque.prototype.clear = function Deque$clear() {
  173. var len = this._length;
  174. var front = this._front;
  175. var capacity = this._capacity;
  176. for (var j = 0; j < len; ++j) {
  177. this[(front + j) & (capacity - 1)] = void 0;
  178. }
  179. this._length = 0;
  180. this._front = 0;
  181. };
  182. Deque.prototype.toString = function Deque$toString() {
  183. return this.toArray().toString();
  184. };
  185. Deque.prototype.valueOf = Deque.prototype.toString;
  186. Deque.prototype.removeFront = Deque.prototype.shift;
  187. Deque.prototype.removeBack = Deque.prototype.pop;
  188. Deque.prototype.insertFront = Deque.prototype.unshift;
  189. Deque.prototype.insertBack = Deque.prototype.push;
  190. Deque.prototype.enqueue = Deque.prototype.push;
  191. Deque.prototype.dequeue = Deque.prototype.shift;
  192. Deque.prototype.toJSON = Deque.prototype.toArray;
  193. Object.defineProperty(Deque.prototype, "length", {
  194. get: function() {
  195. return this._length;
  196. },
  197. set: function() {
  198. throw new RangeError("");
  199. }
  200. });
  201. Deque.prototype._checkCapacity = function Deque$_checkCapacity(size) {
  202. if (this._capacity < size) {
  203. this._resizeTo(getCapacity(this._capacity * 1.5 + 16));
  204. }
  205. };
  206. Deque.prototype._resizeTo = function Deque$_resizeTo(capacity) {
  207. var oldCapacity = this._capacity;
  208. this._capacity = capacity;
  209. var front = this._front;
  210. var length = this._length;
  211. if (front + length > oldCapacity) {
  212. var moveItemsCount = (front + length) & (oldCapacity - 1);
  213. arrayMove(this, 0, this, oldCapacity, moveItemsCount);
  214. }
  215. };
  216. var isArray = Array.isArray;
  217. function arrayMove(src, srcIndex, dst, dstIndex, len) {
  218. for (var j = 0; j < len; ++j) {
  219. dst[j + dstIndex] = src[j + srcIndex];
  220. src[j + srcIndex] = void 0;
  221. }
  222. }
  223. function pow2AtLeast(n) {
  224. n = n >>> 0;
  225. n = n - 1;
  226. n = n | (n >> 1);
  227. n = n | (n >> 2);
  228. n = n | (n >> 4);
  229. n = n | (n >> 8);
  230. n = n | (n >> 16);
  231. return n + 1;
  232. }
  233. function getCapacity(capacity) {
  234. if (typeof capacity !== "number") {
  235. if (isArray(capacity)) {
  236. capacity = capacity.length;
  237. }
  238. else {
  239. return 16;
  240. }
  241. }
  242. return pow2AtLeast(
  243. Math.min(
  244. Math.max(16, capacity), 1073741824)
  245. );
  246. }
  247. module.exports = Deque;