Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 1 | // Copyright 2009 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Nigel Tao | 6a186d3 | 2011-04-20 09:57:05 +1000 | [diff] [blame] | 5 | // Package ring implements operations on circular lists. |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 6 | package ring |
| 7 | |
| 8 | // A Ring is an element of a circular list, or ring. |
| 9 | // Rings do not have a beginning or end; a pointer to any ring element |
| 10 | // serves as reference to the entire ring. Empty rings are represented |
| 11 | // as nil Ring pointers. The zero value for a Ring is a one-element |
| 12 | // ring with a nil Value. |
| 13 | // |
| 14 | type Ring struct { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 15 | next, prev *Ring |
| 16 | Value interface{} // for use by client; untouched by this library |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 17 | } |
| 18 | |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 19 | func (r *Ring) init() *Ring { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 20 | r.next = r |
| 21 | r.prev = r |
| 22 | return r |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 23 | } |
| 24 | |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 25 | // Next returns the next ring element. r must not be empty. |
| 26 | func (r *Ring) Next() *Ring { |
| 27 | if r.next == nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 28 | return r.init() |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 29 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 30 | return r.next |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 31 | } |
| 32 | |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 33 | // Prev returns the previous ring element. r must not be empty. |
| 34 | func (r *Ring) Prev() *Ring { |
| 35 | if r.next == nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 36 | return r.init() |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 37 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 38 | return r.prev |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Robert Griesemer | d27bae5 | 2009-07-28 15:03:05 -0700 | [diff] [blame] | 41 | // Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0) |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 42 | // in the ring and returns that ring element. r must not be empty. |
| 43 | // |
| 44 | func (r *Ring) Move(n int) *Ring { |
| 45 | if r.next == nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 46 | return r.init() |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 47 | } |
| 48 | switch { |
| 49 | case n < 0: |
| 50 | for ; n < 0; n++ { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 51 | r = r.prev |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 52 | } |
| 53 | case n > 0: |
| 54 | for ; n > 0; n-- { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 55 | r = r.next |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 56 | } |
| 57 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 58 | return r |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 59 | } |
| 60 | |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 61 | // New creates a ring of n elements. |
| 62 | func New(n int) *Ring { |
| 63 | if n <= 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 64 | return nil |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 65 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 66 | r := new(Ring) |
| 67 | p := r |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 68 | for i := 1; i < n; i++ { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 69 | p.next = &Ring{prev: p} |
| 70 | p = p.next |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 71 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 72 | p.next = r |
| 73 | r.prev = p |
| 74 | return r |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 75 | } |
| 76 | |
Shenghou Ma | 42c8904 | 2012-11-22 02:58:24 +0800 | [diff] [blame] | 77 | // Link connects ring r with ring s such that r.Next() |
Robert Griesemer | d27bae5 | 2009-07-28 15:03:05 -0700 | [diff] [blame] | 78 | // becomes s and returns the original value for r.Next(). |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 79 | // r must not be empty. |
| 80 | // |
| 81 | // If r and s point to the same ring, linking |
| 82 | // them removes the elements between r and s from the ring. |
| 83 | // The removed elements form a subring and the result is a |
| 84 | // reference to that subring (if no elements were removed, |
Robert Griesemer | d27bae5 | 2009-07-28 15:03:05 -0700 | [diff] [blame] | 85 | // the result is still the original value for r.Next(), |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 86 | // and not nil). |
| 87 | // |
| 88 | // If r and s point to different rings, linking |
| 89 | // them creates a single ring with the elements of s inserted |
| 90 | // after r. The result points to the element following the |
| 91 | // last element of s after insertion. |
| 92 | // |
| 93 | func (r *Ring) Link(s *Ring) *Ring { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 94 | n := r.Next() |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 95 | if s != nil { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 96 | p := s.Prev() |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 97 | // Note: Cannot use multiple assignment because |
| 98 | // evaluation order of LHS is not specified. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 99 | r.next = s |
| 100 | s.prev = r |
| 101 | n.prev = p |
| 102 | p.next = n |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 103 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 104 | return n |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 105 | } |
| 106 | |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 107 | // Unlink removes n % r.Len() elements from the ring r, starting |
| 108 | // at r.Next(). If n % r.Len() == 0, r remains unchanged. |
| 109 | // The result is the removed subring. r must not be empty. |
| 110 | // |
| 111 | func (r *Ring) Unlink(n int) *Ring { |
| 112 | if n <= 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 113 | return nil |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 114 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 115 | return r.Link(r.Move(n + 1)) |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 116 | } |
| 117 | |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 118 | // Len computes the number of elements in ring r. |
| 119 | // It executes in time proportional to the number of elements. |
| 120 | // |
| 121 | func (r *Ring) Len() int { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 122 | n := 0 |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 123 | if r != nil { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 124 | n = 1 |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 125 | for p := r.Next(); p != r; p = p.next { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 126 | n++ |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 127 | } |
| 128 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 129 | return n |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 130 | } |
| 131 | |
Kyle Consalus | 3629d72 | 2011-02-08 20:07:05 -0800 | [diff] [blame] | 132 | // Do calls function f on each element of the ring, in forward order. |
| 133 | // The behavior of Do is undefined if f changes *r. |
| 134 | func (r *Ring) Do(f func(interface{})) { |
| 135 | if r != nil { |
| 136 | f(r.Value) |
| 137 | for p := r.Next(); p != r; p = p.next { |
| 138 | f(p.Value) |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 139 | } |
Kyle Consalus | 3629d72 | 2011-02-08 20:07:05 -0800 | [diff] [blame] | 140 | } |
Robert Griesemer | 6d3d25d | 2009-07-28 14:54:49 -0700 | [diff] [blame] | 141 | } |