metadata.go 1.8 KB

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