<commit_before>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"errors"
	"os"
	"strings"
)

func query(filename, query string, bufSize int) (res []string, err error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.WriteString(query)
	if err != nil {
		return
	}
	_, err = file.Seek(0, 0)
	if err != nil {
		return
	}
	buf := make([]byte, bufSize)
	for {
		n, _ := file.Read(buf)
		if n <= 0 {
			break
		}
		res = append(res, string(buf[:n]))
	}
	return
}

func queryCS(net, host, service string) (res []string, err error) {
	switch net {
	case "tcp4", "tcp6":
		net = "tcp"
	case "udp4", "udp6":
		net = "udp"
	}
	if host == "" {
		host = "*"
	}
	return query("/net/cs", net+"!"+host+"!"+service, 128)
}

func queryCS1(net string, ip IP, port int) (clone, dest string, err error) {
	ips := "*"
	if len(ip) != 0 && !ip.IsUnspecified() {
		ips = ip.String()
	}
	lines, err := queryCS(net, ips, itoa(port))
	if err != nil {
		return
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return "", "", errors.New("net: bad response from ndb/cs")
	}
	clone, dest = f[0], f[1]
	return
}

func queryDNS(addr string, typ string) (res []string, err error) {
	return query("/net/dns", addr+" "+typ, 1024)
}

// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(name string) (proto int, err error) {
	lines, err := query("/net/cs", "!protocol="+strings.ToLower(name), 128)
	if err != nil {
		return 0, err
	}
	unknownProtoError := errors.New("unknown IP protocol specified: " + name)
	if len(lines) == 0 {
		return 0, unknownProtoError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownProtoError
	}
	s := f[1]
	if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
		return n, nil
	}
	return 0, unknownProtoError
}

func lookupHost(host string) (addrs []string, err error) {
	// Use /net/cs instead of /net/dns because cs knows about
	// host names in local network (e.g. from /lib/ndb/local)
	lines, err := queryCS("net", host, "1")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		addr := f[1]
		if i := byteIndex(addr, '!'); i >= 0 {
			addr = addr[:i] // remove port
		}
		if ParseIP(addr) == nil {
			continue
		}
		addrs = append(addrs, addr)
	}
	return
}

func lookupIP(host string) (ips []IP, err error) {
	addrs, err := LookupHost(host)
	if err != nil {
		return
	}
	for _, addr := range addrs {
		if ip := ParseIP(addr); ip != nil {
			ips = append(ips, ip)
		}
	}
	return
}

func lookupPort(network, service string) (port int, err error) {
	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}
	lines, err := queryCS(network, "127.0.0.1", service)
	if err != nil {
		return
	}
	unknownPortError := &AddrError{"unknown port", network + "/" + service}
	if len(lines) == 0 {
		return 0, unknownPortError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownPortError
	}
	s := f[1]
	if i := byteIndex(s, '!'); i >= 0 {
		s = s[i+1:] // remove address
	}
	if n, _, ok := dtoi(s, 0); ok {
		return n, nil
	}
	return 0, unknownPortError
}

func lookupCNAME(name string) (cname string, err error) {
	lines, err := queryDNS(name, "cname")
	if err != nil {
		return
	}
	if len(lines) > 0 {
		if f := getFields(lines[0]); len(f) >= 3 {
			return f[2] + ".", nil
		}
	}
	return "", errors.New("net: bad response from ndb/dns")
}

func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
	var target string
	if service == "" && proto == "" {
		target = name
	} else {
		target = "_" + service + "._" + proto + "." + name
	}
	lines, err := queryDNS(target, "srv")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 6 {
			continue
		}
		port, _, portOk := dtoi(f[4], 0)
		priority, _, priorityOk := dtoi(f[3], 0)
		weight, _, weightOk := dtoi(f[2], 0)
		if !(portOk && priorityOk && weightOk) {
			continue
		}
		addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)})
		cname = f[0]
	}
	byPriorityWeight(addrs).sort()
	return
}

func lookupMX(name string) (mx []*MX, err error) {
	lines, err := queryDNS(name, "mx")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 4 {
			continue
		}
		if pref, _, ok := dtoi(f[2], 0); ok {
			mx = append(mx, &MX{f[3], uint16(pref)})
		}
	}
	byPref(mx).sort()
	return
}

func lookupNS(name string) (ns []*NS, err error) {
	lines, err := queryDNS(name, "ns")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		ns = append(ns, &NS{f[2]})
	}
	return
}

func lookupTXT(name string) (txt []string, err error) {
	lines, err := queryDNS(name, "txt")
	if err != nil {
		return
	}
	for _, line := range lines {
		if i := byteIndex(line, '\t'); i >= 0 {
			txt = append(txt, line[i+1:])
		}
	}
	return
}

func lookupAddr(addr string) (name []string, err error) {
	arpa, err := reverseaddr(addr)
	if err != nil {
		return
	}
	lines, err := queryDNS(arpa, "ptr")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		name = append(name, f[2])
	}
	return
}
<commit_msg>net: reimplement toLower to not depend on strings<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"errors"
	"os"
)

func query(filename, query string, bufSize int) (res []string, err error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.WriteString(query)
	if err != nil {
		return
	}
	_, err = file.Seek(0, 0)
	if err != nil {
		return
	}
	buf := make([]byte, bufSize)
	for {
		n, _ := file.Read(buf)
		if n <= 0 {
			break
		}
		res = append(res, string(buf[:n]))
	}
	return
}

func queryCS(net, host, service string) (res []string, err error) {
	switch net {
	case "tcp4", "tcp6":
		net = "tcp"
	case "udp4", "udp6":
		net = "udp"
	}
	if host == "" {
		host = "*"
	}
	return query("/net/cs", net+"!"+host+"!"+service, 128)
}

func queryCS1(net string, ip IP, port int) (clone, dest string, err error) {
	ips := "*"
	if len(ip) != 0 && !ip.IsUnspecified() {
		ips = ip.String()
	}
	lines, err := queryCS(net, ips, itoa(port))
	if err != nil {
		return
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return "", "", errors.New("net: bad response from ndb/cs")
	}
	clone, dest = f[0], f[1]
	return
}

func queryDNS(addr string, typ string) (res []string, err error) {
	return query("/net/dns", addr+" "+typ, 1024)
}

// toLower returns a lower-case version of in. Restricting us to
// ASCII is sufficient to handle the IP protocol names and allow
// us to not depend on the strings and unicode packages.
func toLower(in string) string {
	isAlreadyLowerCase := true
	for _, c := range in {
		if 'A' <= c && c <= 'Z' {
			isAlreadyLowerCase = false
			break
		}
	}
	if isAlreadyLowerCase {
		return in
	}
	out := []byte(in)
	for i, c := range out {
		if 'A' <= c && c <= 'Z' {
			out[i] += 'a' - 'A'
		}
	}
	return string(out)
}

// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(name string) (proto int, err error) {
	lines, err := query("/net/cs", "!protocol="+toLower(name), 128)
	if err != nil {
		return 0, err
	}
	unknownProtoError := errors.New("unknown IP protocol specified: " + name)
	if len(lines) == 0 {
		return 0, unknownProtoError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownProtoError
	}
	s := f[1]
	if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
		return n, nil
	}
	return 0, unknownProtoError
}

func lookupHost(host string) (addrs []string, err error) {
	// Use /net/cs instead of /net/dns because cs knows about
	// host names in local network (e.g. from /lib/ndb/local)
	lines, err := queryCS("net", host, "1")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		addr := f[1]
		if i := byteIndex(addr, '!'); i >= 0 {
			addr = addr[:i] // remove port
		}
		if ParseIP(addr) == nil {
			continue
		}
		addrs = append(addrs, addr)
	}
	return
}

func lookupIP(host string) (ips []IP, err error) {
	addrs, err := LookupHost(host)
	if err != nil {
		return
	}
	for _, addr := range addrs {
		if ip := ParseIP(addr); ip != nil {
			ips = append(ips, ip)
		}
	}
	return
}

func lookupPort(network, service string) (port int, err error) {
	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}
	lines, err := queryCS(network, "127.0.0.1", service)
	if err != nil {
		return
	}
	unknownPortError := &AddrError{"unknown port", network + "/" + service}
	if len(lines) == 0 {
		return 0, unknownPortError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownPortError
	}
	s := f[1]
	if i := byteIndex(s, '!'); i >= 0 {
		s = s[i+1:] // remove address
	}
	if n, _, ok := dtoi(s, 0); ok {
		return n, nil
	}
	return 0, unknownPortError
}

func lookupCNAME(name string) (cname string, err error) {
	lines, err := queryDNS(name, "cname")
	if err != nil {
		return
	}
	if len(lines) > 0 {
		if f := getFields(lines[0]); len(f) >= 3 {
			return f[2] + ".", nil
		}
	}
	return "", errors.New("net: bad response from ndb/dns")
}

func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
	var target string
	if service == "" && proto == "" {
		target = name
	} else {
		target = "_" + service + "._" + proto + "." + name
	}
	lines, err := queryDNS(target, "srv")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 6 {
			continue
		}
		port, _, portOk := dtoi(f[4], 0)
		priority, _, priorityOk := dtoi(f[3], 0)
		weight, _, weightOk := dtoi(f[2], 0)
		if !(portOk && priorityOk && weightOk) {
			continue
		}
		addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)})
		cname = f[0]
	}
	byPriorityWeight(addrs).sort()
	return
}

func lookupMX(name string) (mx []*MX, err error) {
	lines, err := queryDNS(name, "mx")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 4 {
			continue
		}
		if pref, _, ok := dtoi(f[2], 0); ok {
			mx = append(mx, &MX{f[3], uint16(pref)})
		}
	}
	byPref(mx).sort()
	return
}

func lookupNS(name string) (ns []*NS, err error) {
	lines, err := queryDNS(name, "ns")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		ns = append(ns, &NS{f[2]})
	}
	return
}

func lookupTXT(name string) (txt []string, err error) {
	lines, err := queryDNS(name, "txt")
	if err != nil {
		return
	}
	for _, line := range lines {
		if i := byteIndex(line, '\t'); i >= 0 {
			txt = append(txt, line[i+1:])
		}
	}
	return
}

func lookupAddr(addr string) (name []string, err error) {
	arpa, err := reverseaddr(addr)
	if err != nil {
		return
	}
	lines, err := queryDNS(arpa, "ptr")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		name = append(name, f[2])
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sort

import "testing"

func f(a []int, x int) func(int) bool {
	return func(i int) bool {
		return a[i] <= x
	}
}

var data = []int{0: -10, 1: -5, 2: 0, 3: 1, 4: 2, 5: 3, 6: 5, 7: 7, 8: 11, 9: 100, 10: 100, 11: 100, 12: 1000, 13: 10000}

var tests = []struct {
	name string
	n    int
	f    func(int) bool
	i    int
}{
	{"empty", 0, nil, 0},
	{"1 1", 1, func(i int) bool { return i <= 1 }, 0},
	{"1 true", 1, func(i int) bool { return false }, 0},
	{"1 false", 1, func(i int) bool { return true }, 0},
	{"1e9 991", 1e9, func(i int) bool { return i <= 991 }, 991},
	{"1e9 true", 1e9, func(i int) bool { return false }, 0},
	{"1e9 false", 1e9, func(i int) bool { return true }, 1e9 - 1},
	{"data -20", len(data), f(data, -20), 0},
	{"data -10", len(data), f(data, -10), 0},
	{"data -9", len(data), f(data, -9), 0},
	{"data -6", len(data), f(data, -6), 0},
	{"data -5", len(data), f(data, -5), 1},
	{"data 3", len(data), f(data, 3), 5},
	{"data 99", len(data), f(data, 99), 8},
	{"data 100", len(data), f(data, 100), 11},
	{"data 101", len(data), f(data, 101), 11},
	{"data 10000", len(data), f(data, 10000), 13},
	{"data 10001", len(data), f(data, 10001), 13},
	{"descending a", 7, func(i int) bool { return []int{99, 99, 59, 42, 7, 0, -1, -1}[i] >= 7 }, 4},
	{"descending 7", 1e9, func(i int) bool { return 1e9-i >= 7 }, 1e9 - 7},
}

func TestSearch(t *testing.T) {
	for _, e := range tests {
		i := Search(e.n, e.f)
		if i != e.i {
			t.Errorf("%s: expected index %d; got %d", e.name, e.i, i)
		}
	}
}

// Smoke tests for convenience wrappers - not comprehensive.

var fdata = []float{0: -3.14, 1: 0, 2: 1, 3: 2, 4: 1000.7}
var sdata = []string{0: "f", 1: "foo", 2: "foobar", 3: "x"}

var wrappertests = []struct {
	name   string
	result int
	i      int
}{
	{"SearchInts", SearchInts(data, 11), 8},
	{"SearchFloats", SearchFloats(fdata, 2.1), 3},
	{"SearchStrings", SearchStrings(sdata, ""), 0},
	{"IntArray.Search", IntArray(data).Search(0), 2},
	{"FloatArray.Search", FloatArray(fdata).Search(2.0), 3},
	{"StringArray.Search", StringArray(sdata).Search("x"), 3},
}

func TestSearchWrappers(t *testing.T) {
	for _, e := range wrappertests {
		if e.result != e.i {
			t.Errorf("%s: expected index %d; got %d", e.name, e.i, e.result)
		}
	}
}
<commit_msg>sort.Search: more typos<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sort

import "testing"

func f(a []int, x int) func(int) bool {
	return func(i int) bool {
		return a[i] <= x
	}
}

var data = []int{0: -10, 1: -5, 2: 0, 3: 1, 4: 2, 5: 3, 6: 5, 7: 7, 8: 11, 9: 100, 10: 100, 11: 100, 12: 1000, 13: 10000}

var tests = []struct {
	name string
	n    int
	f    func(int) bool
	i    int
}{
	{"empty", 0, nil, 0},
	{"1 1", 1, func(i int) bool { return i <= 1 }, 0},
	{"1 false", 1, func(i int) bool { return false }, 0},
	{"1 true", 1, func(i int) bool { return true }, 0},
	{"1e9 991", 1e9, func(i int) bool { return i <= 991 }, 991},
	{"1e9 false", 1e9, func(i int) bool { return false }, 0},
	{"1e9 true", 1e9, func(i int) bool { return true }, 1e9 - 1},
	{"data -20", len(data), f(data, -20), 0},
	{"data -10", len(data), f(data, -10), 0},
	{"data -9", len(data), f(data, -9), 0},
	{"data -6", len(data), f(data, -6), 0},
	{"data -5", len(data), f(data, -5), 1},
	{"data 3", len(data), f(data, 3), 5},
	{"data 99", len(data), f(data, 99), 8},
	{"data 100", len(data), f(data, 100), 11},
	{"data 101", len(data), f(data, 101), 11},
	{"data 10000", len(data), f(data, 10000), 13},
	{"data 10001", len(data), f(data, 10001), 13},
	{"descending a", 7, func(i int) bool { return []int{99, 99, 59, 42, 7, 0, -1, -1}[i] >= 7 }, 4},
	{"descending 7", 1e9, func(i int) bool { return 1e9-i >= 7 }, 1e9 - 7},
}

func TestSearch(t *testing.T) {
	for _, e := range tests {
		i := Search(e.n, e.f)
		if i != e.i {
			t.Errorf("%s: expected index %d; got %d", e.name, e.i, i)
		}
	}
}

// Smoke tests for convenience wrappers - not comprehensive.

var fdata = []float{0: -3.14, 1: 0, 2: 1, 3: 2, 4: 1000.7}
var sdata = []string{0: "f", 1: "foo", 2: "foobar", 3: "x"}

var wrappertests = []struct {
	name   string
	result int
	i      int
}{
	{"SearchInts", SearchInts(data, 11), 8},
	{"SearchFloats", SearchFloats(fdata, 2.1), 3},
	{"SearchStrings", SearchStrings(sdata, ""), 0},
	{"IntArray.Search", IntArray(data).Search(0), 2},
	{"FloatArray.Search", FloatArray(fdata).Search(2.0), 3},
	{"StringArray.Search", StringArray(sdata).Search("x"), 3},
}

func TestSearchWrappers(t *testing.T) {
	for _, e := range wrappertests {
		if e.result != e.i {
			t.Errorf("%s: expected index %d; got %d", e.name, e.i, e.result)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"testing"
	"time"
	"unicode/utf8"
)

func TestExactly16Bytes(t *testing.T) {
	var tests = []string{
		"",
		"a",
		"日本語",
		"1234567890123456",
		"12345678901234567890",
		"1234567890123本語4567890",
		"12345678901234日本語567890",
		"123456789012345日本語67890",
		"1234567890123456日本語7890",
		"1234567890123456日本語7日本語890",
	}
	for _, str := range tests {
		got := exactly16Bytes(str)
		if len(got) != 16 {
			t.Errorf("exactly16Bytes(%q) is %q, length %d", str, got, len(got))
		}
		// Make sure it is full runes.
		for _, c := range got {
			if c == utf8.RuneError {
				t.Errorf("exactly16Bytes(%q) is %q, has partial rune", str, got)
			}
		}
	}
}

// tmpDir creates a temporary directory and returns its name.
func tmpDir(t *testing.T) string {
	name, err := ioutil.TempDir("", "pack")
	if err != nil {
		t.Fatal(err)
	}
	return name
}

// Test that we can create an archive, write to it, and get the same contents back.
// Tests the rv and then the pv command on a new archive.
func TestCreate(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	name := filepath.Join(dir, "pack.a")
	ar := archive(name, os.O_RDWR, nil)
	// Add an entry by hand.
	ar.addFile(helloFile.Reset())
	ar.fd.Close()
	// Now check it.
	ar = archive(name, os.O_RDONLY, []string{helloFile.name})
	var buf bytes.Buffer
	stdout = &buf
	verbose = true
	defer func() {
		stdout = os.Stdout
		verbose = false
	}()
	ar.scan(ar.printContents)
	ar.fd.Close()
	result := buf.String()
	// Expect verbose output plus file contents.
	expect := fmt.Sprintf("%s\n%s", helloFile.name, helloFile.contents)
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
}

// Test that we can create an archive, put some files in it, and get back a correct listing.
// Tests the tv command.
func TestTableOfContents(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	name := filepath.Join(dir, "pack.a")
	ar := archive(name, os.O_RDWR, nil)
	// Add some entries by hand.
	ar.addFile(helloFile.Reset())
	ar.addFile(goodbyeFile.Reset())
	ar.fd.Close()
	// Now print it.
	ar = archive(name, os.O_RDONLY, nil)
	var buf bytes.Buffer
	stdout = &buf
	verbose = true
	defer func() {
		stdout = os.Stdout
		verbose = false
	}()
	ar.scan(ar.tableOfContents)
	ar.fd.Close()
	result := buf.String()
	// Expect verbose listing.
	expect := fmt.Sprintf("%s\n%s\n", helloFile.Entry(), goodbyeFile.Entry())
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
	// Do it again without verbose.
	verbose = false
	buf.Reset()
	ar = archive(name, os.O_RDONLY, nil)
	ar.scan(ar.tableOfContents)
	ar.fd.Close()
	result = buf.String()
	// Expect non-verbose listing.
	expect = fmt.Sprintf("%s\n%s\n", helloFile.name, goodbyeFile.name)
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
}

// Test that we can create an archive, put some files in it, and get back a file.
// Tests the x command.
func TestExtract(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	name := filepath.Join(dir, "pack.a")
	ar := archive(name, os.O_RDWR, nil)
	// Add some entries by hand.
	ar.addFile(helloFile.Reset())
	ar.addFile(goodbyeFile.Reset())
	ar.fd.Close()
	// Now extract one file. We chdir to the directory of the archive for simplicity.
	pwd, err := os.Getwd()
	if err != nil {
		t.Fatal("os.Getwd: ", err)
	}
	err = os.Chdir(dir)
	if err != nil {
		t.Fatal("os.Chdir: ", err)
	}
	defer func() {
		err := os.Chdir(pwd)
		if err != nil {
			t.Fatal("os.Chdir: ", err)
		}
	}()
	ar = archive(name, os.O_RDONLY, []string{goodbyeFile.name})
	ar.scan(ar.extractContents)
	ar.fd.Close()
	data, err := ioutil.ReadFile(goodbyeFile.name)
	if err != nil {
		t.Fatal(err)
	}
	// Expect contents of file.
	result := string(data)
	expect := goodbyeFile.contents
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
}

// Test that pack-created archives can be understood by the tools.
func TestHello(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	hello := filepath.Join(dir, "hello.go")
	prog := `
		package main
		func main() {
			println("hello world")
		}
	`
	err := ioutil.WriteFile(hello, []byte(prog), 0666)
	if err != nil {
		t.Fatal(err)
	}

	run := func(args ...string) string {
		cmd := exec.Command(args[0], args[1:]...)
		cmd.Dir = dir
		out, err := cmd.CombinedOutput()
		if err != nil {
			t.Fatalf("%v: %v\n%s", args, err, string(out))
		}
		return string(out)
	}

	out := run("go", "env")
	re, err := regexp.Compile(`\s*GOCHAR="?(\w)"?`)
	if err != nil {
		t.Fatal(err)
	}
	fields := re.FindStringSubmatch(out)
	if fields == nil {
		t.Fatal("cannot find GOCHAR in 'go env' output:\n", out)
	}
	char := fields[1]
	run("go", "build", "cmd/pack") // writes pack binary to dir
	run("go", "tool", char+"g", "hello.go")
	run("./pack", "grc", "hello.a", "hello."+char)
	run("go", "tool", char+"l", "-o", "a.out", "hello.a")
	out = run("./a.out")
	if out != "hello world\n" {
		t.Fatal("incorrect output: %q, want %q", out, "hello world\n")
	}
}

// Fake implementation of files.

var helloFile = &FakeFile{
	name:     "hello",
	contents: "hello world", // 11 bytes, an odd number.
	mode:     0644,
}

var goodbyeFile = &FakeFile{
	name:     "goodbye",
	contents: "Sayonara, Jim", // 13 bytes, another odd number.
	mode:     0644,
}

// FakeFile implements FileLike and also os.FileInfo.
type FakeFile struct {
	name     string
	contents string
	mode     os.FileMode
	offset   int
}

// Reset prepares a FakeFile for reuse.
func (f *FakeFile) Reset() *FakeFile {
	f.offset = 0
	return f
}

// FileLike methods.

func (f *FakeFile) Name() string {
	// A bit of a cheat: we only have a basename, so that's also ok for FileInfo.
	return f.name
}

func (f *FakeFile) Stat() (os.FileInfo, error) {
	return f, nil
}

func (f *FakeFile) Read(p []byte) (int, error) {
	if f.offset >= len(f.contents) {
		return 0, io.EOF
	}
	n := copy(p, f.contents[f.offset:])
	f.offset += n
	return n, nil
}

func (f *FakeFile) Close() error {
	return nil
}

// os.FileInfo methods.

func (f *FakeFile) Size() int64 {
	return int64(len(f.contents))
}

func (f *FakeFile) Mode() os.FileMode {
	return f.mode
}

func (f *FakeFile) ModTime() time.Time {
	return time.Time{}
}

func (f *FakeFile) IsDir() bool {
	return false
}

func (f *FakeFile) Sys() interface{} {
	return nil
}

// Special helpers.

func (f *FakeFile) Entry() *Entry {
	return &Entry{
		name:  f.name,
		mtime: 0, // Defined to be zero.
		uid:   0, // Ditto.
		gid:   0, // Ditto.
		mode:  f.mode,
		size:  int64(len(f.contents)),
	}
}
<commit_msg>cmd/pack: another attempt to fix the build for TestHello Plan 9 uses single quotes, not double quotes. I should have known.<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"testing"
	"time"
	"unicode/utf8"
)

func TestExactly16Bytes(t *testing.T) {
	var tests = []string{
		"",
		"a",
		"日本語",
		"1234567890123456",
		"12345678901234567890",
		"1234567890123本語4567890",
		"12345678901234日本語567890",
		"123456789012345日本語67890",
		"1234567890123456日本語7890",
		"1234567890123456日本語7日本語890",
	}
	for _, str := range tests {
		got := exactly16Bytes(str)
		if len(got) != 16 {
			t.Errorf("exactly16Bytes(%q) is %q, length %d", str, got, len(got))
		}
		// Make sure it is full runes.
		for _, c := range got {
			if c == utf8.RuneError {
				t.Errorf("exactly16Bytes(%q) is %q, has partial rune", str, got)
			}
		}
	}
}

// tmpDir creates a temporary directory and returns its name.
func tmpDir(t *testing.T) string {
	name, err := ioutil.TempDir("", "pack")
	if err != nil {
		t.Fatal(err)
	}
	return name
}

// Test that we can create an archive, write to it, and get the same contents back.
// Tests the rv and then the pv command on a new archive.
func TestCreate(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	name := filepath.Join(dir, "pack.a")
	ar := archive(name, os.O_RDWR, nil)
	// Add an entry by hand.
	ar.addFile(helloFile.Reset())
	ar.fd.Close()
	// Now check it.
	ar = archive(name, os.O_RDONLY, []string{helloFile.name})
	var buf bytes.Buffer
	stdout = &buf
	verbose = true
	defer func() {
		stdout = os.Stdout
		verbose = false
	}()
	ar.scan(ar.printContents)
	ar.fd.Close()
	result := buf.String()
	// Expect verbose output plus file contents.
	expect := fmt.Sprintf("%s\n%s", helloFile.name, helloFile.contents)
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
}

// Test that we can create an archive, put some files in it, and get back a correct listing.
// Tests the tv command.
func TestTableOfContents(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	name := filepath.Join(dir, "pack.a")
	ar := archive(name, os.O_RDWR, nil)
	// Add some entries by hand.
	ar.addFile(helloFile.Reset())
	ar.addFile(goodbyeFile.Reset())
	ar.fd.Close()
	// Now print it.
	ar = archive(name, os.O_RDONLY, nil)
	var buf bytes.Buffer
	stdout = &buf
	verbose = true
	defer func() {
		stdout = os.Stdout
		verbose = false
	}()
	ar.scan(ar.tableOfContents)
	ar.fd.Close()
	result := buf.String()
	// Expect verbose listing.
	expect := fmt.Sprintf("%s\n%s\n", helloFile.Entry(), goodbyeFile.Entry())
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
	// Do it again without verbose.
	verbose = false
	buf.Reset()
	ar = archive(name, os.O_RDONLY, nil)
	ar.scan(ar.tableOfContents)
	ar.fd.Close()
	result = buf.String()
	// Expect non-verbose listing.
	expect = fmt.Sprintf("%s\n%s\n", helloFile.name, goodbyeFile.name)
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
}

// Test that we can create an archive, put some files in it, and get back a file.
// Tests the x command.
func TestExtract(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	name := filepath.Join(dir, "pack.a")
	ar := archive(name, os.O_RDWR, nil)
	// Add some entries by hand.
	ar.addFile(helloFile.Reset())
	ar.addFile(goodbyeFile.Reset())
	ar.fd.Close()
	// Now extract one file. We chdir to the directory of the archive for simplicity.
	pwd, err := os.Getwd()
	if err != nil {
		t.Fatal("os.Getwd: ", err)
	}
	err = os.Chdir(dir)
	if err != nil {
		t.Fatal("os.Chdir: ", err)
	}
	defer func() {
		err := os.Chdir(pwd)
		if err != nil {
			t.Fatal("os.Chdir: ", err)
		}
	}()
	ar = archive(name, os.O_RDONLY, []string{goodbyeFile.name})
	ar.scan(ar.extractContents)
	ar.fd.Close()
	data, err := ioutil.ReadFile(goodbyeFile.name)
	if err != nil {
		t.Fatal(err)
	}
	// Expect contents of file.
	result := string(data)
	expect := goodbyeFile.contents
	if result != expect {
		t.Fatalf("expected %q got %q", expect, result)
	}
}

// Test that pack-created archives can be understood by the tools.
func TestHello(t *testing.T) {
	dir := tmpDir(t)
	defer os.RemoveAll(dir)
	hello := filepath.Join(dir, "hello.go")
	prog := `
		package main
		func main() {
			println("hello world")
		}
	`
	err := ioutil.WriteFile(hello, []byte(prog), 0666)
	if err != nil {
		t.Fatal(err)
	}

	run := func(args ...string) string {
		cmd := exec.Command(args[0], args[1:]...)
		cmd.Dir = dir
		out, err := cmd.CombinedOutput()
		if err != nil {
			t.Fatalf("%v: %v\n%s", args, err, string(out))
		}
		return string(out)
	}

	out := run("go", "env")
	re, err := regexp.Compile(`\s*GOCHAR=['"]?(\w)['"]?`)
	if err != nil {
		t.Fatal(err)
	}
	fields := re.FindStringSubmatch(out)
	if fields == nil {
		t.Fatal("cannot find GOCHAR in 'go env' output:\n", out)
	}
	char := fields[1]
	run("go", "build", "cmd/pack") // writes pack binary to dir
	run("go", "tool", char+"g", "hello.go")
	run("./pack", "grc", "hello.a", "hello."+char)
	run("go", "tool", char+"l", "-o", "a.out", "hello.a")
	out = run("./a.out")
	if out != "hello world\n" {
		t.Fatal("incorrect output: %q, want %q", out, "hello world\n")
	}
}

// Fake implementation of files.

var helloFile = &FakeFile{
	name:     "hello",
	contents: "hello world", // 11 bytes, an odd number.
	mode:     0644,
}

var goodbyeFile = &FakeFile{
	name:     "goodbye",
	contents: "Sayonara, Jim", // 13 bytes, another odd number.
	mode:     0644,
}

// FakeFile implements FileLike and also os.FileInfo.
type FakeFile struct {
	name     string
	contents string
	mode     os.FileMode
	offset   int
}

// Reset prepares a FakeFile for reuse.
func (f *FakeFile) Reset() *FakeFile {
	f.offset = 0
	return f
}

// FileLike methods.

func (f *FakeFile) Name() string {
	// A bit of a cheat: we only have a basename, so that's also ok for FileInfo.
	return f.name
}

func (f *FakeFile) Stat() (os.FileInfo, error) {
	return f, nil
}

func (f *FakeFile) Read(p []byte) (int, error) {
	if f.offset >= len(f.contents) {
		return 0, io.EOF
	}
	n := copy(p, f.contents[f.offset:])
	f.offset += n
	return n, nil
}

func (f *FakeFile) Close() error {
	return nil
}

// os.FileInfo methods.

func (f *FakeFile) Size() int64 {
	return int64(len(f.contents))
}

func (f *FakeFile) Mode() os.FileMode {
	return f.mode
}

func (f *FakeFile) ModTime() time.Time {
	return time.Time{}
}

func (f *FakeFile) IsDir() bool {
	return false
}

func (f *FakeFile) Sys() interface{} {
	return nil
}

// Special helpers.

func (f *FakeFile) Entry() *Entry {
	return &Entry{
		name:  f.name,
		mtime: 0, // Defined to be zero.
		uid:   0, // Ditto.
		gid:   0, // Ditto.
		mode:  f.mode,
		size:  int64(len(f.contents)),
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gltext

import (
	"fmt"
	"github.com/go-gl/glow/gl-core/3.3/gl"
	"github.com/go-gl/mathgl/mgl32"
)

const IsEdit = false

type Text struct {
	font *Font

	// final position on screen
	finalPosition mgl32.Vec2

	// text color
	color mgl32.Vec4

	// scaling the text
	Scale       float32
	ScaleMax    float32
	scaleMatrix mgl32.Mat4

	// bounding box of text
	BoundingBox *BoundingBox

	// general opengl values
	vao           uint32
	vbo           uint32
	ebo           uint32
	vboData       []float32
	vboIndexCount int
	eboData       []int32
	eboIndexCount int

	// X1, X2: the lower left and upper right points of a box that bounds the text
	X1 Point
	X2 Point
}

func LoadText(f *Font) (t *Text) {
	t = new(Text)
	t.font = f

	// text hover values - implicit ScaleMin of 1.0
	t.ScaleMax = 1.1
	t.SetScale(1)

	// size of glfloat
	glfloat_size := int32(4)

	// stride of the buffered data
	xy_count := int32(2)
	stride := xy_count + int32(2)

	gl.GenVertexArrays(1, &t.vao)
	gl.GenBuffers(1, &t.vbo)
	gl.GenBuffers(1, &t.ebo)

	// vao
	gl.BindVertexArray(t.vao)

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, t.font.textureID)

	// vbo
	// specify the buffer for which the VertexAttribPointer calls apply
	gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo)

	gl.EnableVertexAttribArray(t.font.centeredPosition)
	gl.VertexAttribPointer(
		t.font.centeredPosition,
		2,
		gl.FLOAT,
		false,
		glfloat_size*stride,
		gl.PtrOffset(0),
	)

	gl.EnableVertexAttribArray(t.font.uv)
	gl.VertexAttribPointer(
		t.font.uv,
		2,
		gl.FLOAT,
		false,
		glfloat_size*stride,
		gl.PtrOffset(int(glfloat_size*xy_count)),
	)

	// ebo
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo)

	// i am guessing that order is important here
	gl.BindVertexArray(0)
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
	return t
}

// Release releases font resources.
// A font can no longer be used for rendering after this call completes.
func (t *Text) Release() {
	gl.DeleteBuffers(1, &t.vbo)
	gl.DeleteBuffers(1, &t.ebo)
	gl.DeleteBuffers(1, &t.vao)
}

func (t *Text) SetScale(s float32) (changed bool) {
	if s > t.ScaleMax || s < 1.0 {
		return
	}
	changed = true
	t.Scale = s
	t.scaleMatrix = mgl32.Scale3D(s, s, s)
	return
}

func (t *Text) AddScale(s float32) (changed bool) {
	if s < 0 && t.Scale <= 1.0 {
		return
	}
	if s > 0 && t.Scale >= t.ScaleMax {
		return
	}
	changed = true
	t.Scale += s
	t.scaleMatrix = mgl32.Scale3D(t.Scale, t.Scale, t.Scale)
	return
}

func (t *Text) SetColor(r, g, b, a float32) {
	t.color = mgl32.Vec4{r, g, b, a}
}

func (t *Text) SetString(fs string, argv ...interface{}) {
	indices := []rune(fmt.Sprintf(fs, argv...))
	if len(indices) == 0 {
		return
	}

	// ebo, vbo data
	glfloat_size := int32(4)

	t.vboIndexCount = len(indices) * 4 * 2 * 2 // 4 indexes per rune (containing 2 position + 2 texture)
	t.eboIndexCount = len(indices) * 6         // each rune requires 6 triangle indices for a quad
	t.vboData = make([]float32, t.vboIndexCount, t.vboIndexCount)
	t.eboData = make([]int32, t.eboIndexCount, t.eboIndexCount)

	// generate the basic vbo data and bounding box
	t.makeBufferData(indices)

	// find the centered position of the bounding box
	lowerLeft := t.center()

	// reposition the vbo data so that it is centered at (0,0)
	// according to the orthographic projection being used
	t.setDataPosition(lowerLeft)

	if IsDebug {
		fmt.Printf("bounding box %v %v\n", t.X1, t.X2)
		fmt.Printf("text vbo data\n%v\n", t.vboData)
		fmt.Printf("text ebo data\n%v\n", t.eboData)
	}
	gl.BindVertexArray(t.vao)
	gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo)
	gl.BufferData(
		gl.ARRAY_BUFFER, int(glfloat_size)*t.vboIndexCount, gl.Ptr(t.vboData), gl.DYNAMIC_DRAW)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo)
	gl.BufferData(
		gl.ELEMENT_ARRAY_BUFFER, int(glfloat_size)*t.eboIndexCount, gl.Ptr(t.eboData), gl.DYNAMIC_DRAW)
	gl.BindVertexArray(0)

	// not necesssary, but i just want to better understand using vertex arrays
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
}

func (t *Text) center() (lowerLeft Point) {
	lineWidthHalf := (t.X2.X - t.X1.X) / 2
	lineHeightHalf := (t.X2.Y - t.X1.Y) / 2

	lowerLeft.X = -lineWidthHalf
	lowerLeft.Y = -lineHeightHalf
	return
}

func (t *Text) SetPosition(x, y float32) {
	// we are in an orthographic projection state with ranges -1 to 1

	// final place the corner on the position specified by the user
	t.finalPosition[0] = x / t.font.WindowWidth
	t.finalPosition[1] = y / t.font.WindowHeight
	if IsEdit {
		t.BoundingBox.finalPosition[0] = x / t.font.WindowWidth
		t.BoundingBox.finalPosition[1] = y / t.font.WindowHeight
	}
}

func (t *Text) Draw() {
	if IsEdit {
		t.BoundingBox.Draw()
	}
	gl.UseProgram(t.font.program)

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, t.font.textureID)

	// uniforms
	gl.Uniform1i(t.font.fragmentTextureUniform, 0)
	gl.Uniform1f(t.font.textLowerBoundUniform, t.font.textLowerBound)
	gl.Uniform4fv(t.font.colorUniform, 1, &t.color[0])
	gl.Uniform2fv(t.font.finalPositionUniform, 1, &t.finalPosition[0])
	gl.UniformMatrix4fv(t.font.orthographicMatrixUniform, 1, false, &t.font.orthographicMatrix[0])
	gl.UniformMatrix4fv(t.font.scaleMatrixUniform, 1, false, &t.scaleMatrix[0])

	// draw
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.BindVertexArray(t.vao)
	gl.DrawElements(gl.TRIANGLES, int32(t.eboIndexCount), gl.UNSIGNED_INT, nil)
	gl.BindVertexArray(0)
	gl.Disable(gl.BLEND)
}

func (t *Text) getBoundingBox(vboIndex int) {
	// index -4: x, index -3: y, index -2: uv's x, index -1 uv's y
	x := t.vboData[vboIndex-4]
	y := t.vboData[vboIndex-3]

	if vboIndex-4 == 0 {
		t.X1.X = x
		t.X1.Y = y
	} else {
		if x < t.X1.X {
			t.X1.X = x
		}
		if y < t.X1.Y {
			t.X1.Y = y
		}
		if x > t.X2.X {
			t.X2.X = x
		}
		if y > t.X2.Y {
			t.X2.Y = y
		}
	}
}

// all text originally sits at point (0,0) which is the
// lower left hand corner of the screen.
func (t *Text) setDataPosition(lowerLeft Point) (err error) {
	length := len(t.vboData)
	for index := 0; index < length; {
		// index (0,0)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3 // skip texture data

		// index (1,0)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3

		// index (1,1)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3

		// index (0,1)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3
	}
	// update bounding box
	t.X1.X += lowerLeft.X
	t.X2.X += lowerLeft.X
	t.X1.Y += lowerLeft.Y
	t.X2.Y += lowerLeft.Y
	if IsEdit {
		t.BoundingBox, err = loadBoundingBox(t.font, t.X1, t.X2)
	}
	fmt.Println(t.X1, t.X2)
	return
}

// currently only supports left to right text flow
func (t *Text) makeBufferData(indices []rune) {
	glyphs := t.font.config.Glyphs
	low := t.font.config.Low

	vboIndex := 0
	eboIndex := 0
	lineX := float32(0)
	eboOffset := int32(0)
	for _, r := range indices {
		r -= low
		if r >= 0 && int(r) < len(glyphs) {
			vw := float32(glyphs[r].Width)
			vh := float32(glyphs[r].Height)
			tP1, tP2 := glyphs[r].GetIndices(t.font)

			// counter-clockwise quad

			// index (0,0)
			t.vboData[vboIndex] = lineX // position
			vboIndex++
			t.vboData[vboIndex] = 0
			vboIndex++
			t.vboData[vboIndex] = tP1.X // texture uv
			vboIndex++
			t.vboData[vboIndex] = tP2.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			// index (1,0)
			t.vboData[vboIndex] = lineX + vw
			vboIndex++
			t.vboData[vboIndex] = 0
			vboIndex++
			t.vboData[vboIndex] = tP2.X
			vboIndex++
			t.vboData[vboIndex] = tP2.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			// index (1,1)
			t.vboData[vboIndex] = lineX + vw
			vboIndex++
			t.vboData[vboIndex] = vh
			vboIndex++
			t.vboData[vboIndex] = tP2.X
			vboIndex++
			t.vboData[vboIndex] = tP1.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			// index (0,1)
			t.vboData[vboIndex] = lineX
			vboIndex++
			t.vboData[vboIndex] = vh
			vboIndex++
			t.vboData[vboIndex] = tP1.X
			vboIndex++
			t.vboData[vboIndex] = tP1.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			advance := float32(glyphs[r].Advance)
			lineX += advance

			// ebo data
			t.eboData[eboIndex] = 0 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 1 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 2 + eboOffset
			eboIndex++

			t.eboData[eboIndex] = 0 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 2 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 3 + eboOffset
			eboIndex++
			eboOffset += 4
		}
	}
	return
}
<commit_msg>Added width and height to text struct. SetPosition updates X1 and X2 values.<commit_after>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gltext

import (
	"fmt"
	"github.com/go-gl/glow/gl-core/3.3/gl"
	"github.com/go-gl/mathgl/mgl32"
)

const IsEdit = false

type Text struct {
	font *Font

	// final position on screen
	finalPosition mgl32.Vec2

	// text color
	color mgl32.Vec4

	// scaling the text
	Scale       float32
	ScaleMax    float32
	scaleMatrix mgl32.Mat4

	// bounding box of text
	BoundingBox *BoundingBox

	// general opengl values
	vao           uint32
	vbo           uint32
	ebo           uint32
	vboData       []float32
	vboIndexCount int
	eboData       []int32
	eboIndexCount int

	// X1, X2: the lower left and upper right points of a box that bounds the text
	//         actual screen coordinates
	X1 Point
	X2 Point

	// Width and Height of the text in screen coordinates
	Width  float32
	Height float32
}

func LoadText(f *Font) (t *Text) {
	t = new(Text)
	t.font = f

	// text hover values - implicit ScaleMin of 1.0
	t.ScaleMax = 1.1
	t.SetScale(1)

	// size of glfloat
	glfloat_size := int32(4)

	// stride of the buffered data
	xy_count := int32(2)
	stride := xy_count + int32(2)

	gl.GenVertexArrays(1, &t.vao)
	gl.GenBuffers(1, &t.vbo)
	gl.GenBuffers(1, &t.ebo)

	// vao
	gl.BindVertexArray(t.vao)

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, t.font.textureID)

	// vbo
	// specify the buffer for which the VertexAttribPointer calls apply
	gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo)

	gl.EnableVertexAttribArray(t.font.centeredPosition)
	gl.VertexAttribPointer(
		t.font.centeredPosition,
		2,
		gl.FLOAT,
		false,
		glfloat_size*stride,
		gl.PtrOffset(0),
	)

	gl.EnableVertexAttribArray(t.font.uv)
	gl.VertexAttribPointer(
		t.font.uv,
		2,
		gl.FLOAT,
		false,
		glfloat_size*stride,
		gl.PtrOffset(int(glfloat_size*xy_count)),
	)

	// ebo
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo)

	// i am guessing that order is important here
	gl.BindVertexArray(0)
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
	return t
}

// Release releases font resources.
// A font can no longer be used for rendering after this call completes.
func (t *Text) Release() {
	gl.DeleteBuffers(1, &t.vbo)
	gl.DeleteBuffers(1, &t.ebo)
	gl.DeleteBuffers(1, &t.vao)
}

func (t *Text) SetScale(s float32) (changed bool) {
	if s > t.ScaleMax || s < 1.0 {
		return
	}
	changed = true
	t.Scale = s
	t.scaleMatrix = mgl32.Scale3D(s, s, s)
	return
}

func (t *Text) AddScale(s float32) (changed bool) {
	if s < 0 && t.Scale <= 1.0 {
		return
	}
	if s > 0 && t.Scale >= t.ScaleMax {
		return
	}
	changed = true
	t.Scale += s
	t.scaleMatrix = mgl32.Scale3D(t.Scale, t.Scale, t.Scale)
	return
}

func (t *Text) SetColor(r, g, b, a float32) {
	t.color = mgl32.Vec4{r, g, b, a}
}

func (t *Text) SetString(fs string, argv ...interface{}) {
	indices := []rune(fmt.Sprintf(fs, argv...))
	if len(indices) == 0 {
		return
	}

	// ebo, vbo data
	glfloat_size := int32(4)

	t.vboIndexCount = len(indices) * 4 * 2 * 2 // 4 indexes per rune (containing 2 position + 2 texture)
	t.eboIndexCount = len(indices) * 6         // each rune requires 6 triangle indices for a quad
	t.vboData = make([]float32, t.vboIndexCount, t.vboIndexCount)
	t.eboData = make([]int32, t.eboIndexCount, t.eboIndexCount)

	// generate the basic vbo data and bounding box
	t.makeBufferData(indices)

	// find the centered position of the bounding box
	lowerLeft := t.center()

	// reposition the vbo data so that it is centered at (0,0)
	// according to the orthographic projection being used
	t.setDataPosition(lowerLeft)

	if IsDebug {
		fmt.Printf("bounding box %v %v\n", t.X1, t.X2)
		fmt.Printf("text vbo data\n%v\n", t.vboData)
		fmt.Printf("text ebo data\n%v\n", t.eboData)
	}
	gl.BindVertexArray(t.vao)
	gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo)
	gl.BufferData(
		gl.ARRAY_BUFFER, int(glfloat_size)*t.vboIndexCount, gl.Ptr(t.vboData), gl.DYNAMIC_DRAW)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo)
	gl.BufferData(
		gl.ELEMENT_ARRAY_BUFFER, int(glfloat_size)*t.eboIndexCount, gl.Ptr(t.eboData), gl.DYNAMIC_DRAW)
	gl.BindVertexArray(0)

	// not necesssary, but i just want to better understand using vertex arrays
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
}

func (t *Text) center() (lowerLeft Point) {
	lineWidthHalf := (t.X2.X - t.X1.X) / 2
	lineHeightHalf := (t.X2.Y - t.X1.Y) / 2

	lowerLeft.X = -lineWidthHalf
	lowerLeft.Y = -lineHeightHalf
	return
}

func (t *Text) SetPosition(x, y float32) {
	// we are in an orthographic projection state with ranges -1 to 1
	t.finalPosition[0] = x / t.font.WindowWidth
	t.finalPosition[1] = y / t.font.WindowHeight
	if IsEdit {
		t.BoundingBox.finalPosition[0] = x / t.font.WindowWidth
		t.BoundingBox.finalPosition[1] = y / t.font.WindowHeight
	}

	// Screen coordinates so -1 to 1 range transform is not required
	t.X1.X += x / 2
	t.X1.Y += y / 2
	t.X2.X += x / 2
	t.X2.Y += y / 2
}

func (t *Text) Draw() {
	if IsEdit {
		t.BoundingBox.Draw()
	}
	gl.UseProgram(t.font.program)

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, t.font.textureID)

	// uniforms
	gl.Uniform1i(t.font.fragmentTextureUniform, 0)
	gl.Uniform1f(t.font.textLowerBoundUniform, t.font.textLowerBound)
	gl.Uniform4fv(t.font.colorUniform, 1, &t.color[0])
	gl.Uniform2fv(t.font.finalPositionUniform, 1, &t.finalPosition[0])
	gl.UniformMatrix4fv(t.font.orthographicMatrixUniform, 1, false, &t.font.orthographicMatrix[0])
	gl.UniformMatrix4fv(t.font.scaleMatrixUniform, 1, false, &t.scaleMatrix[0])

	// draw
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.BindVertexArray(t.vao)
	gl.DrawElements(gl.TRIANGLES, int32(t.eboIndexCount), gl.UNSIGNED_INT, nil)
	gl.BindVertexArray(0)
	gl.Disable(gl.BLEND)
}

func (t *Text) getBoundingBox(vboIndex int) {
	// index -4: x, index -3: y, index -2: uv's x, index -1 uv's y
	x := t.vboData[vboIndex-4]
	y := t.vboData[vboIndex-3]

	if vboIndex-4 == 0 {
		t.X1.X = x
		t.X1.Y = y
	} else {
		if x < t.X1.X {
			t.X1.X = x
		}
		if y < t.X1.Y {
			t.X1.Y = y
		}
		if x > t.X2.X {
			t.X2.X = x
		}
		if y > t.X2.Y {
			t.X2.Y = y
		}
	}
}

// all text originally sits at point (0,0) which is the
// lower left hand corner of the screen.
func (t *Text) setDataPosition(lowerLeft Point) (err error) {
	length := len(t.vboData)
	for index := 0; index < length; {
		// index (0,0)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3 // skip texture data

		// index (1,0)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3

		// index (1,1)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3

		// index (0,1)
		t.vboData[index] += lowerLeft.X
		index++
		t.vboData[index] += lowerLeft.Y
		index += 3
	}
	// update bounding box
	t.X1.X += lowerLeft.X
	t.X2.X += lowerLeft.X
	t.X1.Y += lowerLeft.Y
	t.X2.Y += lowerLeft.Y
	t.Width = t.X2.X - t.X1.X
	t.Height = t.X2.Y - t.X1.Y
	if IsEdit {
		t.BoundingBox, err = loadBoundingBox(t.font, t.X1, t.X2)
	}
	fmt.Println(t.X1, t.X2)
	return
}

// currently only supports left to right text flow
func (t *Text) makeBufferData(indices []rune) {
	glyphs := t.font.config.Glyphs
	low := t.font.config.Low

	vboIndex := 0
	eboIndex := 0
	lineX := float32(0)
	eboOffset := int32(0)
	for _, r := range indices {
		r -= low
		if r >= 0 && int(r) < len(glyphs) {
			vw := float32(glyphs[r].Width)
			vh := float32(glyphs[r].Height)
			tP1, tP2 := glyphs[r].GetIndices(t.font)

			// counter-clockwise quad

			// index (0,0)
			t.vboData[vboIndex] = lineX // position
			vboIndex++
			t.vboData[vboIndex] = 0
			vboIndex++
			t.vboData[vboIndex] = tP1.X // texture uv
			vboIndex++
			t.vboData[vboIndex] = tP2.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			// index (1,0)
			t.vboData[vboIndex] = lineX + vw
			vboIndex++
			t.vboData[vboIndex] = 0
			vboIndex++
			t.vboData[vboIndex] = tP2.X
			vboIndex++
			t.vboData[vboIndex] = tP2.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			// index (1,1)
			t.vboData[vboIndex] = lineX + vw
			vboIndex++
			t.vboData[vboIndex] = vh
			vboIndex++
			t.vboData[vboIndex] = tP2.X
			vboIndex++
			t.vboData[vboIndex] = tP1.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			// index (0,1)
			t.vboData[vboIndex] = lineX
			vboIndex++
			t.vboData[vboIndex] = vh
			vboIndex++
			t.vboData[vboIndex] = tP1.X
			vboIndex++
			t.vboData[vboIndex] = tP1.Y
			vboIndex++
			t.getBoundingBox(vboIndex)

			advance := float32(glyphs[r].Advance)
			lineX += advance

			// ebo data
			t.eboData[eboIndex] = 0 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 1 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 2 + eboOffset
			eboIndex++

			t.eboData[eboIndex] = 0 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 2 + eboOffset
			eboIndex++
			t.eboData[eboIndex] = 3 + eboOffset
			eboIndex++
			eboOffset += 4
		}
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2013 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.

// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package tidb

import (
	"net/http"
	// For pprof
	_ "net/http/pprof"
	"strings"
	"sync"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/domain"
	"github.com/pingcap/tidb/expression"
	"github.com/pingcap/tidb/field"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/optimizer"
	"github.com/pingcap/tidb/parser"
	"github.com/pingcap/tidb/rset"
	"github.com/pingcap/tidb/sessionctx/autocommit"
	"github.com/pingcap/tidb/sessionctx/variable"
	"github.com/pingcap/tidb/stmt"
	"github.com/pingcap/tidb/stmt/stmts"
	"github.com/pingcap/tidb/store/localstore"
	"github.com/pingcap/tidb/store/localstore/boltdb"
	"github.com/pingcap/tidb/store/localstore/engine"
	"github.com/pingcap/tidb/store/localstore/goleveldb"
	"github.com/pingcap/tidb/terror"
)

// Engine prefix name
const (
	EngineGoLevelDBMemory     = "memory://"
	EngineGoLevelDBPersistent = "goleveldb://"
	EngineHBase               = "zk://"
	EngineBoltDB              = "boltdb://"
)

type domainMap struct {
	domains map[string]*domain.Domain
	mu      sync.Mutex
}

func (dm *domainMap) Get(store kv.Storage) (d *domain.Domain, err error) {
	key := store.UUID()
	dm.mu.Lock()
	defer dm.mu.Unlock()
	d = dm.domains[key]
	if d != nil {
		return
	}

	if SchemaLease <= minSchemaLease {
		SchemaLease = minSchemaLease
	}

	lease := SchemaLease
	// if storage is local storage, we may in test environment or
	// run server in single machine mode, so we don't need wait
	// 2 * lease time for DDL operation.
	if localstore.IsLocalStore(store) {
		lease = 0
	}
	d, err = domain.NewDomain(store, lease)
	if err != nil {
		return nil, errors.Trace(err)
	}
	dm.domains[key] = d
	return
}

var (
	domap = &domainMap{
		domains: map[string]*domain.Domain{},
	}
	stores = make(map[string]kv.Driver)
	// Debug is the switch for pprof. If Debug is true, tidb will start with pprof on.
	Debug = true
	// PprofAddr is the pprof url.
	PprofAddr = "localhost:8888"
	// store.UUID()-> IfBootstrapped
	storeBootstrapped = make(map[string]bool)

	// SchemaLease is the time(seconds) for re-updating remote schema.
	// In online DDL, we must wait 2 * SchemaLease time to guarantee
	// all servers get the neweset schema.
	SchemaLease    = 300
	minSchemaLease = 120
)

// What character set should the server translate a statement to after receiving it?
// For this, the server uses the character_set_connection and collation_connection system variables.
// It converts statements sent by the client from character_set_client to character_set_connection
// (except for string literals that have an introducer such as _latin1 or _utf8).
// collation_connection is important for comparisons of literal strings.
// For comparisons of strings with column values, collation_connection does not matter because columns
// have their own collation, which has a higher collation precedence.
// See: https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html
func getCtxCharsetInfo(ctx context.Context) (string, string) {
	sessionVars := variable.GetSessionVars(ctx)
	charset := sessionVars.Systems["character_set_connection"]
	collation := sessionVars.Systems["collation_connection"]
	return charset, collation
}

// Compile is safe for concurrent use by multiple goroutines.
func Compile(ctx context.Context, src string) ([]stmt.Statement, error) {
	log.Debug("compiling", src)
	l := parser.NewLexer(src)
	l.SetCharsetInfo(getCtxCharsetInfo(ctx))
	if parser.YYParse(l) != 0 {
		log.Warnf("compiling %s, error: %v", src, l.Errors()[0])
		return nil, errors.Trace(l.Errors()[0])
	}
	rawStmt := l.Stmts()
	stmts := make([]stmt.Statement, len(rawStmt))
	for i, v := range rawStmt {
		compiler := &optimizer.Compiler{}
		stm, err := compiler.Compile(v)
		if err != nil {
			return nil, errors.Trace(err)
		}
		stmts[i] = stm
	}
	return stmts, nil
}

// CompilePrepare compiles prepared statement, allows placeholder as expr.
// The return values are compiled statement, parameter list and error.
func CompilePrepare(ctx context.Context, src string) (stmt.Statement, []*expression.ParamMarker, error) {
	log.Debug("compiling prepared", src)
	l := parser.NewLexer(src)
	l.SetCharsetInfo(getCtxCharsetInfo(ctx))
	l.SetPrepare()
	if parser.YYParse(l) != 0 {
		log.Errorf("compiling %s\n, error: %v", src, l.Errors()[0])
		return nil, nil, errors.Trace(l.Errors()[0])
	}
	sms := l.Stmts()
	if len(sms) != 1 {
		log.Warnf("compiling %s, error: prepared statement should have only one statement.", src)
		return nil, nil, nil
	}
	sm := sms[0]
	compiler := &optimizer.Compiler{}
	statement, err := compiler.Compile(sm)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	return statement, compiler.ParamMarkers(), nil
}

func prepareStmt(ctx context.Context, sqlText string) (stmtID uint32, paramCount int, fields []*field.ResultField, err error) {
	s := &stmts.PreparedStmt{
		InPrepare: true,
		SQLText:   sqlText,
	}
	_, err = runStmt(ctx, s, nil)
	return s.ID, len(s.Params), s.Fields, errors.Trace(err)
}

func executePreparedStmt(ctx context.Context, stmtID uint32, args ...interface{}) (rset.Recordset, error) {
	s := &stmts.ExecuteStmt{ID: stmtID}
	return runStmt(ctx, s, args...)
}

func dropPreparedStmt(ctx context.Context, stmtID uint32) error {
	s := &stmts.DeallocateStmt{ID: stmtID}
	_, err := runStmt(ctx, s, nil)
	return err
}

func runStmt(ctx context.Context, s stmt.Statement, args ...interface{}) (rset.Recordset, error) {
	var err error
	var rs rset.Recordset
	// before every execution, we must clear affectedrows.
	variable.GetSessionVars(ctx).SetAffectedRows(0)
	switch s.(type) {
	case *stmts.PreparedStmt:
		ps := s.(*stmts.PreparedStmt)
		return runPreparedStmt(ctx, ps)
	case *stmts.ExecuteStmt:
		es := s.(*stmts.ExecuteStmt)
		rs, err = runExecute(ctx, es, args...)
		if err != nil {
			return nil, errors.Trace(err)
		}
	default:
		if s.IsDDL() {
			err = ctx.FinishTxn(false)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
		stmt.BindExecArgs(ctx, args)
		rs, err = s.Exec(ctx)
		stmt.ClearExecArgs(ctx)
	}
	// MySQL DDL should be auto-commit
	if err == nil && (s.IsDDL() || autocommit.ShouldAutocommit(ctx)) {
		err = ctx.FinishTxn(false)
		// We should retry for autocommit
		if terror.ErrorEqual(err, kv.ErrConditionNotMatch) {
			return nil, ctx.(Session).Retry()
		}
	}
	return rs, errors.Trace(err)
}

func runExecute(ctx context.Context, es *stmts.ExecuteStmt, args ...interface{}) (rset.Recordset, error) {
	if len(args) > 0 {
		es.UsingVars = make([]expression.Expression, 0, len(args))
		for _, v := range args {
			var exp expression.Expression = &expression.Value{Val: v}
			es.UsingVars = append(es.UsingVars, exp)
		}
	}
	return es.Exec(ctx)
}

func runPreparedStmt(ctx context.Context, ps *stmts.PreparedStmt) (rset.Recordset, error) {
	SQLText, err := ps.GetSQL(ctx)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if len(SQLText) == 0 {
		// TODO: Empty sql should return error?
		return nil, nil
	}
	// compile SQLText
	stmt, params, err := CompilePrepare(ctx, SQLText)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ps.Params = params
	ps.SQLStmt = stmt
	rs, err := ps.Exec(ctx)
	return rs, errors.Trace(err)
}

// RegisterStore registers a kv storage with unique name and its associated Driver.
func RegisterStore(name string, driver kv.Driver) error {
	name = strings.ToLower(name)

	if _, ok := stores[name]; ok {
		return errors.Errorf("%s is already registered", name)
	}

	stores[name] = driver
	return nil
}

// RegisterLocalStore registers a local kv storage with unique name and its associated engine Driver.
func RegisterLocalStore(name string, driver engine.Driver) error {
	d := localstore.Driver{Driver: driver}
	return RegisterStore(name, d)
}

// NewStore creates a kv Storage with specific uri.
// The uri format must be engine://schema, like goleveldb://testpath
// Engine is the storage name registered with RegisterStore.
// Schema is the storage specific format.
func NewStore(uri string) (kv.Storage, error) {
	pos := strings.Index(uri, "://")
	if pos == -1 {
		return nil, errors.Errorf("invalid uri format, must engine://schema")
	}

	name := strings.ToLower(uri[0:pos])
	schema := uri[pos+3:]

	d, ok := stores[name]
	if !ok {
		return nil, errors.Errorf("invalid uri foramt, storage %s is not registered", name)
	}

	s, err := d.Open(schema)
	return s, errors.Trace(err)
}

var queryStmtTable = []string{"explain", "select", "show", "execute", "describe", "desc"}

func trimSQL(sql string) string {
	// Trim space.
	sql = strings.TrimSpace(sql)
	// Trim leading /*comment*/
	// There may be multiple comments
	for strings.HasPrefix(sql, "/*") {
		i := strings.Index(sql, "*/")
		if i != -1 && i < len(sql)+1 {
			sql = sql[i+2:]
			sql = strings.TrimSpace(sql)
			continue
		}
		break
	}
	// Trim leading '('. For `(select 1);` is also a query.
	return strings.TrimLeft(sql, "( ")
}

// IsQuery checks if a sql statement is a query statement.
func IsQuery(sql string) bool {
	sqlText := strings.ToLower(trimSQL(sql))
	for _, key := range queryStmtTable {
		if strings.HasPrefix(sqlText, key) {
			return true
		}
	}

	return false
}

func init() {
	// Register default memory and goleveldb storage
	RegisterLocalStore("memory", goleveldb.MemoryDriver{})
	RegisterLocalStore("goleveldb", goleveldb.Driver{})
	RegisterLocalStore("boltdb", boltdb.Driver{})

	// start pprof handlers
	if Debug {
		go http.ListenAndServe(PprofAddr, nil)
	}
}
<commit_msg>*: Address comment<commit_after>// Copyright 2013 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.

// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package tidb

import (
	"net/http"
	// For pprof
	_ "net/http/pprof"
	"strings"
	"sync"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/domain"
	"github.com/pingcap/tidb/expression"
	"github.com/pingcap/tidb/field"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/optimizer"
	"github.com/pingcap/tidb/parser"
	"github.com/pingcap/tidb/rset"
	"github.com/pingcap/tidb/sessionctx/autocommit"
	"github.com/pingcap/tidb/sessionctx/variable"
	"github.com/pingcap/tidb/stmt"
	"github.com/pingcap/tidb/stmt/stmts"
	"github.com/pingcap/tidb/store/localstore"
	"github.com/pingcap/tidb/store/localstore/boltdb"
	"github.com/pingcap/tidb/store/localstore/engine"
	"github.com/pingcap/tidb/store/localstore/goleveldb"
	"github.com/pingcap/tidb/terror"
)

// Engine prefix name
const (
	EngineGoLevelDBMemory     = "memory://"
	EngineGoLevelDBPersistent = "goleveldb://"
	EngineHBase               = "zk://"
	EngineBoltDB              = "boltdb://"
)

type domainMap struct {
	domains map[string]*domain.Domain
	mu      sync.Mutex
}

func (dm *domainMap) Get(store kv.Storage) (d *domain.Domain, err error) {
	key := store.UUID()
	dm.mu.Lock()
	defer dm.mu.Unlock()
	d = dm.domains[key]
	if d != nil {
		return
	}

	if SchemaLease <= minSchemaLease {
		SchemaLease = minSchemaLease
	}

	lease := SchemaLease
	// if storage is local storage, we may in test environment or
	// run server in single machine mode, so we don't need wait
	// 2 * lease time for DDL operation.
	if localstore.IsLocalStore(store) {
		lease = 0
	}
	d, err = domain.NewDomain(store, lease)
	if err != nil {
		return nil, errors.Trace(err)
	}
	dm.domains[key] = d
	return
}

var (
	domap = &domainMap{
		domains: map[string]*domain.Domain{},
	}
	stores = make(map[string]kv.Driver)
	// Debug is the switch for pprof. If Debug is true, tidb will start with pprof on.
	Debug = true
	// PprofAddr is the pprof url.
	PprofAddr = "localhost:8888"
	// store.UUID()-> IfBootstrapped
	storeBootstrapped = make(map[string]bool)

	// SchemaLease is the time(seconds) for re-updating remote schema.
	// In online DDL, we must wait 2 * SchemaLease time to guarantee
	// all servers get the neweset schema.
	SchemaLease    = 300
	minSchemaLease = 120
)

// What character set should the server translate a statement to after receiving it?
// For this, the server uses the character_set_connection and collation_connection system variables.
// It converts statements sent by the client from character_set_client to character_set_connection
// (except for string literals that have an introducer such as _latin1 or _utf8).
// collation_connection is important for comparisons of literal strings.
// For comparisons of strings with column values, collation_connection does not matter because columns
// have their own collation, which has a higher collation precedence.
// See: https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html
func getCtxCharsetInfo(ctx context.Context) (string, string) {
	sessionVars := variable.GetSessionVars(ctx)
	charset := sessionVars.Systems["character_set_connection"]
	collation := sessionVars.Systems["collation_connection"]
	return charset, collation
}

// Compile is safe for concurrent use by multiple goroutines.
func Compile(ctx context.Context, src string) ([]stmt.Statement, error) {
	log.Debug("compiling", src)
	l := parser.NewLexer(src)
	l.SetCharsetInfo(getCtxCharsetInfo(ctx))
	if parser.YYParse(l) != 0 {
		log.Warnf("compiling %s, error: %v", src, l.Errors()[0])
		return nil, errors.Trace(l.Errors()[0])
	}
	rawStmt := l.Stmts()
	stmts := make([]stmt.Statement, len(rawStmt))
	for i, v := range rawStmt {
		compiler := &optimizer.Compiler{}
		stm, err := compiler.Compile(v)
		if err != nil {
			return nil, errors.Trace(err)
		}
		stmts[i] = stm
	}
	return stmts, nil
}

// CompilePrepare compiles prepared statement, allows placeholder as expr.
// The return values are compiled statement, parameter list and error.
func CompilePrepare(ctx context.Context, src string) (stmt.Statement, []*expression.ParamMarker, error) {
	log.Debug("compiling prepared", src)
	l := parser.NewLexer(src)
	l.SetCharsetInfo(getCtxCharsetInfo(ctx))
	l.SetPrepare()
	if parser.YYParse(l) != 0 {
		log.Errorf("compiling %s\n, error: %v", src, l.Errors()[0])
		return nil, nil, errors.Trace(l.Errors()[0])
	}
	sms := l.Stmts()
	if len(sms) != 1 {
		log.Warnf("compiling %s, error: prepared statement should have only one statement.", src)
		return nil, nil, nil
	}
	sm := sms[0]
	compiler := &optimizer.Compiler{}
	statement, err := compiler.Compile(sm)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	return statement, compiler.ParamMarkers(), nil
}

func prepareStmt(ctx context.Context, sqlText string) (stmtID uint32, paramCount int, fields []*field.ResultField, err error) {
	s := &stmts.PreparedStmt{
		InPrepare: true,
		SQLText:   sqlText,
	}
	_, err = runStmt(ctx, s, nil)
	return s.ID, len(s.Params), s.Fields, errors.Trace(err)
}

func executePreparedStmt(ctx context.Context, stmtID uint32, args ...interface{}) (rset.Recordset, error) {
	s := &stmts.ExecuteStmt{ID: stmtID}
	return runStmt(ctx, s, args...)
}

func dropPreparedStmt(ctx context.Context, stmtID uint32) error {
	s := &stmts.DeallocateStmt{ID: stmtID}
	_, err := runStmt(ctx, s, nil)
	return err
}

func runStmt(ctx context.Context, s stmt.Statement, args ...interface{}) (rset.Recordset, error) {
	var err error
	var rs rset.Recordset
	// before every execution, we must clear affectedrows.
	variable.GetSessionVars(ctx).SetAffectedRows(0)
	switch s.(type) {
	case *stmts.PreparedStmt:
		ps := s.(*stmts.PreparedStmt)
		return runPreparedStmt(ctx, ps)
	case *stmts.ExecuteStmt:
		es := s.(*stmts.ExecuteStmt)
		rs, err = runExecute(ctx, es, args...)
		if err != nil {
			return nil, errors.Trace(err)
		}
	default:
		if s.IsDDL() {
			err = ctx.FinishTxn(false)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
		stmt.BindExecArgs(ctx, args)
		rs, err = s.Exec(ctx)
		stmt.ClearExecArgs(ctx)
	}
	// MySQL DDL should be auto-commit
	if err == nil && (s.IsDDL() || autocommit.ShouldAutocommit(ctx)) {
		err = ctx.FinishTxn(false)
		// We should retry for autocommit
		if terror.ErrorEqual(err, kv.ErrConditionNotMatch) {
			se, ok := ctx.(Session)
			if ok {
				return nil, se.Retry()
			}
		}
	}
	return rs, errors.Trace(err)
}

func runExecute(ctx context.Context, es *stmts.ExecuteStmt, args ...interface{}) (rset.Recordset, error) {
	if len(args) > 0 {
		es.UsingVars = make([]expression.Expression, 0, len(args))
		for _, v := range args {
			var exp expression.Expression = &expression.Value{Val: v}
			es.UsingVars = append(es.UsingVars, exp)
		}
	}
	return es.Exec(ctx)
}

func runPreparedStmt(ctx context.Context, ps *stmts.PreparedStmt) (rset.Recordset, error) {
	SQLText, err := ps.GetSQL(ctx)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if len(SQLText) == 0 {
		// TODO: Empty sql should return error?
		return nil, nil
	}
	// compile SQLText
	stmt, params, err := CompilePrepare(ctx, SQLText)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ps.Params = params
	ps.SQLStmt = stmt
	rs, err := ps.Exec(ctx)
	return rs, errors.Trace(err)
}

// RegisterStore registers a kv storage with unique name and its associated Driver.
func RegisterStore(name string, driver kv.Driver) error {
	name = strings.ToLower(name)

	if _, ok := stores[name]; ok {
		return errors.Errorf("%s is already registered", name)
	}

	stores[name] = driver
	return nil
}

// RegisterLocalStore registers a local kv storage with unique name and its associated engine Driver.
func RegisterLocalStore(name string, driver engine.Driver) error {
	d := localstore.Driver{Driver: driver}
	return RegisterStore(name, d)
}

// NewStore creates a kv Storage with specific uri.
// The uri format must be engine://schema, like goleveldb://testpath
// Engine is the storage name registered with RegisterStore.
// Schema is the storage specific format.
func NewStore(uri string) (kv.Storage, error) {
	pos := strings.Index(uri, "://")
	if pos == -1 {
		return nil, errors.Errorf("invalid uri format, must engine://schema")
	}

	name := strings.ToLower(uri[0:pos])
	schema := uri[pos+3:]

	d, ok := stores[name]
	if !ok {
		return nil, errors.Errorf("invalid uri foramt, storage %s is not registered", name)
	}

	s, err := d.Open(schema)
	return s, errors.Trace(err)
}

var queryStmtTable = []string{"explain", "select", "show", "execute", "describe", "desc"}

func trimSQL(sql string) string {
	// Trim space.
	sql = strings.TrimSpace(sql)
	// Trim leading /*comment*/
	// There may be multiple comments
	for strings.HasPrefix(sql, "/*") {
		i := strings.Index(sql, "*/")
		if i != -1 && i < len(sql)+1 {
			sql = sql[i+2:]
			sql = strings.TrimSpace(sql)
			continue
		}
		break
	}
	// Trim leading '('. For `(select 1);` is also a query.
	return strings.TrimLeft(sql, "( ")
}

// IsQuery checks if a sql statement is a query statement.
func IsQuery(sql string) bool {
	sqlText := strings.ToLower(trimSQL(sql))
	for _, key := range queryStmtTable {
		if strings.HasPrefix(sqlText, key) {
			return true
		}
	}

	return false
}

func init() {
	// Register default memory and goleveldb storage
	RegisterLocalStore("memory", goleveldb.MemoryDriver{})
	RegisterLocalStore("goleveldb", goleveldb.Driver{})
	RegisterLocalStore("boltdb", boltdb.Driver{})

	// start pprof handlers
	if Debug {
		go http.ListenAndServe(PprofAddr, nil)
	}
}
<|endoftext|>


<commit_before>package dns

import (
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/hex"
	"errors"
	"io"
	"net"
	"strconv"
)

// CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
	switch matchingType {
	case 0:
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw), nil
		case 1:
			return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
		}
	case 1:
		h := sha256.New()
		switch selector {
		case 0:
			io.WriteString(h, string(cert.Raw))
			return hex.EncodeToString(h.Sum(nil)), nil
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil)), nil
		}
	case 2:
		h := sha512.New()
		switch selector {
		case 0:
			io.WriteString(h, string(cert.Raw))
			return hex.EncodeToString(h.Sum(nil)), nil
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil)), nil
		}
	}
	return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector")
}

// Sign creates a TLSA record from an SSL certificate.
func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
	r.Hdr.Rrtype = TypeTLSA
	r.Usage = uint8(usage)
	r.Selector = uint8(selector)
	r.MatchingType = uint8(matchingType)

	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
	if err != nil {
		return err
	}
	return nil
}

// Verify verifies a TLSA record against an SSL certificate. If it is OK
// a nil error is returned.
func (r *TLSA) Verify(cert *x509.Certificate) error {
	c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
	if err != nil {
		return err // Not also ErrSig?
	}
	if r.Certificate == c {
		return nil
	}
	return ErrSig // ErrSig, really?
}

// TLSAName returns the ownername of a TLSA resource record as per the
// rules specified in RFC 6698, Section 3.
func TLSAName(name, service, network string) (string, error) {
	if !IsFqdn(name) {
		return "", ErrFqdn
	}
	p, e := net.LookupPort(network, service)
	if e != nil {
		return "", e
	}
	return "_" + strconv.Itoa(p) + "_" + network + "." + name, nil
}
<commit_msg>Missing dot between service and protocol.<commit_after>package dns

import (
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/hex"
	"errors"
	"io"
	"net"
	"strconv"
)

// CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
	switch matchingType {
	case 0:
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw), nil
		case 1:
			return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
		}
	case 1:
		h := sha256.New()
		switch selector {
		case 0:
			io.WriteString(h, string(cert.Raw))
			return hex.EncodeToString(h.Sum(nil)), nil
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil)), nil
		}
	case 2:
		h := sha512.New()
		switch selector {
		case 0:
			io.WriteString(h, string(cert.Raw))
			return hex.EncodeToString(h.Sum(nil)), nil
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil)), nil
		}
	}
	return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector")
}

// Sign creates a TLSA record from an SSL certificate.
func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
	r.Hdr.Rrtype = TypeTLSA
	r.Usage = uint8(usage)
	r.Selector = uint8(selector)
	r.MatchingType = uint8(matchingType)

	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
	if err != nil {
		return err
	}
	return nil
}

// Verify verifies a TLSA record against an SSL certificate. If it is OK
// a nil error is returned.
func (r *TLSA) Verify(cert *x509.Certificate) error {
	c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
	if err != nil {
		return err // Not also ErrSig?
	}
	if r.Certificate == c {
		return nil
	}
	return ErrSig // ErrSig, really?
}

// TLSAName returns the ownername of a TLSA resource record as per the
// rules specified in RFC 6698, Section 3.
func TLSAName(name, service, network string) (string, error) {
	if !IsFqdn(name) {
		return "", ErrFqdn
	}
	p, e := net.LookupPort(network, service)
	if e != nil {
		return "", e
	}
	return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil
}
<|endoftext|>


<commit_before>package dns

import (
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/hex"
	"io"
	"net"
	"strconv"
)

// TLSA support functions

// certToTLSACert returns the hex data suitable for inclusion in a TLSA record
func certToTLSACert(selector, matchingType uint8, cert *x509.Certificate) string {
	switch matchingType {
	case 0:
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw)
		case 1:
			return hex.EncodeToString(cert.RawSubjectPublicKeyInfo)
		}
	case 1:
		h := sha256.New()
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw)
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil))
		}
	case 2:
		h := sha512.New()
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw)
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil))
		}
	}
	return ""
}

// Sign creates a TLSA record from a SSL certificate.
func (r *RR_TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) error {
	r.Hdr.Rrtype = TypeTLSA
	r.Usage = uint8(usage)
	r.Selector = uint8(selector)
	r.MatchingType = uint8(matchingType)

	r.Certificate = certToTLSACert(r.Selector, r.MatchingType, cert)
	return nil
}

// Verify verifies a TLSA record against a SSL certificate. If it is OK
// a nil error is returned.
func (r *RR_TLSA) Verify(cert *x509.Certificate) error {
	if r.Certificate == certToTLSACert(r.Selector, r.MatchingType, cert) {
		return nil
	}
	return ErrSig	// ErrSig, really?
}

// TLSAName returns the ownername of a TLSA resource record as per the
// rules specified in RFC 6698, Section 3. When an erros occurs the
// empty string is returned.
func TLSAName(name, service, network string) string {
	if !IsFqdn(name) {
		return ""
	}
	p, e := net.LookupPort(network, service)
	if e != nil {
		return ""
	}
	return "_" + strconv.Itoa(p) + "_" + network + "." + name
}
<commit_msg>export this function as users will need it<commit_after>package dns

import (
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/hex"
	"io"
	"net"
	"strconv"
)

// TLSA support functions

// CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) string {
	switch matchingType {
	case 0:
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw)
		case 1:
			return hex.EncodeToString(cert.RawSubjectPublicKeyInfo)
		}
	case 1:
		h := sha256.New()
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw)
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil))
		}
	case 2:
		h := sha512.New()
		switch selector {
		case 0:
			return hex.EncodeToString(cert.Raw)
		case 1:
			io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
			return hex.EncodeToString(h.Sum(nil))
		}
	}
	return ""
}

// Sign creates a TLSA record from a SSL certificate.
func (r *RR_TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) error {
	r.Hdr.Rrtype = TypeTLSA
	r.Usage = uint8(usage)
	r.Selector = uint8(selector)
	r.MatchingType = uint8(matchingType)

	r.Certificate = CertificateToDANE(r.Selector, r.MatchingType, cert)
	return nil
}

// Verify verifies a TLSA record against a SSL certificate. If it is OK
// a nil error is returned.
func (r *RR_TLSA) Verify(cert *x509.Certificate) error {
	if r.Certificate == CertificateToDANE(r.Selector, r.MatchingType, cert) {
		return nil
	}
	return ErrSig	// ErrSig, really?
}

// TLSAName returns the ownername of a TLSA resource record as per the
// rules specified in RFC 6698, Section 3. When an erros occurs the
// empty string is returned.
func TLSAName(name, service, network string) string {
	if !IsFqdn(name) {
		return ""
	}
	p, e := net.LookupPort(network, service)
	if e != nil {
		return ""
	}
	return "_" + strconv.Itoa(p) + "_" + network + "." + name
}
<|endoftext|>


<commit_before>package tmdb

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	apiURL = "http://api.themoviedb.org/3/"
)

// TMDB values:
// apikey store your API key from themoviedb
type TMDB struct {
	apiKey string
}

// response of search/multi
type tmdbResponse struct {
	Page          int
	Results       []tmdbResult
	Total_pages   int
	Total_results int
}

// results format from Tmdb
type tmdbResult struct {
	Name              string
	Adult             bool
	Backdrop_path     string
	Genre_ids         []int64
	Id                int64
	Original_language string
	Original_title    string
	Overview          string
	Release_date      string
	Poster_path       string
	Popularity        float32
	Title             string
	Vote_average      float32
	Vote_count        int64
}

// Init tmbd to set API value
func Init(apiKey string) *TMDB {
	return &TMDB{apiKey: apiKey}
}

// GetByName get data from themoviedb by name
func (tmdb *TMDB) GetByName(movieName string) (string, error) {
	var response = &tmdbResponse{}
	resp, err := http.Get(apiURL + "search/movie?api_key=" + tmdb.apiKey + "&language=ru&query=" + url.QueryEscape(movieName))
	if err != nil {
		return "", err
	}
	if resp.StatusCode != 200 {
		return "", errorStatus(resp.StatusCode)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	err = json.Unmarshal(body, &response)
	if err == nil {
		fmt.Println(response)
	}
	return string(body), err
}

func errorStatus(status int) error {
	return fmt.Errorf("Status Code %d received from TMDb", status)
}
<commit_msg>search by name and year add sleep 1 sec<commit_after>package tmdb

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

const (
	apiURL = "http://api.themoviedb.org/3"
)

// TMDB values:
// apikey store your API key from themoviedb
type TMDB struct {
	apiKey string
	config *tmdbConfig
}

type tmdbConfig struct {
	Images tmdbImagesConfig
}

type tmdbImagesConfig struct {
	Base_url        string
	Secure_base_url string
	Backdrop_sizes  []string
	Logo_sizes      []string
	Poster_sizes    []string
	Profile_sizes   []string
	Still_sizes     []string
}

// response of search/multi
type tmdbResponse struct {
	Page          int
	Results       []tmdbResult
	Total_pages   int
	Total_results int
}

// results format from Tmdb
type tmdbResult struct {
	Name              string
	Adult             bool
	Backdrop_path     string
	Genre_ids         []int64
	Id                int64
	Original_language string
	Original_title    string
	Overview          string
	Release_date      string
	Poster_path       string
	Popularity        float32
	Title             string
	Vote_average      float32
	Vote_count        int64
	Poster_base_url string
}

// Init tmbd to set API value
func Init(apiKey string) *TMDB {
	return &TMDB{apiKey: apiKey}
}

// GetConfig get img configuration from themoviedb
func (tmdb *TMDB) getConfig() error {
	if tmdb.config == nil || tmdb.config.Images.Base_url == "" {
		config := &tmdbConfig{}
		resp, err := http.Get(apiURL + "/configuration?api_key=" + tmdb.apiKey)
		if err != nil {
			fmt.Println(err)
			return err
		}
		if resp.StatusCode != 200 {
			return fmt.Errorf("Status Code %d received from TMDb", resp.StatusCode)
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return err
		}
		err = json.Unmarshal(body, &config)
		if err != nil {
			fmt.Println(err)
			return err
		}
		tmdb.config = config
	}
	return nil
}

// GetByName get data from themoviedb by name
func (tmdb *TMDB) GetByName(movieName string, year string) (tmdbResult, error) {
	tmdb.getConfig()
	time.Sleep(1 * time.Second)
	var response = &tmdbResponse{}
	if year != "" {
		year = "&year=" + year
	}
	queryString := apiURL + "/search/movie?api_key=" + tmdb.apiKey + "&language=ru&query=" + url.QueryEscape(movieName) + year
	resp, err := http.Get(queryString)
	if err != nil {
		return tmdbResult{}, err
	}
	if resp.StatusCode != 200 {
		fmt.Println(resp.Header)
		return tmdbResult{}, fmt.Errorf("Status Code %d received from TMDb", resp.StatusCode)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return tmdbResult{}, err
	}
	err = json.Unmarshal(body, &response)
	if err != nil {
		return tmdbResult{}, err
	}
	if len(response.Results) == 0 {
		return tmdbResult{}, err
	}
	response.Results[0].Poster_base_url = tmdb.config.Images.Base_url
	return response.Results[0], err
}
<|endoftext|>


<commit_before>package slackevents

import (
	"encoding/json"

	"github.com/nlopes/slack"
)

type MessageActionResponse struct {
	ResponseType    string `json:"response_type"`
	ReplaceOriginal bool   `json:"replace_original"`
	Text            string `json:"text"`
}

type MessageActionEntity struct {
	Id     string `json:"id"`
	Domain string `json:"domain"`
}

type MessageAction struct {
	Type             string                   `json:"type"`
	Actions          []slack.AttachmentAction `json:"actions"`
	CallbackId       string                   `json:"callback_id"`
	Team             MessageActionEntity      `json:"team"`
	Channel          MessageActionEntity      `json:"channel"`
	User             MessageActionEntity      `json:"user"`
	ActionTimestamp  json.Number              `json:"action_ts"`
	MessageTimestamp json.Number              `json:"message_ts"`
	AttachmentId     json.Number              `json:"attachment_id"`
	Token            string                   `json:"token"`
	Message          slack.Message            `json:"message"`
	OriginalMessage  slack.Message            `json:"original_message"`
	ResponseUrl      string                   `json:"response_url"`
	TriggerId        string                   `json:"trigger_id"`
}
<commit_msg>Capitalize properties on MessageAction to match AttachmentActionCallback<commit_after>package slackevents

import (
	"encoding/json"

	"github.com/nlopes/slack"
)

type MessageActionResponse struct {
	ResponseType    string `json:"response_type"`
	ReplaceOriginal bool   `json:"replace_original"`
	Text            string `json:"text"`
}

type MessageActionEntity struct {
	ID     string `json:"id"`
	Domain string `json:"domain"`
}

type MessageAction struct {
	Type             string                   `json:"type"`
	Actions          []slack.AttachmentAction `json:"actions"`
	CallbackID       string                   `json:"callback_id"`
	Team             MessageActionEntity      `json:"team"`
	Channel          MessageActionEntity      `json:"channel"`
	User             MessageActionEntity      `json:"user"`
	ActionTimestamp  json.Number              `json:"action_ts"`
	MessageTimestamp json.Number              `json:"message_ts"`
	AttachmentID     json.Number              `json:"attachment_id"`
	Token            string                   `json:"token"`
	Message          slack.Message            `json:"message"`
	OriginalMessage  slack.Message            `json:"original_message"`
	ResponseURL      string                   `json:"response_url"`
	TriggerID        string                   `json:"trigger_id"`
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The tomb package helps with clean goroutine termination.
//
// See the Tomb type for details.
package tomb

import (
	"fmt"
	"os"
	"sync"
)

// A Tomb tracks the lifecycle of a goroutine as alive, dying or dead,
// and the reason for its death.
//
// The initial state of a Tomb informs that a goroutine is about to be
// created or already alive. Once Fatal or Fatalf is called with an
// argument that informs the reason for death, the goroutine is in
// a dying state and is expected to terminate soon. Right before the
// goroutine function or method returns, Done must be called to inform
// that the goroutine is indeed dead and about to stop running.
//
// A Tomb exposes Dying and Dead channels. These channels are closed
// when the Tomb state changes in the respective way. They enable
// explicit blocking until the state changes, and also to selectively
// unblock select statements accordingly.
//
// For background and a detailed example, see the following blog post:
//
//   http://blog.labix.org/2011/10/09/death-of-goroutines-under-control
//
type Tomb struct {
	m      sync.Mutex
	dying  chan struct{}
	dead   chan struct{}
	Dying  <-chan struct{}
	Dead   <-chan struct{}
	reason os.Error
}

// The Stop error is used as a reason for a goroutine to stop cleanly.
var Stop = os.NewError("clean stop")

// New creates a new Tomb to track the lifecycle of a goroutine
// that is already alive or about to be created.
func New() *Tomb {
	t := &Tomb{dying: make(chan struct{}), dead: make(chan struct{})}
	t.Dying = t.dying
	t.Dead = t.dead
	return t
}

// Wait blocks until the goroutine is in a dead state and returns the
// reason for its death. If the reason is Stop, nil is returned.
func (t *Tomb) Wait() os.Error {
	<-t.Dead
	if t.reason == Stop {
		return nil
	}
	return t.reason
}

// Done flags the goroutine as dead, and should be called a single time
// right before the goroutine function or method returns.
// If the goroutine was not already in a dying state before Done is
// called, it will flagged as dying and dead at once with Stop as the
// reason for death.
func (t *Tomb) Done() {
	t.Fatal(Stop)
	close(t.dead)
}

// Fatal flags the goroutine as dying for the given reason.
// Fatal may be called multiple times, but only the first error is
// recorded as the reason for termination. If no errors are found,
// the reason for termination is Stop.
func (t *Tomb) Fatal(reason os.Error) {
	if reason == nil {
		panic("Fatal with nil reason")
	}
	t.m.Lock()
	if t.reason == nil || t.reason == Stop {
		t.reason = reason
	}
	select {
	case <-t.Dying:
	default:
		close(t.dying)
	}
	t.m.Unlock()
}

// Fatalf works like Fatal, but builds the reason providing the received
// arguments to fmt.Errorf. The generated error is also returned.
func (t *Tomb) Fatalf(format string, args ...interface{}) os.Error {
	err := fmt.Errorf(format, args...)
	t.Fatal(err)
	return err
}

// Err returns the reason for the goroutine death provided via Fatal
// or Fatalf. If no actual error was provided to Fatal or Fatalf, the
// reason will be Stop.
// The result is guaranteed not to be nil if the Tomb is flagging to
// goroutine as dying or dead.
func (t *Tomb) Err() (reason os.Error) {
	t.m.Lock()
	reason = t.reason
	t.m.Unlock()
	return
}
<commit_msg>Simplified doc for Err.<commit_after>// Copyright (c) 2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The tomb package helps with clean goroutine termination.
//
// See the Tomb type for details.
package tomb

import (
	"fmt"
	"os"
	"sync"
)

// A Tomb tracks the lifecycle of a goroutine as alive, dying or dead,
// and the reason for its death.
//
// The initial state of a Tomb informs that a goroutine is about to be
// created or already alive. Once Fatal or Fatalf is called with an
// argument that informs the reason for death, the goroutine is in
// a dying state and is expected to terminate soon. Right before the
// goroutine function or method returns, Done must be called to inform
// that the goroutine is indeed dead and about to stop running.
//
// A Tomb exposes Dying and Dead channels. These channels are closed
// when the Tomb state changes in the respective way. They enable
// explicit blocking until the state changes, and also to selectively
// unblock select statements accordingly.
//
// For background and a detailed example, see the following blog post:
//
//   http://blog.labix.org/2011/10/09/death-of-goroutines-under-control
//
type Tomb struct {
	m      sync.Mutex
	dying  chan struct{}
	dead   chan struct{}
	Dying  <-chan struct{}
	Dead   <-chan struct{}
	reason os.Error
}

// The Stop error is used as a reason for a goroutine to stop cleanly.
var Stop = os.NewError("clean stop")

// New creates a new Tomb to track the lifecycle of a goroutine
// that is already alive or about to be created.
func New() *Tomb {
	t := &Tomb{dying: make(chan struct{}), dead: make(chan struct{})}
	t.Dying = t.dying
	t.Dead = t.dead
	return t
}

// Wait blocks until the goroutine is in a dead state and returns the
// reason for its death. If the reason is Stop, nil is returned.
func (t *Tomb) Wait() os.Error {
	<-t.Dead
	if t.reason == Stop {
		return nil
	}
	return t.reason
}

// Done flags the goroutine as dead, and should be called a single time
// right before the goroutine function or method returns.
// If the goroutine was not already in a dying state before Done is
// called, it will flagged as dying and dead at once with Stop as the
// reason for death.
func (t *Tomb) Done() {
	t.Fatal(Stop)
	close(t.dead)
}

// Fatal flags the goroutine as dying for the given reason.
// Fatal may be called multiple times, but only the first error is
// recorded as the reason for termination. If no errors are found,
// the reason for termination is Stop.
func (t *Tomb) Fatal(reason os.Error) {
	if reason == nil {
		panic("Fatal with nil reason")
	}
	t.m.Lock()
	if t.reason == nil || t.reason == Stop {
		t.reason = reason
	}
	select {
	case <-t.Dying:
	default:
		close(t.dying)
	}
	t.m.Unlock()
}

// Fatalf works like Fatal, but builds the reason providing the received
// arguments to fmt.Errorf. The generated error is also returned.
func (t *Tomb) Fatalf(format string, args ...interface{}) os.Error {
	err := fmt.Errorf(format, args...)
	t.Fatal(err)
	return err
}

// Err returns the reason for the goroutine death provided via Fatal
// or Fatalf, or nil in case the goroutine is still alive.
func (t *Tomb) Err() (reason os.Error) {
	t.m.Lock()
	reason = t.reason
	t.m.Unlock()
	return
}
<|endoftext|>


<commit_before>package main
import(
	"github.com/draringi/synthia/waveforms"
	)

type ToneGenerator struct {
	sampleRate float64
	step float64 //delta t
	wave waveforms.Wave
}

func NewToneGenerator(sampleRate float64, wave waveforms.Wave) *ToneGenerator {
	if sampleRate < 1 {
		return nil
	}
	t := new(ToneGenerator)
	t.sampleRate = sampleRate
	t.step = 1/sampleRate
	t.wave = wave
	return t
}

//Generates a square wave
func (t *ToneGenerator) Tone(freq, seconds float64, vol int32) []int32{
	var synthArray = make([]int32, int(seconds*t.sampleRate))

	for i:=0; i < len(synthArray); i++ {
		synthArray[i]=int32(t.wave(float64(i)*t.step)*float64(vol));
	}
	return synthArray
}<commit_msg>Merging<commit_after>package main
import(
	"github.com/draringi/synthia/waveforms"
	)

type ToneGenerator struct {
	sampleRate float64
	step float64 //delta t
	wave waveforms.Wave
}

func NewToneGenerator(sampleRate float64, wave waveforms.Wave) *ToneGenerator {
	if sampleRate < 1 {
		return nil
	}
	t := new(ToneGenerator)
	t.sampleRate = sampleRate
	t.step = 1/sampleRate
	t.wave = wave
	return t
}

//Generates a square wave
func (t *ToneGenerator) Tone(freq, seconds float64, vol int32) []int32{
	var synthArray = make([]int32, int(seconds*t.sampleRate))

	for i:=0; i < len(synthArray); i++ {
		synthArray[i]=int32(t.wave(float64(i)*t.step)*float64(vol));

	}
	return synthArray
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/build"
	"log"
	"os"
	"os/exec"
	//"runtime"
	"path"
	"strings"
)

func init() {
	log.SetPrefix("goblin:\t  ")
	log.SetFlags(0)
}

func getPkgPath() (string, error) {
	p, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	cmd := exec.Command("go", "tool", "objdump", "-s=main.main", p)
	out, err := cmd.Output()
	if err != nil {
		return "", err
	}

	s := strings.SplitN(fmt.Sprintf("%s", out), "\n", 2)[0]
	s = s[len("TEXT main.main(SB) "):]

	return s[:len(s)-len("/install.go")], nil
}

func usage() (s string) {
	install := "install:\tinstalls the goblin tools to $GOTOOLDIR"
	return fmt.Sprintln(install)
}

func main() {
	if len(os.Args) == 1 {
		log.Println(usage())
		return
	}
	for _, arg := range os.Args[1:] {
		switch arg {
		case "install":
			install()
		default:
			log.Println("invalid input arg:", arg)
			log.Println(usage())
			return
		}
	}
}

func install() {
	if p, err := getPkgPath(); err != nil {
		log.Fatal(err)
	} else {
		if err := os.Chdir(p); err != nil {
			log.Fatal(err)
		}
	}

	if err := os.Chdir("cmd"); err != nil {
		log.Fatal(err)
	}
	f, err := os.Open(".")
	if err != nil {
		log.Fatal(err)
	}
	dirs, err := f.Readdirnames(0)
	if err != nil {
		log.Fatal(err)
	}
	for _, d := range dirs {
		if err := os.Chdir(d); err != nil {
			log.Fatal(err)
		}
		if d, err := os.Getwd(); err != nil {
			log.Fatal(err)
		} else {
			log.Println(d)
			nm := path.Base(d)
			out, err := exec.Command("go", "build").CombinedOutput()
			if err != nil {
				log.Printf("go build %s failed\n\n", nm)
				fmt.Fprintf(os.Stderr, "[go-build-log]\n%s", out)
				goto quit
			}

			log.Printf("mv %s to $GOTOOLDIR\n", nm)
			if err := os.Rename(d+"/"+nm, build.ToolDir+"/"+nm); err != nil {
				log.Fatal(err)
			}
		}
	quit:
		if err := os.Chdir(".."); err != nil {
			log.Fatal(err)
		}
		fmt.Println()
	}
}
<commit_msg>changed hardcoded filename value that broke stuff<commit_after>package main

import (
	"fmt"
	"go/build"
	"log"
	"os"
	"os/exec"
	//"runtime"
	"path"
	"strings"
)

func init() {
	log.SetPrefix("goblin:\t  ")
	log.SetFlags(0)
}

func getPkgPath() (string, error) {
	p, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	cmd := exec.Command("go", "tool", "objdump", "-s=main.main", p)
	out, err := cmd.Output()
	if err != nil {
		return "", err
	}

	s := strings.SplitN(fmt.Sprintf("%s", out), "\n", 2)[0]
	s = s[len("TEXT main.main(SB) "):]

	//makesure this source file's name matches whats hardcoded here.
	// Otherwise things break.
	return s[:len(s)-len("/tool.go")], nil
}

func usage() (s string) {
	install := "install:\tinstalls the goblin tools to $GOTOOLDIR"
	return fmt.Sprintln(install)
}

func main() {
	if len(os.Args) == 1 {
		log.Println(usage())
		return
	}
	for _, arg := range os.Args[1:] {
		switch arg {
		case "install":
			install()
		default:
			log.Println("invalid input arg:", arg)
			log.Println(usage())
			return
		}
	}
}

func install() {
	if p, err := getPkgPath(); err != nil {
		log.Fatal(err)
	} else {
		if err := os.Chdir(p); err != nil {
			log.Fatal(err)
		}
	}

	if err := os.Chdir("cmd"); err != nil {
		log.Fatal(err)
	}
	f, err := os.Open(".")
	if err != nil {
		log.Fatal(err)
	}
	dirs, err := f.Readdirnames(0)
	if err != nil {
		log.Fatal(err)
	}
	for _, d := range dirs {
		if err := os.Chdir(d); err != nil {
			log.Fatal(err)
		}
		if d, err := os.Getwd(); err != nil {
			log.Fatal(err)
		} else {
			log.Println(d)
			nm := path.Base(d)
			out, err := exec.Command("go", "build").CombinedOutput()
			if err != nil {
				log.Printf("go build %s failed\n\n", nm)
				fmt.Fprintf(os.Stderr, "[go-build-log]\n%s", out)
				goto quit
			}

			log.Printf("mv %s to $GOTOOLDIR\n", nm)
			if err := os.Rename(d+"/"+nm, build.ToolDir+"/"+nm); err != nil {
				log.Fatal(err)
			}
		}
	quit:
		if err := os.Chdir(".."); err != nil {
			log.Fatal(err)
		}
		fmt.Println()
	}
}
<|endoftext|>