<commit_before>package auth

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/mail"
	"strings"

	"gopkg.in/ldap.v2"
)

//SecurityType specifies how to connect to an Active Directory server
type SecurityType int

//Security will default to SecurityNone if not given.
const (
	SecurityNone SecurityType = iota
	SecurityTLS
	SecurityStartTLS
)

//ConfigError is an error resulting from a bad Config
type ConfigError string

func (c ConfigError) Error() string {
	return string(c)
}

//LDAPError is a generic LDAP error
type LDAPError string

func (l LDAPError) Error() string {
	return string(l)
}

//Config contains settings for connecting to an Active Directory server
type Config struct {
	Server    string
	Port      int
	BaseDN    string
	Security  SecurityType
	TLSConfig *tls.Config
	Debug     bool //debug messages are written to stdout
}

//Connect returns an open connection to an Active Directory server specified by the given config
func (c *Config) Connect() (*ldap.Conn, error) {
	if c.TLSConfig == nil {
		c.TLSConfig = &tls.Config{
			ServerName: c.Server,
		}
	}

	switch c.Security {
	case SecurityNone:
		conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", c.Server, c.Port))
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		return conn, nil
	case SecurityTLS:
		conn, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", c.Server, c.Port), c.TLSConfig)
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		return conn, nil
	case SecurityStartTLS:
		conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", c.Server, c.Port))
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		err = conn.StartTLS(c.TLSConfig)
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		return conn, nil
	default:
		return nil, ConfigError("Invalid Security setting")
	}
}

func getDomain(BaseDN string) (string, error) {
	domain := ""
	for _, v := range strings.Split(strings.ToLower(BaseDN), ",") {
		if trimmed := strings.TrimSpace(v); strings.HasPrefix(trimmed, "dc=") {
			domain = domain + "." + trimmed[3:]
		}
	}
	if len(domain) <= 1 {
		return "", ConfigError("Invalid BaseDN")
	}
	return domain[1:], nil
}

func getDN(cn string, config *Config, conn *ldap.Conn) (string, error) {
	search := ldap.NewSearchRequest(
		config.BaseDN,
		ldap.ScopeWholeSubtree,
		ldap.DerefAlways,
		1, 0,
		false,
		fmt.Sprintf("(cn=%s)", cn),
		nil,
		nil,
	)
	result, err := conn.Search(search)
	if err != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", err)
		}
		return "", err
	}
	if len(result.Entries) > 0 {
		return result.Entries[0].DN, nil
	}
	return "", ConfigError(fmt.Sprintf("No DN found for: %s", cn))
}

func attrsToMap(entry *ldap.Entry) map[string][]string {
	m := make(map[string][]string)
	for _, attr := range entry.Attributes {
		m[attr.Name] = attr.Values
	}
	return m
}

func inGroup(upn, group string, config *Config, conn *ldap.Conn, attrs []string) (bool, map[string][]string, error) {
	groupDN, err := getDN(group, config, conn)
	if err != nil {
		if config.Debug {
			log.Printf("DEBUG: Error: %s\n", err)
		}
		return false, nil, err
	}
	search := ldap.NewSearchRequest(
		config.BaseDN,
		ldap.ScopeWholeSubtree,
		ldap.DerefAlways,
		1, 0,
		false,
		fmt.Sprintf("(userPrincipalName=%s)", upn),
		append(attrs, "memberOf"),
		nil,
	)
	result, lErr := conn.Search(search)
	if lErr != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", lErr)
		}
		return false, nil, lErr
	}
	if len(result.Entries) == 1 {
		entryAttrs := attrsToMap(result.Entries[0])
		if groups, ok := entryAttrs["memberOf"]; ok {
			for _, g := range groups {
				if groupDN == g {
					for _, key := range attrs {
						if key == "memberOf" {
							return true, entryAttrs, nil
						}
					}
					delete(entryAttrs, "memberOf")
					return true, entryAttrs, nil
				}
			}
		}
		return false, entryAttrs, nil
	}
	return false, nil, LDAPError("Amount of Entries returned was not one")
}

func getAttrs(upn string, config *Config, conn *ldap.Conn, attrs []string) (map[string][]string, error) {
	search := ldap.NewSearchRequest(
		config.BaseDN,
		ldap.ScopeWholeSubtree,
		ldap.DerefAlways,
		1, 0,
		false,
		fmt.Sprintf("(userPrincipalName=%s)", upn),
		attrs,
		nil,
	)
	result, lErr := conn.Search(search)
	if lErr != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", lErr)
		}
		return nil, lErr
	}
	if len(result.Entries) == 1 {
		return attrsToMap(result.Entries[0]), nil
	}
	return nil, LDAPError("Amount of Entries returned was not one")
}

/*
Login will check if the given username and password authenticate
correctly with server given by config.
username can be in the sAMAccountName or userPrincipalName format.
If group is not an empty string then Login will verify that the user
is in the Active Directory Group with the Common Name group.
error will be non-nil if some sort of server error occurred.
*/
func Login(username, password, group string, config *Config) (bool, error) {
	ok, _, err := LoginWithAttrs(username, password, group, config, nil)
	return ok, err
}

/*
LoginWithAttrs will function exectly like Login, but will return a given
list of attributes for the user if login is successful.
*/
func LoginWithAttrs(username, password, group string, config *Config, attrs []string) (bool, map[string][]string, error) {
	if password == "" {
		return false, nil, nil
	}
	conn, err := config.Connect()
	if err != nil {
		return false, nil, err
	}
	defer conn.Close()

	domain, err := getDomain(config.BaseDN)
	if err != nil {
		return false, nil, err
	}

	var upn string
	if _, err := mail.ParseAddress(username); err == nil {
		upn = username
	} else {
		upn = fmt.Sprintf("%s@%s", username, domain)
	}

	lErr := conn.Bind(upn, password)
	if lErr != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", lErr)
		}
		if e, ok := lErr.(*ldap.Error); ok {
			if e.ResultCode == ldap.LDAPResultInvalidCredentials {
				return false, nil, nil
			}
		}
		return false, nil, lErr
	}
	if group != "" {
		return inGroup(upn, group, config, conn, attrs)
	}
	entryAttrs, err := getAttrs(upn, config, conn, attrs)
	if err != nil {
		return false, nil, err
	}
	return true, entryAttrs, nil
}
<commit_msg>fix overshadowed variable<commit_after>package auth

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/mail"
	"strings"

	"gopkg.in/ldap.v2"
)

//SecurityType specifies how to connect to an Active Directory server
type SecurityType int

//Security will default to SecurityNone if not given.
const (
	SecurityNone SecurityType = iota
	SecurityTLS
	SecurityStartTLS
)

//ConfigError is an error resulting from a bad Config
type ConfigError string

func (c ConfigError) Error() string {
	return string(c)
}

//LDAPError is a generic LDAP error
type LDAPError string

func (l LDAPError) Error() string {
	return string(l)
}

//Config contains settings for connecting to an Active Directory server
type Config struct {
	Server    string
	Port      int
	BaseDN    string
	Security  SecurityType
	TLSConfig *tls.Config
	Debug     bool //debug messages are written to stdout
}

//Connect returns an open connection to an Active Directory server specified by the given config
func (c *Config) Connect() (*ldap.Conn, error) {
	if c.TLSConfig == nil {
		c.TLSConfig = &tls.Config{
			ServerName: c.Server,
		}
	}

	switch c.Security {
	case SecurityNone:
		conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", c.Server, c.Port))
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		return conn, nil
	case SecurityTLS:
		conn, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", c.Server, c.Port), c.TLSConfig)
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		return conn, nil
	case SecurityStartTLS:
		conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", c.Server, c.Port))
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		err = conn.StartTLS(c.TLSConfig)
		if err != nil {
			if c.Debug {
				log.Printf("DEBUG: LDAP Error %v\n", err)
			}
			return nil, err
		}
		return conn, nil
	default:
		return nil, ConfigError("Invalid Security setting")
	}
}

func getDomain(BaseDN string) (string, error) {
	domain := ""
	for _, v := range strings.Split(strings.ToLower(BaseDN), ",") {
		if trimmed := strings.TrimSpace(v); strings.HasPrefix(trimmed, "dc=") {
			domain = domain + "." + trimmed[3:]
		}
	}
	if len(domain) <= 1 {
		return "", ConfigError("Invalid BaseDN")
	}
	return domain[1:], nil
}

func getDN(cn string, config *Config, conn *ldap.Conn) (string, error) {
	search := ldap.NewSearchRequest(
		config.BaseDN,
		ldap.ScopeWholeSubtree,
		ldap.DerefAlways,
		1, 0,
		false,
		fmt.Sprintf("(cn=%s)", cn),
		nil,
		nil,
	)
	result, err := conn.Search(search)
	if err != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", err)
		}
		return "", err
	}
	if len(result.Entries) > 0 {
		return result.Entries[0].DN, nil
	}
	return "", ConfigError(fmt.Sprintf("No DN found for: %s", cn))
}

func attrsToMap(entry *ldap.Entry) map[string][]string {
	m := make(map[string][]string)
	for _, attr := range entry.Attributes {
		m[attr.Name] = attr.Values
	}
	return m
}

func inGroup(upn, group string, config *Config, conn *ldap.Conn, attrs []string) (bool, map[string][]string, error) {
	groupDN, err := getDN(group, config, conn)
	if err != nil {
		if config.Debug {
			log.Printf("DEBUG: Error: %s\n", err)
		}
		return false, nil, err
	}
	search := ldap.NewSearchRequest(
		config.BaseDN,
		ldap.ScopeWholeSubtree,
		ldap.DerefAlways,
		1, 0,
		false,
		fmt.Sprintf("(userPrincipalName=%s)", upn),
		append(attrs, "memberOf"),
		nil,
	)
	result, lErr := conn.Search(search)
	if lErr != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", lErr)
		}
		return false, nil, lErr
	}
	if len(result.Entries) == 1 {
		entryAttrs := attrsToMap(result.Entries[0])
		if groups, ok := entryAttrs["memberOf"]; ok {
			for _, g := range groups {
				if groupDN == g {
					for _, key := range attrs {
						if key == "memberOf" {
							return true, entryAttrs, nil
						}
					}
					delete(entryAttrs, "memberOf")
					return true, entryAttrs, nil
				}
			}
		}
		return false, entryAttrs, nil
	}
	return false, nil, LDAPError("Amount of Entries returned was not one")
}

func getAttrs(upn string, config *Config, conn *ldap.Conn, attrs []string) (map[string][]string, error) {
	search := ldap.NewSearchRequest(
		config.BaseDN,
		ldap.ScopeWholeSubtree,
		ldap.DerefAlways,
		1, 0,
		false,
		fmt.Sprintf("(userPrincipalName=%s)", upn),
		attrs,
		nil,
	)
	result, lErr := conn.Search(search)
	if lErr != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", lErr)
		}
		return nil, lErr
	}
	if len(result.Entries) == 1 {
		return attrsToMap(result.Entries[0]), nil
	}
	return nil, LDAPError("Amount of Entries returned was not one")
}

/*
Login will check if the given username and password authenticate
correctly with server given by config.
username can be in the sAMAccountName or userPrincipalName format.
If group is not an empty string then Login will verify that the user
is in the Active Directory Group with the Common Name group.
error will be non-nil if some sort of server error occurred.
*/
func Login(username, password, group string, config *Config) (bool, error) {
	ok, _, err := LoginWithAttrs(username, password, group, config, nil)
	return ok, err
}

/*
LoginWithAttrs will function exectly like Login, but will return a given
list of attributes for the user if login is successful.
*/
func LoginWithAttrs(username, password, group string, config *Config, attrs []string) (bool, map[string][]string, error) {
	if password == "" {
		return false, nil, nil
	}
	conn, err := config.Connect()
	if err != nil {
		return false, nil, err
	}
	defer conn.Close()

	domain, err := getDomain(config.BaseDN)
	if err != nil {
		return false, nil, err
	}

	var upn string
	if _, err = mail.ParseAddress(username); err == nil {
		upn = username
	} else {
		upn = fmt.Sprintf("%s@%s", username, domain)
	}

	lErr := conn.Bind(upn, password)
	if lErr != nil {
		if config.Debug {
			log.Printf("DEBUG: LDAP Error %v\n", lErr)
		}
		if e, ok := lErr.(*ldap.Error); ok {
			if e.ResultCode == ldap.LDAPResultInvalidCredentials {
				return false, nil, nil
			}
		}
		return false, nil, lErr
	}
	if group != "" {
		return inGroup(upn, group, config, conn, attrs)
	}
	entryAttrs, err := getAttrs(upn, config, conn, attrs)
	if err != nil {
		return false, nil, err
	}
	return true, entryAttrs, nil
}
<|endoftext|>


<commit_before>package beegoHelper

import (
	"encoding/base64"
	"strings"
)

func (this *Base) CheckBaseAuth(cred string) bool {
	this.Ctx.Output.Header("WWW-Authenticate", `Basic realm="Authenticate"`)
	s := strings.SplitN(this.Ctx.Input.Header("Authorization"), " ", 2)
	if len(s) != 2 {
		return false
	}

	b, err := base64.StdEncoding.DecodeString(s[1])
	if err != nil {
		return false
	}

	pair := strings.SplitN(string(b), ":", 2)
	if len(pair) != 2 {
		return false
	}

	user := strings.Split(cred, ":")
	return pair[0] == user[0] && pair[1] == user[1]
}
<commit_msg>add banner string to checkAuth<commit_after>package beegoHelper

import (
	"encoding/base64"
	"strings"
)

func (this *Base) CheckBaseAuth(cred string, banner string) bool {
	this.Ctx.Output.Header("WWW-Authenticate", `Basic realm="`+banner+`"`)
	s := strings.SplitN(this.Ctx.Input.Header("Authorization"), " ", 2)
	if len(s) != 2 {
		return false
	}

	b, err := base64.StdEncoding.DecodeString(s[1])
	if err != nil {
		return false
	}

	pair := strings.SplitN(string(b), ":", 2)
	if len(pair) != 2 {
		return false
	}

	user := strings.Split(cred, ":")
	return pair[0] == user[0] && pair[1] == user[1]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/bgentry/heroku-go"
	"github.com/bgentry/speakeasy"
	"github.com/heroku/hk/term"
)

var cmdCreds = &Command{
	Run:      runCreds,
	Usage:    "creds",
	Category: "hk",
	Short:    "show credentials" + extra,
	Long:     `Creds shows credentials that will be used for API calls.`,
}

func runCreds(cmd *Command, args []string) {
	fmt.Println(getCreds(apiURL))
}

var cmdLogin = &Command{
	Run:      runLogin,
	Usage:    "login <email>",
	Category: "hk",
	Short:    "log in to your Heroku account" + extra,
	Long: `
Log in with your Heroku credentials. Input is accepted by typing
on the terminal. On unix machines, you can also pipe a password
on standard input.

Example:

    $ hk login user@test.com
    Enter password:
    Login successful.
`,
}

func runLogin(cmd *Command, args []string) {
	if len(args) != 1 {
		cmd.printUsage()
		os.Exit(2)
	}
	username := args[0]

	// NOTE: gopass doesn't support multi-byte chars on Windows
	password, err := readPassword("Enter password: ")
	if err != nil {
		printError("reading password: " + err.Error())
	}

	description := "hk login from " + time.Now().UTC().Format(time.RFC3339)
	expires := 2592000 // 30 days
	opts := heroku.OAuthAuthorizationCreateOpts{
		Description: &description,
		ExpiresIn:   &expires,
	}

	req, err := client.NewRequest("POST", "/oauth/authorizations", &opts)
	if err != nil {
		printError("unknown error when creating login request: %s", err.Error())
	}
	req.SetBasicAuth(username, password)

	var auth heroku.OAuthAuthorization
	err = client.DoReq(req, &auth)
	must(err)

	if auth.AccessToken == nil {
		printError("access token missing from Heroku API login response")
	}
	err = saveCreds(strings.Split(req.Host, ":")[0], username, auth.AccessToken.Token)
	if err != nil {
		printError("saving new token: " + err.Error())
	}
	fmt.Println("Logged in.")
}

func readPassword(prompt string) (password string, err error) {
	if acceptPasswordFromStdin && !term.IsTerminal(os.Stdin) {
		_, err = fmt.Scanln(&password)
		return
	}
	// NOTE: gopass doesn't support multi-byte chars on Windows
	return speakeasy.Ask("Enter password: ")
}

var cmdLogout = &Command{
	Run:      runLogout,
	Usage:    "logout",
	Category: "hk",
	Short:    "log out of your Heroku account" + extra,
	Long: `
Log out of your Heroku account and remove credentials from
this machine.

Example:

    $ hk logout
    Logged out.
`,
}

func runLogout(cmd *Command, args []string) {
	if len(args) != 0 {
		cmd.printUsage()
		os.Exit(2)
	}
	u, err := url.Parse(client.URL)
	if err != nil {
		printError("couldn't parse client URL: " + err.Error())
	}
	err = removeCreds(strings.Split(u.Host, ":")[0])
	if err != nil {
		printError("saving new netrc: " + err.Error())
	}
	fmt.Println("Logged out.")
}
<commit_msg>2FA login support<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/bgentry/heroku-go"
	"github.com/bgentry/speakeasy"
	"github.com/heroku/hk/term"
)

var cmdCreds = &Command{
	Run:      runCreds,
	Usage:    "creds",
	Category: "hk",
	Short:    "show credentials" + extra,
	Long:     `Creds shows credentials that will be used for API calls.`,
}

func runCreds(cmd *Command, args []string) {
	fmt.Println(getCreds(apiURL))
}

var cmdLogin = &Command{
	Run:      runLogin,
	Usage:    "login <email>",
	Category: "hk",
	Short:    "log in to your Heroku account" + extra,
	Long: `
Log in with your Heroku credentials. Input is accepted by typing
on the terminal. On unix machines, you can also pipe a password
on standard input.

Example:

    $ hk login user@test.com
    Enter password:
    Login successful.
`,
}

func runLogin(cmd *Command, args []string) {
	if len(args) != 1 {
		cmd.printUsage()
		os.Exit(2)
	}
	username := args[0]

	// NOTE: gopass doesn't support multi-byte chars on Windows
	password, err := readPassword("Enter password: ")
	if err != nil {
		printError("reading password: " + err.Error())
	}

	hostname, token, err := attemptLogin(username, password, "")
	if err != nil {
		if herror, ok := err.(heroku.Error); ok && herror.Id == "two_factor" {
			// 2FA requested, attempt 2FA login
			var twoFactorCode string
			fmt.Printf("Enter two-factor auth code: ")
			_, err := fmt.Scanln(&twoFactorCode)
			if err != nil {
				printError("reading two-factor auth code: " + err.Error())
			}
			hostname, token, err = attemptLogin(username, password, twoFactorCode)
			must(err)
		} else {
			must(err)
		}
	}

	err = saveCreds(hostname, username, token)
	if err != nil {
		printError("saving new token: " + err.Error())
	}
	fmt.Println("Logged in.")
}

func readPassword(prompt string) (password string, err error) {
	if acceptPasswordFromStdin && !term.IsTerminal(os.Stdin) {
		_, err = fmt.Scanln(&password)
		return
	}
	// NOTE: speakeasy may not support multi-byte chars on Windows
	return speakeasy.Ask("Enter password: ")
}

func attemptLogin(username, password, twoFactorCode string) (hostname, token string, err error) {
	description := "hk login from " + time.Now().UTC().Format(time.RFC3339)
	expires := 2592000 // 30 days
	opts := heroku.OAuthAuthorizationCreateOpts{
		Description: &description,
		ExpiresIn:   &expires,
	}

	req, err := client.NewRequest("POST", "/oauth/authorizations", &opts)
	if err != nil {
		return "", "", fmt.Errorf("unknown error when creating login request: %s", err.Error())
	}
	req.SetBasicAuth(username, password)

	if twoFactorCode != "" {
		req.Header.Set("Heroku-Two-Factor-Code", twoFactorCode)
	}

	var auth heroku.OAuthAuthorization
	if err = client.DoReq(req, &auth); err != nil {
		return
	}
	if auth.AccessToken == nil {
		return "", "", fmt.Errorf("access token missing from Heroku API login response")
	}
	return strings.Split(req.Host, ":")[0], auth.AccessToken.Token, nil
}

var cmdLogout = &Command{
	Run:      runLogout,
	Usage:    "logout",
	Category: "hk",
	Short:    "log out of your Heroku account" + extra,
	Long: `
Log out of your Heroku account and remove credentials from
this machine.

Example:

    $ hk logout
    Logged out.
`,
}

func runLogout(cmd *Command, args []string) {
	if len(args) != 0 {
		cmd.printUsage()
		os.Exit(2)
	}
	u, err := url.Parse(client.URL)
	if err != nil {
		printError("couldn't parse client URL: " + err.Error())
	}
	err = removeCreds(strings.Split(u.Host, ":")[0])
	if err != nil {
		printError("saving new netrc: " + err.Error())
	}
	fmt.Println("Logged out.")
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Mauro de Carvalho

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Package provides functions for generating simple Unicode graphs based on a
// series of float64 inputs.
package bars

// Holds the set of characters that will be used to render the graph. Each
// character will be used to represent a different value in the graph. Values
// go from Zero to One in one eighth increments.
type BarSet struct {
	Zero          rune
	Eighth        rune
	Quarter       rune
	ThreeEighths  rune
	Half          rune
	FiveEighths   rune
	ThreeQuarters rune
	SevenEighths  rune
	One           rune
}

// A pre-defined character set based on Unicode blocks.
var NiceBarSet = BarSet{
	' ',
	'▁',
	'▂',
	'▃',
	'▄',
	'▅',
	'▆',
	'▇',
	'█',
}

// A pre-defined character set based on Braile characters.
var BraileBarSet = BarSet{
	' ',
	'⣀',
	'⣀',
	'⣤',
	'⣤',
	'⣶',
	'⣶',
	'⣿',
	'⣿',
}

// Renders a graph, one character per input value to display the given values.
// the lowest value given will be represented with a value of Zero int he graph,
// while the highest value will be represented with a value of One.
// If only one value is given it will be represented as one half.
// The graph is rendered as an array of runes, one rune per value given.
func MakeBar(seq []float64, set BarSet) []rune {
	// If the sequence is empty just return an empty result.
	if len(seq) == 0 {
		return []rune{}
	}

	// If the sequence is only one number it is not possible to calculate the
	// result. We are returning half. The value is completely arbitrary.
	if len(seq) == 1 {
		return []rune{set.Half}
	}

	// We can calculate bars. Determine the minimum and maximum values.
	min := seq[0]
	max := seq[0]
	for i := 1; i < len(seq); i++ {
		if min > seq[i] {
			min = seq[i]
			continue
		}

		if max < seq[i] {
			max = seq[i]
		}
	}

	// for each value, calculate the percentage and add it to the solution
	var diff = max - min
	result := make([]rune, len(seq))

	// Create a lookup table so that we can fetch a char by index
	lookup := []rune{
		set.Zero,
		set.Eighth,
		set.Quarter,
		set.ThreeEighths,
		set.Half,
		set.FiveEighths,
		set.ThreeQuarters,
		set.SevenEighths,
		set.One,
	}

	for i := 0; i < len(seq); i++ {
		// Get what percentage the value is of the total between min and max
		percent := (seq[i] - min) / diff

		// Figure out what char to display it with. 0, 1/16 will use Zero,
		// 1/16, 3/16 will use 1/8, 3/16, 5/16 will use 1/4 and so on...
		index := int((percent + 1/16.) * 8)

		result[i] = lookup[index]
	}

	return result
}
<commit_msg>Minor doc typo fix<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Mauro de Carvalho

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Package provides functions for generating simple Unicode graphs based on a
// series of float64 inputs.
package bars

// Holds the set of characters that will be used to render the graph. Each
// character will be used to represent a different value in the graph. Values
// go from Zero to One in one eighth increments.
type BarSet struct {
	Zero          rune
	Eighth        rune
	Quarter       rune
	ThreeEighths  rune
	Half          rune
	FiveEighths   rune
	ThreeQuarters rune
	SevenEighths  rune
	One           rune
}

// A pre-defined character set based on Unicode blocks.
var NiceBarSet = BarSet{
	' ',
	'▁',
	'▂',
	'▃',
	'▄',
	'▅',
	'▆',
	'▇',
	'█',
}

// A pre-defined character set based on Braile characters.
var BraileBarSet = BarSet{
	' ',
	'⣀',
	'⣀',
	'⣤',
	'⣤',
	'⣶',
	'⣶',
	'⣿',
	'⣿',
}

// Renders a graph, one character per input value to display the given values.
// The lowest value given will be represented with a value of Zero in the graph,
// while the highest value will be represented with a value of One.
// If only one value is given it will be represented as one half.
// The graph is rendered as an array of runes, one rune per value given.
func MakeBar(seq []float64, set BarSet) []rune {
	// If the sequence is empty just return an empty result.
	if len(seq) == 0 {
		return []rune{}
	}

	// If the sequence is only one number it is not possible to calculate the
	// result. We are returning half. The value is completely arbitrary.
	if len(seq) == 1 {
		return []rune{set.Half}
	}

	// We can calculate bars. Determine the minimum and maximum values.
	min := seq[0]
	max := seq[0]
	for i := 1; i < len(seq); i++ {
		if min > seq[i] {
			min = seq[i]
			continue
		}

		if max < seq[i] {
			max = seq[i]
		}
	}

	// for each value, calculate the percentage and add it to the solution
	var diff = max - min
	result := make([]rune, len(seq))

	// Create a lookup table so that we can fetch a char by index
	lookup := []rune{
		set.Zero,
		set.Eighth,
		set.Quarter,
		set.ThreeEighths,
		set.Half,
		set.FiveEighths,
		set.ThreeQuarters,
		set.SevenEighths,
		set.One,
	}

	for i := 0; i < len(seq); i++ {
		// Get what percentage the value is of the total between min and max
		percent := (seq[i] - min) / diff

		// Figure out what char to display it with. 0, 1/16 will use Zero,
		// 1/16, 3/16 will use 1/8, 3/16, 5/16 will use 1/4 and so on...
		index := int((percent + 1/16.) * 8)

		result[i] = lookup[index]
	}

	return result
}
<|endoftext|>


<commit_before>package main

import (
	"container/list"
	"fmt"
)

const (
	PREV = iota + 13
	NEXT
	PLUS
	MINUS
	PRINT
	READ
	LOOP
	END
	SET
	MOV
	MOV_NONZERO
)

const (
	BUF_MAX = iota + 20000
)

type Buffer struct {
	buf  [BUF_MAX]int
	bidx int
	next *Buffer
	prev *Buffer
}

type Instruction struct {
	inst_type      int
	inst_parameter int
	inst_pair      *Instruction
	next           *Instruction
	prev           *Instruction
}

func appendNewBuffer(head *Buffer) *Buffer {
	for head.next != nil {
		head = head.next
	}
	head.next = new(Buffer)
	head.next.prev = head
	return head.next
}

func appendNewInstruction(head *Instruction, inst_type int, inst_parameter int, inst_pair *Instruction) *Instruction {
	if head.inst_type == 0 { // The very first instruction
		head.inst_type = inst_type
		head.inst_parameter = inst_parameter
		return head
	} else {
		for head.next != nil {
			head = head.next
		}
		head.next = new(Instruction)
		head.next.prev = head
		head.next.inst_type = inst_type
		head.next.inst_parameter = inst_parameter
		head.next.inst_pair = inst_pair
		if inst_pair != nil {
			inst_pair.inst_pair = head.next // Since `]` will always appear in the end of instruction list
		}
		return head.next
	}
}

func movePtrByOffset(buf *Buffer, offset int) *Buffer {
	if offset >= 0 {
		if buf.bidx+offset > BUF_MAX-1 {
			diff := BUF_MAX - 1 - buf.bidx
			buf.bidx = BUF_MAX - 1
			if buf.next == nil {
				new_buf := appendNewBuffer(buf)
				new_buf.bidx = offset - diff
				buf = new_buf
			} else {
				buf = buf.next
				buf.bidx = offset - diff
			}
			return buf
		} else {
			buf.bidx += offset
			return buf
		}
	} else {
		if buf.bidx-offset < 0 {
			if buf.prev == nil {
				return nil
			}
			diff := offset + buf.bidx
			buf = buf.prev
			buf.bidx += diff
			return buf
		} else {
			buf.bidx += offset
			return buf
		}
	}
}

func movePtrToNonzero(buf *Buffer, gap int) *Buffer {
	for i := buf.bidx; ; i += gap {
		if i > BUF_MAX-1 {
			buf.bidx = BUF_MAX - 1
			diff := i - BUF_MAX - 1
			if buf.next == nil {
				new_buf := appendNewBuffer(buf)
				new_buf.bidx = diff
				buf = new_buf
			} else {
				buf = buf.next
				buf.bidx = diff
			}
			i = diff
		} else if i < 0 {
			buf.bidx = 0
			buf = buf.prev
			buf.bidx += i
			i = buf.bidx
		}

		if buf.buf[i] == 0 {
			buf.bidx = i
			return buf
		}
	}
}

func movePtrToPrev(buf *Buffer) *Buffer {
	if buf.bidx == 0 {
		if buf.prev == nil {
			return nil
		}
		return buf.prev
	} else {
		buf.bidx -= 1
		return buf
	}
}

func movePtrToNext(buf *Buffer) *Buffer {
	if buf.bidx == BUF_MAX-1 {
		if buf.next == nil {
			return appendNewBuffer(buf)
		} else {
			return buf.next
		}
	} else {
		buf.bidx += 1
		return buf
	}
}

func addPtr(buf *Buffer, val int) {
	buf.buf[buf.bidx] += val
}

func subPtr(buf *Buffer, val int) {
	buf.buf[buf.bidx] -= val
}

func printPtr(buf *Buffer) {
	fmt.Printf("%c", buf.buf[buf.bidx])
}

func readPtr(buf *Buffer) {
	fmt.Scanf("%c", &(buf.buf[buf.bidx]))
}

func execute(inst *Instruction, buf *Buffer) *Instruction {
	for inst != nil {
		switch inst.inst_type {
		default:
			return nil
		case PREV:
			buf = movePtrToPrev(buf)
		case NEXT:
			buf = movePtrToNext(buf)
		case PLUS:
			addPtr(buf, inst.inst_parameter)
		case MINUS:
			subPtr(buf, inst.inst_parameter)
		case PRINT:
			printPtr(buf)
		case READ:
			readPtr(buf)
		case LOOP:
			next_inst := inst.inst_pair
			for buf.buf[buf.bidx] != 0 {
				execute(inst.next, buf)
			}
			inst = next_inst
		case END:
			return inst
		case SET:
			buf.buf[buf.bidx] = inst.inst_parameter
		case MOV:
			buf = movePtrByOffset(buf, inst.inst_parameter)
		case MOV_NONZERO:
			buf = movePtrToNonzero(buf, inst.inst_parameter)
		}
		inst = inst.next
	}
	return nil
}

func optimizeConsecutiveArithmetic(inst *Instruction) {
	// Transform consecutive arithmetic operation, ex: ++++ to PLUS 4
	sum := 0
	start := (*Instruction)(nil)
	for inst != nil {
		if inst.inst_type == PLUS || inst.inst_type == MINUS {
			if start == nil {
				if inst.inst_type == PLUS {
					sum = 1
				} else {
					sum = -1
				}
				start = inst
			} else {
				if inst.inst_type == PLUS {
					sum += 1
				} else {
					sum -= 1
				}
			}
		} else {
			if start != nil && start != inst.prev {
				if sum > 0 {
					start.inst_type = PLUS
				} else if sum < 0 {
					start.inst_type = MINUS
					sum = -sum
				}
				start.inst_parameter = sum

				sum = 0
				start.next = inst
				inst.prev = start
			}
			start = nil
		}
		inst = inst.next
	}

	if start != nil {
		start.next = nil
	}
}

func optimizeConsecutiveMovement(inst *Instruction) {
	// Transform consecutive pointer movement, ex: <<<< to MOV -4
	offset := 0
	start := (*Instruction)(nil)
	for inst != nil {
		if inst.inst_type == PREV || inst.inst_type == NEXT {
			if start == nil {
				if inst.inst_type == NEXT {
					offset = 1
				} else {
					offset = -1
				}
				start = inst
			} else {
				if inst.inst_type == NEXT {
					offset += 1
				} else {
					offset -= 1
				}
			}
		} else {
			if start != nil && start != inst.prev {
				start.inst_type = MOV
				start.inst_parameter = offset

				start.next = inst
				inst.prev = start
			}
			offset = 0
			start = nil
		}
		inst = inst.next
	}

	if start != nil {
		start.next = nil
	}
}

func optimizeSubstractionToZero(inst *Instruction) {
	// For pattern: [-]
	for inst != nil {
		if inst.inst_type == LOOP {
			if inst.next != nil && inst.next.next != nil {
				if inst.next.inst_type == MINUS && inst.next.next.inst_type == END {
					new_inst := new(Instruction)
					new_inst.prev = inst.prev
					if inst.prev != nil {
						inst.prev.next = new_inst
					}
					new_inst.next = inst.next.next.next
					if inst.next.next.next != nil {
						inst.next.next.next.prev = new_inst
					}
					new_inst.inst_type = SET
					new_inst.inst_parameter = 0
					inst = new_inst
				}
			}
		}
		inst = inst.next
	}
}

func optimizeMovementLoop(inst *Instruction) {
	// For pattern: [>], [<], [>>>]
	for inst != nil {
		if inst.inst_type == LOOP {
			inner_inst := inst.next
			if inner_inst.next.inst_type == END {
				is_movement := false
				switch inner_inst.inst_type {
				case NEXT:
					is_movement = true
					inst.inst_type = MOV_NONZERO
					inst.inst_parameter = 1
				case PREV:
					is_movement = true
					inst.inst_type = MOV_NONZERO
					inst.inst_parameter = -1
				case MOV:
					is_movement = true
					inst.inst_type = MOV_NONZERO
					inst.inst_parameter = inner_inst.inst_parameter
				}
				if is_movement {
					inst.next = inst.inst_pair.next
					inst.inst_pair = nil
				}
			}
		}
		inst = inst.next
	}
}

func optimizeAssignment(inst *Instruction) {
	// For pattern: [-]++++++, considered as variable assignment
	for inst != nil {
		if inst.inst_type == SET {
			if inst.next != nil {
				if inst.next.inst_type == PLUS {
					inst.inst_parameter = inst.next.inst_parameter
					inst.next = inst.next.next
				} else if inst.inst_type == MINUS {
					inst.inst_parameter = 0 - inst.next.inst_parameter
					inst.next = inst.next.next
				}
			}
		}
		inst = inst.next
	}
}

func optimizeInstructions(inst *Instruction) *Instruction {
	head := inst
	optimizeConsecutiveArithmetic(inst)
	optimizeConsecutiveMovement(inst)
	optimizeSubstractionToZero(inst)
	optimizeMovementLoop(inst)
	optimizeAssignment(inst)
	return head
}

func main() {
	inst := new(Instruction)
	buf := new(Buffer)
	stack := list.New()
	var c int
	i, _ := fmt.Scanf("%c", &c)
	for i != 0 {
		switch c {
		case '>':
			appendNewInstruction(inst, NEXT, 0, nil)
		case '<':
			appendNewInstruction(inst, PREV, 0, nil)
		case '+':
			appendNewInstruction(inst, PLUS, 1, nil)
		case '-':
			appendNewInstruction(inst, MINUS, 1, nil)
		case '.':
			appendNewInstruction(inst, PRINT, 0, nil)
		case ',':
			appendNewInstruction(inst, READ, 0, nil)
		case '[':
			begin := appendNewInstruction(inst, LOOP, 0, nil)
			stack.PushBack(begin)
		case ']':
			begin := stack.Back().Value.(*Instruction)
			appendNewInstruction(inst, END, 0, begin)
			stack.Remove(stack.Back())
		}
		i, _ = fmt.Scanf("%c", &c)
	}
	inst = optimizeInstructions(inst)
	execute(inst, buf)
}
<commit_msg>[Optimization] simple loop multiplication pattern<commit_after>package main

import (
	"container/list"
	"fmt"
)

const (
	PREV = iota + 13
	NEXT
	PLUS
	MINUS
	PRINT
	READ
	LOOP
	END
	SET
	MOV
	MOV_NONZERO
	NOP
)

const (
	BUF_MAX = iota + 20000
)

type Buffer struct {
	buf  [BUF_MAX]int
	bidx int
	next *Buffer
	prev *Buffer
}

type Instruction struct {
	inst_type      int
	inst_parameter int
	inst_pair      *Instruction
	next           *Instruction
	prev           *Instruction
}

func appendNewBuffer(head *Buffer) *Buffer {
	for head.next != nil {
		head = head.next
	}
	head.next = new(Buffer)
	head.next.prev = head
	return head.next
}

func appendNewInstruction(head *Instruction, inst_type int, inst_parameter int, inst_pair *Instruction) *Instruction {
	if head.inst_type == 0 { // The very first instruction
		head.inst_type = inst_type
		head.inst_parameter = inst_parameter
		return head
	} else {
		for head.next != nil {
			head = head.next
		}
		head.next = new(Instruction)
		head.next.prev = head
		head.next.inst_type = inst_type
		head.next.inst_parameter = inst_parameter
		head.next.inst_pair = inst_pair
		if inst_pair != nil {
			inst_pair.inst_pair = head.next // Since `]` will always appear in the end of instruction list
		}
		return head.next
	}
}

func movePtrByOffset(buf *Buffer, offset int) *Buffer {
	if offset >= 0 {
		if buf.bidx+offset > BUF_MAX-1 {
			diff := BUF_MAX - 1 - buf.bidx
			buf.bidx = BUF_MAX - 1
			if buf.next == nil {
				new_buf := appendNewBuffer(buf)
				new_buf.bidx = offset - diff
				buf = new_buf
			} else {
				buf = buf.next
				buf.bidx = offset - diff
			}
			return buf
		} else {
			buf.bidx += offset
			return buf
		}
	} else {
		if buf.bidx-offset < 0 {
			if buf.prev == nil {
				return nil
			}
			diff := offset + buf.bidx
			buf = buf.prev
			buf.bidx += diff
			return buf
		} else {
			buf.bidx += offset
			return buf
		}
	}
}

func movePtrToNonzero(buf *Buffer, gap int) *Buffer {
	for i := buf.bidx; ; i += gap {
		if i > BUF_MAX-1 {
			buf.bidx = BUF_MAX - 1
			diff := i - BUF_MAX - 1
			if buf.next == nil {
				new_buf := appendNewBuffer(buf)
				new_buf.bidx = diff
				buf = new_buf
			} else {
				buf = buf.next
				buf.bidx = diff
			}
			i = diff
		} else if i < 0 {
			buf.bidx = 0
			buf = buf.prev
			buf.bidx += i
			i = buf.bidx
		}

		if buf.buf[i] == 0 {
			buf.bidx = i
			return buf
		}
	}
}

func movePtrToPrev(buf *Buffer) *Buffer {
	if buf.bidx == 0 {
		if buf.prev == nil {
			return nil
		}
		return buf.prev
	} else {
		buf.bidx -= 1
		return buf
	}
}

func movePtrToNext(buf *Buffer) *Buffer {
	if buf.bidx == BUF_MAX-1 {
		if buf.next == nil {
			return appendNewBuffer(buf)
		} else {
			return buf.next
		}
	} else {
		buf.bidx += 1
		return buf
	}
}

func addPtr(buf *Buffer, val int) {
	buf.buf[buf.bidx] += val
}

func subPtr(buf *Buffer, val int) {
	buf.buf[buf.bidx] -= val
}

func printPtr(buf *Buffer) {
	fmt.Printf("%c", buf.buf[buf.bidx])
}

func readPtr(buf *Buffer) {
	fmt.Scanf("%c", &(buf.buf[buf.bidx]))
}

func execute(inst *Instruction, buf *Buffer) *Instruction {
	for inst != nil {
		switch inst.inst_type {
		default:
			return nil
		case PREV:
			buf = movePtrToPrev(buf)
		case NEXT:
			buf = movePtrToNext(buf)
		case PLUS:
			addPtr(buf, inst.inst_parameter)
		case MINUS:
			subPtr(buf, inst.inst_parameter)
		case PRINT:
			printPtr(buf)
		case READ:
			readPtr(buf)
		case LOOP:
			next_inst := inst.inst_pair
			for buf.buf[buf.bidx] != 0 {
				execute(inst.next, buf)
			}
			inst = next_inst
		case END:
			return inst
		case SET:
			buf.buf[buf.bidx] = inst.inst_parameter
		case MOV:
			buf = movePtrByOffset(buf, inst.inst_parameter)
		case MOV_NONZERO:
			buf = movePtrToNonzero(buf, inst.inst_parameter)
		case NOP:
			break
		}
		inst = inst.next
	}
	return nil
}

func optimizeConsecutiveArithmetic(inst *Instruction) {
	// Transform consecutive arithmetic operation, ex: ++++ to PLUS 4
	sum := 0
	start := (*Instruction)(nil)
	for inst != nil {
		if inst.inst_type == PLUS || inst.inst_type == MINUS {
			if start == nil {
				if inst.inst_type == PLUS {
					sum = 1
				} else {
					sum = -1
				}
				start = inst
			} else {
				if inst.inst_type == PLUS {
					sum += 1
				} else {
					sum -= 1
				}
			}
		} else {
			if start != nil && start != inst.prev {
				if sum > 0 {
					start.inst_type = PLUS
				} else if sum < 0 {
					start.inst_type = MINUS
					sum = -sum
				}
				start.inst_parameter = sum

				sum = 0
				start.next = inst
				inst.prev = start
			}
			start = nil
		}
		inst = inst.next
	}

	if start != nil {
		start.next = nil
	}
}

func optimizeConsecutiveMovement(inst *Instruction) {
	// Transform consecutive pointer movement, ex: <<<< to MOV -4
	offset := 0
	start := (*Instruction)(nil)
	for inst != nil {
		if inst.inst_type == PREV || inst.inst_type == NEXT {
			if start == nil {
				if inst.inst_type == NEXT {
					offset = 1
				} else {
					offset = -1
				}
				start = inst
			} else {
				if inst.inst_type == NEXT {
					offset += 1
				} else {
					offset -= 1
				}
			}
		} else {
			if start != nil && start != inst.prev {
				start.inst_type = MOV
				start.inst_parameter = offset

				start.next = inst
				inst.prev = start
			}
			offset = 0
			start = nil
		}
		inst = inst.next
	}

	if start != nil {
		start.next = nil
	}
}

func optimizeSubstractionToZero(inst *Instruction) {
	// For pattern: [-]
	for inst != nil {
		if inst.inst_type == LOOP {
			if inst.next != nil && inst.next.next != nil {
				if inst.next.inst_type == MINUS && inst.next.next.inst_type == END {
					new_inst := new(Instruction)
					new_inst.prev = inst.prev
					if inst.prev != nil {
						inst.prev.next = new_inst
					}
					new_inst.next = inst.next.next.next
					if new_inst.next != nil {
						new_inst.next.prev = new_inst
					}
					new_inst.inst_type = SET
					new_inst.inst_parameter = 0
					inst = new_inst
				}
			}
		}
		inst = inst.next
	}
}

func optimizeMovementLoop(inst *Instruction) {
	// For pattern: [>], [<], [>>>]
	for inst != nil {
		if inst.inst_type == LOOP {
			inner_inst := inst.next
			if inner_inst.next.inst_type == END {
				is_movement := false
				switch inner_inst.inst_type {
				case NEXT:
					is_movement = true
					inst.inst_type = MOV_NONZERO
					inst.inst_parameter = 1
				case PREV:
					is_movement = true
					inst.inst_type = MOV_NONZERO
					inst.inst_parameter = -1
				case MOV:
					is_movement = true
					inst.inst_type = MOV_NONZERO
					inst.inst_parameter = inner_inst.inst_parameter
				}
				if is_movement {
					inst.next = inst.inst_pair.next
					if inst.next != nil {
						inst.next.prev = inst
					}
					inst.inst_pair = nil
				}
			}
		}
		inst = inst.next
	}
}

func optimizeAssignment(inst *Instruction) {
	// For pattern: [-]++++++, considered as variable assignment
	for inst != nil {
		if inst.inst_type == SET {
			if inst.next != nil {
				if inst.next.inst_type == PLUS {
					inst.inst_parameter = inst.next.inst_parameter
					inst.next = inst.next.next
					if inst.next != nil {
						inst.next.prev = inst
					}
				} else if inst.inst_type == MINUS {
					inst.inst_parameter = 0 - inst.next.inst_parameter
					inst.next = inst.next.next
				}
			}
		}
		inst = inst.next
	}
}

func optimizeSimpleLoopMultiplication(inst *Instruction) {
	// For pattern: ++++++[->+>++++<<]
	for inst != nil {
		if inst.inst_type == LOOP {
			// Determine if this loop represents the pattern
			if inst.inst_parameter == 1 || inst.prev == nil {
				// Has subloops
				inst = inst.next
				continue
			}
			if inst.prev != nil && inst.prev.inst_type != PLUS && inst.prev.inst_type != SET {
				inst = inst.next
				continue
			}
			loop_inst := inst.next
			pattern_match := true
			offset := 0
			for loop_inst != inst.inst_pair {
				switch loop_inst.inst_type {
				case NEXT:
					offset += 1
				case PREV:
					offset -= 1
				case MOV:
					offset += loop_inst.inst_parameter
				case READ:
					pattern_match = false
				}
				loop_inst = loop_inst.next
			}
			if offset != 0 {
				pattern_match = false
			}
			if pattern_match {
				mul_factor := inst.prev.inst_parameter
				loop_inst = inst.next
				for loop_inst != inst.inst_pair {
					if loop_inst.inst_type == PLUS {
						loop_inst.inst_parameter *= mul_factor
					} else if loop_inst.inst_type == MINUS && loop_inst.inst_parameter == 1 {
						// Check if it's substraction to condition index
						if loop_inst.prev.inst_type == LOOP || loop_inst.next.inst_type == END {
							loop_inst.inst_type = NOP
						}
					} else if loop_inst.inst_type == MINUS {
						loop_inst.inst_parameter *= mul_factor
					}
					loop_inst = loop_inst.next
				}
				inst.prev.inst_type = NOP
				inst.prev.inst_parameter = 0
				inst.prev.next = inst.next
				inst.next.prev = inst.prev
				loop_inst.prev.next = loop_inst.next
				inst = loop_inst
			} else {
				inst = inst.inst_pair
			}
		}
		inst = inst.next
	}
}

func optimizeInstructions(inst *Instruction) *Instruction {
	head := inst
	optimizeConsecutiveArithmetic(inst)
	optimizeConsecutiveMovement(inst)
	optimizeSubstractionToZero(inst)
	optimizeMovementLoop(inst)
	optimizeAssignment(inst)
	optimizeSimpleLoopMultiplication(inst)
	return head
}

func main() {
	inst := new(Instruction)
	buf := new(Buffer)
	stack := list.New()
	var c int
	i, _ := fmt.Scanf("%c", &c)
	for i != 0 {
		switch c {
		case '>':
			appendNewInstruction(inst, NEXT, 0, nil)
		case '<':
			appendNewInstruction(inst, PREV, 0, nil)
		case '+':
			appendNewInstruction(inst, PLUS, 1, nil)
		case '-':
			appendNewInstruction(inst, MINUS, 1, nil)
		case '.':
			appendNewInstruction(inst, PRINT, 0, nil)
		case ',':
			appendNewInstruction(inst, READ, 0, nil)
		case '[':
			begin := appendNewInstruction(inst, LOOP, 0, nil)
			stack.PushBack(begin)
		case ']':
			begin := stack.Back().Value.(*Instruction)
			appendNewInstruction(inst, END, 0, begin)
			stack.Remove(stack.Back())
			for e := stack.Front(); e != nil; e = e.Next() {
				e.Value.(*Instruction).inst_parameter = 1
			}
		}
		i, _ = fmt.Scanf("%c", &c)
	}
	inst = optimizeInstructions(inst)
	execute(inst, buf)
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"net"
	"net/http"
	gourl "net/url"
	"os"
	"regexp"
	"strings"

	"github.com/rakyll/boom/commands"
)

var (
	flagMethod   = flag.String("m", "GET", "")
	flagHeaders  = flag.String("h", "", "")
	flagD        = flag.String("d", "", "")
	flagType     = flag.String("T", "text/html", "")
	flagAuth     = flag.String("a", "", "")
	flagInsecure = flag.Bool("allow-insecure", false, "")
	flagOutput   = flag.String("o", "", "")

	flagC = flag.Int("c", 50, "")
	flagN = flag.Int("n", 200, "")
	flagQ = flag.Int("q", 0, "")
	flagT = flag.Int("t", 0, "")
)

var usage = `Usage: boom [options...] <url>

Options:
  -n  Number of requests to run.
  -c  Number of requests to run concurrently. Total number of requests cannot
      be smaller than the concurency level.
  -q  Rate limit, in seconds (QPS).
  -o  Output type. If none provided, a summary is printed.
      "csv" is the only supported alternative. Dumps the response
      metrics in comma-seperated values format.

  -m  HTTP method, one of GET, POST, PUT, DELETE, HEAD, OPTIONS.
  -h  Custom HTTP headers, name1:value1;name2:value2.
  -d  HTTP request body.
  -T  Content-type, defaults to "text/html".
  -a  Basic authentication, username:password.

  -allow-insecure Allow bad/expired TLS/SSL certificates.
`

// Default DNS resolver.
var defaultDnsResolver dnsResolver = &netDnsResolver{}

// DNS resolver interface.
type dnsResolver interface {
	Lookup(domain string) (addr []string, err error)
}

// A DNS resolver based on net.LookupHost.
type netDnsResolver struct{}

// Looks up for the resolved IP addresses of
// the provided domain.
func (*netDnsResolver) Lookup(domain string) (addr []string, err error) {
	return net.LookupHost(domain)
}

func main() {
	flag.Usage = func() {
		fmt.Fprint(os.Stderr, usage)
	}

	flag.Parse()
	if flag.NArg() < 1 {
		usageAndExit("")
	}

	n := *flagN
	c := *flagC
	q := *flagQ
	t := *flagT

	if n <= 0 || c <= 0 {
		usageAndExit("n and c cannot be smaller than 1.")
	}

	// If total number is smaller than concurrency level,
	// make the total number c.
	if c > n {
		n = c
	}

	url := flag.Args()[0]
	method := strings.ToUpper(*flagMethod)

	ipResolvedUrl, serverName := newURL(url)
	req, _ := http.NewRequest(
		method, ipResolvedUrl.String(), strings.NewReader(*flagD))
	// set content-type
	req.Header.Set("Content-Type", *flagType)

	// set any other additional headers
	if *flagHeaders != "" {
		headers := strings.Split(*flagHeaders, ";")
		for _, h := range headers {
			re := regexp.MustCompile("([\\w|-]+):(.+)")
			matches := re.FindAllStringSubmatch(h, -1)
			if len(matches) < 1 {
				usageAndExit("")
			}
			req.Header.Set(matches[0][1], matches[0][2])
		}
	}

	// set basic auth if set
	if *flagAuth != "" {
		re := regexp.MustCompile("(\\w+):(\\w+)")
		matches := re.FindAllStringSubmatch(*flagAuth, -1)
		if len(matches) < 1 {
			usageAndExit("")
		}
		req.SetBasicAuth(matches[0][1], matches[0][2])
	}

	if *flagOutput != "csv" && *flagOutput != "" {
		usageAndExit("Invalid output type.")
	}

	(&commands.Boom{
		N:              n,
		C:              c,
		Qps:            q,
		Timeout:        t,
		Req:            req,
		OrigServerName: serverName,
		AllowInsecure:  *flagInsecure,
		Output:         *flagOutput}).Run()
}

// Replaces host with an IP and returns the provided
// string URL as a *url.URL.
//
// DNS lookups are not cached in the package level in Go,
// and it's a huge overhead to resolve a host
// before each request in our case. Instead we resolve
// the domain and replace it with the resolved IP to avoid
// lookups during request time. Supported url strings:
//
// <schema>://google.com[:port]
// <schema>://173.194.116.73[:port]
// <schema>://\[2a00:1450:400a:806::1007\][:port]
func newURL(url string) (*gourl.URL, string) {
	uri, err := gourl.ParseRequestURI(url)
	if err != nil {
		usageAndExit(err.Error())
	}

	serverName, port, err := net.SplitHostPort(uri.Host)
	if err != nil {
		serverName = uri.Host
	}

	addrs, err := defaultDnsResolver.Lookup(serverName)
	if err != nil {
		usageAndExit("Hostname " + serverName + " cannot be resolved")
	}

	if port != "" {
		// join automatically puts square brackets around the
		// ipv6 IPs.
		uri.Host = net.JoinHostPort(addrs[0], port)
	} else {
		// square brackets are required for ipv6 IPs.
		// otherwise, net.Dial fails with a parsing error.
		uri.Host = fmt.Sprintf("[%s]", addrs[0])
	}
	return uri, serverName
}

func usageAndExit(message string) {
	if message != "" {
		fmt.Fprintf(os.Stderr, message)
		fmt.Fprintf(os.Stderr, "\n\n")
	}
	flag.Usage()
	fmt.Fprintf(os.Stderr, "\n")
	os.Exit(1)
}
<commit_msg>Print lookup error instead of a custom message.<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"fmt"
	"net"
	"net/http"
	gourl "net/url"
	"os"
	"regexp"
	"strings"

	"github.com/rakyll/boom/commands"
)

var (
	flagMethod   = flag.String("m", "GET", "")
	flagHeaders  = flag.String("h", "", "")
	flagD        = flag.String("d", "", "")
	flagType     = flag.String("T", "text/html", "")
	flagAuth     = flag.String("a", "", "")
	flagInsecure = flag.Bool("allow-insecure", false, "")
	flagOutput   = flag.String("o", "", "")

	flagC = flag.Int("c", 50, "")
	flagN = flag.Int("n", 200, "")
	flagQ = flag.Int("q", 0, "")
	flagT = flag.Int("t", 0, "")
)

var usage = `Usage: boom [options...] <url>

Options:
  -n  Number of requests to run.
  -c  Number of requests to run concurrently. Total number of requests cannot
      be smaller than the concurency level.
  -q  Rate limit, in seconds (QPS).
  -o  Output type. If none provided, a summary is printed.
      "csv" is the only supported alternative. Dumps the response
      metrics in comma-seperated values format.

  -m  HTTP method, one of GET, POST, PUT, DELETE, HEAD, OPTIONS.
  -h  Custom HTTP headers, name1:value1;name2:value2.
  -d  HTTP request body.
  -T  Content-type, defaults to "text/html".
  -a  Basic authentication, username:password.

  -allow-insecure Allow bad/expired TLS/SSL certificates.
`

// Default DNS resolver.
var defaultDnsResolver dnsResolver = &netDnsResolver{}

// DNS resolver interface.
type dnsResolver interface {
	Lookup(domain string) (addr []string, err error)
}

// A DNS resolver based on net.LookupHost.
type netDnsResolver struct{}

// Looks up for the resolved IP addresses of
// the provided domain.
func (*netDnsResolver) Lookup(domain string) (addr []string, err error) {
	return net.LookupHost(domain)
}

func main() {
	flag.Usage = func() {
		fmt.Fprint(os.Stderr, usage)
	}

	flag.Parse()
	if flag.NArg() < 1 {
		usageAndExit("")
	}

	n := *flagN
	c := *flagC
	q := *flagQ
	t := *flagT

	if n <= 0 || c <= 0 {
		usageAndExit("n and c cannot be smaller than 1.")
	}

	// If total number is smaller than concurrency level,
	// make the total number c.
	if c > n {
		n = c
	}

	url := flag.Args()[0]
	method := strings.ToUpper(*flagMethod)

	ipResolvedUrl, serverName := newURL(url)
	req, _ := http.NewRequest(
		method, ipResolvedUrl.String(), strings.NewReader(*flagD))
	// set content-type
	req.Header.Set("Content-Type", *flagType)

	// set any other additional headers
	if *flagHeaders != "" {
		headers := strings.Split(*flagHeaders, ";")
		for _, h := range headers {
			re := regexp.MustCompile("([\\w|-]+):(.+)")
			matches := re.FindAllStringSubmatch(h, -1)
			if len(matches) < 1 {
				usageAndExit("")
			}
			req.Header.Set(matches[0][1], matches[0][2])
		}
	}

	// set basic auth if set
	if *flagAuth != "" {
		re := regexp.MustCompile("(\\w+):(\\w+)")
		matches := re.FindAllStringSubmatch(*flagAuth, -1)
		if len(matches) < 1 {
			usageAndExit("")
		}
		req.SetBasicAuth(matches[0][1], matches[0][2])
	}

	if *flagOutput != "csv" && *flagOutput != "" {
		usageAndExit("Invalid output type.")
	}

	(&commands.Boom{
		N:              n,
		C:              c,
		Qps:            q,
		Timeout:        t,
		Req:            req,
		OrigServerName: serverName,
		AllowInsecure:  *flagInsecure,
		Output:         *flagOutput}).Run()
}

// Replaces host with an IP and returns the provided
// string URL as a *url.URL.
//
// DNS lookups are not cached in the package level in Go,
// and it's a huge overhead to resolve a host
// before each request in our case. Instead we resolve
// the domain and replace it with the resolved IP to avoid
// lookups during request time. Supported url strings:
//
// <schema>://google.com[:port]
// <schema>://173.194.116.73[:port]
// <schema>://\[2a00:1450:400a:806::1007\][:port]
func newURL(url string) (*gourl.URL, string) {
	uri, err := gourl.ParseRequestURI(url)
	if err != nil {
		usageAndExit(err.Error())
	}

	serverName, port, err := net.SplitHostPort(uri.Host)
	if err != nil {
		serverName = uri.Host
	}

	addrs, err := defaultDnsResolver.Lookup(serverName)
	if err != nil {
		usageAndExit(err.Error())
	}

	if port != "" {
		// join automatically puts square brackets around the
		// ipv6 IPs.
		uri.Host = net.JoinHostPort(addrs[0], port)
	} else {
		// square brackets are required for ipv6 IPs.
		// otherwise, net.Dial fails with a parsing error.
		uri.Host = fmt.Sprintf("[%s]", addrs[0])
	}
	return uri, serverName
}

func usageAndExit(message string) {
	if message != "" {
		fmt.Fprintf(os.Stderr, message)
		fmt.Fprintf(os.Stderr, "\n\n")
	}
	flag.Usage()
	fmt.Fprintf(os.Stderr, "\n")
	os.Exit(1)
}
<|endoftext|>


<commit_before>package gitmediafilters

import (
	".."
	"fmt"
	"io"
	"os"
)

// git media clean writer that outputs the large asset meta data to stdin, and
// deletes the temp file.  This is used directly if the large asset has been
// saved to the git media directory already.
type ExistingWriter struct {
	tempfile *os.File
	writer   io.Writer
}

func NewExistingWriter(cleaned *CleanedAsset, writer io.Writer) io.WriteCloser {
	return &ExistingWriter{cleaned.File, writer}
}

func (w *ExistingWriter) Write(buf []byte) (int, error) {
	return w.writer.Write(buf)
}

func (w *ExistingWriter) Close() error {
	return os.Remove(w.tempfile.Name())
}

type Writer struct {
	metafile *os.File
	*ExistingWriter
}

// a git media clean writer that writes the large asset data to the local
// git media directory.  Also embeds an ExistingWriter.
func NewWriter(cleaned *CleanedAsset, writer io.Writer) io.WriteCloser {
	mediafile := gitmedia.LocalMediaPath(cleaned.Sha)
	metafile := mediafile + ".txt"

	if err := os.Rename(cleaned.File.Name(), mediafile); err != nil {
		fmt.Printf("Unable to move %s to %s\n", cleaned.File.Name(), mediafile)
		panic(err)
	}

	file, err := os.Create(metafile)
	if err != nil {
		fmt.Printf("Unable to create meta data file: %s\n", metafile)
		panic(err)
	}

	return &Writer{
		metafile:       file,
		ExistingWriter: &ExistingWriter{cleaned.File, io.MultiWriter(writer, file)},
	}
}

func (w *Writer) Write(buf []byte) (int, error) {
	return w.writer.Write(buf)
}

func (w *Writer) Close() error {
	w.ExistingWriter.Close()
	return w.metafile.Close()
}
<commit_msg>don't bother writing the metadata file, all we need is the sha<commit_after>package gitmediafilters

import (
	".."
	"fmt"
	"io"
	"os"
)

// git media clean writer that outputs the large asset meta data to stdin, and
// deletes the temp file.  This is used directly if the large asset has been
// saved to the git media directory already.
type ExistingWriter struct {
	tempfile *os.File
	writer   io.Writer
}

func NewExistingWriter(cleaned *CleanedAsset, writer io.Writer) *ExistingWriter {
	return &ExistingWriter{cleaned.File, writer}
}

func (w *ExistingWriter) Write(buf []byte) (int, error) {
	return w.writer.Write(buf)
}

func (w *ExistingWriter) Close() error {
	return os.Remove(w.tempfile.Name())
}

type Writer struct {
	*ExistingWriter
}

// a git media clean writer that writes the large asset data to the local
// git media directory.  Also embeds an ExistingWriter.
func NewWriter(cleaned *CleanedAsset, writer io.Writer) *Writer {
	mediafile := gitmedia.LocalMediaPath(cleaned.Sha)

	if err := os.Rename(cleaned.File.Name(), mediafile); err != nil {
		fmt.Printf("Unable to move %s to %s\n", cleaned.File.Name(), mediafile)
		panic(err)
	}

	return &Writer{NewExistingWriter(cleaned, writer)}
}

func (w *Writer) Write(buf []byte) (int, error) {
	return w.writer.Write(buf)
}

func (w *Writer) Close() error {
	return w.ExistingWriter.Close()
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	skippedPaths   = regexp.MustCompile(`Godeps|third_party|_gopath|_output|\.git|cluster/env.sh|vendor|test/e2e/generated/bindata.go|site/themes/docsy`)
	boilerplatedir = flag.String("boilerplate-dir", ".", "Boilerplate directory for boilerplate files")
	rootdir        = flag.String("rootdir", "../../", "Root directory to examine")
)

func main() {
	flag.Parse()
	refs := extensionToBoilerplate(*boilerplatedir)
	if len(refs) == 0 {
		log.Fatal("no references in ", *boilerplatedir)
	}
	files := filesToCheck(*rootdir, refs)
	for _, file := range files {
		if !filePasses(file, refs[fileExtension(file)]) {
			fmt.Println(file)
		}
	}

}

// extensionToBoilerplate returns a map of file extension to required boilerplate text
func extensionToBoilerplate(dir string) map[string][]byte {
	refs := make(map[string][]byte)
	files, _ := filepath.Glob(dir + "/*.txt")
	for _, filename := range files {
		re := regexp.MustCompile(`\.txt`)
		extension := strings.ToLower(fileExtension(re.ReplaceAllString(filename, "")))
		data, err := ioutil.ReadFile(filename)
		if err != nil {
			log.Fatal(err)
		}
		re = regexp.MustCompile(`\r`)
		refs[extension] = re.ReplaceAll(data, nil)
	}
	return refs
}

// filePasses checks whether the processed file is valid. Returning false means that the file does not the proper boilerplate template.
func filePasses(filename string, expectedBoilerplate []byte) bool {
	var re *regexp.Regexp
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatal(err)
	}
	re = regexp.MustCompile(`\r`)
	data = re.ReplaceAll(data, nil)

	extension := fileExtension(filename)

	// remove build tags from the top of Go files
	if extension == "go" {
		re = regexp.MustCompile(`(?m)^(// \+build.*\n)+\n`)
		data = re.ReplaceAll(data, nil)
	}

	// remove shebang from the top of shell files
	if extension == "sh" {
		re = regexp.MustCompile(`(?m)^(#!.*\n)\n*`)
		data = re.ReplaceAll(data, nil)
	}

	// if our test file is smaller than the reference it surely fails!
	if len(data) < len(expectedBoilerplate) {
		return false
	}

	data = data[:len(expectedBoilerplate)]

	// Search for "Copyright YEAR" which exists in the boilerplate, but shouldn't in the real thing
	re = regexp.MustCompile(`Copyright YEAR`)
	if re.Match(data) {
		return false
	}

	// Replace all occurrences of the regex "Copyright \d{4}" with "Copyright YEAR"
	re = regexp.MustCompile(`Copyright \d{4}`)
	data = re.ReplaceAll(data, []byte(`Copyright YEAR`))

	return bytes.Equal(data, expectedBoilerplate)
}

/**
Function to get the file extensin or the filename if the file has no extension
*/
func fileExtension(filename string) string {
	splitted := strings.Split(filepath.Base(filename), ".")
	return strings.ToLower(splitted[len(splitted)-1])
}

// filesToCheck returns the list of the filers that will be checked for the boilerplate.
func filesToCheck(rootDir string, extensions map[string][]byte) []string {
	var outFiles []string
	err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		// remove current workdir from the beginig of the path in case it matches the skipped path
		cwd, _ := os.Getwd()
		// replace "\" with "\\" for windows style path
		re := regexp.MustCompile(`\\`)
		re = regexp.MustCompile(`^` + re.ReplaceAllString(cwd, `\\`))
		if !info.IsDir() && !skippedPaths.MatchString(re.ReplaceAllString(filepath.Dir(path), "")) {
			if extensions[strings.ToLower(fileExtension(path))] != nil {
				outFiles = append(outFiles, path)
			}
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
	return outFiles
}
<commit_msg>Refactor error handling in boilerplate.go<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	skippedPaths   = regexp.MustCompile(`Godeps|third_party|_gopath|_output|\.git|cluster/env.sh|vendor|test/e2e/generated/bindata.go|site/themes/docsy`)
	boilerplatedir = flag.String("boilerplate-dir", ".", "Boilerplate directory for boilerplate files")
	rootdir        = flag.String("rootdir", "../../", "Root directory to examine")
)

func main() {
	flag.Parse()
	refs, err := extensionToBoilerplate(*boilerplatedir)
	if err != nil {
		log.Fatal(err)
	}
	if len(refs) == 0 {
		log.Fatal("no references in ", *boilerplatedir)
	}
	files, err := filesToCheck(*rootdir, refs)
	if err != nil {
		log.Fatal(err)
	}
	for _, file := range files {
		pass, err := filePasses(file, refs[fileExtension(file)])
		if err != nil {
			log.Println(err)
		}
		if !pass {
			path, err := filepath.Abs(file)
			if err != nil {
				log.Println(err)
			}
			fmt.Println(path)
		}
	}

}

// extensionToBoilerplate returns a map of file extension to required boilerplate text
func extensionToBoilerplate(dir string) (map[string][]byte, error) {
	refs := make(map[string][]byte)
	files, _ := filepath.Glob(dir + "/*.txt")
	for _, filename := range files {
		re := regexp.MustCompile(`\.txt`)
		extension := strings.ToLower(fileExtension(re.ReplaceAllString(filename, "")))
		data, err := ioutil.ReadFile(filename)
		if err != nil {
			return nil, err
		}
		re = regexp.MustCompile(`\r`)
		refs[extension] = re.ReplaceAll(data, nil)
	}
	return refs, nil
}

// filePasses checks whether the processed file is valid. Returning false means that the file does not the proper boilerplate template.
func filePasses(filename string, expectedBoilerplate []byte) (bool, error) {
	var re *regexp.Regexp
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return false, err
	}
	re = regexp.MustCompile(`\r`)
	data = re.ReplaceAll(data, nil)

	extension := fileExtension(filename)

	// remove build tags from the top of Go files
	if extension == "go" {
		re = regexp.MustCompile(`(?m)^(// \+build.*\n)+\n`)
		data = re.ReplaceAll(data, nil)
	}

	// remove shebang from the top of shell files
	if extension == "sh" {
		re = regexp.MustCompile(`(?m)^(#!.*\n)\n*`)
		data = re.ReplaceAll(data, nil)
	}

	// if our test file is smaller than the reference it surely fails!
	if len(data) < len(expectedBoilerplate) {
		return false, nil
	}

	data = data[:len(expectedBoilerplate)]

	// Search for "Copyright YEAR" which exists in the boilerplate, but shouldn't in the real thing
	re = regexp.MustCompile(`Copyright YEAR`)
	if re.Match(data) {
		return false, nil
	}

	// Replace all occurrences of the regex "Copyright \d{4}" with "Copyright YEAR"
	re = regexp.MustCompile(`Copyright \d{4}`)
	data = re.ReplaceAll(data, []byte(`Copyright YEAR`))

	return bytes.Equal(data, expectedBoilerplate), nil
}

/**
Function to get the file extensin or the filename if the file has no extension
*/
func fileExtension(filename string) string {
	splitted := strings.Split(filepath.Base(filename), ".")
	return strings.ToLower(splitted[len(splitted)-1])
}

// filesToCheck returns the list of the filers that will be checked for the boilerplate.
func filesToCheck(rootDir string, extensions map[string][]byte) ([]string, error) {
	var outFiles []string
	err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		// remove current workdir from the beginig of the path in case it matches the skipped path
		cwd, _ := os.Getwd()
		// replace "\" with "\\" for windows style path
		re := regexp.MustCompile(`\\`)
		re = regexp.MustCompile(`^` + re.ReplaceAllString(cwd, `\\`))
		if !info.IsDir() && !skippedPaths.MatchString(re.ReplaceAllString(filepath.Dir(path), "")) {
			if extensions[strings.ToLower(fileExtension(path))] != nil {
				outFiles = append(outFiles, path)
			}
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return outFiles, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 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.

// +build mips mipsle

package atomic

import (
	"runtime/internal/sys"
	"unsafe"
)

// TODO implement lock striping
var lock struct {
	state uint32
	pad   [sys.CacheLineSize - 4]byte
}

//go:noescape
func spinLock(state *uint32)

//go:noescape
func spinUnlock(state *uint32)

//go:nosplit
func lockAndCheck(addr *uint64) {
	// ensure 8-byte alignement
	if uintptr(unsafe.Pointer(addr))&7 != 0 {
		addr = nil
	}
	// force dereference before taking lock
	_ = *addr

	spinLock(&lock.state)
}

//go:nosplit
func unlock() {
	spinUnlock(&lock.state)
}

//go:nosplit
func unlockNoFence() {
	lock.state = 0
}

//go:nosplit
func Xadd64(addr *uint64, delta int64) (new uint64) {
	lockAndCheck(addr)

	new = *addr + uint64(delta)
	*addr = new

	unlock()
	return
}

//go:nosplit
func Xchg64(addr *uint64, new uint64) (old uint64) {
	lockAndCheck(addr)

	old = *addr
	*addr = new

	unlock()
	return
}

//go:nosplit
func Cas64(addr *uint64, old, new uint64) (swapped bool) {
	lockAndCheck(addr)

	if (*addr) == old {
		*addr = new
		unlock()
		return true
	}

	unlockNoFence()
	return false
}

//go:nosplit
func Load64(addr *uint64) (val uint64) {
	lockAndCheck(addr)

	val = *addr

	unlock()
	return
}

//go:nosplit
func Store64(addr *uint64, val uint64) {
	lockAndCheck(addr)

	*addr = val

	unlock()
	return
}

//go:noescape
func Xadd(ptr *uint32, delta int32) uint32

//go:noescape
func Xadduintptr(ptr *uintptr, delta uintptr) uintptr

//go:noescape
func Xchg(ptr *uint32, new uint32) uint32

//go:noescape
func Xchguintptr(ptr *uintptr, new uintptr) uintptr

//go:noescape
func Load(ptr *uint32) uint32

//go:noescape
func Loadp(ptr unsafe.Pointer) unsafe.Pointer

//go:noescape
func And8(ptr *uint8, val uint8)

//go:noescape
func Or8(ptr *uint8, val uint8)

//go:noescape
func Store(ptr *uint32, val uint32)

// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
<commit_msg>runtime: fix typo in comment<commit_after>// Copyright 2016 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.

// +build mips mipsle

package atomic

import (
	"runtime/internal/sys"
	"unsafe"
)

// TODO implement lock striping
var lock struct {
	state uint32
	pad   [sys.CacheLineSize - 4]byte
}

//go:noescape
func spinLock(state *uint32)

//go:noescape
func spinUnlock(state *uint32)

//go:nosplit
func lockAndCheck(addr *uint64) {
	// ensure 8-byte alignment
	if uintptr(unsafe.Pointer(addr))&7 != 0 {
		addr = nil
	}
	// force dereference before taking lock
	_ = *addr

	spinLock(&lock.state)
}

//go:nosplit
func unlock() {
	spinUnlock(&lock.state)
}

//go:nosplit
func unlockNoFence() {
	lock.state = 0
}

//go:nosplit
func Xadd64(addr *uint64, delta int64) (new uint64) {
	lockAndCheck(addr)

	new = *addr + uint64(delta)
	*addr = new

	unlock()
	return
}

//go:nosplit
func Xchg64(addr *uint64, new uint64) (old uint64) {
	lockAndCheck(addr)

	old = *addr
	*addr = new

	unlock()
	return
}

//go:nosplit
func Cas64(addr *uint64, old, new uint64) (swapped bool) {
	lockAndCheck(addr)

	if (*addr) == old {
		*addr = new
		unlock()
		return true
	}

	unlockNoFence()
	return false
}

//go:nosplit
func Load64(addr *uint64) (val uint64) {
	lockAndCheck(addr)

	val = *addr

	unlock()
	return
}

//go:nosplit
func Store64(addr *uint64, val uint64) {
	lockAndCheck(addr)

	*addr = val

	unlock()
	return
}

//go:noescape
func Xadd(ptr *uint32, delta int32) uint32

//go:noescape
func Xadduintptr(ptr *uintptr, delta uintptr) uintptr

//go:noescape
func Xchg(ptr *uint32, new uint32) uint32

//go:noescape
func Xchguintptr(ptr *uintptr, new uintptr) uintptr

//go:noescape
func Load(ptr *uint32) uint32

//go:noescape
func Loadp(ptr unsafe.Pointer) unsafe.Pointer

//go:noescape
func And8(ptr *uint8, val uint8)

//go:noescape
func Or8(ptr *uint8, val uint8)

//go:noescape
func Store(ptr *uint32, val uint32)

// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
<|endoftext|>


<commit_before>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime"
)

var (
	cfg *config
)

// btcdMain is the real main function for btcd.  It is necessary to work around
// the fact that deferred functions do not run when os.Exit() is called.
func btcdMain() error {
	// Initialize logging and setup deferred flushing to ensure all
	// outstanding messages are written on shutdown.
	loggers := setLogLevel(defaultLogLevel)
	defer func() {
		for _, logger := range loggers {
			logger.Flush()
		}
	}()

	// Load configuration and parse command line.
	tcfg, _, err := loadConfig()
	if err != nil {
		return err
	}
	cfg = tcfg

	// Change the logging level if needed.
	if cfg.DebugLevel != defaultLogLevel {
		loggers = setLogLevel(cfg.DebugLevel)
	}

	// Show version at startup.
	log.Infof("Version %s", version())

	// See if we want to enable profiling.
	if cfg.Profile != "" {
		go func() {
			listenAddr := net.JoinHostPort("", cfg.Profile)
			log.Infof("Profile server listening on %s", listenAddr)
			log.Errorf("%v", http.ListenAndServe(listenAddr, nil))
		}()
	}

	// Perform upgrades to btcd as new versions require it.
	if err := doUpgrades(); err != nil {
		log.Errorf("%v", err)
		return err
	}

	// Load the block database.
	db, err := loadBlockDB()
	if err != nil {
		log.Errorf("%v", err)
		return err
	}
	defer db.Close()

	// Ensure the database is sync'd and closed on Ctrl+C.
	addInterruptHandler(func() {
		db.RollbackClose()
	})

	// Create server and start it.
	listenAddr := net.JoinHostPort("", cfg.Port)
	server, err := newServer(listenAddr, db, activeNetParams.btcnet)
	if err != nil {
		log.Errorf("Unable to start server on %v: %v", listenAddr, err)
		return err
	}
	server.Start()

	server.WaitForShutdown()
	return nil
}

func main() {
	// Use all processor cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Up some limits.
	if err := setLimits(); err != nil {
		os.Exit(1)
	}

	// Work around defer not working after os.Exit()
	if err := btcdMain(); err != nil {
		os.Exit(1)
	}
}
<commit_msg>Add default redirect for profiling when enabled.<commit_after>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime"
)

var (
	cfg *config
)

// btcdMain is the real main function for btcd.  It is necessary to work around
// the fact that deferred functions do not run when os.Exit() is called.
func btcdMain() error {
	// Initialize logging and setup deferred flushing to ensure all
	// outstanding messages are written on shutdown.
	loggers := setLogLevel(defaultLogLevel)
	defer func() {
		for _, logger := range loggers {
			logger.Flush()
		}
	}()

	// Load configuration and parse command line.
	tcfg, _, err := loadConfig()
	if err != nil {
		return err
	}
	cfg = tcfg

	// Change the logging level if needed.
	if cfg.DebugLevel != defaultLogLevel {
		loggers = setLogLevel(cfg.DebugLevel)
	}

	// Show version at startup.
	log.Infof("Version %s", version())

	// See if we want to enable profiling.
	if cfg.Profile != "" {
		go func() {
			listenAddr := net.JoinHostPort("", cfg.Profile)
			log.Infof("Profile server listening on %s", listenAddr)
			profileRedirect := http.RedirectHandler("/debug/pprof",
				http.StatusSeeOther)
			http.Handle("/", profileRedirect)
			log.Errorf("%v", http.ListenAndServe(listenAddr, nil))
		}()
	}

	// Perform upgrades to btcd as new versions require it.
	if err := doUpgrades(); err != nil {
		log.Errorf("%v", err)
		return err
	}

	// Load the block database.
	db, err := loadBlockDB()
	if err != nil {
		log.Errorf("%v", err)
		return err
	}
	defer db.Close()

	// Ensure the database is sync'd and closed on Ctrl+C.
	addInterruptHandler(func() {
		db.RollbackClose()
	})

	// Create server and start it.
	listenAddr := net.JoinHostPort("", cfg.Port)
	server, err := newServer(listenAddr, db, activeNetParams.btcnet)
	if err != nil {
		log.Errorf("Unable to start server on %v: %v", listenAddr, err)
		return err
	}
	server.Start()

	server.WaitForShutdown()
	return nil
}

func main() {
	// Use all processor cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Up some limits.
	if err := setLimits(); err != nil {
		os.Exit(1)
	}

	// Work around defer not working after os.Exit()
	if err := btcdMain(); err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/urfave/cli"
	"context"
)

const (
	CommandName  = ""
	CommandUsage = ""
)

func Action(c *cli.Context) error {
	return nil
}

func Command() *cli.Command {
	return &cli.Command{
		Name:   CommandName,
		Usage:  CommandUsage,
		Action: Action,
	}
}

<commit_msg>Removed corrupted file<commit_after><|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

const (
	confVersion = "1"
)

var (
	errNeedReconfigure = errors.New("Need Reconfigure")
)

type confStruct struct {
	username string
}

func firstRun() {
	var conf confStruct

	fmt.Printf("Please enter your username:")
	fmt.Scanf("%s\n", &conf.username)

	updateConf(conf, filepath.Join(flConfDir, confName))

}

func updateConf(c confStruct, f string) error {
	file, err := os.Create(f)
	if err != nil {
		return err
	}
	defer file.Close()

	fmt.Fprintf(file, "version=%d\n", confVersion)
	fmt.Fprintf(file, "username=%s\n", c.username)
	return nil
}

func readConf(f string) (*confStruct, error) {
	re := new(confStruct)

	file, err := os.Open(f)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		s := strings.SplitN(scanner.Text(), "=", 2)
		switch s[0] {
		case "username":
			re.username = s[1]
		case "version":
			if s[1] != confVersion {
				return nil, errNeedReconfigure
			}
		default:
			panic("ERROR")
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return re, nil
}
<commit_msg>fprintf confVersion as %s<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

const (
	confVersion = "1"
)

var (
	errNeedReconfigure = errors.New("Need Reconfigure")
)

type confStruct struct {
	username string
}

func firstRun() {
	var conf confStruct

	fmt.Printf("Please enter your username:")
	fmt.Scanf("%s\n", &conf.username)

	updateConf(conf, filepath.Join(flConfDir, confName))

}

func updateConf(c confStruct, f string) error {
	file, err := os.Create(f)
	if err != nil {
		return err
	}
	defer file.Close()

	fmt.Fprintf(file, "version=%s\n", confVersion)
	fmt.Fprintf(file, "username=%s\n", c.username)
	return nil
}

func readConf(f string) (*confStruct, error) {
	re := new(confStruct)

	file, err := os.Open(f)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		s := strings.SplitN(scanner.Text(), "=", 2)
		switch s[0] {
		case "username":
			re.username = s[1]
		case "version":
			if s[1] != confVersion {
				return nil, errNeedReconfigure
			}
		default:
			panic("ERROR")
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return re, nil
}
<|endoftext|>


<commit_before>package pqx

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
)

type conn struct {
	conn          net.Conn          // the underlying TCP or unix domain socket connection
	buf           []byte            // work buffer to avoid constant alloc and dealloc
	pid           int32             // backend pid
	secretKey     int32             // key to use to send a cancel query message to the server
	runtimeParams map[string]string // parameters that have been reported by the server
	txStatus      byte
}

func Connect(options map[string]string) (c *conn, err error) {
	c = new(conn)

	var present bool
	var socket string

	if socket, present = options["socket"]; present {
		c.conn, err = net.Dial("unix", socket)
		if err != nil {
			return nil, err
		}
	}

	c.buf = make([]byte, 1024)
	c.runtimeParams = make(map[string]string)

	// conn, err := net.Dial("tcp", "localhost:5432")

	msg := newStartupMessage()
	msg.options["user"] = "jack"
	c.txStartupMessage(msg)

	for {
		var t byte
		var r *messageReader
		if t, r, err = c.rxMsg(); err == nil {
			switch t {
			case backendKeyData:
				c.rxBackendKeyData(r)
			case authenticationX:
				c.rxAuthenticationX(r)
			case readyForQuery:
				return c, nil
			default:
				if err = c.processContextFreeMsg(t, r); err != nil {
					return nil, err
				}
			}
		} else {
			return nil, err
		}
	}

	panic("Unreachable")
}

func (c *conn) Close() (err error) {
	buf := c.getBuf(5)
	buf[0] = 'X'
	binary.BigEndian.PutUint32(buf[1:], 4)
	_, err = c.conn.Write(buf)
	return
}

func (c *conn) Query(sql string) (rows []map[string]string, err error) {
	if err = c.sendSimpleQuery(sql); err != nil {
		return
	}

	var fields []fieldDescription
	for {
		var t byte
		var r *messageReader
		if t, r, err = c.rxMsg(); err == nil {
			switch t {
			case readyForQuery:
				return nil, nil
			case rowDescription:
				fields = c.rxRowDescription(r)
			case dataRow:
				c.rxDataRow(r, fields)
			case commandComplete:
				c.rxCommandComplete(r)
			default:
				if err = c.processContextFreeMsg(t, r); err != nil {
					return nil, err
				}
			}
		} else {
			return nil, err
		}
	}

	panic("Unreachable")
}

func (c *conn) sendSimpleQuery(sql string) (err error) {
	bufSize := 5 + len(sql) + 1 // message identifier (1), message size (4), null string terminator (1)
	buf := c.getBuf(bufSize)
	buf[0] = 'Q'
	binary.BigEndian.PutUint32(buf[1:5], uint32(bufSize-1))
	copy(buf[5:], sql)
	buf[bufSize-1] = 0

	_, err = c.conn.Write(buf)
	return err
}

// Processes messages that are not exclusive to one context such as
// authentication or query response. The response to these messages
// is the same regardless of when they occur.
func (c *conn) processContextFreeMsg(t byte, r *messageReader) (err error) {
	switch t {
	case 'S':
		c.rxParameterStatus(r)
		return nil
	default:
		return fmt.Errorf("Received unknown message type: %c", t)
	}

	panic("Unreachable")

}

func (c *conn) rxMsg() (t byte, r *messageReader, err error) {
	var bodySize int32
	t, bodySize, err = c.rxMsgHeader()
	if err != nil {
		return
	}

	var body []byte
	if body, err = c.rxMsgBody(bodySize); err != nil {
		return
	}

	r = newMessageReader(body)
	return
}

func (c *conn) rxMsgHeader() (t byte, bodySize int32, err error) {
	buf := c.buf[:5]
	if _, err = io.ReadFull(c.conn, buf); err != nil {
		return 0, 0, err
	}

	t = buf[0]
	bodySize = int32(binary.BigEndian.Uint32(buf[1:5])) - 4
	return t, bodySize, nil
}

func (c *conn) rxMsgBody(bodySize int32) (buf []byte, err error) {
	buf = c.getBuf(int(bodySize))
	_, err = io.ReadFull(c.conn, buf)
	return
}

func (c *conn) rxAuthenticationX(r *messageReader) (err error) {
	code := r.readInt32()
	switch code {
	case 0: // AuthenticationOk
	default:
		err = errors.New("Received unknown authentication message")
	}

	return
}

func (c *conn) rxParameterStatus(r *messageReader) {
	key := r.readString()
	value := r.readString()
	c.runtimeParams[key] = value
}

func (c *conn) rxBackendKeyData(r *messageReader) {
	c.pid = r.readInt32()
	c.secretKey = r.readInt32()
}

func (c *conn) rxReadyForQuery(r *messageReader) {
	c.txStatus = r.readByte()
}

func (c *conn) rxRowDescription(r *messageReader) (fields []fieldDescription) {
	fieldCount := r.readInt16()
	fields = make([]fieldDescription, fieldCount)
	for i := int16(0); i < fieldCount; i++ {
		f := &fields[i]
		f.name = r.readString()
		f.table = r.readOid()
		f.attributeNumber = r.readInt16()
		f.dataType = r.readOid()
		f.dataTypeSize = r.readInt16()
		f.modifier = r.readInt32()
		f.formatCode = r.readInt16()
	}
	return
}

func (c *conn) rxDataRow(r *messageReader, fields []fieldDescription) (row map[string]string, err error) {
	fieldCount := r.readInt16()

	row = make(map[string]string, fieldCount)
	for i := int16(0); i < fieldCount; i++ {
		// TODO - handle nulls
		size := r.readInt32()
		row[fields[i].name] = r.readByteString(size)
	}
	return
}

func (c *conn) rxCommandComplete(r *messageReader) string {
	return r.readString()
}

func (c *conn) txStartupMessage(msg *startupMessage) (err error) {
	_, err = c.conn.Write(msg.Bytes())
	return
}

// Gets a []byte of n length. If possible it will reuse the connection buffer
// otherwise it will allocate a new buffer
func (c *conn) getBuf(n int) (buf []byte) {
	if n <= cap(c.buf) {
		buf = c.buf[:n]
	} else {
		buf = make([]byte, n)
	}
	return
}
<commit_msg>Added basic Query functionality<commit_after>package pqx

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
)

type conn struct {
	conn          net.Conn          // the underlying TCP or unix domain socket connection
	buf           []byte            // work buffer to avoid constant alloc and dealloc
	pid           int32             // backend pid
	secretKey     int32             // key to use to send a cancel query message to the server
	runtimeParams map[string]string // parameters that have been reported by the server
	txStatus      byte
}

func Connect(options map[string]string) (c *conn, err error) {
	c = new(conn)

	var present bool
	var socket string

	if socket, present = options["socket"]; present {
		c.conn, err = net.Dial("unix", socket)
		if err != nil {
			return nil, err
		}
	}

	c.buf = make([]byte, 1024)
	c.runtimeParams = make(map[string]string)

	// conn, err := net.Dial("tcp", "localhost:5432")

	msg := newStartupMessage()
	msg.options["user"] = "jack"
	c.txStartupMessage(msg)

	for {
		var t byte
		var r *messageReader
		if t, r, err = c.rxMsg(); err == nil {
			switch t {
			case backendKeyData:
				c.rxBackendKeyData(r)
			case authenticationX:
				c.rxAuthenticationX(r)
			case readyForQuery:
				return c, nil
			default:
				if err = c.processContextFreeMsg(t, r); err != nil {
					return nil, err
				}
			}
		} else {
			return nil, err
		}
	}

	panic("Unreachable")
}

func (c *conn) Close() (err error) {
	buf := c.getBuf(5)
	buf[0] = 'X'
	binary.BigEndian.PutUint32(buf[1:], 4)
	_, err = c.conn.Write(buf)
	return
}

func (c *conn) Query(sql string) (rows []map[string]string, err error) {
	if err = c.sendSimpleQuery(sql); err != nil {
		return
	}

	var fields []fieldDescription
	rows = make([]map[string]string, 0)
	for {
		var t byte
		var r *messageReader
		if t, r, err = c.rxMsg(); err == nil {
			switch t {
			case readyForQuery:
				return rows, nil
			case rowDescription:
				fields = c.rxRowDescription(r)
			case dataRow:
				rows = append(rows, c.rxDataRow(r, fields))
			case commandComplete:
				c.rxCommandComplete(r)
			default:
				if err = c.processContextFreeMsg(t, r); err != nil {
					return nil, err
				}
			}
		} else {
			return nil, err
		}
	}

	panic("Unreachable")
}

func (c *conn) sendSimpleQuery(sql string) (err error) {
	bufSize := 5 + len(sql) + 1 // message identifier (1), message size (4), null string terminator (1)
	buf := c.getBuf(bufSize)
	buf[0] = 'Q'
	binary.BigEndian.PutUint32(buf[1:5], uint32(bufSize-1))
	copy(buf[5:], sql)
	buf[bufSize-1] = 0

	_, err = c.conn.Write(buf)
	return err
}

// Processes messages that are not exclusive to one context such as
// authentication or query response. The response to these messages
// is the same regardless of when they occur.
func (c *conn) processContextFreeMsg(t byte, r *messageReader) (err error) {
	switch t {
	case 'S':
		c.rxParameterStatus(r)
		return nil
	default:
		return fmt.Errorf("Received unknown message type: %c", t)
	}

	panic("Unreachable")

}

func (c *conn) rxMsg() (t byte, r *messageReader, err error) {
	var bodySize int32
	t, bodySize, err = c.rxMsgHeader()
	if err != nil {
		return
	}

	var body []byte
	if body, err = c.rxMsgBody(bodySize); err != nil {
		return
	}

	r = newMessageReader(body)
	return
}

func (c *conn) rxMsgHeader() (t byte, bodySize int32, err error) {
	buf := c.buf[:5]
	if _, err = io.ReadFull(c.conn, buf); err != nil {
		return 0, 0, err
	}

	t = buf[0]
	bodySize = int32(binary.BigEndian.Uint32(buf[1:5])) - 4
	return t, bodySize, nil
}

func (c *conn) rxMsgBody(bodySize int32) (buf []byte, err error) {
	buf = c.getBuf(int(bodySize))
	_, err = io.ReadFull(c.conn, buf)
	return
}

func (c *conn) rxAuthenticationX(r *messageReader) (err error) {
	code := r.readInt32()
	switch code {
	case 0: // AuthenticationOk
	default:
		err = errors.New("Received unknown authentication message")
	}

	return
}

func (c *conn) rxParameterStatus(r *messageReader) {
	key := r.readString()
	value := r.readString()
	c.runtimeParams[key] = value
}

func (c *conn) rxBackendKeyData(r *messageReader) {
	c.pid = r.readInt32()
	c.secretKey = r.readInt32()
}

func (c *conn) rxReadyForQuery(r *messageReader) {
	c.txStatus = r.readByte()
}

func (c *conn) rxRowDescription(r *messageReader) (fields []fieldDescription) {
	fieldCount := r.readInt16()
	fields = make([]fieldDescription, fieldCount)
	for i := int16(0); i < fieldCount; i++ {
		f := &fields[i]
		f.name = r.readString()
		f.table = r.readOid()
		f.attributeNumber = r.readInt16()
		f.dataType = r.readOid()
		f.dataTypeSize = r.readInt16()
		f.modifier = r.readInt32()
		f.formatCode = r.readInt16()
	}
	return
}

func (c *conn) rxDataRow(r *messageReader, fields []fieldDescription) (row map[string]string) {
	fieldCount := r.readInt16()

	row = make(map[string]string, fieldCount)
	for i := int16(0); i < fieldCount; i++ {
		// TODO - handle nulls
		size := r.readInt32()
		row[fields[i].name] = r.readByteString(size)
	}
	return
}

func (c *conn) rxCommandComplete(r *messageReader) string {
	return r.readString()
}

func (c *conn) txStartupMessage(msg *startupMessage) (err error) {
	_, err = c.conn.Write(msg.Bytes())
	return
}

// Gets a []byte of n length. If possible it will reuse the connection buffer
// otherwise it will allocate a new buffer
func (c *conn) getBuf(n int) (buf []byte) {
	if n <= cap(c.buf) {
		buf = c.buf[:n]
	} else {
		buf = make([]byte, n)
	}
	return
}
<|endoftext|>


<commit_before>package osc

import (
	"errors"
	"net"
	"strings"
)

const (
	readBufSize = 4096
)

// Common errors.
var (
	errBundle         = errors.New("message is a bundle")
	ErrNilDispatcher  = errors.New("nil dispatcher")
	ErrPrematureClose = errors.New("server cannot be closed before calling Listen")
	networkTCP        = "tcp"
	networkUDP        = "udp"
)

// Conn defines the methods
type Conn interface {
	net.Conn
	Serve(Dispatcher) error
	Send(*Message) error
}

var invalidAddressRunes = []rune{'*', '?', ',', '[', ']', '{', '}', '#', ' '}

func validateAddress(addr string) error {
	for _, chr := range invalidAddressRunes {
		if strings.ContainsRune(addr, chr) {
			return ErrInvalidAddress
		}
	}
	return nil
}
<commit_msg>fix Send signature for osc.Conn<commit_after>package osc

import (
	"errors"
	"net"
	"strings"
)

const (
	readBufSize = 4096
)

// Common errors.
var (
	errBundle         = errors.New("message is a bundle")
	ErrNilDispatcher  = errors.New("nil dispatcher")
	ErrPrematureClose = errors.New("server cannot be closed before calling Listen")
	networkTCP        = "tcp"
	networkUDP        = "udp"
)

// Conn defines the methods
type Conn interface {
	net.Conn
	Serve(Dispatcher) error
	Send(Packet) error
}

var invalidAddressRunes = []rune{'*', '?', ',', '[', ']', '{', '}', '#', ' '}

func validateAddress(addr string) error {
	for _, chr := range invalidAddressRunes {
		if strings.ContainsRune(addr, chr) {
			return ErrInvalidAddress
		}
	}
	return nil
}
<|endoftext|>