-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
115 lines (101 loc) · 2.25 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict'
module.exports = class LoopQueue {
//
constructor (loops, capacity, hash) {
if (typeof hash === 'function') {
this._hash = hash
} else if (typeof capacity === 'function') {
this._hash = capacity
capacity = false
} else if (typeof loops === 'function') {
this._hash = loops
loops = capacity = false
} else {
this._hash = item => item
}
this._loops = loops > 0 && loops
this._capacity = capacity > 0 && capacity
this._map = new Map()
this._it = null
}
get length () {
return this._map.size
}
get (hash) {
const map = this._map
if (map.has(hash)) {
return map.get(hash).item
}
}
[Symbol.iterator] () {
return makeIter(this._map)
}
values () {
return makeIter(this._map)
}
remove (hash) {
return this._map.delete(hash)
}
clear () {
this._map.clear()
}
push (item) {
if (item !== undefined) {
if (this._capacity && this._capacity <= this.length) {
this.shift()
}
const hash = this._hash(item)
this._map.set(hash, { item, count: 0 })
return hash
}
}
shift () {
const map = this._map
const next = map.keys().next()
if (!next.done) {
const item = map.get(next.value).item
this._map.delete(next.value)
return item
}
}
next (remove) {
if (this.length < 1) return
let next = null
let it = this._it
const map = this._map
const limit = this._loops
if (it) {
next = it.next()
if (next.done) {
it = this._it = map.keys()
next = it.next()
}
} else {
it = this._it = map.keys()
next = it.next()
}
const value = map.get(next.value)
if (typeof remove === 'function') {
if (remove(value.item)) {
this._map.delete(next.value)
}
} else if (remove || (limit && ++value.count >= limit)) {
this._map.delete(next.value)
}
return value.item
}
}
function makeIter (map) {
if (map.size > 0) {
const internalIt = map.values()
return {
next: () => {
const { value, done } = internalIt.next()
return { value: value && value.item, done }
}
}
}
return {
next: () => ({ value: undefined, done: true })
}
}