Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
orderedmap.go287 linesDownload Raw Back to typeparam
1// run2 3// Copyright 2021 The Go Authors. All rights reserved.4// Use of this source code is governed by a BSD-style5// license that can be found in the LICENSE file.6 7// Package orderedmap provides an ordered map, implemented as a binary tree.8package main9 10import (11	"bytes"12	"context"13	"fmt"14	"runtime"15)16 17type Ordered interface {18	~int | ~int8 | ~int16 | ~int32 | ~int64 |19		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |20		~float32 | ~float64 |21		~string22}23 24// _Map is an ordered map.25type _Map[K, V any] struct {26	root    *node[K, V]27	compare func(K, K) int28}29 30// node is the type of a node in the binary tree.31type node[K, V any] struct {32	key         K33	val         V34	left, right *node[K, V]35}36 37// _New returns a new map. It takes a comparison function that compares two38// keys and returns < 0 if the first is less, == 0 if they are equal,39// > 0 if the first is greater.40func _New[K, V any](compare func(K, K) int) *_Map[K, V] {41	return &_Map[K, V]{compare: compare}42}43 44// _NewOrdered returns a new map whose key is an ordered type.45// This is like _New, but does not require providing a compare function.46// The map compare function uses the obvious key ordering.47func _NewOrdered[K Ordered, V any]() *_Map[K, V] {48	return _New[K, V](func(k1, k2 K) int {49		switch {50		case k1 < k2:51			return -152		case k1 == k2:53			return 054		default:55			return 156		}57	})58}59 60// find looks up key in the map, returning either a pointer to the slot of the61// node holding key, or a pointer to the slot where should a node would go.62func (m *_Map[K, V]) find(key K) **node[K, V] {63	pn := &m.root64	for *pn != nil {65		switch cmp := m.compare(key, (*pn).key); {66		case cmp < 0:67			pn = &(*pn).left68		case cmp > 0:69			pn = &(*pn).right70		default:71			return pn72		}73	}74	return pn75}76 77// Insert inserts a new key/value into the map.78// If the key is already present, the value is replaced.79// Reports whether this is a new key.80func (m *_Map[K, V]) Insert(key K, val V) bool {81	pn := m.find(key)82	if *pn != nil {83		(*pn).val = val84		return false85	}86	*pn = &node[K, V]{key: key, val: val}87	return true88}89 90// Find returns the value associated with a key, or the zero value91// if not present. The found result reports whether the key was found.92func (m *_Map[K, V]) Find(key K) (V, bool) {93	pn := m.find(key)94	if *pn == nil {95		var zero V96		return zero, false97	}98	return (*pn).val, true99}100 101// keyValue is a pair of key and value used while iterating.102type keyValue[K, V any] struct {103	key K104	val V105}106 107// iterate returns an iterator that traverses the map.108func (m *_Map[K, V]) Iterate() *_Iterator[K, V] {109	sender, receiver := _Ranger[keyValue[K, V]]()110	var f func(*node[K, V]) bool111	f = func(n *node[K, V]) bool {112		if n == nil {113			return true114		}115		// Stop the traversal if Send fails, which means that116		// nothing is listening to the receiver.117		return f(n.left) &&118			sender.Send(context.Background(), keyValue[K, V]{n.key, n.val}) &&119			f(n.right)120	}121	go func() {122		f(m.root)123		sender.Close()124	}()125	return &_Iterator[K, V]{receiver}126}127 128// _Iterator is used to iterate over the map.129type _Iterator[K, V any] struct {130	r *_Receiver[keyValue[K, V]]131}132 133// Next returns the next key and value pair, and a boolean that reports134// whether they are valid. If not valid, we have reached the end of the map.135func (it *_Iterator[K, V]) Next() (K, V, bool) {136	keyval, ok := it.r.Next(context.Background())137	if !ok {138		var zerok K139		var zerov V140		return zerok, zerov, false141	}142	return keyval.key, keyval.val, true143}144 145func TestMap() {146	m := _New[[]byte, int](bytes.Compare)147 148	if _, found := m.Find([]byte("a")); found {149		panic(fmt.Sprintf("unexpectedly found %q in empty map", []byte("a")))150	}151	if !m.Insert([]byte("a"), 'a') {152		panic(fmt.Sprintf("key %q unexpectedly already present", []byte("a")))153	}154	if !m.Insert([]byte("c"), 'c') {155		panic(fmt.Sprintf("key %q unexpectedly already present", []byte("c")))156	}157	if !m.Insert([]byte("b"), 'b') {158		panic(fmt.Sprintf("key %q unexpectedly already present", []byte("b")))159	}160	if m.Insert([]byte("c"), 'x') {161		panic(fmt.Sprintf("key %q unexpectedly not present", []byte("c")))162	}163 164	if v, found := m.Find([]byte("a")); !found {165		panic(fmt.Sprintf("did not find %q", []byte("a")))166	} else if v != 'a' {167		panic(fmt.Sprintf("key %q returned wrong value %c, expected %c", []byte("a"), v, 'a'))168	}169	if v, found := m.Find([]byte("c")); !found {170		panic(fmt.Sprintf("did not find %q", []byte("c")))171	} else if v != 'x' {172		panic(fmt.Sprintf("key %q returned wrong value %c, expected %c", []byte("c"), v, 'x'))173	}174 175	if _, found := m.Find([]byte("d")); found {176		panic(fmt.Sprintf("unexpectedly found %q", []byte("d")))177	}178 179	gather := func(it *_Iterator[[]byte, int]) []int {180		var r []int181		for {182			_, v, ok := it.Next()183			if !ok {184				return r185			}186			r = append(r, v)187		}188	}189	got := gather(m.Iterate())190	want := []int{'a', 'b', 'x'}191	if !_SliceEqual(got, want) {192		panic(fmt.Sprintf("Iterate returned %v, want %v", got, want))193	}194}195 196func main() {197	TestMap()198}199 200// _Equal reports whether two slices are equal: the same length and all201// elements equal. All floating point NaNs are considered equal.202func _SliceEqual[Elem comparable](s1, s2 []Elem) bool {203	if len(s1) != len(s2) {204		return false205	}206	for i, v1 := range s1 {207		v2 := s2[i]208		if v1 != v2 {209			isNaN := func(f Elem) bool { return f != f }210			if !isNaN(v1) || !isNaN(v2) {211				return false212			}213		}214	}215	return true216}217 218// Ranger returns a Sender and a Receiver. The Receiver provides a219// Next method to retrieve values. The Sender provides a Send method220// to send values and a Close method to stop sending values. The Next221// method indicates when the Sender has been closed, and the Send222// method indicates when the Receiver has been freed.223//224// This is a convenient way to exit a goroutine sending values when225// the receiver stops reading them.226func _Ranger[Elem any]() (*_Sender[Elem], *_Receiver[Elem]) {227	c := make(chan Elem)228	d := make(chan struct{})229	s := &_Sender[Elem]{230		values: c,231		done:   d,232	}233	r := &_Receiver[Elem]{234		values: c,235		done:   d,236	}237	runtime.SetFinalizer(r, (*_Receiver[Elem]).finalize)238	return s, r239}240 241// A _Sender is used to send values to a Receiver.242type _Sender[Elem any] struct {243	values chan<- Elem244	done   <-chan struct{}245}246 247// Send sends a value to the receiver. It reports whether the value was sent.248// The value will not be sent if the context is closed or the receiver249// is freed.250func (s *_Sender[Elem]) Send(ctx context.Context, v Elem) bool {251	select {252	case <-ctx.Done():253		return false254	case s.values <- v:255		return true256	case <-s.done:257		return false258	}259}260 261// Close tells the receiver that no more values will arrive.262// After Close is called, the _Sender may no longer be used.263func (s *_Sender[Elem]) Close() {264	close(s.values)265}266 267// A _Receiver receives values from a _Sender.268type _Receiver[Elem any] struct {269	values <-chan Elem270	done   chan<- struct{}271}272 273// Next returns the next value from the channel. The bool result indicates274// whether the value is valid.275func (r *_Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) {276	select {277	case <-ctx.Done():278	case v, ok = <-r.values:279	}280	return v, ok281}282 283// finalize is a finalizer for the receiver.284func (r *_Receiver[Elem]) finalize() {285	close(r.done)286}287 
codekingpro/portable-devtools · Team Ai