<commit_before>// Package herots provide fast way to create TLS services: server and client.
//
// Explanation of the name: HERald Of The Swarm
//
// By the way - have a nice day :)
package herots

import (
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
)

////////////////////////////////////////////////////////////////////////////////
//                       Shared functions and structs                         //
////////////////////////////////////////////////////////////////////////////////

// LogHandlerFunc - type for log handler functions
type LogHandlerFunc func(message string, lvl LogLevelType)

// LogLevelType - declare the level of informatyvity of log message
type LogLevelType int

// predefined LogLevelType levels
const (
	LogLevelNone = iota
	LogLevelNotice
	LogLevelInfo
	LogLevelError
)

// log - struct for internal log service
type log struct {
	LogLevel       LogLevelType
	LogDestination io.Writer
	Handler        LogHandlerFunc
}

func (l *log) Log(message string, lvl LogLevelType) {
	if l.Handler != nil {
		l.Handler(message, lvl)
		return
	}

	if l.LogLevel == 0 {
		return
	}

	if lvl <= l.LogLevel {
		fmt.Fprintf(l.LogDestination, "herots: %s\n", message)
	}

}

// loadKeyPair - internal function for load certificate and private key pair.
func loadKeyPair(cert, key []byte) (tls.Certificate, *x509.Certificate, error) {
	c, err := tls.X509KeyPair(cert, key)
	if err != nil {
		return tls.Certificate{}, &x509.Certificate{}, err
	}

	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return tls.Certificate{}, &x509.Certificate{}, err
	}

	return c, ca, nil
}

// Options - structure, which is used to configure a TLS server and client.
type Options struct {
	// Server host.
	//
	// Default: '127.0.0.1'.
	Host string

	// Server port.
	//
	// Default: '9000'.
	Port int

	// LogLevel provides the opportunity to choose the level of
	// information messages.
	// Each level includes the messages from the previous level.
	// LogLevelNone   - no messages // 0
	// LogLevelNotice - notice      // 1
	// LogLevelInfo   - info        // 2
	// LogLevelError  - error       // 3
	//
	// Default: LogLevelNone.
	LogLevel LogLevelType

	// LogDestination provides the opportunity to choose the own
	// destination for log messages (errors, info, etc).
	//
	// Default: 'os.Stdout'.
	LogDestination io.Writer

	// LogHandler takes log messages to bypass the internal
	// mechanism of the message processing
	//
	// If LogHandler is selected - all log settings will be ignored.
	LogHandler LogHandlerFunc

	// TLSAuthType - refer to http://golang.org/pkg/crypto/tls/#ClientAuthType
	//
	// This option ignored for client implementation.
	//
	// Default: tls.RequireAnyClientCert
	TLSAuthType tls.ClientAuthType
}

// predefined errors messages
const (
	LoadKeyPairError   = "load key pair error"
	NoKeyPairLoadError = "no load key pair (use LoadKeyPair func)"
)

////////////////////////////////////////////////////////////////////////////////
//                                  Server                                    //
////////////////////////////////////////////////////////////////////////////////

// Server - primary struct for server implementation.
type Server struct {
	options *Options
	certs   struct {
		Cert tls.Certificate
		Pool *x509.CertPool
	}
	listener net.Listener
	logger   *log
}

// NewServer - function for create Server struct
func NewServer(o *Options) *Server {
	s := &Server{}

	// check mandatory options
	if o.LogDestination == nil {
		o.LogDestination = os.Stdout
	}

	if o.Port == 0 {
		o.Port = 9000
	}

	if o.TLSAuthType == 0 {
		o.TLSAuthType = tls.RequireAnyClientCert
	}

	l := &log{
		LogLevel:       o.LogLevel,
		LogDestination: o.LogDestination,
		Handler:        o.LogHandler,
	}

	s.options = o
	s.logger = l

	return s
}

// LoadKeyPair - function for load certificate and private key pair.
//
// Public/private key pair require as PEM encoded data.
func (s *Server) LoadKeyPair(cert, key []byte) error {
	c, ca, err := loadKeyPair(cert, key)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}

	s.certs.Cert = c

	s.certs.Pool = x509.NewCertPool()
	s.certs.Pool.AddCert(ca)

	s.logger.Log("load key pair - ok", LogLevelInfo)

	return nil
}

// AddClientCACert - function for adding client CA certificate to
// x509.CertPool (tls.Config.ClientCAs).
//
// By default server add cert from server public/private key pair (LoadKeyPair)
// to cert pool.
func (s *Server) AddClientCACert(cert []byte) error {
	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("load client CA cert error: %v\n", err)
	}
	s.certs.Pool.AddCert(ca)

	s.logger.Log("load client CA cert - ok", LogLevelInfo)

	return nil
}

// Accept - accept and return connections.
func (s *Server) Accept() (net.Conn, error) {
	conn, err := s.listener.Accept()
	if err != nil {
		s.logger.Log("accept conn error: "+err.Error(), LogLevelError)
		return conn, fmt.Errorf("connection accept fail: %v\n", err)
	}
	s.logger.Log("accepted conn from "+conn.RemoteAddr().String(), LogLevelInfo)
	return conn, nil
}

// Start - function for start server.
func (s *Server) Start() error {
	// load keypair check
	if len(s.certs.Cert.Certificate) == 0 {
		return fmt.Errorf("%s\n", NoKeyPairLoadError)
	}

	config := tls.Config{
		ClientAuth:   s.options.TLSAuthType,
		Certificates: []tls.Certificate{s.certs.Cert},
		ClientCAs:    s.certs.Pool,
		Rand:         rand.Reader,
	}

	service := s.options.Host + ":" + strconv.Itoa(s.options.Port)

	listener, err := tls.Listen("tcp", service, &config)
	if err != nil {
		return fmt.Errorf("start tls server fail: %v\n", err)
	}
	s.listener = listener

	s.logger.Log("listening on "+service, LogLevelNotice)

	return nil
}

////////////////////////////////////////////////////////////////////////////////
//                                  Client                                    //
////////////////////////////////////////////////////////////////////////////////

// Client - primary struct for client implementation.
type Client struct {
	options *Options
	certs   struct {
		Cert tls.Certificate
		Pool *x509.CertPool
	}
	logger *log
}

// NewClient - function for create Client struct
func NewClient(o *Options) *Client {
	c := &Client{}

	// check mandatory options
	if o.LogDestination == nil {
		o.LogDestination = os.Stdout
	}

	if o.Port == 0 {
		o.Port = 9000
	}

	l := &log{
		LogLevel:       o.LogLevel,
		LogDestination: o.LogDestination,
	}

	c.options = o
	c.logger = l
	c.certs.Pool = x509.NewCertPool()

	return c
}

// LoadKeyPair - function for load certificate and private key pair.
//
// Public/private key pair require as PEM encoded data.
func (c *Client) LoadKeyPair(cert, key []byte) error {
	c0, ca, err := loadKeyPair(cert, key)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}

	c.certs.Cert = c0
	c.certs.Pool.AddCert(ca)

	c.logger.Log("load key pair - ok", LogLevelInfo)

	return nil
}

// AddCertToRootCA - function to load additional certificates to root CA pool.
func (c *Client) AddCertToRootCA(cert []byte) error {
	pemData, _ := pem.Decode(cert)

	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("load CA cert error: %v\n", err)
	}

	c.certs.Pool.AddCert(ca)

	c.logger.Log("add cert to root CA - ok", LogLevelInfo)

	return nil
}

// Dial - function for start connection with server.
func (c *Client) Dial() (*tls.Conn, error) {
	// load keypair check
	if len(c.certs.Cert.Certificate) == 0 {
		return nil, fmt.Errorf("%s\n", NoKeyPairLoadError)
	}

	config := &tls.Config{
		Certificates:       []tls.Certificate{c.certs.Cert},
		InsecureSkipVerify: false,
		RootCAs:            c.certs.Pool,
	}

	service := c.options.Host + ":" + strconv.Itoa(c.options.Port)

	conn, err := tls.Dial("tcp", service, config)
	if err != nil {
		return nil, fmt.Errorf("fail to dial with server: %v\n", err)
	}

	c.logger.Log("dial to "+service+" - ok", LogLevelInfo)

	return conn, nil
}
<commit_msg>add LogHandler to Client<commit_after>// Package herots provide fast way to create TLS services: server and client.
//
// Explanation of the name: HERald Of The Swarm
//
// By the way - have a nice day :)
package herots

import (
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
)

////////////////////////////////////////////////////////////////////////////////
//                       Shared functions and structs                         //
////////////////////////////////////////////////////////////////////////////////

// LogHandlerFunc - type for log handler functions
type LogHandlerFunc func(message string, lvl LogLevelType)

// LogLevelType - declare the level of informatyvity of log message
type LogLevelType int

// predefined LogLevelType levels
const (
	LogLevelNone = iota
	LogLevelNotice
	LogLevelInfo
	LogLevelError
)

// log - struct for internal log service
type log struct {
	LogLevel       LogLevelType
	LogDestination io.Writer
	Handler        LogHandlerFunc
}

func (l *log) Log(message string, lvl LogLevelType) {
	if l.Handler != nil {
		l.Handler(message, lvl)
		return
	}

	if l.LogLevel == 0 {
		return
	}

	if lvl <= l.LogLevel {
		fmt.Fprintf(l.LogDestination, "herots: %s\n", message)
	}

}

// loadKeyPair - internal function for load certificate and private key pair.
func loadKeyPair(cert, key []byte) (tls.Certificate, *x509.Certificate, error) {
	c, err := tls.X509KeyPair(cert, key)
	if err != nil {
		return tls.Certificate{}, &x509.Certificate{}, err
	}

	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return tls.Certificate{}, &x509.Certificate{}, err
	}

	return c, ca, nil
}

// Options - structure, which is used to configure a TLS server and client.
type Options struct {
	// Server host.
	//
	// Default: '127.0.0.1'.
	Host string

	// Server port.
	//
	// Default: '9000'.
	Port int

	// LogLevel provides the opportunity to choose the level of
	// information messages.
	// Each level includes the messages from the previous level.
	// LogLevelNone   - no messages // 0
	// LogLevelNotice - notice      // 1
	// LogLevelInfo   - info        // 2
	// LogLevelError  - error       // 3
	//
	// Default: LogLevelNone.
	LogLevel LogLevelType

	// LogDestination provides the opportunity to choose the own
	// destination for log messages (errors, info, etc).
	//
	// Default: 'os.Stdout'.
	LogDestination io.Writer

	// LogHandler takes log messages to bypass the internal
	// mechanism of the message processing
	//
	// If LogHandler is selected - all log settings will be ignored.
	LogHandler LogHandlerFunc

	// TLSAuthType - refer to http://golang.org/pkg/crypto/tls/#ClientAuthType
	//
	// This option ignored for client implementation.
	//
	// Default: tls.RequireAnyClientCert
	TLSAuthType tls.ClientAuthType
}

// predefined errors messages
const (
	LoadKeyPairError   = "load key pair error"
	NoKeyPairLoadError = "no load key pair (use LoadKeyPair func)"
)

////////////////////////////////////////////////////////////////////////////////
//                                  Server                                    //
////////////////////////////////////////////////////////////////////////////////

// Server - primary struct for server implementation.
type Server struct {
	options *Options
	certs   struct {
		Cert tls.Certificate
		Pool *x509.CertPool
	}
	listener net.Listener
	logger   *log
}

// NewServer - function for create Server struct
func NewServer(o *Options) *Server {
	s := &Server{}

	// check mandatory options
	if o.LogDestination == nil {
		o.LogDestination = os.Stdout
	}

	if o.Port == 0 {
		o.Port = 9000
	}

	if o.TLSAuthType == 0 {
		o.TLSAuthType = tls.RequireAnyClientCert
	}

	l := &log{
		LogLevel:       o.LogLevel,
		LogDestination: o.LogDestination,
		Handler:        o.LogHandler,
	}

	s.options = o
	s.logger = l

	return s
}

// LoadKeyPair - function for load certificate and private key pair.
//
// Public/private key pair require as PEM encoded data.
func (s *Server) LoadKeyPair(cert, key []byte) error {
	c, ca, err := loadKeyPair(cert, key)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}

	s.certs.Cert = c

	s.certs.Pool = x509.NewCertPool()
	s.certs.Pool.AddCert(ca)

	s.logger.Log("load key pair - ok", LogLevelInfo)

	return nil
}

// AddClientCACert - function for adding client CA certificate to
// x509.CertPool (tls.Config.ClientCAs).
//
// By default server add cert from server public/private key pair (LoadKeyPair)
// to cert pool.
func (s *Server) AddClientCACert(cert []byte) error {
	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("load client CA cert error: %v\n", err)
	}
	s.certs.Pool.AddCert(ca)

	s.logger.Log("load client CA cert - ok", LogLevelInfo)

	return nil
}

// Accept - accept and return connections.
func (s *Server) Accept() (net.Conn, error) {
	conn, err := s.listener.Accept()
	if err != nil {
		s.logger.Log("accept conn error: "+err.Error(), LogLevelError)
		return conn, fmt.Errorf("connection accept fail: %v\n", err)
	}
	s.logger.Log("accepted conn from "+conn.RemoteAddr().String(), LogLevelInfo)
	return conn, nil
}

// Start - function for start server.
func (s *Server) Start() error {
	// load keypair check
	if len(s.certs.Cert.Certificate) == 0 {
		return fmt.Errorf("%s\n", NoKeyPairLoadError)
	}

	config := tls.Config{
		ClientAuth:   s.options.TLSAuthType,
		Certificates: []tls.Certificate{s.certs.Cert},
		ClientCAs:    s.certs.Pool,
		Rand:         rand.Reader,
	}

	service := s.options.Host + ":" + strconv.Itoa(s.options.Port)

	listener, err := tls.Listen("tcp", service, &config)
	if err != nil {
		return fmt.Errorf("start tls server fail: %v\n", err)
	}
	s.listener = listener

	s.logger.Log("listening on "+service, LogLevelNotice)

	return nil
}

////////////////////////////////////////////////////////////////////////////////
//                                  Client                                    //
////////////////////////////////////////////////////////////////////////////////

// Client - primary struct for client implementation.
type Client struct {
	options *Options
	certs   struct {
		Cert tls.Certificate
		Pool *x509.CertPool
	}
	logger *log
}

// NewClient - function for create Client struct
func NewClient(o *Options) *Client {
	c := &Client{}

	// check mandatory options
	if o.LogDestination == nil {
		o.LogDestination = os.Stdout
	}

	if o.Port == 0 {
		o.Port = 9000
	}

	l := &log{
		LogLevel:       o.LogLevel,
		LogDestination: o.LogDestination,
		Handler:        o.LogHandler,
	}

	c.options = o
	c.logger = l
	c.certs.Pool = x509.NewCertPool()

	return c
}

// LoadKeyPair - function for load certificate and private key pair.
//
// Public/private key pair require as PEM encoded data.
func (c *Client) LoadKeyPair(cert, key []byte) error {
	c0, ca, err := loadKeyPair(cert, key)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}

	c.certs.Cert = c0
	c.certs.Pool.AddCert(ca)

	c.logger.Log("load key pair - ok", LogLevelInfo)

	return nil
}

// AddCertToRootCA - function to load additional certificates to root CA pool.
func (c *Client) AddCertToRootCA(cert []byte) error {
	pemData, _ := pem.Decode(cert)

	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("load CA cert error: %v\n", err)
	}

	c.certs.Pool.AddCert(ca)

	c.logger.Log("add cert to root CA - ok", LogLevelInfo)

	return nil
}

// Dial - function for start connection with server.
func (c *Client) Dial() (*tls.Conn, error) {
	// load keypair check
	if len(c.certs.Cert.Certificate) == 0 {
		return nil, fmt.Errorf("%s\n", NoKeyPairLoadError)
	}

	config := &tls.Config{
		Certificates:       []tls.Certificate{c.certs.Cert},
		InsecureSkipVerify: false,
		RootCAs:            c.certs.Pool,
	}

	service := c.options.Host + ":" + strconv.Itoa(c.options.Port)

	conn, err := tls.Dial("tcp", service, config)
	if err != nil {
		return nil, fmt.Errorf("fail to dial with server: %v\n", err)
	}

	c.logger.Log("dial to "+service+" - ok", LogLevelInfo)

	return conn, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"os"
	"os/exec"
	"testing"
)

func TestParseCov(t *testing.T) {
	cmd := exec.Command("gocov", "test", "github.com/BenLubar/goveralls/goveralls-test")
	cmd.Stderr = os.Stderr
	cov, err := cmd.Output()
	if err != nil {
		t.Fatal(err)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
		return
	}

	files := ParseCov(cov, wd)
	filesJson, err := json.Marshal(files)
	if err != nil {
		t.Fatal(err)
		return
	}

	expected, err := ioutil.ReadFile("goveralls-test/expected.json")
	if err != nil {
		t.Fatal(err)
		return
	}

	if !bytes.Equal(filesJson, expected) {
		t.Errorf("Expected:\t%q", expected)
		t.Errorf("Actual:\t%q", filesJson)
	}
}
<commit_msg>re-encode the json to avoid subtle encoder differences (& was being encoded as a unicode codepoint instead of a single byte in one case but not the other)<commit_after>package main

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"os/exec"
	"bytes"
	"testing"
)

func TestParseCov(t *testing.T) {
	cmd := exec.Command("gocov", "test", "github.com/BenLubar/goveralls/goveralls-test")
	cmd.Stderr = os.Stderr
	cov, err := cmd.Output()
	if err != nil {
		t.Fatal(err)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
		return
	}

	files := ParseCov(cov, wd)
	if err != nil {
		t.Fatal(err)
		return
	}

	expectedJson, err := ioutil.ReadFile("goveralls-test/expected.json")
	if err != nil {
		t.Fatal(err)
		return
	}
	var expected []*File
	err = json.Unmarshal(expectedJson, &expected)
	if err != nil {
		t.Fatal(err)
		return
	}

	filesJson, _ := json.Marshal(files)
	expectedJson, _ = json.Marshal(expected)
	if !bytes.Equal(filesJson, expectedJson) {
		t.Errorf("Actual:  \t%q", filesJson)
		t.Errorf("Expected:\t%q", expectedJson)
	}
}
<|endoftext|>


<commit_before>package character

import (
	"net/http"
	"sort"

	"github.com/aerogo/aero"
	"github.com/animenotifier/arn"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/utils"
	"github.com/fatih/color"
)

const (
	maxRelevantCharacters = 12
)

// Get character.
func Get(ctx *aero.Context) string {
	user := utils.GetUser(ctx)
	id := ctx.Get("id")
	character, err := arn.GetCharacter(id)

	if err != nil {
		return ctx.Error(http.StatusNotFound, "Character not found", err)
	}

	// Anime
	characterAnime := character.Anime()

	sort.Slice(characterAnime, func(i, j int) bool {
		if characterAnime[i].StartDate == "" {
			return false
		}

		if characterAnime[j].StartDate == "" {
			return true
		}

		return characterAnime[i].StartDate < characterAnime[j].StartDate
	})

	// Characters from the same anime
	characterAppearances := map[string]int{}

	for _, anime := range characterAnime {
		for _, animeCharacter := range anime.Characters().Items {
			if animeCharacter.CharacterID == character.ID {
				continue
			}

			characterAppearances[animeCharacter.CharacterID]++
		}
	}

	relevantCharacters := []*arn.Character{}

	for characterID := range characterAppearances {
		relevantCharacter, err := arn.GetCharacter(characterID)

		if !relevantCharacter.HasImage() {
			continue
		}

		if err != nil {
			color.Red(err.Error())
			continue
		}

		relevantCharacters = append(relevantCharacters, relevantCharacter)
	}

	sort.Slice(relevantCharacters, func(i, j int) bool {
		aRelevance := characterAppearances[relevantCharacters[i].ID]
		bRelevance := characterAppearances[relevantCharacters[j].ID]

		if aRelevance == bRelevance {
			aLikes := len(relevantCharacters[i].Likes)
			bLikes := len(relevantCharacters[j].Likes)

			if aLikes == bLikes {
				return relevantCharacters[i].Name.Canonical < relevantCharacters[j].Name.Canonical
			}

			return aLikes > bLikes
		}

		return aRelevance > bRelevance
	})

	if len(relevantCharacters) > maxRelevantCharacters {
		relevantCharacters = relevantCharacters[:maxRelevantCharacters]
	}

	// Quotes
	mainQuote := character.MainQuote()
	quotes := character.Quotes()

	arn.SortQuotesPopularFirst(quotes)

	// Set OpenGraph attributes
	description := utils.CutLongDescription(character.Description)

	ctx.Data = &arn.OpenGraph{
		Tags: map[string]string{
			"og:title":       character.Name.Canonical,
			"og:image":       "https:" + character.ImageLink("large"),
			"og:url":         "https://" + ctx.App.Config.Domain + character.Link(),
			"og:site_name":   "notify.moe",
			"og:description": description,

			// The OpenGraph type "profile" is meant for real-life persons but I think it's okay in this context.
			// An alternative would be to use "article" which is mostly used for blog posts and news.
			"og:type": "profile",
		},
		Meta: map[string]string{
			"description": description,
			"keywords":    character.Name.Canonical + ",anime,character",
		},
	}

	// Friends
	var friends []*arn.User

	if user != nil {
		friendIDs := utils.Intersection(character.Likes, user.Follows().Items)
		friendObjects := arn.DB.GetMany("User", friendIDs)

		for _, obj := range friendObjects {
			if obj == nil {
				continue
			}

			friends = append(friends, obj.(*arn.User))
		}
	}

	return ctx.HTML(components.CharacterDetails(character, characterAnime, quotes, friends, relevantCharacters, mainQuote, user))
}
<commit_msg>Check relevant character before accessing it<commit_after>package character

import (
	"net/http"
	"sort"

	"github.com/aerogo/aero"
	"github.com/animenotifier/arn"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/utils"
	"github.com/fatih/color"
)

const (
	maxRelevantCharacters = 12
)

// Get character.
func Get(ctx *aero.Context) string {
	user := utils.GetUser(ctx)
	id := ctx.Get("id")
	character, err := arn.GetCharacter(id)

	if err != nil {
		return ctx.Error(http.StatusNotFound, "Character not found", err)
	}

	// Anime
	characterAnime := character.Anime()

	sort.Slice(characterAnime, func(i, j int) bool {
		if characterAnime[i].StartDate == "" {
			return false
		}

		if characterAnime[j].StartDate == "" {
			return true
		}

		return characterAnime[i].StartDate < characterAnime[j].StartDate
	})

	// Characters from the same anime
	characterAppearances := map[string]int{}

	for _, anime := range characterAnime {
		for _, animeCharacter := range anime.Characters().Items {
			if animeCharacter.CharacterID == character.ID {
				continue
			}

			characterAppearances[animeCharacter.CharacterID]++
		}
	}

	relevantCharacters := []*arn.Character{}

	for characterID := range characterAppearances {
		relevantCharacter, err := arn.GetCharacter(characterID)

		if err != nil {
			color.Red(err.Error())
			continue
		}

		if !relevantCharacter.HasImage() {
			continue
		}

		relevantCharacters = append(relevantCharacters, relevantCharacter)
	}

	sort.Slice(relevantCharacters, func(i, j int) bool {
		aRelevance := characterAppearances[relevantCharacters[i].ID]
		bRelevance := characterAppearances[relevantCharacters[j].ID]

		if aRelevance == bRelevance {
			aLikes := len(relevantCharacters[i].Likes)
			bLikes := len(relevantCharacters[j].Likes)

			if aLikes == bLikes {
				return relevantCharacters[i].Name.Canonical < relevantCharacters[j].Name.Canonical
			}

			return aLikes > bLikes
		}

		return aRelevance > bRelevance
	})

	if len(relevantCharacters) > maxRelevantCharacters {
		relevantCharacters = relevantCharacters[:maxRelevantCharacters]
	}

	// Quotes
	mainQuote := character.MainQuote()
	quotes := character.Quotes()

	arn.SortQuotesPopularFirst(quotes)

	// Set OpenGraph attributes
	description := utils.CutLongDescription(character.Description)

	ctx.Data = &arn.OpenGraph{
		Tags: map[string]string{
			"og:title":       character.Name.Canonical,
			"og:image":       "https:" + character.ImageLink("large"),
			"og:url":         "https://" + ctx.App.Config.Domain + character.Link(),
			"og:site_name":   "notify.moe",
			"og:description": description,

			// The OpenGraph type "profile" is meant for real-life persons but I think it's okay in this context.
			// An alternative would be to use "article" which is mostly used for blog posts and news.
			"og:type": "profile",
		},
		Meta: map[string]string{
			"description": description,
			"keywords":    character.Name.Canonical + ",anime,character",
		},
	}

	// Friends
	var friends []*arn.User

	if user != nil {
		friendIDs := utils.Intersection(character.Likes, user.Follows().Items)
		friendObjects := arn.DB.GetMany("User", friendIDs)

		for _, obj := range friendObjects {
			if obj == nil {
				continue
			}

			friends = append(friends, obj.(*arn.User))
		}
	}

	return ctx.HTML(components.CharacterDetails(character, characterAnime, quotes, friends, relevantCharacters, mainQuote, user))
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, 2014 Conformal Systems LLC <info@conformal.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package main

import (
	"bytes"
	"errors"
	"fmt"
	badrand "math/rand"
	"sort"
	"sync"
	"time"

	"github.com/conformal/btcchain"
	"github.com/conformal/btcscript"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwallet/txstore"
	"github.com/conformal/btcwallet/wallet"
	"github.com/conformal/btcwire"
)

// InsufficientFundsError represents an error where there are not enough
// funds from unspent tx outputs for a wallet to create a transaction.
// This may be caused by not enough inputs for all of the desired total
// transaction output amount, or due to
type InsufficientFundsError struct {
	in, out, fee btcutil.Amount
}

// Error satisifies the builtin error interface.
func (e InsufficientFundsError) Error() string {
	total := e.out + e.fee
	if e.fee == 0 {
		return fmt.Sprintf("insufficient funds: transaction requires "+
			"%s input but only %v spendable", total, e.in)
	}
	return fmt.Sprintf("insufficient funds: transaction requires %s input "+
		"(%v output + %v fee) but only %v spendable", total, e.out,
		e.fee, e.in)
}

// ErrNonPositiveAmount represents an error where a bitcoin amount is
// not positive (either negative, or zero).
var ErrNonPositiveAmount = errors.New("amount is not positive")

// ErrNegativeFee represents an error where a fee is erroneously
// negative.
var ErrNegativeFee = errors.New("fee is negative")

// minTxFee is the default minimum transation fee (0.0001 BTC,
// measured in satoshis) added to transactions requiring a fee.
const minTxFee = 10000

// TxFeeIncrement represents the global transaction fee per KB of Tx
// added to newly-created transactions and sent as a reward to the block
// miner.  i is measured in satoshis.
var TxFeeIncrement = struct {
	sync.Mutex
	i btcutil.Amount
}{
	i: minTxFee,
}

type CreatedTx struct {
	tx         *btcutil.Tx
	inputs     []txstore.Credit
	changeAddr btcutil.Address
}

// ByAmount defines the methods needed to satisify sort.Interface to
// sort a slice of Utxos by their amount.
type ByAmount []txstore.Credit

func (u ByAmount) Len() int           { return len(u) }
func (u ByAmount) Less(i, j int) bool { return u[i].Amount() < u[j].Amount() }
func (u ByAmount) Swap(i, j int)      { u[i], u[j] = u[j], u[i] }

// selectInputs selects the minimum number possible of unspent
// outputs to use to create a new transaction that spends amt satoshis.
// btcout is the total number of satoshis which would be spent by the
// combination of all selected previous outputs.  err will equal
// ErrInsufficientFunds if there are not enough unspent outputs to spend amt
// amt.
func selectInputs(eligible []txstore.Credit, amt, fee btcutil.Amount,
	minconf int) (selected []txstore.Credit, out btcutil.Amount, err error) {

	// Iterate throguh eligible transactions, appending to outputs and
	// increasing out.  This is finished when out is greater than the
	// requested amt to spend.
	selected = make([]txstore.Credit, 0, len(eligible))
	for _, e := range eligible {
		selected = append(selected, e)
		out += e.Amount()
		if out >= amt+fee {
			return selected, out, nil
		}
	}
	if out < amt+fee {
		return nil, 0, InsufficientFundsError{out, amt, fee}
	}

	return selected, out, nil
}

// txToPairs creates a raw transaction sending the amounts for each
// address/amount pair and fee to each address and the miner.  minconf
// specifies the minimum number of confirmations required before an
// unspent output is eligible for spending. Leftover input funds not sent
// to addr or as a fee for the miner are sent to a newly generated
// address. If change is needed to return funds back to an owned
// address, changeUtxo will point to a unconfirmed (height = -1, zeroed
// block hash) Utxo.  ErrInsufficientFunds is returned if there are not
// enough eligible unspent outputs to create the transaction.
func (a *Account) txToPairs(pairs map[string]btcutil.Amount,
	minconf int) (*CreatedTx, error) {

	// Wallet must be unlocked to compose transaction.
	if a.IsLocked() {
		return nil, wallet.ErrWalletLocked
	}

	// Create a new transaction which will include all input scripts.
	msgtx := btcwire.NewMsgTx()

	// Calculate minimum amount needed for inputs.
	var amt btcutil.Amount
	for _, v := range pairs {
		// Error out if any amount is negative.
		if v <= 0 {
			return nil, ErrNonPositiveAmount
		}
		amt += v
	}

	// Add outputs to new tx.
	for addrStr, amt := range pairs {
		addr, err := btcutil.DecodeAddress(addrStr, activeNet.Params)
		if err != nil {
			return nil, fmt.Errorf("cannot decode address: %s", err)
		}

		// Add output to spend amt to addr.
		pkScript, err := btcscript.PayToAddrScript(addr)
		if err != nil {
			return nil, fmt.Errorf("cannot create txout script: %s", err)
		}
		txout := btcwire.NewTxOut(int64(amt), pkScript)
		msgtx.AddTxOut(txout)
	}

	// Get current block's height and hash.
	bs, err := GetCurBlock()
	if err != nil {
		return nil, err
	}

	// Make a copy of msgtx before any inputs are added.  This will be
	// used as a starting point when trying a fee and starting over with
	// a higher fee if not enough was originally chosen.
	txNoInputs := msgtx.Copy()

	unspent, err := a.TxStore.UnspentOutputs()
	if err != nil {
		return nil, err
	}

	// Filter out unspendable outputs, that is, remove those that (at this
	// time) are not P2PKH outputs.  Other inputs must be manually included
	// in transactions and sent (for example, using createrawtransaction,
	// signrawtransaction, and sendrawtransaction).
	eligible := make([]txstore.Credit, 0, len(unspent))
	for i := range unspent {
		switch btcscript.GetScriptClass(unspent[i].TxOut().PkScript) {
		case btcscript.PubKeyHashTy:
			if !unspent[i].Confirmed(minconf, bs.Height) {
				continue
			}
			// Coinbase transactions must have have reached maturity
			// before their outputs may be spent.
			if unspent[i].IsCoinbase() {
				target := btcchain.CoinbaseMaturity
				if !unspent[i].Confirmed(target, bs.Height) {
					continue
				}
			}
			eligible = append(eligible, unspent[i])
		}
	}

	// Sort eligible inputs, as selectInputs expects these to be sorted
	// by amount in reverse order.
	sort.Sort(sort.Reverse(ByAmount(eligible)))

	var selectedInputs []txstore.Credit
	// changeAddr is nil/zeroed until a change address is needed, and reused
	// again in case a change utxo has already been chosen.
	var changeAddr btcutil.Address

	// Get the number of satoshis to increment fee by when searching for
	// the minimum tx fee needed.
	fee := btcutil.Amount(0)
	for {
		msgtx = txNoInputs.Copy()

		// Select eligible outputs to be used in transaction based on the amount
		// neededing to sent, and the current fee estimation.
		inputs, btcin, err := selectInputs(eligible, amt, fee, minconf)
		if err != nil {
			return nil, err
		}

		// Check if there are leftover unspent outputs, and return coins back to
		// a new address we own.
		change := btcin - amt - fee
		if change > 0 {
			// Get a new change address if one has not already been found.
			if changeAddr == nil {
				changeAddr, err = a.ChangeAddress(&bs, cfg.KeypoolSize)
				if err != nil {
					return nil, fmt.Errorf("failed to get next address: %s", err)
				}

				// Mark change address as belonging to this account.
				AcctMgr.MarkAddressForAccount(changeAddr, a)
			}

			// Spend change.
			pkScript, err := btcscript.PayToAddrScript(changeAddr)
			if err != nil {
				return nil, fmt.Errorf("cannot create txout script: %s", err)
			}
			msgtx.AddTxOut(btcwire.NewTxOut(int64(change), pkScript))

			// Randomize index of the change output.
			rng := badrand.New(badrand.NewSource(time.Now().UnixNano()))
			r := rng.Int31n(int32(len(msgtx.TxOut))) // random index
			c := len(msgtx.TxOut) - 1                // change index
			msgtx.TxOut[r], msgtx.TxOut[c] = msgtx.TxOut[c], msgtx.TxOut[r]
		}

		// Selected unspent outputs become new transaction's inputs.
		for _, ip := range inputs {
			msgtx.AddTxIn(btcwire.NewTxIn(ip.OutPoint(), nil))
		}
		for i, input := range inputs {
			// Errors don't matter here, as we only consider the
			// case where len(addrs) == 1.
			_, addrs, _, _ := input.Addresses(activeNet.Params)
			if len(addrs) != 1 {
				continue
			}
			apkh, ok := addrs[0].(*btcutil.AddressPubKeyHash)
			if !ok {
				continue // don't handle inputs to this yes
			}

			ai, err := a.Address(apkh)
			if err != nil {
				return nil, fmt.Errorf("cannot get address info: %v", err)
			}

			pka := ai.(wallet.PubKeyAddress)

			privkey, err := pka.PrivKey()
			if err == wallet.ErrWalletLocked {
				return nil, wallet.ErrWalletLocked
			} else if err != nil {
				return nil, fmt.Errorf("cannot get address key: %v", err)
			}

			sigscript, err := btcscript.SignatureScript(msgtx, i,
				input.TxOut().PkScript, btcscript.SigHashAll, privkey,
				ai.Compressed())
			if err != nil {
				return nil, fmt.Errorf("cannot create sigscript: %s", err)
			}
			msgtx.TxIn[i].SignatureScript = sigscript
		}

		noFeeAllowed := false
		if !cfg.DisallowFree {
			noFeeAllowed = allowFree(bs.Height, inputs, msgtx.SerializeSize())
		}
		if minFee := minimumFee(msgtx, noFeeAllowed); fee < minFee {
			fee = minFee
		} else {
			selectedInputs = inputs
			break
		}
	}

	// Validate msgtx before returning the raw transaction.
	flags := btcscript.ScriptCanonicalSignatures
	bip16 := time.Now().After(btcscript.Bip16Activation)
	if bip16 {
		flags |= btcscript.ScriptBip16
	}
	for i, txin := range msgtx.TxIn {
		engine, err := btcscript.NewScript(txin.SignatureScript,
			selectedInputs[i].TxOut().PkScript, i, msgtx, flags)
		if err != nil {
			return nil, fmt.Errorf("cannot create script engine: %s", err)
		}
		if err = engine.Execute(); err != nil {
			return nil, fmt.Errorf("cannot validate transaction: %s", err)
		}
	}

	buf := bytes.Buffer{}
	buf.Grow(msgtx.SerializeSize())
	if err := msgtx.BtcEncode(&buf, btcwire.ProtocolVersion); err != nil {
		// Hitting OOM by growing or writing to a bytes.Buffer already
		// panics, and all returned errors are unexpected.
		panic(err)
	}
	info := &CreatedTx{
		tx:         btcutil.NewTx(msgtx),
		inputs:     selectedInputs,
		changeAddr: changeAddr,
	}
	return info, nil
}

// minimumFee calculates the minimum fee required for a transaction.
// If allowFree is true, a fee may be zero so long as the entire
// transaction has a serialized length less than 1 kilobyte
// and none of the outputs contain a value less than 1 bitcent.
// Otherwise, the fee will be calculated using TxFeeIncrement,
// incrementing the fee for each kilobyte of transaction.
func minimumFee(tx *btcwire.MsgTx, allowFree bool) btcutil.Amount {
	txLen := tx.SerializeSize()
	TxFeeIncrement.Lock()
	incr := TxFeeIncrement.i
	TxFeeIncrement.Unlock()
	fee := btcutil.Amount(int64(1+txLen/1000) * int64(incr))

	if allowFree && txLen < 1000 {
		fee = 0
	}

	if fee < incr {
		for _, txOut := range tx.TxOut {
			if txOut.Value < btcutil.SatoshiPerBitcent {
				return incr
			}
		}
	}

	max := btcutil.Amount(btcutil.MaxSatoshi)
	if fee < 0 || fee > max {
		fee = max
	}

	return fee
}

// allowFree calculates the transaction priority and checks that the
// priority reaches a certain threshhold.  If the threshhold is
// reached, a free transaction fee is allowed.
func allowFree(curHeight int32, txouts []txstore.Credit, txSize int) bool {
	const blocksPerDayEstimate = 144
	const txSizeEstimate = 250

	var weightedSum int64
	for _, txout := range txouts {
		depth := chainDepth(txout.BlockHeight, curHeight)
		weightedSum += int64(txout.Amount()) * int64(depth)
	}
	priority := float64(weightedSum) / float64(txSize)
	return priority > float64(btcutil.SatoshiPerBitcoin)*blocksPerDayEstimate/txSizeEstimate
}

// chainDepth returns the chaindepth of a target given the current
// blockchain height.
func chainDepth(target, current int32) int32 {
	if target == -1 {
		// target is not yet in a block.
		return 0
	}

	// target is in a block.
	return current - target + 1
}
<commit_msg>InsufficientFundsError -> InsufficientFunds<commit_after>/*
 * Copyright (c) 2013, 2014 Conformal Systems LLC <info@conformal.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package main

import (
	"bytes"
	"errors"
	"fmt"
	badrand "math/rand"
	"sort"
	"sync"
	"time"

	"github.com/conformal/btcchain"
	"github.com/conformal/btcscript"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwallet/txstore"
	"github.com/conformal/btcwallet/wallet"
	"github.com/conformal/btcwire"
)

// InsufficientFundsError represents an error where there are not enough
// funds from unspent tx outputs for a wallet to create a transaction.
// This may be caused by not enough inputs for all of the desired total
// transaction output amount, or due to
type InsufficientFunds struct {
	in, out, fee btcutil.Amount
}

// Error satisifies the builtin error interface.
func (e InsufficientFunds) Error() string {
	total := e.out + e.fee
	if e.fee == 0 {
		return fmt.Sprintf("insufficient funds: transaction requires "+
			"%s input but only %v spendable", total, e.in)
	}
	return fmt.Sprintf("insufficient funds: transaction requires %s input "+
		"(%v output + %v fee) but only %v spendable", total, e.out,
		e.fee, e.in)
}

// ErrNonPositiveAmount represents an error where a bitcoin amount is
// not positive (either negative, or zero).
var ErrNonPositiveAmount = errors.New("amount is not positive")

// ErrNegativeFee represents an error where a fee is erroneously
// negative.
var ErrNegativeFee = errors.New("fee is negative")

// minTxFee is the default minimum transation fee (0.0001 BTC,
// measured in satoshis) added to transactions requiring a fee.
const minTxFee = 10000

// TxFeeIncrement represents the global transaction fee per KB of Tx
// added to newly-created transactions and sent as a reward to the block
// miner.  i is measured in satoshis.
var TxFeeIncrement = struct {
	sync.Mutex
	i btcutil.Amount
}{
	i: minTxFee,
}

type CreatedTx struct {
	tx         *btcutil.Tx
	inputs     []txstore.Credit
	changeAddr btcutil.Address
}

// ByAmount defines the methods needed to satisify sort.Interface to
// sort a slice of Utxos by their amount.
type ByAmount []txstore.Credit

func (u ByAmount) Len() int           { return len(u) }
func (u ByAmount) Less(i, j int) bool { return u[i].Amount() < u[j].Amount() }
func (u ByAmount) Swap(i, j int)      { u[i], u[j] = u[j], u[i] }

// selectInputs selects the minimum number possible of unspent
// outputs to use to create a new transaction that spends amt satoshis.
// btcout is the total number of satoshis which would be spent by the
// combination of all selected previous outputs.  err will equal
// ErrInsufficientFunds if there are not enough unspent outputs to spend amt
// amt.
func selectInputs(eligible []txstore.Credit, amt, fee btcutil.Amount,
	minconf int) (selected []txstore.Credit, out btcutil.Amount, err error) {

	// Iterate throguh eligible transactions, appending to outputs and
	// increasing out.  This is finished when out is greater than the
	// requested amt to spend.
	selected = make([]txstore.Credit, 0, len(eligible))
	for _, e := range eligible {
		selected = append(selected, e)
		out += e.Amount()
		if out >= amt+fee {
			return selected, out, nil
		}
	}
	if out < amt+fee {
		return nil, 0, InsufficientFunds{out, amt, fee}
	}

	return selected, out, nil
}

// txToPairs creates a raw transaction sending the amounts for each
// address/amount pair and fee to each address and the miner.  minconf
// specifies the minimum number of confirmations required before an
// unspent output is eligible for spending. Leftover input funds not sent
// to addr or as a fee for the miner are sent to a newly generated
// address. If change is needed to return funds back to an owned
// address, changeUtxo will point to a unconfirmed (height = -1, zeroed
// block hash) Utxo.  ErrInsufficientFunds is returned if there are not
// enough eligible unspent outputs to create the transaction.
func (a *Account) txToPairs(pairs map[string]btcutil.Amount,
	minconf int) (*CreatedTx, error) {

	// Wallet must be unlocked to compose transaction.
	if a.IsLocked() {
		return nil, wallet.ErrWalletLocked
	}

	// Create a new transaction which will include all input scripts.
	msgtx := btcwire.NewMsgTx()

	// Calculate minimum amount needed for inputs.
	var amt btcutil.Amount
	for _, v := range pairs {
		// Error out if any amount is negative.
		if v <= 0 {
			return nil, ErrNonPositiveAmount
		}
		amt += v
	}

	// Add outputs to new tx.
	for addrStr, amt := range pairs {
		addr, err := btcutil.DecodeAddress(addrStr, activeNet.Params)
		if err != nil {
			return nil, fmt.Errorf("cannot decode address: %s", err)
		}

		// Add output to spend amt to addr.
		pkScript, err := btcscript.PayToAddrScript(addr)
		if err != nil {
			return nil, fmt.Errorf("cannot create txout script: %s", err)
		}
		txout := btcwire.NewTxOut(int64(amt), pkScript)
		msgtx.AddTxOut(txout)
	}

	// Get current block's height and hash.
	bs, err := GetCurBlock()
	if err != nil {
		return nil, err
	}

	// Make a copy of msgtx before any inputs are added.  This will be
	// used as a starting point when trying a fee and starting over with
	// a higher fee if not enough was originally chosen.
	txNoInputs := msgtx.Copy()

	unspent, err := a.TxStore.UnspentOutputs()
	if err != nil {
		return nil, err
	}

	// Filter out unspendable outputs, that is, remove those that (at this
	// time) are not P2PKH outputs.  Other inputs must be manually included
	// in transactions and sent (for example, using createrawtransaction,
	// signrawtransaction, and sendrawtransaction).
	eligible := make([]txstore.Credit, 0, len(unspent))
	for i := range unspent {
		switch btcscript.GetScriptClass(unspent[i].TxOut().PkScript) {
		case btcscript.PubKeyHashTy:
			if !unspent[i].Confirmed(minconf, bs.Height) {
				continue
			}
			// Coinbase transactions must have have reached maturity
			// before their outputs may be spent.
			if unspent[i].IsCoinbase() {
				target := btcchain.CoinbaseMaturity
				if !unspent[i].Confirmed(target, bs.Height) {
					continue
				}
			}
			eligible = append(eligible, unspent[i])
		}
	}

	// Sort eligible inputs, as selectInputs expects these to be sorted
	// by amount in reverse order.
	sort.Sort(sort.Reverse(ByAmount(eligible)))

	var selectedInputs []txstore.Credit
	// changeAddr is nil/zeroed until a change address is needed, and reused
	// again in case a change utxo has already been chosen.
	var changeAddr btcutil.Address

	// Get the number of satoshis to increment fee by when searching for
	// the minimum tx fee needed.
	fee := btcutil.Amount(0)
	for {
		msgtx = txNoInputs.Copy()

		// Select eligible outputs to be used in transaction based on the amount
		// neededing to sent, and the current fee estimation.
		inputs, btcin, err := selectInputs(eligible, amt, fee, minconf)
		if err != nil {
			return nil, err
		}

		// Check if there are leftover unspent outputs, and return coins back to
		// a new address we own.
		change := btcin - amt - fee
		if change > 0 {
			// Get a new change address if one has not already been found.
			if changeAddr == nil {
				changeAddr, err = a.ChangeAddress(&bs, cfg.KeypoolSize)
				if err != nil {
					return nil, fmt.Errorf("failed to get next address: %s", err)
				}

				// Mark change address as belonging to this account.
				AcctMgr.MarkAddressForAccount(changeAddr, a)
			}

			// Spend change.
			pkScript, err := btcscript.PayToAddrScript(changeAddr)
			if err != nil {
				return nil, fmt.Errorf("cannot create txout script: %s", err)
			}
			msgtx.AddTxOut(btcwire.NewTxOut(int64(change), pkScript))

			// Randomize index of the change output.
			rng := badrand.New(badrand.NewSource(time.Now().UnixNano()))
			r := rng.Int31n(int32(len(msgtx.TxOut))) // random index
			c := len(msgtx.TxOut) - 1                // change index
			msgtx.TxOut[r], msgtx.TxOut[c] = msgtx.TxOut[c], msgtx.TxOut[r]
		}

		// Selected unspent outputs become new transaction's inputs.
		for _, ip := range inputs {
			msgtx.AddTxIn(btcwire.NewTxIn(ip.OutPoint(), nil))
		}
		for i, input := range inputs {
			// Errors don't matter here, as we only consider the
			// case where len(addrs) == 1.
			_, addrs, _, _ := input.Addresses(activeNet.Params)
			if len(addrs) != 1 {
				continue
			}
			apkh, ok := addrs[0].(*btcutil.AddressPubKeyHash)
			if !ok {
				continue // don't handle inputs to this yes
			}

			ai, err := a.Address(apkh)
			if err != nil {
				return nil, fmt.Errorf("cannot get address info: %v", err)
			}

			pka := ai.(wallet.PubKeyAddress)

			privkey, err := pka.PrivKey()
			if err == wallet.ErrWalletLocked {
				return nil, wallet.ErrWalletLocked
			} else if err != nil {
				return nil, fmt.Errorf("cannot get address key: %v", err)
			}

			sigscript, err := btcscript.SignatureScript(msgtx, i,
				input.TxOut().PkScript, btcscript.SigHashAll, privkey,
				ai.Compressed())
			if err != nil {
				return nil, fmt.Errorf("cannot create sigscript: %s", err)
			}
			msgtx.TxIn[i].SignatureScript = sigscript
		}

		noFeeAllowed := false
		if !cfg.DisallowFree {
			noFeeAllowed = allowFree(bs.Height, inputs, msgtx.SerializeSize())
		}
		if minFee := minimumFee(msgtx, noFeeAllowed); fee < minFee {
			fee = minFee
		} else {
			selectedInputs = inputs
			break
		}
	}

	// Validate msgtx before returning the raw transaction.
	flags := btcscript.ScriptCanonicalSignatures
	bip16 := time.Now().After(btcscript.Bip16Activation)
	if bip16 {
		flags |= btcscript.ScriptBip16
	}
	for i, txin := range msgtx.TxIn {
		engine, err := btcscript.NewScript(txin.SignatureScript,
			selectedInputs[i].TxOut().PkScript, i, msgtx, flags)
		if err != nil {
			return nil, fmt.Errorf("cannot create script engine: %s", err)
		}
		if err = engine.Execute(); err != nil {
			return nil, fmt.Errorf("cannot validate transaction: %s", err)
		}
	}

	buf := bytes.Buffer{}
	buf.Grow(msgtx.SerializeSize())
	if err := msgtx.BtcEncode(&buf, btcwire.ProtocolVersion); err != nil {
		// Hitting OOM by growing or writing to a bytes.Buffer already
		// panics, and all returned errors are unexpected.
		panic(err)
	}
	info := &CreatedTx{
		tx:         btcutil.NewTx(msgtx),
		inputs:     selectedInputs,
		changeAddr: changeAddr,
	}
	return info, nil
}

// minimumFee calculates the minimum fee required for a transaction.
// If allowFree is true, a fee may be zero so long as the entire
// transaction has a serialized length less than 1 kilobyte
// and none of the outputs contain a value less than 1 bitcent.
// Otherwise, the fee will be calculated using TxFeeIncrement,
// incrementing the fee for each kilobyte of transaction.
func minimumFee(tx *btcwire.MsgTx, allowFree bool) btcutil.Amount {
	txLen := tx.SerializeSize()
	TxFeeIncrement.Lock()
	incr := TxFeeIncrement.i
	TxFeeIncrement.Unlock()
	fee := btcutil.Amount(int64(1+txLen/1000) * int64(incr))

	if allowFree && txLen < 1000 {
		fee = 0
	}

	if fee < incr {
		for _, txOut := range tx.TxOut {
			if txOut.Value < btcutil.SatoshiPerBitcent {
				return incr
			}
		}
	}

	max := btcutil.Amount(btcutil.MaxSatoshi)
	if fee < 0 || fee > max {
		fee = max
	}

	return fee
}

// allowFree calculates the transaction priority and checks that the
// priority reaches a certain threshhold.  If the threshhold is
// reached, a free transaction fee is allowed.
func allowFree(curHeight int32, txouts []txstore.Credit, txSize int) bool {
	const blocksPerDayEstimate = 144
	const txSizeEstimate = 250

	var weightedSum int64
	for _, txout := range txouts {
		depth := chainDepth(txout.BlockHeight, curHeight)
		weightedSum += int64(txout.Amount()) * int64(depth)
	}
	priority := float64(weightedSum) / float64(txSize)
	return priority > float64(btcutil.SatoshiPerBitcoin)*blocksPerDayEstimate/txSizeEstimate
}

// chainDepth returns the chaindepth of a target given the current
// blockchain height.
func chainDepth(target, current int32) int32 {
	if target == -1 {
		// target is not yet in a block.
		return 0
	}

	// target is in a block.
	return current - target + 1
}
<|endoftext|>


<commit_before>package solr

import (
	"fmt"
	"net/url"
	"time"
)

type SolrHttpRetrier struct {
	solrCli            SolrHTTP
	retries            int
	exponentialBackoff time.Duration
	readTimeout        time.Duration
	updateTimeout      time.Duration
}

func NewSolrHttpRetrier(solrHttp SolrHTTP, retries int, exponentialBackoff time.Duration) SolrHTTP {

	solrRetrier := SolrHttpRetrier{solrCli: solrHttp, retries: retries, exponentialBackoff: exponentialBackoff}
	return &solrRetrier
}

func (s *SolrHttpRetrier) Read(nodeUris []string, opts ...func(url.Values)) (SolrResponse, error) {
	if len(nodeUris) == 0 {
		return SolrResponse{}, fmt.Errorf("[Solr HTTP Retrier]Length of nodes in solr is empty")
	}
	now := time.Now()
	var resp SolrResponse
	var err error
	for attempt := 0; attempt < s.retries; attempt++ {
		uri := nodeUris[attempt%len(nodeUris)]
		resp, err = s.solrCli.Read([]string{uri}, opts...)
		if err == ErrNotFound {
			return resp, err
		}
		if err != nil {
			s.Logger().Printf("[Solr Http Retrier] Error Retrying %v ", err)
			s.backoff(now, attempt)
			continue
		}
		if attempt > 0 {
			s.Logger().Printf("[Solr Http Retrier] healed after %d", attempt)
		}
		break
	}
	return resp, err
}

func (s *SolrHttpRetrier) Update(nodeUris []string, jsonDocs bool, doc interface{}, opts ...func(url.Values)) error {
	if len(nodeUris) == 0 {
		return fmt.Errorf("[Solr HTTP Retrier]Length of nodes in solr is empty")
	}
	now := time.Now()
	var err error
	backoff := s.exponentialBackoff
	for attempt := 0; attempt < s.retries; attempt++ {
		uri := nodeUris[attempt%len(nodeUris)]
		err = s.solrCli.Update([]string{uri}, jsonDocs, doc, opts...)
		if err == ErrNotFound {
			return err
		}
		if err != nil {
			s.Logger().Printf("[Solr Http Retrier] Error Retrying %v ", err)
			backoff = s.backoff(backoff)
			s.Logger().Printf("Sleeping attempt: %d, for time: %v running for: %v ", attempt, backoff, time.Since(now))
			continue
		}
		if attempt > 0 && err == nil {
			s.Logger().Printf("[Solr Http Retrier] Healed after attempt %d", attempt)
		}
		break
	}
	return err
}

func (s *SolrHttpRetrier) Logger() Logger {
	return s.solrCli.Logger()
}

//returns whether cap has been passed
func (s *SolrHttpRetrier) backoff(backoffInterval time.Duration) time.Duration {
	//cap the time, whichever is less ,float
	backoffInterval = time.Duration(backoffInterval.Nanoseconds() * 2)

	time.Sleep(backoffInterval)
	return backoffInterval
}

func min(a, b time.Duration) time.Duration {
	if a < b {
		return time.Duration(a)
	}
	return time.Duration(b)
}
<commit_msg>backoff<commit_after>package solr

import (
	"fmt"
	"net/url"
	"time"
)

type SolrHttpRetrier struct {
	solrCli            SolrHTTP
	retries            int
	exponentialBackoff time.Duration
	readTimeout        time.Duration
	updateTimeout      time.Duration
}

func NewSolrHttpRetrier(solrHttp SolrHTTP, retries int, exponentialBackoff time.Duration) SolrHTTP {

	solrRetrier := SolrHttpRetrier{solrCli: solrHttp, retries: retries, exponentialBackoff: exponentialBackoff}
	return &solrRetrier
}

func (s *SolrHttpRetrier) Read(nodeUris []string, opts ...func(url.Values)) (SolrResponse, error) {
	if len(nodeUris) == 0 {
		return SolrResponse{}, fmt.Errorf("[Solr HTTP Retrier]Length of nodes in solr is empty")
	}
	now := time.Now()
	var resp SolrResponse
	var err error
	backoff := s.exponentialBackoff
	for attempt := 0; attempt < s.retries; attempt++ {
		uri := nodeUris[attempt%len(nodeUris)]
		resp, err = s.solrCli.Read([]string{uri}, opts...)
		if err == ErrNotFound {
			return resp, err
		}
		if err != nil {
			s.Logger().Printf("[Solr Http Retrier] Error Retrying %v ", err)
			backoff = s.backoff(backoff)
			s.Logger().Printf("Sleeping attempt: %d, for time: %v running for: %v ", attempt, backoff, time.Since(now))
			continue
		}
		if attempt > 0 {
			s.Logger().Printf("[Solr Http Retrier] healed after %d", attempt)
		}
		break
	}
	return resp, err
}

func (s *SolrHttpRetrier) Update(nodeUris []string, jsonDocs bool, doc interface{}, opts ...func(url.Values)) error {
	if len(nodeUris) == 0 {
		return fmt.Errorf("[Solr HTTP Retrier]Length of nodes in solr is empty")
	}
	now := time.Now()
	var err error
	backoff := s.exponentialBackoff
	for attempt := 0; attempt < s.retries; attempt++ {
		uri := nodeUris[attempt%len(nodeUris)]
		err = s.solrCli.Update([]string{uri}, jsonDocs, doc, opts...)
		if err == ErrNotFound {
			return err
		}
		if err != nil {
			s.Logger().Printf("[Solr Http Retrier] Error Retrying %v ", err)
			backoff = s.backoff(backoff)
			s.Logger().Printf("Sleeping attempt: %d, for time: %v running for: %v ", attempt, backoff, time.Since(now))
			continue
		}
		if attempt > 0 && err == nil {
			s.Logger().Printf("[Solr Http Retrier] Healed after attempt %d", attempt)
		}
		break
	}
	return err
}

func (s *SolrHttpRetrier) Logger() Logger {
	return s.solrCli.Logger()
}

//returns whether cap has been passed
func (s *SolrHttpRetrier) backoff(backoffInterval time.Duration) time.Duration {
	//cap the time, whichever is less ,float
	backoffInterval = time.Duration(backoffInterval.Nanoseconds() * 2)

	time.Sleep(backoffInterval)
	return backoffInterval
}

func min(a, b time.Duration) time.Duration {
	if a < b {
		return time.Duration(a)
	}
	return time.Duration(b)
}
<|endoftext|>


<commit_before>package keccak

import (
	"encoding/binary"
	"hash"
)

const rounds = 24

var roundConstants = []uint64{
	0x0000000000000001, 0x0000000000008082,
	0x800000000000808A, 0x8000000080008000,
	0x000000000000808B, 0x0000000080000001,
	0x8000000080008081, 0x8000000000008009,
	0x000000000000008A, 0x0000000000000088,
	0x0000000080008009, 0x000000008000000A,
	0x000000008000808B, 0x800000000000008B,
	0x8000000000008089, 0x8000000000008003,
	0x8000000000008002, 0x8000000000000080,
	0x000000000000800A, 0x800000008000000A,
	0x8000000080008081, 0x8000000000008080,
	0x0000000080000001, 0x8000000080008008,
}

var rotationConstants = [24]uint{
	1, 3, 6, 10, 15, 21, 28, 36,
	45, 55, 2, 14, 27, 41, 56, 8,
	25, 43, 62, 18, 39, 61, 20, 44,
}

var piLane = [24]uint{
	10, 7, 11, 17, 18, 3, 5, 16,
	8, 21, 24, 4, 15, 23, 19, 13,
	12, 2, 20, 14, 22, 9, 6, 1,
}

type keccak struct {
	S         [25]uint64
	size      int
	blockSize int
	buf       []byte
}

func newKeccak(bitlen int) hash.Hash {
	var h keccak
	h.size = bitlen / 8
	h.blockSize = (200 - 2*h.size)
	return &h
}

func New224() hash.Hash {
	return newKeccak(224)
}

func New256() hash.Hash {
	return newKeccak(256)
}

func New384() hash.Hash {
	return newKeccak(384)
}

func New512() hash.Hash {
	return newKeccak(512)
}

func (k *keccak) Write(b []byte) (int, error) {
	n := len(b)

	if len(k.buf) > 0 {
		x := k.blockSize - len(k.buf)
		if x > len(b) {
			x = len(b)
		}
		k.buf = append(k.buf, b[:x]...)
		b = b[x:]

		if len(k.buf) < k.blockSize {
			return n, nil
		}

		k.f(k.buf)
		k.buf = nil
	}

	for len(b) >= k.blockSize {
		k.f(b[:k.blockSize])
		b = b[k.blockSize:]
	}

	k.buf = b

	return n, nil
}

func (k0 *keccak) Sum(b []byte) []byte {

	k := *k0

	last := k.pad(k.buf)
	k.f(last)

	buf := make([]byte, len(k.S)*8)
	for i := range k.S {
		binary.LittleEndian.PutUint64(buf[i*8:], k.S[i])
	}
	return append(b, buf[:k.size]...)
}

func (k *keccak) Reset() {
	for i := range k.S {
		k.S[i] = 0
	}
	k.buf = nil
}

func (k *keccak) Size() int {
	return k.size
}

func (k *keccak) BlockSize() int {
	return k.blockSize
}

func (k *keccak) f(block []byte) {

	if len(block) != k.blockSize {
		panic("write() called with invalid block size")
	}

	for i := 0; i < k.blockSize/8; i++ {
		k.S[i] ^= binary.LittleEndian.Uint64(block[i*8:])
	}

	for r := 0; r < rounds; r++ {
		var bc [5]uint64

		// theta
		for i := range bc {
			bc[i] = k.S[i] ^ k.S[5+i] ^ k.S[10+i] ^ k.S[15+i] ^ k.S[20+i]
		}
		for i := range bc {
			t := bc[(i+4)%5] ^ rotl64(bc[(i+1)%5], 1)
			for j := 0; j < len(k.S); j += 5 {
				k.S[i+j] ^= t
			}
		}

		// rho phi
		temp := k.S[1]
		for i := range piLane {
			j := piLane[i]
			temp2 := k.S[j]
			k.S[j] = rotl64(temp, rotationConstants[i])
			temp = temp2
		}

		// chi
		for j := 0; j < len(k.S); j += 5 {
			for i := range bc {
				bc[i] = k.S[j+i]
			}
			for i := range bc {
				k.S[j+i] ^= (^bc[(i+1)%5]) & bc[(i+2)%5]
			}
		}

		// iota
		k.S[0] ^= roundConstants[r]
	}
}

func (k *keccak) pad(block []byte) []byte {

	padded := make([]byte, k.blockSize)

	copy(padded, k.buf)
	padded[len(k.buf)] = 0x01
	padded[len(padded)-1] |= 0x80

	return padded
}

func rotl64(x uint64, n uint) uint64 {
	return (x << n) | (x >> (64 - n))
}
<commit_msg>remove encoding/binary dependency<commit_after>package keccak

import (
	"hash"
)

const rounds = 24

var roundConstants = []uint64{
	0x0000000000000001, 0x0000000000008082,
	0x800000000000808A, 0x8000000080008000,
	0x000000000000808B, 0x0000000080000001,
	0x8000000080008081, 0x8000000000008009,
	0x000000000000008A, 0x0000000000000088,
	0x0000000080008009, 0x000000008000000A,
	0x000000008000808B, 0x800000000000008B,
	0x8000000000008089, 0x8000000000008003,
	0x8000000000008002, 0x8000000000000080,
	0x000000000000800A, 0x800000008000000A,
	0x8000000080008081, 0x8000000000008080,
	0x0000000080000001, 0x8000000080008008,
}

var rotationConstants = [24]uint{
	1, 3, 6, 10, 15, 21, 28, 36,
	45, 55, 2, 14, 27, 41, 56, 8,
	25, 43, 62, 18, 39, 61, 20, 44,
}

var piLane = [24]uint{
	10, 7, 11, 17, 18, 3, 5, 16,
	8, 21, 24, 4, 15, 23, 19, 13,
	12, 2, 20, 14, 22, 9, 6, 1,
}

type keccak struct {
	S         [25]uint64
	size      int
	blockSize int
	buf       []byte
}

func newKeccak(bitlen int) hash.Hash {
	var h keccak
	h.size = bitlen / 8
	h.blockSize = (200 - 2*h.size)
	return &h
}

func New224() hash.Hash {
	return newKeccak(224)
}

func New256() hash.Hash {
	return newKeccak(256)
}

func New384() hash.Hash {
	return newKeccak(384)
}

func New512() hash.Hash {
	return newKeccak(512)
}

func (k *keccak) Write(b []byte) (int, error) {
	n := len(b)

	if len(k.buf) > 0 {
		x := k.blockSize - len(k.buf)
		if x > len(b) {
			x = len(b)
		}
		k.buf = append(k.buf, b[:x]...)
		b = b[x:]

		if len(k.buf) < k.blockSize {
			return n, nil
		}

		k.f(k.buf)
		k.buf = nil
	}

	for len(b) >= k.blockSize {
		k.f(b[:k.blockSize])
		b = b[k.blockSize:]
	}

	k.buf = b

	return n, nil
}

func (k0 *keccak) Sum(b []byte) []byte {

	k := *k0

	last := k.pad(k.buf)
	k.f(last)

	buf := make([]byte, len(k.S)*8)
	for i := range k.S {
		putUint64le(buf[i*8:], k.S[i])
	}
	return append(b, buf[:k.size]...)
}

func (k *keccak) Reset() {
	for i := range k.S {
		k.S[i] = 0
	}
	k.buf = nil
}

func (k *keccak) Size() int {
	return k.size
}

func (k *keccak) BlockSize() int {
	return k.blockSize
}

func (k *keccak) f(block []byte) {

	if len(block) != k.blockSize {
		panic("write() called with invalid block size")
	}

	for i := 0; i < k.blockSize/8; i++ {
		k.S[i] ^= uint64le(block[i*8:])
	}

	for r := 0; r < rounds; r++ {
		var bc [5]uint64

		// theta
		for i := range bc {
			bc[i] = k.S[i] ^ k.S[5+i] ^ k.S[10+i] ^ k.S[15+i] ^ k.S[20+i]
		}
		for i := range bc {
			t := bc[(i+4)%5] ^ rotl64(bc[(i+1)%5], 1)
			for j := 0; j < len(k.S); j += 5 {
				k.S[i+j] ^= t
			}
		}

		// rho phi
		temp := k.S[1]
		for i := range piLane {
			j := piLane[i]
			temp2 := k.S[j]
			k.S[j] = rotl64(temp, rotationConstants[i])
			temp = temp2
		}

		// chi
		for j := 0; j < len(k.S); j += 5 {
			for i := range bc {
				bc[i] = k.S[j+i]
			}
			for i := range bc {
				k.S[j+i] ^= (^bc[(i+1)%5]) & bc[(i+2)%5]
			}
		}

		// iota
		k.S[0] ^= roundConstants[r]
	}
}

func (k *keccak) pad(block []byte) []byte {

	padded := make([]byte, k.blockSize)

	copy(padded, k.buf)
	padded[len(k.buf)] = 0x01
	padded[len(padded)-1] |= 0x80

	return padded
}

func rotl64(x uint64, n uint) uint64 {
	return (x << n) | (x >> (64 - n))
}

func uint64le(v []byte) uint64 {
	return uint64(v[0]) |
		uint64(v[1])<<8 |
		uint64(v[2])<<16 |
		uint64(v[3])<<24 |
		uint64(v[4])<<32 |
		uint64(v[5])<<40 |
		uint64(v[6])<<48 |
		uint64(v[7])<<56

}

func putUint64le(v []byte, x uint64) {
	v[0] = byte(x)
	v[1] = byte(x >> 8)
	v[2] = byte(x >> 16)
	v[3] = byte(x >> 24)
	v[4] = byte(x >> 32)
	v[5] = byte(x >> 40)
	v[6] = byte(x >> 48)
	v[7] = byte(x >> 56)
}
<|endoftext|>


<commit_before>package check

import (
	"testing"

	"github.com/alcortesm/queue"
)

func Seq(n int) []int {
	ret := make([]int, n)
	for i, _ := range ret {
		ret[i] = i
	}
	return ret
}

func Bounded(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Bounded()
	if obtained != expected {
		t.Errorf("%swrong bounded info: expected %t, got %t",
			context, expected, obtained)
	}
}

func CapInfinite(t *testing.T, q queue.Queue, context string) {
	capacity, err := q.Cap()
	if err == nil {
		t.Errorf(
			"%snil error calling Cap, ErrInfinite was expected, capacity was %d",
			context, capacity)
	}
	if err != queue.ErrInfinite {
		t.Errorf("%swrong error calling Cap: %s", context, err)
	}
}

func CapBounded(t *testing.T, q queue.Queue, expected int, context string) {
	obtained, err := q.Cap()
	if err != nil {
		t.Errorf("%sunexpected error calling Cap: %s", context, err)
	}
	if obtained != expected {
		t.Errorf("%swrong Cap: expected %d, got %d",
			context, expected, obtained)
	}
}

func Len(t *testing.T, q queue.Queue, expected int, context string) {
	obtained := q.Len()
	if obtained != expected {
		t.Errorf("%swrong Len: expected %d, got %d",
			context, expected, obtained)
	}
}

func Empty(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Empty()
	if obtained != expected {
		t.Errorf("%swrong Empty: expected %t, got %t",
			context, expected, obtained)
	}
}

func Full(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Full()
	if obtained != expected {
		t.Errorf("%swrong Full: expected %t, got %t",
			context, expected, obtained)
	}
}
<commit_msg>check: simplify error reporting<commit_after>package check

import (
	"fmt"
	"testing"

	"github.com/alcortesm/queue"
)

func Seq(n int) []int {
	ret := make([]int, n)
	for i, _ := range ret {
		ret[i] = i
	}
	return ret
}

func error(t *testing.T, ctx string, msg string) {
	t.Errorf("context: %q\n %s", ctx, msg)
}

func Bounded(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Bounded()
	if obtained != expected {
		msg := fmt.Sprintf("wrong bounded info: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func CapInfinite(t *testing.T, q queue.Queue, context string) {
	capacity, err := q.Cap()
	if err == nil {
		msg := fmt.Sprintf("nil error calling Cap, "+
			"ErrInfinite was expected, capacity was %d",
			capacity)
		error(t, context, msg)
	}
	if err != queue.ErrInfinite {
		t.Errorf("%swrong error calling Cap: %s", context, err)
	}
}

func CapBounded(t *testing.T, q queue.Queue, expected int, context string) {
	obtained, err := q.Cap()
	if err != nil {
		msg := fmt.Sprintf("unexpected error calling Cap: %s", err)
		error(t, context, msg)
	}
	if obtained != expected {
		msg := fmt.Sprintf("wrong Cap: expected %d, got %d",
			expected, obtained)
		error(t, context, msg)
	}
}

func Len(t *testing.T, q queue.Queue, expected int, context string) {
	obtained := q.Len()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Len: expected %d, got %d",
			expected, obtained)
		error(t, context, msg)
	}
}

func Empty(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Empty()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Empty: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func Full(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Full()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Full: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}
<|endoftext|>


<commit_before>package check

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

var (
	skipDirs     = []string{"Godeps", "vendor", "third_party"}
	skipSuffixes = []string{".pb.go", ".pb.gw.go", ".generated.go", "bindata.go"}
)

func addSkipDirs(params []string) []string {
	for _, dir := range skipDirs {
		params = append(params, fmt.Sprintf("--skip=%s", dir))
	}
	return params
}

// GoFiles returns a slice of Go filenames
// in a given directory.
func GoFiles(dir string) ([]string, error) {
	var filenames []string
	visit := func(fp string, fi os.FileInfo, err error) error {
		for _, skip := range skipDirs {
			if strings.Contains(fp, fmt.Sprintf("/%s/", skip)) {
				return nil
			}
		}
		if err != nil {
			fmt.Println(err) // can't walk here,
			return nil       // but continue walking elsewhere
		}
		if fi.IsDir() {
			return nil // not a file.  ignore.
		}
		fiName := fi.Name()
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(fiName, skip) {
				return nil
			}
		}
		ext := filepath.Ext(fiName)
		if ext == ".go" {
			filenames = append(filenames, fp)
		}
		return nil
	}

	err := filepath.Walk(dir, visit)

	return filenames, err
}

// lineCount returns the number of lines in a given file
func lineCount(filepath string) (int, error) {
	out, err := exec.Command("wc", "-l", filepath).Output()
	if err != nil {
		return 0, err
	}
	// wc output is like: 999 filename.go
	count, err := strconv.Atoi(strings.Split(strings.TrimSpace(string(out)), " ")[0])
	if err != nil {
		return 0, err
	}

	return count, nil
}

// Error contains the line number and the reason for
// an error output from a command
type Error struct {
	LineNumber  int    `json:"line_number"`
	ErrorString string `json:"error_string"`
}

// FileSummary contains the filename, location of the file
// on GitHub, and all of the errors related to the file
type FileSummary struct {
	Filename string  `json:"filename"`
	FileURL  string  `json:"file_url"`
	Errors   []Error `json:"errors"`
}

// AddError adds an Error to FileSummary
func (fs *FileSummary) AddError(out string) error {
	s := strings.SplitN(out, ":", 2)
	msg := strings.SplitAfterN(s[1], ":", 3)[2]

	e := Error{ErrorString: msg}
	ls := strings.Split(s[1], ":")
	ln, err := strconv.Atoi(ls[0])
	if err != nil {
		return err
	}
	e.LineNumber = ln

	fs.Errors = append(fs.Errors, e)

	return nil
}

// GoTool runs a given go command (for example gofmt, go tool vet)
// on a directory
func GoTool(dir string, filenames, command []string) (float64, []FileSummary, error) {
	params := command[1:]
	params = addSkipDirs(params)
	params = append(params, dir+"/...")

	cmd := exec.Command(command[0], params...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	out := bufio.NewScanner(stdout)

	githubLink := strings.TrimPrefix(dir, "repos/src")

	// the same file can appear multiple times out of order
	// in the output, so we can't go line by line, have to store
	// a map of filename to FileSummary
	fsMap := map[string]FileSummary{}
	var failed = []FileSummary{}
outer:
	for out.Scan() {
		filename := strings.Split(out.Text(), ":")[0]
		filename = strings.TrimPrefix(filename, "repos/src")
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(filename, skip) {
				continue outer
			}
		}
		var fileURL string
		base := strings.TrimPrefix(dir, "repos/src/")
		switch {
		case strings.HasPrefix(base, "golang.org/x/"):
			var pkg string
			if len(strings.Split(base, "/")) >= 3 {
				pkg = strings.Split(base, "/")[2]
			}
			fileURL = "https://" + fmt.Sprintf("github.com/golang/%s", pkg) + "/blob/master" + strings.TrimPrefix(filename, githubLink)
		default:
			fileURL = "https://" + strings.TrimPrefix(dir, "repos/src/") + "/blob/master" + strings.TrimPrefix(filename, githubLink)
		}
		fs := fsMap[filename]
		if fs.Filename == "" {
			fs.Filename = filename
			if strings.HasPrefix(filename, "/github.com") {
				sp := strings.Split(filename, "/")
				if len(sp) > 3 {
					fs.Filename = strings.Join(sp[3:], "/")
				}

			}
			fs.FileURL = fileURL
		}
		err = fs.AddError(out.Text())
		if err != nil {
			return 0, []FileSummary{}, err
		}
		fsMap[filename] = fs
	}
	if err := out.Err(); err != nil {
		return 0, []FileSummary{}, err
	}

	for _, v := range fsMap {
		failed = append(failed, v)
	}

	err = cmd.Wait()
	if exitErr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0

		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			// some commands exit 1 when files fail to pass (for example go vet)
			if status.ExitStatus() != 1 {
				return 0, failed, err
				// return 0, Error{}, err
			}
		}
	}

	if len(filenames) == 1 {
		lc, err := lineCount(filenames[0])
		if err != nil {
			return 0, failed, err
		}

		var errors int
		if len(failed) != 0 {
			errors = len(failed[0].Errors)
		}

		return float64(lc-errors) / float64(lc), failed, nil
	}

	return float64(len(filenames)-len(failed)) / float64(len(filenames)), failed, nil
}
<commit_msg>#95 remove extra var<commit_after>package check

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

var (
	skipDirs     = []string{"Godeps", "vendor", "third_party"}
	skipSuffixes = []string{".pb.go", ".pb.gw.go", ".generated.go", "bindata.go"}
)

func addSkipDirs(params []string) []string {
	for _, dir := range skipDirs {
		params = append(params, fmt.Sprintf("--skip=%s", dir))
	}
	return params
}

// GoFiles returns a slice of Go filenames
// in a given directory.
func GoFiles(dir string) ([]string, error) {
	var filenames []string
	visit := func(fp string, fi os.FileInfo, err error) error {
		for _, skip := range skipDirs {
			if strings.Contains(fp, fmt.Sprintf("/%s/", skip)) {
				return nil
			}
		}
		if err != nil {
			fmt.Println(err) // can't walk here,
			return nil       // but continue walking elsewhere
		}
		if fi.IsDir() {
			return nil // not a file.  ignore.
		}
		fiName := fi.Name()
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(fiName, skip) {
				return nil
			}
		}
		ext := filepath.Ext(fiName)
		if ext == ".go" {
			filenames = append(filenames, fp)
		}
		return nil
	}

	err := filepath.Walk(dir, visit)

	return filenames, err
}

// lineCount returns the number of lines in a given file
func lineCount(filepath string) (int, error) {
	out, err := exec.Command("wc", "-l", filepath).Output()
	if err != nil {
		return 0, err
	}
	// wc output is like: 999 filename.go
	count, err := strconv.Atoi(strings.Split(strings.TrimSpace(string(out)), " ")[0])
	if err != nil {
		return 0, err
	}

	return count, nil
}

// Error contains the line number and the reason for
// an error output from a command
type Error struct {
	LineNumber  int    `json:"line_number"`
	ErrorString string `json:"error_string"`
}

// FileSummary contains the filename, location of the file
// on GitHub, and all of the errors related to the file
type FileSummary struct {
	Filename string  `json:"filename"`
	FileURL  string  `json:"file_url"`
	Errors   []Error `json:"errors"`
}

// AddError adds an Error to FileSummary
func (fs *FileSummary) AddError(out string) error {
	s := strings.SplitN(out, ":", 2)
	msg := strings.SplitAfterN(s[1], ":", 3)[2]

	e := Error{ErrorString: msg}
	ls := strings.Split(s[1], ":")
	ln, err := strconv.Atoi(ls[0])
	if err != nil {
		return err
	}
	e.LineNumber = ln

	fs.Errors = append(fs.Errors, e)

	return nil
}

// GoTool runs a given go command (for example gofmt, go tool vet)
// on a directory
func GoTool(dir string, filenames, command []string) (float64, []FileSummary, error) {
	params := command[1:]
	params = addSkipDirs(params)
	params = append(params, dir+"/...")

	cmd := exec.Command(command[0], params...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	out := bufio.NewScanner(stdout)

	// the same file can appear multiple times out of order
	// in the output, so we can't go line by line, have to store
	// a map of filename to FileSummary
	fsMap := map[string]FileSummary{}
	var failed = []FileSummary{}
outer:
	for out.Scan() {
		filename := strings.Split(out.Text(), ":")[0]
		filename = strings.TrimPrefix(filename, "repos/src")
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(filename, skip) {
				continue outer
			}
		}
		var fileURL string
		base := strings.TrimPrefix(dir, "repos/src/")
		switch {
		case strings.HasPrefix(base, "golang.org/x/"):
			var pkg string
			if len(strings.Split(base, "/")) >= 3 {
				pkg = strings.Split(base, "/")[2]
			}
			fileURL = "https://" + fmt.Sprintf("github.com/golang/%s", pkg) + "/blob/master" + strings.TrimPrefix(filename, "/"+base)
		default:
			fileURL = "https://" + base + "/blob/master" + strings.TrimPrefix(filename, "/"+base)
		}
		fs := fsMap[filename]
		if fs.Filename == "" {
			fs.Filename = filename
			if strings.HasPrefix(filename, "/github.com") {
				sp := strings.Split(filename, "/")
				if len(sp) > 3 {
					fs.Filename = strings.Join(sp[3:], "/")
				}

			}
			fs.FileURL = fileURL
		}
		err = fs.AddError(out.Text())
		if err != nil {
			return 0, []FileSummary{}, err
		}
		fsMap[filename] = fs
	}
	if err := out.Err(); err != nil {
		return 0, []FileSummary{}, err
	}

	for _, v := range fsMap {
		failed = append(failed, v)
	}

	err = cmd.Wait()
	if exitErr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0

		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			// some commands exit 1 when files fail to pass (for example go vet)
			if status.ExitStatus() != 1 {
				return 0, failed, err
				// return 0, Error{}, err
			}
		}
	}

	if len(filenames) == 1 {
		lc, err := lineCount(filenames[0])
		if err != nil {
			return 0, failed, err
		}

		var errors int
		if len(failed) != 0 {
			errors = len(failed[0].Errors)
		}

		return float64(lc-errors) / float64(lc), failed, nil
	}

	return float64(len(filenames)-len(failed)) / float64(len(filenames)), failed, nil
}
<|endoftext|>


<commit_before>package clw11

/*
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#ifdef __APPLE__
#include "OpenCL/opencl.h"
#else
#include "CL/opencl.h"
#endif
*/
import "C"
import "unsafe"

type (
	Kernel              C.cl_kernel
	KernelInfo          C.cl_kernel_info
	KernelWorkGroupInfo C.cl_kernel_work_group_info
)

const (
	KernelFunctionName    = KernelInfo(C.CL_KERNEL_FUNCTION_NAME)
	KernelNumArgs         = KernelInfo(C.CL_KERNEL_NUM_ARGS)
	KernelReference_count = KernelInfo(C.CL_KERNEL_REFERENCE_COUNT)
	KernelContext         = KernelInfo(C.CL_KERNEL_CONTEXT)
	KernelProgram         = KernelInfo(C.CL_KERNEL_PROGRAM)
)

const (
	KernelWorkGroupSize                  = KernelWorkGroupInfo(C.CL_KERNEL_WORK_GROUP_SIZE)
	KernelCompileWorkGroupSize           = KernelWorkGroupInfo(C.CL_KERNEL_COMPILE_WORK_GROUP_SIZE)
	KernelLocalMemSize                   = KernelWorkGroupInfo(C.CL_KERNEL_LOCAL_MEM_SIZE)
	KernelPreferredWorkGroupSizeMultiple = KernelWorkGroupInfo(C.CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE)
	KernelPrivateMemSize                 = KernelWorkGroupInfo(C.CL_KERNEL_PRIVATE_MEM_SIZE)
)

// Creates a kernal object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateKernel.html
func CreateKernel(program Program, kernel_name string) (Kernel, error) {

	name := C.CString(kernel_name)
	defer C.free(unsafe.Pointer(name))

	var err C.cl_int
	kernel := C.clCreateKernel(program, name, &err)

	return Kernel(kernel), toError(err)
}

// Creates kernel objects for all kernel functions in a program object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateKernelsInProgram.html
func CreateKernelsInProgram(program Program, kernels []Kernel, num_kernels_ret *Uint) error {

	var num_kernels C.cl_uint
	var cKernels *C.cl_kernel
	if kernels != nil {
		num_kernels = C.cl_uint(len(kernels))
		cKernels = (*C.cl_kernel)(&kernels[0])
	}

	return toError(C.clCreateKernelsInProgram(program, num_kernels, cKernels, (*C.cl_uint)(num_kernels_ret)))
}

// Increments the kernel object reference count.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clRetainKernel.html
func RetainKernel(kernel Kernel) error {
	return toError(C.clRetainKernel(kernel))
}

// Decrements the kernel reference count.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clReleaseKernel.html
func ReleaseKernel(kernel Kernel) error {
	return toError(C.clReleaseKernel(kernel))
}

// Used to set the argument value for a specific argument of a kernel.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clSetKernelArg.html
func SetKernelArg(kernel Kernel, arg_index Uint, arg_size Size, arg_value unsafe.Pointer) error {
	return toError(C.clSetKernelArg(kernel, C.cl_uint(arg_index), C.size_t(arg_size), arg_value))
}

// Returns information about the kernel object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetKernelInfo.html
func GetKernelInfo(kernel Kernel, param_name KernelInfo, param_value_size Size, param_value unsafe.Pointer,
	param_value_size_ret *Size) error {

	return toError(C.clGetKernelInfo(kernel, C.cl_kernel_info(param_name), C.size_t(param_value_size),
		param_value, (*C.size_t)(param_value_size_ret)))
}

// Returns information about the kernel object that may be specific to a device.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetKernelWorkGroupInfo.html
func GetKernelWorkGroupInfo(kernel Kernel, device DeviceID, param_name KernelWorkGroupInfo, param_value_size Size,
	param_value unsafe.Pointer, param_value_size_ret *Size) error {

	return toError(C.clGetKernelWorkGroupInfo(kernel, device, C.cl_kernel_work_group_info(param_name),
		C.size_t(param_value_size), param_value, (*C.size_t)(param_value_size_ret)))
}

// Enqueues a command to execute a kernel on a device.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueNDRangeKernel.html
func EnqueueNDRangeKernel(command_queue CommandQueue, kernel Kernel, global_work_offset, global_work_size,
	local_work_size []Size, wait_list []Event, event *Event) error {

	event_wait_list, num_events_in_wait_list := toEventList(wait_list)
	return toError(C.clEnqueueNDRangeKernel(command_queue, kernel, C.cl_uint(len(global_work_offset)),
		(*C.size_t)(&global_work_offset[0]), (*C.size_t)(&global_work_size[0]), (*C.size_t)(&local_work_size[0]),
		num_events_in_wait_list, event_wait_list, (*C.cl_event)(event)))
}

// Enqueues a command to execute a kernel on a device.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueTask.html
func EnqueueTask(command_queue CommandQueue, kernel Kernel, wait_list []Event, event *Event) error {

	event_wait_list, num_events_in_wait_list := toEventList(wait_list)
	return toError(C.clEnqueueTask(command_queue, kernel, num_events_in_wait_list, event_wait_list,
		(*C.cl_event)(event)))
}

// Enqueues a command to execute a native C/C++ function not compiled using the
// OpenCL compiler.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueNativeKernel.html
func EnqueueNativeKernel(command_queue CommandQueue, user_func unsafe.Pointer, args unsafe.Pointer, cb_args Size,
	mem_object_list []Mem, args_mem_loc *unsafe.Pointer, wait_list []Event, event *Event) error {

	var num_mem_object Uint
	var mem_list *Mem
	if mem_object_list != nil && len(mem_object_list) > 0 {
		num_mem_object = Uint(len(mem_object_list))
		mem_list = &mem_object_list[0]
	}
	event_wait_list, num_events_in_wait_list := toEventList(wait_list)

	return toError(C.clEnqueueNativeKernel(command_queue, (*[0]byte)(user_func), args, C.size_t(cb_args),
		C.cl_uint(num_mem_object), (*C.cl_mem)(mem_list), args_mem_loc, num_events_in_wait_list, event_wait_list,
		(*C.cl_event)(event)))
}
<commit_msg>Fixed variable name.<commit_after>package clw11

/*
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#ifdef __APPLE__
#include "OpenCL/opencl.h"
#else
#include "CL/opencl.h"
#endif
*/
import "C"
import "unsafe"

type (
	Kernel              C.cl_kernel
	KernelInfo          C.cl_kernel_info
	KernelWorkGroupInfo C.cl_kernel_work_group_info
)

const (
	KernelFunctionName   = KernelInfo(C.CL_KERNEL_FUNCTION_NAME)
	KernelNumArgs        = KernelInfo(C.CL_KERNEL_NUM_ARGS)
	KernelReferenceCount = KernelInfo(C.CL_KERNEL_REFERENCE_COUNT)
	KernelContext        = KernelInfo(C.CL_KERNEL_CONTEXT)
	KernelProgram        = KernelInfo(C.CL_KERNEL_PROGRAM)
)

const (
	KernelWorkGroupSize                  = KernelWorkGroupInfo(C.CL_KERNEL_WORK_GROUP_SIZE)
	KernelCompileWorkGroupSize           = KernelWorkGroupInfo(C.CL_KERNEL_COMPILE_WORK_GROUP_SIZE)
	KernelLocalMemSize                   = KernelWorkGroupInfo(C.CL_KERNEL_LOCAL_MEM_SIZE)
	KernelPreferredWorkGroupSizeMultiple = KernelWorkGroupInfo(C.CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE)
	KernelPrivateMemSize                 = KernelWorkGroupInfo(C.CL_KERNEL_PRIVATE_MEM_SIZE)
)

// Creates a kernal object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateKernel.html
func CreateKernel(program Program, kernel_name string) (Kernel, error) {

	name := C.CString(kernel_name)
	defer C.free(unsafe.Pointer(name))

	var err C.cl_int
	kernel := C.clCreateKernel(program, name, &err)

	return Kernel(kernel), toError(err)
}

// Creates kernel objects for all kernel functions in a program object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateKernelsInProgram.html
func CreateKernelsInProgram(program Program, kernels []Kernel, num_kernels_ret *Uint) error {

	var num_kernels C.cl_uint
	var cKernels *C.cl_kernel
	if kernels != nil {
		num_kernels = C.cl_uint(len(kernels))
		cKernels = (*C.cl_kernel)(&kernels[0])
	}

	return toError(C.clCreateKernelsInProgram(program, num_kernels, cKernels, (*C.cl_uint)(num_kernels_ret)))
}

// Increments the kernel object reference count.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clRetainKernel.html
func RetainKernel(kernel Kernel) error {
	return toError(C.clRetainKernel(kernel))
}

// Decrements the kernel reference count.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clReleaseKernel.html
func ReleaseKernel(kernel Kernel) error {
	return toError(C.clReleaseKernel(kernel))
}

// Used to set the argument value for a specific argument of a kernel.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clSetKernelArg.html
func SetKernelArg(kernel Kernel, arg_index Uint, arg_size Size, arg_value unsafe.Pointer) error {
	return toError(C.clSetKernelArg(kernel, C.cl_uint(arg_index), C.size_t(arg_size), arg_value))
}

// Returns information about the kernel object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetKernelInfo.html
func GetKernelInfo(kernel Kernel, param_name KernelInfo, param_value_size Size, param_value unsafe.Pointer,
	param_value_size_ret *Size) error {

	return toError(C.clGetKernelInfo(kernel, C.cl_kernel_info(param_name), C.size_t(param_value_size),
		param_value, (*C.size_t)(param_value_size_ret)))
}

// Returns information about the kernel object that may be specific to a device.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetKernelWorkGroupInfo.html
func GetKernelWorkGroupInfo(kernel Kernel, device DeviceID, param_name KernelWorkGroupInfo, param_value_size Size,
	param_value unsafe.Pointer, param_value_size_ret *Size) error {

	return toError(C.clGetKernelWorkGroupInfo(kernel, device, C.cl_kernel_work_group_info(param_name),
		C.size_t(param_value_size), param_value, (*C.size_t)(param_value_size_ret)))
}

// Enqueues a command to execute a kernel on a device.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueNDRangeKernel.html
func EnqueueNDRangeKernel(command_queue CommandQueue, kernel Kernel, global_work_offset, global_work_size,
	local_work_size []Size, wait_list []Event, event *Event) error {

	event_wait_list, num_events_in_wait_list := toEventList(wait_list)
	return toError(C.clEnqueueNDRangeKernel(command_queue, kernel, C.cl_uint(len(global_work_offset)),
		(*C.size_t)(&global_work_offset[0]), (*C.size_t)(&global_work_size[0]), (*C.size_t)(&local_work_size[0]),
		num_events_in_wait_list, event_wait_list, (*C.cl_event)(event)))
}

// Enqueues a command to execute a kernel on a device.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueTask.html
func EnqueueTask(command_queue CommandQueue, kernel Kernel, wait_list []Event, event *Event) error {

	event_wait_list, num_events_in_wait_list := toEventList(wait_list)
	return toError(C.clEnqueueTask(command_queue, kernel, num_events_in_wait_list, event_wait_list,
		(*C.cl_event)(event)))
}

// Enqueues a command to execute a native C/C++ function not compiled using the
// OpenCL compiler.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueNativeKernel.html
func EnqueueNativeKernel(command_queue CommandQueue, user_func unsafe.Pointer, args unsafe.Pointer, cb_args Size,
	mem_object_list []Mem, args_mem_loc *unsafe.Pointer, wait_list []Event, event *Event) error {

	var num_mem_object Uint
	var mem_list *Mem
	if mem_object_list != nil && len(mem_object_list) > 0 {
		num_mem_object = Uint(len(mem_object_list))
		mem_list = &mem_object_list[0]
	}
	event_wait_list, num_events_in_wait_list := toEventList(wait_list)

	return toError(C.clEnqueueNativeKernel(command_queue, (*[0]byte)(user_func), args, C.size_t(cb_args),
		C.cl_uint(num_mem_object), (*C.cl_mem)(mem_list), args_mem_loc, num_events_in_wait_list, event_wait_list,
		(*C.cl_event)(event)))
}
<|endoftext|>


<commit_before>package peco

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/nsf/termbox-go"
)

type KeymapHandler func(*Input, termbox.Event)
type Keymap map[termbox.Key]KeymapHandler
type KeymapStringKey string
type KeymapStringHandler string

// This map is populated using some magic numbers, which must match
// the values defined in termbox-go. Verification against the actual
// termbox constants are done in the test
var stringToKey = map[string]termbox.Key{}

func init() {
	fidx := 12
	for k := termbox.KeyF1; k > termbox.KeyF12; k-- {
		sk := fmt.Sprintf("F%d", fidx)
		stringToKey[sk] = k
		fidx--
	}

	names := []string{
		"Insert",
		"Delete",
		"Home",
		"End",
		"Pgup",
		"Pgdn",
		"ArrowUp",
		"ArrowDown",
		"ArrowLeft",
		"ArrowRight",
	}
	for i, n := range names {
		stringToKey[n] = termbox.Key(int(termbox.KeyF12) - (i + 1))
	}

	names = []string{
		"Left",
		"Middle",
		"Right",
	}
	for i, n := range names {
		sk := fmt.Sprintf("Mouse%s", n)
		stringToKey[sk] = termbox.Key(int(termbox.KeyArrowRight) - (i + 2))
	}

	whacky := [][]string{
		{"~", "2", "Space"},
		{"a"},
		{"b"},
		{"c"},
		{"d"},
		{"e"},
		{"f"},
		{"g"},
		{"h"},
		{"i"},
		{"j"},
		{"k"},
		{"l"},
		{"m"},
		{"n"},
		{"o"},
		{"p"},
		{"q"},
		{"r"},
		{"s"},
		{"t"},
		{"u"},
		{"v"},
		{"w"},
		{"x"},
		{"y"},
		{"z"},
		{"[", "3"},
		{"4", "\\"},
		{"5", "]"},
		{"6"},
		{"7", "/", "_"},
	}
	for i, list := range whacky {
		for _, n := range list {
			sk := fmt.Sprintf("C-%s", n)
			stringToKey[sk] = termbox.Key(int(termbox.KeyCtrlTilde) + i)
		}
	}

	stringToKey["BS"] = termbox.KeyBackspace
	stringToKey["Tab"] = termbox.KeyTab
	stringToKey["Enter"] = termbox.KeyEnter
	stringToKey["Esc"] = termbox.KeyEsc
	stringToKey["Space"] = termbox.KeySpace
	stringToKey["BS2"] = termbox.KeyBackspace2
	stringToKey["C-8"] = termbox.KeyCtrl8

	//	panic(fmt.Sprintf("%#q", stringToKey))
}

func handleAcceptChar(i *Input, ev termbox.Event) {
	if ev.Key == termbox.KeySpace {
		ev.Ch = ' '
	}

	if ev.Ch > 0 {
		if len(i.query) == i.caretPos {
			i.query = append(i.query, ev.Ch)
		} else {
			buf := make([]rune, len(i.query)+1)
			copy(buf, i.query[:i.caretPos])
			buf[i.caretPos] = ev.Ch
			copy(buf[i.caretPos+1:], i.query[i.caretPos:])
			i.query = buf
		}
		i.caretPos++
		i.ExecQuery(string(i.query))
	}
}

// peco.Finish -> end program, exit with success
func handleFinish(i *Input, _ termbox.Event) {
	if len(i.current) == 1 {
		i.result = i.current[0].line
	} else if i.selectedLine > 0 && i.selectedLine < len(i.current) {
		i.result = i.current[i.selectedLine-1].line
	}
	i.Finish()
}

// peco.Cancel -> end program, exit with failure
func handleCancel(i *Input, ev termbox.Event) {
	i.ExitStatus = 1
	i.Finish()
}

func handleSelectPrevious(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToPrevLine
	i.DrawMatches(nil)
}

func handleSelectNext(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToNextLine
	i.DrawMatches(nil)
}

func handleSelectPreviousPage(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToPrevPage
	i.DrawMatches(nil)
}

func handleSelectNextPage(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToNextPage
	i.DrawMatches(nil)
}

func handleForwardChar(i *Input, _ termbox.Event) {
	if i.caretPos >= len(i.query) {
		return
	}
	i.caretPos++
	i.DrawMatches(nil)
}

func handleBackwardChar(i *Input, _ termbox.Event) {
	if i.caretPos <= 0 {
		return
	}
	i.caretPos--
	i.DrawMatches(nil)
}

func handleDeleteBackwardChar(i *Input, ev termbox.Event) {
	if len(i.query) <= 0 {
		return
	}

	if i.caretPos == len(i.query) {
		i.query = i.query[:len(i.query)-1]
	} else {
		buf := make([]rune, len(i.query)-1)
		copy(buf, i.query[:i.caretPos])
		copy(buf[i.caretPos-1:], i.query[i.caretPos:])
		i.query = buf
	}
	i.caretPos--
	if len(i.query) > 0 {
		i.ExecQuery(string(i.query))
		return
	}

	i.current = nil
	i.DrawMatches(nil)
}

func (ksk KeymapStringKey) ToKey() (k termbox.Key, err error) {
	k, ok := stringToKey[string(ksk)]
	if !ok {
		err = fmt.Errorf("No such key %s", ksk)
	}
	return
}

func (ksh KeymapStringHandler) ToHandler() (h KeymapHandler, err error) {
	switch ksh {
	case "peco.ForwardChar":
		h = handleForwardChar
	case "peco.BackwardChar":
		h = handleBackwardChar
	case "peco.DeleteBackwardChar":
		h = handleDeleteBackwardChar
	case "peco.SelectPreviousPage":
		h = handleSelectPreviousPage
	case "peco.SelectNextPage":
		h = handleSelectNextPage
	case "peco.SelectPrevious":
		h = handleSelectPrevious
	case "peco.SelectNext":
		h = handleSelectNext
	case "peco.Finish":
		h = handleFinish
	case "peco.Cancel":
		h = handleCancel
	default:
		err = fmt.Errorf("No such handler %s", ksh)
	}
	return
}

func NewKeymap() Keymap {
	return Keymap{
		termbox.KeyEsc:        handleCancel,
		termbox.KeyEnter:      handleFinish,
		termbox.KeyArrowUp:    handleSelectPrevious,
		termbox.KeyCtrlK:      handleSelectPrevious,
		termbox.KeyArrowDown:  handleSelectNext,
		termbox.KeyCtrlJ:      handleSelectNext,
		termbox.KeyArrowLeft:  handleSelectPreviousPage,
		termbox.KeyArrowRight: handleSelectNextPage,
		termbox.KeyBackspace:  handleDeleteBackwardChar,
		termbox.KeyBackspace2: handleDeleteBackwardChar,
	}
}

func (km Keymap) Handler(k termbox.Key) KeymapHandler {
	h, ok := km[k]
	if ok {
		return h
	}
	return handleAcceptChar
}

func (km Keymap) UnmarshalJSON(buf []byte) error {
	raw := map[string]string{}
	if err := json.Unmarshal(buf, &raw); err != nil {
		return err
	}

	for ks, vs := range raw {
		k, err := KeymapStringKey(ks).ToKey()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unknown key %s", ks)
			continue
		}

		v, err := KeymapStringHandler(vs).ToHandler()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unknown handler %s", vs)
			continue
		}

		km[k] = v
	}

	return nil
}
<commit_msg>Handle BeginningOfLine + EndOfLine<commit_after>package peco

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/nsf/termbox-go"
)

type KeymapHandler func(*Input, termbox.Event)
type Keymap map[termbox.Key]KeymapHandler
type KeymapStringKey string
type KeymapStringHandler string

// This map is populated using some magic numbers, which must match
// the values defined in termbox-go. Verification against the actual
// termbox constants are done in the test
var stringToKey = map[string]termbox.Key{}

func init() {
	fidx := 12
	for k := termbox.KeyF1; k > termbox.KeyF12; k-- {
		sk := fmt.Sprintf("F%d", fidx)
		stringToKey[sk] = k
		fidx--
	}

	names := []string{
		"Insert",
		"Delete",
		"Home",
		"End",
		"Pgup",
		"Pgdn",
		"ArrowUp",
		"ArrowDown",
		"ArrowLeft",
		"ArrowRight",
	}
	for i, n := range names {
		stringToKey[n] = termbox.Key(int(termbox.KeyF12) - (i + 1))
	}

	names = []string{
		"Left",
		"Middle",
		"Right",
	}
	for i, n := range names {
		sk := fmt.Sprintf("Mouse%s", n)
		stringToKey[sk] = termbox.Key(int(termbox.KeyArrowRight) - (i + 2))
	}

	whacky := [][]string{
		{"~", "2", "Space"},
		{"a"},
		{"b"},
		{"c"},
		{"d"},
		{"e"},
		{"f"},
		{"g"},
		{"h"},
		{"i"},
		{"j"},
		{"k"},
		{"l"},
		{"m"},
		{"n"},
		{"o"},
		{"p"},
		{"q"},
		{"r"},
		{"s"},
		{"t"},
		{"u"},
		{"v"},
		{"w"},
		{"x"},
		{"y"},
		{"z"},
		{"[", "3"},
		{"4", "\\"},
		{"5", "]"},
		{"6"},
		{"7", "/", "_"},
	}
	for i, list := range whacky {
		for _, n := range list {
			sk := fmt.Sprintf("C-%s", n)
			stringToKey[sk] = termbox.Key(int(termbox.KeyCtrlTilde) + i)
		}
	}

	stringToKey["BS"] = termbox.KeyBackspace
	stringToKey["Tab"] = termbox.KeyTab
	stringToKey["Enter"] = termbox.KeyEnter
	stringToKey["Esc"] = termbox.KeyEsc
	stringToKey["Space"] = termbox.KeySpace
	stringToKey["BS2"] = termbox.KeyBackspace2
	stringToKey["C-8"] = termbox.KeyCtrl8

	//	panic(fmt.Sprintf("%#q", stringToKey))
}

func handleAcceptChar(i *Input, ev termbox.Event) {
	if ev.Key == termbox.KeySpace {
		ev.Ch = ' '
	}

	if ev.Ch > 0 {
		if len(i.query) == i.caretPos {
			i.query = append(i.query, ev.Ch)
		} else {
			buf := make([]rune, len(i.query)+1)
			copy(buf, i.query[:i.caretPos])
			buf[i.caretPos] = ev.Ch
			copy(buf[i.caretPos+1:], i.query[i.caretPos:])
			i.query = buf
		}
		i.caretPos++
		i.ExecQuery(string(i.query))
	}
}

// peco.Finish -> end program, exit with success
func handleFinish(i *Input, _ termbox.Event) {
	if len(i.current) == 1 {
		i.result = i.current[0].line
	} else if i.selectedLine > 0 && i.selectedLine < len(i.current) {
		i.result = i.current[i.selectedLine-1].line
	}
	i.Finish()
}

// peco.Cancel -> end program, exit with failure
func handleCancel(i *Input, ev termbox.Event) {
	i.ExitStatus = 1
	i.Finish()
}

func handleSelectPrevious(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToPrevLine
	i.DrawMatches(nil)
}

func handleSelectNext(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToNextLine
	i.DrawMatches(nil)
}

func handleSelectPreviousPage(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToPrevPage
	i.DrawMatches(nil)
}

func handleSelectNextPage(i *Input, ev termbox.Event) {
	i.PagingCh() <- ToNextPage
	i.DrawMatches(nil)
}

func handleForwardChar(i *Input, _ termbox.Event) {
	if i.caretPos >= len(i.query) {
		return
	}
	i.caretPos++
	i.DrawMatches(nil)
}

func handleBackwardChar(i *Input, _ termbox.Event) {
	if i.caretPos <= 0 {
		return
	}
	i.caretPos--
	i.DrawMatches(nil)
}

func handleBeginningOfLine(i *Input, _ termbox.Event) {
	i.caretPos = 0
	i.DrawMatches(nil)
}

func handleEndOfLine(i *Input, _ termbox.Event) {
	i.caretPos = len(i.query)
	i.DrawMatches(nil)
}

func handleDeleteBackwardChar(i *Input, ev termbox.Event) {
	if len(i.query) <= 0 {
		return
	}

	switch i.caretPos {
	case 0:
		// No op
		return
	case len(i.query):
		i.query = i.query[:len(i.query)-1]
	default:
		buf := make([]rune, len(i.query)-1)
		copy(buf, i.query[:i.caretPos])
		copy(buf[i.caretPos-1:], i.query[i.caretPos:])
		i.query = buf
	}
	i.caretPos--
	if len(i.query) > 0 {
		i.ExecQuery(string(i.query))
		return
	}

	i.current = nil
	i.DrawMatches(nil)
}

func (ksk KeymapStringKey) ToKey() (k termbox.Key, err error) {
	k, ok := stringToKey[string(ksk)]
	if !ok {
		err = fmt.Errorf("No such key %s", ksk)
	}
	return
}

func (ksh KeymapStringHandler) ToHandler() (h KeymapHandler, err error) {
	switch ksh {
	case "peco.BeginningOfLine":
		h = handleBeginningOfLine
	case "peco.EndOfLine":
		h = handleEndOfLine
	case "peco.ForwardChar":
		h = handleForwardChar
	case "peco.BackwardChar":
		h = handleBackwardChar
	case "peco.DeleteBackwardChar":
		h = handleDeleteBackwardChar
	case "peco.SelectPreviousPage":
		h = handleSelectPreviousPage
	case "peco.SelectNextPage":
		h = handleSelectNextPage
	case "peco.SelectPrevious":
		h = handleSelectPrevious
	case "peco.SelectNext":
		h = handleSelectNext
	case "peco.Finish":
		h = handleFinish
	case "peco.Cancel":
		h = handleCancel
	default:
		err = fmt.Errorf("No such handler %s", ksh)
	}
	return
}

func NewKeymap() Keymap {
	return Keymap{
		termbox.KeyEsc:        handleCancel,
		termbox.KeyEnter:      handleFinish,
		termbox.KeyArrowUp:    handleSelectPrevious,
		termbox.KeyCtrlK:      handleSelectPrevious,
		termbox.KeyArrowDown:  handleSelectNext,
		termbox.KeyCtrlJ:      handleSelectNext,
		termbox.KeyArrowLeft:  handleSelectPreviousPage,
		termbox.KeyArrowRight: handleSelectNextPage,
		termbox.KeyBackspace:  handleDeleteBackwardChar,
		termbox.KeyBackspace2: handleDeleteBackwardChar,
	}
}

func (km Keymap) Handler(k termbox.Key) KeymapHandler {
	h, ok := km[k]
	if ok {
		return h
	}
	return handleAcceptChar
}

func (km Keymap) UnmarshalJSON(buf []byte) error {
	raw := map[string]string{}
	if err := json.Unmarshal(buf, &raw); err != nil {
		return err
	}

	for ks, vs := range raw {
		k, err := KeymapStringKey(ks).ToKey()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unknown key %s", ks)
			continue
		}

		v, err := KeymapStringHandler(vs).ToHandler()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unknown handler %s", vs)
			continue
		}

		km[k] = v
	}

	return nil
}
<|endoftext|>