1 | 'use strict'
|
2 | module.exports = Yallist
|
3 |
|
4 | Yallist.Node = Node
|
5 | Yallist.create = Yallist
|
6 |
|
7 | function Yallist (list) {
|
8 | var self = this
|
9 | if (!(self instanceof Yallist)) {
|
10 | self = new Yallist()
|
11 | }
|
12 |
|
13 | self.tail = null
|
14 | self.head = null
|
15 | self.length = 0
|
16 |
|
17 | if (list && typeof list.forEach === 'function') {
|
18 | list.forEach(function (item) {
|
19 | self.push(item)
|
20 | })
|
21 | } else if (arguments.length > 0) {
|
22 | for (var i = 0, l = arguments.length; i < l; i++) {
|
23 | self.push(arguments[i])
|
24 | }
|
25 | }
|
26 |
|
27 | return self
|
28 | }
|
29 |
|
30 | Yallist.prototype.removeNode = function (node) {
|
31 | if (node.list !== this) {
|
32 | throw new Error('removing node which does not belong to this list')
|
33 | }
|
34 |
|
35 | var next = node.next
|
36 | var prev = node.prev
|
37 |
|
38 | if (next) {
|
39 | next.prev = prev
|
40 | }
|
41 |
|
42 | if (prev) {
|
43 | prev.next = next
|
44 | }
|
45 |
|
46 | if (node === this.head) {
|
47 | this.head = next
|
48 | }
|
49 | if (node === this.tail) {
|
50 | this.tail = prev
|
51 | }
|
52 |
|
53 | node.list.length--
|
54 | node.next = null
|
55 | node.prev = null
|
56 | node.list = null
|
57 | }
|
58 |
|
59 | Yallist.prototype.unshiftNode = function (node) {
|
60 | if (node === this.head) {
|
61 | return
|
62 | }
|
63 |
|
64 | if (node.list) {
|
65 | node.list.removeNode(node)
|
66 | }
|
67 |
|
68 | var head = this.head
|
69 | node.list = this
|
70 | node.next = head
|
71 | if (head) {
|
72 | head.prev = node
|
73 | }
|
74 |
|
75 | this.head = node
|
76 | if (!this.tail) {
|
77 | this.tail = node
|
78 | }
|
79 | this.length++
|
80 | }
|
81 |
|
82 | Yallist.prototype.pushNode = function (node) {
|
83 | if (node === this.tail) {
|
84 | return
|
85 | }
|
86 |
|
87 | if (node.list) {
|
88 | node.list.removeNode(node)
|
89 | }
|
90 |
|
91 | var tail = this.tail
|
92 | node.list = this
|
93 | node.prev = tail
|
94 | if (tail) {
|
95 | tail.next = node
|
96 | }
|
97 |
|
98 | this.tail = node
|
99 | if (!this.head) {
|
100 | this.head = node
|
101 | }
|
102 | this.length++
|
103 | }
|
104 |
|
105 | Yallist.prototype.push = function () {
|
106 | for (var i = 0, l = arguments.length; i < l; i++) {
|
107 | push(this, arguments[i])
|
108 | }
|
109 | return this.length
|
110 | }
|
111 |
|
112 | Yallist.prototype.unshift = function () {
|
113 | for (var i = 0, l = arguments.length; i < l; i++) {
|
114 | unshift(this, arguments[i])
|
115 | }
|
116 | return this.length
|
117 | }
|
118 |
|
119 | Yallist.prototype.pop = function () {
|
120 | if (!this.tail) {
|
121 | return undefined
|
122 | }
|
123 |
|
124 | var res = this.tail.value
|
125 | this.tail = this.tail.prev
|
126 | if (this.tail) {
|
127 | this.tail.next = null
|
128 | } else {
|
129 | this.head = null
|
130 | }
|
131 | this.length--
|
132 | return res
|
133 | }
|
134 |
|
135 | Yallist.prototype.shift = function () {
|
136 | if (!this.head) {
|
137 | return undefined
|
138 | }
|
139 |
|
140 | var res = this.head.value
|
141 | this.head = this.head.next
|
142 | if (this.head) {
|
143 | this.head.prev = null
|
144 | } else {
|
145 | this.tail = null
|
146 | }
|
147 | this.length--
|
148 | return res
|
149 | }
|
150 |
|
151 | Yallist.prototype.forEach = function (fn, thisp) {
|
152 | thisp = thisp || this
|
153 | for (var walker = this.head, i = 0; walker !== null; i++) {
|
154 | fn.call(thisp, walker.value, i, this)
|
155 | walker = walker.next
|
156 | }
|
157 | }
|
158 |
|
159 | Yallist.prototype.forEachReverse = function (fn, thisp) {
|
160 | thisp = thisp || this
|
161 | for (var walker = this.tail, i = this.length - 1; walker !== null; i--) {
|
162 | fn.call(thisp, walker.value, i, this)
|
163 | walker = walker.prev
|
164 | }
|
165 | }
|
166 |
|
167 | Yallist.prototype.get = function (n) {
|
168 | for (var i = 0, walker = this.head; walker !== null && i < n; i++) {
|
169 |
|
170 | walker = walker.next
|
171 | }
|
172 | if (i === n && walker !== null) {
|
173 | return walker.value
|
174 | }
|
175 | }
|
176 |
|
177 | Yallist.prototype.getReverse = function (n) {
|
178 | for (var i = 0, walker = this.tail; walker !== null && i < n; i++) {
|
179 |
|
180 | walker = walker.prev
|
181 | }
|
182 | if (i === n && walker !== null) {
|
183 | return walker.value
|
184 | }
|
185 | }
|
186 |
|
187 | Yallist.prototype.map = function (fn, thisp) {
|
188 | thisp = thisp || this
|
189 | var res = new Yallist()
|
190 | for (var walker = this.head; walker !== null;) {
|
191 | res.push(fn.call(thisp, walker.value, this))
|
192 | walker = walker.next
|
193 | }
|
194 | return res
|
195 | }
|
196 |
|
197 | Yallist.prototype.mapReverse = function (fn, thisp) {
|
198 | thisp = thisp || this
|
199 | var res = new Yallist()
|
200 | for (var walker = this.tail; walker !== null;) {
|
201 | res.push(fn.call(thisp, walker.value, this))
|
202 | walker = walker.prev
|
203 | }
|
204 | return res
|
205 | }
|
206 |
|
207 | Yallist.prototype.reduce = function (fn, initial) {
|
208 | var acc
|
209 | var walker = this.head
|
210 | if (arguments.length > 1) {
|
211 | acc = initial
|
212 | } else if (this.head) {
|
213 | walker = this.head.next
|
214 | acc = this.head.value
|
215 | } else {
|
216 | throw new TypeError('Reduce of empty list with no initial value')
|
217 | }
|
218 |
|
219 | for (var i = 0; walker !== null; i++) {
|
220 | acc = fn(acc, walker.value, i)
|
221 | walker = walker.next
|
222 | }
|
223 |
|
224 | return acc
|
225 | }
|
226 |
|
227 | Yallist.prototype.reduceReverse = function (fn, initial) {
|
228 | var acc
|
229 | var walker = this.tail
|
230 | if (arguments.length > 1) {
|
231 | acc = initial
|
232 | } else if (this.tail) {
|
233 | walker = this.tail.prev
|
234 | acc = this.tail.value
|
235 | } else {
|
236 | throw new TypeError('Reduce of empty list with no initial value')
|
237 | }
|
238 |
|
239 | for (var i = this.length - 1; walker !== null; i--) {
|
240 | acc = fn(acc, walker.value, i)
|
241 | walker = walker.prev
|
242 | }
|
243 |
|
244 | return acc
|
245 | }
|
246 |
|
247 | Yallist.prototype.toArray = function () {
|
248 | var arr = new Array(this.length)
|
249 | for (var i = 0, walker = this.head; walker !== null; i++) {
|
250 | arr[i] = walker.value
|
251 | walker = walker.next
|
252 | }
|
253 | return arr
|
254 | }
|
255 |
|
256 | Yallist.prototype.toArrayReverse = function () {
|
257 | var arr = new Array(this.length)
|
258 | for (var i = 0, walker = this.tail; walker !== null; i++) {
|
259 | arr[i] = walker.value
|
260 | walker = walker.prev
|
261 | }
|
262 | return arr
|
263 | }
|
264 |
|
265 | Yallist.prototype.slice = function (from, to) {
|
266 | to = to || this.length
|
267 | if (to < 0) {
|
268 | to += this.length
|
269 | }
|
270 | from = from || 0
|
271 | if (from < 0) {
|
272 | from += this.length
|
273 | }
|
274 | var ret = new Yallist()
|
275 | if (to < from || to < 0) {
|
276 | return ret
|
277 | }
|
278 | if (from < 0) {
|
279 | from = 0
|
280 | }
|
281 | if (to > this.length) {
|
282 | to = this.length
|
283 | }
|
284 | for (var i = 0, walker = this.head; walker !== null && i < from; i++) {
|
285 | walker = walker.next
|
286 | }
|
287 | for (; walker !== null && i < to; i++, walker = walker.next) {
|
288 | ret.push(walker.value)
|
289 | }
|
290 | return ret
|
291 | }
|
292 |
|
293 | Yallist.prototype.sliceReverse = function (from, to) {
|
294 | to = to || this.length
|
295 | if (to < 0) {
|
296 | to += this.length
|
297 | }
|
298 | from = from || 0
|
299 | if (from < 0) {
|
300 | from += this.length
|
301 | }
|
302 | var ret = new Yallist()
|
303 | if (to < from || to < 0) {
|
304 | return ret
|
305 | }
|
306 | if (from < 0) {
|
307 | from = 0
|
308 | }
|
309 | if (to > this.length) {
|
310 | to = this.length
|
311 | }
|
312 | for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) {
|
313 | walker = walker.prev
|
314 | }
|
315 | for (; walker !== null && i > from; i--, walker = walker.prev) {
|
316 | ret.push(walker.value)
|
317 | }
|
318 | return ret
|
319 | }
|
320 |
|
321 | Yallist.prototype.reverse = function () {
|
322 | var head = this.head
|
323 | var tail = this.tail
|
324 | for (var walker = head; walker !== null; walker = walker.prev) {
|
325 | var p = walker.prev
|
326 | walker.prev = walker.next
|
327 | walker.next = p
|
328 | }
|
329 | this.head = tail
|
330 | this.tail = head
|
331 | return this
|
332 | }
|
333 |
|
334 | function push (self, item) {
|
335 | self.tail = new Node(item, self.tail, null, self)
|
336 | if (!self.head) {
|
337 | self.head = self.tail
|
338 | }
|
339 | self.length++
|
340 | }
|
341 |
|
342 | function unshift (self, item) {
|
343 | self.head = new Node(item, null, self.head, self)
|
344 | if (!self.tail) {
|
345 | self.tail = self.head
|
346 | }
|
347 | self.length++
|
348 | }
|
349 |
|
350 | function Node (value, prev, next, list) {
|
351 | if (!(this instanceof Node)) {
|
352 | return new Node(value, prev, next, list)
|
353 | }
|
354 |
|
355 | this.list = list
|
356 | this.value = value
|
357 |
|
358 | if (prev) {
|
359 | prev.next = this
|
360 | this.prev = prev
|
361 | } else {
|
362 | this.prev = null
|
363 | }
|
364 |
|
365 | if (next) {
|
366 | next.prev = this
|
367 | this.next = next
|
368 | } else {
|
369 | this.next = null
|
370 | }
|
371 | }
|
372 |
|
373 | try {
|
374 |
|
375 | require('./iterator.js')(Yallist)
|
376 | } catch (er) {}
|