github.com/gopherd/gonum@v0.0.4/graph/iterator/lines_map_safe.go (about)

     1  // Copyright ©2021 The Gonum 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  
     5  //go:build safe
     6  // +build safe
     7  
     8  package iterator
     9  
    10  import (
    11  	"reflect"
    12  
    13  	"github.com/gopherd/gonum/graph"
    14  )
    15  
    16  // Lines implements the graph.Lines interfaces.
    17  // The iteration order of Lines is randomized.
    18  type Lines struct {
    19  	lines reflect.Value
    20  	iter  *reflect.MapIter
    21  	pos   int
    22  	curr  graph.Line
    23  }
    24  
    25  // NewLines returns a Lines initialized with the provided lines, a
    26  // map of line IDs to graph.Lines. No check is made that the keys
    27  // match the graph.Line IDs, and the map keys are not used.
    28  //
    29  // Behavior of the Lines is unspecified if lines is mutated after
    30  // the call to NewLines.
    31  func NewLines(lines map[int64]graph.Line) *Lines {
    32  	rv := reflect.ValueOf(lines)
    33  	return &Lines{lines: rv, iter: rv.MapRange()}
    34  }
    35  
    36  // Len returns the remaining number of lines to be iterated over.
    37  func (l *Lines) Len() int {
    38  	return l.lines.Len() - l.pos
    39  }
    40  
    41  // Next returns whether the next call of Line will return a valid line.
    42  func (l *Lines) Next() bool {
    43  	if l.pos >= l.lines.Len() {
    44  		return false
    45  	}
    46  	ok := l.iter.Next()
    47  	if ok {
    48  		l.pos++
    49  		l.curr = l.iter.Value().Interface().(graph.Line)
    50  	}
    51  	return ok
    52  }
    53  
    54  // Line returns the current line of the iterator. Next must have been
    55  // called prior to a call to Line.
    56  func (l *Lines) Line() graph.Line {
    57  	return l.curr
    58  }
    59  
    60  // Reset returns the iterator to its initial state.
    61  func (l *Lines) Reset() {
    62  	l.curr = nil
    63  	l.pos = 0
    64  	l.iter = l.lines.MapRange()
    65  }
    66  
    67  // LineSlice returns all the remaining lines in the iterator and advances
    68  // the iterator. The order of lines within the returned slice is not
    69  // specified.
    70  func (l *Lines) LineSlice() []graph.Line {
    71  	if l.Len() == 0 {
    72  		return nil
    73  	}
    74  	lines := make([]graph.Line, 0, l.Len())
    75  	for l.iter.Next() {
    76  		lines = append(lines, l.iter.Value().Interface().(graph.Line))
    77  	}
    78  	l.pos = l.lines.Len()
    79  	return lines
    80  }
    81  
    82  // WeightedLines implements the graph.WeightedLines interfaces.
    83  // The iteration order of WeightedLines is randomized.
    84  type WeightedLines struct {
    85  	lines reflect.Value
    86  	iter  *reflect.MapIter
    87  	pos   int
    88  	curr  graph.WeightedLine
    89  }
    90  
    91  // NewWeightedLines returns a WeightedLines initialized with the provided lines, a
    92  // map of line IDs to graph.WeightedLines. No check is made that the keys
    93  // match the graph.WeightedLine IDs, and the map keys are not used.
    94  //
    95  // Behavior of the WeightedLines is unspecified if lines is mutated after
    96  // the call to NewWeightedLines.
    97  func NewWeightedLines(lines map[int64]graph.WeightedLine) *WeightedLines {
    98  	rv := reflect.ValueOf(lines)
    99  	return &WeightedLines{lines: rv, iter: rv.MapRange()}
   100  }
   101  
   102  // Len returns the remaining number of lines to be iterated over.
   103  func (l *WeightedLines) Len() int {
   104  	return l.lines.Len() - l.pos
   105  }
   106  
   107  // Next returns whether the next call of WeightedLine will return a valid line.
   108  func (l *WeightedLines) Next() bool {
   109  	if l.pos >= l.lines.Len() {
   110  		return false
   111  	}
   112  	ok := l.iter.Next()
   113  	if ok {
   114  		l.pos++
   115  		l.curr = l.iter.Value().Interface().(graph.WeightedLine)
   116  	}
   117  	return ok
   118  }
   119  
   120  // WeightedLine returns the current line of the iterator. Next must have been
   121  // called prior to a call to WeightedLine.
   122  func (l *WeightedLines) WeightedLine() graph.WeightedLine {
   123  	return l.curr
   124  }
   125  
   126  // Reset returns the iterator to its initial state.
   127  func (l *WeightedLines) Reset() {
   128  	l.curr = nil
   129  	l.pos = 0
   130  	l.iter = l.lines.MapRange()
   131  }
   132  
   133  // WeightedLineSlice returns all the remaining lines in the iterator and advances
   134  // the iterator. The order of lines within the returned slice is not
   135  // specified.
   136  func (l *WeightedLines) WeightedLineSlice() []graph.WeightedLine {
   137  	if l.Len() == 0 {
   138  		return nil
   139  	}
   140  	lines := make([]graph.WeightedLine, 0, l.Len())
   141  	for l.iter.Next() {
   142  		lines = append(lines, l.iter.Value().Interface().(graph.WeightedLine))
   143  	}
   144  	l.pos = l.lines.Len()
   145  	return lines
   146  }