github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/iterator/map.go (about) 1 // Copyright ©2020 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 // Copyright 2009 The Go Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 9 // +build !safe 10 11 package iterator 12 13 import ( 14 "unsafe" 15 16 "github.com/jingcheng-WU/gonum/graph" 17 ) 18 19 // A mapIter is an iterator for ranging over a map. 20 type mapIter struct { 21 m *emptyInterface 22 it unsafe.Pointer 23 } 24 25 type emptyInterface struct { 26 typ, word unsafe.Pointer 27 } 28 29 // newMapIterNodes returns a range iterator for a map of nodes. 30 func newMapIterNodes(m map[int64]graph.Node) *mapIter { 31 return &mapIter{m: eface(m)} 32 } 33 34 // newMapIterEdges returns a range iterator for a map of edges. 35 // The returned mapIter must not have its node method called. 36 func newMapIterEdges(m map[int64]graph.Edge) *mapIter { 37 return &mapIter{m: eface(m)} 38 } 39 40 // newMapIterWeightedEdges returns a range iterator for a map of edges. 41 // The returned mapIter must not have its node method called. 42 func newMapIterWeightedEdges(m map[int64]graph.WeightedEdge) *mapIter { 43 return &mapIter{m: eface(m)} 44 } 45 46 // newMapIterLines returns a range iterator for a map of edges. 47 // The returned mapIter must not have its node method called. 48 func newMapIterLines(m map[int64]map[int64]graph.Line) *mapIter { 49 return &mapIter{m: eface(m)} 50 } 51 52 // newMapIterWeightedLines returns a range iterator for a map of edges. 53 // The returned mapIter must not have its node method called. 54 func newMapIterWeightedLines(m map[int64]map[int64]graph.WeightedLine) *mapIter { 55 return &mapIter{m: eface(m)} 56 } 57 58 func eface(i interface{}) *emptyInterface { 59 return (*emptyInterface)(unsafe.Pointer(&i)) 60 } 61 62 // id returns the key of the iterator's current map entry. 63 func (it *mapIter) id() int64 { 64 if it.it == nil { 65 panic("mapIter.id called before Next") 66 } 67 if mapiterkey(it.it) == nil { 68 panic("mapIter.id called on exhausted iterator") 69 } 70 return *(*int64)(mapiterkey(it.it)) 71 } 72 73 // node returns the value of the iterator's current map entry. 74 func (it *mapIter) node() graph.Node { 75 if it.it == nil { 76 panic("mapIter.node called before next") 77 } 78 if mapiterkey(it.it) == nil { 79 panic("mapIter.node called on exhausted iterator") 80 } 81 return *(*graph.Node)(mapiterelem(it.it)) 82 } 83 84 // next advances the map iterator and reports whether there is another 85 // entry. It returns false when the iterator is exhausted; subsequent 86 // calls to Key, Value, or next will panic. 87 func (it *mapIter) next() bool { 88 if it.it == nil { 89 it.it = mapiterinit(it.m.typ, it.m.word) 90 } else { 91 if mapiterkey(it.it) == nil { 92 panic("mapIter.next called on exhausted iterator") 93 } 94 mapiternext(it.it) 95 } 96 return mapiterkey(it.it) != nil 97 } 98 99 // m escapes into the return value, but the caller of mapiterinit 100 // doesn't let the return value escape. 101 //go:linkname mapiterinit reflect.mapiterinit 102 //go:noescape 103 func mapiterinit(t, m unsafe.Pointer) unsafe.Pointer 104 105 //go:linkname mapiterkey reflect.mapiterkey 106 //go:noescape 107 func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer) 108 109 //go:linkname mapiterelem reflect.mapiterelem 110 //go:noescape 111 func mapiterelem(it unsafe.Pointer) (elem unsafe.Pointer) 112 113 //go:linkname mapiternext reflect.mapiternext 114 //go:noescape 115 func mapiternext(it unsafe.Pointer)