| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package ring implements operations on circular lists. |
| package ring |
| |
| // A Ring is an element of a circular list, or ring. |
| // Rings do not have a beginning or end; a pointer to any ring element |
| // serves as reference to the entire ring. Empty rings are represented |
| // as nil Ring pointers. The zero value for a Ring is a one-element |
| // ring with a nil Value. |
| type Ring struct { |
| next, prev *Ring |
| Value any // for use by client; untouched by this library |
| } |
| |
| func (r *Ring) init() *Ring { |
| r.next = r |
| r.prev = r |
| return r |
| } |
| |
| // Next returns the next ring element. r must not be empty. |
| func (r *Ring) Next() *Ring { |
| if r.next == nil { |
| return r.init() |
| } |
| return r.next |
| } |
| |
| // Prev returns the previous ring element. r must not be empty. |
| func (r *Ring) Prev() *Ring { |
| if r.next == nil { |
| return r.init() |
| } |
| return r.prev |
| } |
| |
| // Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0) |
| // in the ring and returns that ring element. r must not be empty. |
| func (r *Ring) Move(n int) *Ring { |
| if r.next == nil { |
| return r.init() |
| } |
| switch { |
| case n < 0: |
| for ; n < 0; n++ { |
| r = r.prev |
| } |
| case n > 0: |
| for ; n > 0; n-- { |
| r = r.next |
| } |
| } |
| return r |
| } |
| |
| // New creates a ring of n elements. |
| func New(n int) *Ring { |
| if n <= 0 { |
| return nil |
| } |
| r := new(Ring) |
| p := r |
| for i := 1; i < n; i++ { |
| p.next = &Ring{prev: p} |
| p = p.next |
| } |
| p.next = r |
| r.prev = p |
| return r |
| } |
| |
| // Link connects ring r with ring s such that r.Next() |
| // becomes s and returns the original value for r.Next(). |
| // r must not be empty. |
| // |
| // If r and s point to the same ring, linking |
| // them removes the elements between r and s from the ring. |
| // The removed elements form a subring and the result is a |
| // reference to that subring (if no elements were removed, |
| // the result is still the original value for r.Next(), |
| // and not nil). |
| // |
| // If r and s point to different rings, linking |
| // them creates a single ring with the elements of s inserted |
| // after r. The result points to the element following the |
| // last element of s after insertion. |
| func (r *Ring) Link(s *Ring) *Ring { |
| n := r.Next() |
| if s != nil { |
| p := s.Prev() |
| // Note: Cannot use multiple assignment because |
| // evaluation order of LHS is not specified. |
| r.next = s |
| s.prev = r |
| n.prev = p |
| p.next = n |
| } |
| return n |
| } |
| |
| // Unlink removes n % r.Len() elements from the ring r, starting |
| // at r.Next(). If n % r.Len() == 0, r remains unchanged. |
| // The result is the removed subring. r must not be empty. |
| func (r *Ring) Unlink(n int) *Ring { |
| if n <= 0 { |
| return nil |
| } |
| return r.Link(r.Move(n + 1)) |
| } |
| |
| // Len computes the number of elements in ring r. |
| // It executes in time proportional to the number of elements. |
| func (r *Ring) Len() int { |
| n := 0 |
| if r != nil { |
| n = 1 |
| for p := r.Next(); p != r; p = p.next { |
| n++ |
| } |
| } |
| return n |
| } |
| |
| // Do calls function f on each element of the ring, in forward order. |
| // The behavior of Do is undefined if f changes *r. |
| func (r *Ring) Do(f func(any)) { |
| if r != nil { |
| f(r.Value) |
| for p := r.Next(); p != r; p = p.next { |
| f(p.Value) |
| } |
| } |
| } |