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  }