collect-your-stuff 1.3.2 → 2.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.
Files changed (34) hide show
  1. package/dist/collections/arrayable/Arrayable.d.ts +2 -2
  2. package/dist/collections/arrayable/Arrayable.js +10 -0
  3. package/dist/collections/arrayable/Arrayable.min.js +1 -1
  4. package/dist/collections/doubly-linked-list/DoublyLinkedList.d.ts +14 -8
  5. package/dist/collections/doubly-linked-list/DoublyLinkedList.js +91 -56
  6. package/dist/collections/doubly-linked-list/DoublyLinkedList.min.js +1 -1
  7. package/dist/collections/linked-list/LinkedList.d.ts +14 -3
  8. package/dist/collections/linked-list/LinkedList.js +76 -32
  9. package/dist/collections/linked-list/LinkedList.min.js +1 -1
  10. package/dist/collections/linked-tree-list/LinkedTreeList.d.ts +9 -3
  11. package/dist/collections/linked-tree-list/LinkedTreeList.js +19 -21
  12. package/dist/collections/linked-tree-list/LinkedTreeList.min.js +1 -1
  13. package/dist/collections/queue/Queue.d.ts +35 -42
  14. package/dist/collections/queue/Queue.js +64 -80
  15. package/dist/collections/queue/Queue.min.js +1 -1
  16. package/dist/collections/queue/TaskQueue.d.ts +68 -0
  17. package/dist/collections/queue/TaskQueue.js +137 -0
  18. package/dist/collections/queue/TaskQueue.min.js +1 -0
  19. package/dist/collections/stack/Stack.d.ts +40 -40
  20. package/dist/collections/stack/Stack.js +73 -52
  21. package/dist/collections/stack/Stack.min.js +1 -1
  22. package/dist/collections/stack/TaskStack.d.ts +65 -0
  23. package/dist/collections/stack/TaskStack.js +107 -0
  24. package/dist/collections/stack/TaskStack.min.js +1 -0
  25. package/dist/main.d.ts +7 -1
  26. package/dist/main.js +16 -0
  27. package/dist/main.min.js +1 -1
  28. package/dist/recipes/IsQueue.d.ts +37 -0
  29. package/dist/recipes/IsQueue.js +5 -0
  30. package/dist/recipes/IsQueue.min.js +1 -0
  31. package/dist/recipes/IsStack.d.ts +36 -0
  32. package/dist/recipes/IsStack.js +5 -0
  33. package/dist/recipes/IsStack.min.js +1 -0
  34. package/package.json +1 -1
@@ -14,6 +14,13 @@ var _DoublyLinkedList = require('../doubly-linked-list/DoublyLinkedList')
14
14
  * @memberOf module:collect-your-stuff
15
15
  */
16
16
 
17
+ /**
18
+ * Use one of the accessors of DoublyLinkedList (which keeps track of the head, tail and length) for a LinkedTreeList.
19
+ * @param {string} name The accessor to use
20
+ * @param {LinkedTreeList} list The list to use it on
21
+ * @returns {*}
22
+ */
23
+ const borrowedGetter = (name, list) => Object.getOwnPropertyDescriptor(_DoublyLinkedList.DoublyLinkedList.prototype, name).get.call(list)
17
24
  /**
18
25
  * LinkedTreeList represents a collection stored with a root and spreading in branching (tree) formation.
19
26
  * @extends DoublyLinkedList
@@ -30,6 +37,10 @@ class LinkedTreeList {
30
37
  this.innerList = null
31
38
  /** Whether the inner list has been initialized (it can only be initialized once). */
32
39
  this.initialized = false
40
+ /** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
41
+ this.tailCache = null
42
+ /** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
43
+ this.countCache = null
33
44
  this.linkerClass = linkerClass
34
45
  }
35
46
 
@@ -61,38 +72,24 @@ class LinkedTreeList {
61
72
  * @returns {TreeLinker}
62
73
  */
63
74
  get first () {
64
- return this.reset()
75
+ return borrowedGetter('first', this)
65
76
  }
66
77
 
67
78
  /**
68
- * Retrieve the last TreeLinker in the list.
79
+ * Retrieve the last TreeLinker in the list. The end is remembered, so this does not walk the list.
69
80
  * @returns {TreeLinker}
70
81
  */
71
82
  get last () {
72
- let tail = this.innerList
73
- if (tail === null) {
74
- return null
75
- }
76
- let next = tail.next
77
- while (next !== null) {
78
- tail = next
79
- next = tail.next
80
- }
81
- return tail
83
+ return borrowedGetter('last', this)
82
84
  }
83
85
 
84
86
  /**
85
- * Return the length of the list.
87
+ * Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
88
+ * (call reset() after linkers were changed directly).
86
89
  * @returns {number}
87
90
  */
88
91
  get length () {
89
- let current = this.first
90
- let length = 0
91
- while (current !== null) {
92
- ++length
93
- current = current.next
94
- }
95
- return length
92
+ return borrowedGetter('length', this)
96
93
  }
97
94
 
98
95
  /**
@@ -201,7 +198,8 @@ class LinkedTreeList {
201
198
  }
202
199
 
203
200
  /**
204
- * Refresh all references and return head reference.
201
+ * Refresh all references (the head, the end and the length) by walking the list once, and return the head. The
202
+ * list's own methods keep these up to date, so this is only needed after linkers were changed directly.
205
203
  * @return {TreeLinker}
206
204
  */
207
205
  reset () {
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedTreeList=void 0;var _TreeLinker=require("./TreeLinker"),_TreeLinkerIterator=require("../../recipes/TreeLinkerIterator"),_DoublyLinkedList=require("../doubly-linked-list/DoublyLinkedList");class LinkedTreeList{constructor(e=_TreeLinker.TreeLinker){this.classType=LinkedTreeList,this.innerList=null,this.initialized=!1,this.linkerClass=e}initialize(e){return this.initialized?(console.warn("Attempt to initialize LinkedTreeList which is not empty."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return this.reset()}get last(){let e=this.innerList;if(null===e)return null;let t=e.next;for(;null!==t;)e=t,t=e.next;return e}get length(){let e=this.first,t=0;for(;null!==e;)++t,e=e.next;return t}get parent(){return null===this.first?null:this.first.parent}set parent(e){let t=this.first;for(;null!==t;)t.parent=e,t=t.next;e&&(e.children=this)}get rootParent(){let e=this.first;if(!e)return null;let t=this.first.parent;for(;null!==t;)e=t,t=e.parent;return e}setChildren(e,t=null){Array.from(this).indexOf(e)<0&&console.error("item is not a child of this"),t.parent=e}insertAfter(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this,e,t)}insertBefore(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this,e,t)}append(e,t=this.last){return _DoublyLinkedList.DoublyLinkedList.prototype.append.call(this,e,t)}prepend(e,t=this.first){return _DoublyLinkedList.DoublyLinkedList.prototype.prepend.call(this,e,t)}remove(e){return _DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this,e)}reset(){return _DoublyLinkedList.DoublyLinkedList.prototype.reset.call(this)}item(e){return _DoublyLinkedList.DoublyLinkedList.prototype.item.call(this,e)}forEach(e,t=this){let i=0,r=t.first;for(;null!==r;)e(r,i,t),r=r.next,++i;return t}[Symbol.iterator](){let e=this.rootParent;return new _TreeLinkerIterator.TreeLinkerIterator(e)}}exports.LinkedTreeList=LinkedTreeList,LinkedTreeList.fromArray=(e=[],t=_TreeLinker.TreeLinker,i=LinkedTreeList)=>new i(t).initialize(t.fromArray(e).head);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedTreeList=void 0;var _TreeLinker=require("./TreeLinker"),_TreeLinkerIterator=require("../../recipes/TreeLinkerIterator"),_DoublyLinkedList=require("../doubly-linked-list/DoublyLinkedList");const borrowedGetter=(e,t)=>Object.getOwnPropertyDescriptor(_DoublyLinkedList.DoublyLinkedList.prototype,e).get.call(t);class LinkedTreeList{constructor(e=_TreeLinker.TreeLinker){this.classType=LinkedTreeList,this.innerList=null,this.initialized=!1,this.tailCache=null,this.countCache=null,this.linkerClass=e}initialize(e){return this.initialized?(console.warn("Attempt to initialize LinkedTreeList which is not empty."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return borrowedGetter("first",this)}get last(){return borrowedGetter("last",this)}get length(){return borrowedGetter("length",this)}get parent(){return null===this.first?null:this.first.parent}set parent(e){let t=this.first;for(;null!==t;)t.parent=e,t=t.next;e&&(e.children=this)}get rootParent(){let e=this.first;if(!e)return null;let t=this.first.parent;for(;null!==t;)e=t,t=e.parent;return e}setChildren(e,t=null){Array.from(this).indexOf(e)<0&&console.error("item is not a child of this"),t.parent=e}insertAfter(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this,e,t)}insertBefore(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this,e,t)}append(e,t=this.last){return _DoublyLinkedList.DoublyLinkedList.prototype.append.call(this,e,t)}prepend(e,t=this.first){return _DoublyLinkedList.DoublyLinkedList.prototype.prepend.call(this,e,t)}remove(e){return _DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this,e)}reset(){return _DoublyLinkedList.DoublyLinkedList.prototype.reset.call(this)}item(e){return _DoublyLinkedList.DoublyLinkedList.prototype.item.call(this,e)}forEach(e,t=this){let r=0,i=t.first;for(;null!==i;)e(i,r,t),i=i.next,++r;return t}[Symbol.iterator](){let e=this.rootParent;return new _TreeLinkerIterator.TreeLinkerIterator(e)}}exports.LinkedTreeList=LinkedTreeList,LinkedTreeList.fromArray=(e=[],t=_TreeLinker.TreeLinker,r=LinkedTreeList)=>new r(t).initialize(t.fromArray(e).head);
@@ -1,66 +1,59 @@
1
- /**
2
- * @file queue
3
- * @author Joshua Heagle <joshuaheagle@gmail.com>
4
- * @version 1.1.0
5
- * @memberOf module:collect-your-stuff
6
- */
7
- import { Queueable } from './Queueable';
1
+ import { Linker } from '../linked-list/Linker';
8
2
  import { IsArrayable } from '../../recipes/IsArrayable';
9
- import { IsLinker } from '../../recipes/IsLinker';
10
- import { completeResponse } from '../../recipes/Runnable';
3
+ import { IsQueue } from '../../recipes/IsQueue';
11
4
  /**
12
- * Maintain a series of queued items.
5
+ * A first-in-first-out collection: items are added to the back with enqueue and taken from the front with dequeue.
6
+ * Any value can be queued (it is stored as it is, whether it is a function, an object or null), and adding and taking
7
+ * are constant time. To queue tasks which are run as they are taken use TaskQueue.
13
8
  */
14
- export declare class Queue {
15
- /** The list which stores the queueables, the first is next to be dequeued. */
9
+ export declare class Queue<T = any> implements IsQueue<T>, Iterable<T> {
10
+ /** The list which stores the queued items, the first is next to be dequeued. */
16
11
  queuedList: IsArrayable<any>;
17
- private listClass;
18
- private queueableClass;
12
+ private readonly linkerClass;
19
13
  /**
20
- * Instantiate the queue with the given queue list.
21
- * @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
22
- * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
23
- * @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
14
+ * Instantiate the queue, optionally with a list of items to start from.
15
+ * @param {IsArrayable|null} [queuedList=null] The list of linkers to start in this queue (the first is the front)
16
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
17
+ * @param {Linker} [linkerClass=Linker] The class used to hold each queued item
24
18
  */
25
- constructor(queuedList?: IsArrayable<any>, listClass?: any, queueableClass?: typeof Queueable);
19
+ constructor(queuedList?: IsArrayable<any> | null, listClass?: any, linkerClass?: typeof Linker);
26
20
  /**
27
- * Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
28
- * queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
29
- * completed tasks are discarded.
30
- * @return {completeResponse|*}
21
+ * Take the item from the front of the queue.
22
+ * @return {*|null} The item, or null when the queue is empty
31
23
  */
32
- dequeue(): completeResponse | any;
24
+ dequeue(): T | null;
33
25
  /**
34
- * Return true if the queue is empty (there are no tasks in the queue list)
26
+ * Check whether the queue has no items.
35
27
  * @return {boolean}
36
28
  */
37
29
  empty(): boolean;
38
30
  /**
39
- * Add a queued task to the end of the queue
40
- * @param {Queueable} queueable Add a new queueable to the end of the queue
41
- */
42
- enqueue(queueable: Queueable): void;
43
- /**
44
- * Take a look at the next queued task
45
- * @return {Queueable}
31
+ * Add an item to the back of the queue.
32
+ * @param {*} data The item to add
33
+ * @return {Queue} This queue, so that adding can be chained
46
34
  */
47
- peek(): IsLinker;
35
+ enqueue(data: T): this;
48
36
  /**
49
- * Remove the next queued item and return it.
50
- * @return {Queueable|null}
37
+ * Look at the item at the front of the queue, without removing it.
38
+ * @return {*|null} The item, or null when the queue is empty
51
39
  */
52
- remove(): Queueable | null;
40
+ peek(): T | null;
53
41
  /**
54
- * Get the length of the current queue.
42
+ * Count the items in the queue.
55
43
  * @return {number}
56
44
  */
57
45
  size(): number;
58
46
  /**
59
- * Convert an array to a Queue.
60
- * @param {Array} values An array of values which will be converted to queueables in this queue
61
- * @param {Queueable} queueableClass The class to use for each queueable
62
- * @param {Queue|Iterable} listClass The class to use to manage the queueables
47
+ * Iterate over the items from the front of the queue to the back, without removing them.
48
+ * @return {Iterator}
49
+ */
50
+ [Symbol.iterator](): Iterator<T>;
51
+ /**
52
+ * Convert an array to a Queue, the first value is at the front.
53
+ * @param {Array} [values=[]] The items to queue
54
+ * @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
55
+ * @param {Linker} [linkerClass=Linker] The class used to hold each queued item
63
56
  * @returns {Queue}
64
57
  */
65
- static fromArray: (values?: Array<any>, queueableClass?: typeof Queueable, listClass?: any) => Queue;
58
+ static fromArray: <T_1 = any>(values?: Array<T_1>, listClass?: any, linkerClass?: typeof Linker) => Queue<T_1>;
66
59
  }
@@ -4,81 +4,49 @@ Object.defineProperty(exports, '__esModule', {
4
4
  value: true
5
5
  })
6
6
  exports.Queue = void 0
7
- var _Queueable = require('./Queueable')
7
+ require('core-js/modules/esnext.iterator.constructor.js')
8
+ require('core-js/modules/esnext.iterator.for-each.js')
8
9
  var _LinkedList = require('../linked-list/LinkedList')
10
+ var _Linker = require('../linked-list/Linker')
9
11
  /**
10
12
  * @file queue
11
13
  * @author Joshua Heagle <joshuaheagle@gmail.com>
12
- * @version 1.1.0
14
+ * @version 2.0.0
13
15
  * @memberOf module:collect-your-stuff
14
16
  */
15
17
 
16
18
  /**
17
- * Maintain a series of queued items.
19
+ * A first-in-first-out collection: items are added to the back with enqueue and taken from the front with dequeue.
20
+ * Any value can be queued (it is stored as it is, whether it is a function, an object or null), and adding and taking
21
+ * are constant time. To queue tasks which are run as they are taken use TaskQueue.
18
22
  */
19
23
  class Queue {
20
24
  /**
21
- * Instantiate the queue with the given queue list.
22
- * @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
23
- * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
24
- * @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
25
+ * Instantiate the queue, optionally with a list of items to start from.
26
+ * @param {IsArrayable|null} [queuedList=null] The list of linkers to start in this queue (the first is the front)
27
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
28
+ * @param {Linker} [linkerClass=Linker] The class used to hold each queued item
25
29
  */
26
- constructor (queuedList = null, listClass = _LinkedList.LinkedList, queueableClass = _Queueable.Queueable) {
27
- this.listClass = listClass
28
- this.queueableClass = queueableClass
29
- if (queuedList === null) {
30
- queuedList = new listClass(queueableClass)
31
- }
32
- this.queuedList = queuedList
30
+ constructor (queuedList = null, listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) {
31
+ this.linkerClass = linkerClass
32
+ this.queuedList = queuedList === null ? new listClass(linkerClass) : queuedList
33
33
  }
34
34
 
35
35
  /**
36
- * Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
37
- * queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
38
- * completed tasks are discarded.
39
- * @return {completeResponse|*}
36
+ * Take the item from the front of the queue.
37
+ * @return {*|null} The item, or null when the queue is empty
40
38
  */
41
39
  dequeue () {
42
- let next = this.remove()
43
- // Tasks which already completed are discarded when they reach the front of the queue
44
- while (next && next.complete) {
45
- next = this.remove()
46
- }
47
- if (!next) {
48
- return {
49
- success: 'No more queueable tasks in the queue',
50
- error: false,
51
- context: this.queuedList
52
- }
53
- }
54
- if (next.running) {
55
- // The unfinished task reports back through its own complete callback, so it is not kept in the queue
56
- return {
57
- success: false,
58
- error: 'The queue has been blocked by an unfinished task.',
59
- context: next
60
- }
61
- }
62
- if (!next.isReady) {
63
- // Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
64
- this.enqueue(next)
65
- // We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
66
- // Also, we want the loop handled externally
67
- return {
68
- success: false,
69
- error: 'Unable to find ready task.',
70
- context: next
71
- }
72
- }
73
- if (!this.empty()) {
74
- // Place back in queue to be checked once again next time, only if the queue will not be empty
75
- this.enqueue(next)
40
+ const front = this.queuedList.first
41
+ if (front === null || typeof front === 'undefined') {
42
+ return null
76
43
  }
77
- return next.run.call(next)
44
+ this.queuedList.remove(front)
45
+ return front.data
78
46
  }
79
47
 
80
48
  /**
81
- * Return true if the queue is empty (there are no tasks in the queue list)
49
+ * Check whether the queue has no items.
82
50
  * @return {boolean}
83
51
  */
84
52
  empty () {
@@ -86,50 +54,66 @@ class Queue {
86
54
  }
87
55
 
88
56
  /**
89
- * Add a queued task to the end of the queue
90
- * @param {Queueable} queueable Add a new queueable to the end of the queue
57
+ * Add an item to the back of the queue.
58
+ * @param {*} data The item to add
59
+ * @return {Queue} This queue, so that adding can be chained
91
60
  */
92
- enqueue (queueable) {
93
- this.queuedList.append(queueable)
61
+ enqueue (data) {
62
+ // The item is wrapped here rather than left to the list, since the list treats objects that look like a linker's
63
+ // settings (they have a data property) as such, and a queue must give back exactly what it was given
64
+ this.queuedList.append(new this.linkerClass({
65
+ data
66
+ }))
67
+ return this
94
68
  }
95
69
 
96
70
  /**
97
- * Take a look at the next queued task
98
- * @return {Queueable}
71
+ * Look at the item at the front of the queue, without removing it.
72
+ * @return {*|null} The item, or null when the queue is empty
99
73
  */
100
74
  peek () {
101
- return this.queuedList.first
75
+ const front = this.queuedList.first
76
+ return front === null || typeof front === 'undefined' ? null : front.data
102
77
  }
103
78
 
104
79
  /**
105
- * Remove the next queued item and return it.
106
- * @return {Queueable|null}
80
+ * Count the items in the queue.
81
+ * @return {number}
107
82
  */
108
- remove () {
109
- if (this.empty()) {
110
- return null
111
- }
112
- return this.queuedList.remove(this.queuedList.first)
83
+ size () {
84
+ return this.queuedList.length
113
85
  }
114
86
 
115
87
  /**
116
- * Get the length of the current queue.
117
- * @return {number}
88
+ * Iterate over the items from the front of the queue to the back, without removing them.
89
+ * @return {Iterator}
118
90
  */
119
- size () {
120
- return this.queuedList.length
91
+ [Symbol.iterator] () {
92
+ const linkers = this.queuedList[Symbol.iterator]()
93
+ return {
94
+ next: () => {
95
+ const result = linkers.next()
96
+ return result.done ? {
97
+ done: true,
98
+ value: undefined
99
+ } : {
100
+ done: false,
101
+ value: result.value.data
102
+ }
103
+ }
104
+ }
121
105
  }
122
106
  }
123
107
  /**
124
- * Convert an array to a Queue.
125
- * @param {Array} values An array of values which will be converted to queueables in this queue
126
- * @param {Queueable} queueableClass The class to use for each queueable
127
- * @param {Queue|Iterable} listClass The class to use to manage the queueables
108
+ * Convert an array to a Queue, the first value is at the front.
109
+ * @param {Array} [values=[]] The items to queue
110
+ * @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
111
+ * @param {Linker} [linkerClass=Linker] The class used to hold each queued item
128
112
  * @returns {Queue}
129
113
  */
130
114
  exports.Queue = Queue
131
- Queue.fromArray = (values = [], queueableClass = _Queueable.Queueable, listClass = _LinkedList.LinkedList) => {
132
- const list = new listClass(queueableClass)
133
- list.initialize(queueableClass.fromArray(values, queueableClass).head)
134
- return new Queue(list, listClass, queueableClass)
115
+ Queue.fromArray = (values = [], listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) => {
116
+ const queue = new Queue(null, listClass, linkerClass)
117
+ values.forEach(value => queue.enqueue(value))
118
+ return queue
135
119
  }
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0;var _Queueable=require("./Queueable"),_LinkedList=require("../linked-list/LinkedList");class Queue{constructor(e=null,u=_LinkedList.LinkedList,t=_Queueable.Queueable){this.listClass=u,this.queueableClass=t,null===e&&(e=new u(t)),this.queuedList=e}dequeue(){let e=this.remove();for(;e&&e.complete;)e=this.remove();return e?e.running?{success:!1,error:"The queue has been blocked by an unfinished task.",context:e}:e.isReady?(this.empty()||this.enqueue(e),e.run.call(e)):(this.enqueue(e),{success:!1,error:"Unable to find ready task.",context:e}):{success:"No more queueable tasks in the queue",error:!1,context:this.queuedList}}empty(){return this.size()<=0}enqueue(e){this.queuedList.append(e)}peek(){return this.queuedList.first}remove(){return this.empty()?null:this.queuedList.remove(this.queuedList.first)}size(){return this.queuedList.length}}exports.Queue=Queue,Queue.fromArray=(e=[],u=_Queueable.Queueable,t=_LinkedList.LinkedList)=>{const s=new t(u);return s.initialize(u.fromArray(e,u).head),new Queue(s,t,u)};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _LinkedList=require("../linked-list/LinkedList"),_Linker=require("../linked-list/Linker");class Queue{constructor(e=null,t=_LinkedList.LinkedList,r=_Linker.Linker){this.linkerClass=r,this.queuedList=null===e?new t(r):e}dequeue(){const e=this.queuedList.first;return null==e?null:(this.queuedList.remove(e),e.data)}empty(){return this.size()<=0}enqueue(e){return this.queuedList.append(new this.linkerClass({data:e})),this}peek(){const e=this.queuedList.first;return null==e?null:e.data}size(){return this.queuedList.length}[Symbol.iterator](){const e=this.queuedList[Symbol.iterator]();return{next:()=>{const t=e.next();return t.done?{done:!0,value:void 0}:{done:!1,value:t.value.data}}}}}exports.Queue=Queue,Queue.fromArray=(e=[],t=_LinkedList.LinkedList,r=_Linker.Linker)=>{const u=new Queue(null,t,r);return e.forEach((e=>u.enqueue(e))),u};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @file task queue
3
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
4
+ * @version 1.1.0
5
+ * @memberOf module:collect-your-stuff
6
+ */
7
+ import { Queueable } from './Queueable';
8
+ import { IsArrayable } from '../../recipes/IsArrayable';
9
+ import { IsLinker } from '../../recipes/IsLinker';
10
+ import { completeResponse } from '../../recipes/Runnable';
11
+ /**
12
+ * Maintain a series of queued tasks (Queueables): dequeue() takes the next task from the front and RUNS it, giving each
13
+ * task in turn a chance to run (a task which is not ready, or which has not finished, is placed at the back again).
14
+ * This is a task scheduler, for a plain first-in-first-out collection of items use Queue.
15
+ */
16
+ export declare class TaskQueue {
17
+ /** The list which stores the queueables, the first is next to be dequeued. */
18
+ queuedList: IsArrayable<any>;
19
+ private listClass;
20
+ private queueableClass;
21
+ /**
22
+ * Instantiate the queue with the given queue list.
23
+ * @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
24
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
25
+ * @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
26
+ */
27
+ constructor(queuedList?: IsArrayable<any>, listClass?: any, queueableClass?: typeof Queueable);
28
+ /**
29
+ * Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
30
+ * queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
31
+ * completed tasks are discarded.
32
+ * @return {completeResponse|*}
33
+ */
34
+ dequeue(): completeResponse | any;
35
+ /**
36
+ * Return true if the queue is empty (there are no tasks in the queue list)
37
+ * @return {boolean}
38
+ */
39
+ empty(): boolean;
40
+ /**
41
+ * Add a queued task to the end of the queue
42
+ * @param {Queueable} queueable Add a new queueable to the end of the queue
43
+ */
44
+ enqueue(queueable: Queueable): void;
45
+ /**
46
+ * Take a look at the next queued task
47
+ * @return {Queueable}
48
+ */
49
+ peek(): IsLinker;
50
+ /**
51
+ * Remove the next queued item and return it.
52
+ * @return {Queueable|null}
53
+ */
54
+ remove(): Queueable | null;
55
+ /**
56
+ * Get the length of the current queue.
57
+ * @return {number}
58
+ */
59
+ size(): number;
60
+ /**
61
+ * Convert an array to a TaskQueue.
62
+ * @param {Array} values An array of values which will be converted to queueables in this queue
63
+ * @param {Queueable} queueableClass The class to use for each queueable
64
+ * @param {TaskQueue|Iterable} listClass The class to use to manage the queueables
65
+ * @returns {TaskQueue}
66
+ */
67
+ static fromArray: (values?: Array<any>, queueableClass?: typeof Queueable, listClass?: any) => TaskQueue;
68
+ }
@@ -0,0 +1,137 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ })
6
+ exports.TaskQueue = void 0
7
+ var _Queueable = require('./Queueable')
8
+ var _LinkedList = require('../linked-list/LinkedList')
9
+ /**
10
+ * @file task queue
11
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
12
+ * @version 1.1.0
13
+ * @memberOf module:collect-your-stuff
14
+ */
15
+
16
+ /**
17
+ * Maintain a series of queued tasks (Queueables): dequeue() takes the next task from the front and RUNS it, giving each
18
+ * task in turn a chance to run (a task which is not ready, or which has not finished, is placed at the back again).
19
+ * This is a task scheduler, for a plain first-in-first-out collection of items use Queue.
20
+ */
21
+ class TaskQueue {
22
+ /**
23
+ * Instantiate the queue with the given queue list.
24
+ * @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
25
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
26
+ * @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
27
+ */
28
+ constructor (queuedList = null, listClass = _LinkedList.LinkedList, queueableClass = _Queueable.Queueable) {
29
+ this.listClass = listClass
30
+ this.queueableClass = queueableClass
31
+ if (queuedList === null) {
32
+ queuedList = new listClass(queueableClass)
33
+ }
34
+ this.queuedList = queuedList
35
+ }
36
+
37
+ /**
38
+ * Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
39
+ * queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
40
+ * completed tasks are discarded.
41
+ * @return {completeResponse|*}
42
+ */
43
+ dequeue () {
44
+ let next = this.remove()
45
+ // Tasks which already completed are discarded when they reach the front of the queue
46
+ while (next && next.complete) {
47
+ next = this.remove()
48
+ }
49
+ if (!next) {
50
+ return {
51
+ success: 'No more queueable tasks in the queue',
52
+ error: false,
53
+ context: this.queuedList
54
+ }
55
+ }
56
+ if (next.running) {
57
+ // The unfinished task reports back through its own complete callback, so it is not kept in the queue
58
+ return {
59
+ success: false,
60
+ error: 'The queue has been blocked by an unfinished task.',
61
+ context: next
62
+ }
63
+ }
64
+ if (!next.isReady) {
65
+ // Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
66
+ this.enqueue(next)
67
+ // We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
68
+ // Also, we want the loop handled externally
69
+ return {
70
+ success: false,
71
+ error: 'Unable to find ready task.',
72
+ context: next
73
+ }
74
+ }
75
+ if (!this.empty()) {
76
+ // Place back in queue to be checked once again next time, only if the queue will not be empty
77
+ this.enqueue(next)
78
+ }
79
+ return next.run.call(next)
80
+ }
81
+
82
+ /**
83
+ * Return true if the queue is empty (there are no tasks in the queue list)
84
+ * @return {boolean}
85
+ */
86
+ empty () {
87
+ return this.size() <= 0
88
+ }
89
+
90
+ /**
91
+ * Add a queued task to the end of the queue
92
+ * @param {Queueable} queueable Add a new queueable to the end of the queue
93
+ */
94
+ enqueue (queueable) {
95
+ this.queuedList.append(queueable)
96
+ }
97
+
98
+ /**
99
+ * Take a look at the next queued task
100
+ * @return {Queueable}
101
+ */
102
+ peek () {
103
+ return this.queuedList.first
104
+ }
105
+
106
+ /**
107
+ * Remove the next queued item and return it.
108
+ * @return {Queueable|null}
109
+ */
110
+ remove () {
111
+ if (this.empty()) {
112
+ return null
113
+ }
114
+ return this.queuedList.remove(this.queuedList.first)
115
+ }
116
+
117
+ /**
118
+ * Get the length of the current queue.
119
+ * @return {number}
120
+ */
121
+ size () {
122
+ return this.queuedList.length
123
+ }
124
+ }
125
+ /**
126
+ * Convert an array to a TaskQueue.
127
+ * @param {Array} values An array of values which will be converted to queueables in this queue
128
+ * @param {Queueable} queueableClass The class to use for each queueable
129
+ * @param {TaskQueue|Iterable} listClass The class to use to manage the queueables
130
+ * @returns {TaskQueue}
131
+ */
132
+ exports.TaskQueue = TaskQueue
133
+ TaskQueue.fromArray = (values = [], queueableClass = _Queueable.Queueable, listClass = _LinkedList.LinkedList) => {
134
+ const list = new listClass(queueableClass)
135
+ list.initialize(queueableClass.fromArray(values, queueableClass).head)
136
+ return new TaskQueue(list, listClass, queueableClass)
137
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskQueue=void 0;var _Queueable=require("./Queueable"),_LinkedList=require("../linked-list/LinkedList");class TaskQueue{constructor(e=null,u=_LinkedList.LinkedList,s=_Queueable.Queueable){this.listClass=u,this.queueableClass=s,null===e&&(e=new u(s)),this.queuedList=e}dequeue(){let e=this.remove();for(;e&&e.complete;)e=this.remove();return e?e.running?{success:!1,error:"The queue has been blocked by an unfinished task.",context:e}:e.isReady?(this.empty()||this.enqueue(e),e.run.call(e)):(this.enqueue(e),{success:!1,error:"Unable to find ready task.",context:e}):{success:"No more queueable tasks in the queue",error:!1,context:this.queuedList}}empty(){return this.size()<=0}enqueue(e){this.queuedList.append(e)}peek(){return this.queuedList.first}remove(){return this.empty()?null:this.queuedList.remove(this.queuedList.first)}size(){return this.queuedList.length}}exports.TaskQueue=TaskQueue,TaskQueue.fromArray=(e=[],u=_Queueable.Queueable,s=_LinkedList.LinkedList)=>{const t=new s(u);return t.initialize(u.fromArray(e,u).head),new TaskQueue(t,s,u)};