github.com/cilium/ebpf@v0.16.0/asm/metadata.go (about)

     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  }