mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
8.1 KiB
301 lines
8.1 KiB
5 years ago
|
// Copyright ©2018 The Gonum 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 graph
|
||
|
|
||
|
// Iterator is an item iterator.
|
||
|
type Iterator interface {
|
||
|
// Next advances the iterator and returns whether
|
||
|
// the next call to the item method will return a
|
||
|
// non-nil item.
|
||
|
//
|
||
|
// Next should be called prior to any call to the
|
||
|
// iterator's item retrieval method after the
|
||
|
// iterator has been obtained or reset.
|
||
|
//
|
||
|
// The order of iteration is implementation
|
||
|
// dependent.
|
||
|
Next() bool
|
||
|
|
||
|
// Len returns the number of items remaining in the
|
||
|
// iterator.
|
||
|
//
|
||
|
// If the number of items in the iterator is unknown,
|
||
|
// too large to materialize or too costly to calculate
|
||
|
// then Len may return a negative value.
|
||
|
// In this case the consuming function must be able
|
||
|
// to operate on the items of the iterator directly
|
||
|
// without materializing the items into a slice.
|
||
|
// The magnitude of a negative length has
|
||
|
// implementation-dependent semantics.
|
||
|
Len() int
|
||
|
|
||
|
// Reset returns the iterator to its start position.
|
||
|
Reset()
|
||
|
}
|
||
|
|
||
|
// Nodes is a Node iterator.
|
||
|
type Nodes interface {
|
||
|
Iterator
|
||
|
|
||
|
// Node returns the current Node from the iterator.
|
||
|
Node() Node
|
||
|
}
|
||
|
|
||
|
// NodeSlicer wraps the NodeSlice method.
|
||
|
type NodeSlicer interface {
|
||
|
// NodeSlice returns the set of nodes remaining
|
||
|
// to be iterated by a Nodes iterator.
|
||
|
// The holder of the iterator may arbitrarily
|
||
|
// change elements in the returned slice, but
|
||
|
// those changes may be reflected to other
|
||
|
// iterators.
|
||
|
NodeSlice() []Node
|
||
|
}
|
||
|
|
||
|
// NodesOf returns it.Len() nodes from it. If it is a NodeSlicer, the NodeSlice method
|
||
|
// is used to obtain the nodes. It is safe to pass a nil Nodes to NodesOf.
|
||
|
//
|
||
|
// If the Nodes has an indeterminate length, NodesOf will panic.
|
||
|
func NodesOf(it Nodes) []Node {
|
||
|
if it == nil {
|
||
|
return nil
|
||
|
}
|
||
|
len := it.Len()
|
||
|
switch {
|
||
|
case len == 0:
|
||
|
return nil
|
||
|
case len < 0:
|
||
|
panic("graph: called NodesOf on indeterminate iterator")
|
||
|
}
|
||
|
switch it := it.(type) {
|
||
|
case NodeSlicer:
|
||
|
return it.NodeSlice()
|
||
|
}
|
||
|
n := make([]Node, 0, len)
|
||
|
for it.Next() {
|
||
|
n = append(n, it.Node())
|
||
|
}
|
||
|
return n
|
||
|
}
|
||
|
|
||
|
// Edges is an Edge iterator.
|
||
|
type Edges interface {
|
||
|
Iterator
|
||
|
|
||
|
// Edge returns the current Edge from the iterator.
|
||
|
Edge() Edge
|
||
|
}
|
||
|
|
||
|
// EdgeSlicer wraps the EdgeSlice method.
|
||
|
type EdgeSlicer interface {
|
||
|
// EdgeSlice returns the set of edges remaining
|
||
|
// to be iterated by an Edges iterator.
|
||
|
// The holder of the iterator may arbitrarily
|
||
|
// change elements in the returned slice, but
|
||
|
// those changes may be reflected to other
|
||
|
// iterators.
|
||
|
EdgeSlice() []Edge
|
||
|
}
|
||
|
|
||
|
// EdgesOf returns it.Len() nodes from it. If it is an EdgeSlicer, the EdgeSlice method is used
|
||
|
// to obtain the edges. It is safe to pass a nil Edges to EdgesOf.
|
||
|
//
|
||
|
// If the Edges has an indeterminate length, EdgesOf will panic.
|
||
|
func EdgesOf(it Edges) []Edge {
|
||
|
if it == nil {
|
||
|
return nil
|
||
|
}
|
||
|
len := it.Len()
|
||
|
switch {
|
||
|
case len == 0:
|
||
|
return nil
|
||
|
case len < 0:
|
||
|
panic("graph: called EdgesOf on indeterminate iterator")
|
||
|
}
|
||
|
switch it := it.(type) {
|
||
|
case EdgeSlicer:
|
||
|
return it.EdgeSlice()
|
||
|
}
|
||
|
e := make([]Edge, 0, len)
|
||
|
for it.Next() {
|
||
|
e = append(e, it.Edge())
|
||
|
}
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// WeightedEdges is a WeightedEdge iterator.
|
||
|
type WeightedEdges interface {
|
||
|
Iterator
|
||
|
|
||
|
// Edge returns the current Edge from the iterator.
|
||
|
WeightedEdge() WeightedEdge
|
||
|
}
|
||
|
|
||
|
// WeightedEdgeSlicer wraps the WeightedEdgeSlice method.
|
||
|
type WeightedEdgeSlicer interface {
|
||
|
// EdgeSlice returns the set of edges remaining
|
||
|
// to be iterated by an Edges iterator.
|
||
|
// The holder of the iterator may arbitrarily
|
||
|
// change elements in the returned slice, but
|
||
|
// those changes may be reflected to other
|
||
|
// iterators.
|
||
|
WeightedEdgeSlice() []WeightedEdge
|
||
|
}
|
||
|
|
||
|
// WeightedEdgesOf returns it.Len() weighted edge from it. If it is a WeightedEdgeSlicer, the
|
||
|
// WeightedEdgeSlice method is used to obtain the edges. It is safe to pass a nil WeightedEdges
|
||
|
// to WeightedEdgesOf.
|
||
|
//
|
||
|
// If the WeightedEdges has an indeterminate length, WeightedEdgesOf will panic.
|
||
|
func WeightedEdgesOf(it WeightedEdges) []WeightedEdge {
|
||
|
if it == nil {
|
||
|
return nil
|
||
|
}
|
||
|
len := it.Len()
|
||
|
switch {
|
||
|
case len == 0:
|
||
|
return nil
|
||
|
case len < 0:
|
||
|
panic("graph: called WeightedEdgesOf on indeterminate iterator")
|
||
|
}
|
||
|
switch it := it.(type) {
|
||
|
case WeightedEdgeSlicer:
|
||
|
return it.WeightedEdgeSlice()
|
||
|
}
|
||
|
e := make([]WeightedEdge, 0, len)
|
||
|
for it.Next() {
|
||
|
e = append(e, it.WeightedEdge())
|
||
|
}
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// Lines is a Line iterator.
|
||
|
type Lines interface {
|
||
|
Iterator
|
||
|
|
||
|
// Line returns the current Line from the iterator.
|
||
|
Line() Line
|
||
|
}
|
||
|
|
||
|
// LineSlicer wraps the LineSlice method.
|
||
|
type LineSlicer interface {
|
||
|
// LineSlice returns the set of lines remaining
|
||
|
// to be iterated by an Lines iterator.
|
||
|
// The holder of the iterator may arbitrarily
|
||
|
// change elements in the returned slice, but
|
||
|
// those changes may be reflected to other
|
||
|
// iterators.
|
||
|
LineSlice() []Line
|
||
|
}
|
||
|
|
||
|
// LinesOf returns it.Len() nodes from it. If it is a LineSlicer, the LineSlice method is used
|
||
|
// to obtain the lines. It is safe to pass a nil Lines to LinesOf.
|
||
|
//
|
||
|
// If the Lines has an indeterminate length, LinesOf will panic.
|
||
|
func LinesOf(it Lines) []Line {
|
||
|
if it == nil {
|
||
|
return nil
|
||
|
}
|
||
|
len := it.Len()
|
||
|
switch {
|
||
|
case len == 0:
|
||
|
return nil
|
||
|
case len < 0:
|
||
|
panic("graph: called LinesOf on indeterminate iterator")
|
||
|
}
|
||
|
switch it := it.(type) {
|
||
|
case LineSlicer:
|
||
|
return it.LineSlice()
|
||
|
}
|
||
|
l := make([]Line, 0, len)
|
||
|
for it.Next() {
|
||
|
l = append(l, it.Line())
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// WeightedLines is a WeightedLine iterator.
|
||
|
type WeightedLines interface {
|
||
|
Iterator
|
||
|
|
||
|
// Line returns the current Line from the iterator.
|
||
|
WeightedLine() WeightedLine
|
||
|
}
|
||
|
|
||
|
// WeightedLineSlicer wraps the WeightedLineSlice method.
|
||
|
type WeightedLineSlicer interface {
|
||
|
// LineSlice returns the set of lines remaining
|
||
|
// to be iterated by an Lines iterator.
|
||
|
// The holder of the iterator may arbitrarily
|
||
|
// change elements in the returned slice, but
|
||
|
// those changes may be reflected to other
|
||
|
// iterators.
|
||
|
WeightedLineSlice() []WeightedLine
|
||
|
}
|
||
|
|
||
|
// WeightedLinesOf returns it.Len() weighted line from it. If it is a WeightedLineSlicer, the
|
||
|
// WeightedLineSlice method is used to obtain the lines. It is safe to pass a nil WeightedLines
|
||
|
// to WeightedLinesOf.
|
||
|
//
|
||
|
// If the WeightedLines has an indeterminate length, WeightedLinesOf will panic.
|
||
|
func WeightedLinesOf(it WeightedLines) []WeightedLine {
|
||
|
if it == nil {
|
||
|
return nil
|
||
|
}
|
||
|
len := it.Len()
|
||
|
switch {
|
||
|
case len == 0:
|
||
|
return nil
|
||
|
case len < 0:
|
||
|
panic("graph: called WeightedLinesOf on indeterminate iterator")
|
||
|
}
|
||
|
switch it := it.(type) {
|
||
|
case WeightedLineSlicer:
|
||
|
return it.WeightedLineSlice()
|
||
|
}
|
||
|
l := make([]WeightedLine, 0, len)
|
||
|
for it.Next() {
|
||
|
l = append(l, it.WeightedLine())
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// Empty is an empty set of nodes, edges or lines. It should be used when
|
||
|
// a graph returns a zero-length Iterator. Empty implements the slicer
|
||
|
// interfaces for nodes, edges and lines, returning nil for each of these.
|
||
|
const Empty = nothing
|
||
|
|
||
|
var (
|
||
|
_ Iterator = Empty
|
||
|
_ Nodes = Empty
|
||
|
_ NodeSlicer = Empty
|
||
|
_ Edges = Empty
|
||
|
_ EdgeSlicer = Empty
|
||
|
_ WeightedEdges = Empty
|
||
|
_ WeightedEdgeSlicer = Empty
|
||
|
_ Lines = Empty
|
||
|
_ LineSlicer = Empty
|
||
|
_ WeightedLines = Empty
|
||
|
_ WeightedLineSlicer = Empty
|
||
|
)
|
||
|
|
||
|
const nothing = empty(true)
|
||
|
|
||
|
type empty bool
|
||
|
|
||
|
func (empty) Next() bool { return false }
|
||
|
func (empty) Len() int { return 0 }
|
||
|
func (empty) Reset() {}
|
||
|
func (empty) Node() Node { return nil }
|
||
|
func (empty) NodeSlice() []Node { return nil }
|
||
|
func (empty) Edge() Edge { return nil }
|
||
|
func (empty) EdgeSlice() []Edge { return nil }
|
||
|
func (empty) WeightedEdge() WeightedEdge { return nil }
|
||
|
func (empty) WeightedEdgeSlice() []WeightedEdge { return nil }
|
||
|
func (empty) Line() Line { return nil }
|
||
|
func (empty) LineSlice() []Line { return nil }
|
||
|
func (empty) WeightedLine() WeightedLine { return nil }
|
||
|
func (empty) WeightedLineSlice() []WeightedLine { return nil }
|