package goja
import (
"hash/maphash"
)
type mapEntry struct {
key, value Value
iterPrev, iterNext *mapEntry
hNext *mapEntry
}
type orderedMap struct {
hash *maphash .Hash
hashTable map [uint64 ]*mapEntry
iterFirst, iterLast *mapEntry
size int
}
type orderedMapIter struct {
m *orderedMap
cur *mapEntry
}
func (m *orderedMap ) lookup (key Value ) (h uint64 , entry , hPrev *mapEntry ) {
if key == _negativeZero {
key = intToValue (0 )
}
h = key .hash (m .hash )
for entry = m .hashTable [h ]; entry != nil && !entry .key .SameAs (key ); hPrev , entry = entry , entry .hNext {
}
return
}
func (m *orderedMap ) set (key , value Value ) {
h , entry , hPrev := m .lookup (key )
if entry != nil {
entry .value = value
} else {
if key == _negativeZero {
key = intToValue (0 )
}
entry = &mapEntry {key : key , value : value }
if hPrev == nil {
m .hashTable [h ] = entry
} else {
hPrev .hNext = entry
}
if m .iterLast != nil {
entry .iterPrev = m .iterLast
m .iterLast .iterNext = entry
} else {
m .iterFirst = entry
}
m .iterLast = entry
m .size ++
}
}
func (m *orderedMap ) get (key Value ) Value {
_ , entry , _ := m .lookup (key )
if entry != nil {
return entry .value
}
return nil
}
func (m *orderedMap ) remove (key Value ) bool {
h , entry , hPrev := m .lookup (key )
if entry != nil {
entry .key = nil
entry .value = nil
if entry .iterPrev != nil {
entry .iterPrev .iterNext = entry .iterNext
} else {
m .iterFirst = entry .iterNext
}
if entry .iterNext != nil {
entry .iterNext .iterPrev = entry .iterPrev
} else {
m .iterLast = entry .iterPrev
}
if hPrev == nil {
if entry .hNext == nil {
delete (m .hashTable , h )
} else {
m .hashTable [h ] = entry .hNext
}
} else {
hPrev .hNext = entry .hNext
}
m .size --
return true
}
return false
}
func (m *orderedMap ) has (key Value ) bool {
_ , entry , _ := m .lookup (key )
return entry != nil
}
func (iter *orderedMapIter ) next () *mapEntry {
if iter .m == nil {
return nil
}
cur := iter .cur
for cur != nil && cur .key == nil {
cur = cur .iterPrev
}
if cur != nil {
cur = cur .iterNext
} else {
cur = iter .m .iterFirst
}
if cur == nil {
iter .close ()
} else {
iter .cur = cur
}
return cur
}
func (iter *orderedMapIter ) close () {
iter .m = nil
iter .cur = nil
}
func newOrderedMap(h *maphash .Hash ) *orderedMap {
return &orderedMap {
hash : h ,
hashTable : make (map [uint64 ]*mapEntry ),
}
}
func (m *orderedMap ) newIter () *orderedMapIter {
iter := &orderedMapIter {
m : m ,
}
return iter
}
func (m *orderedMap ) clear () {
for item := m .iterFirst ; item != nil ; item = item .iterNext {
item .key = nil
item .value = nil
if item .iterPrev != nil {
item .iterPrev .iterNext = nil
}
}
m .iterFirst = nil
m .iterLast = nil
m .hashTable = make (map [uint64 ]*mapEntry )
m .size = 0
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .