File: map.go

package info (click to toggle)
golang-github-maxatome-go-testdeep 1.14.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,416 kB
  • sloc: perl: 1,012; yacc: 130; makefile: 2
file content (91 lines) | stat: -rw-r--r-- 2,054 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright (c) 2018, Maxime Soulé
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.

package tdutil

import (
	"reflect"
	"sort"

	"github.com/maxatome/go-testdeep/internal/visited"
)

// MapSortedKeys returns a slice of all sorted keys of map m. It
// panics if m's [reflect.Kind] is not [reflect.Map].
func MapSortedKeys(m reflect.Value) []reflect.Value {
	ks := m.MapKeys()
	sort.Sort(SortableValues(ks))
	return ks
}

type kv struct {
	key   reflect.Value
	value reflect.Value
}

type kvSlice struct {
	v visited.Visited
	s []kv
}

func newKvSlice(l int) *kvSlice {
	s := kvSlice{}
	if l > 0 {
		s.s = make([]kv, 0, l)
		if l > 1 {
			s.v = visited.NewVisited()
		}
	}
	return &s
}

func (s *kvSlice) Len() int { return len(s.s) }
func (s *kvSlice) Less(i, j int) bool {
	return cmp(s.v, s.s[i].key, s.s[j].key) < 0
}
func (s *kvSlice) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] }

// MapEach calls fn for each key/value pair of map m. If fn
// returns false, it will not be called again.
func MapEach(m reflect.Value, fn func(k, v reflect.Value) bool) bool {
	kvs := newKvSlice(m.Len())
	iter := m.MapRange()
	for iter.Next() {
		kvs.s = append(kvs.s, kv{key: iter.Key(), value: iter.Value()})
	}
	sort.Sort(kvs)

	for _, kv := range kvs.s {
		if !fn(kv.key, kv.value) {
			return false
		}
	}
	return true
}

// MapEachValue calls fn for each value of map m. If fn returns
// false, it will not be called again.
func MapEachValue(m reflect.Value, fn func(k reflect.Value) bool) bool {
	iter := m.MapRange()
	for iter.Next() {
		if !fn(iter.Value()) {
			return false
		}
	}
	return true
}

// MapSortedValues returns a slice of all sorted values of map m. It
// panics if m's [reflect.Kind] is not [reflect.Map].
func MapSortedValues(m reflect.Value) []reflect.Value {
	vs := make([]reflect.Value, 0, m.Len())
	iter := m.MapRange()
	for iter.Next() {
		vs = append(vs, iter.Value())
	}
	sort.Sort(SortableValues(vs))
	return vs
}