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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements the parser.

package golisp

import (
	"errors"
	"fmt"
	"io/ioutil"
	"unsafe"
)

func makeInteger(str string) (n *Data, err error) {
	var i int64
	_, err = fmt.Sscanf(str, "%d", &i)
	if err != nil {
		return
	}
	n = IntegerWithValue(i)
	return
}

func makeHexInteger(str string) (n *Data, err error) {
	var i int64
	_, err = fmt.Sscanf(str, "%v", &i)
	if err != nil {
		return
	}
	n = IntegerWithValue(i)
	return
}

func makeFloat(str string) (n *Data, err error) {
	var i float32
	_, err = fmt.Sscanf(str, "%f", &i)
	if err != nil {
		return
	}
	n = FloatWithValue(i)
	return
}

func makeString(str string) (s *Data, err error) {
	s = StringWithValue(str)
	return
}

func makeSymbol(str string) (s *Data, err error) {
	s = Intern(str)
	return
}

func parseConsCell(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	tok, _ := s.NextToken()
	if tok == RPAREN {
		s.ConsumeToken()
		sexpr = nil
		return
	}

	var car *Data
	var cdr *Data
	cells := make([]*Data, 0, 10)
	for tok != RPAREN {
		if tok == PERIOD {
			s.ConsumeToken()
			cdr, eof, err = parseExpression(s)
			if eof || err != nil {
				return
			}
			tok, _ = s.NextToken()
			if tok != RPAREN {
				err = errors.New("Expected ')'")
				return
			}
			s.ConsumeToken()
			sexpr = ArrayToListWithTail(cells, cdr)
			return
		} else {
			car, eof, err = parseExpression(s)
			if eof {
				err = errors.New("Unexpected EOF (expected closing parenthesis)")
				return
			}
			if err != nil {
				return
			}
			cells = append(cells, car)
		}
		tok, _ = s.NextToken()
	}

	s.ConsumeToken()
	sexpr = ArrayToList(cells)
	return
}

func allIntegers(data []*Data) bool {
	for _, n := range data {
		if !IntegerP(n) {
			return false
		}
	}
	return true
}

func listToBytearray(cells []*Data) *Data {
	bytes := make([]byte, 0, len(cells))
	for _, cell := range cells {
		b := IntegerValue(cell)
		bytes = append(bytes, byte(b))
	}
	return ObjectWithTypeAndValue("[]byte", unsafe.Pointer(&bytes))
}

func parseBytearray(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	tok, _ := s.NextToken()
	if tok == RBRACKET {
		s.ConsumeToken()
		bytes := make([]byte, 0)
		sexpr = ObjectWithTypeAndValue("[]byte", unsafe.Pointer(&bytes))
		return
	}

	var element *Data
	cells := make([]*Data, 0, 10)
	for tok != RBRACKET {
		element, eof, err = parseExpression(s)
		if eof {
			err = errors.New("Unexpected EOF (expected closing bracket)")
			return
		}
		if err != nil {
			return
		}
		if IntegerP(element) && IntegerValue(element) > 255 {
			err = errors.New(fmt.Sprintf("Numeric literals in a bytearray must be bytes. Encountered %s.", String(element)))
			return
		}
		if !IntegerP(element) && !SymbolP(element) && !ListP(element) {
			err = errors.New(fmt.Sprintf("Bytearray elements must be numbers, symbols, or lists (function calls). Encountered %s.", String(element)))
			return
		}
		cells = append(cells, element)
		tok, _ = s.NextToken()
	}

	s.ConsumeToken()
	if allIntegers(cells) {
		sexpr = listToBytearray(cells)
	} else {
		sexpr = InternalMakeList(Intern("list-to-bytearray"), QuoteIt(ArrayToList(cells)))
	}
	return
}

func parseFrame(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	tok, _ := s.NextToken()
	if tok == RBRACKET {
		s.ConsumeToken()
		f := make(FrameMap)
		sexpr = FrameWithValue(&f)
		return
	}

	var element *Data
	cells := make([]*Data, 0, 10)
	for tok != RBRACE {
		element, eof, err = parseExpression(s)
		if eof {
			err = errors.New("Unexpected EOF (expected closing brace)")
			return
		}
		if err != nil {
			return
		}
		cells = append(cells, element)
		tok, _ = s.NextToken()
	}

	s.ConsumeToken()
	sexpr = Cons(Intern("make-frame"), ArrayToList(cells))
	return
}

func parseExpression(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	for {
		tok, lit := s.NextToken()
		switch tok {
		case EOF:
			eof = true
			err = nil
			return
		case COMMENT:
			s.ConsumeToken()
			break
		case NUMBER:
			s.ConsumeToken()
			sexpr, err = makeInteger(lit)
			return
		case HEXNUMBER:
			s.ConsumeToken()
			sexpr, err = makeHexInteger(lit)
			return
		case FLOAT:
			s.ConsumeToken()
			sexpr, err = makeFloat(lit)
			return
		case STRING:
			s.ConsumeToken()
			sexpr, err = makeString(lit)
			return
		case LPAREN:
			s.ConsumeToken()
			sexpr, eof, err = parseConsCell(s)
			return
		case LBRACKET:
			s.ConsumeToken()
			sexpr, eof, err = parseBytearray(s)
			return
		case LBRACE:
			s.ConsumeToken()
			sexpr, eof, err = parseFrame(s)
			return
		case SYMBOL:
			s.ConsumeToken()
			sexpr, err = makeSymbol(lit)
			return
		case FALSE:
			s.ConsumeToken()
			sexpr = LispFalse
			return
		case TRUE:
			s.ConsumeToken()
			sexpr = LispTrue
			return
		case QUOTE:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("quote"), Cons(sexpr, nil))
			}
			return
		case BACKQUOTE:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("quasiquote"), Cons(sexpr, nil))
			}
			return
		case COMMA:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("unquote"), Cons(sexpr, nil))
			}
			return
		case COMMAAT:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("unquote-splicing"), Cons(sexpr, nil))
			}
			return
		case ILLEGAL:
			err = errors.New(fmt.Sprintf("Illegal character: %s", lit))
			return
		default:
			s.ConsumeToken()
			sexpr, err = makeSymbol(lit)
			return
		}
	}
}

func Parse(src string) (sexpr *Data, err error) {
	s := NewTokenizer(src)
	sexpr, _, err = parseExpression(s)
	return
}

func ParseAll(src string) (result []*Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	var eof bool
	for {
		sexpr, eof, err = parseExpression(s)
		if err != nil || eof {
			break
		}
		result = append(result, sexpr)
	}
	return
}

func ReadFile(filename string) (s string, err error) {
	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	s = *(*string)(unsafe.Pointer(&contents))
	return
}

func ProcessFile(filename string) (result *Data, err error) {
	src, err := ReadFile(filename)
	if err != nil {
		return
	}
	result, err = ParseAndEvalAll(src)
	return
}

func ParseAndEvalAll(src string) (result *Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	var eof bool
	for {
		sexpr, eof, err = parseExpression(s)
		if err != nil {
			return
		}
		if eof {
			return
		}
		if NilP(sexpr) {
			return
		}
		result, err = Eval(sexpr, Global)
		if err != nil {
			return
		}
	}
	return
}

func ParseAndEval(src string) (result *Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	sexpr, _, err = parseExpression(s)
	if err != nil {
		return
	}
	if NilP(sexpr) {
		return
	}
	result, err = Eval(sexpr, Global)
	if err != nil {
		return
	}
	return
}
<commit_msg>Add equivalents for ParseAndEval and ParseAndEvalAll for specific environments<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements the parser.

package golisp

import (
	"errors"
	"fmt"
	"io/ioutil"
	"unsafe"
)

func makeInteger(str string) (n *Data, err error) {
	var i int64
	_, err = fmt.Sscanf(str, "%d", &i)
	if err != nil {
		return
	}
	n = IntegerWithValue(i)
	return
}

func makeHexInteger(str string) (n *Data, err error) {
	var i int64
	_, err = fmt.Sscanf(str, "%v", &i)
	if err != nil {
		return
	}
	n = IntegerWithValue(i)
	return
}

func makeFloat(str string) (n *Data, err error) {
	var i float32
	_, err = fmt.Sscanf(str, "%f", &i)
	if err != nil {
		return
	}
	n = FloatWithValue(i)
	return
}

func makeString(str string) (s *Data, err error) {
	s = StringWithValue(str)
	return
}

func makeSymbol(str string) (s *Data, err error) {
	s = Intern(str)
	return
}

func parseConsCell(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	tok, _ := s.NextToken()
	if tok == RPAREN {
		s.ConsumeToken()
		sexpr = nil
		return
	}

	var car *Data
	var cdr *Data
	cells := make([]*Data, 0, 10)
	for tok != RPAREN {
		if tok == PERIOD {
			s.ConsumeToken()
			cdr, eof, err = parseExpression(s)
			if eof || err != nil {
				return
			}
			tok, _ = s.NextToken()
			if tok != RPAREN {
				err = errors.New("Expected ')'")
				return
			}
			s.ConsumeToken()
			sexpr = ArrayToListWithTail(cells, cdr)
			return
		} else {
			car, eof, err = parseExpression(s)
			if eof {
				err = errors.New("Unexpected EOF (expected closing parenthesis)")
				return
			}
			if err != nil {
				return
			}
			cells = append(cells, car)
		}
		tok, _ = s.NextToken()
	}

	s.ConsumeToken()
	sexpr = ArrayToList(cells)
	return
}

func allIntegers(data []*Data) bool {
	for _, n := range data {
		if !IntegerP(n) {
			return false
		}
	}
	return true
}

func listToBytearray(cells []*Data) *Data {
	bytes := make([]byte, 0, len(cells))
	for _, cell := range cells {
		b := IntegerValue(cell)
		bytes = append(bytes, byte(b))
	}
	return ObjectWithTypeAndValue("[]byte", unsafe.Pointer(&bytes))
}

func parseBytearray(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	tok, _ := s.NextToken()
	if tok == RBRACKET {
		s.ConsumeToken()
		bytes := make([]byte, 0)
		sexpr = ObjectWithTypeAndValue("[]byte", unsafe.Pointer(&bytes))
		return
	}

	var element *Data
	cells := make([]*Data, 0, 10)
	for tok != RBRACKET {
		element, eof, err = parseExpression(s)
		if eof {
			err = errors.New("Unexpected EOF (expected closing bracket)")
			return
		}
		if err != nil {
			return
		}
		if IntegerP(element) && IntegerValue(element) > 255 {
			err = errors.New(fmt.Sprintf("Numeric literals in a bytearray must be bytes. Encountered %s.", String(element)))
			return
		}
		if !IntegerP(element) && !SymbolP(element) && !ListP(element) {
			err = errors.New(fmt.Sprintf("Bytearray elements must be numbers, symbols, or lists (function calls). Encountered %s.", String(element)))
			return
		}
		cells = append(cells, element)
		tok, _ = s.NextToken()
	}

	s.ConsumeToken()
	if allIntegers(cells) {
		sexpr = listToBytearray(cells)
	} else {
		sexpr = InternalMakeList(Intern("list-to-bytearray"), QuoteIt(ArrayToList(cells)))
	}
	return
}

func parseFrame(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	tok, _ := s.NextToken()
	if tok == RBRACKET {
		s.ConsumeToken()
		f := make(FrameMap)
		sexpr = FrameWithValue(&f)
		return
	}

	var element *Data
	cells := make([]*Data, 0, 10)
	for tok != RBRACE {
		element, eof, err = parseExpression(s)
		if eof {
			err = errors.New("Unexpected EOF (expected closing brace)")
			return
		}
		if err != nil {
			return
		}
		cells = append(cells, element)
		tok, _ = s.NextToken()
	}

	s.ConsumeToken()
	sexpr = Cons(Intern("make-frame"), ArrayToList(cells))
	return
}

func parseExpression(s *Tokenizer) (sexpr *Data, eof bool, err error) {
	for {
		tok, lit := s.NextToken()
		switch tok {
		case EOF:
			eof = true
			err = nil
			return
		case COMMENT:
			s.ConsumeToken()
			break
		case NUMBER:
			s.ConsumeToken()
			sexpr, err = makeInteger(lit)
			return
		case HEXNUMBER:
			s.ConsumeToken()
			sexpr, err = makeHexInteger(lit)
			return
		case FLOAT:
			s.ConsumeToken()
			sexpr, err = makeFloat(lit)
			return
		case STRING:
			s.ConsumeToken()
			sexpr, err = makeString(lit)
			return
		case LPAREN:
			s.ConsumeToken()
			sexpr, eof, err = parseConsCell(s)
			return
		case LBRACKET:
			s.ConsumeToken()
			sexpr, eof, err = parseBytearray(s)
			return
		case LBRACE:
			s.ConsumeToken()
			sexpr, eof, err = parseFrame(s)
			return
		case SYMBOL:
			s.ConsumeToken()
			sexpr, err = makeSymbol(lit)
			return
		case FALSE:
			s.ConsumeToken()
			sexpr = LispFalse
			return
		case TRUE:
			s.ConsumeToken()
			sexpr = LispTrue
			return
		case QUOTE:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("quote"), Cons(sexpr, nil))
			}
			return
		case BACKQUOTE:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("quasiquote"), Cons(sexpr, nil))
			}
			return
		case COMMA:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("unquote"), Cons(sexpr, nil))
			}
			return
		case COMMAAT:
			s.ConsumeToken()
			sexpr, eof, err = parseExpression(s)
			if sexpr != nil {
				sexpr = Cons(Intern("unquote-splicing"), Cons(sexpr, nil))
			}
			return
		case ILLEGAL:
			err = errors.New(fmt.Sprintf("Illegal character: %s", lit))
			return
		default:
			s.ConsumeToken()
			sexpr, err = makeSymbol(lit)
			return
		}
	}
}

func Parse(src string) (sexpr *Data, err error) {
	s := NewTokenizer(src)
	sexpr, _, err = parseExpression(s)
	return
}

func ParseAll(src string) (result []*Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	var eof bool
	for {
		sexpr, eof, err = parseExpression(s)
		if err != nil || eof {
			break
		}
		result = append(result, sexpr)
	}
	return
}

func ReadFile(filename string) (s string, err error) {
	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	s = *(*string)(unsafe.Pointer(&contents))
	return
}

func ProcessFile(filename string) (result *Data, err error) {
	src, err := ReadFile(filename)
	if err != nil {
		return
	}
	result, err = ParseAndEvalAll(src)
	return
}

func ParseAndEvalAll(src string) (result *Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	var eof bool
	for {
		sexpr, eof, err = parseExpression(s)
		if err != nil {
			return
		}
		if eof {
			return
		}
		if NilP(sexpr) {
			return
		}
		result, err = Eval(sexpr, Global)
		if err != nil {
			return
		}
	}
	return
}

func ParseAndEval(src string) (result *Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	sexpr, _, err = parseExpression(s)
	if err != nil {
		return
	}
	if NilP(sexpr) {
		return
	}
	result, err = Eval(sexpr, Global)
	if err != nil {
		return
	}
	return
}

func ParseAndEvalAllInEnvironment(src string, env *SymbolTableFrame) (result *Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	var eof bool
	for {
		sexpr, eof, err = parseExpression(s)
		if err != nil {
			return
		}
		if eof {
			return
		}
		if NilP(sexpr) {
			return
		}
		result, err = Eval(sexpr, env)
		if err != nil {
			return
		}
	}
	return
}

func ParseAndEvalInEnvironment(src string, env *SymbolTableFrame) (result *Data, err error) {
	s := NewTokenizer(src)
	var sexpr *Data
	sexpr, _, err = parseExpression(s)
	if err != nil {
		return
	}
	if NilP(sexpr) {
		return
	}
	result, err = Eval(sexpr, env)
	if err != nil {
		return
	}
	return
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strconv"

	"github.com/ejcx/passgo/edit"
	"github.com/ejcx/passgo/generate"
	"github.com/ejcx/passgo/initialize"
	"github.com/ejcx/passgo/insert"
	"github.com/ejcx/passgo/pio"
	"github.com/ejcx/passgo/show"
	"github.com/spf13/cobra"
)

const (
	version = `v2.0`
)

var (
	copyPass bool
	RootCmd  = &cobra.Command{
		Use:   "passgo",
		Short: "Print the contents of the vault.",
		Long: `Print the contents of the vault. If you have
not yet initialized your vault, it is necessary to run
the init subcommand in order to create your passgo
directory, and initialize your cryptographic keys.`,
		Run: func(cmd *cobra.Command, args []string) {
			if exists, _ := pio.PassFileDirExists(); exists {
				show.ListAll()
			} else {
				cmd.Help()
			}
		},
	}
	versionCmd = &cobra.Command{
		Use:   "version",
		Short: "Print the version of your passgo binary.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println(version)
		},
	}
	initCmd = &cobra.Command{
		Use:   "init",
		Long:  "Initialize the .passgo directory, and generate your secret keys",
		Short: "Initialize your passgo vault",
		Run: func(cmd *cobra.Command, args []string) {
			initialize.Init()
		},
	}
	insertCmd = &cobra.Command{
		Use:   "insert",
		Short: "Initialize your passgo vault",
		Args:  cobra.ExactArgs(1),
		Long: `Add a site to your password store. This site can optionally be a part
		of a group by prepending a group name and slash to the site name.
		Will prompt for confirmation when a site path is not unique.`,
		Run: func(cmd *cobra.Command, args []string) {
			pathName := args[0]
			insert.Password(pathName)
		},
	}
	showCmd = &cobra.Command{
		Use:   "show",
		Short: "Print the password of a passgo entry.",
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			show.Site(path, copyPass)
		},
	}
	generateCmd = &cobra.Command{
		Use:   "generate",
		Short: "Generate a secure password",
		Long: `Prints a randomly generated password. The length of this password defaults
to 24. If a password length is specified as greater than 2048 then generate
will fail.`,
		Args: cobra.RangeArgs(0, 1),
		Run: func(cmd *cobra.Command, args []string) {
			pwlen := -1
			if len(args) != 0 {
				pwlenStr := args[0]
				pwlenint, err := strconv.Atoi(pwlenStr)
				if err != nil {
					pwlen = -1
				} else {
					pwlen = pwlenint
				}
			}
			pass := generate.Generate(pwlen)
			fmt.Println(pass)
		},
	}
	findCmd = &cobra.Command{
		Use:     "find",
		Aliases: []string{"ls"},
		Short:   "Find a site that contains the site-path.",
		Long: `Prints all sites that contain the site-path. Used to print just
one group or all sites that contain a certain word in the group or name`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			show.Find(path)
		},
	}
	renameCmd = &cobra.Command{
		Use:   "rename",
		Short: "Rename an entry in the password vault",
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.Rename(path)
		},
	}
	editCmd = &cobra.Command{
		Use:   "edit",
		Short: "Change the password of a site in the vault.",
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.Edit(path)
		},
	}
	removeCmd = &cobra.Command{
		Use:     "remove",
		Aliases: []string{"rm"},
		Short:   "Remove a site from the password vault by specifying the entire site-path.",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.RemovePassword(path)
		},
	}
	removeFileCmd = &cobra.Command{
		Use:     "remove-file",
		Aliases: []string{"rm-file", "removefile", "rmfile"},
		Short:   "Remove a file from the vault by specifying the entire file-path.",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.RemoveFile(path)
		},
	}
	insertFileCmd = &cobra.Command{
		Use:     "insert-file",
		Aliases: []string{"insertfile"},
		Short:   "Insert a file in to your vault",
		Args:    cobra.ExactArgs(2),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			filename := args[1]
			insert.File(path, filename)
		},
	}
)

func init() {
	showCmd.PersistentFlags().BoolVarP(&copyPass, "copy", "c", false, "Copy your password to the clipboard")
	RootCmd.AddCommand(findCmd)
	RootCmd.AddCommand(generateCmd)
	RootCmd.AddCommand(initCmd)
	RootCmd.AddCommand(insertCmd)
	RootCmd.AddCommand(insertFileCmd)
	RootCmd.AddCommand(removeCmd)
	RootCmd.AddCommand(removeFileCmd)
	RootCmd.AddCommand(renameCmd)
	RootCmd.AddCommand(showCmd)
	RootCmd.AddCommand(versionCmd)
}

func main() {
	RootCmd.Execute()
}
<commit_msg>Add examples to cobra commands.<commit_after>package main

import (
	"fmt"
	"strconv"

	"github.com/ejcx/passgo/edit"
	"github.com/ejcx/passgo/generate"
	"github.com/ejcx/passgo/initialize"
	"github.com/ejcx/passgo/insert"
	"github.com/ejcx/passgo/pio"
	"github.com/ejcx/passgo/show"
	"github.com/spf13/cobra"
)

const (
	version = `v2.0`
)

var (
	copyPass bool
	RootCmd  = &cobra.Command{
		Use:   "passgo",
		Short: "Print the contents of the vault.",
		Long: `Print the contents of the vault. If you have
not yet initialized your vault, it is necessary to run
the init subcommand in order to create your passgo
directory, and initialize your cryptographic keys.`,
		Run: func(cmd *cobra.Command, args []string) {
			if exists, _ := pio.PassFileDirExists(); exists {
				show.ListAll()
			} else {
				cmd.Help()
			}
		},
	}
	versionCmd = &cobra.Command{
		Use:   "version",
		Short: "Print the version of your passgo binary.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println(version)
		},
	}
	initCmd = &cobra.Command{
		Use:   "init",
		Long:  "Initialize the .passgo directory, and generate your secret keys",
		Short: "Initialize your passgo vault",
		Run: func(cmd *cobra.Command, args []string) {
			initialize.Init()
		},
	}
	insertCmd = &cobra.Command{
		Use:     "insert",
		Short:   "Initialize your passgo vault",
		Example: "passgo insert money/bank.com",
		Args:    cobra.ExactArgs(1),
		Long: `Add a site to your password store. This site can optionally be a part
of a group by prepending a group name and slash to the site name.
Will prompt for confirmation when a site path is not unique.`,
		Run: func(cmd *cobra.Command, args []string) {
			pathName := args[0]
			insert.Password(pathName)
		},
	}
	showCmd = &cobra.Command{
		Use:     "show",
		Example: "passgo show money/bank.com",
		Short:   "Print the password of a passgo entry.",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			show.Site(path, copyPass)
		},
	}
	generateCmd = &cobra.Command{
		Use:     "generate",
		Short:   "Generate a secure password",
		Example: "passgo generate",
		Long: `Prints a randomly generated password. The length of this password defaults
to 24. If a password length is specified as greater than 2048 then generate
will fail.`,
		Args: cobra.RangeArgs(0, 1),
		Run: func(cmd *cobra.Command, args []string) {
			pwlen := -1
			if len(args) != 0 {
				pwlenStr := args[0]
				pwlenint, err := strconv.Atoi(pwlenStr)
				if err != nil {
					pwlen = -1
				} else {
					pwlen = pwlenint
				}
			}
			pass := generate.Generate(pwlen)
			fmt.Println(pass)
		},
	}
	findCmd = &cobra.Command{
		Use:     "find",
		Aliases: []string{"ls"},
		Example: "passgo find bank.com",
		Short:   "Find a site that contains the site-path.",
		Long: `Prints all sites that contain the site-path. Used to print just
one group or all sites that contain a certain word in the group or name`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			show.Find(path)
		},
	}
	renameCmd = &cobra.Command{
		Use:     "rename",
		Short:   "Rename an entry in the password vault",
		Example: "passgo rename money/bank.com",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.Rename(path)
		},
	}
	editCmd = &cobra.Command{
		Use:     "edit",
		Aliases: []string{"update"},
		Short:   "Change the password of a site in the vault.",
		Example: "passgo edit money/bank.com",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.Edit(path)
		},
	}
	removeCmd = &cobra.Command{
		Use:     "remove",
		Aliases: []string{"rm"},
		Example: "passgo remove money/bank.com",
		Short:   "Remove a site from the password vault by specifying the entire site-path.",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.RemovePassword(path)
		},
	}
	removeFileCmd = &cobra.Command{
		Use:     "remove-file",
		Example: "passgo remove-file money/budget.csv",
		Aliases: []string{"rm-file", "removefile", "rmfile"},
		Short:   "Remove a file from the vault by specifying the entire file-path.",
		Args:    cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			edit.RemoveFile(path)
		},
	}
	insertFileCmd = &cobra.Command{
		Use:     "insert-file",
		Aliases: []string{"insertfile"},
		Example: "passgo insert-file money/budget.csv ~/Desktop/budget.csv",
		Short:   "Insert a file in to your vault",
		Args:    cobra.ExactArgs(2),
		Run: func(cmd *cobra.Command, args []string) {
			path := args[0]
			filename := args[1]
			insert.File(path, filename)
		},
	}
)

func init() {
	showCmd.PersistentFlags().BoolVarP(&copyPass, "copy", "c", false, "Copy your password to the clipboard")
	RootCmd.AddCommand(findCmd)
	RootCmd.AddCommand(generateCmd)
	RootCmd.AddCommand(initCmd)
	RootCmd.AddCommand(insertCmd)
	RootCmd.AddCommand(insertFileCmd)
	RootCmd.AddCommand(removeCmd)
	RootCmd.AddCommand(removeFileCmd)
	RootCmd.AddCommand(renameCmd)
	RootCmd.AddCommand(showCmd)
	RootCmd.AddCommand(versionCmd)
}

func main() {
	RootCmd.Execute()
}
<|endoftext|>


<commit_before>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * 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.
 *
 * pcstat.go - page cache stat
 *
 * uses the mincore(2) syscall to find out which pages (almost always 4k)
 * of a file are currently cached in memory
 *
 */

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"strings"
	"syscall"
	"unsafe"
)

// pcStat: page cache status
// Bytes: size of the file (from os.File.Stat())
// Pages: array of booleans: true if cached, false otherwise
type pcStat struct {
	Name     string  `json:"filename"` // file name as specified on command line
	Size     int64   `json:"size"`     // file size in bytes
	Pages    int     `json:"pages"`    // total memory pages
	Cached   int     `json:"cached"`   // number of pages that are cached
	Uncached int     `json:"uncached"` // number of pages that are not cached
	Percent  float64 `json:"percent"`  // percentage of pages cached
	PPStat   []bool  `json:"status"`   // per-page status, true if cached, false otherwise
}

type pcStatList []pcStat

var (
	terseFlag, nohdrFlag, jsonFlag, ppsFlag, bnameFlag bool
)

func init() {
	// TODO: error on useless/broken combinations
	flag.BoolVar(&terseFlag, "terse", false, "show terse output")
	flag.BoolVar(&nohdrFlag, "nohdr", false, "omit the header from terse & text output")
	flag.BoolVar(&jsonFlag, "json", false, "return data in JSON format")
	flag.BoolVar(&ppsFlag, "pps", false, "include the per-page status in JSON output")
	flag.BoolVar(&bnameFlag, "bname", false, "convert paths to basename to narrow the output")
}

func main() {
	flag.Parse()

	// all non-flag arguments are considered to be filenames
	// this works well with shell globbing
	// file order is preserved throughout this program
	stats := make(pcStatList, len(flag.Args()))

	for i, fname := range flag.Args() {
		stats[i] = getMincore(fname)
	}

	if jsonFlag {
		stats.formatJson()
	} else if terseFlag {
		stats.formatTerse()
	} else {
		stats.formatText()
	}
}

func (stats pcStatList) formatText() {
	// find the longest filename in the data for calculating whitespace padding
	maxName := 8
	for _, pcs := range stats {
		if len(pcs.Name) > maxName {
			maxName = len(pcs.Name)
		}
	}

	// create horizontal grid line
	pad := strings.Repeat("-", maxName+2)
	hr := fmt.Sprintf("|%s+----------------+------------+-----------+---------|", pad)

	fmt.Println(hr)

	// -nohdr may be chosen to save 2 lines of precious vertical space
	if !nohdrFlag {
		pad = strings.Repeat(" ", maxName-4)
		fmt.Printf("| Name%s | Size           | Pages      | Cached    | Percent |\n", pad)
		fmt.Println(hr)
	}

	for _, pcs := range stats {
		pad = strings.Repeat(" ", maxName-len(pcs.Name))

		// %07.3f was chosen to make it easy to scan the percentages vertically
		// I tried a few different formats only this one kept the decimals aligned
		fmt.Printf("| %s%s | %-15d| %-11d| %-10d| %07.3f |\n",
			pcs.Name, pad, pcs.Size, pcs.Pages, pcs.Cached, pcs.Percent)
	}

	fmt.Println(hr)
}

func (stats pcStatList) formatTerse() {
	if !nohdrFlag {
		fmt.Println("name,size,pages,cached,percent")
	}
	for _, pcs := range stats {
		fmt.Printf("%s,%d,%d,%d,%g\n",
			pcs.Name, pcs.Size, pcs.Pages, pcs.Cached, pcs.Percent)
	}
}

func (stats pcStatList) formatJson() {
	b, err := json.Marshal(stats)
	if err != nil {
		log.Fatalf("JSON formatting failed: %s\n", err)
	}
	os.Stdout.Write(b)
	fmt.Println("")
}

func getMincore(fname string) pcStat {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatalf("Could not open file '%s' for read: %s\n", fname, err)
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		log.Fatalf("Could not stat file %s: %s\n", fname, err)
	}
	if fi.Size() == 0 {
		log.Fatalf("%s appears to be 0 bytes in length\n", fname)
	}

	// []byte slice
	mmap, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()), syscall.PROT_NONE, syscall.MAP_SHARED)
	if err != nil {
		log.Fatalf("Could not mmap file '%s': %s\n", fname, err)
	}
	// TODO: check for MAP_FAILED which is ((void *) -1)
	// but maybe unnecessary since it looks like errno is always set when MAP_FAILED

	// one byte per page, only LSB is used, remainder is reserved and clear
	vecsz := (fi.Size() + int64(os.Getpagesize()) - 1) / int64(os.Getpagesize())
	vec := make([]byte, vecsz)

	// get all of the arguments to the mincore syscall converted to uintptr
	mmap_ptr := uintptr(unsafe.Pointer(&mmap[0]))
	size_ptr := uintptr(fi.Size())
	vec_ptr := uintptr(unsafe.Pointer(&vec[0]))

	// use Go's ASM to submit directly to the kernel, no C wrapper needed
	// mincore(2): int mincore(void *addr, size_t length, unsigned char *vec);
	// 0 on success, takes the pointer to the mmap, a size, which is the
	// size that came from f.Stat(), and the vector, which is a pointer
	// to the memory behind an []byte
	// this writes a snapshot of the data into vec which a list of 8-bit flags
	// with the LSB set if the page in that position is currently in VFS cache
	ret, _, err := syscall.RawSyscall(syscall.SYS_MINCORE, mmap_ptr, size_ptr, vec_ptr)
	if ret != 0 {
		log.Fatalf("syscall SYS_MINCORE failed: %s", err)
	}
	defer syscall.Munmap(mmap)

	pcs := pcStat{fname, fi.Size(), int(vecsz), 0, 0, 0.0, []bool{}}

	// only export the per-page cache mapping if it's explicitly enabled
	// an empty "status": [] field, but NBD.
	if ppsFlag {
		pcs.PPStat = make([]bool, vecsz)

		// there is no bitshift only bool
		for i, b := range vec {
			if b%2 == 1 {
				pcs.PPStat[i] = true
			} else {
				pcs.PPStat[i] = false
			}
		}

	}

	// convert long paths to their basename with the -bname flag
	// this overwrites the original filename in pcs but it doesn't matter since
	// it's not used to access the file again -- and should not be!
	if bnameFlag {
		pcs.Name = path.Base(fname)
	}

	for _, b := range vec {
		if b%2 == 1 {
			pcs.Cached++
		} else {
			pcs.Uncached++
		}
	}

	// convert to float for the occasional sparsely-cached file
	// see the README.md for how to produce one
	pcs.Percent = (float64(pcs.Cached) / float64(pcs.Pages)) * 100.00

	return pcs
}
<commit_msg>Add mtime to json & terse output.<commit_after>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * 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.
 *
 * pcstat.go - page cache stat
 *
 * uses the mincore(2) syscall to find out which pages (almost always 4k)
 * of a file are currently cached in memory
 *
 */

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

// pcStat: page cache status
// Bytes: size of the file (from os.File.Stat())
// Pages: array of booleans: true if cached, false otherwise
type pcStat struct {
	Name     string    `json:"filename"` // file name as specified on command line
	Size     int64     `json:"size"`     // file size in bytes
	Mtime    time.Time `json:"mtime"`    // last modification time of the file
	Pages    int       `json:"pages"`    // total memory pages
	Cached   int       `json:"cached"`   // number of pages that are cached
	Uncached int       `json:"uncached"` // number of pages that are not cached
	Percent  float64   `json:"percent"`  // percentage of pages cached
	PPStat   []bool    `json:"status"`   // per-page status, true if cached, false otherwise
}

type pcStatList []pcStat

var (
	terseFlag, nohdrFlag, jsonFlag, ppsFlag, bnameFlag bool
)

func init() {
	// TODO: error on useless/broken combinations
	flag.BoolVar(&terseFlag, "terse", false, "show terse output")
	flag.BoolVar(&nohdrFlag, "nohdr", false, "omit the header from terse & text output")
	flag.BoolVar(&jsonFlag, "json", false, "return data in JSON format")
	flag.BoolVar(&ppsFlag, "pps", false, "include the per-page status in JSON output")
	flag.BoolVar(&bnameFlag, "bname", false, "convert paths to basename to narrow the output")
}

func main() {
	flag.Parse()

	// all non-flag arguments are considered to be filenames
	// this works well with shell globbing
	// file order is preserved throughout this program
	stats := make(pcStatList, len(flag.Args()))

	for i, fname := range flag.Args() {
		stats[i] = getMincore(fname)
	}

	if jsonFlag {
		stats.formatJson()
	} else if terseFlag {
		stats.formatTerse()
	} else {
		stats.formatText()
	}
}

func (stats pcStatList) formatText() {
	// find the longest filename in the data for calculating whitespace padding
	maxName := 8
	for _, pcs := range stats {
		if len(pcs.Name) > maxName {
			maxName = len(pcs.Name)
		}
	}

	// create horizontal grid line
	pad := strings.Repeat("-", maxName+2)
	hr := fmt.Sprintf("|%s+----------------+------------+-----------+---------|", pad)

	fmt.Println(hr)

	// -nohdr may be chosen to save 2 lines of precious vertical space
	if !nohdrFlag {
		pad = strings.Repeat(" ", maxName-4)
		fmt.Printf("| Name%s | Size           | Pages      | Cached    | Percent |\n", pad)
		fmt.Println(hr)
	}

	for _, pcs := range stats {
		pad = strings.Repeat(" ", maxName-len(pcs.Name))

		// %07.3f was chosen to make it easy to scan the percentages vertically
		// I tried a few different formats only this one kept the decimals aligned
		fmt.Printf("| %s%s | %-15d| %-11d| %-10d| %07.3f |\n",
			pcs.Name, pad, pcs.Size, pcs.Pages, pcs.Cached, pcs.Percent)
	}

	fmt.Println(hr)
}

func (stats pcStatList) formatTerse() {
	if !nohdrFlag {
		fmt.Println("name,size,mtime,pages,cached,percent")
	}
	for _, pcs := range stats {
		mtime := pcs.Mtime.Unix()
		fmt.Printf("%s,%d,%d,%d,%d,%g\n",
			pcs.Name, pcs.Size, mtime, pcs.Pages, pcs.Cached, pcs.Percent)
	}
}

func (stats pcStatList) formatJson() {
	b, err := json.Marshal(stats)
	if err != nil {
		log.Fatalf("JSON formatting failed: %s\n", err)
	}
	os.Stdout.Write(b)
	fmt.Println("")
}

func getMincore(fname string) pcStat {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatalf("Could not open file '%s' for read: %s\n", fname, err)
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		log.Fatalf("Could not stat file %s: %s\n", fname, err)
	}
	if fi.Size() == 0 {
		log.Fatalf("%s appears to be 0 bytes in length\n", fname)
	}

	// []byte slice
	mmap, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()), syscall.PROT_NONE, syscall.MAP_SHARED)
	if err != nil {
		log.Fatalf("Could not mmap file '%s': %s\n", fname, err)
	}
	// TODO: check for MAP_FAILED which is ((void *) -1)
	// but maybe unnecessary since it looks like errno is always set when MAP_FAILED

	// one byte per page, only LSB is used, remainder is reserved and clear
	vecsz := (fi.Size() + int64(os.Getpagesize()) - 1) / int64(os.Getpagesize())
	vec := make([]byte, vecsz)

	// get all of the arguments to the mincore syscall converted to uintptr
	mmap_ptr := uintptr(unsafe.Pointer(&mmap[0]))
	size_ptr := uintptr(fi.Size())
	vec_ptr := uintptr(unsafe.Pointer(&vec[0]))

	// use Go's ASM to submit directly to the kernel, no C wrapper needed
	// mincore(2): int mincore(void *addr, size_t length, unsigned char *vec);
	// 0 on success, takes the pointer to the mmap, a size, which is the
	// size that came from f.Stat(), and the vector, which is a pointer
	// to the memory behind an []byte
	// this writes a snapshot of the data into vec which a list of 8-bit flags
	// with the LSB set if the page in that position is currently in VFS cache
	ret, _, err := syscall.RawSyscall(syscall.SYS_MINCORE, mmap_ptr, size_ptr, vec_ptr)
	if ret != 0 {
		log.Fatalf("syscall SYS_MINCORE failed: %s", err)
	}
	defer syscall.Munmap(mmap)

	pcs := pcStat{fname, fi.Size(), fi.ModTime(), int(vecsz), 0, 0, 0.0, []bool{}}

	// only export the per-page cache mapping if it's explicitly enabled
	// an empty "status": [] field, but NBD.
	if ppsFlag {
		pcs.PPStat = make([]bool, vecsz)

		// there is no bitshift only bool
		for i, b := range vec {
			if b%2 == 1 {
				pcs.PPStat[i] = true
			} else {
				pcs.PPStat[i] = false
			}
		}

	}

	// convert long paths to their basename with the -bname flag
	// this overwrites the original filename in pcs but it doesn't matter since
	// it's not used to access the file again -- and should not be!
	if bnameFlag {
		pcs.Name = path.Base(fname)
	}

	for _, b := range vec {
		if b%2 == 1 {
			pcs.Cached++
		} else {
			pcs.Uncached++
		}
	}

	// convert to float for the occasional sparsely-cached file
	// see the README.md for how to produce one
	pcs.Percent = (float64(pcs.Cached) / float64(pcs.Pages)) * 100.00

	return pcs
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

// The MIT License (MIT)
//
// Copyright (c) 2014 wandoulabs
// Copyright (c) 2014 siddontang
//
// 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.

// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"bufio"
	"io"
	"net"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/mysql"
)

type packetIO struct {
	rb *bufio.Reader
	wb *bufio.Writer

	sequence uint8
}

func newPacketIO(conn net.Conn) *packetIO {
	p := &packetIO{
		rb: bufio.NewReaderSize(conn, 8192),
		wb: bufio.NewWriterSize(conn, 8192),
	}

	return p
}

func (p *packetIO) readPacket() ([]byte, error) {
	header := []byte{0, 0, 0, 0}

	if _, err := io.ReadFull(p.rb, header); err != nil {
		return nil, errors.Trace(err)
	}

	length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16)
	if length < 1 {
		return nil, errors.Errorf("invalid payload length %d", length)
	}

	sequence := uint8(header[3])
	if sequence != p.sequence {
		return nil, errors.Errorf("invalid sequence %d != %d", sequence, p.sequence)
	}

	p.sequence++

	data := make([]byte, length)
	if _, err := io.ReadFull(p.rb, data); err != nil {
		return nil, errors.Trace(err)
	}
	if length < mysql.MaxPayloadLen {
		return data, nil
	}

	var buf []byte
	buf, err := p.readPacket()
	if err != nil {
		return nil, errors.Trace(err)
	}
	return append(data, buf...), nil
}

// writePacket writes data that already have header
func (p *packetIO) writePacket(data []byte) error {
	length := len(data) - 4

	for length >= mysql.MaxPayloadLen {
		data[0] = 0xff
		data[1] = 0xff
		data[2] = 0xff

		data[3] = p.sequence

		if n, err := p.wb.Write(data[:4+mysql.MaxPayloadLen]); err != nil {
			return mysql.ErrBadConn
		} else if n != (4 + mysql.MaxPayloadLen) {
			return mysql.ErrBadConn
		} else {
			p.sequence++
			length -= mysql.MaxPayloadLen
			data = data[mysql.MaxPayloadLen:]
		}
	}

	data[0] = byte(length)
	data[1] = byte(length >> 8)
	data[2] = byte(length >> 16)
	data[3] = p.sequence

	if n, err := p.wb.Write(data); err != nil {
		return errors.Trace(mysql.ErrBadConn)
	} else if n != len(data) {
		return errors.Trace(mysql.ErrBadConn)
	} else {
		p.sequence++
		return nil
	}
}

func (p *packetIO) flush() error {
	return p.wb.Flush()
}
<commit_msg>Address comments<commit_after>// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

// The MIT License (MIT)
//
// Copyright (c) 2014 wandoulabs
// Copyright (c) 2014 siddontang
//
// 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.

// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"bufio"
	"io"
	"net"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/mysql"
)

const (
	DefaultReaderSize = 16 * 1024
	DefaultWriterSize = 16 * 1024
)

type packetIO struct {
	rb *bufio.Reader
	wb *bufio.Writer

	sequence uint8
}

func newPacketIO(conn net.Conn) *packetIO {
	p := &packetIO{
		rb: bufio.NewReaderSize(conn, DefaultReaderSize),
		wb: bufio.NewWriterSize(conn, DefaultWriterSize),
	}

	return p
}

func (p *packetIO) readPacket() ([]byte, error) {
	var header [4]byte

	if _, err := io.ReadFull(p.rb, header[:]); err != nil {
		return nil, errors.Trace(err)
	}

	length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16)
	if length < 1 {
		return nil, errors.Errorf("invalid payload length %d", length)
	}

	sequence := uint8(header[3])
	if sequence != p.sequence {
		return nil, errors.Errorf("invalid sequence %d != %d", sequence, p.sequence)
	}

	p.sequence++

	data := make([]byte, length)
	if _, err := io.ReadFull(p.rb, data); err != nil {
		return nil, errors.Trace(err)
	}
	if length < mysql.MaxPayloadLen {
		return data, nil
	}

	var buf []byte
	buf, err := p.readPacket()
	if err != nil {
		return nil, errors.Trace(err)
	}
	return append(data, buf...), nil
}

// writePacket writes data that already have header
func (p *packetIO) writePacket(data []byte) error {
	length := len(data) - 4

	for length >= mysql.MaxPayloadLen {
		data[0] = 0xff
		data[1] = 0xff
		data[2] = 0xff

		data[3] = p.sequence

		if n, err := p.wb.Write(data[:4+mysql.MaxPayloadLen]); err != nil {
			return mysql.ErrBadConn
		} else if n != (4 + mysql.MaxPayloadLen) {
			return mysql.ErrBadConn
		} else {
			p.sequence++
			length -= mysql.MaxPayloadLen
			data = data[mysql.MaxPayloadLen:]
		}
	}

	data[0] = byte(length)
	data[1] = byte(length >> 8)
	data[2] = byte(length >> 16)
	data[3] = p.sequence

	if n, err := p.wb.Write(data); err != nil {
		return errors.Trace(mysql.ErrBadConn)
	} else if n != len(data) {
		return errors.Trace(mysql.ErrBadConn)
	} else {
		p.sequence++
		return nil
	}
}

func (p *packetIO) flush() error {
	return p.wb.Flush()
}
<|endoftext|>


<commit_before>package blog

import (
	"bitbucket.org/ikeikeikeike/antenna/models"
	"bitbucket.org/ikeikeikeike/antenna/models/score"
	"github.com/jmcvetta/randutil"
	"github.com/k0kubun/pp"
)

/*
	Return weighted items by blog's score.
*/
func WeightChoiceBlogs(in []*models.Blog, max int) []*models.Blog {
	var (
		choices []randutil.Choice
		blogs   []*models.Blog
	)

	for _, b := range in {
		s := score.RandomGetByBlog(b)
		pp.Println(s.Name)

		// If site had many blog, Remove code below.
		cnt := int(s.Count)
		if cnt < 1 {
			cnt = 1
		}

		// DMCA affect
		weight := cnt * b.VerifyScore()
		if b.IsPenalty {
			weight = 1
		}

		choices = append(choices, randutil.Choice{
			Weight: weight,
			Item:   b,
		})
	}

	limit := 0
	for len(blogs) < max && limit <= 1000000 {
		limit++

		wc, err := randutil.WeightedChoice(choices)
		if err == nil {
			blogs = appendIfMissing(blogs, wc.Item.(*models.Blog))
		}
	}

	return blogs
}

func appendIfMissing(blogs []*models.Blog, blog *models.Blog) []*models.Blog {
	for _, elm := range blogs {
		if elm == blog {
			return blogs
		}
	}
	return append(blogs, blog)
}
<commit_msg>fix previous commit<commit_after>package blog

import (
	"bitbucket.org/ikeikeikeike/antenna/models"
	"bitbucket.org/ikeikeikeike/antenna/models/score"
	"github.com/jmcvetta/randutil"
)

/*
	Return weighted items by blog's score.
*/
func WeightChoiceBlogs(in []*models.Blog, max int) []*models.Blog {
	var (
		choices []randutil.Choice
		blogs   []*models.Blog
	)

	for _, b := range in {
		s := score.RandomGetByBlog(b)

		// If site had many blog, Remove code below.
		cnt := int(s.Count)
		if cnt < 1 {
			cnt = 1
		}

		// DMCA affect
		weight := cnt * b.VerifyScore()
		if b.IsPenalty {
			weight = 1
		}

		choices = append(choices, randutil.Choice{
			Weight: weight,
			Item:   b,
		})
	}

	limit := 0
	for len(blogs) < max && limit <= 1000000 {
		limit++

		wc, err := randutil.WeightedChoice(choices)
		if err == nil {
			blogs = appendIfMissing(blogs, wc.Item.(*models.Blog))
		}
	}

	return blogs
}

func appendIfMissing(blogs []*models.Blog, blog *models.Blog) []*models.Blog {
	for _, elm := range blogs {
		if elm == blog {
			return blogs
		}
	}
	return append(blogs, blog)
}
<|endoftext|>


<commit_before>package dispatch

//go:generate stringer -type=ContentType -output=enums-gen.go

import (
	"io"

	"github.com/golang/protobuf/proto"
)

type ContentType int

const (
	Bytes ContentType = iota + 1
	Text
	ProtoBuf
)

type Sink struct {
	ContentType
	b []byte
}

func NewTextSink(v string) *Sink {
	return &Sink{
		ContentType: Text,
		b:           []byte(v),
	}
}

func NewBytesSink(b []byte) *Sink {
	return &Sink{
		ContentType: Bytes,
		b:           b,
	}
}

func NewProtoSink(m proto.Message) *Sink {
	if b, err := proto.Marshal(m); err == nil {
		return &Sink{
			ContentType: ProtoBuf,
			b:           b,
		}
	}
	return &Sink{}
}

func (s *Sink) Bytes() []byte {
	return s.b
}

func (s *Sink) String() string {
	return string(s.b)
}

func (s *Sink) UnmarshalProtoMessage(m proto.Message) error {
	return proto.Unmarshal(s.b, m)
}

func (s *Sink) Write(w io.Writer) {
	w.Write(s.b)
}

type Request interface {
	Protocol() string
	Dest() string
	Body() *Sink
}

type SimpleRequest struct {
	Proto, Dst string
	*Sink
}

func (s *SimpleRequest) Protocol() string {
	return s.Proto
}

func (s *SimpleRequest) Dest() string {
	return s.Dst
}

func (s *SimpleRequest) Body() *Sink {
	return s.Sink
}

type Response interface {
	Error() error
	Body() *Sink
}

type SimpleResponse struct {
	Err  error
	Body *Sink
}

type errResponse struct {
	e error
}

func ErrResponse(err error) Response {
	return errResponse{e: err}
}

func (e errResponse) Error() error {
	return e.e
}

func (e errResponse) Body() *Sink {
	return nil
}
<commit_msg>errors<commit_after>package dispatch

//go:generate stringer -type=ContentType -output=enums-gen.go

import (
	"io"

	"github.com/golang/protobuf/proto"
)

type ContentType int

const (
	Bytes ContentType = iota + 1
	Text
	ProtoBuf
)

type Sink struct {
	ContentType
	b []byte
}

func NewTextSink(v string) *Sink {
	return &Sink{
		ContentType: Text,
		b:           []byte(v),
	}
}

func NewBytesSink(b []byte) *Sink {
	return &Sink{
		ContentType: Bytes,
		b:           b,
	}
}

func NewProtoSink(m proto.Message) *Sink {
	if b, err := proto.Marshal(m); err == nil {
		return &Sink{
			ContentType: ProtoBuf,
			b:           b,
		}
	}
	return &Sink{}
}

func (s *Sink) Bytes() []byte {
	return s.b
}

func (s *Sink) String() string {
	return string(s.b)
}

func (s *Sink) UnmarshalProtoMessage(m proto.Message) error {
	return proto.Unmarshal(s.b, m)
}

func (s *Sink) Write(w io.Writer) {
	w.Write(s.b)
}

type Request interface {
	Protocol() string
	Dest() string
	Body() *Sink
}

type SimpleRequest struct {
	Proto, Dst string
	*Sink
}

func (s *SimpleRequest) Protocol() string {
	return s.Proto
}

func (s *SimpleRequest) Dest() string {
	return s.Dst
}

func (s *SimpleRequest) Body() *Sink {
	return s.Sink
}

type Response interface {
	Error() error
	Body() *Sink
}

type SimpleResponse struct {
	Err error
	*Sink
}

func (s *SimpleResponse) Error() error {
	return s.Err
}

func (s *SimpleResponse) Body() *Sink {
	return s.Sink
}

type errResponse struct {
	e error
}

func (e errResponse) Error() error {
	return e.e
}

func (e errResponse) Body() *Sink {
	return nil
}

func ErrResponse(err error) Response {
	return errResponse{e: err}
}
<|endoftext|>


<commit_before>// Package metrics provides minimalist instrumentation for your applications in
// the form of counters and gauges.
//
// Counters
//
// A counter is a monotonically-increasing, unsigned, 64-bit integer used to
// represent the number of times an event has occurred. By tracking the deltas
// between measurements of a counter over intervals of time, an aggregation
// layer can derive rates, acceleration, etc.
//
// Gauges
//
// A gauge returns instantaneous measurements of something using 64-bit floating
// point values.
//
// Histograms
//
// A histogram tracks the distribution of a stream of values (e.g. the number of
// milliseconds it takes to handle requests), adding gauges for the values at
// meaningful quantiles: 50th, 75th, 90th, 95th, 99th, 99.9th.
//
// Reporting
//
// Measurements from counters and gauges are available as expvars. Your service
// should return its expvars from an HTTP endpoint (i.e., /debug/vars) as a JSON
// object.
package metrics

import (
	"expvar"
	"sync"
	"time"

	"github.com/codahale/hdrhistogram/hdr"
)

// A Counter is a monotonically increasing unsigned integer.
//
// Use a counter to derive rates (e.g., record total number of requests, derive
// requests per second).
type Counter string

// Add increments the counter by one.
func (c Counter) Add() {
	c.AddN(1)
}

// AddN increments the counter by N.
func (c Counter) AddN(delta uint64) {
	cm.Lock()
	counters[string(c)] += delta
	cm.Unlock()
}

// SetFunc sets the counter's value to the lazily-called return value of the
// given function.
func (c Counter) SetFunc(f func() uint64) {
	cm.Lock()
	defer cm.Unlock()

	counterFuncs[string(c)] = f
}

// SetBatchFunc sets the counter's value to the lazily-called return value of
// the given function, with an additional initializer function for a related
// batch of counters, all of which are keyed by an arbitrary value.
func (c Counter) SetBatchFunc(key interface{}, init func(), f func() uint64) {
	cm.Lock()
	defer cm.Unlock()

	gm.Lock()
	defer gm.Unlock()

	counterFuncs[string(c)] = f
	if _, ok := inits[key]; !ok {
		inits[key] = init
	}
}

// A Gauge is an instantaneous measurement of a value.
//
// Use a gauge to track metrics which increase and decrease (e.g., amount of
// free memory).
type Gauge string

// Set the gauge's value to the given value.
func (g Gauge) Set(value float64) {
	gm.Lock()
	gauges[string(g)] = func() float64 {
		return value
	}
	gm.Unlock()
}

// SetFunc sets the gauge's value to the lazily-called return value of the given
// function.
func (g Gauge) SetFunc(f func() float64) {
	gm.Lock()
	gauges[string(g)] = f
	gm.Unlock()
}

// SetBatchFunc sets the gauge's value to the lazily-called return value of the
// given function, with an additional initializer function for a related batch
// of gauges, all of which are keyed by an arbitrary value.
func (g Gauge) SetBatchFunc(key interface{}, init func(), f func() float64) {
	gm.Lock()
	gauges[string(g)] = f
	if _, ok := inits[key]; !ok {
		inits[key] = init
	}
	gm.Unlock()
}

// Reset removes all existing counters and gauges.
func Reset() {
	cm.Lock()
	defer cm.Unlock()

	gm.Lock()
	defer gm.Unlock()

	hm.Lock()
	defer hm.Unlock()

	counters = make(map[string]uint64)
	counterFuncs = make(map[string]func() uint64)
	gauges = make(map[string]func() float64)
	histograms = make(map[string]*Histogram)
	inits = make(map[interface{}]func())
}

// Snapshot returns a copy of the values of all registered counters and gauges.
func Snapshot() (c map[string]uint64, g map[string]float64) {
	cm.Lock()
	defer cm.Unlock()

	gm.Lock()
	defer gm.Unlock()

	hm.Lock()
	defer hm.Unlock()

	for _, init := range inits {
		init()
	}

	c = make(map[string]uint64, len(counters)+len(counterFuncs))
	for n, v := range counters {
		c[n] = v
	}

	for n, f := range counterFuncs {
		c[n] = f()
	}

	g = make(map[string]float64, len(gauges))
	for n, f := range gauges {
		g[n] = f()
	}

	return
}

// NewHistogram returns a windowed HDR histogram which drops data older than
// five minutes. The returned histogram is safe to use from multiple goroutines.
//
// Use a histogram to track the distribution of a stream of values (e.g., the
// latency associated with HTTP requests).
func NewHistogram(name string, minValue, maxValue int64, sigfigs int) *Histogram {
	hm.Lock()
	defer hm.Unlock()

	if _, ok := histograms[name]; ok {
		panic(name + " already exists")
	}

	hist := &Histogram{
		hist: hdr.NewWindowedHistogram(5, minValue, maxValue, sigfigs),
	}
	histograms[name] = hist

	Gauge(name+".P50").SetBatchFunc(hname(name), hist.merge, hist.valueAt(50))
	Gauge(name+".P75").SetBatchFunc(hname(name), hist.merge, hist.valueAt(75))
	Gauge(name+".P90").SetBatchFunc(hname(name), hist.merge, hist.valueAt(90))
	Gauge(name+".P95").SetBatchFunc(hname(name), hist.merge, hist.valueAt(95))
	Gauge(name+".P99").SetBatchFunc(hname(name), hist.merge, hist.valueAt(99))
	Gauge(name+".P999").SetBatchFunc(hname(name), hist.merge, hist.valueAt(99.9))

	return hist
}

type hname string // unexported to prevent collisions

// A Histogram measures the distribution of a stream of values.
type Histogram struct {
	hist *hdr.WindowedHistogram
	m    *hdr.Histogram
	rw   sync.RWMutex
}

// RecordValue records the given value, or returns an error if the value is out
// of range.
func (h *Histogram) RecordValue(v int64) error {
	h.rw.Lock()
	defer h.rw.Unlock()

	return h.hist.Current.RecordValue(v)
}

func (h *Histogram) rotate() {
	h.rw.Lock()
	defer h.rw.Unlock()

	h.hist.Rotate()
}

func (h *Histogram) merge() {
	h.rw.Lock()
	defer h.rw.Unlock()

	h.m = h.hist.Merge()
}

func (h *Histogram) valueAt(q float64) func() float64 {
	return func() float64 {
		h.rw.RLock()
		defer h.rw.RUnlock()

		if h.m == nil {
			return 0
		}

		return float64(h.m.ValueAtQuantile(q))
	}
}

var (
	counters     = make(map[string]uint64)
	counterFuncs = make(map[string]func() uint64)
	gauges       = make(map[string]func() float64)
	inits        = make(map[interface{}]func())
	histograms   = make(map[string]*Histogram)

	cm, gm, hm sync.Mutex
)

func init() {
	expvar.Publish("metrics", expvar.Func(func() interface{} {
		counters, gauges := Snapshot()
		return map[string]interface{}{
			"Counters": counters,
			"Gauges":   gauges,
		}
	}))

	go func() {
		for _ = range time.NewTicker(1 * time.Minute).C {
			hm.Lock()
			for _, h := range histograms {
				h.rotate()
			}
			hm.Unlock()
		}
	}()
}
<commit_msg>Simplify locking for gauges.<commit_after>// Package metrics provides minimalist instrumentation for your applications in
// the form of counters and gauges.
//
// Counters
//
// A counter is a monotonically-increasing, unsigned, 64-bit integer used to
// represent the number of times an event has occurred. By tracking the deltas
// between measurements of a counter over intervals of time, an aggregation
// layer can derive rates, acceleration, etc.
//
// Gauges
//
// A gauge returns instantaneous measurements of something using 64-bit floating
// point values.
//
// Histograms
//
// A histogram tracks the distribution of a stream of values (e.g. the number of
// milliseconds it takes to handle requests), adding gauges for the values at
// meaningful quantiles: 50th, 75th, 90th, 95th, 99th, 99.9th.
//
// Reporting
//
// Measurements from counters and gauges are available as expvars. Your service
// should return its expvars from an HTTP endpoint (i.e., /debug/vars) as a JSON
// object.
package metrics

import (
	"expvar"
	"sync"
	"time"

	"github.com/codahale/hdrhistogram/hdr"
)

// A Counter is a monotonically increasing unsigned integer.
//
// Use a counter to derive rates (e.g., record total number of requests, derive
// requests per second).
type Counter string

// Add increments the counter by one.
func (c Counter) Add() {
	c.AddN(1)
}

// AddN increments the counter by N.
func (c Counter) AddN(delta uint64) {
	cm.Lock()
	counters[string(c)] += delta
	cm.Unlock()
}

// SetFunc sets the counter's value to the lazily-called return value of the
// given function.
func (c Counter) SetFunc(f func() uint64) {
	cm.Lock()
	defer cm.Unlock()

	counterFuncs[string(c)] = f
}

// SetBatchFunc sets the counter's value to the lazily-called return value of
// the given function, with an additional initializer function for a related
// batch of counters, all of which are keyed by an arbitrary value.
func (c Counter) SetBatchFunc(key interface{}, init func(), f func() uint64) {
	cm.Lock()
	defer cm.Unlock()

	gm.Lock()
	defer gm.Unlock()

	counterFuncs[string(c)] = f
	if _, ok := inits[key]; !ok {
		inits[key] = init
	}
}

// A Gauge is an instantaneous measurement of a value.
//
// Use a gauge to track metrics which increase and decrease (e.g., amount of
// free memory).
type Gauge string

// Set the gauge's value to the given value.
func (g Gauge) Set(value float64) {
	gm.Lock()
	defer gm.Unlock()

	gauges[string(g)] = func() float64 {
		return value
	}
}

// SetFunc sets the gauge's value to the lazily-called return value of the given
// function.
func (g Gauge) SetFunc(f func() float64) {
	gm.Lock()
	defer gm.Unlock()

	gauges[string(g)] = f
}

// SetBatchFunc sets the gauge's value to the lazily-called return value of the
// given function, with an additional initializer function for a related batch
// of gauges, all of which are keyed by an arbitrary value.
func (g Gauge) SetBatchFunc(key interface{}, init func(), f func() float64) {
	gm.Lock()
	defer gm.Unlock()

	gauges[string(g)] = f
	if _, ok := inits[key]; !ok {
		inits[key] = init
	}
}

// Reset removes all existing counters and gauges.
func Reset() {
	cm.Lock()
	defer cm.Unlock()

	gm.Lock()
	defer gm.Unlock()

	hm.Lock()
	defer hm.Unlock()

	counters = make(map[string]uint64)
	counterFuncs = make(map[string]func() uint64)
	gauges = make(map[string]func() float64)
	histograms = make(map[string]*Histogram)
	inits = make(map[interface{}]func())
}

// Snapshot returns a copy of the values of all registered counters and gauges.
func Snapshot() (c map[string]uint64, g map[string]float64) {
	cm.Lock()
	defer cm.Unlock()

	gm.Lock()
	defer gm.Unlock()

	hm.Lock()
	defer hm.Unlock()

	for _, init := range inits {
		init()
	}

	c = make(map[string]uint64, len(counters)+len(counterFuncs))
	for n, v := range counters {
		c[n] = v
	}

	for n, f := range counterFuncs {
		c[n] = f()
	}

	g = make(map[string]float64, len(gauges))
	for n, f := range gauges {
		g[n] = f()
	}

	return
}

// NewHistogram returns a windowed HDR histogram which drops data older than
// five minutes. The returned histogram is safe to use from multiple goroutines.
//
// Use a histogram to track the distribution of a stream of values (e.g., the
// latency associated with HTTP requests).
func NewHistogram(name string, minValue, maxValue int64, sigfigs int) *Histogram {
	hm.Lock()
	defer hm.Unlock()

	if _, ok := histograms[name]; ok {
		panic(name + " already exists")
	}

	hist := &Histogram{
		hist: hdr.NewWindowedHistogram(5, minValue, maxValue, sigfigs),
	}
	histograms[name] = hist

	Gauge(name+".P50").SetBatchFunc(hname(name), hist.merge, hist.valueAt(50))
	Gauge(name+".P75").SetBatchFunc(hname(name), hist.merge, hist.valueAt(75))
	Gauge(name+".P90").SetBatchFunc(hname(name), hist.merge, hist.valueAt(90))
	Gauge(name+".P95").SetBatchFunc(hname(name), hist.merge, hist.valueAt(95))
	Gauge(name+".P99").SetBatchFunc(hname(name), hist.merge, hist.valueAt(99))
	Gauge(name+".P999").SetBatchFunc(hname(name), hist.merge, hist.valueAt(99.9))

	return hist
}

type hname string // unexported to prevent collisions

// A Histogram measures the distribution of a stream of values.
type Histogram struct {
	hist *hdr.WindowedHistogram
	m    *hdr.Histogram
	rw   sync.RWMutex
}

// RecordValue records the given value, or returns an error if the value is out
// of range.
func (h *Histogram) RecordValue(v int64) error {
	h.rw.Lock()
	defer h.rw.Unlock()

	return h.hist.Current.RecordValue(v)
}

func (h *Histogram) rotate() {
	h.rw.Lock()
	defer h.rw.Unlock()

	h.hist.Rotate()
}

func (h *Histogram) merge() {
	h.rw.Lock()
	defer h.rw.Unlock()

	h.m = h.hist.Merge()
}

func (h *Histogram) valueAt(q float64) func() float64 {
	return func() float64 {
		h.rw.RLock()
		defer h.rw.RUnlock()

		if h.m == nil {
			return 0
		}

		return float64(h.m.ValueAtQuantile(q))
	}
}

var (
	counters     = make(map[string]uint64)
	counterFuncs = make(map[string]func() uint64)
	gauges       = make(map[string]func() float64)
	inits        = make(map[interface{}]func())
	histograms   = make(map[string]*Histogram)

	cm, gm, hm sync.Mutex
)

func init() {
	expvar.Publish("metrics", expvar.Func(func() interface{} {
		counters, gauges := Snapshot()
		return map[string]interface{}{
			"Counters": counters,
			"Gauges":   gauges,
		}
	}))

	go func() {
		for _ = range time.NewTicker(1 * time.Minute).C {
			hm.Lock()
			for _, h := range histograms {
				h.rotate()
			}
			hm.Unlock()
		}
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	tb := &ToolBox{}
	tb.init("/data")
	fmt.Println(help)
	in := bufio.NewReader(os.Stdin)
	for {
		prompt(tb)
		cmd, err := in.ReadString('\n')
		if err != nil {
			fmt.Println(err)
			os.Exit(-1)
		}
		tb.parse_exec(cmd)
	}
}

func prompt(tb *ToolBox) {
	var ps string
	if tb.fileid != -1 {
		ps += fmt.Sprintf("\033[0;31mfile(%v)\033[0m", tb.fileid)
	}
	if tb.userid != -1 {
		ps += fmt.Sprintf("\033[0;32muserid(%v)\033[0m", tb.userid)
	}
	if tb.duration_set {
		ps += fmt.Sprintf("\033[1m(%v -- %v)\033[0m", tb.duration_a, tb.duration_b)
	}
	ps += "> "
	fmt.Print(ps)
}
<commit_msg>prompt<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	tb := &ToolBox{}
	tb.init("/data")
	fmt.Println(help)
	in := bufio.NewReader(os.Stdin)
	for {
		prompt(tb)
		cmd, err := in.ReadString('\n')
		if err != nil {
			fmt.Println(err)
			os.Exit(-1)
		}
		tb.parse_exec(cmd)
	}
}

func prompt(tb *ToolBox) {
	var ps string
	if tb.fileid != -1 {
		ps += fmt.Sprintf("\033[0;31mfile(%v)\033[0m", tb.fileid)
	}
	if tb.userid != -1 {
		ps += fmt.Sprintf("\033[0;32mid(%v)\033[0m", tb.userid)
	}
	if tb.duration_set {
		ps += fmt.Sprintf("\033[1m(%v -- %v)\033[0m", tb.duration_a, tb.duration_b)
	}
	ps += "> "
	fmt.Print(ps)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/mattn/go-colorable"
	"github.com/mgutz/ansi"
)

var tagsFlag = flag.String("t", "", "Filter by tag. Tags list separated by ','")
var statusFlag = flag.String("s", "", "Filter by status. Status list separated by ','")
var recomputeIDFlag = flag.Bool("recomputeId", false, "Recompute id for all task. Warning! this will change all ids")
var jsonFlag = flag.Bool("json", false, "Print json db")

// Task represents what we have to do
type Task struct {
	ID      int      `json:"id"`      // Id of the task
	Created int64    `json:"created"` // timestamp when it has been created
	Text    string   `json:"text"`    // Text description of the Task
	Status  string   `json:"status"`  // Status of the task
	Tags    []string `json:"tags"`    // Tags of the task
}

// TaskByTime sort by timestamp
type TaskByTime []Task

func (t TaskByTime) Len() int           { return len(t) }
func (t TaskByTime) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t TaskByTime) Less(i, j int) bool { return t[i].Created < t[j].Created }

func (t Task) String() string {
	date := time.Unix(t.Created/1000, 0)
	var ansiStatus string
	if t.Status == "pending" || t.Status == "open" {
		ansiStatus = ansi.Color(t.Status, "94")
	} else if t.Status == "done" {
		ansiStatus = ansi.Color(t.Status, "90")
	}
	return fmt.Sprintf("%d %s %s\n  (%s) %s", t.ID, ansiStatus, ansi.Color(t.Text, "100"), ansi.Color(strings.Join(t.Tags, ", "), "80"), date.Format("2006-01-02"))
}

// JSONDb is a Task database in json
type JSONDb struct {
	Tags  []string // List of existing tags that can be used for a task
	Tasks []Task   // List of tasks
}

// FilterByTags return tasks list that have one the tags
func FilterByTags(tasks []Task, tags []string) []Task {
	var result []Task
	for _, task := range tasks {
		if tags[0] == "" || containsOne(tags, task.Tags) {
			result = append(result, task)
		}
	}
	return result
}

// FilterByStatus return tasks list that have one of the status
func FilterByStatus(tasks []Task, status []string) []Task {
	var result []Task
	for _, task := range tasks {
		if status[0] == "" || contains(status, task.Status) {
			result = append(result, task)
		}
	}
	return result
}

func containsOne(strs1 []string, strs2 []string) bool {
	for _, str1 := range strs1 {
		for _, str2 := range strs2 {
			if strings.ToLower(str1) == strings.ToLower(str2) {
				return true
			}
		}
	}
	return false
}

func contains(strs []string, s string) bool {
	for _, str := range strs {
		if strings.ToLower(str) == strings.ToLower(s) {
			return true
		}
	}
	return false
}

func main() {
	// Ensure that we have an ansi enabled terminal
	ansi.DisableColors(false)
	stdout := colorable.NewColorableStdout()

	flag.Parse()
	// Open file database
	var db JSONDb
	var decoder *json.Decoder
	if len(flag.Args()) == 0 {
		decoder = json.NewDecoder(os.Stdin)
	} else {
		f, err := os.Open(flag.Arg(0))
		if err != nil {
			// Stop if the file opening failed
			fmt.Print(err)
			return
		}
		defer f.Close()
		decoder = json.NewDecoder(f)
	}

	decoder.Decode(&db)

	tags := strings.Split(*tagsFlag, ",")
	status := strings.Split(*statusFlag, ",")

	// sort task
	sort.Sort(TaskByTime(db.Tasks))

	// be sure we have an id
	if *recomputeIDFlag {
		count := 1
		for i := range db.Tasks {
			db.Tasks[i].ID = count
			count++
		}
	}
	// Filter
	db.Tasks = FilterByTags(db.Tasks, tags)
	db.Tasks = FilterByStatus(db.Tasks, status)

	// Print result
	if *jsonFlag {
		result, err := json.MarshalIndent(db, "", " ")
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Fprintln(stdout, string(result))

	} else {
		for _, task := range db.Tasks {
			fmt.Fprintln(stdout, task)
		}
		fmt.Printf("%d tasks.\n.", len(db.Tasks))
	}

}
<commit_msg>Find task by text<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/mattn/go-colorable"
	"github.com/mgutz/ansi"
)

var tagsFlag = flag.String("t", "", "Filter by tag. Tags list separated by ','")
var statusFlag = flag.String("s", "", "Filter by status. Status list separated by ','")
var findTextFlag = flag.String("f", "", "Find text in task.")
var recomputeIDFlag = flag.Bool("recomputeId", false, "Recompute id for all task. Warning! this will change all ids")
var jsonFlag = flag.Bool("json", false, "Print json db")

// Task represents what we have to do
type Task struct {
	ID      int      `json:"id"`      // Id of the task
	Created int64    `json:"created"` // timestamp when it has been created
	Text    string   `json:"text"`    // Text description of the Task
	Status  string   `json:"status"`  // Status of the task
	Tags    []string `json:"tags"`    // Tags of the task
}

// TaskByTime sort by timestamp
type TaskByTime []Task

func (t TaskByTime) Len() int           { return len(t) }
func (t TaskByTime) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t TaskByTime) Less(i, j int) bool { return t[i].Created < t[j].Created }

// AnsiString provide string with ansi color escapes
func (t Task) AnsiString() string {
	date := time.Unix(t.Created/1000, 0)
	var ansiStatus string
	if t.Status == "pending" || t.Status == "open" {
		ansiStatus = ansi.Color(t.Status, "94")
	} else if t.Status == "done" {
		ansiStatus = ansi.Color(t.Status, "90")
	}
	return fmt.Sprintf("%d %s %s\n  (%s) %s", t.ID, ansiStatus, ansi.Color(t.Text, "80"), ansi.Color(strings.Join(t.Tags, ", "), "90"), date.Format("2006-01-02"))
}

// JSONDb is a Task database in json
type JSONDb struct {
	Tags  []string // List of existing tags that can be used for a task
	Tasks []Task   // List of tasks
}

// FilterByTags return tasks list that have one the tags
func FilterByTags(tasks []Task, tags []string) []Task {
	var result []Task
	for _, task := range tasks {
		if tags[0] == "" || containsOne(tags, task.Tags) {
			result = append(result, task)
		}
	}
	return result
}

// FilterByStatus return tasks list that have one of the status
func FilterByStatus(tasks []Task, status []string) []Task {
	var result []Task
	for _, task := range tasks {
		if status[0] == "" || contains(status, task.Status) {
			result = append(result, task)
		}
	}
	return result
}

// FilterByText return tasks list that have contains text
func FilterByText(tasks []Task, text string) []Task {
	var result []Task
	for _, task := range tasks {
		if strings.Index(strings.ToLower(task.Text), strings.ToLower(text)) != -1 {
			result = append(result, task)
		}
	}
	return result
}

func containsOne(strs1 []string, strs2 []string) bool {
	for _, str1 := range strs1 {
		for _, str2 := range strs2 {
			if strings.ToLower(str1) == strings.ToLower(str2) {
				return true
			}
		}
	}
	return false
}

func contains(strs []string, s string) bool {
	for _, str := range strs {
		if strings.ToLower(str) == strings.ToLower(s) {
			return true
		}
	}
	return false
}

func main() {
	// Ensure that we have an ansi enabled terminal
	ansi.DisableColors(false)
	stdout := colorable.NewColorableStdout()

	flag.Parse()
	// Open file database
	var db JSONDb
	var decoder *json.Decoder
	if len(flag.Args()) == 0 {
		decoder = json.NewDecoder(os.Stdin)
	} else {
		f, err := os.Open(flag.Arg(0))
		if err != nil {
			// Stop if the file opening failed
			fmt.Print(err)
			return
		}
		decoder = json.NewDecoder(f)
		defer f.Close()
	}

	err := decoder.Decode(&db)
	if err != nil {
		fmt.Println(err)
		return
	}

	tags := strings.Split(*tagsFlag, ",")
	status := strings.Split(*statusFlag, ",")

	// sort task
	sort.Sort(TaskByTime(db.Tasks))

	// be sure we have an id
	if *recomputeIDFlag {
		count := 1
		for i := range db.Tasks {
			db.Tasks[i].ID = count
			count++
		}
	}

	// Filter
	db.Tasks = FilterByTags(db.Tasks, tags)
	db.Tasks = FilterByStatus(db.Tasks, status)
	db.Tasks = FilterByText(db.Tasks, *findTextFlag)

	// Print result
	if *jsonFlag {
		result, err := json.MarshalIndent(db, "", " ")
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Fprintln(stdout, string(result))

	} else {
		for _, task := range db.Tasks {
			fmt.Fprintln(stdout, task.AnsiString())
		}
		fmt.Printf("%d tasks.\n.", len(db.Tasks))
	}

}
<|endoftext|>


<commit_before>package main

import (
  "io"
  "strings"
  "os"
  "log"
  "encoding/json"
  "net/http"
  "io/ioutil"
)

type Releases []Release

type Release struct {
  Url string
  Assets_url string
  Upload_url string
  Html_url string
  Id int
  Tag_name string
  Target_commitish string
  Name string
  Draft bool
  Authors []Author
  Prelease bool
  Created_at int64
  Published_at int64
  Assets []Asset
  Tarball_url string
  Zipball_url string
  Body string
}

type Author struct {
  Author_info []string
}

type Asset struct {
  Url string
  Id int
  Name string
  Label string
  Uploader []Upload
  Content_type string
  State string
  Size int
  Download_count int
  Created_at int64
  Updated_at int64
  Browser_download_url string
}

type Upload struct {
  Upload_info []string
}

func get_latest_release() {
  resp, err := http.Get("https://api.github.com/repos/groupon/Selenium-Grid-Extras/releases")
  if err != nil {
    log.Fatal(err.Error())
  }
  defer resp.Body.Close()

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatal(err.Error())
  }

  var releases Releases
  json.Unmarshal(body, &releases)

  // the first assets is the latest release
  for _, asset := range releases[0].Assets {

    // determine filename
    tokens := strings.Split(asset.Browser_download_url, "/")
    filename := tokens[len(tokens)-1]

    // SeleniumGridExtras-*-jar-with-dependencies.jar
    if asset.Content_type == "application/java-archive" {

      // prevent re-downloading file if already exists
      if _, err := os.Stat(filename); os.IsNotExist(err) {
        downloadFromUrl(asset.Browser_download_url, filename)

        // create symlink to latest release
        os.Symlink(filename, "SeleniumGridExtras-jar-with-dependencies.jar")
      }
      if err != nil {
        log.Fatal(err.Error())
      }
    }
  }
}

func main() {
  get_latest_release()
}

// https://github.com/thbar/golang-playground/blob/master/download-files.go
func downloadFromUrl(url string, fileName string) {
  log.Println("Downloading", url, "to", fileName)

  // TODO: check file existence first with io.IsExist
  output, err := os.Create(fileName)
  if err != nil {
    log.Fatal(err.Error())
  }
  defer output.Close()

  resp, err := http.Get(url)
  if err != nil {
    log.Fatal(err.Error())
  }
  defer resp.Body.Close()

  if resp.StatusCode != 200 {
    log.Fatal("Response.StatusCode: ", resp.StatusCode)
  }

  n, err := io.Copy(output, resp.Body)
  if err != nil {
    log.Fatal(err.Error())
  }
  log.Println(n, "bytes downloaded.")
}
<commit_msg>more error handling for status code to invalid url, etc if not 200<commit_after>package main

import (
  "io"
  "strings"
  "os"
  "log"
  "encoding/json"
  "net/http"
  "io/ioutil"
)

type Releases []Release

type Release struct {
  Url string
  Assets_url string
  Upload_url string
  Html_url string
  Id int
  Tag_name string
  Target_commitish string
  Name string
  Draft bool
  Authors []Author
  Prelease bool
  Created_at int64
  Published_at int64
  Assets []Asset
  Tarball_url string
  Zipball_url string
  Body string
}

type Author struct {
  Author_info []string
}

type Asset struct {
  Url string
  Id int
  Name string
  Label string
  Uploader []Upload
  Content_type string
  State string
  Size int
  Download_count int
  Created_at int64
  Updated_at int64
  Browser_download_url string
}

type Upload struct {
  Upload_info []string
}

func get_latest_release() {
  resp, err := http.Get("https://api.github.com/repos/groupon/Selenium-Grid-Extras/releases")
  if err != nil {
    log.Fatal(err)
  }
  defer resp.Body.Close()

  if resp.StatusCode != 200 {
    log.Fatal(resp.Request.URL, " => Response.StatusCode: ", resp.StatusCode)
  }

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatal(err)
  }

  var releases Releases
  json.Unmarshal(body, &releases)

  // the first assets is the latest release
  for _, asset := range releases[0].Assets {

    // determine filename
    tokens := strings.Split(asset.Browser_download_url, "/")
    filename := tokens[len(tokens)-1]

    // SeleniumGridExtras-*-jar-with-dependencies.jar
    if asset.Content_type == "application/java-archive" {

      // prevent re-downloading file if already exists
      if _, err := os.Stat(filename); os.IsNotExist(err) {
        downloadFromUrl(asset.Browser_download_url, filename)

        // create symlink to latest release
        os.Symlink(filename, "SeleniumGridExtras-jar-with-dependencies.jar")
      }
      if err != nil {
        log.Fatal(err)
      }
    }
  }
}

func main() {
  get_latest_release()
}

// https://github.com/thbar/golang-playground/blob/master/download-files.go
func downloadFromUrl(url string, fileName string) {
  log.Println("Downloading", url, "to", fileName)

  // TODO: check file existence first with io.IsExist
  output, err := os.Create(fileName)
  if err != nil {
    log.Fatal(err)
  }
  defer output.Close()

  resp, err := http.Get(url)
  if err != nil {
    log.Fatal(err)
  }
  defer resp.Body.Close()

  if resp.StatusCode != 200 {
    log.Fatal(resp.Request.URL, " => Response.StatusCode: ", resp.StatusCode)
  }

  n, err := io.Copy(output, resp.Body)
  if err != nil {
    log.Fatal(err)
  }
  log.Println(n, "bytes downloaded.")
}
<|endoftext|>


<commit_before>package lfchan

import (
	"runtime"
	"sync/atomic"
	"time"
	"unsafe"
)

type innerChan struct {
	q       []aValue
	sendIdx uint32
	recvIdx uint32
	slen    uint32
	rlen    uint32
	die     uint32
}

// Chan is a lock free channel that supports concurrent channel operations.
type Chan struct {
	*innerChan
}

// New returns a new channel with the buffer set to 1
func New() Chan {
	return NewSize(1)
}

// NewSize creates a buffered channel, with minimum length of 1
func NewSize(sz int) Chan {
	if sz < 1 {
		panic("sz < 1")
	}
	return Chan{&innerChan{
		q:       make([]aValue, sz),
		sendIdx: ^uint32(0),
		recvIdx: ^uint32(0),
	}}
}

// Send adds v to the buffer of the channel and returns true, if the channel is closed it returns false
func (ch Chan) Send(v interface{}, block bool) bool {
	if !block && ch.Len() == ch.Cap() {
		return false
	}
	ln, cnt := uint32(len(ch.q)), uint32(0)
	for !ch.Closed() {
		if ch.Len() == ch.Cap() {
			if !block {
				break
			}
			runtime.Gosched()
			continue
		}
		i := atomic.AddUint32(&ch.sendIdx, 1)
		if ch.q[i%ln].CompareAndSwapIfNil(v) {
			atomic.AddUint32(&ch.slen, 1)
			return true
		}
		if block {
			if i%250 == 0 {
				pause(1)
			}
		} else if cnt++; cnt == ln {
			break
		}
		runtime.Gosched()
	}
	return false
}

// Recv blocks until a value is available and returns v, true, or if the channel is closed and
// the buffer is empty, it will return nil, false
func (ch Chan) Recv(block bool) (interface{}, bool) {
	if !block && ch.Len() == 0 { // fast path
		return zeroValue, false
	}
	ln, cnt := uint32(len(ch.q)), uint32(0)
	for chln := ch.Len(); !ch.Closed() || chln > 0; chln = ch.Len() {
		if chln == 0 {
			if !block {
				break
			}
			runtime.Gosched()
			continue
		}
		i := atomic.AddUint32(&ch.recvIdx, 1)
		if v, ok := ch.q[i%ln].SwapWithNil(); ok {
			atomic.AddUint32(&ch.rlen, 1)
			return v, true
		}
		if block {
			if i%250 == 0 {
				pause(1)
			}
		} else if cnt++; cnt == ln {
			break
		}
		runtime.Gosched()
	}
	return zeroValue, false
}

// SendOnly returns a send-only channel.
func (ch Chan) SendOnly() SendOnly { return SendOnly{ch} }

// RecvOnly returns a receive-only channel.
func (ch Chan) RecvOnly() RecvOnly { return RecvOnly{ch} }

// Close marks the channel as closed
func (ch Chan) Close() { atomic.StoreUint32(&ch.die, 1) }

// Closed returns true if the channel have been closed
func (ch Chan) Closed() bool { return atomic.LoadUint32(&ch.die) == 1 }

// Cap returns the size of the internal queue
func (ch Chan) Cap() int { return len(ch.q) }

// Len returns the number of elements queued
func (ch Chan) Len() int { return int(atomic.LoadUint32(&ch.slen) - atomic.LoadUint32(&ch.rlen)) }

// SelectSend sends v to the first available channel, if block is true, it blocks until a channel a accepts the value.
// returns false if all channels were full and block is false.
func SelectSend(block bool, v interface{}, chans ...Sender) bool {
	for {
		for i := range chans {
			if ok := chans[i].Send(v, false); ok {
				return ok
			}
		}
		if !block {
			return false
		}
		pause(1)
	}
}

// SelectRecv returns the first available value from chans, if block is true, it blocks until a value is available.
// returns nil, false if all channels were empty and block is false.
func SelectRecv(block bool, chans ...Receiver) (interface{}, bool) {
	for {
		for i := range chans {
			if v, ok := chans[i].Recv(false); ok {
				return v, ok
			}
		}
		if !block {
			return zeroValue, false
		}
		pause(1)
	}
}

// SendOnly is a send-only channel.
type SendOnly struct{ c Chan }

// Send is an alias for Chan.Send.
func (so SendOnly) Send(v interface{}, block bool) bool { return so.c.Send(v, block) }

// Sender represents a Chan or SendOnly.
type Sender interface {
	Send(v interface{}, block bool) bool
}

// RecvOnly is a receive-only channel.
type RecvOnly struct{ c Chan }

// Recv is an alias for Chan.Recv.
func (ro RecvOnly) Recv(block bool) (interface{}, bool) { return ro.c.Recv(block) }

// Receiver represents a Chan or RecvOnly.
type Receiver interface {
	Recv(block bool) (interface{}, bool)
}

func pause(p time.Duration) { time.Sleep(time.Millisecond * p) }

var (
	_ Sender   = (*Chan)(nil)
	_ Sender   = (*SendOnly)(nil)
	_ Receiver = (*Chan)(nil)
	_ Receiver = (*RecvOnly)(nil)
)

var zeroValue interface{}

type aValue struct {
	v interface{}
}

func (a *aValue) CompareAndSwapIfNil(newVal interface{}) bool {
	x := unsafe.Pointer(&a.v)
	return atomic.CompareAndSwapPointer((*unsafe.Pointer)(atomic.LoadPointer(&x)), nil, unsafe.Pointer(&newVal))
}

func (a *aValue) SwapWithNil() (interface{}, bool) {
	x := unsafe.Pointer(&a.v)
	if v := atomic.SwapPointer((*unsafe.Pointer)(atomic.LoadPointer(&x)), nil); v != nil {
		return *(*interface{})(v), true
	}
	return zeroValue, false
}
<commit_msg>shard the queue<commit_after>package lfchan

import (
	"runtime"
	"sync/atomic"
	"time"
	"unsafe"
)

var ncpu = runtime.NumCPU()

type innerChan struct {
	q       [][]aValue
	sendIdx uint32
	recvIdx uint32
	slen    uint32
	rlen    uint32
	die     uint32
}

// Chan is a lock free channel that supports concurrent channel operations.
type Chan struct {
	*innerChan
}

// New returns a new channel with the buffer set to 1
func New() Chan {
	return NewSize(1)
}

// NewSize creates a buffered channel, with minimum length of 1
func NewSize(sz int) Chan {
	if sz < 1 {
		panic("sz < 1")
	}
	n := ncpu
	if sz < n {
		n = sz
	}
	ch := Chan{&innerChan{
		q:       make([][]aValue, n),
		sendIdx: ^uint32(0),
		recvIdx: ^uint32(0),
	}}
	for i := range ch.q {
		ch.q[i] = make([]aValue, sz/n)
	}
	return ch
}

// Send adds v to the buffer of the channel and returns true, if the channel is closed it returns false
func (ch Chan) Send(v interface{}, block bool) bool {
	if !block && ch.Len() == ch.Cap() {
		return false
	}
	qln, ln, cnt := uint32(len(ch.q)), uint32(len(ch.q[0])), uint32(0)
	for !ch.Closed() {
		if ch.Len() == ch.Cap() {
			if !block {
				break
			}
			runtime.Gosched()
			continue
		}
		i := atomic.AddUint32(&ch.sendIdx, 1)
		if ch.q[i%qln][i%ln].CompareAndSwapIfNil(v) {
			atomic.AddUint32(&ch.slen, 1)
			return true
		}
		if block {
			if i%250 == 0 {
				pause(1)
			}
		} else if cnt++; cnt == ln {
			break
		}
		runtime.Gosched()
	}
	return false
}

// Recv blocks until a value is available and returns v, true, or if the channel is closed and
// the buffer is empty, it will return nil, false
func (ch Chan) Recv(block bool) (interface{}, bool) {
	if !block && ch.Len() == 0 { // fast path
		return zeroValue, false
	}
	qln, ln, cnt := uint32(len(ch.q)), uint32(len(ch.q[0])), uint32(0)
	for chln := ch.Len(); !ch.Closed() || chln > 0; chln = ch.Len() {
		if chln == 0 {
			if !block {
				break
			}
			runtime.Gosched()
			continue
		}
		i := atomic.AddUint32(&ch.recvIdx, 1)
		if v, ok := ch.q[i%qln][i%ln].SwapWithNil(); ok {
			atomic.AddUint32(&ch.rlen, 1)
			return v, true
		}
		if block {
			if i%250 == 0 {
				pause(1)
			}
		} else if cnt++; cnt == ln {
			break
		}
		runtime.Gosched()
	}
	return zeroValue, false
}

// SendOnly returns a send-only channel.
func (ch Chan) SendOnly() SendOnly { return SendOnly{ch} }

// RecvOnly returns a receive-only channel.
func (ch Chan) RecvOnly() RecvOnly { return RecvOnly{ch} }

// Close marks the channel as closed
func (ch Chan) Close() { atomic.StoreUint32(&ch.die, 1) }

// Closed returns true if the channel have been closed
func (ch Chan) Closed() bool { return atomic.LoadUint32(&ch.die) == 1 }

// Cap returns the size of the internal queue
func (ch Chan) Cap() int { return len(ch.q) }

// Len returns the number of elements queued
func (ch Chan) Len() int { return int(atomic.LoadUint32(&ch.slen) - atomic.LoadUint32(&ch.rlen)) }

// SelectSend sends v to the first available channel, if block is true, it blocks until a channel a accepts the value.
// returns false if all channels were full and block is false.
func SelectSend(block bool, v interface{}, chans ...Sender) bool {
	for {
		for i := range chans {
			if ok := chans[i].Send(v, false); ok {
				return ok
			}
		}
		if !block {
			return false
		}
		pause(1)
	}
}

// SelectRecv returns the first available value from chans, if block is true, it blocks until a value is available.
// returns nil, false if all channels were empty and block is false.
func SelectRecv(block bool, chans ...Receiver) (interface{}, bool) {
	for {
		for i := range chans {
			if v, ok := chans[i].Recv(false); ok {
				return v, ok
			}
		}
		if !block {
			return zeroValue, false
		}
		pause(1)
	}
}

// SendOnly is a send-only channel.
type SendOnly struct{ c Chan }

// Send is an alias for Chan.Send.
func (so SendOnly) Send(v interface{}, block bool) bool { return so.c.Send(v, block) }

// Sender represents a Chan or SendOnly.
type Sender interface {
	Send(v interface{}, block bool) bool
}

// RecvOnly is a receive-only channel.
type RecvOnly struct{ c Chan }

// Recv is an alias for Chan.Recv.
func (ro RecvOnly) Recv(block bool) (interface{}, bool) { return ro.c.Recv(block) }

// Receiver represents a Chan or RecvOnly.
type Receiver interface {
	Recv(block bool) (interface{}, bool)
}

func pause(p time.Duration) { time.Sleep(time.Millisecond * p) }

var (
	_ Sender   = (*Chan)(nil)
	_ Sender   = (*SendOnly)(nil)
	_ Receiver = (*Chan)(nil)
	_ Receiver = (*RecvOnly)(nil)
)

var zeroValue interface{}

type aValue struct {
	v interface{}
}

func (a *aValue) CompareAndSwapIfNil(newVal interface{}) bool {
	x := unsafe.Pointer(&a.v)
	return atomic.CompareAndSwapPointer((*unsafe.Pointer)(atomic.LoadPointer(&x)), nil, unsafe.Pointer(&newVal))
}

func (a *aValue) SwapWithNil() (interface{}, bool) {
	x := unsafe.Pointer(&a.v)
	if v := atomic.SwapPointer((*unsafe.Pointer)(atomic.LoadPointer(&x)), nil); v != nil {
		return *(*interface{})(v), true
	}
	return zeroValue, false
}
<|endoftext|>


<commit_before>package types

import (
	"reflect"
	"testing"
)

func TestBaseInit(t *testing.T) {
	msg := `Method initialized must return "%v", got "%v".`

	e := false
	b := &base{}
	ok := b.initialized()
	if ok {
		t.Errorf(msg, e, ok)
	}

	e = false
	b.requireInit(e)
	ok = b.initialized()
	if !ok {
		t.Errorf(msg, !e, !ok)
	}

	e = true
	b.requireInit(e)
	ok = b.initialized()
	if ok {
		t.Errorf(msg, e, ok)
	}
}

func TestStr(t *testing.T) {
	for exp, inp := range map[string]*test{
		"[]":        &test{},
		"[a]":       &test{d: []string{"a"}},
		"[a; b; c]": &test{d: []string{"a", "b", "c"}},
	} {
		if res := str(inp); res != exp {
			t.Errorf(`"%v": Expected "%s", got "%s".`, inp, exp, res)
		}
	}
}

func TestSet(t *testing.T) {
	for _, v := range []struct {
		fn  func(*testing.T, *test)
		exp []string
	}{
		{
			func(t *testing.T, st *test) {
			},
			nil,
		},
		{
			func(t *testing.T, st *test) {
				set(st, "a")
			},
			[]string{"a"},
		},
		{
			func(t *testing.T, st *test) {
				set(st, "a")
				set(st, "b")
				set(st, "c")
			},
			[]string{"a", "b", "c"},
		},
		{
			func(t *testing.T, st *test) {
				set(st, "a")
				set(st, "b")
				set(st, "c")

				set(st, EOI)

				set(st, "x")
				set(st, "y")
				set(st, "z")
			},
			[]string{"x", "y", "z"},
		},
	} {
		st := &test{}
		v.fn(t, st)
		if !reflect.DeepEqual(st.d, v.exp) {
			t.Errorf("Incorrect slice values. Expected:\n`%#v`.\nGot:\n`%#v`.", v.exp, st.d)
		}
	}
}

//
// Test object that implements a slice interface is below.
//

type test struct {
	base
	d []string
}

func (t *test) length() int {
	return len(t.d)
}

func (t *test) get(i int) string {
	return t.d[i]
}

func (t *test) alloc() {
	t.d = []string{}
}

func (t *test) add(v string) error {
	t.d = append(t.d, v)
	return nil
}
<commit_msg>Run gofmt with -s flag on tests<commit_after>package types

import (
	"reflect"
	"testing"
)

func TestBaseInit(t *testing.T) {
	msg := `Method initialized must return "%v", got "%v".`

	e := false
	b := &base{}
	ok := b.initialized()
	if ok {
		t.Errorf(msg, e, ok)
	}

	e = false
	b.requireInit(e)
	ok = b.initialized()
	if !ok {
		t.Errorf(msg, !e, !ok)
	}

	e = true
	b.requireInit(e)
	ok = b.initialized()
	if ok {
		t.Errorf(msg, e, ok)
	}
}

func TestStr(t *testing.T) {
	for exp, inp := range map[string]*test{
		"[]":        {},
		"[a]":       {d: []string{"a"}},
		"[a; b; c]": {d: []string{"a", "b", "c"}},
	} {
		if res := str(inp); res != exp {
			t.Errorf(`"%v": Expected "%s", got "%s".`, inp, exp, res)
		}
	}
}

func TestSet(t *testing.T) {
	for _, v := range []struct {
		fn  func(*testing.T, *test)
		exp []string
	}{
		{
			func(t *testing.T, st *test) {
			},
			nil,
		},
		{
			func(t *testing.T, st *test) {
				set(st, "a")
			},
			[]string{"a"},
		},
		{
			func(t *testing.T, st *test) {
				set(st, "a")
				set(st, "b")
				set(st, "c")
			},
			[]string{"a", "b", "c"},
		},
		{
			func(t *testing.T, st *test) {
				set(st, "a")
				set(st, "b")
				set(st, "c")

				set(st, EOI)

				set(st, "x")
				set(st, "y")
				set(st, "z")
			},
			[]string{"x", "y", "z"},
		},
	} {
		st := &test{}
		v.fn(t, st)
		if !reflect.DeepEqual(st.d, v.exp) {
			t.Errorf("Incorrect slice values. Expected:\n`%#v`.\nGot:\n`%#v`.", v.exp, st.d)
		}
	}
}

//
// Test object that implements a slice interface is below.
//

type test struct {
	base
	d []string
}

func (t *test) length() int {
	return len(t.d)
}

func (t *test) get(i int) string {
	return t.d[i]
}

func (t *test) alloc() {
	t.d = []string{}
}

func (t *test) add(v string) error {
	t.d = append(t.d, v)
	return nil
}
<|endoftext|>