diff --git a/README.md b/README.md index 2c31298..fe8ebf8 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ See [docs](https://aureooms.github.io/js-collections-deque). Parent is [@aureooms/js-data-structures](https://github.com/aureooms/js-data-structures). ```js +import {deque} from '@aureooms/js-collections-deque'; deque( 'abcde' , 3 ) ; // 'cde' ``` diff --git a/doc/manual/usage.md b/doc/manual/usage.md index f05e2c8..d7fe6ce 100644 --- a/doc/manual/usage.md +++ b/doc/manual/usage.md @@ -9,7 +9,7 @@ import 'regenerator-runtime/runtime.js' ; Then ```js -const number = require( '@aureooms/js-collections-deque' ) ; +const {deque} = require( '@aureooms/js-collections-deque' ) ; // or -import number from '@aureooms/js-collections-deque' ; +import {deque} from '@aureooms/js-collections-deque' ; ``` diff --git a/mangle.json b/mangle.json index e765f9c..8e40801 100644 --- a/mangle.json +++ b/mangle.json @@ -7,6 +7,23 @@ } }, "props": { - "props": {} + "props": { + "$_center": "x", + "$_checkbounds": "b", + "$_container": "c", + "$_copy": "y", + "$_currentsize": "s", + "$_empty": "e", + "$_grow": "g", + "$_growth": "G", + "$_maxlen": "M", + "$_minsize": "m", + "$_popindex": "p", + "$_range": "r", + "$_realloc": "a", + "$_shrink": "s", + "$_value": "v", + "$_where": "w" + } } } \ No newline at end of file diff --git a/package.json b/package.json index ca32a8b..528869d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@aureooms/js-collections-deque", "description": "Python's deque data structure for JavaScript", - "version": "5.0.0", + "version": "6.0.0", "license": "AGPL-3.0", "author": "Aurélien Ooms ", "homepage": "https://aureooms.github.io/js-collections-deque", @@ -59,15 +59,15 @@ "travis": "npm run lint-config && npm run lint && npm run cover" }, "dependencies": { - "@aureooms/js-error": "^5.0.1" + "@aureooms/js-error": "^5.0.2" }, "devDependencies": { - "@aureooms/js-itertools": "4.1.0", + "@aureooms/js-itertools": "5.0.0", "@babel/core": "7.13.10", "@babel/preset-env": "7.13.10", "@babel/register": "7.13.8", "@commitlint/cli": "12.0.1", - "@js-library/commitlint-config": "0.0.3", + "@js-library/commitlint-config": "0.0.4", "ava": "3.15.0", "babel-plugin-transform-remove-console": "6.9.4", "babel-plugin-unassert": "3.0.1", diff --git a/src/_deque.js b/src/_deque.js index 7b96323..d2dd369 100644 --- a/src/_deque.js +++ b/src/_deque.js @@ -1,12 +1,26 @@ import {TypeError, ValueError} from '@aureooms/js-error'; +/** + * _deque. + * + * @param {Deque} UnboundedDeque + * @param {Deque} BoundedDeque + * @param {Deque} SingleElementDeque + * @param {Deque} EmptyDeque + */ export default function _deque( UnboundedDeque, BoundedDeque, SingleElementDeque, EmptyDeque, ) { - const deque = function (iterable = null, maxlen = null) { + /** + * Deque. + * + * @param {Iterable} iterable + * @param {Number} maxlen + */ + const deque = (iterable = null, maxlen = null) => { if (maxlen === null) { return new UnboundedDeque(iterable); } diff --git a/src/implementation/ArbitrarySizeDeque.js b/src/implementation/ArbitrarySizeDeque.js index 9b4d73b..13f897a 100644 --- a/src/implementation/ArbitrarySizeDeque.js +++ b/src/implementation/ArbitrarySizeDeque.js @@ -1,27 +1,42 @@ import Deque from './Deque.js'; +import {NotImplementedError} from '@aureooms/js-error'; +/** + * ArbitrarySizeDeque. + */ export default function ArbitrarySizeDeque() {} ArbitrarySizeDeque.prototype = new Deque(); ArbitrarySizeDeque.prototype.values = function* () { - let i = this.center; + let i = this._center; const _m = i + this.length; const m = Math.min(this.capacity(), _m); for (; i < m; ++i) { - yield this.container[i]; + yield this._container[i]; } const n = _m % this.capacity(); if (n < _m) { for (i = 0; i < n; ++i) { - yield this.container[i]; + yield this._container[i]; } } }; +/** + * ArbitrarySizeDeque.prototype._popindex. + * + * @param {any} _container + * @param {Number} _index + * @return {any} + */ +ArbitrarySizeDeque.prototype._popindex = function (_container, _index) { + throw new NotImplementedError('_popindex'); +}; + ArbitrarySizeDeque.prototype.pop = function () { const [container, index] = this._where(this.length - 1); @@ -31,8 +46,8 @@ ArbitrarySizeDeque.prototype.pop = function () { ArbitrarySizeDeque.prototype.popleft = function () { const [container, index] = this._where(0); - ++this.center; - this.center %= this.capacity(); + ++this._center; + this._center %= this.capacity(); return this._popindex(container, index); }; diff --git a/src/implementation/BoundedDeque.js b/src/implementation/BoundedDeque.js index fcce4f6..0d5861d 100644 --- a/src/implementation/BoundedDeque.js +++ b/src/implementation/BoundedDeque.js @@ -1,12 +1,18 @@ import ArbitrarySizeDeque from './ArbitrarySizeDeque.js'; +/** + * BoundedDeque. + * + * @param {Iterable} iterable + * @param {Number} maxlen + */ export default function BoundedDeque(iterable, maxlen) { - this.maxlen = maxlen; + this._maxlen = maxlen; // eslint-disable-next-line unicorn/no-new-array - this.container = new Array(maxlen); + this._container = new Array(maxlen); - this.center = 0; + this._center = 0; this.length = 0; @@ -22,17 +28,17 @@ BoundedDeque.prototype.len = function () { }; BoundedDeque.prototype.capacity = function () { - return this.maxlen; + return this._maxlen; }; BoundedDeque.prototype.append = function (x) { - if (this.length === this.maxlen) { - this.container[this.center] = x; - ++this.center; - this.center %= this.maxlen; + if (this.length === this._maxlen) { + this._container[this._center] = x; + ++this._center; + this._center %= this._maxlen; } else { - const i = (this.center + this.length) % this.maxlen; - this.container[i] = x; + const i = (this._center + this.length) % this._maxlen; + this._container[i] = x; ++this.length; } @@ -40,12 +46,12 @@ BoundedDeque.prototype.append = function (x) { }; BoundedDeque.prototype.appendleft = function (x) { - --this.center; - this.center += this.maxlen; - this.center %= this.maxlen; - this.container[this.center] = x; + --this._center; + this._center += this._maxlen; + this._center %= this._maxlen; + this._container[this._center] = x; - if (this.length < this.maxlen) { + if (this.length < this._maxlen) { ++this.length; } @@ -53,26 +59,33 @@ BoundedDeque.prototype.appendleft = function (x) { }; BoundedDeque.prototype.clear = function () { - this.center = 0; + this._center = 0; this.length = 0; // eslint-disable-next-line unicorn/no-new-array - this.container = new Array(this.maxlen); + this._container = new Array(this._maxlen); return this; }; BoundedDeque.prototype.copy = function () { - return new BoundedDeque(this, this.maxlen); + return new BoundedDeque(this, this._maxlen); }; BoundedDeque.prototype._where = function (i) { this._checkbounds(i); - return [this.container, (this.center + i) % this.maxlen]; + return [this._container, (this._center + i) % this._maxlen]; }; +/** + * BoundedDeque.prototype._popindex. + * + * @param {any} container + * @param {Number} index + * @return {any} + */ BoundedDeque.prototype._popindex = function (container, index) { const value = container[index]; diff --git a/src/implementation/Deque.js b/src/implementation/Deque.js index 8be1a3a..12e31a6 100644 --- a/src/implementation/Deque.js +++ b/src/implementation/Deque.js @@ -1,43 +1,97 @@ import {NotImplementedError, IndexError, ValueError} from '@aureooms/js-error'; +/** + * Deque. + */ export default function Deque() {} +/** + * Deque.prototype.len. + * + * @return {Number} + */ Deque.prototype.len = function () { throw new NotImplementedError('len'); }; +/** + * Deque.prototype.capacity. + * + * @return {Number} + */ Deque.prototype.capacity = function () { - throw new NotImplementedError('capcity'); + throw new NotImplementedError('capacity'); }; +/** + * Deque.prototype.empty. + * + * @return {Boolean} + */ Deque.prototype.empty = function () { return this.len() === 0; }; +/** + * Deque.prototype[Symbol.iterator]. + * + * @return {Iterable} + */ Deque.prototype[Symbol.iterator] = function () { return this.values(); }; +/** + * Deque.prototype.values. + * + * @return {Iterable} + */ Deque.prototype.values = function () { throw new NotImplementedError('values'); }; +/** + * Deque.prototype.append. + * + * @param {any} _x + */ Deque.prototype.append = function (_x) { throw new NotImplementedError('append'); }; +/** + * Deque.prototype.appendleft. + * + * @param {any} _x + */ Deque.prototype.appendleft = function (_x) { throw new NotImplementedError('appendleft'); }; +/** + * Deque.prototype.clear. + * + * @return {Deque} + */ Deque.prototype.clear = function () { throw new NotImplementedError('clear'); }; +/** + * Deque.prototype.copy. + * + * @return {Deque} + */ Deque.prototype.copy = function () { throw new NotImplementedError('copy'); }; +/** + * Deque.prototype.count. + * + * @param {any} x + * @return {Number} + */ Deque.prototype.count = function (x) { let c = 0; @@ -50,6 +104,11 @@ Deque.prototype.count = function (x) { return c; }; +/** + * Deque.prototype.extend. + * + * @param {Iterable} iterable + */ Deque.prototype.extend = function (iterable) { for (const x of iterable) { this.append(x); @@ -58,6 +117,11 @@ Deque.prototype.extend = function (iterable) { return this; }; +/** + * Deque.prototype.extendleft. + * + * @param {Iterable} iterable + */ Deque.prototype.extendleft = function (iterable) { for (const x of iterable) { this.appendleft(x); @@ -66,22 +130,46 @@ Deque.prototype.extendleft = function (iterable) { return this; }; +/** + * Deque.prototype._checkbounds. + * + * @param {Number} i + */ Deque.prototype._checkbounds = function (i) { if (i < 0 || i >= this.len()) { throw new IndexError(i); } }; +/** + * Deque.prototype._where. + * + * @param {Number} _i + * @return {Array} + */ Deque.prototype._where = function (_i) { throw new NotImplementedError('_where'); }; +/** + * Deque.prototype.get. + * + * @param {Number} i + * @return {any} + */ Deque.prototype.get = function (i) { const [container, index] = this._where(i); return container[index]; }; +/** + * Deque.prototype.set. + * + * @param {Number} i + * @param {any} value + * @return {Deque} + */ Deque.prototype.set = function (i, value) { const [container, index] = this._where(i); @@ -90,12 +178,26 @@ Deque.prototype.set = function (i, value) { return this; }; +/** + * Deque.prototype._range + * + * @param {Number} start + * @param {Number} stop + * @return {Iterable} + */ Deque.prototype._range = function* (start, stop) { for (let i = start; i < stop; ++i) { yield [i, this.get(i)]; } }; +/** + * Deque.prototype.index. + * + * @param {any} x + * @param {Number} start + * @param {Number} stop + */ Deque.prototype.index = function (x, start = 0, stop = this.len()) { for (const [i, element] of this._range(start, stop)) { if (element === x) { @@ -106,14 +208,30 @@ Deque.prototype.index = function (x, start = 0, stop = this.len()) { throw new ValueError('not found'); }; +/** + * Deque.prototype.pop. + * + * @return {any} + */ Deque.prototype.pop = function () { throw new NotImplementedError('pop'); }; +/** + * Deque.prototype.popleft. + * + * @return {any} + */ Deque.prototype.popleft = function () { throw new NotImplementedError('popleft'); }; +/** + * Deque.prototype.insert. + * + * @param {Number} i + * @param {any} x + */ Deque.prototype.insert = function (i, x) { this._checkbounds(i); @@ -130,6 +248,11 @@ Deque.prototype.insert = function (i, x) { return this; }; +/** + * Deque.prototype.delete. + * + * @param {Number} i + */ Deque.prototype.delete = function (i) { this._checkbounds(i); @@ -144,6 +267,11 @@ Deque.prototype.delete = function (i) { return this; }; +/** + * Deque.prototype.remove. + * + * @param {any} value + */ Deque.prototype.remove = function (value) { const i = this.index(value); @@ -152,6 +280,11 @@ Deque.prototype.remove = function (value) { return this; }; +/** + * Deque.prototype.reverse. + * + * @return {Deque} + */ Deque.prototype.reverse = function () { for (let i = 0, j = this.len(); i < --j; ++i) { const a = this.get(i); @@ -163,6 +296,11 @@ Deque.prototype.reverse = function () { return this; }; +/** + * Deque.prototype.rotate. + * + * @param {Number} n + */ Deque.prototype.rotate = function (n) { if (n > 0) { while (n-- > 0) { diff --git a/src/implementation/EmptyDeque.js b/src/implementation/EmptyDeque.js index f94a4e1..584d420 100644 --- a/src/implementation/EmptyDeque.js +++ b/src/implementation/EmptyDeque.js @@ -1,6 +1,11 @@ import {IndexError} from '@aureooms/js-error'; import Deque from './Deque.js'; +/** + * EmptyDeque. + * + * @param {Iterable} iterable + */ export default function EmptyDeque(iterable) { if (iterable !== null) { this.extend(iterable); diff --git a/src/implementation/SingleElementDeque.js b/src/implementation/SingleElementDeque.js index 96d7179..c2c3d4e 100644 --- a/src/implementation/SingleElementDeque.js +++ b/src/implementation/SingleElementDeque.js @@ -1,10 +1,15 @@ import {IndexError} from '@aureooms/js-error'; import Deque from './Deque.js'; +/** + * SingleElementDeque. + * + * @param {Iterable} iterable + */ export default function SingleElementDeque(iterable) { - this.empty = true; + this._empty = true; - this.value = 0; + this._value = 0; if (iterable !== null) { this.extend(iterable); @@ -14,7 +19,7 @@ export default function SingleElementDeque(iterable) { SingleElementDeque.prototype = new Deque(); SingleElementDeque.prototype.len = function () { - return this.empty ? 0 : 1; + return this._empty ? 0 : 1; }; SingleElementDeque.prototype.capacity = function () { @@ -22,25 +27,25 @@ SingleElementDeque.prototype.capacity = function () { }; SingleElementDeque.prototype.values = function* () { - if (this.empty) { + if (this._empty) { return; } - yield this.value; + yield this._value; }; SingleElementDeque.prototype.append = // eslint-disable-next-line no-multi-assign SingleElementDeque.prototype.appendleft = function (x) { - this.empty = false; - this.value = x; + this._empty = false; + this._value = x; return this; }; SingleElementDeque.prototype.clear = function () { - this.empty = true; - this.value = 0; + this._empty = true; + this._value = 0; return this; }; @@ -52,32 +57,32 @@ SingleElementDeque.prototype.copy = function () { SingleElementDeque.prototype.pop = // eslint-disable-next-line no-multi-assign SingleElementDeque.prototype.popleft = function () { - if (this.empty) { + if (this._empty) { throw new IndexError('pop / popleft'); } - const value = this.value; + const value = this._value; - this.empty = true; - this.value = 0; + this._empty = true; + this._value = 0; return value; }; SingleElementDeque.prototype.get = function (i) { - if (this.empty || i !== 0) { + if (this._empty || i !== 0) { throw new IndexError(i); } - return this.value; + return this._value; }; SingleElementDeque.prototype.set = function (i, value) { - if (this.empty || i !== 0) { + if (this._empty || i !== 0) { throw new IndexError(i); } - this.value = value; + this._value = value; return this; }; diff --git a/src/implementation/UnboundedDeque.js b/src/implementation/UnboundedDeque.js index 9e7e0d8..f3b3bdf 100644 --- a/src/implementation/UnboundedDeque.js +++ b/src/implementation/UnboundedDeque.js @@ -1,16 +1,21 @@ import ArbitrarySizeDeque from './ArbitrarySizeDeque.js'; +/** + * UnboundedDeque. + * + * @param {Iterable} iterable + */ export default function UnboundedDeque(iterable) { - this.growth = 2; + this._growth = 2; - this.minsize = 10; + this._minsize = 10; - this.currentsize = this.minsize; + this._currentsize = this._minsize; // eslint-disable-next-line unicorn/no-new-array - this.container = new Array(this.currentsize); + this._container = new Array(this._currentsize); - this.center = 0; + this._center = 0; this.length = 0; @@ -35,17 +40,17 @@ UnboundedDeque.prototype._realloc = function (newsize) { this._copy(container); - this.container = container; + this._container = container; - this.center = 0; + this._center = 0; - this.currentsize = newsize; + this._currentsize = newsize; }; UnboundedDeque.prototype._shrink = function () { - const newsize = Math.max(this.minsize, this.length * this.growth); + const newsize = Math.max(this._minsize, this.length * this._growth); - if (newsize * this.growth >= this.currentsize) { + if (newsize * this._growth >= this._currentsize) { return; } @@ -53,11 +58,11 @@ UnboundedDeque.prototype._shrink = function () { }; UnboundedDeque.prototype._grow = function (newlen) { - if (newlen <= this.currentsize) { + if (newlen <= this._currentsize) { return; } - this._realloc(newlen * this.growth); + this._realloc(newlen * this._growth); }; UnboundedDeque.prototype.len = function () { @@ -65,14 +70,14 @@ UnboundedDeque.prototype.len = function () { }; UnboundedDeque.prototype.capacity = function () { - return this.currentsize; + return this._currentsize; }; UnboundedDeque.prototype.append = function (x) { this._grow(this.length + 1); - const i = (this.center + this.length) % this.currentsize; - this.container[i] = x; + const i = (this._center + this.length) % this._currentsize; + this._container[i] = x; ++this.length; return this; @@ -81,10 +86,10 @@ UnboundedDeque.prototype.append = function (x) { UnboundedDeque.prototype.appendleft = function (x) { this._grow(this.length + 1); - --this.center; - this.center += this.currentsize; - this.center %= this.currentsize; - this.container[this.center] = x; + --this._center; + this._center += this._currentsize; + this._center %= this._currentsize; + this._container[this._center] = x; ++this.length; @@ -92,12 +97,12 @@ UnboundedDeque.prototype.appendleft = function (x) { }; UnboundedDeque.prototype.clear = function () { - this.currentsize = this.minsize; + this._currentsize = this._minsize; // eslint-disable-next-line unicorn/no-new-array - this.container = new Array(this.currentsize); + this._container = new Array(this._currentsize); - this.center = 0; + this._center = 0; this.length = 0; @@ -111,7 +116,7 @@ UnboundedDeque.prototype.copy = function () { UnboundedDeque.prototype._where = function (i) { this._checkbounds(i); - return [this.container, (this.center + i) % this.currentsize]; + return [this._container, (this._center + i) % this._currentsize]; }; UnboundedDeque.prototype._popindex = function (container, index) { diff --git a/yarn.lock b/yarn.lock index 3a7e644..7f2531c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,30 +2,30 @@ # yarn lockfile v1 -"@aureooms/js-collections-deque@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@aureooms/js-collections-deque/-/js-collections-deque-4.0.1.tgz#bd8b827cdb597d061525c380dd704e338c77bd5f" - integrity sha512-dktRVLyep0sUKpqgtG/JseA232KMdlu9t9ePq2wHcng1dZ3+63qW2C+FlKXBktrT1dU92DDxIL6PqnV97kHA1Q== +"@aureooms/js-collections-deque@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@aureooms/js-collections-deque/-/js-collections-deque-5.0.0.tgz#a574ddc2e53d8e073573f914cec9b130cf5355a8" + integrity sha512-28zJhpXGE4D0hQkaZFDYaeA/maUKTTcoHaScbBBzHCu5iy/+sovU7MnSm4URC0EN+R8AH/uVsSS0CFjDMXo6SQ== dependencies: - "@aureooms/js-error" "^4.0.1" - -"@aureooms/js-error@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@aureooms/js-error/-/js-error-4.0.1.tgz#be2740b3f31a337e0828930c9b70d38113b4dd77" - integrity sha512-zsgs6wmnRsKljlusewYiBaFBM/hIJp43b7OwE9ybpLEL4wfXjGP17cJTTAY8gpzALVFwEA5/flxIK0I6gJJLHQ== + "@aureooms/js-error" "^5.0.1" "@aureooms/js-error@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@aureooms/js-error/-/js-error-5.0.1.tgz#474e2f1dd7189f97df770b5cc6f1bda536de262d" integrity sha512-BbbpKpp4W8L2x9vL4bas+JtuAe4PMojzTpf21puHPw5p3S+lgKd8SfS9y40pVHi/b3SrQrdpmsaEKjL4xviilQ== -"@aureooms/js-itertools@4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@aureooms/js-itertools/-/js-itertools-4.1.0.tgz#c731eaee7de0005c6ea41f2f87cca4bdb2d86ca1" - integrity sha512-P9TfwQPuXk5T5z6QMMfwLLyzh9QsEu4sGWcBk/P/waWgim/xqr+LDTOHVo7WU4QAty+/5CBX8DuW7MrPVfXt5A== +"@aureooms/js-error@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@aureooms/js-error/-/js-error-5.0.2.tgz#dc2ad2fc2b10365581c32c28222daccc5c3c9600" + integrity sha512-HLO95kmZ1nJV5qo8Xq7czHVskFGPkM3l60JFgdTnpvCH6P6lkyWDBplaDB9gI5cPvcRIZDs1HeAHhAlHR/jBxw== + +"@aureooms/js-itertools@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@aureooms/js-itertools/-/js-itertools-5.0.0.tgz#f0f4e27381b8533ddeb9db7c8f4f05da0522cddd" + integrity sha512-LAULGvyCvMjD+V0J4m7PS2QITeG/j3KUxDlSM5rOR7sh0eWZU3jiRMi8H0aBpKhwiVV6AEjXBsMmo3EmhPlJrQ== dependencies: - "@aureooms/js-collections-deque" "^4.0.1" - "@aureooms/js-error" "^4.0.1" + "@aureooms/js-collections-deque" "^5.0.0" + "@aureooms/js-error" "^5.0.1" "@babel/code-frame@7.12.11": version "7.12.11" @@ -1330,10 +1330,10 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@js-library/commitlint-config@0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@js-library/commitlint-config/-/commitlint-config-0.0.3.tgz#4ffa7c5cee08e1a947e54d41e0f10f56a50928a2" - integrity sha512-45eqMFZt8MbZt0/7VBI9PXu3Ms80v3jKvT1Noj47UDx6YftPClvV3VwDxCfr4muwyhzOErYm2r7k3ETQ1ehxJw== +"@js-library/commitlint-config@0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@js-library/commitlint-config/-/commitlint-config-0.0.4.tgz#5243a58b0d4ad36999d4b944c7770c50658c68f5" + integrity sha512-l6un9f0HmIJZswqGe5H/HGBkENpqBQv1b36bdLZLXhZEZBTlm2Chbv3J1hJ2kNG8ogh+EFV5nUYQnL3MefLSDQ== "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1"