metadata.go (1837B)
1 package asm 2 3 // Metadata contains metadata about an instruction. 4 type Metadata struct { 5 head *metaElement 6 } 7 8 type metaElement struct { 9 next *metaElement 10 key, value interface{} 11 } 12 13 // Find the element containing key. 14 // 15 // Returns nil if there is no such element. 16 func (m *Metadata) find(key interface{}) *metaElement { 17 for e := m.head; e != nil; e = e.next { 18 if e.key == key { 19 return e 20 } 21 } 22 return nil 23 } 24 25 // Remove an element from the linked list. 26 // 27 // Copies as many elements of the list as necessary to remove r, but doesn't 28 // perform a full copy. 29 func (m *Metadata) remove(r *metaElement) { 30 current := &m.head 31 for e := m.head; e != nil; e = e.next { 32 if e == r { 33 // We've found the element we want to remove. 34 *current = e.next 35 36 // No need to copy the tail. 37 return 38 } 39 40 // There is another element in front of the one we want to remove. 41 // We have to copy it to be able to change metaElement.next. 42 cpy := &metaElement{key: e.key, value: e.value} 43 *current = cpy 44 current = &cpy.next 45 } 46 } 47 48 // Set a key to a value. 49 // 50 // If value is nil, the key is removed. Avoids modifying old metadata by 51 // copying if necessary. 52 func (m *Metadata) Set(key, value interface{}) { 53 if e := m.find(key); e != nil { 54 if e.value == value { 55 // Key is present and the value is the same. Nothing to do. 56 return 57 } 58 59 // Key is present with a different value. Create a copy of the list 60 // which doesn't have the element in it. 61 m.remove(e) 62 } 63 64 // m.head is now a linked list that doesn't contain key. 65 if value == nil { 66 return 67 } 68 69 m.head = &metaElement{key: key, value: value, next: m.head} 70 } 71 72 // Get the value of a key. 73 // 74 // Returns nil if no value with the given key is present. 75 func (m *Metadata) Get(key interface{}) interface{} { 76 if e := m.find(key); e != nil { 77 return e.value 78 } 79 return nil 80 }