gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }