senaev-utils 1.0.0
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.
- package/README.md +11 -0
- package/package.json +66 -0
- package/src/reactHooks/setDeepEqualState.ts +19 -0
- package/src/reactHooks/useLocationParameter.ts +46 -0
- package/src/reactHooks/useObjectDeepChangesCounter.ts +22 -0
- package/src/reactHooks/useObservableMap/useObservableMap.ts +21 -0
- package/src/reactHooks/useRecentChangeTimer.ts +42 -0
- package/src/reactHooks/useReload.ts +17 -0
- package/src/reactHooks/useVisualizedProcessesTree.ts +202 -0
- package/src/types/Boolean.ts +9 -0
- package/src/types/DeepPartial.ts +1 -0
- package/src/types/GlobalContext.ts +8 -0
- package/src/types/HexColorString.ts +9 -0
- package/src/types/ISOLang.ts +5 -0
- package/src/types/IsEqualUnion.ts +1 -0
- package/src/types/IterableWithIndexAccess.ts +4 -0
- package/src/types/Kilobits.ts +4 -0
- package/src/types/Network/Bits.ts +4 -0
- package/src/types/Network/Bps.ts +4 -0
- package/src/types/Network/Kbps.ts +4 -0
- package/src/types/Network/Mbps.ts +4 -0
- package/src/types/Number/AngleInDegrees.ts +3 -0
- package/src/types/Number/FiniteNumber.ts +11 -0
- package/src/types/Number/Integer.ts +14 -0
- package/src/types/Number/IntegerInString.ts +13 -0
- package/src/types/Number/Number.ts +15 -0
- package/src/types/Number/Portion.ts +4 -0
- package/src/types/Number/PositiveInteger.ts +30 -0
- package/src/types/Number/PositiveNumber.ts +4 -0
- package/src/types/Number/StringUnsignedInteger.ts +4 -0
- package/src/types/Number/UnsignedFiniteNumber.ts +13 -0
- package/src/types/Number/UnsignedInteger.ts +28 -0
- package/src/types/Object/Object.ts +20 -0
- package/src/types/Percent.ts +4 -0
- package/src/types/PixelPosition.ts +9 -0
- package/src/types/PixelSize.ts +9 -0
- package/src/types/Pixels.ts +4 -0
- package/src/types/RangeTuple.ts +1 -0
- package/src/types/Size.ts +8 -0
- package/src/types/Time/DaysCount.ts +6 -0
- package/src/types/Time/Hours.ts +4 -0
- package/src/types/Time/ISODateString/ISODateString.ts +16 -0
- package/src/types/Time/Milliseconds.ts +4 -0
- package/src/types/Time/Minutes.ts +4 -0
- package/src/types/Time/Seconds.ts +5 -0
- package/src/types/Time/Time.ts +13 -0
- package/src/types/Time/Timestamp.ts +6 -0
- package/src/types/Time/UnixTimeMs.ts +6 -0
- package/src/types/Time/UnixTimeSec.ts +11 -0
- package/src/types/Time/const.ts +24 -0
- package/src/types/any/AnyAsyncFunction.ts +2 -0
- package/src/types/any/AnyFunction.ts +2 -0
- package/src/types/assertions/ANY_VALUE.ts +2 -0
- package/src/types/assertions/isNever/isNever.ts +34 -0
- package/src/types/assertions/isTrue/isTrue.ts +13 -0
- package/src/utils/AbortableProcess.ts +160 -0
- package/src/utils/Array/createArray/createArray.ts +8 -0
- package/src/utils/Array/createIntegerSequenceArray/createIntegerSequenceArray.ts +3 -0
- package/src/utils/Array/getUniqueValues/getUniqueValues.ts +3 -0
- package/src/utils/Array/separateToArrays/separateToArrays.ts +24 -0
- package/src/utils/Array/shuffleArray/shuffleArray.ts +18 -0
- package/src/utils/CircularBuffer/CircularBuffer.ts +117 -0
- package/src/utils/DOM/blurDocument.ts +3 -0
- package/src/utils/DOM/unfocusDocument.ts +3 -0
- package/src/utils/Date/dateToUnixTimeSec/dateToUnixTimeSec.ts +6 -0
- package/src/utils/Date/isoDateStringToUnixTimeMs/isoDateStringToUnixTimeMs.ts +6 -0
- package/src/utils/Date/isoDateStringToUnixTimeSec/isoDateStringToUnixTimeSec.ts +7 -0
- package/src/utils/Date/unixTimeSecToIsoDateString/unixTimeSecToIsoDateString.ts +6 -0
- package/src/utils/Deque/Deque.ts +530 -0
- package/src/utils/DeviceDetection/isTouchScreenDevice/isTouchScreenDevice.ts +16 -0
- package/src/utils/Error/rethrowError/rethrowError.ts +8 -0
- package/src/utils/Error/wrapError.ts +32 -0
- package/src/utils/Function/callFirstThenOther/callFirstThenOther.ts +24 -0
- package/src/utils/Function/callFunctions/callFunctions.ts +11 -0
- package/src/utils/Function/callTimes/callTimes.ts +5 -0
- package/src/utils/Function/isFunction.ts +3 -0
- package/src/utils/Function/noop/index.ts +4 -0
- package/src/utils/Function/once/once.ts +32 -0
- package/src/utils/Function/subscribeUpdatesWithTimeout/index.ts +44 -0
- package/src/utils/Function/throttleFunction/throttleFunction.ts +18 -0
- package/src/utils/Function/throttleWithPromiseFunction/throttleWithPromiseFunction.ts +19 -0
- package/src/utils/Function/tryCatch/tryCatch.ts +13 -0
- package/src/utils/Latch/Latch.ts +63 -0
- package/src/utils/Map/ObservableMap/ObservableMap.ts +55 -0
- package/src/utils/Map/findMapsDifferences/findMapsDifferences.ts +35 -0
- package/src/utils/Map/mapGetOrSet/mapGetOrSet.ts +7 -0
- package/src/utils/Map/mapMapToArray/mapMapToArray.ts +6 -0
- package/src/utils/Map/mapMapValues/mapMapValues.ts +9 -0
- package/src/utils/Math/createSimpleMovingAverageSeries/createSimpleMovingAverageSeries.ts +22 -0
- package/src/utils/Math/mean/mean.ts +14 -0
- package/src/utils/Math/simpleMovingAverageUsingAccFabric/simpleMovingAverageUsingAccFabric.ts +29 -0
- package/src/utils/Math/sum/sum.ts +45 -0
- package/src/utils/MinHeap/MinHeap.ts +88 -0
- package/src/utils/MinHeapUniqueNumber/MinHeapUniqueNumber.ts +105 -0
- package/src/utils/MinMaxHeap/MinMaxHeap.ts +91 -0
- package/src/utils/Number/collectIntegerSequences/collectIntegerSequences.ts +36 -0
- package/src/utils/Number/numberToFixedPrecision/numberToFixedPrecision.ts +13 -0
- package/src/utils/Object/cloneObject/cloneObject.ts +3 -0
- package/src/utils/Object/deepEqual/deepEqual.ts +45 -0
- package/src/utils/Object/deleteUndefinedProperties/index.ts +13 -0
- package/src/utils/Object/entriesToObject/entriesToObject.ts +12 -0
- package/src/utils/Object/filterObject/filterObject.ts +18 -0
- package/src/utils/Object/forOwn/forOwn.ts +12 -0
- package/src/utils/Object/getObjectEntries/getObjectEntries.ts +3 -0
- package/src/utils/Object/getObjectKeys/getObjectKeys.ts +3 -0
- package/src/utils/Object/getObjectValues/index.ts +3 -0
- package/src/utils/Object/hasOwnProperty/hasOwnProperty.ts +3 -0
- package/src/utils/Object/invertObject/InvertedObject.ts +3 -0
- package/src/utils/Object/invertObject/invertObject.ts +15 -0
- package/src/utils/Object/isEmptyObject/index.ts +5 -0
- package/src/utils/Object/isObject/index.ts +8 -0
- package/src/utils/Object/mapObjectKeys/mapObjectKeys.ts +25 -0
- package/src/utils/Object/mapObjectValues/mapObjectValues.ts +16 -0
- package/src/utils/Object/mirrorObject/ObjectKeysMirror.ts +1 -0
- package/src/utils/Object/mirrorObject/mirrorObject.ts +7 -0
- package/src/utils/Pagination/DEFAULT_PAGE.ts +1 -0
- package/src/utils/Pagination/calculatePaginationParameters.ts +29 -0
- package/src/utils/Promise/promiseAll/promiseAll.ts +6 -0
- package/src/utils/Promise/restrictParallelCalls/restrictParallelCalls.ts +18 -0
- package/src/utils/Ranges/checkRangesAdjacent/checkRangesAdjacent.ts +23 -0
- package/src/utils/Ranges/checkRangesIntersection/checkRangesIntersection.ts +8 -0
- package/src/utils/Ranges/excludeRanges/excludeRanges.ts +42 -0
- package/src/utils/Ranges/getDistanceToRange/getDistanceToRange.ts +14 -0
- package/src/utils/Ranges/isRangeWithinRanges.ts +14 -0
- package/src/utils/Ranges/mapDateRangeToISODateStringRange/mapDateRangeToISODateStringRange.ts +7 -0
- package/src/utils/Ranges/mapISODateStringRangeToUnixTimeMsRange/mapISODateStringRangeToUnixTimeMsRange.ts +8 -0
- package/src/utils/Ranges/mapRange/mapRange.ts +13 -0
- package/src/utils/Ranges/mapUnixTimeMsRangeToISODateStringRange/mapUnixTimeMsRangeToISODateStringRange.ts +8 -0
- package/src/utils/Ranges/mergeRanges/mergeRanges.ts +34 -0
- package/src/utils/Signal/Signal.ts +47 -0
- package/src/utils/Signal/SignalCallback.ts +1 -0
- package/src/utils/Signal/combineSignalsIntoNewOne/combineSignalsIntoNewOne.ts +75 -0
- package/src/utils/Signal/subscribeSignalAndCallWithCurrentValue/subscribeSignalAndCallWithCurrentValue.ts +7 -0
- package/src/utils/Signal/useSignal.ts +10 -0
- package/src/utils/String/HexString/HEX_SYMBOLS.ts +1 -0
- package/src/utils/String/HexString/HexString.ts +2 -0
- package/src/utils/String/HexString/isHexString.ts +16 -0
- package/src/utils/String/NonEmptyString/NonEmptyString.ts +22 -0
- package/src/utils/String/endsWith/index.ts +6 -0
- package/src/utils/String/isString.ts +3 -0
- package/src/utils/binarySearch/binarySearch.ts +20 -0
- package/src/utils/binarySearchClosest/binarySearchClosest.ts +43 -0
- package/src/utils/createIncrementalIntegerGenerator.ts +7 -0
- package/src/utils/createRemoteDataProcessingWindow/createRemoteDataProcessingWindow.ts +157 -0
- package/src/utils/createSimultaneousOperationsHandler/createSimultaneousOperationsHandler.ts +65 -0
- package/src/utils/encryptDecryptString/encryptDecryptString.ts +34 -0
- package/src/utils/getPrimeNumbersWithEratosthenesSieve/getPrimeNumbersWithEratosthenesSieve.ts +21 -0
- package/src/utils/isPromise/isPromise.ts +30 -0
- package/src/utils/makeAsyncFunctionCallsSimultaneous/makeAsyncFunctionCallsSimultaneous.ts +64 -0
- package/src/utils/parallelsLimitPromise/index.ts +28 -0
- package/src/utils/parallelsLimitQueue/parallelsLimitQueue.ts +69 -0
- package/src/utils/prettyStringify/index.ts +3 -0
- package/src/utils/random/fnv1a/fnv1a.ts +87 -0
- package/src/utils/random/generateHashedFloats/generateHashedFloats.ts +28 -0
- package/src/utils/random/getRandomIntegerInARange/getRandomIntegerInARange.ts +3 -0
- package/src/utils/random/getSampleIndexByStringHash/getSampleIndexByStringHash.ts +10 -0
- package/src/utils/random/randomBoolean/randomBoolean.ts +3 -0
- package/src/utils/random/randomHexString/randomHexString.ts +12 -0
- package/src/utils/requestAnimationFrame/requestAnimationFramePromise/requestAnimationFramePromise.ts +7 -0
- package/src/utils/requestAnimationFrame/requestAnimationFrameThrottle/requestAnimationFrameThrottle.ts +6 -0
- package/src/utils/retryFunctionWrapper/retryFunctionWrapper.ts +40 -0
- package/src/utils/runParallelTimescalesProcessing/runParallelTimescalesProcessing.ts +113 -0
- package/src/utils/stringifyError.ts +3 -0
- package/src/utils/timers/promiseTimeout/promiseTimeout.ts +26 -0
- package/src/utils/timers/subscribeSyntheticInterval/subscribeSyntheticInterval.ts +47 -0
- package/src/utils/waitForFunction/waitForFunction.ts +50 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import { IterableWithIndexAccess } from '../../types/IterableWithIndexAccess';
|
|
2
|
+
|
|
3
|
+
function _nextPowerOf2(num: number): number {
|
|
4
|
+
const log2 = Math.log(num) / Math.log(2);
|
|
5
|
+
const nextPow2 = 1 << (log2 + 1);
|
|
6
|
+
|
|
7
|
+
return Math.max(nextPow2, 4);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DEFAULT_CAPACITY = 4;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Stolen from here
|
|
14
|
+
* https://github.com/invertase/denque/blob/539105bb57854e997dd469221cdc52a0ad80e0a2/index.js#L6
|
|
15
|
+
*/
|
|
16
|
+
export class Deque<T> implements IterableWithIndexAccess<T> {
|
|
17
|
+
public readonly _capacity: number | undefined;
|
|
18
|
+
public _head: number;
|
|
19
|
+
public _tail: number;
|
|
20
|
+
public _capacityMask: number;
|
|
21
|
+
public _list: (T | undefined)[];
|
|
22
|
+
|
|
23
|
+
public constructor(array?: T[], options: {
|
|
24
|
+
/**
|
|
25
|
+
* The capacity (maximum amount of elements) of the deque
|
|
26
|
+
*/
|
|
27
|
+
capacity?: number;
|
|
28
|
+
} = {}) {
|
|
29
|
+
this._capacity = options.capacity;
|
|
30
|
+
|
|
31
|
+
this._head = 0;
|
|
32
|
+
this._tail = 0;
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(array)) {
|
|
35
|
+
const { length } = array;
|
|
36
|
+
const capacity = _nextPowerOf2(length);
|
|
37
|
+
|
|
38
|
+
this._list = new Array(capacity);
|
|
39
|
+
this._capacityMask = capacity - 1;
|
|
40
|
+
this._tail = length;
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < length; i++) {
|
|
43
|
+
this._list[i] = array[i];
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
this._list = new Array(DEFAULT_CAPACITY);
|
|
47
|
+
this._capacityMask = DEFAULT_CAPACITY - 1;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public get length(): number {
|
|
52
|
+
if (this._head === this._tail) {
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (this._head < this._tail) {
|
|
57
|
+
return this._tail - this._head;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return this._capacityMask + 1 - (this._head - this._tail);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public *[Symbol.iterator](): Iterator<T> {
|
|
64
|
+
const { length } = this;
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < length; i++) {
|
|
67
|
+
const item = this.at(i);
|
|
68
|
+
|
|
69
|
+
if (item !== undefined) {
|
|
70
|
+
yield item;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns the item at the specified index from the list.
|
|
77
|
+
* 0 is the first element, 1 is the second, and so on...
|
|
78
|
+
* Elements at negative values are that many from the end: -1 is one before the end
|
|
79
|
+
* (the last element), -2 is two before the end (one before last), etc.
|
|
80
|
+
*/
|
|
81
|
+
public at(index: number): T | undefined {
|
|
82
|
+
let i = index;
|
|
83
|
+
|
|
84
|
+
if ((i !== (i | 0))) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const len = this.length;
|
|
89
|
+
|
|
90
|
+
if (i >= len || i < -len) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (i < 0) {
|
|
95
|
+
i += len;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
i = (this._head + i) & this._capacityMask;
|
|
99
|
+
|
|
100
|
+
return this._list[i];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public peek(): T | undefined {
|
|
104
|
+
if (this._head === this._tail) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return this._list[this._head];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public peekBack(): T | undefined {
|
|
112
|
+
return this.at(-1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Add an item at the beginning of the list
|
|
117
|
+
* Returns new length of the list
|
|
118
|
+
*/
|
|
119
|
+
public unshift(item?: T): number {
|
|
120
|
+
if (arguments.length === 0) {
|
|
121
|
+
return this.length;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const len = this._list.length;
|
|
125
|
+
|
|
126
|
+
this._head = (this._head - 1 + len) & this._capacityMask;
|
|
127
|
+
this._list[this._head] = item;
|
|
128
|
+
|
|
129
|
+
if (this._tail === this._head) {
|
|
130
|
+
this._growArray();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (this._capacity && this.length > this._capacity) {
|
|
134
|
+
this.pop();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this._head < this._tail) {
|
|
138
|
+
return this._tail - this._head;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return this._capacityMask + 1 - (this._head - this._tail);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public pop(): T | undefined {
|
|
145
|
+
const tail = this._tail;
|
|
146
|
+
|
|
147
|
+
if (tail === this._head) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const len = this._list.length;
|
|
152
|
+
|
|
153
|
+
this._tail = (tail - 1 + len) & this._capacityMask;
|
|
154
|
+
const item = this._list[this._tail];
|
|
155
|
+
|
|
156
|
+
this._list[this._tail] = undefined;
|
|
157
|
+
if (this._head < 2 && tail > 10000 && tail <= len >>> 2) {
|
|
158
|
+
this._shrinkArray();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return item;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public shift() {
|
|
165
|
+
const head = this._head;
|
|
166
|
+
|
|
167
|
+
if (head === this._tail) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const item = this._list[head];
|
|
172
|
+
|
|
173
|
+
this._list[head] = undefined;
|
|
174
|
+
this._head = (head + 1) & this._capacityMask;
|
|
175
|
+
if (head < 2 && this._tail > 10000 && this._tail <= this._list.length >>> 2) {
|
|
176
|
+
this._shrinkArray();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return item;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Add an item to the end of the list
|
|
184
|
+
* Returns new length of the list
|
|
185
|
+
*/
|
|
186
|
+
public push(...items: T[]): number {
|
|
187
|
+
if (arguments.length === 0) {
|
|
188
|
+
return this.length;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const tail = this._tail;
|
|
192
|
+
|
|
193
|
+
this._list[tail] = items[0];
|
|
194
|
+
this._tail = (tail + 1) & this._capacityMask;
|
|
195
|
+
|
|
196
|
+
if (this._tail === this._head) {
|
|
197
|
+
this._growArray();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (this._capacity && this.length > this._capacity) {
|
|
201
|
+
this.shift();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (this._head < this._tail) {
|
|
205
|
+
return this._tail - this._head;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return this._capacityMask + 1 - (this._head - this._tail);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public removeOne(index: number): T | undefined {
|
|
212
|
+
let i = index;
|
|
213
|
+
|
|
214
|
+
// expect a number or return undefined
|
|
215
|
+
if ((i !== (i | 0))) {
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (this._head === this._tail) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const { length } = this;
|
|
224
|
+
const len = this._list.length;
|
|
225
|
+
|
|
226
|
+
if (i >= length || i < -length) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (i < 0) {
|
|
231
|
+
i += length;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
i = (this._head + i) & this._capacityMask;
|
|
235
|
+
const item = this._list[i];
|
|
236
|
+
let k;
|
|
237
|
+
|
|
238
|
+
if (index < length / 2) {
|
|
239
|
+
for (k = index; k > 0; k--) {
|
|
240
|
+
this._list[i] = this._list[i = (i - 1 + len) & this._capacityMask];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
this._list[i] = undefined;
|
|
244
|
+
this._head = (this._head + 1 + len) & this._capacityMask;
|
|
245
|
+
} else {
|
|
246
|
+
for (k = length - 1 - index; k > 0; k--) {
|
|
247
|
+
this._list[i] = this._list[i = (i + 1 + len) & this._capacityMask];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
this._list[i] = undefined;
|
|
251
|
+
this._tail = (this._tail - 1 + len) & this._capacityMask;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return item;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
public isEmpty(): boolean {
|
|
258
|
+
return this._head === this._tail;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
public clear(): void {
|
|
262
|
+
this._list = new Array(this._list.length);
|
|
263
|
+
this._head = 0;
|
|
264
|
+
this._tail = 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
public remove(index: number, count: number): T[] | undefined {
|
|
268
|
+
let i = index;
|
|
269
|
+
let removed;
|
|
270
|
+
let del_count = count;
|
|
271
|
+
|
|
272
|
+
// expect a number or return undefined
|
|
273
|
+
if ((i !== (i | 0))) {
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (this._head === this._tail) {
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const { length } = this;
|
|
282
|
+
const len = this._list.length;
|
|
283
|
+
|
|
284
|
+
if (i >= length || i < -length || count < 1) {
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (i < 0) {
|
|
289
|
+
i += length;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (count === 1 || !count) {
|
|
293
|
+
removed = new Array(1);
|
|
294
|
+
removed[0] = this.removeOne(i);
|
|
295
|
+
|
|
296
|
+
return removed;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (i === 0 && i + count >= length) {
|
|
300
|
+
removed = this.toArray();
|
|
301
|
+
this.clear();
|
|
302
|
+
|
|
303
|
+
return removed;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (i + count > length) {
|
|
307
|
+
count = length - i;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
let k;
|
|
311
|
+
|
|
312
|
+
removed = new Array(count);
|
|
313
|
+
for (k = 0; k < count; k++) {
|
|
314
|
+
removed[k] = this._list[(this._head + i + k) & this._capacityMask];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
i = (this._head + i) & this._capacityMask;
|
|
318
|
+
if (index + count === length) {
|
|
319
|
+
this._tail = (this._tail - count + len) & this._capacityMask;
|
|
320
|
+
for (k = count; k > 0; k--) {
|
|
321
|
+
this._list[i = (i + 1 + len) & this._capacityMask] = undefined;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return removed;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (index === 0) {
|
|
328
|
+
this._head = (this._head + count + len) & this._capacityMask;
|
|
329
|
+
for (k = count - 1; k > 0; k--) {
|
|
330
|
+
this._list[i = (i + 1 + len) & this._capacityMask] = undefined;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return removed;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (i < length / 2) {
|
|
337
|
+
this._head = (this._head + index + count + len) & this._capacityMask;
|
|
338
|
+
for (k = index; k > 0; k--) {
|
|
339
|
+
this.unshift(this._list[i = (i - 1 + len) & this._capacityMask]!);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
i = (this._head - 1 + len) & this._capacityMask;
|
|
343
|
+
while (del_count > 0) {
|
|
344
|
+
this._list[i = (i - 1 + len) & this._capacityMask] = undefined;
|
|
345
|
+
del_count--;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (index < 0) {
|
|
349
|
+
this._tail = i;
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
this._tail = i;
|
|
353
|
+
i = (i + count + len) & this._capacityMask;
|
|
354
|
+
for (k = length - (count + index); k > 0; k--) {
|
|
355
|
+
this.push(this._list[i++]!);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
i = this._tail;
|
|
359
|
+
while (del_count > 0) {
|
|
360
|
+
this._list[i = (i + 1 + len) & this._capacityMask] = undefined;
|
|
361
|
+
del_count--;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (this._head < 2 && this._tail > 10000 && this._tail <= len >>> 2) {
|
|
366
|
+
this._shrinkArray();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return removed;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
public toArray() {
|
|
373
|
+
return this._copyArray(false);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
|
|
378
|
+
*/
|
|
379
|
+
public splice(
|
|
380
|
+
/**
|
|
381
|
+
* The zero-based location in the array from which to start removing elements.
|
|
382
|
+
*/
|
|
383
|
+
start: number,
|
|
384
|
+
/**
|
|
385
|
+
* The number of elements to remove.
|
|
386
|
+
*/
|
|
387
|
+
deleteCount: number,
|
|
388
|
+
/**
|
|
389
|
+
* Elements to insert into the array in place of the deleted elements.
|
|
390
|
+
*/
|
|
391
|
+
...items: T[]
|
|
392
|
+
): T[] | undefined {
|
|
393
|
+
let i = start;
|
|
394
|
+
|
|
395
|
+
// expect a number or return undefined
|
|
396
|
+
if ((i !== (i | 0))) {
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const { length } = this;
|
|
401
|
+
|
|
402
|
+
if (i < 0) {
|
|
403
|
+
i += length;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (i > length) {
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
let itemsLength = items.length;
|
|
411
|
+
|
|
412
|
+
if (itemsLength > 0) {
|
|
413
|
+
let k;
|
|
414
|
+
let temp;
|
|
415
|
+
let removed;
|
|
416
|
+
const len = this._list.length;
|
|
417
|
+
let itemIndex = 0;
|
|
418
|
+
|
|
419
|
+
if (!length || i < length / 2) {
|
|
420
|
+
temp = new Array(i);
|
|
421
|
+
for (k = 0; k < i; k++) {
|
|
422
|
+
temp[k] = this._list[(this._head + k) & this._capacityMask];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (deleteCount === 0) {
|
|
426
|
+
removed = [];
|
|
427
|
+
if (i > 0) {
|
|
428
|
+
this._head = (this._head + i + len) & this._capacityMask;
|
|
429
|
+
}
|
|
430
|
+
} else {
|
|
431
|
+
removed = this.remove(i, deleteCount);
|
|
432
|
+
this._head = (this._head + i + len) & this._capacityMask;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
while (itemsLength > itemIndex) {
|
|
436
|
+
this.unshift(items[--itemsLength]);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
for (k = i; k > 0; k--) {
|
|
440
|
+
this.unshift(temp[k - 1]);
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
temp = new Array(length - (i + deleteCount));
|
|
444
|
+
const leng = temp.length;
|
|
445
|
+
|
|
446
|
+
for (k = 0; k < leng; k++) {
|
|
447
|
+
temp[k] = this._list[(this._head + i + deleteCount + k) & this._capacityMask];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (deleteCount === 0) {
|
|
451
|
+
removed = [];
|
|
452
|
+
if (i !== length) {
|
|
453
|
+
this._tail = (this._head + i + len) & this._capacityMask;
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
removed = this.remove(i, deleteCount);
|
|
457
|
+
this._tail = (this._tail - leng + len) & this._capacityMask;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
while (itemIndex < itemsLength) {
|
|
461
|
+
this.push(items[itemIndex++]);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
for (k = 0; k < leng; k++) {
|
|
465
|
+
this.push(temp[k]);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
return removed;
|
|
470
|
+
} else {
|
|
471
|
+
return this.remove(i, deleteCount);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
private _growArray() {
|
|
476
|
+
if (this._head !== 0) {
|
|
477
|
+
// double array size and copy existing data, head to end, then beginning to tail.
|
|
478
|
+
const newList = this._copyArray(true, this._list.length << 1);
|
|
479
|
+
|
|
480
|
+
this._tail = this._list.length;
|
|
481
|
+
this._head = 0;
|
|
482
|
+
|
|
483
|
+
this._list = newList;
|
|
484
|
+
} else {
|
|
485
|
+
this._tail = this._list.length;
|
|
486
|
+
this._list.length <<= 1;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
this._capacityMask = (this._capacityMask << 1) | 1;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
private _copyArray(fullCopy: boolean, sizeToCopy?: number) {
|
|
493
|
+
const src = this._list;
|
|
494
|
+
const capacity = src.length;
|
|
495
|
+
const { length } = this;
|
|
496
|
+
const size = (sizeToCopy ?? 0) | length;
|
|
497
|
+
|
|
498
|
+
// No prealloc requested and the buffer is contiguous
|
|
499
|
+
if (size === length && this._head < this._tail) {
|
|
500
|
+
// Simply do a fast slice copy
|
|
501
|
+
return this._list.slice(this._head, this._tail);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const dest = new Array(size);
|
|
505
|
+
|
|
506
|
+
let k = 0;
|
|
507
|
+
let i;
|
|
508
|
+
|
|
509
|
+
if (fullCopy || this._head > this._tail) {
|
|
510
|
+
for (i = this._head; i < capacity; i++) {
|
|
511
|
+
dest[k++] = src[i];
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
for (i = 0; i < this._tail; i++) {
|
|
515
|
+
dest[k++] = src[i];
|
|
516
|
+
}
|
|
517
|
+
} else {
|
|
518
|
+
for (i = this._head; i < this._tail; i++) {
|
|
519
|
+
dest[k++] = src[i];
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
return dest;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
private _shrinkArray(): void {
|
|
527
|
+
this._list.length >>>= 1;
|
|
528
|
+
this._capacityMask >>>= 1;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { GlobalContext } from '../../../types/GlobalContext';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The check returns true for devices
|
|
5
|
+
* where the PRIMARY mechanism of interaction with the user is a touchscreen
|
|
6
|
+
*
|
|
7
|
+
* This is the easiest way, primitive, but effective way to separate mobile and desktop devices
|
|
8
|
+
*
|
|
9
|
+
* For example, on a laptop with a touchscreen, this utility should return false
|
|
10
|
+
* (since there is a touchscreen, but it's not the primary way of interaction,
|
|
11
|
+
* the user most likely uses a touchpad),
|
|
12
|
+
* while on a tablet with a keyboard - true
|
|
13
|
+
*/
|
|
14
|
+
export function isTouchScreenDevice(win: Pick<GlobalContext, 'ontouchstart'>): boolean {
|
|
15
|
+
return 'ontouchstart' in win;
|
|
16
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { isObject } from '../../types/Object/Object';
|
|
2
|
+
import { isFunction } from '../Function/isFunction';
|
|
3
|
+
import { isString } from '../String/isString';
|
|
4
|
+
|
|
5
|
+
export function wrapError(error: unknown, {
|
|
6
|
+
messageModifier,
|
|
7
|
+
}: Partial<{
|
|
8
|
+
messageModifier: (oldMessage: string) => string;
|
|
9
|
+
}> = {}): Error {
|
|
10
|
+
let resultError: Error;
|
|
11
|
+
|
|
12
|
+
if (error instanceof Error) {
|
|
13
|
+
resultError = error;
|
|
14
|
+
} else {
|
|
15
|
+
resultError = new Error('DEFAULT_ERROR_MESSAGE');
|
|
16
|
+
if (isObject(error)) {
|
|
17
|
+
if (isString(error.message)) {
|
|
18
|
+
resultError.message = error.message;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (isString(error.stack)) {
|
|
22
|
+
resultError.stack = error.stack;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isFunction(messageModifier)) {
|
|
28
|
+
resultError.message = messageModifier(resultError.message);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return resultError;
|
|
32
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrapper for a function that will be called first time with first function, and then with other function
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export function callFirstThenOther<T extends (
|
|
6
|
+
this: unknown, ...args: unknown[]) => unknown>(
|
|
7
|
+
this: unknown,
|
|
8
|
+
first: T,
|
|
9
|
+
other: T
|
|
10
|
+
): T {
|
|
11
|
+
let called = false;
|
|
12
|
+
|
|
13
|
+
const wrapper = function (this: unknown, ...args: unknown[]) {
|
|
14
|
+
const fn = called ? other : first;
|
|
15
|
+
|
|
16
|
+
called = true;
|
|
17
|
+
|
|
18
|
+
return fn.apply(this, args);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return function (this: unknown, ...args: unknown[]) {
|
|
22
|
+
return wrapper.apply(this, args);
|
|
23
|
+
} as T;
|
|
24
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrapper for a function that will be called no more than once
|
|
3
|
+
*
|
|
4
|
+
* Call context is preserved
|
|
5
|
+
*
|
|
6
|
+
* Subsequent calls return the result of the first call
|
|
7
|
+
*
|
|
8
|
+
* Subsequent recursive calls will not be executed either
|
|
9
|
+
*/
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
export function once<T extends (this: any, ...args: any[]) => any>(this: any, fn: T): T {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
let onceFn = function (this: any) {
|
|
14
|
+
// Create variable in advance to avoid errors when accessing non-existent constant during call
|
|
15
|
+
// eslint-disable-next-line prefer-const, @typescript-eslint/no-explicit-any
|
|
16
|
+
let result: any;
|
|
17
|
+
|
|
18
|
+
// Overwrite function in advance to avoid recursive call inside once
|
|
19
|
+
onceFn = () => result;
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, prefer-rest-params
|
|
22
|
+
result = fn.apply(this, arguments as any);
|
|
23
|
+
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
return function (this: any) {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, prefer-rest-params
|
|
30
|
+
return onceFn.apply(this, arguments as any);
|
|
31
|
+
} as T;
|
|
32
|
+
}
|