github.com/DQNEO/babygo@v0.0.3/src/runtime/map.go (about) 1 package runtime 2 3 import "unsafe" 4 5 type Map struct { 6 first *item 7 length int 8 valueSize uintptr 9 } 10 11 type item struct { 12 next *item 13 key interface{} 14 value uintptr 15 } 16 17 func (i *item) valueAddr() unsafe.Pointer { 18 return unsafe.Pointer(i.value) 19 } 20 21 func (i *item) match(key interface{}) bool { 22 switch k := key.(type) { 23 case string: 24 return i.key.(string) == k 25 case unsafe.Pointer: 26 return i.key.(unsafe.Pointer) == k 27 default: 28 panic("Not supported key type") 29 } 30 panic("Not supported key type") 31 return false 32 } 33 34 func makeMap(length uintptr, valueSize uintptr) uintptr { 35 var mp = &Map{ 36 valueSize: valueSize, 37 } 38 var addr uintptr = uintptr(unsafe.Pointer(mp)) 39 return addr 40 } 41 42 func lenMap(mp *Map) int { 43 return mp.length 44 } 45 46 func deleteFromMap(mp *Map, key interface{}) { 47 if mp.first == nil { 48 return 49 } 50 if mp.first.match(key) { 51 mp.first = mp.first.next 52 mp.length -= 1 53 return 54 } 55 var prev *item 56 for item := mp.first; item != nil; item = item.next { 57 if item.match(key) { 58 prev.next = item.next 59 mp.length -= 1 60 return 61 } 62 prev = item 63 } 64 } 65 66 func getAddrForMapSet(mp *Map, key interface{}) unsafe.Pointer { 67 var last *item 68 for item := mp.first; item != nil; item = item.next { 69 if item.match(key) { 70 return item.valueAddr() 71 } 72 last = item 73 } 74 newItem := &item{ 75 key: key, 76 value: malloc(mp.valueSize), 77 } 78 if mp.first == nil { 79 mp.first = newItem 80 } else { 81 last.next = newItem 82 } 83 mp.length += 1 84 return newItem.valueAddr() 85 } 86 87 func getAddrForMapGet(mp *Map, key interface{}) (bool, unsafe.Pointer) { 88 for item := mp.first; item != nil; item = item.next { 89 if item.match(key) { 90 // not found 91 return true, item.valueAddr() 92 } 93 } 94 // not found 95 return false, unsafe.Pointer(nil) 96 } 97 98 func deleteMap(mp *Map, key interface{}) { 99 if mp.first == nil { 100 return 101 } 102 if mp.first.match(key) { 103 mp.first = mp.first.next 104 mp.length -= 1 105 return 106 } 107 var prev *item 108 for item := mp.first; item != nil; item = item.next { 109 if item.match(key) { 110 prev.next = item.next 111 mp.length -= 1 112 return 113 } 114 prev = item 115 } 116 }