summaryrefslogtreecommitdiffstats
path: root/src/queue.js
blob: abcfb84ceaa0a46f210d0c0f8035f1a919873451 (plain)
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
SVG.Queue = SVG.invent({
  create: function () {
    this._first = null
    this._last = null
    this.length = 0
    this.id = 0
  },

  extend: {
    push: function (value) {

      // An item stores an id and the provided value
      var item = { id: this.id++, value: value }

      // Deal with the queue being empty or populated
      if (this._last) {
        this._last = this._last.next = item
      } else {
        this._last = this._first = item
      }

      this.length++
    },

    shift: function () {
      if (this.length == 0) {
        return
      }

      var remove = this._first
      this._first = remove.next
      this._last = --this.length ? this._last : null
      return remove.value
    },

    // Shows us the first item in the list
    first: function () {
      return this._first && this._first.value
    },

    // Shows us the last item in the list
    last: function () {
      return this._last && this._last.value
    },

    // Removes the first item from the front where matcher returns true
    remove: function (matcher) {
      // Find the first match
      var previous = null
      var current = this._first
      while (current) {

        // If we have a match, we are done
        if (matcher(current)) break

        // Otherwise, advance both of the pointers
        previous = current
        current = current.next
      }

      // If we got the first item, adjust the first pointer
      if (current && current === this._first)
        this._first = this._first.next

      // If we got the last item, adjust the last pointer
      if (current && current === this._last)
        this._last = previous

      // If we got an item, fix the list and return the item
      if (current) {
        --this.length

        if (previous) {
          previous.next = current.next
        }

        return current.item
      }
    }
  }
})