mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	Bump to latest SMD to pick up performance optimizations
This commit is contained in:
		
							
								
								
									
										253
									
								
								vendor/sigs.k8s.io/structured-merge-diff/v3/value/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										253
									
								
								vendor/sigs.k8s.io/structured-merge-diff/v3/value/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -18,7 +18,6 @@ package value
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Map represents a Map or go structure.
 | 
			
		||||
@@ -27,6 +26,11 @@ type Map interface {
 | 
			
		||||
	Set(key string, val Value)
 | 
			
		||||
	// Get returns the value for the given key, if present, or (nil, false) otherwise.
 | 
			
		||||
	Get(key string) (Value, bool)
 | 
			
		||||
	// GetUsing uses the provided allocator and returns the value for the given key,
 | 
			
		||||
	// if present, or (nil, false) otherwise.
 | 
			
		||||
	// The returned Value should be given back to the Allocator when no longer needed
 | 
			
		||||
	// by calling Allocator.Free(Value).
 | 
			
		||||
	GetUsing(a Allocator, key string) (Value, bool)
 | 
			
		||||
	// Has returns true if the key is present, or false otherwise.
 | 
			
		||||
	Has(key string) bool
 | 
			
		||||
	// Delete removes the key from the map.
 | 
			
		||||
@@ -34,12 +38,162 @@ type Map interface {
 | 
			
		||||
	// Equals compares the two maps, and return true if they are the same, false otherwise.
 | 
			
		||||
	// Implementations can use MapEquals as a general implementation for this methods.
 | 
			
		||||
	Equals(other Map) bool
 | 
			
		||||
	// EqualsUsing uses the provided allocator and compares the two maps, and return true if
 | 
			
		||||
	// they are the same, false otherwise. Implementations can use MapEqualsUsing as a general
 | 
			
		||||
	// implementation for this methods.
 | 
			
		||||
	EqualsUsing(a Allocator, other Map) bool
 | 
			
		||||
	// Iterate runs the given function for each key/value in the
 | 
			
		||||
	// map. Returning false in the closure prematurely stops the
 | 
			
		||||
	// iteration.
 | 
			
		||||
	Iterate(func(key string, value Value) bool) bool
 | 
			
		||||
	// IterateUsing uses the provided allocator and runs the given function for each key/value
 | 
			
		||||
	// in the map. Returning false in the closure prematurely stops the iteration.
 | 
			
		||||
	IterateUsing(Allocator, func(key string, value Value) bool) bool
 | 
			
		||||
	// Length returns the number of items in the map.
 | 
			
		||||
	Length() int
 | 
			
		||||
	// Empty returns true if the map is empty.
 | 
			
		||||
	Empty() bool
 | 
			
		||||
	// Zip iterates over the entries of two maps together. If both maps contain a value for a given key, fn is called
 | 
			
		||||
	// with the values from both maps, otherwise it is called with the value of the map that contains the key and nil
 | 
			
		||||
	// for the map that does not contain the key. Returning false in the closure prematurely stops the iteration.
 | 
			
		||||
	Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool
 | 
			
		||||
	// ZipUsing uses the provided allocator and iterates over the entries of two maps together. If both maps
 | 
			
		||||
	// contain a value for a given key, fn is called with the values from both maps, otherwise it is called with
 | 
			
		||||
	// the value of the map that contains the key and nil for the map that does not contain the key. Returning
 | 
			
		||||
	// false in the closure prematurely stops the iteration.
 | 
			
		||||
	ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapTraverseOrder defines the map traversal ordering available.
 | 
			
		||||
type MapTraverseOrder int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Unordered indicates that the map traversal has no ordering requirement.
 | 
			
		||||
	Unordered = iota
 | 
			
		||||
	// LexicalKeyOrder indicates that the map traversal is ordered by key, lexically.
 | 
			
		||||
	LexicalKeyOrder
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MapZip iterates over the entries of two maps together. If both maps contain a value for a given key, fn is called
 | 
			
		||||
// with the values from both maps, otherwise it is called with the value of the map that contains the key and nil
 | 
			
		||||
// for the other map. Returning false in the closure prematurely stops the iteration.
 | 
			
		||||
func MapZip(lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
 | 
			
		||||
	return MapZipUsing(HeapAllocator, lhs, rhs, order, fn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapZipUsing uses the provided allocator and iterates over the entries of two maps together. If both maps
 | 
			
		||||
// contain a value for a given key, fn is called with the values from both maps, otherwise it is called with
 | 
			
		||||
// the value of the map that contains the key and nil for the other map. Returning false in the closure
 | 
			
		||||
// prematurely stops the iteration.
 | 
			
		||||
func MapZipUsing(a Allocator, lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
 | 
			
		||||
	if lhs != nil {
 | 
			
		||||
		return lhs.ZipUsing(a, rhs, order, fn)
 | 
			
		||||
	}
 | 
			
		||||
	if rhs != nil {
 | 
			
		||||
		return rhs.ZipUsing(a, lhs, order, func(key string, rhs, lhs Value) bool { // arg positions of lhs and rhs deliberately swapped
 | 
			
		||||
			return fn(key, lhs, rhs)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// defaultMapZip provides a default implementation of Zip for implementations that do not need to provide
 | 
			
		||||
// their own optimized implementation.
 | 
			
		||||
func defaultMapZip(a Allocator, lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
 | 
			
		||||
	switch order {
 | 
			
		||||
	case Unordered:
 | 
			
		||||
		return unorderedMapZip(a, lhs, rhs, fn)
 | 
			
		||||
	case LexicalKeyOrder:
 | 
			
		||||
		return lexicalKeyOrderedMapZip(a, lhs, rhs, fn)
 | 
			
		||||
	default:
 | 
			
		||||
		panic("Unsupported map order")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func unorderedMapZip(a Allocator, lhs, rhs Map, fn func(key string, lhs, rhs Value) bool) bool {
 | 
			
		||||
	if (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty()) {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if lhs != nil {
 | 
			
		||||
		ok := lhs.IterateUsing(a, func(key string, lhsValue Value) bool {
 | 
			
		||||
			var rhsValue Value
 | 
			
		||||
			if rhs != nil {
 | 
			
		||||
				if item, ok := rhs.GetUsing(a, key); ok {
 | 
			
		||||
					rhsValue = item
 | 
			
		||||
					defer a.Free(rhsValue)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return fn(key, lhsValue, rhsValue)
 | 
			
		||||
		})
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if rhs != nil {
 | 
			
		||||
		return rhs.IterateUsing(a, func(key string, rhsValue Value) bool {
 | 
			
		||||
			if lhs == nil || !lhs.Has(key) {
 | 
			
		||||
				return fn(key, nil, rhsValue)
 | 
			
		||||
			}
 | 
			
		||||
			return true
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lexicalKeyOrderedMapZip(a Allocator, lhs, rhs Map, fn func(key string, lhs, rhs Value) bool) bool {
 | 
			
		||||
	var lhsLength, rhsLength int
 | 
			
		||||
	var orderedLength int // rough estimate of length of union of map keys
 | 
			
		||||
	if lhs != nil {
 | 
			
		||||
		lhsLength = lhs.Length()
 | 
			
		||||
		orderedLength = lhsLength
 | 
			
		||||
	}
 | 
			
		||||
	if rhs != nil {
 | 
			
		||||
		rhsLength = rhs.Length()
 | 
			
		||||
		if rhsLength > orderedLength {
 | 
			
		||||
			orderedLength = rhsLength
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if lhsLength == 0 && rhsLength == 0 {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ordered := make([]string, 0, orderedLength)
 | 
			
		||||
	if lhs != nil {
 | 
			
		||||
		lhs.IterateUsing(a, func(key string, _ Value) bool {
 | 
			
		||||
			ordered = append(ordered, key)
 | 
			
		||||
			return true
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	if rhs != nil {
 | 
			
		||||
		rhs.IterateUsing(a, func(key string, _ Value) bool {
 | 
			
		||||
			if lhs == nil || !lhs.Has(key) {
 | 
			
		||||
				ordered = append(ordered, key)
 | 
			
		||||
			}
 | 
			
		||||
			return true
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	sort.Strings(ordered)
 | 
			
		||||
	for _, key := range ordered {
 | 
			
		||||
		var litem, ritem Value
 | 
			
		||||
		if lhs != nil {
 | 
			
		||||
			litem, _ = lhs.GetUsing(a, key)
 | 
			
		||||
		}
 | 
			
		||||
		if rhs != nil {
 | 
			
		||||
			ritem, _ = rhs.GetUsing(a, key)
 | 
			
		||||
		}
 | 
			
		||||
		ok := fn(key, litem, ritem)
 | 
			
		||||
		if litem != nil {
 | 
			
		||||
			a.Free(litem)
 | 
			
		||||
		}
 | 
			
		||||
		if ritem != nil {
 | 
			
		||||
			a.Free(ritem)
 | 
			
		||||
		}
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapLess compares two maps lexically.
 | 
			
		||||
@@ -49,65 +203,68 @@ func MapLess(lhs, rhs Map) bool {
 | 
			
		||||
 | 
			
		||||
// MapCompare compares two maps lexically.
 | 
			
		||||
func MapCompare(lhs, rhs Map) int {
 | 
			
		||||
	lorder := make([]string, 0, lhs.Length())
 | 
			
		||||
	lhs.Iterate(func(key string, _ Value) bool {
 | 
			
		||||
		lorder = append(lorder, key)
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
	sort.Strings(lorder)
 | 
			
		||||
	rorder := make([]string, 0, rhs.Length())
 | 
			
		||||
	rhs.Iterate(func(key string, _ Value) bool {
 | 
			
		||||
		rorder = append(rorder, key)
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
	sort.Strings(rorder)
 | 
			
		||||
	return MapCompareUsing(HeapAllocator, lhs, rhs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	i := 0
 | 
			
		||||
	for {
 | 
			
		||||
		if i >= len(lorder) && i >= len(rorder) {
 | 
			
		||||
			// Maps are the same length and all items are equal.
 | 
			
		||||
			return 0
 | 
			
		||||
		}
 | 
			
		||||
		if i >= len(lorder) {
 | 
			
		||||
			// LHS is shorter.
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
		if i >= len(rorder) {
 | 
			
		||||
			// RHS is shorter.
 | 
			
		||||
			return 1
 | 
			
		||||
		}
 | 
			
		||||
		if c := strings.Compare(lorder[i], rorder[i]); c != 0 {
 | 
			
		||||
			return c
 | 
			
		||||
		}
 | 
			
		||||
		litem, _ := lhs.Get(lorder[i])
 | 
			
		||||
		ritem, _ := rhs.Get(rorder[i])
 | 
			
		||||
		if c := Compare(litem, ritem); c != 0 {
 | 
			
		||||
			return c
 | 
			
		||||
		}
 | 
			
		||||
		litem.Recycle()
 | 
			
		||||
		ritem.Recycle()
 | 
			
		||||
		// The items are equal; continue.
 | 
			
		||||
		i++
 | 
			
		||||
// MapCompareUsing uses the provided allocator and compares two maps lexically.
 | 
			
		||||
func MapCompareUsing(a Allocator, lhs, rhs Map) int {
 | 
			
		||||
	c := 0
 | 
			
		||||
	var llength, rlength int
 | 
			
		||||
	if lhs != nil {
 | 
			
		||||
		llength = lhs.Length()
 | 
			
		||||
	}
 | 
			
		||||
	if rhs != nil {
 | 
			
		||||
		rlength = rhs.Length()
 | 
			
		||||
	}
 | 
			
		||||
	if llength == 0 && rlength == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	i := 0
 | 
			
		||||
	MapZipUsing(a, lhs, rhs, LexicalKeyOrder, func(key string, lhs, rhs Value) bool {
 | 
			
		||||
		switch {
 | 
			
		||||
		case i == llength:
 | 
			
		||||
			c = -1
 | 
			
		||||
		case i == rlength:
 | 
			
		||||
			c = 1
 | 
			
		||||
		case lhs == nil:
 | 
			
		||||
			c = 1
 | 
			
		||||
		case rhs == nil:
 | 
			
		||||
			c = -1
 | 
			
		||||
		default:
 | 
			
		||||
			c = CompareUsing(a, lhs, rhs)
 | 
			
		||||
		}
 | 
			
		||||
		i++
 | 
			
		||||
		return c == 0
 | 
			
		||||
	})
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapEquals returns true if lhs == rhs, false otherwise. This function
 | 
			
		||||
// acts on generic types and should not be used by callers, but can help
 | 
			
		||||
// implement Map.Equals.
 | 
			
		||||
// WARN: This is a naive implementation, calling lhs.Equals(rhs) is typically the most efficient.
 | 
			
		||||
func MapEquals(lhs, rhs Map) bool {
 | 
			
		||||
	return MapEqualsUsing(HeapAllocator, lhs, rhs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapEqualsUsing uses the provided allocator and returns true if lhs == rhs,
 | 
			
		||||
// false otherwise. This function acts on generic types and should not be used
 | 
			
		||||
// by callers, but can help implement Map.Equals.
 | 
			
		||||
// WARN: This is a naive implementation, calling lhs.EqualsUsing(allocator, rhs) is typically the most efficient.
 | 
			
		||||
func MapEqualsUsing(a Allocator, lhs, rhs Map) bool {
 | 
			
		||||
	if lhs == nil && rhs == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if lhs == nil || rhs == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if lhs.Length() != rhs.Length() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return lhs.Iterate(func(k string, v Value) bool {
 | 
			
		||||
		vo, ok := rhs.Get(k)
 | 
			
		||||
		if !ok {
 | 
			
		||||
	return MapZipUsing(a, lhs, rhs, Unordered, func(key string, lhs, rhs Value) bool {
 | 
			
		||||
		if lhs == nil || rhs == nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if !Equals(v, vo) {
 | 
			
		||||
			vo.Recycle()
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		vo.Recycle()
 | 
			
		||||
		return true
 | 
			
		||||
		return EqualsUsing(a, lhs, rhs)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user