@thi.ng/idgen
Advanced tools
Comparing version 0.2.16 to 0.2.17
@@ -6,2 +6,10 @@ # Change Log | ||
## [0.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/idgen@0.2.16...@thi.ng/idgen@0.2.17) (2020-07-02) | ||
**Note:** Version bump only for package @thi.ng/idgen | ||
## [0.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/idgen@0.2.15...@thi.ng/idgen@0.2.16) (2020-06-20) | ||
@@ -8,0 +16,0 @@ |
213
index.js
@@ -5,118 +5,115 @@ import { __decorate } from "tslib"; | ||
export const EVENT_REMOVED = "removed"; | ||
let IDGen = /** @class */ (() => { | ||
let IDGen = class IDGen { | ||
constructor(bits = 32, vbits = 32 - bits, cap = 2 ** bits, next = 0) { | ||
const maxCap = 2 ** bits; | ||
assert(bits > 0 && bits + vbits <= 32, "wrong total bit size [1..32]"); | ||
assert(cap <= maxCap, `requested capacity too large for bit size (max. ${maxCap})`); | ||
this.ids = []; | ||
this.nextID = next; | ||
this.start = next; | ||
this._capacity = cap; | ||
this.num = 0; | ||
this.mask = maxCap - 1; | ||
this.vmask = (1 << vbits) - 1; | ||
let IDGen = class IDGen { | ||
constructor(bits = 32, vbits = 32 - bits, cap = 2 ** bits, next = 0) { | ||
const maxCap = 2 ** bits; | ||
assert(bits > 0 && bits + vbits <= 32, "wrong total bit size [1..32]"); | ||
assert(cap <= maxCap, `requested capacity too large for bit size (max. ${maxCap})`); | ||
this.ids = []; | ||
this.nextID = next; | ||
this.start = next; | ||
this._capacity = cap; | ||
this.num = 0; | ||
this.mask = maxCap - 1; | ||
this.vmask = (1 << vbits) - 1; | ||
this.shift = bits; | ||
this._freeID = -1; | ||
} | ||
id(id) { | ||
return id & this.mask; | ||
} | ||
version(id) { | ||
return (id >>> this.shift) & this.vmask; | ||
} | ||
get capacity() { | ||
return this._capacity; | ||
} | ||
/** | ||
* Attempts to set new capacity to given value. Capacity can only be | ||
* increased and the operation is only supported for unversioned | ||
* instances (i.e. vbits = 0). | ||
*/ | ||
set capacity(newCap) { | ||
assert(!this.vmask, "can't change capacity w/ versioning enabled"); | ||
if (newCap >= this.mask + 1) { | ||
const bits = Math.ceil(Math.log2(newCap)); | ||
assert(bits > 0 && bits <= 32, "wrong bit size for new capacity [1..32]"); | ||
this._capacity = newCap; | ||
this.mask = 2 ** bits - 1; | ||
this.shift = bits; | ||
this._freeID = -1; | ||
} | ||
id(id) { | ||
return id & this.mask; | ||
else { | ||
throw new Error("can't reduce capacity"); | ||
} | ||
version(id) { | ||
return (id >>> this.shift) & this.vmask; | ||
} | ||
get available() { | ||
return this._capacity - this.num - this.start; | ||
} | ||
get used() { | ||
return this.num; | ||
} | ||
get freeID() { | ||
return this._freeID; | ||
} | ||
*[Symbol.iterator]() { | ||
for (let i = this.nextID; --i >= 0;) { | ||
const id = this.ids[i]; | ||
if ((id & this.mask) === i) | ||
yield id; | ||
} | ||
get capacity() { | ||
return this._capacity; | ||
} | ||
/** | ||
* Attempts to set new capacity to given value. Capacity can only be | ||
* increased and the operation is only supported for unversioned | ||
* instances (i.e. vbits = 0). | ||
*/ | ||
set capacity(newCap) { | ||
assert(!this.vmask, "can't change capacity w/ versioning enabled"); | ||
if (newCap >= this.mask + 1) { | ||
const bits = Math.ceil(Math.log2(newCap)); | ||
assert(bits > 0 && bits <= 32, "wrong bit size for new capacity [1..32]"); | ||
this._capacity = newCap; | ||
this.mask = 2 ** bits - 1; | ||
this.shift = bits; | ||
} | ||
else { | ||
throw new Error("can't reduce capacity"); | ||
} | ||
} | ||
get available() { | ||
return this._capacity - this.num - this.start; | ||
} | ||
get used() { | ||
return this.num; | ||
} | ||
get freeID() { | ||
return this._freeID; | ||
} | ||
*[Symbol.iterator]() { | ||
for (let i = this.nextID; --i >= 0;) { | ||
const id = this.ids[i]; | ||
if ((id & this.mask) === i) | ||
yield id; | ||
} | ||
} | ||
clear() { | ||
this.ids.length = 0; | ||
this.nextID = this.start; | ||
this.num = 0; | ||
this._freeID = -1; | ||
} | ||
next() { | ||
let id; | ||
if (this._freeID !== -1) { | ||
id = this._freeID; | ||
const rawID = this.id(id); | ||
this._freeID = this.ids[rawID]; | ||
this.ids[rawID] = id; | ||
} | ||
else { | ||
assert(this.nextID < this._capacity, "max capacity reached"); | ||
id = this.nextID++; | ||
this.ids[id] = id; | ||
} | ||
this.num++; | ||
this.notify({ id: EVENT_ADDED, target: this, value: id }); | ||
return id; | ||
} | ||
free(id) { | ||
if (!this.has(id)) | ||
return false; | ||
this.ids[this.id(id)] = this._freeID; | ||
this._freeID = this.nextVersion(id); | ||
this.num--; | ||
this.notify({ id: EVENT_REMOVED, target: this, value: id }); | ||
return true; | ||
} | ||
has(id) { | ||
} | ||
clear() { | ||
this.ids.length = 0; | ||
this.nextID = this.start; | ||
this.num = 0; | ||
this._freeID = -1; | ||
} | ||
next() { | ||
let id; | ||
if (this._freeID !== -1) { | ||
id = this._freeID; | ||
const rawID = this.id(id); | ||
return id >= 0 && rawID < this.nextID && this.ids[rawID] === id; | ||
this._freeID = this.ids[rawID]; | ||
this.ids[rawID] = id; | ||
} | ||
/** {@inheritDoc @thi.ng/api#INotify.addListener} */ | ||
// @ts-ignore: mixin | ||
addListener(id, fn, scope) { } | ||
/** {@inheritDoc @thi.ng/api#INotify.removeListener} */ | ||
// @ts-ignore: mixin | ||
removeListener(id, fn, scope) { } | ||
/** {@inheritDoc @thi.ng/api#INotify.notify} */ | ||
// @ts-ignore: mixin | ||
notify(event) { } | ||
nextVersion(id) { | ||
return (((id & this.mask) | | ||
(((this.version(id) + 1) & this.vmask) << this.shift)) >>> | ||
0); | ||
else { | ||
assert(this.nextID < this._capacity, "max capacity reached"); | ||
id = this.nextID++; | ||
this.ids[id] = id; | ||
} | ||
}; | ||
IDGen = __decorate([ | ||
INotifyMixin | ||
], IDGen); | ||
return IDGen; | ||
})(); | ||
this.num++; | ||
this.notify({ id: EVENT_ADDED, target: this, value: id }); | ||
return id; | ||
} | ||
free(id) { | ||
if (!this.has(id)) | ||
return false; | ||
this.ids[this.id(id)] = this._freeID; | ||
this._freeID = this.nextVersion(id); | ||
this.num--; | ||
this.notify({ id: EVENT_REMOVED, target: this, value: id }); | ||
return true; | ||
} | ||
has(id) { | ||
const rawID = this.id(id); | ||
return id >= 0 && rawID < this.nextID && this.ids[rawID] === id; | ||
} | ||
/** {@inheritDoc @thi.ng/api#INotify.addListener} */ | ||
// @ts-ignore: mixin | ||
addListener(id, fn, scope) { } | ||
/** {@inheritDoc @thi.ng/api#INotify.removeListener} */ | ||
// @ts-ignore: mixin | ||
removeListener(id, fn, scope) { } | ||
/** {@inheritDoc @thi.ng/api#INotify.notify} */ | ||
// @ts-ignore: mixin | ||
notify(event) { } | ||
nextVersion(id) { | ||
return (((id & this.mask) | | ||
(((this.version(id) + 1) & this.vmask) << this.shift)) >>> | ||
0); | ||
} | ||
}; | ||
IDGen = __decorate([ | ||
INotifyMixin | ||
], IDGen); | ||
export { IDGen }; | ||
export const idgen = (bits, vbits, cap, next) => new IDGen(bits, vbits, cap, next); |
194
lib/index.js
@@ -10,111 +10,107 @@ 'use strict'; | ||
const EVENT_REMOVED = "removed"; | ||
let IDGen = (() => { | ||
let IDGen = class IDGen { | ||
constructor(bits = 32, vbits = 32 - bits, cap = 2 ** bits, next = 0) { | ||
const maxCap = 2 ** bits; | ||
api.assert(bits > 0 && bits + vbits <= 32, "wrong total bit size [1..32]"); | ||
api.assert(cap <= maxCap, `requested capacity too large for bit size (max. ${maxCap})`); | ||
this.ids = []; | ||
this.nextID = next; | ||
this.start = next; | ||
this._capacity = cap; | ||
this.num = 0; | ||
this.mask = maxCap - 1; | ||
this.vmask = (1 << vbits) - 1; | ||
exports.IDGen = class IDGen { | ||
constructor(bits = 32, vbits = 32 - bits, cap = 2 ** bits, next = 0) { | ||
const maxCap = 2 ** bits; | ||
api.assert(bits > 0 && bits + vbits <= 32, "wrong total bit size [1..32]"); | ||
api.assert(cap <= maxCap, `requested capacity too large for bit size (max. ${maxCap})`); | ||
this.ids = []; | ||
this.nextID = next; | ||
this.start = next; | ||
this._capacity = cap; | ||
this.num = 0; | ||
this.mask = maxCap - 1; | ||
this.vmask = (1 << vbits) - 1; | ||
this.shift = bits; | ||
this._freeID = -1; | ||
} | ||
id(id) { | ||
return id & this.mask; | ||
} | ||
version(id) { | ||
return (id >>> this.shift) & this.vmask; | ||
} | ||
get capacity() { | ||
return this._capacity; | ||
} | ||
set capacity(newCap) { | ||
api.assert(!this.vmask, "can't change capacity w/ versioning enabled"); | ||
if (newCap >= this.mask + 1) { | ||
const bits = Math.ceil(Math.log2(newCap)); | ||
api.assert(bits > 0 && bits <= 32, "wrong bit size for new capacity [1..32]"); | ||
this._capacity = newCap; | ||
this.mask = 2 ** bits - 1; | ||
this.shift = bits; | ||
this._freeID = -1; | ||
} | ||
id(id) { | ||
return id & this.mask; | ||
else { | ||
throw new Error("can't reduce capacity"); | ||
} | ||
version(id) { | ||
return (id >>> this.shift) & this.vmask; | ||
} | ||
get available() { | ||
return this._capacity - this.num - this.start; | ||
} | ||
get used() { | ||
return this.num; | ||
} | ||
get freeID() { | ||
return this._freeID; | ||
} | ||
*[Symbol.iterator]() { | ||
for (let i = this.nextID; --i >= 0;) { | ||
const id = this.ids[i]; | ||
if ((id & this.mask) === i) | ||
yield id; | ||
} | ||
get capacity() { | ||
return this._capacity; | ||
} | ||
set capacity(newCap) { | ||
api.assert(!this.vmask, "can't change capacity w/ versioning enabled"); | ||
if (newCap >= this.mask + 1) { | ||
const bits = Math.ceil(Math.log2(newCap)); | ||
api.assert(bits > 0 && bits <= 32, "wrong bit size for new capacity [1..32]"); | ||
this._capacity = newCap; | ||
this.mask = 2 ** bits - 1; | ||
this.shift = bits; | ||
} | ||
else { | ||
throw new Error("can't reduce capacity"); | ||
} | ||
} | ||
get available() { | ||
return this._capacity - this.num - this.start; | ||
} | ||
get used() { | ||
return this.num; | ||
} | ||
get freeID() { | ||
return this._freeID; | ||
} | ||
*[Symbol.iterator]() { | ||
for (let i = this.nextID; --i >= 0;) { | ||
const id = this.ids[i]; | ||
if ((id & this.mask) === i) | ||
yield id; | ||
} | ||
} | ||
clear() { | ||
this.ids.length = 0; | ||
this.nextID = this.start; | ||
this.num = 0; | ||
this._freeID = -1; | ||
} | ||
next() { | ||
let id; | ||
if (this._freeID !== -1) { | ||
id = this._freeID; | ||
const rawID = this.id(id); | ||
this._freeID = this.ids[rawID]; | ||
this.ids[rawID] = id; | ||
} | ||
else { | ||
api.assert(this.nextID < this._capacity, "max capacity reached"); | ||
id = this.nextID++; | ||
this.ids[id] = id; | ||
} | ||
this.num++; | ||
this.notify({ id: EVENT_ADDED, target: this, value: id }); | ||
return id; | ||
} | ||
free(id) { | ||
if (!this.has(id)) | ||
return false; | ||
this.ids[this.id(id)] = this._freeID; | ||
this._freeID = this.nextVersion(id); | ||
this.num--; | ||
this.notify({ id: EVENT_REMOVED, target: this, value: id }); | ||
return true; | ||
} | ||
has(id) { | ||
} | ||
clear() { | ||
this.ids.length = 0; | ||
this.nextID = this.start; | ||
this.num = 0; | ||
this._freeID = -1; | ||
} | ||
next() { | ||
let id; | ||
if (this._freeID !== -1) { | ||
id = this._freeID; | ||
const rawID = this.id(id); | ||
return id >= 0 && rawID < this.nextID && this.ids[rawID] === id; | ||
this._freeID = this.ids[rawID]; | ||
this.ids[rawID] = id; | ||
} | ||
addListener(id, fn, scope) { } | ||
removeListener(id, fn, scope) { } | ||
notify(event) { } | ||
nextVersion(id) { | ||
return (((id & this.mask) | | ||
(((this.version(id) + 1) & this.vmask) << this.shift)) >>> | ||
0); | ||
else { | ||
api.assert(this.nextID < this._capacity, "max capacity reached"); | ||
id = this.nextID++; | ||
this.ids[id] = id; | ||
} | ||
}; | ||
IDGen = tslib.__decorate([ | ||
api.INotifyMixin | ||
], IDGen); | ||
return IDGen; | ||
})(); | ||
const idgen = (bits, vbits, cap, next) => new IDGen(bits, vbits, cap, next); | ||
this.num++; | ||
this.notify({ id: EVENT_ADDED, target: this, value: id }); | ||
return id; | ||
} | ||
free(id) { | ||
if (!this.has(id)) | ||
return false; | ||
this.ids[this.id(id)] = this._freeID; | ||
this._freeID = this.nextVersion(id); | ||
this.num--; | ||
this.notify({ id: EVENT_REMOVED, target: this, value: id }); | ||
return true; | ||
} | ||
has(id) { | ||
const rawID = this.id(id); | ||
return id >= 0 && rawID < this.nextID && this.ids[rawID] === id; | ||
} | ||
addListener(id, fn, scope) { } | ||
removeListener(id, fn, scope) { } | ||
notify(event) { } | ||
nextVersion(id) { | ||
return (((id & this.mask) | | ||
(((this.version(id) + 1) & this.vmask) << this.shift)) >>> | ||
0); | ||
} | ||
}; | ||
exports.IDGen = tslib.__decorate([ | ||
api.INotifyMixin | ||
], exports.IDGen); | ||
const idgen = (bits, vbits, cap, next) => new exports.IDGen(bits, vbits, cap, next); | ||
exports.EVENT_ADDED = EVENT_ADDED; | ||
exports.EVENT_REMOVED = EVENT_REMOVED; | ||
exports.IDGen = IDGen; | ||
exports.idgen = idgen; |
@@ -1,1 +0,1 @@ | ||
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports,require("tslib"),require("@thi.ng/api")):"function"==typeof define&&define.amd?define(["exports","tslib","@thi.ng/api"],i):i(((t=t||self).thi=t.thi||{},t.thi.ng=t.thi.ng||{},t.thi.ng.idgen={}),t.thi.ng[""],t.thi.ng.api)}(this,(function(t,i,e){"use strict";let s=(()=>{let t=class{constructor(t=32,i=32-t,s=2**t,h=0){const r=2**t;e.assert(t>0&&t+i<=32,"wrong total bit size [1..32]"),e.assert(s<=r,`requested capacity too large for bit size (max. ${r})`),this.ids=[],this.nextID=h,this.start=h,this._capacity=s,this.num=0,this.mask=r-1,this.vmask=(1<<i)-1,this.shift=t,this._freeID=-1}id(t){return t&this.mask}version(t){return t>>>this.shift&this.vmask}get capacity(){return this._capacity}set capacity(t){if(e.assert(!this.vmask,"can't change capacity w/ versioning enabled"),!(t>=this.mask+1))throw new Error("can't reduce capacity");{const i=Math.ceil(Math.log2(t));e.assert(i>0&&i<=32,"wrong bit size for new capacity [1..32]"),this._capacity=t,this.mask=2**i-1,this.shift=i}}get available(){return this._capacity-this.num-this.start}get used(){return this.num}get freeID(){return this._freeID}*[Symbol.iterator](){for(let t=this.nextID;--t>=0;){const i=this.ids[t];(i&this.mask)===t&&(yield i)}}clear(){this.ids.length=0,this.nextID=this.start,this.num=0,this._freeID=-1}next(){let t;if(-1!==this._freeID){t=this._freeID;const i=this.id(t);this._freeID=this.ids[i],this.ids[i]=t}else e.assert(this.nextID<this._capacity,"max capacity reached"),t=this.nextID++,this.ids[t]=t;return this.num++,this.notify({id:"added",target:this,value:t}),t}free(t){return!!this.has(t)&&(this.ids[this.id(t)]=this._freeID,this._freeID=this.nextVersion(t),this.num--,this.notify({id:"removed",target:this,value:t}),!0)}has(t){const i=this.id(t);return t>=0&&i<this.nextID&&this.ids[i]===t}addListener(t,i,e){}removeListener(t,i,e){}notify(t){}nextVersion(t){return(t&this.mask|(this.version(t)+1&this.vmask)<<this.shift)>>>0}};return t=i.__decorate([e.INotifyMixin],t),t})();t.EVENT_ADDED="added",t.EVENT_REMOVED="removed",t.IDGen=s,t.idgen=(t,i,e,h)=>new s(t,i,e,h),Object.defineProperty(t,"__esModule",{value:!0})})); | ||
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports,require("tslib"),require("@thi.ng/api")):"function"==typeof define&&define.amd?define(["exports","tslib","@thi.ng/api"],i):i(((t=t||self).thi=t.thi||{},t.thi.ng=t.thi.ng||{},t.thi.ng.idgen={}),t.thi.ng[""],t.thi.ng.api)}(this,(function(t,i,e){"use strict";t.IDGen=class{constructor(t=32,i=32-t,s=2**t,h=0){const r=2**t;e.assert(t>0&&t+i<=32,"wrong total bit size [1..32]"),e.assert(s<=r,`requested capacity too large for bit size (max. ${r})`),this.ids=[],this.nextID=h,this.start=h,this._capacity=s,this.num=0,this.mask=r-1,this.vmask=(1<<i)-1,this.shift=t,this._freeID=-1}id(t){return t&this.mask}version(t){return t>>>this.shift&this.vmask}get capacity(){return this._capacity}set capacity(t){if(e.assert(!this.vmask,"can't change capacity w/ versioning enabled"),!(t>=this.mask+1))throw new Error("can't reduce capacity");{const i=Math.ceil(Math.log2(t));e.assert(i>0&&i<=32,"wrong bit size for new capacity [1..32]"),this._capacity=t,this.mask=2**i-1,this.shift=i}}get available(){return this._capacity-this.num-this.start}get used(){return this.num}get freeID(){return this._freeID}*[Symbol.iterator](){for(let t=this.nextID;--t>=0;){const i=this.ids[t];(i&this.mask)===t&&(yield i)}}clear(){this.ids.length=0,this.nextID=this.start,this.num=0,this._freeID=-1}next(){let t;if(-1!==this._freeID){t=this._freeID;const i=this.id(t);this._freeID=this.ids[i],this.ids[i]=t}else e.assert(this.nextID<this._capacity,"max capacity reached"),t=this.nextID++,this.ids[t]=t;return this.num++,this.notify({id:"added",target:this,value:t}),t}free(t){return!!this.has(t)&&(this.ids[this.id(t)]=this._freeID,this._freeID=this.nextVersion(t),this.num--,this.notify({id:"removed",target:this,value:t}),!0)}has(t){const i=this.id(t);return t>=0&&i<this.nextID&&this.ids[i]===t}addListener(t,i,e){}removeListener(t,i,e){}notify(t){}nextVersion(t){return(t&this.mask|(this.version(t)+1&this.vmask)<<this.shift)>>>0}},t.IDGen=i.__decorate([e.INotifyMixin],t.IDGen);t.EVENT_ADDED="added",t.EVENT_REMOVED="removed",t.idgen=(i,e,s,h)=>new t.IDGen(i,e,s,h),Object.defineProperty(t,"__esModule",{value:!0})})); |
{ | ||
"name": "@thi.ng/idgen", | ||
"version": "0.2.16", | ||
"version": "0.2.17", | ||
"description": "Generator of opaque numeric identifiers with optional support for ID versioning and efficient re-use", | ||
@@ -45,11 +45,11 @@ "module": "./index.js", | ||
"@types/node": "^14.0.1", | ||
"mocha": "^7.1.2", | ||
"nyc": "^15.0.1", | ||
"mocha": "^8.0.1", | ||
"nyc": "^15.1.0", | ||
"ts-node": "^8.10.1", | ||
"typedoc": "^0.17.6", | ||
"typescript": "^3.9.2" | ||
"typescript": "^3.9.5" | ||
}, | ||
"dependencies": { | ||
"@thi.ng/api": "^6.11.2", | ||
"tslib": "^1.12.0" | ||
"@thi.ng/api": "^6.11.3", | ||
"tslib": "^2.0.0" | ||
}, | ||
@@ -77,3 +77,3 @@ "files": [ | ||
}, | ||
"gitHead": "71008cd78a3288d0f740c3e4b379b353f5c926b9" | ||
"gitHead": "af932be5734c03553f3a4df9b00cb45e061f3a53" | ||
} |
@@ -64,3 +64,3 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
Package sizes (gzipped, pre-treeshake): ESM: 853 bytes / CJS: 909 bytes / UMD: 992 bytes | ||
Package sizes (gzipped, pre-treeshake): ESM: 843 bytes / CJS: 890 bytes / UMD: 981 bytes | ||
@@ -67,0 +67,0 @@ ## Dependencies |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
39382
269
+ Addedtslib@2.8.1(transitive)
- Removedtslib@1.14.1(transitive)
Updated@thi.ng/api@^6.11.3
Updatedtslib@^2.0.0