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