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 }