add: humidity (WIP)
This commit is contained in:
		
							
								
								
									
										14
									
								
								vendor/periph.io/x/periph/conn/spi/func.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/periph.io/x/periph/conn/spi/func.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// Copyright 2018 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package spi
 | 
			
		||||
 | 
			
		||||
import "periph.io/x/periph/conn/pin"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	CLK  pin.Func = "SPI_CLK"  // Clock
 | 
			
		||||
	CS   pin.Func = "SPI_CS"   // Chip select
 | 
			
		||||
	MISO pin.Func = "SPI_MISO" // Master in
 | 
			
		||||
	MOSI pin.Func = "SPI_MOSI" // Master out
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										187
									
								
								vendor/periph.io/x/periph/conn/spi/spi.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								vendor/periph.io/x/periph/conn/spi/spi.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package spi defines the API to communicate with devices over the SPI
 | 
			
		||||
// protocol.
 | 
			
		||||
//
 | 
			
		||||
// As described in https://periph.io/x/periph/conn#hdr-Concepts, periph.io uses
 | 
			
		||||
// the concepts of Bus, Port and Conn.
 | 
			
		||||
//
 | 
			
		||||
// In the package spi, 'Bus' is not exposed, as it would be SPI bus number
 | 
			
		||||
// without a CS line, for example on linux asking for "/dev/spi0" without the
 | 
			
		||||
// ".0" suffix.
 | 
			
		||||
//
 | 
			
		||||
// The OS doesn't allow that so it is counter productive to express this at the
 | 
			
		||||
// API layer, so 'Port' is exposed directly instead.
 | 
			
		||||
//
 | 
			
		||||
// Use Port.Connect() converts the uninitialized Port into a Conn.
 | 
			
		||||
//
 | 
			
		||||
// See https://en.wikipedia.org/wiki/Serial_Peripheral_Interface for more
 | 
			
		||||
// information.
 | 
			
		||||
package spi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn"
 | 
			
		||||
	"periph.io/x/periph/conn/gpio"
 | 
			
		||||
	"periph.io/x/periph/conn/physic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Mode determines how communication is done.
 | 
			
		||||
//
 | 
			
		||||
// The bits can be OR'ed to change the parameters used for
 | 
			
		||||
// communication.
 | 
			
		||||
//
 | 
			
		||||
type Mode int
 | 
			
		||||
 | 
			
		||||
// Mode determines the SPI communication parameters.
 | 
			
		||||
//
 | 
			
		||||
// CPOL means the clock polarity. Idle is High when set.
 | 
			
		||||
//
 | 
			
		||||
// CPHA is the clock phase, sample on trailing edge when set.
 | 
			
		||||
const (
 | 
			
		||||
	Mode0 Mode = 0x0 // CPOL=0, CPHA=0
 | 
			
		||||
	Mode1 Mode = 0x1 // CPOL=0, CPHA=1
 | 
			
		||||
	Mode2 Mode = 0x2 // CPOL=1, CPHA=0
 | 
			
		||||
	Mode3 Mode = 0x3 // CPOL=1, CPHA=1
 | 
			
		||||
 | 
			
		||||
	// HalfDuplex specifies that MOSI and MISO use the same wire, and that only
 | 
			
		||||
	// one duplex is used at a time.
 | 
			
		||||
	HalfDuplex Mode = 0x4
 | 
			
		||||
	// NoCS request the driver to not use the CS line.
 | 
			
		||||
	NoCS Mode = 0x8
 | 
			
		||||
	// LSBFirst requests the words to be encoded in little endian instead of the
 | 
			
		||||
	// default big endian.
 | 
			
		||||
	LSBFirst = 0x10
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (m Mode) String() string {
 | 
			
		||||
	s := ""
 | 
			
		||||
	switch m & Mode3 {
 | 
			
		||||
	case Mode0:
 | 
			
		||||
		s = "Mode0"
 | 
			
		||||
	case Mode1:
 | 
			
		||||
		s = "Mode1"
 | 
			
		||||
	case Mode2:
 | 
			
		||||
		s = "Mode2"
 | 
			
		||||
	case Mode3:
 | 
			
		||||
		s = "Mode3"
 | 
			
		||||
	}
 | 
			
		||||
	m &^= Mode3
 | 
			
		||||
	if m&HalfDuplex != 0 {
 | 
			
		||||
		s += "|HalfDuplex"
 | 
			
		||||
	}
 | 
			
		||||
	m &^= HalfDuplex
 | 
			
		||||
	if m&NoCS != 0 {
 | 
			
		||||
		s += "|NoCS"
 | 
			
		||||
	}
 | 
			
		||||
	m &^= NoCS
 | 
			
		||||
	if m&LSBFirst != 0 {
 | 
			
		||||
		s += "|LSBFirst"
 | 
			
		||||
	}
 | 
			
		||||
	m &^= LSBFirst
 | 
			
		||||
	if m != 0 {
 | 
			
		||||
		s += "|0x"
 | 
			
		||||
		s += strconv.FormatUint(uint64(m), 16)
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Packet represents one packet when sending multiple packets as a transaction.
 | 
			
		||||
type Packet struct {
 | 
			
		||||
	// W and R are the output and input data. When HalfDuplex is specified to
 | 
			
		||||
	// Connect, only one of the two can be set.
 | 
			
		||||
	W, R []byte
 | 
			
		||||
	// BitsPerWord overrides the default bits per word value set in Connect.
 | 
			
		||||
	BitsPerWord uint8
 | 
			
		||||
	// KeepCS tells the driver to keep CS asserted after this packet is
 | 
			
		||||
	// completed. This can be leveraged to create long transaction as multiple
 | 
			
		||||
	// packets like to use 9 bits commands then 8 bits data.
 | 
			
		||||
	//
 | 
			
		||||
	// Normally during a spi.Conn.TxPackets() call, KeepCS should be set to true
 | 
			
		||||
	// for all packets except the last one. If the last one is set to true, the
 | 
			
		||||
	// CS line stays asserted, leaving the transaction hanging on the bus.
 | 
			
		||||
	//
 | 
			
		||||
	// KeepCS is ignored when NoCS was specified to Connect.
 | 
			
		||||
	KeepCS bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Conn defines the interface a concrete SPI driver must implement.
 | 
			
		||||
//
 | 
			
		||||
// Implementers can optionally implement io.Writer and io.Reader for
 | 
			
		||||
// unidirectional operation.
 | 
			
		||||
type Conn interface {
 | 
			
		||||
	conn.Conn
 | 
			
		||||
	// TxPackets does multiple operations over the SPI connection.
 | 
			
		||||
	//
 | 
			
		||||
	// The maximum number of bytes can be limited depending on the driver. Query
 | 
			
		||||
	// conn.Limits.MaxTxSize() can be used to determine the limit.
 | 
			
		||||
	//
 | 
			
		||||
	// If the last packet has KeepCS:true, the CS line stays asserted. This
 | 
			
		||||
	// enables doing SPI transaction over multiple calls.
 | 
			
		||||
	//
 | 
			
		||||
	// Conversely, if any packet beside the last one has KeepCS:false, the CS
 | 
			
		||||
	// line will blip for a short amount of time to force a new transaction.
 | 
			
		||||
	//
 | 
			
		||||
	// It was observed on RPi3 hardware to have a one clock delay between each
 | 
			
		||||
	// packet.
 | 
			
		||||
	TxPackets(p []Packet) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Port is the interface to be provided to device drivers.
 | 
			
		||||
//
 | 
			
		||||
// The device driver, that is the driver for the peripheral connected over
 | 
			
		||||
// this port, calls Connect() to retrieve a configured connection as Conn.
 | 
			
		||||
type Port interface {
 | 
			
		||||
	String() string
 | 
			
		||||
	// Connect sets the communication parameters of the connection for use by a
 | 
			
		||||
	// device.
 | 
			
		||||
	//
 | 
			
		||||
	// The device driver must call this function exactly once.
 | 
			
		||||
	//
 | 
			
		||||
	// f must specify the maximum rated speed by the device's spec. The lowest
 | 
			
		||||
	// speed between the port speed and the device speed is selected. Use 0 for f
 | 
			
		||||
	// if there is no known maximum value for this device.
 | 
			
		||||
	//
 | 
			
		||||
	// mode specifies the clock and signal polarities, if the port is using half
 | 
			
		||||
	// duplex (shared MISO and MOSI) or if CS is not needed.
 | 
			
		||||
	//
 | 
			
		||||
	// bits is the number of bits per word. Generally you should use 8.
 | 
			
		||||
	Connect(f physic.Frequency, mode Mode, bits int) (Conn, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PortCloser is a SPI port that can be closed.
 | 
			
		||||
//
 | 
			
		||||
// This interface is meant to be handled by the application.
 | 
			
		||||
type PortCloser interface {
 | 
			
		||||
	io.Closer
 | 
			
		||||
	Port
 | 
			
		||||
	// LimitSpeed sets the maximum port speed.
 | 
			
		||||
	//
 | 
			
		||||
	// It lets an application use a device at a lower speed than the maximum
 | 
			
		||||
	// speed as rated by the device driver. This is useful for example when the
 | 
			
		||||
	// wires are long or the connection is of poor quality.
 | 
			
		||||
	//
 | 
			
		||||
	// This function can be called multiple times and resets the previous value.
 | 
			
		||||
	// 0 is not a valid value for f. The lowest speed between the port speed and
 | 
			
		||||
	// the device speed is selected.
 | 
			
		||||
	LimitSpeed(f physic.Frequency) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pins defines the pins that a SPI port interconnect is using on the host.
 | 
			
		||||
//
 | 
			
		||||
// It is expected that a implementer of ConnCloser or Conn also implement Pins
 | 
			
		||||
// but this is not a requirement.
 | 
			
		||||
type Pins interface {
 | 
			
		||||
	// CLK returns the SCK (clock) pin.
 | 
			
		||||
	CLK() gpio.PinOut
 | 
			
		||||
	// MOSI returns the SDO (master out, slave in) pin.
 | 
			
		||||
	MOSI() gpio.PinOut
 | 
			
		||||
	// MISO returns the SDI (master in, slave out) pin.
 | 
			
		||||
	MISO() gpio.PinIn
 | 
			
		||||
	// CS returns the CSN (chip select) pin.
 | 
			
		||||
	CS() gpio.PinOut
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										262
									
								
								vendor/periph.io/x/periph/conn/spi/spireg/spireg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								vendor/periph.io/x/periph/conn/spi/spireg/spireg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,262 @@
 | 
			
		||||
// Copyright 2017 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package spireg defines the SPI registry for SPI ports discovered on the host.
 | 
			
		||||
//
 | 
			
		||||
// SPI ports discovered on the host are automatically registered in the SPI
 | 
			
		||||
// registry by host.Init().
 | 
			
		||||
package spireg
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/spi"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Opener opens an handle to a port.
 | 
			
		||||
//
 | 
			
		||||
// It is provided by the actual port driver.
 | 
			
		||||
type Opener func() (spi.PortCloser, error)
 | 
			
		||||
 | 
			
		||||
// Ref references a SPI port.
 | 
			
		||||
//
 | 
			
		||||
// It is returned by All() to enumerate all registered ports.
 | 
			
		||||
type Ref struct {
 | 
			
		||||
	// Name of the port.
 | 
			
		||||
	//
 | 
			
		||||
	// It must not be a sole number. It must be unique across the host.
 | 
			
		||||
	Name string
 | 
			
		||||
	// Aliases are the alternative names that can be used to reference this port.
 | 
			
		||||
	Aliases []string
 | 
			
		||||
	// Number of the bus or -1 if the bus doesn't have any "native" number.
 | 
			
		||||
	//
 | 
			
		||||
	// Buses provided by the CPU normally have a 0 based number. Buses provided
 | 
			
		||||
	// via an addon (like over USB) generally are not numbered.
 | 
			
		||||
	//
 | 
			
		||||
	// The port is a bus number plus a CS line.
 | 
			
		||||
	Number int
 | 
			
		||||
	// Open is the factory to open an handle to this SPI port.
 | 
			
		||||
	Open Opener
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open opens a SPI port by its name, an alias or its number and returns an
 | 
			
		||||
// handle to it.
 | 
			
		||||
//
 | 
			
		||||
// Specify the empty string "" to get the first available port. This is the
 | 
			
		||||
// recommended default value unless an application knows the exact port to use.
 | 
			
		||||
//
 | 
			
		||||
// Each port can register multiple aliases, each leading to the same port
 | 
			
		||||
// handle.
 | 
			
		||||
//
 | 
			
		||||
// "Bus number" is a generic concept that is highly dependent on the platform
 | 
			
		||||
// and OS. On some platform, the first port may have the number 0, 1 or as high
 | 
			
		||||
// as 32766. Bus numbers are not necessarily continuous and may not start at 0.
 | 
			
		||||
// It was observed that the bus number as reported by the OS may change across
 | 
			
		||||
// OS revisions.
 | 
			
		||||
//
 | 
			
		||||
// A SPI port is constructed of the bus number and the chip select (CS) number.
 | 
			
		||||
//
 | 
			
		||||
// When the SPI port is provided by an off board plug and play bus like USB via
 | 
			
		||||
// a FT232H USB device, there can be no associated number.
 | 
			
		||||
func Open(name string) (spi.PortCloser, error) {
 | 
			
		||||
	var r *Ref
 | 
			
		||||
	var err error
 | 
			
		||||
	func() {
 | 
			
		||||
		mu.Lock()
 | 
			
		||||
		defer mu.Unlock()
 | 
			
		||||
		if len(byName) == 0 {
 | 
			
		||||
			err = errors.New("spireg: no port found; did you forget to call Init()?")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if len(name) == 0 {
 | 
			
		||||
			r = getDefault()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// Try by name, by alias, by number.
 | 
			
		||||
		if r = byName[name]; r == nil {
 | 
			
		||||
			if r = byAlias[name]; r == nil {
 | 
			
		||||
				if i, err2 := strconv.Atoi(name); err2 == nil {
 | 
			
		||||
					r = byNumber[i]
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if r == nil {
 | 
			
		||||
		return nil, errors.New("spireg: can't open unknown port: " + strconv.Quote(name))
 | 
			
		||||
	}
 | 
			
		||||
	return r.Open()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// All returns a copy of all the registered references to all know SPI ports
 | 
			
		||||
// available on this host.
 | 
			
		||||
//
 | 
			
		||||
// The list is sorted by the port name.
 | 
			
		||||
func All() []*Ref {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	out := make([]*Ref, 0, len(byName))
 | 
			
		||||
	for _, v := range byName {
 | 
			
		||||
		r := &Ref{Name: v.Name, Aliases: make([]string, len(v.Aliases)), Number: v.Number, Open: v.Open}
 | 
			
		||||
		copy(r.Aliases, v.Aliases)
 | 
			
		||||
		out = insertRef(out, r)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Register registers a SPI port.
 | 
			
		||||
//
 | 
			
		||||
// Registering the same port name twice is an error, e.g. o.Name(). o.Number()
 | 
			
		||||
// can be -1 to signify that the port doesn't have an inherent "bus number". A
 | 
			
		||||
// good example is a port provided over a FT232H device connected on an USB bus.
 | 
			
		||||
// In this case, the port name should be created from the serial number of the
 | 
			
		||||
// device for unique identification.
 | 
			
		||||
//
 | 
			
		||||
// Only ports with the CS #0 are registered with their number.
 | 
			
		||||
func Register(name string, aliases []string, number int, o Opener) error {
 | 
			
		||||
	if len(name) == 0 {
 | 
			
		||||
		return errors.New("spireg: can't register a port with no name")
 | 
			
		||||
	}
 | 
			
		||||
	if o == nil {
 | 
			
		||||
		return errors.New("spireg: can't register port " + strconv.Quote(name) + " with nil Opener")
 | 
			
		||||
	}
 | 
			
		||||
	if number < -1 {
 | 
			
		||||
		return errors.New("spireg: can't register port " + strconv.Quote(name) + " with invalid port number " + strconv.Itoa(number))
 | 
			
		||||
	}
 | 
			
		||||
	if _, err := strconv.Atoi(name); err == nil {
 | 
			
		||||
		return errors.New("spireg: can't register port " + strconv.Quote(name) + " with name being only a number")
 | 
			
		||||
	}
 | 
			
		||||
	if strings.Contains(name, ":") {
 | 
			
		||||
		return errors.New("spireg: can't register port " + strconv.Quote(name) + " with name containing ':'")
 | 
			
		||||
	}
 | 
			
		||||
	for _, alias := range aliases {
 | 
			
		||||
		if len(alias) == 0 {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an empty alias")
 | 
			
		||||
		}
 | 
			
		||||
		if name == alias {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an alias the same as the port name")
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := strconv.Atoi(alias); err == nil {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an alias that is a number: " + strconv.Quote(alias))
 | 
			
		||||
		}
 | 
			
		||||
		if strings.Contains(alias, ":") {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an alias containing ':': " + strconv.Quote(alias))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if _, ok := byName[name]; ok {
 | 
			
		||||
		return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice")
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := byAlias[name]; ok {
 | 
			
		||||
		return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice; it is already an alias")
 | 
			
		||||
	}
 | 
			
		||||
	if number != -1 {
 | 
			
		||||
		if _, ok := byNumber[number]; ok {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + "; port number " + strconv.Itoa(number) + " is already registered")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for _, alias := range aliases {
 | 
			
		||||
		if _, ok := byName[alias]; ok {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice; alias " + strconv.Quote(alias) + " is already a port")
 | 
			
		||||
		}
 | 
			
		||||
		if _, ok := byAlias[alias]; ok {
 | 
			
		||||
			return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice; alias " + strconv.Quote(alias) + " is already an alias")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r := &Ref{Name: name, Aliases: make([]string, len(aliases)), Number: number, Open: o}
 | 
			
		||||
	copy(r.Aliases, aliases)
 | 
			
		||||
	byName[name] = r
 | 
			
		||||
	if number != -1 {
 | 
			
		||||
		byNumber[number] = r
 | 
			
		||||
	}
 | 
			
		||||
	for _, alias := range aliases {
 | 
			
		||||
		byAlias[alias] = r
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unregister removes a previously registered SPI port.
 | 
			
		||||
//
 | 
			
		||||
// This can happen when a SPI port is exposed via an USB device and the device
 | 
			
		||||
// is unplugged.
 | 
			
		||||
func Unregister(name string) error {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	r := byName[name]
 | 
			
		||||
	if r == nil {
 | 
			
		||||
		return errors.New("spireg: can't unregister unknown port name " + strconv.Quote(name))
 | 
			
		||||
	}
 | 
			
		||||
	delete(byName, name)
 | 
			
		||||
	delete(byNumber, r.Number)
 | 
			
		||||
	for _, alias := range r.Aliases {
 | 
			
		||||
		delete(byAlias, alias)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mu     sync.Mutex
 | 
			
		||||
	byName = map[string]*Ref{}
 | 
			
		||||
	// Caches
 | 
			
		||||
	byNumber = map[int]*Ref{}
 | 
			
		||||
	byAlias  = map[string]*Ref{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// getDefault returns the Ref that should be used as the default port.
 | 
			
		||||
func getDefault() *Ref {
 | 
			
		||||
	var o *Ref
 | 
			
		||||
	if len(byNumber) == 0 {
 | 
			
		||||
		// Fallback to use byName using a lexical sort.
 | 
			
		||||
		name := ""
 | 
			
		||||
		for n, o2 := range byName {
 | 
			
		||||
			if len(name) == 0 || n < name {
 | 
			
		||||
				o = o2
 | 
			
		||||
				name = n
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return o
 | 
			
		||||
	}
 | 
			
		||||
	number := int((^uint(0)) >> 1)
 | 
			
		||||
	for n, o2 := range byNumber {
 | 
			
		||||
		if number > n {
 | 
			
		||||
			number = n
 | 
			
		||||
			o = o2
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return o
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func insertRef(l []*Ref, r *Ref) []*Ref {
 | 
			
		||||
	n := r.Name
 | 
			
		||||
	i := search(len(l), func(i int) bool { return l[i].Name > n })
 | 
			
		||||
	l = append(l, nil)
 | 
			
		||||
	copy(l[i+1:], l[i:])
 | 
			
		||||
	l[i] = r
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// search implements the same algorithm as sort.Search().
 | 
			
		||||
//
 | 
			
		||||
// It was extracted to to not depend on sort, which depends on reflect.
 | 
			
		||||
func search(n int, f func(int) bool) int {
 | 
			
		||||
	lo := 0
 | 
			
		||||
	for hi := n; lo < hi; {
 | 
			
		||||
		if i := int(uint(lo+hi) >> 1); !f(i) {
 | 
			
		||||
			lo = i + 1
 | 
			
		||||
		} else {
 | 
			
		||||
			hi = i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return lo
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user