map.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package goja
  2. import (
  3. "hash/maphash"
  4. )
  5. type mapEntry struct {
  6. key, value Value
  7. iterPrev, iterNext *mapEntry
  8. hNext *mapEntry
  9. }
  10. type orderedMap struct {
  11. hash *maphash.Hash
  12. hashTable map[uint64]*mapEntry
  13. iterFirst, iterLast *mapEntry
  14. size int
  15. }
  16. type orderedMapIter struct {
  17. m *orderedMap
  18. cur *mapEntry
  19. }
  20. func (m *orderedMap) lookup(key Value) (h uint64, entry, hPrev *mapEntry) {
  21. if key == _negativeZero {
  22. key = intToValue(0)
  23. }
  24. h = key.hash(m.hash)
  25. for entry = m.hashTable[h]; entry != nil && !entry.key.SameAs(key); hPrev, entry = entry, entry.hNext {
  26. }
  27. return
  28. }
  29. func (m *orderedMap) set(key, value Value) {
  30. h, entry, hPrev := m.lookup(key)
  31. if entry != nil {
  32. entry.value = value
  33. } else {
  34. if key == _negativeZero {
  35. key = intToValue(0)
  36. }
  37. entry = &mapEntry{key: key, value: value}
  38. if hPrev == nil {
  39. m.hashTable[h] = entry
  40. } else {
  41. hPrev.hNext = entry
  42. }
  43. if m.iterLast != nil {
  44. entry.iterPrev = m.iterLast
  45. m.iterLast.iterNext = entry
  46. } else {
  47. m.iterFirst = entry
  48. }
  49. m.iterLast = entry
  50. m.size++
  51. }
  52. }
  53. func (m *orderedMap) get(key Value) Value {
  54. _, entry, _ := m.lookup(key)
  55. if entry != nil {
  56. return entry.value
  57. }
  58. return nil
  59. }
  60. func (m *orderedMap) remove(key Value) bool {
  61. h, entry, hPrev := m.lookup(key)
  62. if entry != nil {
  63. entry.key = nil
  64. entry.value = nil
  65. // remove from the doubly-linked list
  66. if entry.iterPrev != nil {
  67. entry.iterPrev.iterNext = entry.iterNext
  68. } else {
  69. m.iterFirst = entry.iterNext
  70. }
  71. if entry.iterNext != nil {
  72. entry.iterNext.iterPrev = entry.iterPrev
  73. } else {
  74. m.iterLast = entry.iterPrev
  75. }
  76. // remove from the hashTable
  77. if hPrev == nil {
  78. if entry.hNext == nil {
  79. delete(m.hashTable, h)
  80. } else {
  81. m.hashTable[h] = entry.hNext
  82. }
  83. } else {
  84. hPrev.hNext = entry.hNext
  85. }
  86. m.size--
  87. return true
  88. }
  89. return false
  90. }
  91. func (m *orderedMap) has(key Value) bool {
  92. _, entry, _ := m.lookup(key)
  93. return entry != nil
  94. }
  95. func (iter *orderedMapIter) next() *mapEntry {
  96. if iter.m == nil {
  97. // closed iterator
  98. return nil
  99. }
  100. cur := iter.cur
  101. // if the current item was deleted, track back to find the latest that wasn't
  102. for cur != nil && cur.key == nil {
  103. cur = cur.iterPrev
  104. }
  105. if cur != nil {
  106. cur = cur.iterNext
  107. } else {
  108. cur = iter.m.iterFirst
  109. }
  110. if cur == nil {
  111. iter.close()
  112. } else {
  113. iter.cur = cur
  114. }
  115. return cur
  116. }
  117. func (iter *orderedMapIter) close() {
  118. iter.m = nil
  119. iter.cur = nil
  120. }
  121. func newOrderedMap(h *maphash.Hash) *orderedMap {
  122. return &orderedMap{
  123. hash: h,
  124. hashTable: make(map[uint64]*mapEntry),
  125. }
  126. }
  127. func (m *orderedMap) newIter() *orderedMapIter {
  128. iter := &orderedMapIter{
  129. m: m,
  130. }
  131. return iter
  132. }
  133. func (m *orderedMap) clear() {
  134. for item := m.iterFirst; item != nil; item = item.iterNext {
  135. item.key = nil
  136. item.value = nil
  137. if item.iterPrev != nil {
  138. item.iterPrev.iterNext = nil
  139. }
  140. }
  141. m.iterFirst = nil
  142. m.iterLast = nil
  143. m.hashTable = make(map[uint64]*mapEntry)
  144. m.size = 0
  145. }