@creejs/commons-collection 2.0.4 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CommonsLang = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
- function a$1(t){return "boolean"==typeof t}function c$1(t){return "function"==typeof t}function l$1(t){return null!=t&&"object"==typeof t&&!A(t)}function y(t){return null==t}function p$1(t){return !!m$1(t)&&t>0}function h$1(t){return !!m$1(t)&&t>=0}function g$1(t){return !!m$1(t)&&t<0}function w$1(t){return null===t}function d$1(t){return void 0===t}function m$1(t){return null!=t&&"number"==typeof t}function b$1(t){return null!=t&&"object"==typeof t}function A(t){return null!==t&&"object"==typeof t&&(t.constructor===Object||void 0===t.constructor)}function E(t){return null!=t&&"function"==typeof t.then}function N(t){return null!=t&&"string"==typeof t}function $(t){return null!=t&&"symbol"==typeof t}function O$1(t){return ArrayBuffer.isView(t)&&t.constructor!==DataView}function v$1(t){return t instanceof Int8Array}function j(t){return t instanceof Uint8Array}function P(t){return t instanceof Uint8ClampedArray}function S(t){return t instanceof Int16Array}function x(t){return t instanceof Uint16Array}function U(t){return t instanceof Int32Array}function T(t){return t instanceof Uint32Array}function I(t){return t instanceof Float32Array}function B(t){return t instanceof Float64Array}function k$1(t){return t instanceof BigInt64Array}function L$1(t){return t instanceof BigUint64Array}function F(t){return t instanceof ArrayBuffer}var C={assertNumber:q,assertPositive:_$1,assertNegative:function(t,r){if(!g$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Negative: ${t}`)},assertNotNegative:J,assertBoolean:function(t,r){if(!a$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Boolean: type=${typeof t} value=${Z(t)}`)},assertObject:R,assertPlainObject:function(t,r){if(!A(t))throw new Error(`${r?'"'+r+'" ':""}Not PlainObject: type=${typeof t} value=${Z(t)}`)},assertSymbol:function(t,r){if(!$(t))throw new Error(`${r?'"'+r+'" ':""}Not Symbol: type=${typeof t} value=${Z(t)}`)},assertFunction:W,assertInstance:function(t,r){if(!l$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Class Instance: type=${typeof t} value=${Z(t)}`)},assertPromise:H,assertNil:function(t,r){if(!y(t))throw new Error(`${r?'"'+r+'" ':""}Neither Null nor Undefined: type=${typeof t} value=${Z(t)}`)},assertNotNil:V,assertNull:function(t,r){if(!w$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Null: type=${typeof t} value=${Z(t)}`)},assertNotNull:function(t,r){if(w$1(t))throw new Error((r?'"'+r+'" ':"")+"Should Not Null")},assertUndefined:function(t,r){if(!d$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Undefined: type=${typeof t} value=${Z(t)}`)},assertString:M,assertArray:D,assertStringOrSymbol:function(t,r){if(!N(t)&&!$(t))throw new Error(`${r?'"'+r+'" ':""}Not String or Symbol: type=${typeof t} value=${Z(t)}`)},assertInt8Array:function(t,r){if(v$1(t))throw new Error((r?'"'+r+'" ':"")+"Not Int8Array")},assertUint8Array:function(t,r){if(j(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint8Array")},assertUint8ClampedArray:function(t,r){if(P(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint8ClampedArray")},assertInt16Array:function(t,r){if(S(t))throw new Error((r?'"'+r+'" ':"")+"Not Int16Array")},assertUint16Array:function(t,r){if(x(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint16Array")},assertInt32Array:function(t,r){if(U(t))throw new Error((r?'"'+r+'" ':"")+"Not Int32Array")},assertUint32Array:function(t,r){if(T(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint32Array")},assertFloat32Array:function(t,r){if(I(t))throw new Error((r?'"'+r+'" ':"")+"Not Float32Array")},assertFloat64Array:function(t,r){if(B(t))throw new Error((r?'"'+r+'" ':"")+"Not Float64Array")},assertBigInt64Array:function(t,r){if(k$1(t))throw new Error((r?'"'+r+'" ':"")+"Not BigInt64Array")},assertBigUint64Array:function(t,r){if(L$1(t))throw new Error((r?'"'+r+'" ':"")+"Not BigUint64Array")},assertTypedArray:function(t,r){if(O$1(t))throw new Error((r?'"'+r+'" ':"")+"Not TypedArray")},assertArrayBuffer:z};function D(t,r){if(!Array.isArray(t))throw new Error(`${r?'"'+r+'" ':""}Not Array: type=${typeof t} value=${Z(t)}`)}function M(t,r){if(!N(t))throw new Error(`${r?'"'+r+'" ':""}Not String: type=${typeof t} value=${Z(t)}`)}function q(t,r){if(!m$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Number: type=${typeof t} value=${Z(t)}`)}function _$1(t,r){if(!p$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Positive: ${t}`)}function J(t,r){if(!h$1(t))throw new Error(`${r?'"'+r+'" ':""}Not "0 or Positive": ${t}`)}function R(t,r){if(!b$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Object: type=${typeof t} value=${Z(t)}`)}function W(t,r){if(!c$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Function: type=${typeof t} value=${Z(t)}`)}function H(t,r){if(!E(t))throw new Error(`${r?'"'+r+'" ':""}Not Promise: type=${typeof t} value=${Z(t)}`)}function V(t,r){if(y(t))throw new Error((r?'"'+r+'" ':"")+"Should Not Nil")}function z(t,r){if(!F(t))throw new Error((r?'"'+r+'" ':"")+"Not ArrayBuffer")}function Z(t){if(null===t)return "null";if(void 0===t)return "undefined";let r;try{r=JSON.stringify(t);}catch(e){r=t.toString();}return r}new TextDecoder;new TextEncoder;const dt=1e6;var mt={s2ns:1e9,ms2ns:dt,timestamp:function(){if("undefined"!=typeof performance&&"number"==typeof performance.timeOrigin){const t=performance.timeOrigin,r=performance.now();return Math.ceil((t+r)/dt)}return Date.now()},timestamp64:bt,lapseNano:At,lapseMillis:Et,timeoutNano:function(t,r){return At(t)>r},timeoutMillis:function(t,r){return Et(t)>r}};function bt(){if("undefined"!=typeof performance&&"number"==typeof performance.timeOrigin){const t=performance.timeOrigin,r=performance.now();return BigInt((t+r)*dt)}return BigInt(Date.now()*dt)}function At(t,r){return (r??bt())-t}function Et(t,r){r=r??bt();return BigInt(r-t)/BigInt(dt)}
7
+ function a$1(t){return "boolean"==typeof t}function c$1(t){return "function"==typeof t}function l$1(t){return null!=t&&"object"==typeof t&&!A(t)}function y(t){return null==t}function p$1(t){return !!m$1(t)&&t>0}function h$1(t){return !!m$1(t)&&t>=0}function g$1(t){return !!m$1(t)&&t<0}function w$1(t){return null===t}function d$1(t){return void 0===t}function m$1(t){return null!=t&&"number"==typeof t}function b$1(t){return null!=t&&"object"==typeof t}function A(t){return null!==t&&"object"==typeof t&&(t.constructor===Object||void 0===t.constructor)}function E(t){return null!=t&&"function"==typeof t.then}function N(t){return null!=t&&"string"==typeof t}function $(t){return null!=t&&"symbol"==typeof t}function O$1(t){return ArrayBuffer.isView(t)&&t.constructor!==DataView}function v$1(t){return t instanceof Int8Array}function P(t){return t instanceof Uint8Array}function j(t){return t instanceof Uint8ClampedArray}function S(t){return t instanceof Int16Array}function x(t){return t instanceof Uint16Array}function U(t){return t instanceof Int32Array}function T(t){return t instanceof Uint32Array}function I(t){return t instanceof Float32Array}function B(t){return t instanceof Float64Array}function k$1(t){return t instanceof BigInt64Array}function L$1(t){return t instanceof BigUint64Array}function F(t){return t instanceof ArrayBuffer}var C={assertNumber:q,assertPositive:_$1,assertNegative:function(t,r){if(!g$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Negative: ${t}`)},assertNotNegative:R,assertBoolean:function(t,r){if(!a$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Boolean: type=${typeof t} value=${Z(t)}`)},assertObject:J,assertPlainObject:function(t,r){if(!A(t))throw new Error(`${r?'"'+r+'" ':""}Not PlainObject: type=${typeof t} value=${Z(t)}`)},assertSymbol:function(t,r){if(!$(t))throw new Error(`${r?'"'+r+'" ':""}Not Symbol: type=${typeof t} value=${Z(t)}`)},assertFunction:W,assertInstance:function(t,r){if(!l$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Class Instance: type=${typeof t} value=${Z(t)}`)},assertPromise:H,assertNil:function(t,r){if(!y(t))throw new Error(`${r?'"'+r+'" ':""}Neither Null nor Undefined: type=${typeof t} value=${Z(t)}`)},assertNotNil:V,assertNull:function(t,r){if(!w$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Null: type=${typeof t} value=${Z(t)}`)},assertNotNull:function(t,r){if(w$1(t))throw new Error((r?'"'+r+'" ':"")+"Should Not Null")},assertUndefined:function(t,r){if(!d$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Undefined: type=${typeof t} value=${Z(t)}`)},assertString:D,assertArray:M,assertStringOrSymbol:function(t,r){if(!N(t)&&!$(t))throw new Error(`${r?'"'+r+'" ':""}Not String or Symbol: type=${typeof t} value=${Z(t)}`)},assertInt8Array:function(t,r){if(v$1(t))throw new Error((r?'"'+r+'" ':"")+"Not Int8Array")},assertUint8Array:function(t,r){if(P(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint8Array")},assertUint8ClampedArray:function(t,r){if(j(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint8ClampedArray")},assertInt16Array:function(t,r){if(S(t))throw new Error((r?'"'+r+'" ':"")+"Not Int16Array")},assertUint16Array:function(t,r){if(x(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint16Array")},assertInt32Array:function(t,r){if(U(t))throw new Error((r?'"'+r+'" ':"")+"Not Int32Array")},assertUint32Array:function(t,r){if(T(t))throw new Error((r?'"'+r+'" ':"")+"Not Uint32Array")},assertFloat32Array:function(t,r){if(I(t))throw new Error((r?'"'+r+'" ':"")+"Not Float32Array")},assertFloat64Array:function(t,r){if(B(t))throw new Error((r?'"'+r+'" ':"")+"Not Float64Array")},assertBigInt64Array:function(t,r){if(k$1(t))throw new Error((r?'"'+r+'" ':"")+"Not BigInt64Array")},assertBigUint64Array:function(t,r){if(L$1(t))throw new Error((r?'"'+r+'" ':"")+"Not BigUint64Array")},assertTypedArray:function(t,r){if(O$1(t))throw new Error((r?'"'+r+'" ':"")+"Not TypedArray")},assertArrayBuffer:z};function M(t,r){if(!Array.isArray(t))throw new Error(`${r?'"'+r+'" ':""}Not Array: type=${typeof t} value=${Z(t)}`)}function D(t,r){if(!N(t))throw new Error(`${r?'"'+r+'" ':""}Not String: type=${typeof t} value=${Z(t)}`)}function q(t,r){if(!m$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Number: type=${typeof t} value=${Z(t)}`)}function _$1(t,r){if(!p$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Positive: ${t}`)}function R(t,r){if(!h$1(t))throw new Error(`${r?'"'+r+'" ':""}Not "0 or Positive": ${t}`)}function J(t,r){if(!b$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Object: type=${typeof t} value=${Z(t)}`)}function W(t,r){if(!c$1(t))throw new Error(`${r?'"'+r+'" ':""}Not Function: type=${typeof t} value=${Z(t)}`)}function H(t,r){if(!E(t))throw new Error(`${r?'"'+r+'" ':""}Not Promise: type=${typeof t} value=${Z(t)}`)}function V(t,r){if(y(t))throw new Error((r?'"'+r+'" ':"")+"Should Not Nil")}function z(t,r){if(!F(t))throw new Error((r?'"'+r+'" ':"")+"Not ArrayBuffer")}var G={isEmpty:K,assertNotEmpty:Y,isBlank:Q,assertNotBlank:function(t,r){if(Q(t))throw new Error(`${r?'"'+r+'" ':""}Is Blank: ${t}`)},capitalize:function(t){if(D(t),0===t.length)return t;const r=t.charAt(0),e=r.toUpperCase();return r===e?t:e+t.slice(1)},decapitalize:function(t){if(D(t),0===t.length)return t;const r=t.charAt(0),e=r.toLowerCase();return r===e?t:e+t.slice(1)},splitWithFixedLength:function(t,r,e=" "){if(D(t),q(r),D(e),0===t.length)return [];if(r<=0)throw new Error("length muse >=0");if(t.length<r)return [t.padEnd(r,e)];const n=[];for(let o=0;o<t.length;o+=r){const i=t.substring(o,o+r);n.push(i.padEnd(r,e));}return n},split:function(t,...r){D(t);if(0===t.length)return [];const e=[...r];0===r.length&&r.push(",");const n=X(t,...e);if(0===n.length)return [];const o=[];let i="",s=0;for(const{marker:r,index:e}of n)i=t.substring(s,e),o.push(i),s=e+r.length;return i=t.substring(s),o.push(i),o},findMarkerPositions:function(t,...r){if(D(t),0===r.length)throw new Error("At least one marker must be provided");const e=[];for(const n of new Set(r)){if(K(n))continue;D(n);let r=t.indexOf(n);for(;-1!==r;)e.push({marker:n,index:r}),r=t.indexOf(n,r+n.length);}return e.sort((t,r)=>t.index-r.index),e},findMarkerPositionsRegex:X,substringBefore:function(t,r){if(D(t),D(r),0===t.length||0===r.length)return;const e=t.indexOf(r);if(-1===e)return;return t.substring(0,e)},substringBeforeLast:function(t,r){if(D(t),D(r),0===t.length||0===r.length)return;const e=t.lastIndexOf(r);if(-1===e)return;return t.substring(0,e)},substringAfter:function(t,r){if(D(t),D(r),0===t.length||0===r.length)return;const e=t.indexOf(r);if(-1===e)return;return t.substring(e+r.length)},substringAfterLast:function(t,r){if(D(t),D(r),0===t.length||0===r.length)return;const e=t.lastIndexOf(r);if(-1===e)return;return t.substring(e+r.length)},substringBetween:function(t,r,e){Y(t),Y(r),Y(e);const n=t.indexOf(r);if(-1===n)return;const o=t.indexOf(e,n+r.length);if(-1===o)return;return t.substring(n+r.length,o)},substringBetweenGreedy:function(t,r,e){Y(t),Y(r),Y(e);const n=t.indexOf(r);if(-1===n)return;const o=t.lastIndexOf(e);if(-1===o||o<=n)return;return t.substring(n+r.length,o)},substringsBetween:function(t,r,e){Y(t),Y(r),Y(e);const n=[];let o=0;for(;;){const i=t.indexOf(r,o);if(-1===i)break;const s=t.indexOf(e,i+r.length);if(-1===s)break;n.push(t.substring(i+r.length,s)),o=s+e.length;}return n},safeToString:Z};function K(t){return null==t||(D(t),0===t.length)}function Y(t,r){if(K(t))throw new Error(`${r?'"'+r+'" ':""}IsEmpty String: ${t}`)}function Q(t){return null==t||(D(t),0===t.trim().length)}function X(t,...r){if(D(t),0===r.length)throw new Error("At least one marker must be provided");const e=[...new Set(r.filter(t=>null!=t))].map(t=>(D(t),t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"))),n=new RegExp(e.map(t=>`(${t})`).join("|"),"g"),o=[];let i=null;for(;null!==(i=n.exec(t));){for(let t=1;t<i.length;t++)if(i[t]){o.push({marker:r[t-1],index:i.index});break}0===i[0].length&&n.lastIndex++;}return o}function Z(t){if(null===t)return "null";if(void 0===t)return "undefined";const r=typeof t;if("string"===r)return t;if("symbol"===r)return `Symbol(${t.description})`;if("function"===r)return `Function ${t.name}(){}`;if(t instanceof String)return t.toString();if(Number.isNaN(t))return "NaN";if(t===1/0)return "Infinity";if(t===-1/0)return "-Infinity";if(t instanceof Error)return `${t.constructor.name}: ${t.message}`;if(t instanceof Promise)return "Promise";if(t instanceof Set)return `Set: ${Z(Array.from(t))}`;if(t instanceof Map)return `Map: ${Z(Array.from(t.entries()))}`;if(t instanceof RegExp)return t.toString();if(Array.isArray(t))return `[${t.map(Z).join(", ")}]`;let e;try{e=JSON.stringify(t);}catch(r){e=t.toString();}return e}new TextDecoder;new TextEncoder;const dt=1e6;var mt={s2ns:1e9,ms2ns:dt,timestamp:function(){if("undefined"!=typeof performance&&"number"==typeof performance.timeOrigin){const t=performance.timeOrigin,r=performance.now();return Math.ceil((t+r)/dt)}return Date.now()},timestamp64:bt,lapseNano:At,lapseMillis:Et,timeoutNano:function(t,r){return At(t)>r},timeoutMillis:function(t,r){return Et(t)>r}};function bt(){if("undefined"!=typeof performance&&"number"==typeof performance.timeOrigin){const t=performance.timeOrigin,r=performance.now();return BigInt((t+r)*dt)}return BigInt(Date.now()*dt)}function At(t,r){return (r??bt())-t}function Et(t,r){r=r??bt();return BigInt(r-t)/BigInt(dt)}
8
8
 
9
9
  // internal
10
10
  // owned
@@ -18,7 +18,7 @@
18
18
  */
19
19
 
20
20
  // module vars
21
- const { assertPositive } = C;
21
+ const { assertPositive: assertPositive$1 } = C;
22
22
 
23
23
  /**
24
24
  * A set that has a fixed capacity and automatically removes the oldest element when the capacity is reached.
@@ -33,7 +33,7 @@
33
33
  * @throws {Error} If capacity is less than or equal to 0
34
34
  */
35
35
  constructor (capacity) {
36
- assertPositive(capacity, 'capacity');
36
+ assertPositive$1(capacity, 'capacity');
37
37
  this.capacity = capacity;
38
38
  /**
39
39
  * 1. key is the Value stored in CappedSet
@@ -724,10 +724,639 @@
724
724
  }
725
725
  }
726
726
 
727
- var index = { CappedSet, TimeWheelCache, Hour24TimeWheelCache };
727
+ // internal
728
+ // owned
729
+
730
+ /**
731
+ * @typedef {{
732
+ * value: any,
733
+ * prev: Node|undefined,
734
+ * next: Node|undefined
735
+ * }} Node
736
+ */
737
+
738
+ // module vars
739
+ const { assertNotNegative } = C;
740
+
741
+ /**
742
+ * A doubly linked list implementation.
743
+ *
744
+ * @class LinkedList
745
+ */
746
+ class LinkedList {
747
+ /**
748
+ * Creates a new LinkedList instance.
749
+ * @constructor
750
+ */
751
+ constructor () {
752
+ /**
753
+ * @type {Node|undefined}
754
+ */
755
+ this._head = undefined;
756
+ /**
757
+ * @type {Node|undefined}
758
+ */
759
+ this._tail = undefined;
760
+ /**
761
+ * @type {number}
762
+ */
763
+ this._size = 0;
764
+ }
765
+
766
+ get size () {
767
+ return this._size
768
+ }
769
+
770
+ /**
771
+ * get the first element
772
+ */
773
+ get first () {
774
+ return this._head?.value
775
+ }
776
+
777
+ /**
778
+ * get the last element
779
+ */
780
+ get last () {
781
+ return this._tail?.value
782
+ }
783
+
784
+ [Symbol.iterator] () {
785
+ let current = this._head;
786
+ const iterator = {
787
+ next () {
788
+ if (current) {
789
+ const value = current.value;
790
+ current = current.next;
791
+ return { value, done: false }
792
+ }
793
+ return { value: undefined, done: true }
794
+ },
795
+ [Symbol.iterator] () {
796
+ return this
797
+ }
798
+ };
799
+ return iterator
800
+ }
801
+
802
+ /**
803
+ * Adds a value to the beginning of the linked list.
804
+ * @param {*} value - The value to add
805
+ * @returns {LinkedList} This linked list instance for chaining
806
+ */
807
+ addFirst (value) {
808
+ /**
809
+ * @type {Node}
810
+ */
811
+ const node = { value, prev: undefined, next: this._head };
812
+
813
+ if (this._head) {
814
+ this._head.prev = node;
815
+ } else {
816
+ this._tail = node;
817
+ }
818
+
819
+ this._head = node;
820
+ this._size++;
821
+ return this
822
+ }
823
+
824
+ /**
825
+ * Adds a value to the end of the linked list.
826
+ * @param {*} value - The value to add
827
+ * @returns {LinkedList} This linked list instance for chaining
828
+ */
829
+ addLast (value) {
830
+ /**
831
+ * @type {Node}
832
+ */
833
+ const node = { value, prev: this._tail, next: undefined };
834
+
835
+ if (this._tail) {
836
+ this._tail.next = node;
837
+ } else {
838
+ this._head = node;
839
+ }
840
+
841
+ this._tail = node;
842
+ this._size++;
843
+ return this
844
+ }
845
+
846
+ /**
847
+ * Adds a value to the end of the linked list.
848
+ * @param {*} value - The value to add
849
+ * @returns {LinkedList} This linked list instance for chaining
850
+ */
851
+ add (value) {
852
+ return this.addLast(value)
853
+ }
854
+
855
+ /**
856
+ * Removes and returns the first element from the linked list.
857
+ * @returns {*} The removed value, or undefined if the list is empty
858
+ */
859
+ removeFirst () {
860
+ if (!this._head) {
861
+ return undefined
862
+ }
863
+
864
+ const value = this._head.value;
865
+ this._head = this._head.next;
866
+
867
+ if (this._head) {
868
+ this._head.prev = undefined;
869
+ } else {
870
+ this._tail = undefined;
871
+ }
872
+
873
+ this._size--;
874
+ return value
875
+ }
876
+
877
+ /**
878
+ * Removes and returns the last element from the linked list.
879
+ * @returns {*} The removed value, or undefined if the list is empty
880
+ */
881
+ removeLast () {
882
+ if (!this._tail) {
883
+ return undefined
884
+ }
885
+
886
+ const value = this._tail.value;
887
+ this._tail = this._tail.prev;
888
+
889
+ if (this._tail) {
890
+ this._tail.next = undefined;
891
+ } else {
892
+ this._head = undefined;
893
+ }
894
+
895
+ this._size--;
896
+ return value
897
+ }
898
+
899
+ /**
900
+ * Removes the first occurrence of the specified value from the linked list.
901
+ * @param {*} value - The value to remove
902
+ * @param {function(*, *): boolean} [comparator] - Optional comparison function (a, b) => boolean
903
+ * @returns {boolean} True if the value was found and removed, false otherwise
904
+ */
905
+ remove (value, comparator) {
906
+ const compare = comparator || this._defaultComparator;
907
+ let current = this._head;
908
+
909
+ while (current) {
910
+ if (compare(current.value, value)) {
911
+ this._removeNode(current);
912
+ return true
913
+ }
914
+ current = current.next;
915
+ }
916
+
917
+ return false
918
+ }
919
+
920
+ /**
921
+ * Removes all occurrences of the specified value from the linked list.
922
+ * @param {*} value - The value to remove
923
+ * @param {function(*, *): boolean} [comparator] - Optional comparison function (a, b) => boolean
924
+ * @returns {number} The number of elements removed
925
+ */
926
+ removeAll (value, comparator) {
927
+ const compare = comparator || this._defaultComparator;
928
+ let removedCount = 0;
929
+ let current = this._head;
930
+
931
+ while (current) {
932
+ const next = current.next; // Store next before potential removal
933
+ if (compare(current.value, value)) {
934
+ this._removeNode(current);
935
+ removedCount++;
936
+ }
937
+ current = next;
938
+ }
939
+
940
+ return removedCount
941
+ }
942
+
943
+ /**
944
+ * Removes the element at the specified index.
945
+ * @param {number} index - The index of the element to remove
946
+ * @returns {*} The removed value, or undefined if index is out of bounds
947
+ */
948
+ removeAt (index) {
949
+ assertNotNegative(index, 'index');
950
+
951
+ if (index >= this._size) {
952
+ return undefined
953
+ }
954
+
955
+ if (index === 0) {
956
+ return this.removeFirst()
957
+ }
958
+
959
+ if (index === this._size - 1) {
960
+ return this.removeLast()
961
+ }
962
+
963
+ let current = this._head;
964
+ for (let i = 0; i < index; i++) {
965
+ current = current?.next;
966
+ }
967
+
968
+ if (current) {
969
+ const value = current.value;
970
+ this._removeNode(current);
971
+ return value
972
+ }
973
+
974
+ return undefined
975
+ }
976
+
977
+ /**
978
+ * Checks if the linked list contains the specified value.
979
+ * @param {*} value - The value to check for
980
+ * @param {function(*, *): boolean} [comparator] - Optional comparison function (a, b) => boolean
981
+ * @returns {boolean} True if the value exists, false otherwise
982
+ */
983
+ contains (value, comparator) {
984
+ const compare = comparator || this._defaultComparator;
985
+ let current = this._head;
986
+ while (current) {
987
+ if (compare(current.value, value)) {
988
+ return true
989
+ }
990
+ current = current.next;
991
+ }
992
+ return false
993
+ }
994
+
995
+ /**
996
+ * Returns the index of the first occurrence of the specified value.
997
+ * @param {*} value - The value to find
998
+ * @param {function(*, *): boolean} [comparator] - Optional comparison function (a, b) => boolean
999
+ * @returns {number} The index of the value, or -1 if not found
1000
+ */
1001
+ indexOf (value, comparator) {
1002
+ const compare = comparator || this._defaultComparator;
1003
+ let current = this._head;
1004
+ let index = 0;
1005
+ while (current) {
1006
+ if (compare(current.value, value)) {
1007
+ return index
1008
+ }
1009
+ current = current.next;
1010
+ index++;
1011
+ }
1012
+ return -1
1013
+ }
1014
+
1015
+ /**
1016
+ * Returns the index of the last occurrence of the specified value.
1017
+ * @param {*} value - The value to find
1018
+ * @param {function(*, *): boolean} [comparator] - Optional comparison function (a, b) => boolean
1019
+ * @returns {number} The index of the last occurrence, or -1 if not found
1020
+ */
1021
+ indexLastOf (value, comparator) {
1022
+ const compare = comparator || this._defaultComparator;
1023
+ let current = this._tail;
1024
+ let index = this._size - 1;
1025
+ while (current) {
1026
+ if (compare(current.value, value)) {
1027
+ return index
1028
+ }
1029
+ current = current.prev;
1030
+ index--;
1031
+ }
1032
+ return -1
1033
+ }
1034
+
1035
+ /**
1036
+ * Gets the value at the specified index.
1037
+ * @param {number} index - The index of the value to get
1038
+ * @returns {*} The value at the index, or undefined if index is out of bounds
1039
+ */
1040
+ get (index) {
1041
+ assertNotNegative(index, 'index');
1042
+
1043
+ if (index >= this._size) {
1044
+ return undefined
1045
+ }
1046
+
1047
+ let current = this._head;
1048
+ for (let i = 0; i < index; i++) {
1049
+ current = current?.next;
1050
+ }
1051
+
1052
+ return current?.value
1053
+ }
1054
+
1055
+ /**
1056
+ * Inserts a value at the specified index.
1057
+ * @param {number} index - The index at which to insert the value
1058
+ * @param {*} value - The value to insert
1059
+ * @returns {LinkedList} This linked list instance for chaining
1060
+ */
1061
+ insertAt (index, value) {
1062
+ assertNotNegative(index, 'index');
1063
+
1064
+ if (index === 0) {
1065
+ return this.addFirst(value)
1066
+ }
1067
+
1068
+ if (index >= this._size) {
1069
+ return this.addLast(value)
1070
+ }
1071
+
1072
+ let current = this._head;
1073
+ for (let i = 0; i < index - 1; i++) {
1074
+ current = current?.next;
1075
+ }
1076
+
1077
+ if (current) {
1078
+ /**
1079
+ * @type {Node}
1080
+ */
1081
+ const node = { value, prev: current, next: current.next };
1082
+ if (current.next) {
1083
+ current.next.prev = node;
1084
+ }
1085
+ current.next = node;
1086
+ this._size++;
1087
+ }
1088
+
1089
+ return this
1090
+ }
1091
+
1092
+ /**
1093
+ * Removes all elements from the linked list.
1094
+ */
1095
+ clear () {
1096
+ this._head = undefined;
1097
+ this._tail = undefined;
1098
+ this._size = 0;
1099
+ }
1100
+
1101
+ /**
1102
+ * Returns an array containing all the values in the linked list.
1103
+ * @returns {any[]} An array of all values
1104
+ */
1105
+ toArray () {
1106
+ const result = [];
1107
+ let current = this._head;
1108
+ while (current) {
1109
+ result.push(current.value);
1110
+ current = current.next;
1111
+ }
1112
+ return result
1113
+ }
1114
+
1115
+ /**
1116
+ * Returns an iterator of the values in the linked list.
1117
+ * @returns {Iterator<any>} An iterator object that yields the values of the linked list
1118
+ */
1119
+ values () {
1120
+ return this[Symbol.iterator]()
1121
+ }
1122
+
1123
+ /**
1124
+ * Returns a slice of the linked list as an array.
1125
+ * @param {number} [start=0] - The start index (inclusive). If negative, counts from the end.
1126
+ * @param {number} [end=this.size] - The end index (exclusive). If negative, counts from the end.
1127
+ * @returns {any[]} An array containing the sliced elements
1128
+ */
1129
+ slice (start = 0, end = this.size) {
1130
+ // Handle negative indices
1131
+ const normalizedStart = start < 0 ? Math.max(this.size + start, 0) : Math.min(start, this.size);
1132
+ const normalizedEnd = end < 0 ? Math.max(this.size + end, 0) : Math.min(end, this.size);
1133
+
1134
+ if (normalizedStart >= normalizedEnd) {
1135
+ return []
1136
+ }
1137
+
1138
+ if (start < 0) {
1139
+ return this._sliceNegative(normalizedStart, normalizedEnd)
1140
+ } else {
1141
+ return this._slicePositive(normalizedStart, normalizedEnd)
1142
+ }
1143
+ }
1144
+
1145
+ /**
1146
+ * Returns a string representation of the FixedLinkedList.
1147
+ * @returns {string} String representation
1148
+ */
1149
+ toString () {
1150
+ const partialElements = this.slice(0, 3);
1151
+ const partialString = this.size > 3 ? G.safeToString(partialElements) + '...' : G.safeToString(partialElements);
1152
+ return `LinkedList[${this.size}](${partialString})`
1153
+ }
1154
+
1155
+ /**
1156
+ * Slice implementation for positive indices (iterates from head to tail)
1157
+ * @param {number} start - Normalized start index (inclusive)
1158
+ * @param {number} end - Normalized end index (exclusive)
1159
+ * @returns {any[]} An array containing the sliced elements
1160
+ * @private
1161
+ */
1162
+ _slicePositive (start, end) {
1163
+ const result = [];
1164
+ let current = this._head;
1165
+ let index = 0;
1166
+
1167
+ // Move to the starting position
1168
+ while (current && index < start) {
1169
+ current = current.next;
1170
+ index++;
1171
+ }
1172
+
1173
+ // Collect elements from start to end
1174
+ while (current && index < end) {
1175
+ result.push(current.value);
1176
+ current = current.next;
1177
+ index++;
1178
+ }
1179
+
1180
+ return result
1181
+ }
1182
+
1183
+ /**
1184
+ * Slice implementation for negative indices (iterates from tail to head)
1185
+ * @param {number} start - Normalized start index (inclusive)
1186
+ * @param {number} end - Normalized end index (exclusive)
1187
+ * @returns {any[]} An array containing the sliced elements
1188
+ * @private
1189
+ */
1190
+ _sliceNegative (start, end) {
1191
+ const result = [];
1192
+ let current = this._tail;
1193
+ let index = this.size - 1;
1194
+
1195
+ // Move to the starting position
1196
+ while (current && index > start) {
1197
+ current = current.prev;
1198
+ index--;
1199
+ }
1200
+
1201
+ // Collect elements from start to end
1202
+ while (current && index < end) {
1203
+ result.push(current.value);
1204
+ current = current.next;
1205
+ index++;
1206
+ }
1207
+
1208
+ return result
1209
+ }
1210
+
1211
+ /**
1212
+ * Removes a node from the linked list.
1213
+ * @param {Node} node - The node to be removed
1214
+ * @private
1215
+ */
1216
+ _removeNode (node) {
1217
+ if (node.prev) {
1218
+ node.prev.next = node.next;
1219
+ } else {
1220
+ this._head = node.next;
1221
+ }
1222
+
1223
+ if (node.next) {
1224
+ node.next.prev = node.prev;
1225
+ } else {
1226
+ this._tail = node.prev;
1227
+ }
1228
+
1229
+ this._size--;
1230
+ }
1231
+
1232
+ /**
1233
+ * Default comparator for strict equality comparison.
1234
+ * @param {*} a - First value to compare
1235
+ * @param {*} b - Second value to compare
1236
+ * @returns {boolean} True if values are strictly equal
1237
+ * @private
1238
+ */
1239
+ _defaultComparator (a, b) {
1240
+ return a === b
1241
+ }
1242
+ }
1243
+
1244
+ // internal
1245
+ // owned
1246
+
1247
+ // module vars
1248
+ const { assertPositive } = C;
1249
+
1250
+ /**
1251
+ * A fixed-capacity linked list that automatically removes elements when capacity is exceeded.
1252
+ * When adding to the end (addLast), it removes the first element if capacity is full.
1253
+ * When adding to the beginning (addFirst), it removes the last element if capacity is full.
1254
+ *
1255
+ * @class FixedLinkedList
1256
+ * @extends LinkedList
1257
+ */
1258
+ class FixedLinkedList extends LinkedList {
1259
+ /**
1260
+ * Creates a new FixedLinkedList instance with a fixed capacity.
1261
+ * @constructor
1262
+ * @param {number} capacity - The maximum number of elements the list can hold (must be > 0)
1263
+ * @throws {Error} If capacity is less than or equal to 0
1264
+ */
1265
+ constructor (capacity) {
1266
+ assertPositive(capacity, 'capacity');
1267
+ super();
1268
+ this.capacity = Math.ceil(capacity);
1269
+ }
1270
+
1271
+ /**
1272
+ * Adds a value to the beginning of the linked list.
1273
+ * If the list is at capacity, removes the last element before adding.
1274
+ * @param {*} value - The value to add
1275
+ * @returns {FixedLinkedList} This linked list instance for chaining
1276
+ */
1277
+ addFirst (value) {
1278
+ if (this.size >= this.capacity) {
1279
+ this.removeLast();
1280
+ }
1281
+ super.addFirst(value);
1282
+ return this
1283
+ }
1284
+
1285
+ /**
1286
+ * Adds a value to the end of the linked list.
1287
+ * If the list is at capacity, removes the first element before adding.
1288
+ * @param {*} value - The value to add
1289
+ * @returns {FixedLinkedList} This linked list instance for chaining
1290
+ */
1291
+ addLast (value) {
1292
+ if (this.size >= this.capacity) {
1293
+ this.removeFirst();
1294
+ }
1295
+ super.addLast(value);
1296
+ return this
1297
+ }
1298
+
1299
+ /**
1300
+ * Adds a value to the end of the linked list.
1301
+ * If the list is at capacity, removes the first element before adding.
1302
+ * @param {*} value - The value to add
1303
+ * @returns {FixedLinkedList} This linked list instance for chaining
1304
+ */
1305
+ add (value) {
1306
+ return this.addLast(value)
1307
+ }
1308
+
1309
+ /**
1310
+ * Inserts a value at the specified index.
1311
+ * If the list is at capacity and index is not at the end, removes the first element before adding.
1312
+ * If the list is at capacity and index is at the end, removes the first element before adding.
1313
+ * @param {number} index - The index at which to insert the value
1314
+ * @param {*} value - The value to insert
1315
+ * @returns {FixedLinkedList} This linked list instance for chaining
1316
+ */
1317
+ insertAt (index, value) {
1318
+ // Remove an element if we're at capacity and not adding beyond current size
1319
+ if (this.size >= this.capacity) {
1320
+ // Always remove first element to maintain capacity
1321
+ this.removeFirst();
1322
+ }
1323
+ super.insertAt(index, value);
1324
+ return this
1325
+ }
1326
+
1327
+ /**
1328
+ * Returns the remaining capacity of the list.
1329
+ * @returns {number} The number of additional elements that can be added
1330
+ */
1331
+ get remainingCapacity () {
1332
+ return this.capacity - this.size
1333
+ }
1334
+
1335
+ /**
1336
+ * Checks if the list is at full capacity.
1337
+ * @returns {boolean} True if the list is full, false otherwise
1338
+ */
1339
+ get isFull () {
1340
+ return this.size >= this.capacity
1341
+ }
1342
+
1343
+ /**
1344
+ * Returns a string representation of the FixedLinkedList.
1345
+ * @returns {string} String representation
1346
+ */
1347
+ toString () {
1348
+ const partialElements = this.slice(0, 3);
1349
+ const partialString = this.size > 3 ? G.safeToString(partialElements) + '...' : G.safeToString(partialElements);
1350
+ return `FixedLinkedList[${this.size}/${this.capacity}](${partialString})`
1351
+ }
1352
+ }
1353
+
1354
+ var index = { CappedSet, TimeWheelCache, Hour24TimeWheelCache, LinkedList, FixedLinkedList };
728
1355
 
729
1356
  exports.CappedSet = CappedSet;
1357
+ exports.FixedLinkedList = FixedLinkedList;
730
1358
  exports.Hour24TimeWheelCache = Hour24TimeWheelCache;
1359
+ exports.LinkedList = LinkedList;
731
1360
  exports.TimeWheelCache = TimeWheelCache;
732
1361
  exports.default = index;
733
1362