Skip to content

Commit

Permalink
✨ Add WeakValueSetMap class
Browse files Browse the repository at this point in the history
  • Loading branch information
skerit committed Jan 29, 2024
1 parent 1f5fa14 commit 187267d
Show file tree
Hide file tree
Showing 4 changed files with 429 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Add `Function.postInherit(task)`, which will execute the task after the class has been inherited
* Add `Blast.parseClassPath(path)` method
* Add `WeakValueSet` class
* Add `WeakValueSetMap` class

## 0.8.18 (2024-01-19)

Expand Down
1 change: 1 addition & 0 deletions lib/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ function BlastInit(modifyPrototype) {
'BackedMap',
'WeakValueMap',
'WeakValueSet',
'WeakValueSetMap',
];

Blast.modifyPrototype = modifyPrototype;
Expand Down
229 changes: 229 additions & 0 deletions lib/weakvaluesetmap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
const DATA = Symbol('data');

/**
* The WeakValueSetMap Class
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
const WeakValueSetMap = Fn.inherits(null, function WeakValueSetMap(entries) {

// The actual data
this[DATA] = new Map();

if (entries) {
for (const [key, set] of entries) {
for (const val of set) {
this.add(key, val);
}
}
}
});

/**
* Get the current size of the map:
* All the non-empty sets that still have references
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setProperty(function size() {

let to_remove,
count = 0;

for (const [key, set] of this[DATA]) {

if (!set.size) {
if (!to_remove) {
to_remove = [];
}

to_remove.push(key);
continue;
}

count++;
}

if (to_remove) {
let key;

for (key of to_remove) {
this[DATA].delete(key);
}
}

return count;
});

/**
* Remove all the values from the map
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod(function clear() {
this[DATA].clear();
});

/**
* Delete an entry from the map by its key
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod('delete', function _delete(key, value) {

if (arguments.length == 1) {
return this[DATA].delete(key);
}

let set = this.get(key);

if (!set) {
return false;
}

let result = set.delete(value);

if (set.size == 0) {
this[DATA].delete(key);
}

return result;
});

/**
* Get the set
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*
* @param {*} key
*
* @return {WeakValueSet}
*/
WeakValueSetMap.setMethod(function get(key) {
let set = this[DATA].get(key);

if (!set) {
return null;
}

if (set.size == 0) {
this[DATA].delete(key);
return null;
}

return set;
});

/**
* Check if the map contains a key (that is still referenced)
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod(function has(key, value) {

let set = this[DATA].get(key);

if (arguments.length == 1) {
return set.size > 0;
}

if (!set) {
return false;
}

return set.has(value);
});

/**
* Add a value to the set of the given key
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*
* @param {*} key
* @param {*} value
*
* @return {WeakValueSetMap}
*/
WeakValueSetMap.setMethod(function add(key, value) {

let set = this[DATA].get(key);

if (!set) {
set = new Blast.Classes.WeakValueSet();
this[DATA].set(key, set);
}

set.add(value);

return this;
});

/**
* Get an iterator
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod(function *entries() {
for (const [key, set] of this[DATA].entries()) {

if (set.size == 0) {
this[DATA].delete(key);
continue;
}

yield [key, set];
}
});

/**
* Get an iterator for the keys
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod(function *keys() {
for (const [key, value] of this) {
yield key;
}
});

/**
* Get an iterator for the values
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod(function *values() {
for (const [key, value] of this) {
yield value;
}
});

/**
* Set the iterable symbol
*
* @author Jelle De Loecker <[email protected]>
* @since 0.9.0
* @version 0.9.0
*/
WeakValueSetMap.setMethod(Symbol.iterator, function entries() {
return this.entries();
});
Loading

0 comments on commit 187267d

Please sign in to comment.