@the-w1zard/dx 1.0.11 → 1.0.13

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.
@@ -0,0 +1,223 @@
1
+ export class SET2BI {
2
+ readonly cap: N;
3
+ readonly flags: Uint8Array; // [pid] -> 0/1, O(1) has()
4
+ readonly slots: I32; // [idx] -> pid, dense, for iteration
5
+ readonly pidToIdx: I32; // [pid] -> idx into slots, -1 = absent
6
+
7
+ #size = 0;
8
+
9
+ constructor(maxParticles: N = 8192, seed?: Iterable<N>) {
10
+ this.cap = maxParticles;
11
+ this.flags = new Uint8Array(maxParticles);
12
+ this.slots = new Int32Array(maxParticles).fill(-1);
13
+ this.pidToIdx = new Int32Array(maxParticles).fill(-1);
14
+ if (seed) for (const pid of seed) this.add(pid);
15
+ }
16
+
17
+ get size(): N { return this.#size; }
18
+
19
+ // ---------------------------------------------------------------- core
20
+ public s = this.add.bind(this); // [s alias]
21
+ public add(pid: N): this { // [ADD]
22
+ if (this.flags[pid] === 0) {
23
+ this.flags[pid] = 1;
24
+ const idx = this.#size;
25
+ this.slots[idx] = pid;
26
+ this.pidToIdx[pid] = idx;
27
+ this.#size++;
28
+ }
29
+ return this;
30
+ }
31
+ public has(pid: N): B { return this.flags[pid] === 1; } // [HAS]
32
+ public delete(pid: N): B { // [DELETE]
33
+ if (this.flags[pid] !== 1) return false;
34
+ this.flags[pid] = 0;
35
+ const idx = this.pidToIdx[pid];
36
+ const lastIdx = this.#size - 1;
37
+ const lastPid = this.slots[lastIdx];
38
+ if (idx !== lastIdx) {
39
+ this.slots[idx] = lastPid;
40
+ this.pidToIdx[lastPid] = idx;
41
+ }
42
+ this.slots[lastIdx] = -1;
43
+ this.pidToIdx[pid] = -1;
44
+ this.#size--;
45
+ return true;
46
+ }
47
+ public clear(): V { // [CLEAR]
48
+ for (let i = 0; i < this.#size; i++) this.flags[this.slots[i]] = 0;
49
+ this.slots.fill(-1, 0, this.#size);
50
+ this.pidToIdx.fill(-1); // cheap enough; or loop same range if cap is huge
51
+ this.#size = 0;
52
+ }
53
+
54
+ // ---------------------------------------------------------------- iteration
55
+ public *[Symbol.iterator](): Generator<N> { for (let i = 0; i < this.#size; i++) yield this.slots[i]; }
56
+ public values(): Generator<N> { return this[Symbol.iterator](); }
57
+ public keys(): Generator<N> { return this[Symbol.iterator](); }
58
+ public *entries(): Generator<[N, N]> { for (let i = 0; i < this.#size; i++) yield [this.slots[i], this.slots[i]]; }
59
+
60
+ // ---------------------------------------------------------------- sugar
61
+ public take(pid: N): N | UD { return this.delete(pid) ? pid : undefined; } // [TAKE]
62
+ public peek(pid: N): N | false { return this.has(pid) ? pid : false; } // [PEEK]
63
+ public toggle(pid: N): B { // [TOGGLE]
64
+ if (this.has(pid)) { this.delete(pid); return false; }
65
+ this.add(pid);
66
+ return true;
67
+ }
68
+ public first(): N | UD { return this.#size === 0 ? undefined : this.slots[0]; } // [FIRST]
69
+ public last(): N | UD { return this.#size === 0 ? undefined : this.slots[this.#size - 1]; } // [LAST]
70
+
71
+ // ---------------------------------------------------------------- set algebra (-> new SET2BI, same cap)
72
+ public union(other: Iterable<N>): SET2BI { // [UNION]
73
+ const out = new SET2BI(this.cap, this);
74
+ for (const pid of other) out.add(pid);
75
+ return out;
76
+ }
77
+ public intersection(other: Iterable<N>): SET2BI { // [INTERSECTION]
78
+ const probe = new SET2BI(this.cap, other);
79
+ const out = new SET2BI(this.cap);
80
+ for (const pid of this) if (probe.has(pid)) out.add(pid);
81
+ return out;
82
+ }
83
+ public difference(other: Iterable<N>): SET2BI { // [DIFFERENCE]
84
+ const probe = new SET2BI(this.cap, other);
85
+ const out = new SET2BI(this.cap);
86
+ for (const pid of this) if (!probe.has(pid)) out.add(pid);
87
+ return out;
88
+ }
89
+ public symmetricDifference(other: Iterable<N>): SET2BI { // [SYMMETRICDIFFERENCE]
90
+ const probe = new SET2BI(this.cap, other);
91
+ const out = new SET2BI(this.cap);
92
+ for (const pid of this) if (!probe.has(pid)) out.add(pid);
93
+ for (const pid of probe) if (!this.has(pid)) out.add(pid);
94
+ return out;
95
+ }
96
+ public isSubsetOf(other: Iterable<N>): B { // [ISSUBSETOF]
97
+ const probe = new SET2BI(this.cap, other);
98
+ for (const pid of this) if (!probe.has(pid)) return false;
99
+ return true;
100
+ }
101
+ public isSupersetOf(other: Iterable<N>): B { // [ISSUPERSETOF]
102
+ for (const pid of other) if (!this.has(pid)) return false;
103
+ return true;
104
+ }
105
+ public isDisjointFrom(other: Iterable<N>): B { // [ISDISJOINT]
106
+ for (const pid of other) if (this.has(pid)) return false;
107
+ return true;
108
+ }
109
+ public equals(other: Iterable<N>): B { // [EQUALS]
110
+ const probe = new SET2BI(this.cap, other);
111
+ return this.#size === probe.size && this.isSubsetOf(probe);
112
+ }
113
+
114
+ // ---------------------------------------------------------------- functional
115
+ public filter(fn: (pid: N, set: this) => B): SET2BI { // [FILTER]
116
+ const out = new SET2BI(this.cap);
117
+ for (const pid of this) if (fn(pid, this)) out.add(pid);
118
+ return out;
119
+ }
120
+ public map(fn: (pid: N, set: this) => N): SET2BI { // [MAP]
121
+ const out = new SET2BI(this.cap); // fn must still yield in-range pids
122
+ for (const pid of this) out.add(fn(pid, this));
123
+ return out;
124
+ }
125
+ public partition(fn: (pid: N, set: this) => B): [SET2BI, SET2BI] { // [PARTITION]
126
+ const yes = new SET2BI(this.cap), no = new SET2BI(this.cap);
127
+ for (const pid of this) (fn(pid, this) ? yes : no).add(pid);
128
+ return [yes, no];
129
+ }
130
+ public differenceBy<G>(other: Iterable<N>, fn: (pid: N) => G): SET2BI { // [DIFFERENCEBY]
131
+ const keys = new Set<G>();
132
+ for (const pid of other) keys.add(fn(pid));
133
+ const out = new SET2BI(this.cap);
134
+ for (const pid of this) if (!keys.has(fn(pid))) out.add(pid);
135
+ return out;
136
+ }
137
+ public uniqueBy<G>(fn: (pid: N) => G): SET2BI { // [UNIQUEBY]
138
+ const keys = new Set<G>();
139
+ const out = new SET2BI(this.cap);
140
+ for (const pid of this) {
141
+ const key = fn(pid);
142
+ if (keys.has(key)) continue;
143
+ keys.add(key);
144
+ out.add(pid);
145
+ }
146
+ return out;
147
+ }
148
+ public find(fn: (pid: N, set: this) => B): N | UD { // [FIND]
149
+ for (const pid of this) if (fn(pid, this)) return pid;
150
+ return undefined;
151
+ }
152
+ public every(fn: (pid: N, set: this) => B): B { // [EVERY]
153
+ for (const pid of this) if (!fn(pid, this)) return false;
154
+ return true;
155
+ }
156
+ public some(fn: (pid: N, set: this) => B): B { // [SOME]
157
+ for (const pid of this) if (fn(pid, this)) return true;
158
+ return false;
159
+ }
160
+ public reduce<G>(fn: (acc: G, pid: N, set: this) => G, initial: G): G { // [REDUCE]
161
+ let result = initial;
162
+ for (const pid of this) result = fn(result, pid, this);
163
+ return result;
164
+ }
165
+
166
+ // ---------------------------------------------------------------- bulk mutation
167
+ public addAll(pids: Iterable<N>): this { for (const pid of pids) this.add(pid); return this; } // [ADDALL]
168
+ public deleteAll(pids: Iterable<N>): N { // [DELETEALL]
169
+ let count = 0;
170
+ for (const pid of pids) if (this.delete(pid)) count++;
171
+ return count;
172
+ }
173
+ public retainAll(pids: Iterable<N>): this { // [RETAINALL]
174
+ const keep = new SET2BI(this.cap, pids);
175
+ for (const pid of [...this]) if (!keep.has(pid)) this.delete(pid);
176
+ return this;
177
+ }
178
+ public update(pids: Iterable<N>): this { return this.addAll(pids); } // [UPDATE]
179
+ public replace(pids: Iterable<N>): this { // [REPLACE]
180
+ this.clear();
181
+ for (const pid of pids) this.add(pid);
182
+ return this;
183
+ }
184
+ public swap(a: N, b: N): B { // [SWAP]
185
+ if (!this.has(a)) return false;
186
+ this.delete(a);
187
+ this.add(b);
188
+ return true;
189
+ }
190
+
191
+ // ---------------------------------------------------------------- export
192
+ public clone(): SET2BI { return new SET2BI(this.cap, this); } // [CLONE]
193
+ public toArray(): AR<N> { return [...this]; } // [TOARRAY]
194
+ public toMap<K, T>(fn: (pid: N) => [K, T]): Map<K, T> { // [TOMAP]
195
+ const out = new Map<K, T>();
196
+ for (const pid of this) { const [key, result] = fn(pid); out.set(key, result); }
197
+ return out;
198
+ }
199
+ public toObject(fn?: (pid: N) => S): OB<N> { // [TOOBJECT]
200
+ const out = {} as OB<N>;
201
+ for (const pid of this) out[fn ? fn(pid) : String(pid)] = pid;
202
+ return out;
203
+ }
204
+ public toJSON(): AR<N> { return this.toArray(); } // [TOJSON]
205
+
206
+ static fromArray(pids: AR<N>, maxParticles?: N): SET2BI { // [FROMARRAY]
207
+ return new SET2BI(maxParticles ?? Math.max(...pids, 0) + 1, pids);
208
+ }
209
+ static fromObject(obj: Record<S, N>, maxParticles?: N): SET2BI { // [FROMOBJECT]
210
+ return SET2BI.fromArray(Object.values(obj), maxParticles);
211
+ }
212
+ static fromEntries(entries: I<readonly [A, N]>, maxParticles?: N): SET2BI { // [FROMENTIRES]
213
+ const pids: AR<N> = [];
214
+ for (const [, pid] of entries) pids.push(pid);
215
+ return SET2BI.fromArray(pids, maxParticles);
216
+ }
217
+ static from(pids: Iterable<N>, maxParticles?: N): SET2BI { // [FROM]
218
+ return new SET2BI(maxParticles ?? 8192, pids);
219
+ }
220
+ }
221
+
222
+ globalThis.SET2B = SET2BI;
223
+
@@ -0,0 +1,27 @@
1
+ export class SOA_CODEC {// HIGH_PERFORMANCE_SOA_CODEC
2
+ public readonly maxPids: number;
3
+ // SoA Memory Layout (Typed Arrays for Cache Locality)
4
+ public readonly channelMap: Int32Array;
5
+ public readonly subChannelMap: Int32Array;
6
+ public readonly tripChannelMap: Int32Array;
7
+ public readonly keyMap: Int32Array;
8
+ public readonly listeners: Array<((pid: number, val?: number) => void) | undefined>;
9
+ public nextPid = 1;
10
+ constructor( maxPids = 8192) {
11
+ this.maxPids = maxPids;
12
+ this.channelMap = new Int32Array(maxPids);
13
+ this.subChannelMap = new Int32Array(maxPids);
14
+ this.tripChannelMap = new Int32Array(maxPids);
15
+ this.keyMap = new Int32Array(maxPids);
16
+ this.listeners = new Array(maxPids);
17
+ }// Hot path lookup or allocation: O(1) inline integer assignment
18
+ public allocatePid(rId: number, mId: number, sId: number, kId: number): number {
19
+ const pid = this.nextPid++;
20
+ if (pid >= this.maxPids) throw new Error("PID capacity exceeded");
21
+ this.channelMap[pid] = rId;
22
+ this.subChannelMap[pid] = mId;
23
+ this.tripChannelMap[pid] = sId;
24
+ this.keyMap[pid] = kId;
25
+ return pid;
26
+ }
27
+ }
package/src/string.ts ADDED
@@ -0,0 +1,175 @@
1
+
2
+
3
+ export class S2I extends String implements S2 {
4
+ constructor(value: A = "") {
5
+ super(value);
6
+ }
7
+
8
+ empty(): boolean {
9
+ return this.length === 0;
10
+ }
11
+
12
+ notEmpty(): boolean {
13
+ return this.length > 0;
14
+ }
15
+
16
+ blank(): boolean {
17
+ return this.trim().length === 0;
18
+ }
19
+
20
+ notBlank(): boolean {
21
+ return !this.blank();
22
+ }
23
+
24
+ equals(value: string): boolean {
25
+ return this.toString() === value;
26
+ }
27
+
28
+ equalsIgnoreCase(value: string): boolean {
29
+ return this.toLowerCase() === value.toLowerCase();
30
+ }
31
+
32
+ contains(value: string): boolean {
33
+ return this.includes(value);
34
+ }
35
+
36
+ starts(value: string): boolean {
37
+ return this.startsWith(value);
38
+ }
39
+
40
+ ends(value: string): boolean {
41
+ return this.endsWith(value);
42
+ }
43
+
44
+ first(): string {
45
+ return this.charAt(0);
46
+ }
47
+
48
+ last(): string {
49
+ return this.charAt(this.length - 1);
50
+ }
51
+
52
+ reverse(): string {
53
+ return Array.from(this.toString()).reverse().join("");
54
+ }
55
+
56
+ capitalize(): string {
57
+ return this.length ? this.charAt(0).toUpperCase() + this.slice(1) : "";
58
+ }
59
+
60
+ uncapitalize(): string {
61
+ return this.length ? this.charAt(0).toLowerCase() + this.slice(1) : "";
62
+ }
63
+
64
+ titleCase(): string {
65
+ return this.toLowerCase().replace(/\b\w/g, char => char.toUpperCase());
66
+ }
67
+
68
+ camelCase(): string {
69
+ return this.toString()
70
+ .replace(/([a-z\d])([A-Z])/g, "$1 $2")
71
+ .split(/[^a-zA-Z\d]+/)
72
+ .filter(Boolean)
73
+ .map((word, index) =>
74
+ index === 0
75
+ ? word.toLowerCase()
76
+ : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),
77
+ )
78
+ .join("");
79
+ }
80
+
81
+ kebabCase(): string {
82
+ return this.toString()
83
+ .replace(/([a-z\d])([A-Z])/g, "$1-$2")
84
+ .replace(/[^a-zA-Z\d]+/g, "-")
85
+ .replace(/^-+|-+$/g, "")
86
+ .toLowerCase();
87
+ }
88
+
89
+ snakeCase(): string {
90
+ return this.kebabCase().replace(/-/g, "_");
91
+ }
92
+
93
+ pascalCase(): string {
94
+ return this.toString()
95
+ .replace(/([a-z\d])([A-Z])/g, "$1 $2")
96
+ .split(/[^a-zA-Z\d]+/)
97
+ .filter(Boolean)
98
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
99
+ .join("");
100
+ }
101
+
102
+ words(): string[] {
103
+ return this.toString().match(/[\p{L}\p{N}]+/gu) ?? [];
104
+ }
105
+
106
+ lines(): string[] {
107
+ return this.split(/\r\n|\r|\n/);
108
+ }
109
+
110
+ chars(): string[] {
111
+ return Array.from(this.toString());
112
+ }
113
+
114
+ unique(): string {
115
+ return Array.from(new Set(this.chars())).join("");
116
+ }
117
+
118
+ escapeRegExp(): string {
119
+ return this.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
120
+ }
121
+
122
+ stripHtml(): string {
123
+ return this.replace(/<[^>]*>/g, "");
124
+ }
125
+
126
+ stripWhitespace(): string {
127
+ return this.replace(/\s+/g, "");
128
+ }
129
+
130
+ truncate(length: N, suffix = "..."): string {
131
+ if (this.length <= length) return this.toString();
132
+ return this.slice(0, Math.max(0, length - suffix.length)) + suffix;
133
+ }
134
+
135
+ limit(length: N, suffix = "..."): string {
136
+ return this.truncate(length, suffix);
137
+ }
138
+
139
+ toNumber(): number {
140
+ return Number(this.toString());
141
+ }
142
+
143
+ toInt(radix?: N): number {
144
+ return Number.parseInt(this.toString(), radix);
145
+ }
146
+
147
+ toFloat(): number {
148
+ return Number.parseFloat(this.toString());
149
+ }
150
+
151
+ toBoolean(): boolean {
152
+ const value = this.trim().toLowerCase();
153
+ return value === "true" || value === "1" || value === "yes" || value === "on";
154
+ }
155
+
156
+ toArray(): string[] {
157
+ return this.chars();
158
+ }
159
+
160
+ toJSON(): string {
161
+ return JSON.stringify(this.toString());
162
+ }
163
+ isWellFormed(): boolean {
164
+ return !/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u.test(this.toString());
165
+ }
166
+
167
+ toWellFormed(): string {
168
+ return this.toString().replace(
169
+ /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/gu,
170
+ "\uFFFD",
171
+ );
172
+ }
173
+ }
174
+
175
+ globalThis.S2 = S2I ;