<commit_before>// Copyright 2012 Arne Roomann-Kurrik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package json

import (
	"bytes"
	"fmt"
	"reflect"
	"strings"
	"strconv"
)

const (
	STRING = iota
	NUMBER
	MAP
	ARRAY
	ENDARRAY
	ESCAPE
	BOOL
	NULL
)

type Event struct {
	Type  int
	Index int
}

type State struct {
	data   []byte
	i      int
	v      interface{}
	events []Event
}

func (s *State) Read() (err error) {
	var t int = s.nextType()
	switch t {
	case STRING:
		err = s.readString()
	case NUMBER:
		err = s.readNumber()
	case MAP:
		err = s.readMap()
	case ARRAY:
		err = s.readArray()
	case ENDARRAY:
		s.i++
		err = EndArray{}
	case BOOL:
		err = s.readBool()
	case NULL:
		err = s.readNull()
	case ESCAPE:
		err = fmt.Errorf("JSON should not start with escape")
	default:
		b := string(s.data[s.i-10 : s.i])
		c := string(s.data[s.i : s.i+1])
		e := string(s.data[s.i+1 : s.i+10])
		err = fmt.Errorf("Unrecognized type in %v -->%v<-- %v", b, c, e)
	}
	return
}

func (s *State) nextType() int {
	for {
		c := s.data[s.i]
		switch {
		case c == ' ':
			fallthrough
		case c == '\t':
			s.i++
			break
		case c == '"':
			return STRING
		case '0' <= c && c <= '9' || c == '-':
			return NUMBER
		case c == '[':
			return ARRAY
		case c == ']':
			return ENDARRAY
		case c == '{':
			return MAP
		case c == 't' || c == 'T' || c == 'f' || c == 'F':
			return BOOL
		case c == 'n':
			return NULL
		}
	}
	return -1
}

func (s *State) readString() (err error) {
	var (
		c       byte
		start   int
		buf     *bytes.Buffer
		atstart bool = false
		more    bool = true
		utf     bool = false
	)
	for atstart == false {
		c = s.data[s.i]
		switch {
		case c == ' ':
			fallthrough
		case c == '\t':
			s.i++
		case c == '"':
			atstart = true
			break
		case c == '}':
			s.i++
			return EndMap{}
		case c == ']':
			s.i++
			return EndArray{}
		}
	}
	s.i++
	start = s.i
	buf = new(bytes.Buffer)
	for more {
		c = s.data[s.i]
		switch {
		case c == '\\':
			buf.Write(s.data[start:s.i])
			if len(s.data) > s.i+6 {
				if s.data[s.i+1] == 'u' {
					utf = true
					buf.WriteString("\\")
				}
			}
			s.i++
			start = s.i
		case c == '"':
			more = false
		case s.i >= len(s.data)-1:
			return fmt.Errorf("No string terminator")
		}
		s.i++
	}
	buf.Write(s.data[start : s.i-1])
	s.v = buf.String()
	if utf == true {
		s.v, err = strconv.Unquote(fmt.Sprintf("\"%v\"", s.v))
	}
	return
}

func (s *State) readNumber() (err error) {
	var c byte
	var val int64 = 0
	var valf float64 = 0
	var mult int64 = 1
	if s.data[s.i] == '-' {
		mult = -1
		s.i++
	}
	var more = true
	var places int = 0
	for more {
		c = s.data[s.i]
		switch {
		case '0' <= c && c <= '9':
			if places != 0 {
				places *= 10
			}
			val = val*10 + int64(c-'0')
		case '}' == c:
			err = EndMap{}
			more = false
		case ']' == c:
			err = EndArray{}
			more = false
		case ',' == c:
			s.i--
			more = false
		case ' ' == c || '\t' == c:
			more = false
		case '.' == c:
			valf = float64(val)
			val = 0
			places = 1
		default:
			return fmt.Errorf("Bad num char: %v", string([]byte{c}))
		}
		if s.i >= len(s.data)-1 {
			more = false
		}
		s.i++
	}
	if places > 0 {
		s.v = valf + (float64(val)/float64(places))*float64(mult)
	} else {
		s.v = val * mult
	}
	return
}

type EndMap struct{}

func (e EndMap) Error() string {
	return "End of map structure encountered."
}

type EndArray struct{}

func (e EndArray) Error() string {
	return "End of array structure encountered."
}

func (s *State) readComma() (err error) {
	var more = true
	for more {
		switch {
		case s.data[s.i] == ',':
			more = false
		case s.data[s.i] == '}':
			s.i++
			return EndMap{}
		case s.data[s.i] == ']':
			s.i++
			return EndArray{}
		case s.i >= len(s.data)-1:
			return fmt.Errorf("No comma")
		}
		s.i++
	}
	return nil
}

func (s *State) readColon() (err error) {
	var more = true
	for more {
		switch {
		case s.data[s.i] == ':':
			more = false
		case s.i >= len(s.data)-1:
			return fmt.Errorf("No colon")
		}
		s.i++
	}
	return nil
}

func (s *State) readMap() (err error) {
	s.i++
	var (
		m   map[string]interface{}
		key string
	)
	m = make(map[string]interface{})
	for {
		if err = s.readString(); err != nil {
			return
		}
		key = s.v.(string)
		if err = s.readColon(); err != nil {
			return
		}
		if err = s.Read(); err != nil {
			if _, ok := err.(EndMap); !ok {
				return
			}
		}
		m[key] = s.v
		if _, ok := err.(EndMap); ok {
			break
		}
		if err = s.readComma(); err != nil {
			if _, ok := err.(EndMap); ok {
				break
			}
			return
		}
	}
	s.v = m
	return nil
}

func (s *State) readArray() (err error) {
	s.i++
	var (
		a []interface{}
	)
	a = make([]interface{}, 0, 10)
	for {
		if err = s.Read(); err != nil {
			if _, ok := err.(EndArray); !ok {
				return
			}
		}
		a = append(a, s.v)
		if _, ok := err.(EndArray); ok {
			break
		}
		if err = s.readComma(); err != nil {
			if _, ok := err.(EndArray); ok {
				break
			}
			return
		}
	}
	s.v = a
	return nil
}

func (s *State) readBool() (err error) {
	if strings.ToLower(string(s.data[s.i:s.i+4])) == "true" {
		s.i += 4
		s.v = true
	} else if strings.ToLower(string(s.data[s.i:s.i+5])) == "false" {
		s.i += 5
		s.v = false
	} else {
		err = fmt.Errorf("Could not parse boolean")
	}
	return
}

func (s *State) readNull() (err error) {
	if strings.ToLower(string(s.data[s.i:s.i+4])) == "null" {
		s.i += 4
		s.v = nil
	} else {
		err = fmt.Errorf("Could not parse null")
	}
	return
}

func Unmarshal(data []byte, v interface{}) error {
	state := &State{data, 0, v, make([]Event, 0, 10)}
	if err := state.Read(); err != nil {
		return err
	}
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return fmt.Errorf("Need a pointer, got %v", reflect.TypeOf(v))
	}
	for rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}
	sv := reflect.ValueOf(state.v)
	for sv.Kind() == reflect.Ptr {
		sv = sv.Elem()
	}
	var (
		rvt = rv.Type()
		svt = sv.Type()
	)
	if !svt.AssignableTo(rvt) {
		if rv.Kind() != reflect.Slice && sv.Kind() != reflect.Slice {
			return fmt.Errorf("Cannot assign %v to %v", svt, rvt)
		}
		var (
			mapi  map[string]interface{}
			mapt  = reflect.TypeOf(mapi)
			svte  = svt.Elem()
			rvte  = rvt.Elem()
			ismap bool
		)
		_, ismap = sv.Index(0).Interface().(map[string]interface{})
		if !(ismap && mapt.AssignableTo(rvte)) {
			return fmt.Errorf("Cannot assign %v to %v", svte, rvte)
		}
		var (
			ssv = reflect.MakeSlice(rvt, sv.Len(), sv.Cap())
		)
		for i := 0; i < sv.Len(); i++ {
			v := sv.Index(i).Interface().(map[string]interface{})
			ssv.Index(i).Set(reflect.ValueOf(v))
		}
		sv = ssv
	}
	rv.Set(sv)
	return nil
}
<commit_msg>Add more cases for decoding escaped UTF.<commit_after>// Copyright 2012 Arne Roomann-Kurrik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package json

import (
	"bytes"
	"fmt"
	"reflect"
	"strings"
	"strconv"
)

const (
	STRING = iota
	NUMBER
	MAP
	ARRAY
	ENDARRAY
	ESCAPE
	BOOL
	NULL
)

type Event struct {
	Type  int
	Index int
}

type State struct {
	data   []byte
	i      int
	v      interface{}
	events []Event
}

func (s *State) Read() (err error) {
	var t int = s.nextType()
	switch t {
	case STRING:
		err = s.readString()
	case NUMBER:
		err = s.readNumber()
	case MAP:
		err = s.readMap()
	case ARRAY:
		err = s.readArray()
	case ENDARRAY:
		s.i++
		err = EndArray{}
	case BOOL:
		err = s.readBool()
	case NULL:
		err = s.readNull()
	case ESCAPE:
		err = fmt.Errorf("JSON should not start with escape")
	default:
		b := string(s.data[s.i-10 : s.i])
		c := string(s.data[s.i : s.i+1])
		e := string(s.data[s.i+1 : s.i+10])
		err = fmt.Errorf("Unrecognized type in %v -->%v<-- %v", b, c, e)
	}
	return
}

func (s *State) nextType() int {
	for {
		c := s.data[s.i]
		switch {
		case c == ' ':
			fallthrough
		case c == '\t':
			s.i++
			break
		case c == '"':
			return STRING
		case '0' <= c && c <= '9' || c == '-':
			return NUMBER
		case c == '[':
			return ARRAY
		case c == ']':
			return ENDARRAY
		case c == '{':
			return MAP
		case c == 't' || c == 'T' || c == 'f' || c == 'F':
			return BOOL
		case c == 'n':
			return NULL
		}
	}
	return -1
}

func (s *State) readString() (err error) {
	var (
		c       byte
		start   int
		buf     *bytes.Buffer
		atstart bool = false
		more    bool = true
		utf     bool = false
	)
	for atstart == false {
		c = s.data[s.i]
		switch {
		case c == ' ':
			fallthrough
		case c == '\t':
			s.i++
		case c == '"':
			atstart = true
			break
		case c == '}':
			s.i++
			return EndMap{}
		case c == ']':
			s.i++
			return EndArray{}
		}
	}
	s.i++
	start = s.i
	buf = new(bytes.Buffer)
	for more {
		c = s.data[s.i]
		switch {
		case c == '\\':
			buf.Write(s.data[start:s.i])
			switch {
			case len(s.data) > s.i+8 && s.data[s.i+1] == 'U':
				fallthrough
			case len(s.data) > s.i+6 && s.data[s.i+1] == 'u':
				fallthrough
			case len(s.data) > s.i+4 && s.data[s.i+1] == 'x':
				utf = true
				buf.WriteString("\\")
			}
			s.i++
			start = s.i
		case c == '"':
			more = false
		case s.i >= len(s.data)-1:
			return fmt.Errorf("No string terminator")
		}
		s.i++
	}
	buf.Write(s.data[start : s.i-1])
	s.v = buf.String()
	if utf == true {
		s.v, err = strconv.Unquote(fmt.Sprintf("\"%v\"", s.v))
	}
	return
}

func (s *State) readNumber() (err error) {
	var c byte
	var val int64 = 0
	var valf float64 = 0
	var mult int64 = 1
	if s.data[s.i] == '-' {
		mult = -1
		s.i++
	}
	var more = true
	var places int = 0
	for more {
		c = s.data[s.i]
		switch {
		case '0' <= c && c <= '9':
			if places != 0 {
				places *= 10
			}
			val = val*10 + int64(c-'0')
		case '}' == c:
			err = EndMap{}
			more = false
		case ']' == c:
			err = EndArray{}
			more = false
		case ',' == c:
			s.i--
			more = false
		case ' ' == c || '\t' == c:
			more = false
		case '.' == c:
			valf = float64(val)
			val = 0
			places = 1
		default:
			return fmt.Errorf("Bad num char: %v", string([]byte{c}))
		}
		if s.i >= len(s.data)-1 {
			more = false
		}
		s.i++
	}
	if places > 0 {
		s.v = valf + (float64(val)/float64(places))*float64(mult)
	} else {
		s.v = val * mult
	}
	return
}

type EndMap struct{}

func (e EndMap) Error() string {
	return "End of map structure encountered."
}

type EndArray struct{}

func (e EndArray) Error() string {
	return "End of array structure encountered."
}

func (s *State) readComma() (err error) {
	var more = true
	for more {
		switch {
		case s.data[s.i] == ',':
			more = false
		case s.data[s.i] == '}':
			s.i++
			return EndMap{}
		case s.data[s.i] == ']':
			s.i++
			return EndArray{}
		case s.i >= len(s.data)-1:
			return fmt.Errorf("No comma")
		}
		s.i++
	}
	return nil
}

func (s *State) readColon() (err error) {
	var more = true
	for more {
		switch {
		case s.data[s.i] == ':':
			more = false
		case s.i >= len(s.data)-1:
			return fmt.Errorf("No colon")
		}
		s.i++
	}
	return nil
}

func (s *State) readMap() (err error) {
	s.i++
	var (
		m   map[string]interface{}
		key string
	)
	m = make(map[string]interface{})
	for {
		if err = s.readString(); err != nil {
			return
		}
		key = s.v.(string)
		if err = s.readColon(); err != nil {
			return
		}
		if err = s.Read(); err != nil {
			if _, ok := err.(EndMap); !ok {
				return
			}
		}
		m[key] = s.v
		if _, ok := err.(EndMap); ok {
			break
		}
		if err = s.readComma(); err != nil {
			if _, ok := err.(EndMap); ok {
				break
			}
			return
		}
	}
	s.v = m
	return nil
}

func (s *State) readArray() (err error) {
	s.i++
	var (
		a []interface{}
	)
	a = make([]interface{}, 0, 10)
	for {
		if err = s.Read(); err != nil {
			if _, ok := err.(EndArray); !ok {
				return
			}
		}
		a = append(a, s.v)
		if _, ok := err.(EndArray); ok {
			break
		}
		if err = s.readComma(); err != nil {
			if _, ok := err.(EndArray); ok {
				break
			}
			return
		}
	}
	s.v = a
	return nil
}

func (s *State) readBool() (err error) {
	if strings.ToLower(string(s.data[s.i:s.i+4])) == "true" {
		s.i += 4
		s.v = true
	} else if strings.ToLower(string(s.data[s.i:s.i+5])) == "false" {
		s.i += 5
		s.v = false
	} else {
		err = fmt.Errorf("Could not parse boolean")
	}
	return
}

func (s *State) readNull() (err error) {
	if strings.ToLower(string(s.data[s.i:s.i+4])) == "null" {
		s.i += 4
		s.v = nil
	} else {
		err = fmt.Errorf("Could not parse null")
	}
	return
}

func Unmarshal(data []byte, v interface{}) error {
	state := &State{data, 0, v, make([]Event, 0, 10)}
	if err := state.Read(); err != nil {
		return err
	}
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return fmt.Errorf("Need a pointer, got %v", reflect.TypeOf(v))
	}
	for rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}
	sv := reflect.ValueOf(state.v)
	for sv.Kind() == reflect.Ptr {
		sv = sv.Elem()
	}
	var (
		rvt = rv.Type()
		svt = sv.Type()
	)
	if !svt.AssignableTo(rvt) {
		if rv.Kind() != reflect.Slice && sv.Kind() != reflect.Slice {
			return fmt.Errorf("Cannot assign %v to %v", svt, rvt)
		}
		var (
			mapi  map[string]interface{}
			mapt  = reflect.TypeOf(mapi)
			svte  = svt.Elem()
			rvte  = rvt.Elem()
			ismap bool
		)
		_, ismap = sv.Index(0).Interface().(map[string]interface{})
		if !(ismap && mapt.AssignableTo(rvte)) {
			return fmt.Errorf("Cannot assign %v to %v", svte, rvte)
		}
		var (
			ssv = reflect.MakeSlice(rvt, sv.Len(), sv.Cap())
		)
		for i := 0; i < sv.Len(); i++ {
			v := sv.Index(i).Interface().(map[string]interface{})
			ssv.Index(i).Set(reflect.ValueOf(v))
		}
		sv = ssv
	}
	rv.Set(sv)
	return nil
}
<|endoftext|>


<commit_before>package core

import "github.com/mitchellh/go-homedir"

var directory string = "~/.config/runcom"

const Command = "runcom"
const Name = "Runcom"

func Directory() string {
	dir, err := homedir.Expand(directory)
	if err != nil {
		return ""
	}
	return dir
}
<commit_msg>Add PluginDirectory helper.<commit_after>package core

import "github.com/mitchellh/go-homedir"

var directory string = "~/.config/runcom"

const Command = "runcom"
const Name = "Runcom"

func Directory() string {
	dir, err := homedir.Expand(directory)
	if err != nil {
		return ""
	}
	return dir
}

func PluginDirectory(plugin string) string {
	dir := Directory()
	return filepath.Join(dir, plugin)
}
<|endoftext|>


<commit_before>// +build linux,amd64 linux,ppc64le

// Build constraint to use this file for amd64 & ppc64le on Linux

package endpoint

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"sync"
	"time"

	"github.com/bluele/gcache"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	log "github.com/sirupsen/logrus"
)

const (
	bufSize                     = 8 * 1024 * 1024 // 8MB
	maxReverseDNSrecords        = 10000
	maxLogsPerDecodingError     = 4
	maxDecodingErrorCardinality = 1000
)

// DNSSnooper is a snopper of DNS queries
type DNSSnooper struct {
	stop       chan struct{}
	pcapHandle *pcap.Handle
	// gcache is goroutine-safe, but the cached values aren't
	reverseDNSMutex     sync.RWMutex
	reverseDNSCache     gcache.Cache
	decodingErrorCounts map[string]uint64 // for limiting
}

// NewDNSSnooper creates a new snooper of DNS queries
func NewDNSSnooper() (*DNSSnooper, error) {
	pcapHandle, err := newPcapHandle()
	if err != nil {
		return nil, err
	}
	reverseDNSCache := gcache.New(maxReverseDNSrecords).LRU().Build()

	s := &DNSSnooper{
		stop:                make(chan struct{}),
		pcapHandle:          pcapHandle,
		reverseDNSCache:     reverseDNSCache,
		decodingErrorCounts: map[string]uint64{},
	}
	go s.run()
	return s, nil
}

func newPcapHandle() (*pcap.Handle, error) {
	inactive, err := pcap.NewInactiveHandle("any")
	if err != nil {
		return nil, err
	}
	defer inactive.CleanUp()
	// pcap timeout blackmagic copied from Weave Net to reduce CPU consumption
	// see https://github.com/weaveworks/weave/commit/025315363d5ea8b8265f1b3ea800f24df2be51a4
	if err = inactive.SetTimeout(time.Duration(math.MaxInt64)); err != nil {
		return nil, err
	}
	if err = inactive.SetImmediateMode(true); err != nil {
		// If gopacket is compiled against an older pcap.h that
		// doesn't have pcap_set_immediate_mode, it supplies a dummy
		// definition that always returns PCAP_ERROR.  That becomes
		// "Generic error", which is not very helpful.  The real
		// pcap_set_immediate_mode never returns PCAP_ERROR, so this
		// turns it into a more informative message.
		if fmt.Sprint(err) == "Generic error" {
			return nil, fmt.Errorf("compiled against an old version of libpcap; please compile against libpcap-1.5.0 or later")
		}

		return nil, err
	}
	if err = inactive.SetBufferSize(bufSize); err != nil {
		return nil, err
	}
	pcapHandle, err := inactive.Activate()
	if err != nil {
		return nil, err
	}
	if err := pcapHandle.SetDirection(pcap.DirectionIn); err != nil {
		pcapHandle.Close()
		return nil, err
	}
	if err := pcapHandle.SetBPFFilter("inbound and port 53"); err != nil {
		pcapHandle.Close()
		return nil, err
	}

	return pcapHandle, nil
}

// CachedNamesForIP obtains the domains associated to an IP,
// obtained while snooping A-record queries
func (s *DNSSnooper) CachedNamesForIP(ip string) []string {
	result := []string{}
	if s == nil {
		return result
	}
	domains, err := s.reverseDNSCache.Get(ip)
	if err != nil {
		return result
	}
	s.reverseDNSMutex.RLock()
	for domain := range domains.(map[string]struct{}) {
		result = append(result, domain)
	}
	s.reverseDNSMutex.RUnlock()

	return result
}

// Stop makes the snooper stop inspecting DNS communications
func (s *DNSSnooper) Stop() {
	if s != nil {
		close(s.stop)
	}
}

// Gopacket doesn't provide direct support for DNS over TCP, see https://github.com/google/gopacket/issues/236
type tcpWithDNSSupport struct {
	tcp layers.TCP
}

func (m *tcpWithDNSSupport) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	return m.tcp.DecodeFromBytes(data, df)
}

func (m *tcpWithDNSSupport) CanDecode() gopacket.LayerClass { return m.tcp.CanDecode() }

// Determine if a TCP segment contains a full DNS message (i.e. not fragmented)
func (m *tcpWithDNSSupport) hasSelfContainedDNSPayload() bool {
	payload := m.tcp.LayerPayload()
	if len(payload) < 2 {
		return false
	}

	// Assume it's a self-contained DNS message if the Length field
	// matches the length of the TCP segment
	dnsLengthField := binary.BigEndian.Uint16(payload)
	return int(dnsLengthField) == len(payload)-2
}

func (m *tcpWithDNSSupport) NextLayerType() gopacket.LayerType {
	// TODO: deal with TCP fragmentation and out-of-order segments
	if (m.tcp.SrcPort == 53 || m.tcp.DstPort == 53) && m.hasSelfContainedDNSPayload() {
		return layers.LayerTypeDNS
	}
	return m.tcp.NextLayerType()
}

func (m *tcpWithDNSSupport) LayerPayload() []byte {
	payload := m.tcp.LayerPayload()
	if len(payload) > 1 && (m.tcp.SrcPort == 53 || m.tcp.DstPort == 53) {
		// Omit the DNS length field, only included
		// in TCP, in order to reuse the DNS UDP parser
		payload = payload[2:]
	}
	return payload
}

func (s *DNSSnooper) run() {
	var (
		decodedLayers []gopacket.LayerType
		dns           layers.DNS
		udp           layers.UDP
		tcp           tcpWithDNSSupport
		ip4           layers.IPv4
		ip6           layers.IPv6
		eth           layers.Ethernet
		dot1q         layers.Dot1Q
		sll           layers.LinuxSLL
	)

	// assumes that the "any" interface is being used (see https://wiki.wireshark.org/SLL)
	packetParser := gopacket.NewDecodingLayerParser(layers.LayerTypeLinuxSLL, &sll, &dot1q, &eth, &ip4, &ip6, &udp, &tcp, &dns)

	for {
		select {
		case <-s.stop:
			s.pcapHandle.Close()
			return
		default:
		}

		packet, _, err := s.pcapHandle.ZeroCopyReadPacketData()
		if err != nil {
			// TimeoutExpired is acceptable due to the Timeout black magic
			// on the handle.
			if err != pcap.NextErrorTimeoutExpired {
				log.Errorf("DNSSnooper: error reading packet data: %s", err)
			}
			continue
		}

		if err := packetParser.DecodeLayers(packet, &decodedLayers); err != nil {
			// LayerTypePayload indicates the TCP payload has non-DNS data, which we are not interested in
			if layer, ok := err.(gopacket.UnsupportedLayerType); !ok || gopacket.LayerType(layer) != gopacket.LayerTypePayload {
				s.handleDecodingError(err)
			}
			continue
		}

		for _, layerType := range decodedLayers {
			if layerType == layers.LayerTypeDNS {
				s.processDNSMessage(&dns)
			}
		}
	}
}

// handleDecodeError logs errors up to the maximum allowed count
func (s *DNSSnooper) handleDecodingError(err error) {
	// prevent potential memory leak
	if len(s.decodingErrorCounts) > maxDecodingErrorCardinality {
		return
	}

	str := err.Error()
	count := s.decodingErrorCounts[str]
	count++
	s.decodingErrorCounts[str] = count
	switch {
	case count == maxLogsPerDecodingError:
		log.Errorf("DNSSnooper: error decoding packet: %s (reached %d occurrences, silencing)", str, maxLogsPerDecodingError)
	case count < maxLogsPerDecodingError:
		log.Errorf("DNSSnooper: error decoding packet: %s", str)
	}
}

func (s *DNSSnooper) processDNSMessage(dns *layers.DNS) {

	// Only consider responses to singleton, A-record questions
	if !dns.QR || dns.ResponseCode != 0 || len(dns.Questions) != 1 {
		return
	}
	question := dns.Questions[0]
	if question.Type != layers.DNSTypeA || question.Class != layers.DNSClassIN {
		return
	}

	var (
		domainQueried = question.Name
		records       = append(dns.Answers, dns.Additionals...)
		ips           = map[string]struct{}{}
		aliases       = [][]byte{}
	)

	// Traverse all the CNAME records and the get the aliases. There are cases when the A record is for only one of the
	// aliases. We traverse CNAME records first because there is no guarantee that the A records will be the first ones
	for _, record := range records {
		if record.Type == layers.DNSTypeCNAME && record.Class == layers.DNSClassIN {
			aliases = append(aliases, record.CNAME)
		}
	}

	// Finally, get the answer
	for _, record := range records {
		if record.Type != layers.DNSTypeA || record.Class != layers.DNSClassIN {
			continue
		}
		if bytes.Equal(domainQueried, record.Name) {
			ips[record.IP.String()] = struct{}{}
			continue
		}
		for _, alias := range aliases {
			if bytes.Equal(alias, record.Name) {
				ips[record.IP.String()] = struct{}{}
				break
			}
		}
	}

	// Update cache
	newDomain := string(domainQueried)
	log.Debugf("DNSSnooper: caught DNS lookup: %s -> %v", newDomain, ips)
	for ip := range ips {
		if existingDomains, err := s.reverseDNSCache.Get(ip); err != nil {
			s.reverseDNSCache.Set(ip, map[string]struct{}{newDomain: {}})
		} else {
			// TODO: Be smarter about the expiration of entries with pre-existing associated domains
			s.reverseDNSMutex.Lock()
			existingDomains.(map[string]struct{})[newDomain] = struct{}{}
			s.reverseDNSMutex.Unlock()
		}
	}
}
<commit_msg>Change dns snooper timeout to avoid spinning in pcap<commit_after>// +build linux,amd64 linux,ppc64le

// Build constraint to use this file for amd64 & ppc64le on Linux

package endpoint

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"sync"
	"time"

	"github.com/bluele/gcache"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	log "github.com/sirupsen/logrus"
)

const (
	bufSize                     = 8 * 1024 * 1024 // 8MB
	maxReverseDNSrecords        = 10000
	maxLogsPerDecodingError     = 4
	maxDecodingErrorCardinality = 1000
)

// DNSSnooper is a snopper of DNS queries
type DNSSnooper struct {
	stop       chan struct{}
	pcapHandle *pcap.Handle
	// gcache is goroutine-safe, but the cached values aren't
	reverseDNSMutex     sync.RWMutex
	reverseDNSCache     gcache.Cache
	decodingErrorCounts map[string]uint64 // for limiting
}

// NewDNSSnooper creates a new snooper of DNS queries
func NewDNSSnooper() (*DNSSnooper, error) {
	pcapHandle, err := newPcapHandle()
	if err != nil {
		return nil, err
	}
	reverseDNSCache := gcache.New(maxReverseDNSrecords).LRU().Build()

	s := &DNSSnooper{
		stop:                make(chan struct{}),
		pcapHandle:          pcapHandle,
		reverseDNSCache:     reverseDNSCache,
		decodingErrorCounts: map[string]uint64{},
	}
	go s.run()
	return s, nil
}

func newPcapHandle() (*pcap.Handle, error) {
	inactive, err := pcap.NewInactiveHandle("any")
	if err != nil {
		return nil, err
	}
	defer inactive.CleanUp()
	// Set a long timeout because "pcap.BlockForever" actually spins on a 10ms timeout
	// see https://github.com/weaveworks/weave/commit/025315363d5ea8b8265f1b3ea800f24df2be51a4
	// (note the value in microseconds has to fit in a 32-bit signed int)
	if err = inactive.SetTimeout(time.Minute * 30); err != nil {
		return nil, err
	}
	if err = inactive.SetImmediateMode(true); err != nil {
		// If gopacket is compiled against an older pcap.h that
		// doesn't have pcap_set_immediate_mode, it supplies a dummy
		// definition that always returns PCAP_ERROR.  That becomes
		// "Generic error", which is not very helpful.  The real
		// pcap_set_immediate_mode never returns PCAP_ERROR, so this
		// turns it into a more informative message.
		if fmt.Sprint(err) == "Generic error" {
			return nil, fmt.Errorf("compiled against an old version of libpcap; please compile against libpcap-1.5.0 or later")
		}

		return nil, err
	}
	if err = inactive.SetBufferSize(bufSize); err != nil {
		return nil, err
	}
	pcapHandle, err := inactive.Activate()
	if err != nil {
		return nil, err
	}
	if err := pcapHandle.SetDirection(pcap.DirectionIn); err != nil {
		pcapHandle.Close()
		return nil, err
	}
	if err := pcapHandle.SetBPFFilter("inbound and port 53"); err != nil {
		pcapHandle.Close()
		return nil, err
	}

	return pcapHandle, nil
}

// CachedNamesForIP obtains the domains associated to an IP,
// obtained while snooping A-record queries
func (s *DNSSnooper) CachedNamesForIP(ip string) []string {
	result := []string{}
	if s == nil {
		return result
	}
	domains, err := s.reverseDNSCache.Get(ip)
	if err != nil {
		return result
	}
	s.reverseDNSMutex.RLock()
	for domain := range domains.(map[string]struct{}) {
		result = append(result, domain)
	}
	s.reverseDNSMutex.RUnlock()

	return result
}

// Stop makes the snooper stop inspecting DNS communications
func (s *DNSSnooper) Stop() {
	if s != nil {
		close(s.stop)
	}
}

// Gopacket doesn't provide direct support for DNS over TCP, see https://github.com/google/gopacket/issues/236
type tcpWithDNSSupport struct {
	tcp layers.TCP
}

func (m *tcpWithDNSSupport) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	return m.tcp.DecodeFromBytes(data, df)
}

func (m *tcpWithDNSSupport) CanDecode() gopacket.LayerClass { return m.tcp.CanDecode() }

// Determine if a TCP segment contains a full DNS message (i.e. not fragmented)
func (m *tcpWithDNSSupport) hasSelfContainedDNSPayload() bool {
	payload := m.tcp.LayerPayload()
	if len(payload) < 2 {
		return false
	}

	// Assume it's a self-contained DNS message if the Length field
	// matches the length of the TCP segment
	dnsLengthField := binary.BigEndian.Uint16(payload)
	return int(dnsLengthField) == len(payload)-2
}

func (m *tcpWithDNSSupport) NextLayerType() gopacket.LayerType {
	// TODO: deal with TCP fragmentation and out-of-order segments
	if (m.tcp.SrcPort == 53 || m.tcp.DstPort == 53) && m.hasSelfContainedDNSPayload() {
		return layers.LayerTypeDNS
	}
	return m.tcp.NextLayerType()
}

func (m *tcpWithDNSSupport) LayerPayload() []byte {
	payload := m.tcp.LayerPayload()
	if len(payload) > 1 && (m.tcp.SrcPort == 53 || m.tcp.DstPort == 53) {
		// Omit the DNS length field, only included
		// in TCP, in order to reuse the DNS UDP parser
		payload = payload[2:]
	}
	return payload
}

func (s *DNSSnooper) run() {
	var (
		decodedLayers []gopacket.LayerType
		dns           layers.DNS
		udp           layers.UDP
		tcp           tcpWithDNSSupport
		ip4           layers.IPv4
		ip6           layers.IPv6
		eth           layers.Ethernet
		dot1q         layers.Dot1Q
		sll           layers.LinuxSLL
	)

	// assumes that the "any" interface is being used (see https://wiki.wireshark.org/SLL)
	packetParser := gopacket.NewDecodingLayerParser(layers.LayerTypeLinuxSLL, &sll, &dot1q, &eth, &ip4, &ip6, &udp, &tcp, &dns)

	for {
		select {
		case <-s.stop:
			s.pcapHandle.Close()
			return
		default:
		}

		packet, _, err := s.pcapHandle.ZeroCopyReadPacketData()
		if err != nil {
			// TimeoutExpired is acceptable due to the Timeout black magic
			// on the handle.
			if err != pcap.NextErrorTimeoutExpired {
				log.Errorf("DNSSnooper: error reading packet data: %s", err)
			}
			continue
		}

		if err := packetParser.DecodeLayers(packet, &decodedLayers); err != nil {
			// LayerTypePayload indicates the TCP payload has non-DNS data, which we are not interested in
			if layer, ok := err.(gopacket.UnsupportedLayerType); !ok || gopacket.LayerType(layer) != gopacket.LayerTypePayload {
				s.handleDecodingError(err)
			}
			continue
		}

		for _, layerType := range decodedLayers {
			if layerType == layers.LayerTypeDNS {
				s.processDNSMessage(&dns)
			}
		}
	}
}

// handleDecodeError logs errors up to the maximum allowed count
func (s *DNSSnooper) handleDecodingError(err error) {
	// prevent potential memory leak
	if len(s.decodingErrorCounts) > maxDecodingErrorCardinality {
		return
	}

	str := err.Error()
	count := s.decodingErrorCounts[str]
	count++
	s.decodingErrorCounts[str] = count
	switch {
	case count == maxLogsPerDecodingError:
		log.Errorf("DNSSnooper: error decoding packet: %s (reached %d occurrences, silencing)", str, maxLogsPerDecodingError)
	case count < maxLogsPerDecodingError:
		log.Errorf("DNSSnooper: error decoding packet: %s", str)
	}
}

func (s *DNSSnooper) processDNSMessage(dns *layers.DNS) {

	// Only consider responses to singleton, A-record questions
	if !dns.QR || dns.ResponseCode != 0 || len(dns.Questions) != 1 {
		return
	}
	question := dns.Questions[0]
	if question.Type != layers.DNSTypeA || question.Class != layers.DNSClassIN {
		return
	}

	var (
		domainQueried = question.Name
		records       = append(dns.Answers, dns.Additionals...)
		ips           = map[string]struct{}{}
		aliases       = [][]byte{}
	)

	// Traverse all the CNAME records and the get the aliases. There are cases when the A record is for only one of the
	// aliases. We traverse CNAME records first because there is no guarantee that the A records will be the first ones
	for _, record := range records {
		if record.Type == layers.DNSTypeCNAME && record.Class == layers.DNSClassIN {
			aliases = append(aliases, record.CNAME)
		}
	}

	// Finally, get the answer
	for _, record := range records {
		if record.Type != layers.DNSTypeA || record.Class != layers.DNSClassIN {
			continue
		}
		if bytes.Equal(domainQueried, record.Name) {
			ips[record.IP.String()] = struct{}{}
			continue
		}
		for _, alias := range aliases {
			if bytes.Equal(alias, record.Name) {
				ips[record.IP.String()] = struct{}{}
				break
			}
		}
	}

	// Update cache
	newDomain := string(domainQueried)
	log.Debugf("DNSSnooper: caught DNS lookup: %s -> %v", newDomain, ips)
	for ip := range ips {
		if existingDomains, err := s.reverseDNSCache.Get(ip); err != nil {
			s.reverseDNSCache.Set(ip, map[string]struct{}{newDomain: {}})
		} else {
			// TODO: Be smarter about the expiration of entries with pre-existing associated domains
			s.reverseDNSMutex.Lock()
			existingDomains.(map[string]struct{})[newDomain] = struct{}{}
			s.reverseDNSMutex.Unlock()
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
)

type product struct {
	ID    int     `json:"id"`
	Name  string  `json:"name"`
	Price float64 `json:"price"`
}

func (p *product) getProduct(db *sql.DB) error {
	return db.QueryRow("SELECT name, price FROM products WHERE id=$1", p.ID).Scan(&p.Name, &p.Price)
}

func (p *product) updateProduct(db *sql.DB) error {
	_, err := db.Exec("UPDATE products SET name=$1, price=$2 WHERE id=$3", p.Name, p.Price, p.ID)
	return err
}

func (p *product) deleteProduct(db *sql.DB) error {
	_, err := db.Exec("DELETE FROM products WHERE id=$1", p.ID)
	return err
}

func (p *product) createProduct(db *sql.DB) error {
	err := db.QueryRow("INSERT INTO products(name, price) VLAUES($1, $2) RETURNING id", p.Name, p.Price).Scan(&p.ID)

	if err != nil {
		return err
	}
	return nil
}

//fetch al products
func getProducts(db *sql.DB, start, count int) ([]product, error) {
	rows, err := db.Query("SELECT id, name, price FROM products LIMIT $1 OFFSET $2", count, start)

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	products := []product{}

	for rows.Next() {
		var p product
		if err := rows.Scan(&p.ID, &p.Name, &p.Price); err != nil {
			return nil, err
		}
		products = append(products, p)
	}

	return products, nil

}
<commit_msg>Fix test to create product<commit_after>package main

import (
	"database/sql"
)

type product struct {
	ID    int     `json:"id"`
	Name  string  `json:"name"`
	Price float64 `json:"price"`
}

func (p *product) getProduct(db *sql.DB) error {
	return db.QueryRow("SELECT name, price FROM products WHERE id=$1", p.ID).Scan(&p.Name, &p.Price)
}

func (p *product) updateProduct(db *sql.DB) error {
	_, err := db.Exec("UPDATE products SET name=$1, price=$2 WHERE id=$3", p.Name, p.Price, p.ID)
	return err
}

func (p *product) deleteProduct(db *sql.DB) error {
	_, err := db.Exec("DELETE FROM products WHERE id=$1", p.ID)
	return err
}

func (p *product) createProduct(db *sql.DB) error {
	err := db.QueryRow("INSERT INTO products(name, price) VALUES($1, $2) RETURNING id", p.Name, p.Price).Scan(&p.ID)

	if err != nil {
		return err
	}
	return nil
}

//fetch al products
func getProducts(db *sql.DB, start, count int) ([]product, error) {
	rows, err := db.Query("SELECT id, name, price FROM products LIMIT $1 OFFSET $2", count, start)

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	products := []product{}

	for rows.Next() {
		var p product
		if err := rows.Scan(&p.ID, &p.Name, &p.Price); err != nil {
			return nil, err
		}
		products = append(products, p)
	}

	return products, nil

}
<|endoftext|>


<commit_before>package radix

import (
	"strings"
	"sync"
	"time"
)

var blockingCmds = map[string]bool{
	"WAIT": true,

	// taken from https://github.com/joomcode/redispipe#limitations
	"BLPOP":      true,
	"BRPOP":      true,
	"BRPOPLPUSH": true,

	"BZPOPMIN": true,
	"BZPOPMAX": true,

	"XREAD":      true,
	"XREADGROUP": true,

	"SAVE": true,
}

type pipeliner struct {
	c Client

	limit  int
	window time.Duration

	// reqsBufCh contains buffers for collecting commands and acts as a semaphore
	// to limit the number of concurrent flushes.
	reqsBufCh chan []CmdAction

	reqCh chan *pipelinerCmd
	reqWG sync.WaitGroup

	l      sync.RWMutex
	closed bool
}

var _ Client = (*pipeliner)(nil)

func newPipeliner(c Client, concurrency, limit int, window time.Duration) *pipeliner {
	if concurrency < 1 {
		concurrency = 1
	}

	p := &pipeliner{
		c: c,

		limit:  limit,
		window: window,

		reqsBufCh: make(chan []CmdAction, concurrency),

		reqCh: make(chan *pipelinerCmd, 32), // https://xkcd.com/221/
	}

	p.reqWG.Add(1)
	go func() {
		defer p.reqWG.Done()
		p.reqLoop()
	}()

	for i := 0; i < cap(p.reqsBufCh); i++ {
		if p.limit > 0 {
			p.reqsBufCh <- make([]CmdAction, 0, limit)
		} else {
			p.reqsBufCh <- nil
		}
	}

	return p
}

// CanDo checks if the given Action can be executed / passed to p.Do.
//
// If CanDo returns false, the Action must not be given to Do.
func (p *pipeliner) CanDo(a Action) bool {
	// there is currently no way to get the command for CmdAction implementations
	// from outside the radix package so we can not multiplex those commands. User
	// defined pipelines are not pipelined to let the user better control them.
	if cmdA, ok := a.(*cmdAction); ok {
		return !blockingCmds[strings.ToUpper(cmdA.cmd)]
	}
	return false
}

// Do executes the given Action as part of the pipeline.
//
// If a is not a CmdAction, Do panics.
func (p *pipeliner) Do(a Action) error {
	req := getPipelinerCmd(a.(CmdAction)) // get this outside the lock to avoid

	p.l.RLock()
	if p.closed {
		p.l.RUnlock()
		return errClientClosed
	}
	p.reqCh <- req
	p.l.RUnlock()

	err := <-req.resCh
	poolPipelinerCmd(req)
	return err
}

// Close closes the pipeliner and makes sure that all background goroutines
// are stopped before returning.
//
// Close does *not* close the underlying Client.
func (p *pipeliner) Close() error {
	p.l.Lock()
	defer p.l.Unlock()

	if p.closed {
		return nil
	}

	close(p.reqCh)
	p.reqWG.Wait()

	for i := 0; i < cap(p.reqsBufCh); i++ {
		<-p.reqsBufCh
	}

	p.c, p.closed = nil, true
	return nil
}

func (p *pipeliner) reqLoop() {
	t := getTimer(time.Hour)
	defer putTimer(t)

	t.Stop()

	reqs := <-p.reqsBufCh
	defer func() {
		p.reqsBufCh <- reqs
	}()

	for {
		select {
		case req, ok := <-p.reqCh:
			if !ok {
				reqs = p.flush(reqs)
				return
			}

			reqs = append(reqs, req)

			if p.limit > 0 && len(reqs) == p.limit {
				// if we reached the pipeline limit, execute now to avoid unnecessary waiting
				t.Stop()

				reqs = p.flush(reqs)
			} else if len(reqs) == 1 {
				t.Reset(p.window)
			}
		case <-t.C:
			reqs = p.flush(reqs)
		}
	}
}

func (p *pipeliner) flush(reqs []CmdAction) []CmdAction {
	if len(reqs) == 0 {
		return reqs
	}

	go func() {
		defer func() {
			p.reqsBufCh <- reqs[:0]
		}()

		pipe := pipelinerPipeline{
			pipeline: pipeline(reqs),
		}

		if err := p.c.Do(pipe); err != nil {
			for _, req := range reqs {
				req.(*pipelinerCmd).resCh <- err
			}
		}
	}()

	return <-p.reqsBufCh
}

type pipelinerCmd struct {
	CmdAction
	resCh chan error
}

var pipelinerCmdPool sync.Pool

func getPipelinerCmd(cmd CmdAction) *pipelinerCmd {
	req, _ := pipelinerCmdPool.Get().(*pipelinerCmd)
	if req != nil {
		req.CmdAction = cmd
		return req
	}
	return &pipelinerCmd{
		CmdAction: cmd,
		// using a buffer of 1 is faster than no buffer in most cases
		resCh: make(chan error, 1),
	}
}

func poolPipelinerCmd(req *pipelinerCmd) {
	req.CmdAction = nil
	pipelinerCmdPool.Put(req)
}

type pipelinerPipeline struct {
	pipeline
}

func (p pipelinerPipeline) Run(c Conn) error {
	if err := c.Encode(p); err != nil {
		return err
	}
	for _, req := range p.pipeline {
		req.(*pipelinerCmd).resCh <- c.Decode(req)
	}
	return nil
}
<commit_msg>Stop decoding responses after a net.Error when pipelining<commit_after>package radix

import (
	"net"
	"strings"
	"sync"
	"time"
)

var blockingCmds = map[string]bool{
	"WAIT": true,

	// taken from https://github.com/joomcode/redispipe#limitations
	"BLPOP":      true,
	"BRPOP":      true,
	"BRPOPLPUSH": true,

	"BZPOPMIN": true,
	"BZPOPMAX": true,

	"XREAD":      true,
	"XREADGROUP": true,

	"SAVE": true,
}

type pipeliner struct {
	c Client

	limit  int
	window time.Duration

	// reqsBufCh contains buffers for collecting commands and acts as a semaphore
	// to limit the number of concurrent flushes.
	reqsBufCh chan []CmdAction

	reqCh chan *pipelinerCmd
	reqWG sync.WaitGroup

	l      sync.RWMutex
	closed bool
}

var _ Client = (*pipeliner)(nil)

func newPipeliner(c Client, concurrency, limit int, window time.Duration) *pipeliner {
	if concurrency < 1 {
		concurrency = 1
	}

	p := &pipeliner{
		c: c,

		limit:  limit,
		window: window,

		reqsBufCh: make(chan []CmdAction, concurrency),

		reqCh: make(chan *pipelinerCmd, 32), // https://xkcd.com/221/
	}

	p.reqWG.Add(1)
	go func() {
		defer p.reqWG.Done()
		p.reqLoop()
	}()

	for i := 0; i < cap(p.reqsBufCh); i++ {
		if p.limit > 0 {
			p.reqsBufCh <- make([]CmdAction, 0, limit)
		} else {
			p.reqsBufCh <- nil
		}
	}

	return p
}

// CanDo checks if the given Action can be executed / passed to p.Do.
//
// If CanDo returns false, the Action must not be given to Do.
func (p *pipeliner) CanDo(a Action) bool {
	// there is currently no way to get the command for CmdAction implementations
	// from outside the radix package so we can not multiplex those commands. User
	// defined pipelines are not pipelined to let the user better control them.
	if cmdA, ok := a.(*cmdAction); ok {
		return !blockingCmds[strings.ToUpper(cmdA.cmd)]
	}
	return false
}

// Do executes the given Action as part of the pipeline.
//
// If a is not a CmdAction, Do panics.
func (p *pipeliner) Do(a Action) error {
	req := getPipelinerCmd(a.(CmdAction)) // get this outside the lock to avoid

	p.l.RLock()
	if p.closed {
		p.l.RUnlock()
		return errClientClosed
	}
	p.reqCh <- req
	p.l.RUnlock()

	err := <-req.resCh
	poolPipelinerCmd(req)
	return err
}

// Close closes the pipeliner and makes sure that all background goroutines
// are stopped before returning.
//
// Close does *not* close the underlying Client.
func (p *pipeliner) Close() error {
	p.l.Lock()
	defer p.l.Unlock()

	if p.closed {
		return nil
	}

	close(p.reqCh)
	p.reqWG.Wait()

	for i := 0; i < cap(p.reqsBufCh); i++ {
		<-p.reqsBufCh
	}

	p.c, p.closed = nil, true
	return nil
}

func (p *pipeliner) reqLoop() {
	t := getTimer(time.Hour)
	defer putTimer(t)

	t.Stop()

	reqs := <-p.reqsBufCh
	defer func() {
		p.reqsBufCh <- reqs
	}()

	for {
		select {
		case req, ok := <-p.reqCh:
			if !ok {
				reqs = p.flush(reqs)
				return
			}

			reqs = append(reqs, req)

			if p.limit > 0 && len(reqs) == p.limit {
				// if we reached the pipeline limit, execute now to avoid unnecessary waiting
				t.Stop()

				reqs = p.flush(reqs)
			} else if len(reqs) == 1 {
				t.Reset(p.window)
			}
		case <-t.C:
			reqs = p.flush(reqs)
		}
	}
}

func (p *pipeliner) flush(reqs []CmdAction) []CmdAction {
	if len(reqs) == 0 {
		return reqs
	}

	go func() {
		defer func() {
			p.reqsBufCh <- reqs[:0]
		}()

		pipe := pipelinerPipeline{
			pipeline: pipeline(reqs),
		}

		if err := p.c.Do(pipe); err != nil {
			for _, req := range reqs {
				select {
				case req.(*pipelinerCmd).resCh <- err:
				default:
				}
			}
		}
	}()

	return <-p.reqsBufCh
}

type pipelinerCmd struct {
	CmdAction
	resCh chan error
}

var pipelinerCmdPool sync.Pool

func getPipelinerCmd(cmd CmdAction) *pipelinerCmd {
	req, _ := pipelinerCmdPool.Get().(*pipelinerCmd)
	if req != nil {
		req.CmdAction = cmd
		return req
	}
	return &pipelinerCmd{
		CmdAction: cmd,
		// using a buffer of 1 is faster than no buffer in most cases
		resCh: make(chan error, 1),
	}
}

func poolPipelinerCmd(req *pipelinerCmd) {
	req.CmdAction = nil
	pipelinerCmdPool.Put(req)
}

type pipelinerPipeline struct {
	pipeline
}

func (p pipelinerPipeline) Run(c Conn) error {
	if err := c.Encode(p); err != nil {
		return err
	}
	for _, req := range p.pipeline {
		err := c.Decode(req)
		if _, ok := err.(net.Error); ok {
			return err
		}
		req.(*pipelinerCmd).resCh <- err
	}
	return nil
}
<|endoftext|>


<commit_before>package pkgconfig

import (
	"bytes"
	"errors"
	"io"
	"os"
	"strings"
)

var errSkipGithub = errors.New("PKG_CONDIF_GITHUB not exported, skipping github.com lookup")

func lookupGithubIfEnv(pkg string) (*PC, error) {
	if os.Getenv("PKG_CONFIG_GITHUB") == "1" {
		return LookupGithub(pkg)
	}
	return nil, errSkipGithub
}

var lookups = map[string]func(string) (*PC, error){
	"$GOPATH":          LookupGopath,
	"github.com":       lookupGithubIfEnv,
	"$PKG_CONFIG_PATH": LookupPC,
	"<autogenerated>":  GenerateGopath,
}

type namedErrors map[string]error

func (ne namedErrors) Error() string {
	s := make([]string, 0, len(ne))
	for name, err := range ne {
		s = append(s, "error "+name+": "+err.Error())
	}
	return strings.Join(s, "\n")
}

// DefaultLookup TODO(rjeczalik): document
func DefaultLookup(pkg string) (pc *PC, err error) {
	ne := make(map[string]error, len(lookups))
	for name, lookup := range lookups {
		if pc, err = lookup(pkg); err == nil {
			return
		}
		ne[name] = err
	}
	return nil, namedErrors(ne)
}

// Pkg TODO(rjeczalik): document
type Pkg struct {
	Packages []string
	Libs     bool
	Cflags   bool
	Lookup   func(string) (*PC, error)
	pc       []*PC
}

// NewPkgArgs TODO(rjeczalik): document
func NewPkgArgs(args []string) *Pkg {
	pkg := &Pkg{}
	for _, arg := range args {
		switch {
		case arg == "--libs":
			pkg.Libs = true
		case arg == "--cflags":
			pkg.Cflags = true
		case strings.HasPrefix(arg, "-"):
		default:
			pkg.Packages = append(pkg.Packages, arg)
		}
	}
	return pkg
}

// Resolve TODO(rjeczalik): document
func (pkg *Pkg) Resolve() error {
	if len(pkg.Packages) == 0 {
		return ErrEmptyPC
	}
	lu := pkg.Lookup
	if lu == nil {
		lu = DefaultLookup
	}
	var (
		pc   = make([]*PC, 0, len(pkg.Packages))
		dups = make(map[string]struct{})
	)
	for _, p := range pkg.Packages {
		if _, ok := dups[p]; !ok {
			pkg, err := lu(p)
			if err != nil {
				return err
			}
			pc = append(pc, pkg)
			dups[p] = struct{}{}
		}
	}
	pkg.pc = pc
	return nil
}

// WriteTo TODO(rjeczalik): document
func (pkg Pkg) WriteTo(w io.Writer) (int64, error) {
	var (
		dups = make(map[string]struct{})
		buf  bytes.Buffer
	)
	if pkg.Cflags {
		for _, pc := range pkg.pc {
			for _, cflag := range pc.Cflags {
				if _, ok := dups[cflag]; !ok {
					buf.WriteString(cflag)
					buf.WriteByte(' ')
					dups[cflag] = struct{}{}
				}
			}
		}
	}
	if pkg.Libs {
		for _, pc := range pkg.pc {
			for _, lib := range pc.Libs {
				if _, ok := dups[lib]; !ok {
					buf.WriteString(lib)
					buf.WriteByte(' ')
					dups[lib] = struct{}{}
				}
			}
		}
	}
	if buf.Len() == 0 {
		return 0, ErrEmptyPC
	}
	p := buf.Bytes()
	p[len(p)-1] = '\n'
	return io.Copy(w, bytes.NewBuffer(p))
}
<commit_msg>Fix non-determinism when looking for config files<commit_after>package pkgconfig

import (
	"bytes"
	"errors"
	"io"
	"os"
	"strings"
)

var errSkipGithub = errors.New("PKG_CONDIF_GITHUB not exported, skipping github.com lookup")

func lookupGithubIfEnv(pkg string) (*PC, error) {
	if os.Getenv("PKG_CONFIG_GITHUB") == "1" {
		return LookupGithub(pkg)
	}
	return nil, errSkipGithub
}

type pathLookupPair struct {
	name string
	fn   func(string) (*PC, error)
}

var lookups = []pathLookupPair{
	{"$GOPATH", LookupGopath},
	{"github.com", lookupGithubIfEnv},
	{"$PKG_CONFIG_PATH", LookupPC},
	{"<autogenerated>", GenerateGopath},
}

type namedErrors map[string]error

func (ne namedErrors) Error() string {
	s := make([]string, 0, len(ne))
	for name, err := range ne {
		s = append(s, "error "+name+": "+err.Error())
	}
	return strings.Join(s, "\n")
}

// DefaultLookup TODO(rjeczalik): document
func DefaultLookup(pkg string) (pc *PC, err error) {
	ne := make(map[string]error, len(lookups))
	for _, lookup := range lookups {
		if pc, err = lookup.fn(pkg); err == nil {
			return
		}
		ne[lookup.name] = err
	}
	return nil, namedErrors(ne)
}

// Pkg TODO(rjeczalik): document
type Pkg struct {
	Packages []string
	Libs     bool
	Cflags   bool
	Lookup   func(string) (*PC, error)
	pc       []*PC
}

// NewPkgArgs TODO(rjeczalik): document
func NewPkgArgs(args []string) *Pkg {
	pkg := &Pkg{}
	for _, arg := range args {
		switch {
		case arg == "--libs":
			pkg.Libs = true
		case arg == "--cflags":
			pkg.Cflags = true
		case strings.HasPrefix(arg, "-"):
		default:
			pkg.Packages = append(pkg.Packages, arg)
		}
	}
	return pkg
}

// Resolve TODO(rjeczalik): document
func (pkg *Pkg) Resolve() error {
	if len(pkg.Packages) == 0 {
		return ErrEmptyPC
	}
	lu := pkg.Lookup
	if lu == nil {
		lu = DefaultLookup
	}
	var (
		pc   = make([]*PC, 0, len(pkg.Packages))
		dups = make(map[string]struct{})
	)
	for _, p := range pkg.Packages {
		if _, ok := dups[p]; !ok {
			pkg, err := lu(p)
			if err != nil {
				return err
			}
			pc = append(pc, pkg)
			dups[p] = struct{}{}
		}
	}
	pkg.pc = pc
	return nil
}

// WriteTo TODO(rjeczalik): document
func (pkg Pkg) WriteTo(w io.Writer) (int64, error) {
	var (
		dups = make(map[string]struct{})
		buf  bytes.Buffer
	)
	if pkg.Cflags {
		for _, pc := range pkg.pc {
			for _, cflag := range pc.Cflags {
				if _, ok := dups[cflag]; !ok {
					buf.WriteString(cflag)
					buf.WriteByte(' ')
					dups[cflag] = struct{}{}
				}
			}
		}
	}
	if pkg.Libs {
		for _, pc := range pkg.pc {
			for _, lib := range pc.Libs {
				if _, ok := dups[lib]; !ok {
					buf.WriteString(lib)
					buf.WriteByte(' ')
					dups[lib] = struct{}{}
				}
			}
		}
	}
	if buf.Len() == 0 {
		return 0, ErrEmptyPC
	}
	p := buf.Bytes()
	p[len(p)-1] = '\n'
	return io.Copy(w, bytes.NewBuffer(p))
}
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2019-11-26 15:02:16.601001 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "f3ec7c2aa739825e435ff85d852d559390d0cd0e"
<commit_msg>"Autogenerated build info"<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2019-11-27 14:43:17.51424 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "d1dfde001e0b4842c51220711a5d680ef0d2f207"
<|endoftext|>


<commit_before>[package plot

import (
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/plt"
	"image/color"
	"math"
	"sort"
)

var (
	DefaultLineStyle = plt.LineStyle{
		Width: vg.Points(0.75),
		Color: color.Black,
	}

	DefaultGlyphStyle = plt.GlyphStyle{
		Radius: vg.Points(2),
		Color:  color.Black,
	}
)

// An XYer wraps methods for getting a set of
// X and Y data values.
type XYer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// X returns an X value
	X(int) float64

	// Y returns a Y value
	Y(int) float64
}

// A Yer wraps methods for getting a set of Y data values.
type Yer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// Y returns a Y value
	Y(int) float64
}

// Line implements the plt.Data interface, drawing a line
// for the Plot method.
type Line struct {
	XYer
	plt.LineStyle
}

func (l Line) Plot(da plt.DrawArea, p *plt.Plot) {
	line := make([]plt.Point, l.Len())
	for i := range line {
		line[i].X = da.X(p.X.Norm(l.X(i)))
		line[i].Y = da.Y(p.Y.Norm(l.Y(i)))
	}
	da.StrokeLines(l.LineStyle, da.ClipLinesXY(line)...)
}

func (s Line) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// Scatter implements the Data interface, drawing
// glyphs at each of the given points.
type Scatter struct {
	XYer
	plt.GlyphStyle
}

func (s Scatter) Plot(da plt.DrawArea, p *plt.Plot) {
	for i := 0; i < s.Len(); i++ {
		x, y := da.X(p.X.Norm(s.X(i))), da.Y(p.Y.Norm(s.Y(i)))
		da.DrawGlyph(s.GlyphStyle, plt.Point{x, y})
	}
}

func (s Scatter) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	r := plt.Rect{
		plt.Point{-s.Radius, -s.Radius},
		plt.Point{s.Radius * 2, s.Radius * 2},
	}
	for i := 0; i < s.Len(); i++ {
		box := plt.GlyphBox{
			X:    p.X.Norm(s.X(i)),
			Y:    p.Y.Norm(s.Y(i)),
			Rect: r,
		}
		boxes = append(boxes, box)
	}
	return
}

func (s Scatter) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// xyData wraps an XYer with an Extents method.
type xyData struct {
	XYer
}

// xyExtents returns the minimum and maximum x
// and y values of all points from the XYer.
func xyExtents(xy XYer) (xmin, ymin, xmax, ymax float64) {
	xmin = math.Inf(1)
	ymin = xmin
	xmax = math.Inf(-1)
	ymax = xmax
	for i := 0; i < xy.Len(); i++ {
		x, y := xy.X(i), xy.Y(i)
		xmin = math.Min(xmin, x)
		xmax = math.Max(xmax, x)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

// Box implements the Data interface, drawing a boxplot.
type Box struct {
	Yer

	// X is the X value, in data coordinates, at which
	// to draw the box.
	X float64

	// Width is the width of the box.
	Width vg.Length

	// BoxStyle is the style used to draw the line
	// around the box, the median line.
	BoxStyle plt.LineStyle

	// WhiskerStyle is the style used to draw the
	// whiskers.
	WhiskerStyle plt.LineStyle

	// CapWidth is the width of the cap on the whiskers.
	CapWidth vg.Length

	// GlyphStyle is the style of the points.
	GlyphStyle plt.GlyphStyle

	// Med, Q1, and Q3 are the median, first, and third
	// quartiles respectively.
	Med, Q1, Q3 float64

	// Points is a slice containing the indices Y values
	// that should be drawn separately as points.
	Points []int
}

// MakeBox returns a Data which draws a box plot
// of the given y values at the given x value.
func MakeBox(w vg.Length, x float64, ys Yer) *Box {
	sorted := sortedIndices(ys)
	return &Box{
		Yer: ys,
		X: x,
		Width: w,
		BoxStyle: DefaultLineStyle,
		WhiskerStyle: DefaultLineStyle,
		CapWidth: w / 2,
		GlyphStyle: DefaultGlyphStyle,
		Med: median(ys, sorted),
		Q1: percentile(ys, sorted, 0.25),
		Q3: percentile(ys, sorted, 0.75),
		Points: tukeyPoints(ys, sortedIndices(ys)),
	}
}

func (b *Box) Plot(da plt.DrawArea, p *plt.Plot) {
	x := da.X(p.X.Norm(b.X))
	q1y := da.Y(p.Y.Norm(b.Q1))
	q3y := da.Y(p.Y.Norm(b.Q3))
	medy := da.Y(p.Y.Norm(b.Med))
	box := da.ClipLinesY([]plt.Point{
		{ x - b.Width/2, q1y }, { x - b.Width/2, q3y },
		{ x + b.Width/2, q3y }, { x + b.Width/2, q1y },
		{ x - b.Width/2 - b.BoxStyle.Width/2, q1y } },
		[]plt.Point{ { x - b.Width/2, medy }, { x + b.Width/2, medy } })
	da.StrokeLines(b.BoxStyle, box...)

	min, max := b.Q1, b.Q3
	if filtered := filteredIndices(b.Yer, b.Points); len(filtered) > 0 {
		min = b.Y(filtered[0])
		max = b.Y(filtered[len(filtered)-1])
	}
	miny := da.Y(p.Y.Norm(min))
	maxy := da.Y(p.Y.Norm(max))
	whisk := da.ClipLinesY([]plt.Point{{x, q3y}, {x, maxy} },
		[]plt.Point{ {x - b.CapWidth/2, maxy}, {x + b.CapWidth/2, maxy} },
		[]plt.Point{ {x, q1y}, {x, miny} },
		[]plt.Point{ {x - b.CapWidth/2, miny}, {x + b.CapWidth/2, miny} })
	da.StrokeLines(b.WhiskerStyle, whisk...)

	for _, i := range b.Points {
		da.DrawGlyph(b.GlyphStyle,  plt.Point{x, da.Y(p.Y.Norm(b.Y(i)))})
	}
}

func (b *Box) Extents() (xmin, ymin, xmax, ymax float64) {
	xmin = b.X
	ymin = xmin
	xmax = b.X
	ymax = xmax
	for i := 0; i < b.Len(); i++ {
		y := b.Y(i)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

func (b *Box) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	x := p.X.Norm(b.X)
	boxes = append(boxes, plt.GlyphBox {
		X: x,
		Y: p.Y.Norm(b.Med),
		plt.Rect: plt.Rect{
			Min: plt.Point{ X: -(b.Width/2 + b.BoxStyle.Width/2)},
			Size: plt.Point{ X: b.Width + b.BoxStyle.Width },
		},
	})

	r := b.GlyphStyle.Radius
	rect := plt.Rect{ plt.Point{-r, -r}, plt.Point{r*2, r*2} }
	for _, i := range b.Points {
		box := plt.GlyphBox{
			X:    x,
			Y:    p.Y.Norm(b.Y(i)),
			Rect: rect,
		}
		boxes = append(boxes, box)
	}
	return
}

// tukeyPoints returns values that are more than ½ of the
// inter-quartile range beyond the 1st and 3rd quartile.
// According to John Tukey, these values are reasonable
// to draw separately as points.
func tukeyPoints(ys Yer, sorted []int) (pts []int) {
	q1 := percentile(ys, sorted, 0.25)
	q3 := percentile(ys, sorted, 0.75)
	min := q1 - 1.5*(q3 - q1)
	max := q3 + 1.5*(q3 - q1)
	for _, i := range sorted {
		if y := ys.Y(i); y > max || y < min {
			pts = append(pts, i)
		}
	}
	return
}

// median returns the median Y value given a sorted
// slice of indices.
func median(ys Yer, sorted []int) float64 {
	med := ys.Y(sorted[len(sorted)/2])
	if len(sorted) % 2 == 0 {
		med += ys.Y(sorted[len(sorted)/2 - 1])
		med /= 2
	}
	return med
}

// percentile returns the given percentile.
// According to Wikipedia, this technique is
// an alternative technique recommended
// by National Institute of Standards and
// Technology (NIST), and is used by MS
// Excel 2007.
func percentile(ys Yer, sorted []int, p float64) float64 {
	n := p*float64(len(sorted)-1) + 1
	k := math.Floor(n)
	d := n - k
	if n <= 1 {
		return ys.Y(sorted[0])
	} else if n >= float64(len(sorted)) {
		return ys.Y(sorted[len(sorted)-1])
	}
	yk := ys.Y(sorted[int(k)])
	yk1 := ys.Y(sorted[int(k)-1])
	return yk1 + d * (yk - yk1)
}

// sortedIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value.
func sortedIndices(ys Yer) []int {
	data := make([]int, ys.Len())
	for i := range data {
		data[i] = i
	}
	sort.Sort(ySorter{ys, data})
	return data

}

// filteredIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value, and
// excluding all indices in outList.
func filteredIndices(ys Yer, outList []int) (data []int) {
	out := make([]bool, ys.Len())
	for _, o := range outList {
		out[o] = true
	}
	for i := 0; i < ys.Len(); i++ {
		if !out[i] {
			data = append(data, i)
		}
	}
	sort.Sort(ySorter{ys, data})
	return data
}

// ySorted implements sort.Interface, sorting a slice
// of indices for the given Yer.
type ySorter struct {
	Yer
	inds []int
}

func (y ySorter) Len() int {
	return len(y.inds)
}

func (y ySorter) Less(i, j int) bool {
	return y.Y(y.inds[i]) < y.Y(y.inds[j])
}

func (y ySorter) Swap(i, j int) {
	y.inds[i], y.inds[j] = y.inds[j], y.inds[i]
}

// Points is a slice of X, Y pairs, implementing the
// XYer interface.
type Points []struct{ X, Y float64 }

func (p Points) Len() int {
	return len(p)
}

func (p Points) X(i int) float64 {
	return p[i].X
}

func (p Points) Y(i int) float64 {
	return p[i].Y
}

// Values is a slice of values, implementing the Yer
// interface.
type Values []float64

func (v Values) Len() int {
	return len(v)
}

func (v Values) Y(i int) float64 {
	return v[i]
}
<commit_msg>Add some more comments.<commit_after>package plot

import (
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/plt"
	"image/color"
	"math"
	"sort"
)

var (
	// DefaultLineStyle is a reasonable default LineStyle
	// for drawing most lines in a plot.
	DefaultLineStyle = plt.LineStyle{
		Width: vg.Points(0.75),
		Color: color.Black,
	}

	// DefaultGlyhpStyle is a reasonable default GlyphStyle
	// for drawing points on a plot.
	DefaultGlyphStyle = plt.GlyphStyle{
		Radius: vg.Points(2),
		Color:  color.Black,
	}
)

// An XYer wraps methods for getting a set of
// X and Y data values.
type XYer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// X returns an X value
	X(int) float64

	// Y returns a Y value
	Y(int) float64
}

// A Yer wraps methods for getting a set of Y data values.
type Yer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// Y returns a Y value
	Y(int) float64
}

// Line implements the plt.Data interface, drawing a line
// for the Plot method.
type Line struct {
	XYer
	plt.LineStyle
}

// Plot implements the Plot method of the Data interface,
// drawing a line that connects each point in the Line.
func (l Line) Plot(da plt.DrawArea, p *plt.Plot) {
	line := make([]plt.Point, l.Len())
	for i := range line {
		line[i].X = da.X(p.X.Norm(l.X(i)))
		line[i].Y = da.Y(p.Y.Norm(l.Y(i)))
	}
	da.StrokeLines(l.LineStyle, da.ClipLinesXY(line)...)
}

// Extents implemnets the Extents function of the
// Data interface.
func (s Line) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// Scatter implements the Data interface, drawing
// glyphs at each of the given points.
type Scatter struct {
	XYer
	plt.GlyphStyle
}

// Plot implements the Plot method of the Data interface,
// drawing a glyph for each point in the Scatter.
func (s Scatter) Plot(da plt.DrawArea, p *plt.Plot) {
	for i := 0; i < s.Len(); i++ {
		x, y := da.X(p.X.Norm(s.X(i))), da.Y(p.Y.Norm(s.Y(i)))
		da.DrawGlyph(s.GlyphStyle, plt.Point{x, y})
	}
}

// GlyphBoxes returns a slice of GlyphBoxes, one for
// each of the glyphs in the Scatter.
func (s Scatter) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	r := plt.Rect{
		plt.Point{-s.Radius, -s.Radius},
		plt.Point{s.Radius * 2, s.Radius * 2},
	}
	for i := 0; i < s.Len(); i++ {
		box := plt.GlyphBox{
			X:    p.X.Norm(s.X(i)),
			Y:    p.Y.Norm(s.Y(i)),
			Rect: r,
		}
		boxes = append(boxes, box)
	}
	return
}

// Extents implemnets the Extents function of the
// Data interface.
func (s Scatter) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// xyData wraps an XYer with an Extents method.
type xyData struct {
	XYer
}

// xyExtents returns the minimum and maximum x
// and y values of all points from the XYer.
func xyExtents(xy XYer) (xmin, ymin, xmax, ymax float64) {
	xmin = math.Inf(1)
	ymin = xmin
	xmax = math.Inf(-1)
	ymax = xmax
	for i := 0; i < xy.Len(); i++ {
		x, y := xy.X(i), xy.Y(i)
		xmin = math.Min(xmin, x)
		xmax = math.Max(xmax, x)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

// Box implements the Data interface, drawing a boxplot.
type Box struct {
	Yer

	// X is the X value, in data coordinates, at which
	// to draw the box.
	X float64

	// Width is the width of the box.
	Width vg.Length

	// BoxStyle is the style used to draw the line
	// around the box, the median line.
	BoxStyle plt.LineStyle

	// WhiskerStyle is the style used to draw the
	// whiskers.
	WhiskerStyle plt.LineStyle

	// CapWidth is the width of the cap on the whiskers.
	CapWidth vg.Length

	// GlyphStyle is the style of the points.
	GlyphStyle plt.GlyphStyle

	// Med, Q1, and Q3 are the median, first, and third
	// quartiles respectively.
	Med, Q1, Q3 float64

	// Points is a slice containing the indices Y values
	// that should be drawn separately as points.
	Points []int
}

// MakeBox returns a Data which draws a box plot
// of the given y values at the given x value.
func MakeBox(w vg.Length, x float64, ys Yer) *Box {
	sorted := sortedIndices(ys)
	return &Box{
		Yer: ys,
		X: x,
		Width: w,
		BoxStyle: DefaultLineStyle,
		WhiskerStyle: DefaultLineStyle,
		CapWidth: w / 2,
		GlyphStyle: DefaultGlyphStyle,
		Med: median(ys, sorted),
		Q1: percentile(ys, sorted, 0.25),
		Q3: percentile(ys, sorted, 0.75),
		Points: tukeyPoints(ys, sortedIndices(ys)),
	}
}

// Plot implements the Plot function of the Data interface,
// drawing a boxplot.
func (b *Box) Plot(da plt.DrawArea, p *plt.Plot) {
	x := da.X(p.X.Norm(b.X))
	q1y := da.Y(p.Y.Norm(b.Q1))
	q3y := da.Y(p.Y.Norm(b.Q3))
	medy := da.Y(p.Y.Norm(b.Med))
	box := da.ClipLinesY([]plt.Point{
		{ x - b.Width/2, q1y }, { x - b.Width/2, q3y },
		{ x + b.Width/2, q3y }, { x + b.Width/2, q1y },
		{ x - b.Width/2 - b.BoxStyle.Width/2, q1y } },
		[]plt.Point{ { x - b.Width/2, medy }, { x + b.Width/2, medy } })
	da.StrokeLines(b.BoxStyle, box...)

	min, max := b.Q1, b.Q3
	if filtered := filteredIndices(b.Yer, b.Points); len(filtered) > 0 {
		min = b.Y(filtered[0])
		max = b.Y(filtered[len(filtered)-1])
	}
	miny := da.Y(p.Y.Norm(min))
	maxy := da.Y(p.Y.Norm(max))
	whisk := da.ClipLinesY([]plt.Point{{x, q3y}, {x, maxy} },
		[]plt.Point{ {x - b.CapWidth/2, maxy}, {x + b.CapWidth/2, maxy} },
		[]plt.Point{ {x, q1y}, {x, miny} },
		[]plt.Point{ {x - b.CapWidth/2, miny}, {x + b.CapWidth/2, miny} })
	da.StrokeLines(b.WhiskerStyle, whisk...)

	for _, i := range b.Points {
		da.DrawGlyph(b.GlyphStyle,  plt.Point{x, da.Y(p.Y.Norm(b.Y(i)))})
	}
}

// Extents implements the Extents function of the Data
// interface.
func (b *Box) Extents() (xmin, ymin, xmax, ymax float64) {
	xmin = b.X
	ymin = xmin
	xmax = b.X
	ymax = xmax
	for i := 0; i < b.Len(); i++ {
		y := b.Y(i)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

// GlyphBoxes returns a slice of GlyphBoxes for the
// points and for the median line of the boxplot.
func (b *Box) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	x := p.X.Norm(b.X)
	boxes = append(boxes, plt.GlyphBox {
		X: x,
		Y: p.Y.Norm(b.Med),
		plt.Rect: plt.Rect{
			Min: plt.Point{ X: -(b.Width/2 + b.BoxStyle.Width/2)},
			Size: plt.Point{ X: b.Width + b.BoxStyle.Width },
		},
	})

	r := b.GlyphStyle.Radius
	rect := plt.Rect{ plt.Point{-r, -r}, plt.Point{r*2, r*2} }
	for _, i := range b.Points {
		box := plt.GlyphBox{
			X:    x,
			Y:    p.Y.Norm(b.Y(i)),
			Rect: rect,
		}
		boxes = append(boxes, box)
	}
	return
}

// tukeyPoints returns values that are more than ½ of the
// inter-quartile range beyond the 1st and 3rd quartile.
// According to John Tukey, these values are reasonable
// to draw separately as points.
func tukeyPoints(ys Yer, sorted []int) (pts []int) {
	q1 := percentile(ys, sorted, 0.25)
	q3 := percentile(ys, sorted, 0.75)
	min := q1 - 1.5*(q3 - q1)
	max := q3 + 1.5*(q3 - q1)
	for _, i := range sorted {
		if y := ys.Y(i); y > max || y < min {
			pts = append(pts, i)
		}
	}
	return
}

// median returns the median Y value given a sorted
// slice of indices.
func median(ys Yer, sorted []int) float64 {
	med := ys.Y(sorted[len(sorted)/2])
	if len(sorted) % 2 == 0 {
		med += ys.Y(sorted[len(sorted)/2 - 1])
		med /= 2
	}
	return med
}

// percentile returns the given percentile.
// According to Wikipedia, this technique is
// an alternative technique recommended
// by National Institute of Standards and
// Technology (NIST), and is used by MS
// Excel 2007.
func percentile(ys Yer, sorted []int, p float64) float64 {
	n := p*float64(len(sorted)-1) + 1
	k := math.Floor(n)
	d := n - k
	if n <= 1 {
		return ys.Y(sorted[0])
	} else if n >= float64(len(sorted)) {
		return ys.Y(sorted[len(sorted)-1])
	}
	yk := ys.Y(sorted[int(k)])
	yk1 := ys.Y(sorted[int(k)-1])
	return yk1 + d * (yk - yk1)
}

// sortedIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value.
func sortedIndices(ys Yer) []int {
	data := make([]int, ys.Len())
	for i := range data {
		data[i] = i
	}
	sort.Sort(ySorter{ys, data})
	return data

}

// filteredIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value, and
// excluding all indices in outList.
func filteredIndices(ys Yer, outList []int) (data []int) {
	out := make([]bool, ys.Len())
	for _, o := range outList {
		out[o] = true
	}
	for i := 0; i < ys.Len(); i++ {
		if !out[i] {
			data = append(data, i)
		}
	}
	sort.Sort(ySorter{ys, data})
	return data
}

// ySorted implements sort.Interface, sorting a slice
// of indices for the given Yer.
type ySorter struct {
	Yer
	inds []int
}

// Len returns the number of indices.
func (y ySorter) Len() int {
	return len(y.inds)
}

// Less returns true if the Y value at index i
// is less than the Y value at index j.
func (y ySorter) Less(i, j int) bool {
	return y.Y(y.inds[i]) < y.Y(y.inds[j])
}

// Swap swaps the ith and jth indices.
func (y ySorter) Swap(i, j int) {
	y.inds[i], y.inds[j] = y.inds[j], y.inds[i]
}

// Points is a slice of X, Y pairs, implementing the
// XYer interface.
type Points []struct{ X, Y float64 }

// Len returns the number of points.
func (p Points) Len() int {
	return len(p)
}

// X returns the ith X value.
func (p Points) X(i int) float64 {
	return p[i].X
}

// Y returns the ith Y value.
func (p Points) Y(i int) float64 {
	return p[i].Y
}

// Values is a slice of values, implementing the Yer
// interface.
type Values []float64

// Len returns the number of values.
func (v Values) Len() int {
	return len(v)
}

// Y returns the ith Y value.
func (v Values) Y(i int) float64 {
	return v[i]
}<|endoftext|>


<commit_before>package plot

import (
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/plt"
	"image/color"
	"math"
	"sort"
)

var (
	DefaultLineStyle = plt.LineStyle{
		Width: vg.Points(0.75),
		Color: color.Black,
	}

	DefaultGlyphStyle = plt.GlyphStyle{
		Radius: vg.Points(2),
		Color:  color.Black,
	}
)

// An XYer wraps methods for getting a set of
// X and Y data values.
type XYer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// X returns an X value
	X(int) float64

	// Y returns a Y value
	Y(int) float64
}

// A Yer wraps methods for getting a set of Y data values.
type Yer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// Y returns a Y value
	Y(int) float64
}

// Line implements the plt.Data interface, drawing a line
// for the Plot method.
type Line struct {
	XYer
	plt.LineStyle
}

func (l Line) Plot(da plt.DrawArea, p *plt.Plot) {
	line := make([]plt.Point, l.Len())
	for i := range line {
		line[i].X = da.X(p.X.Norm(l.X(i)))
		line[i].Y = da.Y(p.Y.Norm(l.Y(i)))
	}
	da.StrokeLines(l.LineStyle, da.ClipLinesXY(line)...)
}

func (s Line) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// Scatter implements the Data interface, drawing
// glyphs at each of the given points.
type Scatter struct {
	XYer
	plt.GlyphStyle
}

func (s Scatter) Plot(da plt.DrawArea, p *plt.Plot) {
	for i := 0; i < s.Len(); i++ {
		x, y := da.X(p.X.Norm(s.X(i))), da.Y(p.Y.Norm(s.Y(i)))
		da.DrawGlyph(s.GlyphStyle, plt.Point{x, y})
	}
}

func (s Scatter) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	r := plt.Rect{
		plt.Point{-s.Radius, -s.Radius},
		plt.Point{s.Radius * 2, s.Radius * 2},
	}
	for i := 0; i < s.Len(); i++ {
		box := plt.GlyphBox{
			X:    p.X.Norm(s.X(i)),
			Y:    p.Y.Norm(s.Y(i)),
			Rect: r,
		}
		boxes = append(boxes, box)
	}
	return
}

func (s Scatter) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// xyData wraps an XYer with an Extents method.
type xyData struct {
	XYer
}

// xyExtents returns the minimum and maximum x
// and y values of all points from the XYer.
func xyExtents(xy XYer) (xmin, ymin, xmax, ymax float64) {
	xmin = math.Inf(1)
	ymin = xmin
	xmax = math.Inf(-1)
	ymax = xmax
	for i := 0; i < xy.Len(); i++ {
		x, y := xy.X(i), xy.Y(i)
		xmin = math.Min(xmin, x)
		xmax = math.Max(xmax, x)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

// Box implements the Data interface, drawing a boxplot.
type Box struct {
	Yer

	// X is the X value, in data coordinates, at which
	// to draw the box.
	X float64

	// Width is the width of the box.
	Width vg.Length

	// BoxStyle is the style used to draw the line
	// around the box, the median line.
	BoxStyle plt.LineStyle

	// WhiskerStyle is the style used to draw the
	// whiskers.
	WhiskerStyle plt.LineStyle

	// CapWidth is the width of the cap on the whiskers.
	CapWidth vg.Length

	// GlyphStyle is the style of the points.
	GlyphStyle plt.GlyphStyle

	// Med, Q1, and Q3 are the median, first, and third
	// quartiles respectively.
	Med, Q1, Q3 float64

	// Points is a slice containing the indices Y values
	// that should be drawn separately as points.
	Points []int
}

// MakeBox returns a Data which draws a box plot
// of the given y values at the given x value.
func MakeBox(w vg.Length, x float64, ys Yer) *Box {
	sorted := sortedIndices(ys)
	return &Box{
		Yer: ys,
		X: x,
		Width: w,
		BoxStyle: DefaultLineStyle,
		WhiskerStyle: DefaultLineStyle,
		CapWidth: w / 2,
		GlyphStyle: DefaultGlyphStyle,
		Med: median(ys, sorted),
		Q1: percentile(ys, sorted, 0.25),
		Q3: percentile(ys, sorted, 0.75),
		Points: tukeyPoints(ys, sortedIndices(ys)),
	}
}

func (b *Box) Plot(da plt.DrawArea, p *plt.Plot) {
	x := da.X(p.X.Norm(b.X))
	q1y := da.Y(p.Y.Norm(b.Q1))
	q3y := da.Y(p.Y.Norm(b.Q3))
	medy := da.Y(p.Y.Norm(b.Med))
	box := da.ClipLinesY([]plt.Point{
		{ x - b.Width/2, q1y }, { x - b.Width/2, q3y },
		{ x + b.Width/2, q3y }, { x + b.Width/2, q1y },
		{ x - b.Width/2 - b.BoxStyle.Width/2, q1y } },
		[]plt.Point{ { x - b.Width/2, medy }, { x + b.Width/2, medy } })
	da.StrokeLines(b.BoxStyle, box...)

	min, max := b.Q1, b.Q3
	if filtered := filteredIndices(b.Yer, b.Points); len(filtered) > 0 {
		min = b.Y(filtered[0])
		max = b.Y(filtered[len(filtered)-1])
	}
	miny := da.Y(p.Y.Norm(min))
	maxy := da.Y(p.Y.Norm(max))
	whisk := da.ClipLinesY([]plt.Point{{x, q3y}, {x, maxy} },
		[]plt.Point{ {x - b.CapWidth/2, maxy}, {x + b.CapWidth/2, maxy} },
		[]plt.Point{ {x, q1y}, {x, miny} },
		[]plt.Point{ {x - b.CapWidth/2, miny}, {x + b.CapWidth/2, miny} })
	da.StrokeLines(b.WhiskerStyle, whisk...)

	for _, i := range b.Points {
		da.DrawGlyph(b.GlyphStyle,  plt.Point{x, da.Y(p.Y.Norm(b.Y(i)))})
	}
}

func (b *Box) Extents() (xmin, ymin, xmax, ymax float64) {
	xmin = b.X
	ymin = xmin
	xmax = b.X
	ymax = xmax
	for i := 0; i < b.Len(); i++ {
		y := b.Y(i)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

func (b *Box) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	x := p.X.Norm(b.X)
	boxes = append(boxes, plt.GlyphBox {
		X: x,
		Y: p.Y.Norm(b.Med),
		plt.Rect: plt.Rect{
			Min: plt.Point{ X: -(b.Width/2 + b.BoxStyle.Width/2)},
			Size: plt.Point{ X: b.Width + b.BoxStyle.Width },
		},
	})

	r := b.GlyphStyle.Radius
	rect := plt.Rect{ plt.Point{-r, -r}, plt.Point{r*2, r*2} }
	for _, i := range b.Points {
		box := plt.GlyphBox{
			X:    x,
			Y:    p.Y.Norm(b.Y(i)),
			Rect: rect,
		}
		boxes = append(boxes, box)
	}
	return
}

// tukeyPoints returns values that are more than ½ of the
// inter-quartile range beyond the 1st and 3rd quartile.
// According to John Tukey, these values are reasonable
// to draw separately as points.
func tukeyPoints(ys Yer, sorted []int) (pts []int) {
	q1 := percentile(ys, sorted, 0.25)
	q3 := percentile(ys, sorted, 0.75)
	min := q1 - 1.5*(q3 - q1)
	max := q3 + 1.5*(q3 - q1)
	for _, i := range sorted {
		if y := ys.Y(i); y > max || y < min {
			pts = append(pts, i)
		}
	}
	return
}

// median returns the median
func median(ys Yer, sorted []int) float64 {
	med := ys.Y(sorted[len(sorted)/2])
	if len(sorted) % 2 == 0 {
		med += ys.Y(sorted[len(sorted)/2 - 1])
		med /= 2
	}
	return med
}

// percentile returns the given percentile.
// According to Wikipedia, this technique is
// an alternative technique recommended
// by National Institute of Standards and
// Technology (NIST), and is used by MS
// Excel 2007.
func percentile(ys Yer, sorted []int, p float64) float64 {
	n := p*float64(len(sorted)-1) + 1
	k := math.Floor(n)
	d := n - k
	if n <= 1 {
		return ys.Y(sorted[0])
	} else if n >= float64(len(sorted)) {
		return ys.Y(sorted[len(sorted)-1])
	}
	yk := ys.Y(sorted[int(k)])
	yk1 := ys.Y(sorted[int(k)-1])
	return yk1 + d * (yk - yk1)
}

// sortedIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value.
func sortedIndices(ys Yer) []int {
	data := make([]int, ys.Len())
	for i := range data {
		data[i] = i
	}
	sort.Sort(ySorter{ys, data})
	return data

}

// filteredIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value, and
// excluding all indices in outList.
func filteredIndices(ys Yer, outList []int) (data []int) {
	out := make([]bool, ys.Len())
	for _, o := range outList {
		out[o] = true
	}
	for i := 0; i < ys.Len(); i++ {
		if !out[i] {
			data = append(data, i)
		}
	}
	sort.Sort(ySorter{ys, data})
	return data
}

// ySorted implements sort.Interface, sorting a slice
// of indices for the given Yer.
type ySorter struct {
	Yer
	inds []int
}

func (y ySorter) Len() int {
	return len(y.inds)
}

func (y ySorter) Less(i, j int) bool {
	return y.Y(y.inds[i]) < y.Y(y.inds[j])
}

func (y ySorter) Swap(i, j int) {
	y.inds[i], y.inds[j] = y.inds[j], y.inds[i]
}

// Points is a slice of X, Y pairs, implementing the
// XYer interface.
type Points []struct{ X, Y float64 }

func (p Points) Len() int {
	return len(p)
}

func (p Points) X(i int) float64 {
	return p[i].X
}

func (p Points) Y(i int) float64 {
	return p[i].Y
}

// Values is a slice of values, implementing the Yer
// interface.
type Values []float64

func (v Values) Len() int {
	return len(v)
}

func (v Values) Y(i int) float64 {
	return v[i]
}
<commit_msg>Small comment fix.<commit_after>[package plot

import (
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/plt"
	"image/color"
	"math"
	"sort"
)

var (
	DefaultLineStyle = plt.LineStyle{
		Width: vg.Points(0.75),
		Color: color.Black,
	}

	DefaultGlyphStyle = plt.GlyphStyle{
		Radius: vg.Points(2),
		Color:  color.Black,
	}
)

// An XYer wraps methods for getting a set of
// X and Y data values.
type XYer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// X returns an X value
	X(int) float64

	// Y returns a Y value
	Y(int) float64
}

// A Yer wraps methods for getting a set of Y data values.
type Yer interface {
	// Len returns the number of X and Y values
	// that are available.
	Len() int

	// Y returns a Y value
	Y(int) float64
}

// Line implements the plt.Data interface, drawing a line
// for the Plot method.
type Line struct {
	XYer
	plt.LineStyle
}

func (l Line) Plot(da plt.DrawArea, p *plt.Plot) {
	line := make([]plt.Point, l.Len())
	for i := range line {
		line[i].X = da.X(p.X.Norm(l.X(i)))
		line[i].Y = da.Y(p.Y.Norm(l.Y(i)))
	}
	da.StrokeLines(l.LineStyle, da.ClipLinesXY(line)...)
}

func (s Line) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// Scatter implements the Data interface, drawing
// glyphs at each of the given points.
type Scatter struct {
	XYer
	plt.GlyphStyle
}

func (s Scatter) Plot(da plt.DrawArea, p *plt.Plot) {
	for i := 0; i < s.Len(); i++ {
		x, y := da.X(p.X.Norm(s.X(i))), da.Y(p.Y.Norm(s.Y(i)))
		da.DrawGlyph(s.GlyphStyle, plt.Point{x, y})
	}
}

func (s Scatter) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	r := plt.Rect{
		plt.Point{-s.Radius, -s.Radius},
		plt.Point{s.Radius * 2, s.Radius * 2},
	}
	for i := 0; i < s.Len(); i++ {
		box := plt.GlyphBox{
			X:    p.X.Norm(s.X(i)),
			Y:    p.Y.Norm(s.Y(i)),
			Rect: r,
		}
		boxes = append(boxes, box)
	}
	return
}

func (s Scatter) Extents() (xmin, ymin, xmax, ymax float64) {
	return xyExtents(s.XYer)
}

// xyData wraps an XYer with an Extents method.
type xyData struct {
	XYer
}

// xyExtents returns the minimum and maximum x
// and y values of all points from the XYer.
func xyExtents(xy XYer) (xmin, ymin, xmax, ymax float64) {
	xmin = math.Inf(1)
	ymin = xmin
	xmax = math.Inf(-1)
	ymax = xmax
	for i := 0; i < xy.Len(); i++ {
		x, y := xy.X(i), xy.Y(i)
		xmin = math.Min(xmin, x)
		xmax = math.Max(xmax, x)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

// Box implements the Data interface, drawing a boxplot.
type Box struct {
	Yer

	// X is the X value, in data coordinates, at which
	// to draw the box.
	X float64

	// Width is the width of the box.
	Width vg.Length

	// BoxStyle is the style used to draw the line
	// around the box, the median line.
	BoxStyle plt.LineStyle

	// WhiskerStyle is the style used to draw the
	// whiskers.
	WhiskerStyle plt.LineStyle

	// CapWidth is the width of the cap on the whiskers.
	CapWidth vg.Length

	// GlyphStyle is the style of the points.
	GlyphStyle plt.GlyphStyle

	// Med, Q1, and Q3 are the median, first, and third
	// quartiles respectively.
	Med, Q1, Q3 float64

	// Points is a slice containing the indices Y values
	// that should be drawn separately as points.
	Points []int
}

// MakeBox returns a Data which draws a box plot
// of the given y values at the given x value.
func MakeBox(w vg.Length, x float64, ys Yer) *Box {
	sorted := sortedIndices(ys)
	return &Box{
		Yer: ys,
		X: x,
		Width: w,
		BoxStyle: DefaultLineStyle,
		WhiskerStyle: DefaultLineStyle,
		CapWidth: w / 2,
		GlyphStyle: DefaultGlyphStyle,
		Med: median(ys, sorted),
		Q1: percentile(ys, sorted, 0.25),
		Q3: percentile(ys, sorted, 0.75),
		Points: tukeyPoints(ys, sortedIndices(ys)),
	}
}

func (b *Box) Plot(da plt.DrawArea, p *plt.Plot) {
	x := da.X(p.X.Norm(b.X))
	q1y := da.Y(p.Y.Norm(b.Q1))
	q3y := da.Y(p.Y.Norm(b.Q3))
	medy := da.Y(p.Y.Norm(b.Med))
	box := da.ClipLinesY([]plt.Point{
		{ x - b.Width/2, q1y }, { x - b.Width/2, q3y },
		{ x + b.Width/2, q3y }, { x + b.Width/2, q1y },
		{ x - b.Width/2 - b.BoxStyle.Width/2, q1y } },
		[]plt.Point{ { x - b.Width/2, medy }, { x + b.Width/2, medy } })
	da.StrokeLines(b.BoxStyle, box...)

	min, max := b.Q1, b.Q3
	if filtered := filteredIndices(b.Yer, b.Points); len(filtered) > 0 {
		min = b.Y(filtered[0])
		max = b.Y(filtered[len(filtered)-1])
	}
	miny := da.Y(p.Y.Norm(min))
	maxy := da.Y(p.Y.Norm(max))
	whisk := da.ClipLinesY([]plt.Point{{x, q3y}, {x, maxy} },
		[]plt.Point{ {x - b.CapWidth/2, maxy}, {x + b.CapWidth/2, maxy} },
		[]plt.Point{ {x, q1y}, {x, miny} },
		[]plt.Point{ {x - b.CapWidth/2, miny}, {x + b.CapWidth/2, miny} })
	da.StrokeLines(b.WhiskerStyle, whisk...)

	for _, i := range b.Points {
		da.DrawGlyph(b.GlyphStyle,  plt.Point{x, da.Y(p.Y.Norm(b.Y(i)))})
	}
}

func (b *Box) Extents() (xmin, ymin, xmax, ymax float64) {
	xmin = b.X
	ymin = xmin
	xmax = b.X
	ymax = xmax
	for i := 0; i < b.Len(); i++ {
		y := b.Y(i)
		ymin = math.Min(ymin, y)
		ymax = math.Max(ymax, y)
	}
	return
}

func (b *Box) GlyphBoxes(p *plt.Plot) (boxes []plt.GlyphBox) {
	x := p.X.Norm(b.X)
	boxes = append(boxes, plt.GlyphBox {
		X: x,
		Y: p.Y.Norm(b.Med),
		plt.Rect: plt.Rect{
			Min: plt.Point{ X: -(b.Width/2 + b.BoxStyle.Width/2)},
			Size: plt.Point{ X: b.Width + b.BoxStyle.Width },
		},
	})

	r := b.GlyphStyle.Radius
	rect := plt.Rect{ plt.Point{-r, -r}, plt.Point{r*2, r*2} }
	for _, i := range b.Points {
		box := plt.GlyphBox{
			X:    x,
			Y:    p.Y.Norm(b.Y(i)),
			Rect: rect,
		}
		boxes = append(boxes, box)
	}
	return
}

// tukeyPoints returns values that are more than ½ of the
// inter-quartile range beyond the 1st and 3rd quartile.
// According to John Tukey, these values are reasonable
// to draw separately as points.
func tukeyPoints(ys Yer, sorted []int) (pts []int) {
	q1 := percentile(ys, sorted, 0.25)
	q3 := percentile(ys, sorted, 0.75)
	min := q1 - 1.5*(q3 - q1)
	max := q3 + 1.5*(q3 - q1)
	for _, i := range sorted {
		if y := ys.Y(i); y > max || y < min {
			pts = append(pts, i)
		}
	}
	return
}

// median returns the median Y value given a sorted
// slice of indices.
func median(ys Yer, sorted []int) float64 {
	med := ys.Y(sorted[len(sorted)/2])
	if len(sorted) % 2 == 0 {
		med += ys.Y(sorted[len(sorted)/2 - 1])
		med /= 2
	}
	return med
}

// percentile returns the given percentile.
// According to Wikipedia, this technique is
// an alternative technique recommended
// by National Institute of Standards and
// Technology (NIST), and is used by MS
// Excel 2007.
func percentile(ys Yer, sorted []int, p float64) float64 {
	n := p*float64(len(sorted)-1) + 1
	k := math.Floor(n)
	d := n - k
	if n <= 1 {
		return ys.Y(sorted[0])
	} else if n >= float64(len(sorted)) {
		return ys.Y(sorted[len(sorted)-1])
	}
	yk := ys.Y(sorted[int(k)])
	yk1 := ys.Y(sorted[int(k)-1])
	return yk1 + d * (yk - yk1)
}

// sortedIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value.
func sortedIndices(ys Yer) []int {
	data := make([]int, ys.Len())
	for i := range data {
		data[i] = i
	}
	sort.Sort(ySorter{ys, data})
	return data

}

// filteredIndices returns a slice of the indices sorted in
// ascending order of their corresponding Y value, and
// excluding all indices in outList.
func filteredIndices(ys Yer, outList []int) (data []int) {
	out := make([]bool, ys.Len())
	for _, o := range outList {
		out[o] = true
	}
	for i := 0; i < ys.Len(); i++ {
		if !out[i] {
			data = append(data, i)
		}
	}
	sort.Sort(ySorter{ys, data})
	return data
}

// ySorted implements sort.Interface, sorting a slice
// of indices for the given Yer.
type ySorter struct {
	Yer
	inds []int
}

func (y ySorter) Len() int {
	return len(y.inds)
}

func (y ySorter) Less(i, j int) bool {
	return y.Y(y.inds[i]) < y.Y(y.inds[j])
}

func (y ySorter) Swap(i, j int) {
	y.inds[i], y.inds[j] = y.inds[j], y.inds[i]
}

// Points is a slice of X, Y pairs, implementing the
// XYer interface.
type Points []struct{ X, Y float64 }

func (p Points) Len() int {
	return len(p)
}

func (p Points) X(i int) float64 {
	return p[i].X
}

func (p Points) Y(i int) float64 {
	return p[i].Y
}

// Values is a slice of values, implementing the Yer
// interface.
type Values []float64

func (v Values) Len() int {
	return len(v)
}

func (v Values) Y(i int) float64 {
	return v[i]
}
<|endoftext|>


<commit_before>package core_io

// TODO rename package to something that doesn't conflict with io/ioutil.
// Pretty names are hard to find.
//
// Candidates:
//
// go-ipfs/core/unix
// go-ipfs/core/io
// go-ipfs/core/ioutil
// go-ipfs/core/coreio
// go-ipfs/core/coreunix

import (
	"io"

	core "github.com/jbenet/go-ipfs/core"
	importer "github.com/jbenet/go-ipfs/importer"
	chunk "github.com/jbenet/go-ipfs/importer/chunk"
	u "github.com/jbenet/go-ipfs/util"
)

func Add(n *core.IpfsNode, r io.Reader) (u.Key, error) {
	// TODO more attractive function signature importer.BuildDagFromReader
	dagNode, err := importer.BuildDagFromReader(
		r,
		n.DAG,
		nil,
		chunk.DefaultSplitter,
	)
	if err != nil {
		return "", err
	}
	return dagNode.Key()
}
<commit_msg>fix(core_io/Add): by default, use pinner<commit_after>package core_io

// TODO rename package to something that doesn't conflict with io/ioutil.
// Pretty names are hard to find.
//
// Candidates:
//
// go-ipfs/core/unix
// go-ipfs/core/io
// go-ipfs/core/ioutil
// go-ipfs/core/coreio
// go-ipfs/core/coreunix

import (
	"io"

	core "github.com/jbenet/go-ipfs/core"
	importer "github.com/jbenet/go-ipfs/importer"
	chunk "github.com/jbenet/go-ipfs/importer/chunk"
	u "github.com/jbenet/go-ipfs/util"
)

func Add(n *core.IpfsNode, r io.Reader) (u.Key, error) {
	// TODO more attractive function signature importer.BuildDagFromReader
	dagNode, err := importer.BuildDagFromReader(
		r,
		n.DAG,
		n.Pinning.GetManual(), // Fix this interface
		chunk.DefaultSplitter,
	)
	if err != nil {
		return "", err
	}
	return dagNode.Key()
}
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2021-01-17 06:10:17.316481 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "46d61f90cacc76d093205e56d8f758250bd1a657"
<commit_msg>"Autogenerated build info"<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2021-01-17 06:59:25.122464 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "9114f55327d0bbcddbffce49b2a1c5e1f6ba341a"
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2021-11-12 07:00:41.767803 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "882652d00dd8f0ea77b47a5009e816472ca130e7"

// SpartaGitShortHash is the short version of SpartaGitHash
const SpartaGitShortHash = "882652d"
<commit_msg>"Autogenerated build info"<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2021-11-13 04:01:23.651616 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "a24eb45ed2c92ea20d280a1eda3bfff3a5d4c696"

// SpartaGitShortHash is the short version of SpartaGitHash
const SpartaGitShortHash = "a24eb45"
<|endoftext|>


<commit_before>package core
import  "strings"
//import "encoding/json"

/*questa funzione controlla se immagine appartiene a tvl o no */
func IsOfSite(url string) int {
    if strings.Contains(url, "tvl.lotrek.it") {
        return 1
    } else {
        return 0
    }
}

/* questa funzione spezzetta il parametro in url passato */
func Parser (name string) ([]string) {

    /*dichiaro un array di ritorno con tre parametri*/
    arr := make([]string, 3)
    /*ci separiamo la stringa passata per il carattere */
    stringSlice := strings.Split(name, "/")
    /*ora in posizoione 0 della stringslide, avremo dimensione e qualita*/
    var dimqual = stringSlice[0]
    /* se togliamo dalla stringa originale con un replace il dimqual, ecco che abbiamo la urla*/
    var url = strings.Replace(name, dimqual+"/", "", -1)

    /*prima di tutto, l'immagine appartiene a tvl ?  */
    var is=IsOfSite(url)
    if is != 0 {

        /* se dimqual ha il parametro in più , tipo "_" si deve comportare in maniera diversa rispetto a non averlo */
        if strings.Contains(dimqual, "_") {
            stringSlice2 := strings.Split(dimqual, "_")
            var  dim = stringSlice2[0]
            var qual = stringSlice2[1]
            arr[0] = dim
            arr[1] = qual
        } else {
            arr[0] = dimqual
            arr[1] = ""
        }
        arr[2] = url

    } else {
        arr[0] =""
        arr[1] =""
        arr[2] =""
    }

    return arr
}
<commit_msg>Redefine parameters<commit_after>package core
import  "strings"
//import "encoding/json"

/*questa funzione controlla se immagine appartiene a tvl o no */
func IsOfSite(url string) int {
    if strings.Contains(url, "tvl.lotrek.it") {
        return 1
    } else {
        return 0
    }
}

/* questa funzione spezzetta il parametro in url passato */

func Parser (name string) ([]string) { //return integer, integer , integer, error

    /*dichiaro un array di ritorno con tre parametri*/
    arr := make([]string, 3)
    /*ci separiamo la stringa passata per il carattere */
    stringSlice := strings.Split(name, "/")
    /*ora in posizoione 0 della stringslide, avremo dimensione e qualita*/
    var dimqual = stringSlice[0]
    /* se togliamo dalla stringa originale con un replace il dimqual, ecco che abbiamo la urla*/
    var url = strings.Replace(name, dimqual+"/", "", -1)

    /*prima di tutto, l'immagine appartiene a tvl ?  */
    var is=IsOfSite(url)
    if is != 0 {

        /* se dimqual ha il parametro in più , tipo "_" si deve comportare in maniera diversa rispetto a non averlo */
        if strings.Contains(dimqual, "_") {
            stringSlice2 := strings.Split(dimqual, "_")
            var  dim = stringSlice2[0]
            var qual = stringSlice2[1]
            arr[0] = dim
            arr[1] = qual
        } else {
            arr[0] = dimqual
            arr[1] = ""
        }
        arr[2] = url

    } else {
        arr[0] =""
        arr[1] =""
        arr[2] =""
    }

    return arr
}
<|endoftext|>


<commit_before>package logmon

import (
	"bytes"
	"crypto/rand"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/hashicorp/nomad/client/lib/fifo"
	"github.com/hashicorp/nomad/helper/testlog"
	"github.com/stretchr/testify/require"
)

func TestLogmon_Start_rotate(t *testing.T) {
	require := require.New(t)
	dir, err := ioutil.TempDir("", "nomadtest")
	require.NoError(err)
	defer os.RemoveAll(dir)
	stdoutLog := "stdout"
	stdoutFifoPath := filepath.Join(dir, "stdout.fifo")
	stderrLog := "stderr"
	stderrFifoPath := filepath.Join(dir, "stderr.fifo")

	cfg := &LogConfig{
		LogDir:        dir,
		StdoutLogFile: stdoutLog,
		StdoutFifo:    stdoutFifoPath,
		StderrLogFile: stderrLog,
		StderrFifo:    stderrFifoPath,
		MaxFiles:      2,
		MaxFileSizeMB: 1,
	}

	lm := NewLogMon(testlog.HCLogger(t))
	require.NoError(lm.Start(cfg))

	stdout, err := fifo.Open(stdoutFifoPath)
	require.NoError(err)

	// Write enough bytes such that the log is rotated
	bytes1MB := make([]byte, 1024*1024)
	_, err = rand.Read(bytes1MB)
	require.NoError(err)

	io.Copy(stdout, bytes.NewBuffer(bytes1MB))

	time.Sleep(200 * time.Millisecond)
	_, err = os.Stat(filepath.Join(dir, "stdout.0"))
	require.NoError(err)
	_, err = os.Stat(filepath.Join(dir, "stdout.1"))
	require.NoError(err)

	require.NoError(lm.Stop())
}

func TestLogmon_Start_restart(t *testing.T) {
	require := require.New(t)
	dir, err := ioutil.TempDir("", "nomadtest")
	require.NoError(err)
	defer os.RemoveAll(dir)
	stdoutLog := "stdout"
	stdoutFifoPath := filepath.Join(dir, "stdout.fifo")
	stderrLog := "stderr"
	stderrFifoPath := filepath.Join(dir, "stderr.fifo")

	cfg := &LogConfig{
		LogDir:        dir,
		StdoutLogFile: stdoutLog,
		StdoutFifo:    stdoutFifoPath,
		StderrLogFile: stderrLog,
		StderrFifo:    stderrFifoPath,
		MaxFiles:      2,
		MaxFileSizeMB: 1,
	}

	lm := NewLogMon(testlog.HCLogger(t))
	impl, ok := lm.(*logmonImpl)
	require.True(ok)
	require.NoError(lm.Start(cfg))

	stdout, err := fifo.Open(stdoutFifoPath)
	require.NoError(err)
	stderr, err := fifo.Open(stderrFifoPath)
	require.NoError(err)

	// Write a string and assert it was written to the file
	io.Copy(stdout, bytes.NewBufferString("test\n"))
	time.Sleep(200 * time.Millisecond)
	raw, err := ioutil.ReadFile(filepath.Join(dir, "stdout.0"))
	require.NoError(err)
	require.Equal("test\n", string(raw))
	require.True(impl.tl.IsRunning())

	// Close stdout and assert that logmon no longer writes to the file
	require.NoError(stdout.Close())
	require.NoError(stderr.Close())

	stdout, err = fifo.Open(stdoutFifoPath)
	require.NoError(err)
	stderr, err = fifo.Open(stderrFifoPath)
	require.NoError(err)
	require.False(impl.tl.IsRunning())
	io.Copy(stdout, bytes.NewBufferString("te"))
	time.Sleep(200 * time.Millisecond)
	raw, err = ioutil.ReadFile(filepath.Join(dir, "stdout.0"))
	require.NoError(err)
	require.Equal("test\n", string(raw))

	// Start logmon again and assert that it appended to the file
	require.NoError(lm.Start(cfg))
	io.Copy(stdout, bytes.NewBufferString("st\n"))
	time.Sleep(200 * time.Millisecond)
	raw, err = ioutil.ReadFile(filepath.Join(dir, "stdout.0"))
	require.NoError(err)
	require.Equal("test\ntest\n", string(raw))
}
<commit_msg>logmon: remove sleeps from tests<commit_after>package logmon

import (
	"crypto/rand"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/hashicorp/nomad/client/lib/fifo"
	"github.com/hashicorp/nomad/helper/testlog"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"
)

func TestLogmon_Start_rotate(t *testing.T) {
	require := require.New(t)
	dir, err := ioutil.TempDir("", "nomadtest")
	require.NoError(err)
	defer os.RemoveAll(dir)
	stdoutLog := "stdout"
	stdoutFifoPath := filepath.Join(dir, "stdout.fifo")
	stderrLog := "stderr"
	stderrFifoPath := filepath.Join(dir, "stderr.fifo")

	cfg := &LogConfig{
		LogDir:        dir,
		StdoutLogFile: stdoutLog,
		StdoutFifo:    stdoutFifoPath,
		StderrLogFile: stderrLog,
		StderrFifo:    stderrFifoPath,
		MaxFiles:      2,
		MaxFileSizeMB: 1,
	}

	lm := NewLogMon(testlog.HCLogger(t))
	require.NoError(lm.Start(cfg))

	stdout, err := fifo.Open(stdoutFifoPath)
	require.NoError(err)

	// Write enough bytes such that the log is rotated
	bytes1MB := make([]byte, 1024*1024)
	_, err = rand.Read(bytes1MB)
	require.NoError(err)

	_, err = stdout.Write(bytes1MB)
	require.NoError(err)

	testutil.WaitForResult(func() (bool, error) {
		_, err = os.Stat(filepath.Join(dir, "stdout.0"))
		return err == nil, err
	}, func(err error) {
		require.NoError(err)
	})
	testutil.WaitForResult(func() (bool, error) {
		_, err = os.Stat(filepath.Join(dir, "stdout.1"))
		return err == nil, err
	}, func(err error) {
		require.NoError(err)
	})
	_, err = os.Stat(filepath.Join(dir, "stdout.2"))
	require.Error(err)
	require.NoError(lm.Stop())
	require.NoError(lm.Stop())
}

// asserts that calling Start twice restarts the log rotator
func TestLogmon_Start_restart(t *testing.T) {
	require := require.New(t)
	dir, err := ioutil.TempDir("", "nomadtest")
	require.NoError(err)
	defer os.RemoveAll(dir)
	stdoutLog := "stdout"
	stdoutFifoPath := filepath.Join(dir, "stdout.fifo")
	stderrLog := "stderr"
	stderrFifoPath := filepath.Join(dir, "stderr.fifo")

	cfg := &LogConfig{
		LogDir:        dir,
		StdoutLogFile: stdoutLog,
		StdoutFifo:    stdoutFifoPath,
		StderrLogFile: stderrLog,
		StderrFifo:    stderrFifoPath,
		MaxFiles:      2,
		MaxFileSizeMB: 1,
	}

	lm := NewLogMon(testlog.HCLogger(t))
	impl, ok := lm.(*logmonImpl)
	require.True(ok)
	require.NoError(lm.Start(cfg))

	stdout, err := fifo.Open(stdoutFifoPath)
	require.NoError(err)
	stderr, err := fifo.Open(stderrFifoPath)
	require.NoError(err)

	// Write a string and assert it was written to the file
	_, err = stdout.Write([]byte("test\n"))
	require.NoError(err)

	testutil.WaitForResult(func() (bool, error) {
		raw, err := ioutil.ReadFile(filepath.Join(dir, "stdout.0"))
		if err != nil {
			return false, err
		}
		return "test\n" == string(raw), fmt.Errorf("unexpected stdout %q", string(raw))
	}, func(err error) {
		require.NoError(err)
	})
	require.True(impl.tl.IsRunning())

	// Close stdout and assert that logmon no longer writes to the file
	require.NoError(stdout.Close())
	require.NoError(stderr.Close())

	stdout, err = fifo.Open(stdoutFifoPath)
	require.NoError(err)
	stderr, err = fifo.Open(stderrFifoPath)
	require.NoError(err)
	require.False(impl.tl.IsRunning())
	_, err = stdout.Write([]byte("te"))
	require.NoError(err)
	testutil.WaitForResult(func() (bool, error) {
		raw, err := ioutil.ReadFile(filepath.Join(dir, "stdout.0"))
		if err != nil {
			return false, err
		}
		return "test\n" == string(raw), fmt.Errorf("unexpected stdout %q", string(raw))
	}, func(err error) {
		require.NoError(err)
	})

	// Start logmon again and assert that it appended to the file
	require.NoError(lm.Start(cfg))
	_, err = stdout.Write([]byte("st\n"))
	require.NoError(err)
	testutil.WaitForResult(func() (bool, error) {
		raw, err := ioutil.ReadFile(filepath.Join(dir, "stdout.0"))
		if err != nil {
			return false, err
		}
		return "test\ntest\n" == string(raw), fmt.Errorf("unexpected stdout %q", string(raw))
	}, func(err error) {
		require.NoError(err)
	})
}
<|endoftext|>


<commit_before>package driver

import (
	"encoding/json"
)

// Job workload.
type Job struct {
	ID int64 `json:"job_id"`
	// The job name, this is unique.
	Name string `json:"name"`
	// The job function reffer on worker function
	Func string `json:"func"`
	// Job args
	Args string `json:"workload"`
	// Job processing timeout
	Timeout int64 `json:"timeout"`
	// When to sched the job.
	SchedAt int64 `json:"sched_at"`
	// The job is start at
	RunAt  int64  `json:"run_at"`
	Status string `json:"status"`
}

// IsReady check job status ready
func (job Job) IsReady() bool {
	return job.Status == "ready"
}

// IsProc check job status processing
func (job Job) IsProc() bool {
	return job.Status == "processing"
}

// SetReady set job status ready
func (job *Job) SetReady() {
	job.Status = "ready"
}

// SetProc set job status processing
func (job *Job) SetProc() {
	job.Status = "processing"
}

// NewJob create a job from json bytes
func NewJob(payload []byte) (job Job, err error) {
	err = json.Unmarshal(payload, &job)
	return
}

// Bytes encode job to json bytes
func (job Job) Bytes() (data []byte) {
	data, _ = json.Marshal(job)
	return
}
<commit_msg>update job comment<commit_after>package driver

import (
	"encoding/json"
)

// Job workload.
type Job struct {
	ID      int64  `json:"job_id"`
	Name    string `json:"name"`     // The job name, this is unique.
	Func    string `json:"func"`     // The job function reffer on worker function
	Args    string `json:"workload"` // Job args
	Timeout int64  `json:"timeout"`  // Job processing timeout
	SchedAt int64  `json:"sched_at"` // When to sched the job.
	RunAt   int64  `json:"run_at"`   // The job is start at
	Status  string `json:"status"`
}

// IsReady check job status ready
func (job Job) IsReady() bool {
	return job.Status == "ready"
}

// IsProc check job status processing
func (job Job) IsProc() bool {
	return job.Status == "processing"
}

// SetReady set job status ready
func (job *Job) SetReady() {
	job.Status = "ready"
}

// SetProc set job status processing
func (job *Job) SetProc() {
	job.Status = "processing"
}

// NewJob create a job from json bytes
func NewJob(payload []byte) (job Job, err error) {
	err = json.Unmarshal(payload, &job)
	return
}

// Bytes encode job to json bytes
func (job Job) Bytes() (data []byte) {
	data, _ = json.Marshal(job)
	return
}
<|endoftext|>