<commit_before>//      __      ___        _______ _____  ______ ______
//     /\ \    / / |      |__   __|  __ \|  ____|  ____|
//    /  \ \  / /| |         | |  | |__) | |__  | |__
//   / /\ \ \/ / | |         | |  |  _  /|  __| |  __|
//  / ____ \  /  | |____     | |  | | \ \| |____| |____
// /_/    \_\/   |______|    |_|  |_|  \_\______|______|
//

package AvlTree

import (
	"bytes"

	"github.com/tendermint/go-db"
)

type AVLNode struct {
	Key       []byte   //node key
	Value     []byte   //node value
	Height    int      //
	ParNode   *AVLNode //Parent AVL node
	LeftNode  *AVLNode //Left node with key less than current node
	RightNode *AVLNode //Right node with key greater than current node
}

func NewAVLTrunk(
	key,
	value []byte) *AVLNode {

	return NewAVLLeaf(nil, key, value)
}

func NewAVLLeaf(
	parNode *AVLNode,
	key,
	value []byte) *AVLNode {

	return AVLNode{
		Key:       key,
		Value:     value,
		Height:    0,
		ParNode:   parNode,
		LeftNode:  nil,
		RightNode: nil,
	}
}

//return the node position of either the matching node or the locatation to place a node
func (n *AVLNode) findPosition(searchKey []byte) (match bool, position, parent *AVLNode) {

	if n == nil {
		return false, n, n.ParNode //parent is set to nil if the trunk node
	}

	//The result will be 0 if a==b, -1 if a < b, and +1 if a > b
	switch bytes.Compare(searchKey, *n.key) {
	case 0:
		return true, n, n.ParNode
	case -1:
		return n.LeftNode.findPosition(searchKey)
	case 1:
		return n.RightNode.findPosition(searchKey)
	}
}

//find either the minimum or maximum sub node key value
func (n *AVLNode) findExtremum(min bool) *AVLNode {
	if min {
		//calling recursively within these function variables
		// should be slighly more efficient then calling the
		// whole function because it avoids checking min
		iterateLeft := func(n2 *AVLNode) *AVLNode {
			if n2.LeftNode == nil {
				return n2
			}
			return iterateLeft(n2.LeftNode)
		}

		return iterateLeft(n)

	} else {
		iterateRight := func(n2 *AVLNode) *AVLNode {
			if n2.RightNode == nil {
				return n2
			}
			return iterateRight(n2.RightNode)
		}

		return iterateRight(n)
	}
}

//updates the height of the current node
func (n *AVLNode) updateHeight() {

	maxHeight := -1

	if n.LeftNode != nil {
		maxHeight = *n.LeftNode.Height
	}

	if n.RightNode != nil && *n.RightNode.Height > maxHeight {
		maxHeight = *n.RightNode.Height
	}

	*n.Height = maxHeight + 1
}

func (n *AVLNode) balance() int {

	RightHeight := 0
	LeftHeight := 0

	if n.RightNode != nil {
		RightHeight = *n.RightNode.Height
	}

	if n.LeftNode != nil {
		LeftHeight = *n.LeftNode.Height
	}

	return RightHeight - LeftHeight
}

func (n *AVLNode) updateBalance() {
	bal = n.balance()

	switch {
	case bal > 1:
		if *n.RightNode.balance() > 0 { //Left Left Rotation
			n.rotateLeft()
		} else { //Right Left Rotation
			n.RightNode.rotateRight()
			n.rotateLeft()
		}
	case bal < -1:
		if *n.LeftNode.balance() < 0 { //Right Right Rotation
			n.rotateRight()
		} else { //Left Right Rotation
			n.LeftNode.rotateLeft()
			n.rotateRight()
		}

	}
}

//update the height and  balances from the area of action upwards
// this will allow the tree to be balanced in the most
// compact way
func (n *AVLNode) updateBalanceRecursive() {
	if n != nil {
		return
	}
	n.updateHeight()
	n.updateBalance()
	n.ParNode.updateBalanceRecursive()
}

func (n *AVLNode) rotateLeft() {

	//new parent takes on old parent's parent
	n.RightNode.ParNode = n.ParNode

	//old parent takes owernership of right nodes left child as its right child
	n.RightNode = n.RightNode.LeftNode

	//old parent node becomes lower left child of old right node
	n.RightNode.LeftNode = n
	n.ParNode = n.RightNode
}

func (n *AVLNode) rotateRight() {
	n.LeftNode.ParNode = n.ParNode
	n.ParNode = n.LeftNode
	n.LeftNode = nil
}
<commit_msg>preliminary - figuring out rotations<commit_after>//      __      ___        _______ _____  ______ ______
//     /\ \    / / |      |__   __|  __ \|  ____|  ____|
//    /  \ \  / /| |         | |  | |__) | |__  | |__
//   / /\ \ \/ / | |         | |  |  _  /|  __| |  __|
//  / ____ \  /  | |____     | |  | | \ \| |____| |____
// /_/    \_\/   |______|    |_|  |_|  \_\______|______|
//

package AvlTree

import (
	"bytes"

	"github.com/tendermint/go-db"
)

type AVLNode struct {
	Key       []byte   //node key
	Value     []byte   //node value
	Height    int      //
	ParNode   *AVLNode //Parent AVL node
	LeftNode  *AVLNode //Left node with key less than current node
	RightNode *AVLNode //Right node with key greater than current node
}

func NewAVLTrunk(
	key,
	value []byte) *AVLNode {

	return NewAVLLeaf(nil, key, value)
}

func NewAVLLeaf(
	parNode *AVLNode,
	key,
	value []byte) *AVLNode {

	return AVLNode{
		Key:       key,
		Value:     value,
		Height:    0,
		ParNode:   parNode,
		LeftNode:  nil,
		RightNode: nil,
	}
}

//return the node position of either the matching node or the locatation to place a node
func (n *AVLNode) findPosition(searchKey []byte) (match bool, position, parent *AVLNode) {

	if n == nil {
		return false, n, n.ParNode //parent is set to nil if the trunk node
	}

	//The result will be 0 if a==b, -1 if a < b, and +1 if a > b
	switch bytes.Compare(searchKey, *n.key) {
	case 0:
		return true, n, n.ParNode
	case -1:
		return n.LeftNode.findPosition(searchKey)
	case 1:
		return n.RightNode.findPosition(searchKey)
	}
}

//find either the minimum or maximum sub node key value
func (n *AVLNode) findExtremum(min bool) *AVLNode {
	if min {
		//calling recursively within these function variables
		// should be slighly more efficient then calling the
		// whole function because it avoids checking min
		iterateLeft := func(n2 *AVLNode) *AVLNode {
			if n2.LeftNode == nil {
				return n2
			}
			return iterateLeft(n2.LeftNode)
		}

		return iterateLeft(n)

	} else {
		iterateRight := func(n2 *AVLNode) *AVLNode {
			if n2.RightNode == nil {
				return n2
			}
			return iterateRight(n2.RightNode)
		}

		return iterateRight(n)
	}
}

//updates the height of the current node
func (n *AVLNode) updateHeight() {

	maxHeight := -1

	if n.LeftNode != nil {
		maxHeight = *n.LeftNode.Height
	}

	if n.RightNode != nil && *n.RightNode.Height > maxHeight {
		maxHeight = *n.RightNode.Height
	}

	*n.Height = maxHeight + 1
}

func (n *AVLNode) balance() int {

	RightHeight := 0
	LeftHeight := 0

	if n.RightNode != nil {
		RightHeight = *n.RightNode.Height
	}

	if n.LeftNode != nil {
		LeftHeight = *n.LeftNode.Height
	}

	return RightHeight - LeftHeight
}

func (n *AVLNode) updateBalance() {
	bal = n.balance()

	switch {
	case bal > 1:
		if *n.RightNode.balance() > 0 { //Left Left Rotation
			n.rotateLeft()
		} else { //Right Left Rotation
			n.RightNode.rotateRight()
			n.rotateLeft()
		}
	case bal < -1:
		if *n.LeftNode.balance() < 0 { //Right Right Rotation
			n.rotateRight()
		} else { //Left Right Rotation
			n.LeftNode.rotateLeft()
			n.rotateRight()
		}

	}
}

//update the height and  balances from the area of action upwards
// this will allow the tree to be balanced in the most
// compact way
func (n *AVLNode) updateBalanceRecursive() {
	if n != nil {
		return
	}
	n.updateHeight()
	n.updateBalance()
	n.ParNode.updateBalanceRecursive()
}

func (n *AVLNode) rotateLeft() {

	//Original right node moving up during rotation
	nodeUp := n.RightNode

	//new parent takes on old parent's parent
	nodeUp.ParNode = n.ParNode

	//old parent takes owernership of right nodes left child as its right child
	n.RightNode = nodeUp.LeftNode

	//old parent node becomes lower left child of old right node
	nodeUp.LeftNode = n
	n.ParNode = nodeUp
}

func (n *AVLNode) rotateRight() {

	//Original left node moving up during rotation
	nodeUp := n.LeftNode

	//new parent takes on old parent's parent
	nodeUp.ParNode = n.ParNode

	//old parent takes owernership of left nodes right child as its left child
	n.LeftNode = nodeUp.RightNode

	//old parent node becomes lower right child of old left node
	nodeUp.RightNode = n
	n.ParNode = nodeUp
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package safemux_test

import (
	"github.com/google/go-cmp/cmp"
	"github.com/google/go-safeweb/safehttp"
	"github.com/google/go-safeweb/safehttp/safehttptest"
	"github.com/google/safehtml"
	safetemplate "github.com/google/safehtml/template"
	"html/template"
	"math"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestMuxDefaultDispatcher(t *testing.T) {
	tests := []struct {
		name        string
		mux         *safehttp.ServeMux
		wantHeaders map[string][]string
		wantBody    string
	}{
		{
			name: "Safe HTML Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.Write(safehtml.HTMLEscaped("
Hello World!
"))
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
			wantHeaders: map[string][]string{
				"Content-Type": {"text/html; charset=utf-8"},
			},
			wantBody: "<h1>Hello World!</h1>",
		},
		{
			name: "Safe HTML Template Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.WriteTemplate(safetemplate.Must(safetemplate.New("name").Parse("
{{ . }}
")), "This is an actual heading, though.")
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
			wantHeaders: map[string][]string{
				"Content-Type": {"text/html; charset=utf-8"},
			},
			wantBody: "
This is an actual heading, though.
",
		},
		{
			name: "Valid JSON Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					data := struct {
						Field string `json:"field"`
					}{Field: "myField"}
					return w.WriteJSON(data)
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
			wantHeaders: map[string][]string{
				"Content-Type": {"application/json; charset=utf-8"},
			},
			wantBody: ")]}',\n{\"field\":\"myField\"}\n",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req := httptest.NewRequest(safehttp.MethodGet, "http://foo.com/pizza", nil)
			b := &strings.Builder{}
			rw := safehttptest.NewTestResponseWriter(b)

			tt.mux.ServeHTTP(rw, req)

			if wantStatus := safehttp.StatusOK; rw.Status() != wantStatus {
				t.Errorf("rw.Status(): got %v want %v", rw.Status(), wantStatus)
			}

			if diff := cmp.Diff(tt.wantHeaders, map[string][]string(rw.Header())); diff != "" {
				t.Errorf("rw.header mismatch (-want +got):\n%s", diff)
			}

			if gotBody := b.String(); tt.wantBody != gotBody {
				t.Errorf("response body: got %v, want %v", gotBody, tt.wantBody)
			}
		})
	}
}

func TestMuxDefaultDispatcherUnsafeResponses(t *testing.T) {
	tests := []struct {
		name string
		mux  *safehttp.ServeMux
	}{
		{
			name: "Unsafe HTML Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.Write("
Hello World!
")
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
		},
		{
			name: "Unsafe Template Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.WriteTemplate(template.Must(template.New("name").Parse("
{{ . }}
")), "This is an actual heading, though.")
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
		},
		{
			name: "Invalid JSON Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.WriteJSON(math.Inf(1))
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// TODO: Unskip these test cases and combine them with the test
			// cases from the previous test into a single table test after
			// error-handling in the ResponseWriter has been fixed.
			t.Skip()
			req := httptest.NewRequest(safehttp.MethodGet, "http://foo.com/pizza", nil)
			b := &strings.Builder{}
			rw := safehttptest.NewTestResponseWriter(b)

			tt.mux.ServeHTTP(rw, req)

			if wantStatus := safehttp.StatusInternalServerError; rw.Status() != wantStatus {
				t.Errorf("rw.Status(): got %v want %v", rw.Status(), wantStatus)
			}

			wantHeaders := map[string][]string{
				"Content-Type":           {"text/plain; charset=utf-8"},
				"X-Content-Type-Options": {"nosniff"},
			}
			if diff := cmp.Diff(wantHeaders, map[string][]string(rw.Header())); diff != "" {
				t.Errorf("rw.Header(): mismatch (-want +got):\n%s", diff)
			}

			if wantBody, gotBody := "Internal Server Error\n", b.String(); wantBody != gotBody {
				t.Errorf("response body: got %v, want %v", gotBody, wantBody)
			}
		})
	}
}
<commit_msg>Rename the package for mux integration tests mux_test<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mux_test

import (
	"github.com/google/go-cmp/cmp"
	"github.com/google/go-safeweb/safehttp"
	"github.com/google/go-safeweb/safehttp/safehttptest"
	"github.com/google/safehtml"
	safetemplate "github.com/google/safehtml/template"
	"html/template"
	"math"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestMuxDefaultDispatcher(t *testing.T) {
	tests := []struct {
		name        string
		mux         *safehttp.ServeMux
		wantHeaders map[string][]string
		wantBody    string
	}{
		{
			name: "Safe HTML Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.Write(safehtml.HTMLEscaped("
Hello World!
"))
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
			wantHeaders: map[string][]string{
				"Content-Type": {"text/html; charset=utf-8"},
			},
			wantBody: "<h1>Hello World!</h1>",
		},
		{
			name: "Safe HTML Template Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.WriteTemplate(safetemplate.Must(safetemplate.New("name").Parse("
{{ . }}
")), "This is an actual heading, though.")
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
			wantHeaders: map[string][]string{
				"Content-Type": {"text/html; charset=utf-8"},
			},
			wantBody: "
This is an actual heading, though.
",
		},
		{
			name: "Valid JSON Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					data := struct {
						Field string `json:"field"`
					}{Field: "myField"}
					return w.WriteJSON(data)
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
			wantHeaders: map[string][]string{
				"Content-Type": {"application/json; charset=utf-8"},
			},
			wantBody: ")]}',\n{\"field\":\"myField\"}\n",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req := httptest.NewRequest(safehttp.MethodGet, "http://foo.com/pizza", nil)
			b := &strings.Builder{}
			rw := safehttptest.NewTestResponseWriter(b)

			tt.mux.ServeHTTP(rw, req)

			if wantStatus := safehttp.StatusOK; rw.Status() != wantStatus {
				t.Errorf("rw.Status(): got %v want %v", rw.Status(), wantStatus)
			}

			if diff := cmp.Diff(tt.wantHeaders, map[string][]string(rw.Header())); diff != "" {
				t.Errorf("rw.header mismatch (-want +got):\n%s", diff)
			}

			if gotBody := b.String(); tt.wantBody != gotBody {
				t.Errorf("response body: got %v, want %v", gotBody, tt.wantBody)
			}
		})
	}
}

func TestMuxDefaultDispatcherUnsafeResponses(t *testing.T) {
	tests := []struct {
		name string
		mux  *safehttp.ServeMux
	}{
		{
			name: "Unsafe HTML Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.Write("
Hello World!
")
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
		},
		{
			name: "Unsafe Template Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.WriteTemplate(template.Must(template.New("name").Parse("
{{ . }}
")), "This is an actual heading, though.")
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
		},
		{
			name: "Invalid JSON Response",
			mux: func() *safehttp.ServeMux {
				mux := safehttp.NewServeMux(safehttp.DefaultDispatcher{}, "foo.com")

				h := safehttp.HandlerFunc(func(w *safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
					return w.WriteJSON(math.Inf(1))
				})
				mux.Handle("/pizza", safehttp.MethodGet, h)
				return mux
			}(),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// TODO: Unskip these test cases and combine them with the test
			// cases from the previous test into a single table test after
			// error-handling in the ResponseWriter has been fixed.
			t.Skip()
			req := httptest.NewRequest(safehttp.MethodGet, "http://foo.com/pizza", nil)
			b := &strings.Builder{}
			rw := safehttptest.NewTestResponseWriter(b)

			tt.mux.ServeHTTP(rw, req)

			if wantStatus := safehttp.StatusInternalServerError; rw.Status() != wantStatus {
				t.Errorf("rw.Status(): got %v want %v", rw.Status(), wantStatus)
			}

			wantHeaders := map[string][]string{
				"Content-Type":           {"text/plain; charset=utf-8"},
				"X-Content-Type-Options": {"nosniff"},
			}
			if diff := cmp.Diff(wantHeaders, map[string][]string(rw.Header())); diff != "" {
				t.Errorf("rw.Header(): mismatch (-want +got):\n%s", diff)
			}

			if wantBody, gotBody := "Internal Server Error\n", b.String(); wantBody != gotBody {
				t.Errorf("response body: got %v, want %v", gotBody, wantBody)
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

import "time"

type sortMethod byte

const (
	naturalSort sortMethod = iota
	nameSort
	sizeSort
	timeSort
)

type sortOption byte

const (
	dirfirstSort sortOption = 1 << iota
	hiddenSort
	reverseSort
)

type sortType struct {
	method sortMethod
	option sortOption
}

var gOpts struct {
	anchorfind     bool
	color256       bool
	dircounts      bool
	drawbox        bool
	globsearch     bool
	ignorecase     bool
	incsearch      bool
	preview        bool
	smartcase      bool
	ignoredia      bool
	smartdia       bool
	wrapscan       bool
	number         bool
	relativenumber bool
	findlen        int
	period         int
	scrolloff      int
	tabstop        int
	errorfmt       string
	filesep        string
	ifs            string
	previewer      string
	promptfmt      string
	shell          string
	timefmt        string
	ratios         []int
	info           []string
	shellopts      []string
	keys           map[string]expr
	cmdkeys        map[string]expr
	cmds           map[string]expr
	sortType       sortType
}

func init() {
	gOpts.anchorfind = true
	gOpts.color256 = false
	gOpts.dircounts = false
	gOpts.drawbox = false
	gOpts.globsearch = false
	gOpts.ignorecase = true
	gOpts.incsearch = false
	gOpts.preview = true
	gOpts.smartcase = true
	gOpts.ignoredia = false
	gOpts.smartdia = false
	gOpts.wrapscan = true
	gOpts.number = false
	gOpts.relativenumber = false
	gOpts.findlen = 1
	gOpts.period = 0
	gOpts.scrolloff = 0
	gOpts.tabstop = 8
	gOpts.errorfmt = "\033[7;31;47m%s\033[0m"
	gOpts.filesep = "\n"
	gOpts.ifs = nil
	gOpts.previewer = nil
	gOpts.promptfmt = "\033[32;1m%u@%h\033[0m:\033[34;1m%w/\033[0m\033[1m%f\033[0m"
	gOpts.shell = gDefaultShell
	gOpts.timefmt = time.ANSIC
	gOpts.ratios = []int{1, 2, 3}
	gOpts.info = nil
	gOpts.shellopts = nil
	gOpts.sortType = sortType{naturalSort, dirfirstSort}

	gOpts.keys = make(map[string]expr)

	gOpts.keys["k"] = &callExpr{"up", nil, 1}
	gOpts.keys["<up>"] = &callExpr{"up", nil, 1}
	gOpts.keys["<c-u>"] = &callExpr{"half-up", nil, 1}
	gOpts.keys["<c-b>"] = &callExpr{"page-up", nil, 1}
	gOpts.keys["<pgup>"] = &callExpr{"page-up", nil, 1}
	gOpts.keys["j"] = &callExpr{"down", nil, 1}
	gOpts.keys["<down>"] = &callExpr{"down", nil, 1}
	gOpts.keys["<c-d>"] = &callExpr{"half-down", nil, 1}
	gOpts.keys["<c-f>"] = &callExpr{"page-down", nil, 1}
	gOpts.keys["<pgdn>"] = &callExpr{"page-down", nil, 1}
	gOpts.keys["h"] = &callExpr{"updir", nil, 1}
	gOpts.keys["<left>"] = &callExpr{"updir", nil, 1}
	gOpts.keys["l"] = &callExpr{"open", nil, 1}
	gOpts.keys["<right>"] = &callExpr{"open", nil, 1}
	gOpts.keys["q"] = &callExpr{"quit", nil, 1}
	gOpts.keys["gg"] = &callExpr{"top", nil, 1}
	gOpts.keys["<home>"] = &callExpr{"top", nil, 1}
	gOpts.keys["G"] = &callExpr{"bottom", nil, 1}
	gOpts.keys["<end>"] = &callExpr{"bottom", nil, 1}
	gOpts.keys["<space>"] = &callExpr{"toggle", nil, 1}
	gOpts.keys["v"] = &callExpr{"invert", nil, 1}
	gOpts.keys["u"] = &callExpr{"unselect", nil, 1}
	gOpts.keys["y"] = &callExpr{"copy", nil, 1}
	gOpts.keys["d"] = &callExpr{"cut", nil, 1}
	gOpts.keys["c"] = &callExpr{"clear", nil, 1}
	gOpts.keys["p"] = &callExpr{"paste", nil, 1}
	gOpts.keys["<c-l>"] = &callExpr{"redraw", nil, 1}
	gOpts.keys["<c-r>"] = &callExpr{"reload", nil, 1}
	gOpts.keys[":"] = &callExpr{"read", nil, 1}
	gOpts.keys["$"] = &callExpr{"shell", nil, 1}
	gOpts.keys["%"] = &callExpr{"shell-pipe", nil, 1}
	gOpts.keys["!"] = &callExpr{"shell-wait", nil, 1}
	gOpts.keys["&"] = &callExpr{"shell-async", nil, 1}
	gOpts.keys["f"] = &callExpr{"find", nil, 1}
	gOpts.keys["F"] = &callExpr{"find-back", nil, 1}
	gOpts.keys[";"] = &callExpr{"find-next", nil, 1}
	gOpts.keys[","] = &callExpr{"find-prev", nil, 1}
	gOpts.keys["/"] = &callExpr{"search", nil, 1}
	gOpts.keys["?"] = &callExpr{"search-back", nil, 1}
	gOpts.keys["n"] = &callExpr{"search-next", nil, 1}
	gOpts.keys["N"] = &callExpr{"search-prev", nil, 1}
	gOpts.keys["m"] = &callExpr{"mark-save", nil, 1}
	gOpts.keys["'"] = &callExpr{"mark-load", nil, 1}
	gOpts.keys["<c-n>"] = &callExpr{"cmd-history-next", nil, 1}
	gOpts.keys["<c-p>"] = &callExpr{"cmd-history-prev", nil, 1}

	gOpts.keys["zh"] = &setExpr{"hidden!", ""}
	gOpts.keys["zr"] = &setExpr{"reverse!", ""}
	gOpts.keys["zn"] = &setExpr{"info", ""}
	gOpts.keys["zs"] = &setExpr{"info", "size"}
	gOpts.keys["zt"] = &setExpr{"info", "time"}
	gOpts.keys["za"] = &setExpr{"info", "size:time"}
	gOpts.keys["sn"] = &listExpr{[]expr{&setExpr{"sortby", "natural"}, &setExpr{"info", ""}}}
	gOpts.keys["ss"] = &listExpr{[]expr{&setExpr{"sortby", "size"}, &setExpr{"info", "size"}}}
	gOpts.keys["st"] = &listExpr{[]expr{&setExpr{"sortby", "time"}, &setExpr{"info", "time"}}}
	gOpts.keys["gh"] = &callExpr{"cd", []string{"~"}, 1}

	gOpts.cmdkeys = make(map[string]expr)

	gOpts.cmdkeys["<space>"] = &callExpr{"cmd-insert", []string{" "}, 1}
	gOpts.cmdkeys["<esc>"] = &callExpr{"cmd-escape", nil, 1}
	gOpts.cmdkeys["<tab>"] = &callExpr{"cmd-complete", nil, 1}
	gOpts.cmdkeys["<enter>"] = &callExpr{"cmd-enter", nil, 1}
	gOpts.cmdkeys["<c-j>"] = &callExpr{"cmd-enter", nil, 1}
	gOpts.cmdkeys["<c-n>"] = &callExpr{"cmd-history-next", nil, 1}
	gOpts.cmdkeys["<c-p>"] = &callExpr{"cmd-history-prev", nil, 1}
	gOpts.cmdkeys["<delete>"] = &callExpr{"cmd-delete", nil, 1}
	gOpts.cmdkeys["<c-d>"] = &callExpr{"cmd-delete", nil, 1}
	gOpts.cmdkeys["<bs>"] = &callExpr{"cmd-delete-back", nil, 1}
	gOpts.cmdkeys["<bs2>"] = &callExpr{"cmd-delete-back", nil, 1}
	gOpts.cmdkeys["<left>"] = &callExpr{"cmd-left", nil, 1}
	gOpts.cmdkeys["<c-b>"] = &callExpr{"cmd-left", nil, 1}
	gOpts.cmdkeys["<right>"] = &callExpr{"cmd-right", nil, 1}
	gOpts.cmdkeys["<c-f>"] = &callExpr{"cmd-right", nil, 1}
	gOpts.cmdkeys["<home>"] = &callExpr{"cmd-home", nil, 1}
	gOpts.cmdkeys["<c-a>"] = &callExpr{"cmd-home", nil, 1}
	gOpts.cmdkeys["<end>"] = &callExpr{"cmd-end", nil, 1}
	gOpts.cmdkeys["<c-e>"] = &callExpr{"cmd-end", nil, 1}
	gOpts.cmdkeys["<c-u>"] = &callExpr{"cmd-delete-home", nil, 1}
	gOpts.cmdkeys["<c-k>"] = &callExpr{"cmd-delete-end", nil, 1}
	gOpts.cmdkeys["<c-w>"] = &callExpr{"cmd-delete-unix-word", nil, 1}
	gOpts.cmdkeys["<c-y>"] = &callExpr{"cmd-yank", nil, 1}
	gOpts.cmdkeys["<c-t>"] = &callExpr{"cmd-transpose", nil, 1}
	gOpts.cmdkeys["<c-c>"] = &callExpr{"cmd-interrupt", nil, 1}
	gOpts.cmdkeys["<a-f>"] = &callExpr{"cmd-word", nil, 1}
	gOpts.cmdkeys["<a-b>"] = &callExpr{"cmd-word-back", nil, 1}
	gOpts.cmdkeys["<a-c>"] = &callExpr{"cmd-capitalize-word", nil, 1}
	gOpts.cmdkeys["<a-d>"] = &callExpr{"cmd-delete-word", nil, 1}
	gOpts.cmdkeys["<a-u>"] = &callExpr{"cmd-uppercase-word", nil, 1}
	gOpts.cmdkeys["<a-l>"] = &callExpr{"cmd-lowercase-word", nil, 1}
	gOpts.cmdkeys["<a-t>"] = &callExpr{"cmd-transpose-word", nil, 1}

	gOpts.cmds = make(map[string]expr)

	setDefaults()
}
<commit_msg>cleanup<commit_after>package main

import "time"

type sortMethod byte

const (
	naturalSort sortMethod = iota
	nameSort
	sizeSort
	timeSort
)

type sortOption byte

const (
	dirfirstSort sortOption = 1 << iota
	hiddenSort
	reverseSort
)

type sortType struct {
	method sortMethod
	option sortOption
}

var gOpts struct {
	anchorfind     bool
	color256       bool
	dircounts      bool
	drawbox        bool
	globsearch     bool
	ignorecase     bool
	incsearch      bool
	preview        bool
	smartcase      bool
	ignoredia      bool
	smartdia       bool
	wrapscan       bool
	number         bool
	relativenumber bool
	findlen        int
	period         int
	scrolloff      int
	tabstop        int
	errorfmt       string
	filesep        string
	ifs            string
	previewer      string
	promptfmt      string
	shell          string
	timefmt        string
	ratios         []int
	info           []string
	shellopts      []string
	keys           map[string]expr
	cmdkeys        map[string]expr
	cmds           map[string]expr
	sortType       sortType
}

func init() {
	gOpts.anchorfind = true
	gOpts.color256 = false
	gOpts.dircounts = false
	gOpts.drawbox = false
	gOpts.globsearch = false
	gOpts.ignorecase = true
	gOpts.incsearch = false
	gOpts.preview = true
	gOpts.smartcase = true
	gOpts.ignoredia = false
	gOpts.smartdia = false
	gOpts.wrapscan = true
	gOpts.number = false
	gOpts.relativenumber = false
	gOpts.findlen = 1
	gOpts.period = 0
	gOpts.scrolloff = 0
	gOpts.tabstop = 8
	gOpts.errorfmt = "\033[7;31;47m%s\033[0m"
	gOpts.filesep = "\n"
	gOpts.ifs = ""
	gOpts.previewer = ""
	gOpts.promptfmt = "\033[32;1m%u@%h\033[0m:\033[34;1m%w/\033[0m\033[1m%f\033[0m"
	gOpts.shell = gDefaultShell
	gOpts.timefmt = time.ANSIC
	gOpts.ratios = []int{1, 2, 3}
	gOpts.info = nil
	gOpts.shellopts = nil
	gOpts.sortType = sortType{naturalSort, dirfirstSort}

	gOpts.keys = make(map[string]expr)

	gOpts.keys["k"] = &callExpr{"up", nil, 1}
	gOpts.keys["<up>"] = &callExpr{"up", nil, 1}
	gOpts.keys["<c-u>"] = &callExpr{"half-up", nil, 1}
	gOpts.keys["<c-b>"] = &callExpr{"page-up", nil, 1}
	gOpts.keys["<pgup>"] = &callExpr{"page-up", nil, 1}
	gOpts.keys["j"] = &callExpr{"down", nil, 1}
	gOpts.keys["<down>"] = &callExpr{"down", nil, 1}
	gOpts.keys["<c-d>"] = &callExpr{"half-down", nil, 1}
	gOpts.keys["<c-f>"] = &callExpr{"page-down", nil, 1}
	gOpts.keys["<pgdn>"] = &callExpr{"page-down", nil, 1}
	gOpts.keys["h"] = &callExpr{"updir", nil, 1}
	gOpts.keys["<left>"] = &callExpr{"updir", nil, 1}
	gOpts.keys["l"] = &callExpr{"open", nil, 1}
	gOpts.keys["<right>"] = &callExpr{"open", nil, 1}
	gOpts.keys["q"] = &callExpr{"quit", nil, 1}
	gOpts.keys["gg"] = &callExpr{"top", nil, 1}
	gOpts.keys["<home>"] = &callExpr{"top", nil, 1}
	gOpts.keys["G"] = &callExpr{"bottom", nil, 1}
	gOpts.keys["<end>"] = &callExpr{"bottom", nil, 1}
	gOpts.keys["<space>"] = &callExpr{"toggle", nil, 1}
	gOpts.keys["v"] = &callExpr{"invert", nil, 1}
	gOpts.keys["u"] = &callExpr{"unselect", nil, 1}
	gOpts.keys["y"] = &callExpr{"copy", nil, 1}
	gOpts.keys["d"] = &callExpr{"cut", nil, 1}
	gOpts.keys["c"] = &callExpr{"clear", nil, 1}
	gOpts.keys["p"] = &callExpr{"paste", nil, 1}
	gOpts.keys["<c-l>"] = &callExpr{"redraw", nil, 1}
	gOpts.keys["<c-r>"] = &callExpr{"reload", nil, 1}
	gOpts.keys[":"] = &callExpr{"read", nil, 1}
	gOpts.keys["$"] = &callExpr{"shell", nil, 1}
	gOpts.keys["%"] = &callExpr{"shell-pipe", nil, 1}
	gOpts.keys["!"] = &callExpr{"shell-wait", nil, 1}
	gOpts.keys["&"] = &callExpr{"shell-async", nil, 1}
	gOpts.keys["f"] = &callExpr{"find", nil, 1}
	gOpts.keys["F"] = &callExpr{"find-back", nil, 1}
	gOpts.keys[";"] = &callExpr{"find-next", nil, 1}
	gOpts.keys[","] = &callExpr{"find-prev", nil, 1}
	gOpts.keys["/"] = &callExpr{"search", nil, 1}
	gOpts.keys["?"] = &callExpr{"search-back", nil, 1}
	gOpts.keys["n"] = &callExpr{"search-next", nil, 1}
	gOpts.keys["N"] = &callExpr{"search-prev", nil, 1}
	gOpts.keys["m"] = &callExpr{"mark-save", nil, 1}
	gOpts.keys["'"] = &callExpr{"mark-load", nil, 1}
	gOpts.keys["<c-n>"] = &callExpr{"cmd-history-next", nil, 1}
	gOpts.keys["<c-p>"] = &callExpr{"cmd-history-prev", nil, 1}

	gOpts.keys["zh"] = &setExpr{"hidden!", ""}
	gOpts.keys["zr"] = &setExpr{"reverse!", ""}
	gOpts.keys["zn"] = &setExpr{"info", ""}
	gOpts.keys["zs"] = &setExpr{"info", "size"}
	gOpts.keys["zt"] = &setExpr{"info", "time"}
	gOpts.keys["za"] = &setExpr{"info", "size:time"}
	gOpts.keys["sn"] = &listExpr{[]expr{&setExpr{"sortby", "natural"}, &setExpr{"info", ""}}}
	gOpts.keys["ss"] = &listExpr{[]expr{&setExpr{"sortby", "size"}, &setExpr{"info", "size"}}}
	gOpts.keys["st"] = &listExpr{[]expr{&setExpr{"sortby", "time"}, &setExpr{"info", "time"}}}
	gOpts.keys["gh"] = &callExpr{"cd", []string{"~"}, 1}

	gOpts.cmdkeys = make(map[string]expr)

	gOpts.cmdkeys["<space>"] = &callExpr{"cmd-insert", []string{" "}, 1}
	gOpts.cmdkeys["<esc>"] = &callExpr{"cmd-escape", nil, 1}
	gOpts.cmdkeys["<tab>"] = &callExpr{"cmd-complete", nil, 1}
	gOpts.cmdkeys["<enter>"] = &callExpr{"cmd-enter", nil, 1}
	gOpts.cmdkeys["<c-j>"] = &callExpr{"cmd-enter", nil, 1}
	gOpts.cmdkeys["<c-n>"] = &callExpr{"cmd-history-next", nil, 1}
	gOpts.cmdkeys["<c-p>"] = &callExpr{"cmd-history-prev", nil, 1}
	gOpts.cmdkeys["<delete>"] = &callExpr{"cmd-delete", nil, 1}
	gOpts.cmdkeys["<c-d>"] = &callExpr{"cmd-delete", nil, 1}
	gOpts.cmdkeys["<bs>"] = &callExpr{"cmd-delete-back", nil, 1}
	gOpts.cmdkeys["<bs2>"] = &callExpr{"cmd-delete-back", nil, 1}
	gOpts.cmdkeys["<left>"] = &callExpr{"cmd-left", nil, 1}
	gOpts.cmdkeys["<c-b>"] = &callExpr{"cmd-left", nil, 1}
	gOpts.cmdkeys["<right>"] = &callExpr{"cmd-right", nil, 1}
	gOpts.cmdkeys["<c-f>"] = &callExpr{"cmd-right", nil, 1}
	gOpts.cmdkeys["<home>"] = &callExpr{"cmd-home", nil, 1}
	gOpts.cmdkeys["<c-a>"] = &callExpr{"cmd-home", nil, 1}
	gOpts.cmdkeys["<end>"] = &callExpr{"cmd-end", nil, 1}
	gOpts.cmdkeys["<c-e>"] = &callExpr{"cmd-end", nil, 1}
	gOpts.cmdkeys["<c-u>"] = &callExpr{"cmd-delete-home", nil, 1}
	gOpts.cmdkeys["<c-k>"] = &callExpr{"cmd-delete-end", nil, 1}
	gOpts.cmdkeys["<c-w>"] = &callExpr{"cmd-delete-unix-word", nil, 1}
	gOpts.cmdkeys["<c-y>"] = &callExpr{"cmd-yank", nil, 1}
	gOpts.cmdkeys["<c-t>"] = &callExpr{"cmd-transpose", nil, 1}
	gOpts.cmdkeys["<c-c>"] = &callExpr{"cmd-interrupt", nil, 1}
	gOpts.cmdkeys["<a-f>"] = &callExpr{"cmd-word", nil, 1}
	gOpts.cmdkeys["<a-b>"] = &callExpr{"cmd-word-back", nil, 1}
	gOpts.cmdkeys["<a-c>"] = &callExpr{"cmd-capitalize-word", nil, 1}
	gOpts.cmdkeys["<a-d>"] = &callExpr{"cmd-delete-word", nil, 1}
	gOpts.cmdkeys["<a-u>"] = &callExpr{"cmd-uppercase-word", nil, 1}
	gOpts.cmdkeys["<a-l>"] = &callExpr{"cmd-lowercase-word", nil, 1}
	gOpts.cmdkeys["<a-t>"] = &callExpr{"cmd-transpose-word", nil, 1}

	gOpts.cmds = make(map[string]expr)

	setDefaults()
}
<|endoftext|>


<commit_before>// Package minify relates MIME type to minifiers. Several minifiers are provided in the subpackages.
package minify // import "github.com/tdewolff/minify"

import (
	"errors"
	"io"
	"os/exec"
	"regexp"

	"github.com/tdewolff/buffer"
)

// ErrNotExist is returned when no minifier exists for a given mimetype.
var ErrNotExist = errors.New("minify function does not exist for mimetype")

////////////////////////////////////////////////////////////////

type MinifierFunc func(*M, io.Writer, io.Reader, map[string]string) error

func (f MinifierFunc) Minify(m *M, w io.Writer, r io.Reader, params map[string]string) error {
	return f(m, w, r, params)
}

// Func is the function interface for minifiers.
// The Minifier parameter is used for embedded resources, such as JS within HTML.
// The mediatype string is for wildcard minifiers so they know what they minify and for parameter passing (charset for example).
type Minifier interface {
	Minify(*M, io.Writer, io.Reader, map[string]string) error
}

////////////////////////////////////////////////////////////////

type patternMinifier struct {
	pattern *regexp.Regexp
	Minifier
}

type cmdMinifier struct {
	cmd *exec.Cmd
}

func (c *cmdMinifier) Minify(_ *M, w io.Writer, r io.Reader, _ map[string]string) error {
	cmd := &exec.Cmd{}
	*cmd = *c.cmd // concurrency safety
	cmd.Stdout = w
	cmd.Stdin = r
	return cmd.Run()
}

////////////////////////////////////////////////////////////////

// M holds a map of mimetype => function to allow recursive minifier calls of the minifier functions.
type M struct {
	literal map[string]Minifier
	pattern []patternMinifier
}

// New returns a new M.
func New() *M {
	return &M{
		map[string]Minifier{},
		[]patternMinifier{},
	}
}

// AddFunc adds a minify function to the mimetype => function map (unsafe for concurrent use).
// It allows one to implement a custom minifier for a specific mimetype.
func (m *M) Add(mimetype string, minifier Minifier) {
	m.literal[mimetype] = minifier
}

func (m *M) AddFunc(mimetype string, minifierFunc MinifierFunc) {
	m.literal[mimetype] = minifierFunc
}

// AddFuncRegexp adds a minify function to the mimetype => function map (unsafe for concurrent use).
// It allows one to implement a custom minifier for a specific mimetype regular expression.
func (m *M) AddPattern(pattern *regexp.Regexp, minifier Minifier) {
	m.pattern = append(m.pattern, patternMinifier{pattern, minifier})
}

func (m *M) AddFuncPattern(pattern *regexp.Regexp, minifierFunc MinifierFunc) {
	m.pattern = append(m.pattern, patternMinifier{pattern, minifierFunc})
}

// AddCmd adds a minify function to the mimetype => function map (unsafe for concurrent use) that executes a command to process the minification.
// It allows the use of external tools like ClosureCompiler, UglifyCSS, etc. for a specific mimetype.
// Be aware that running external tools will slow down minification a lot!
func (m *M) AddCmd(mimetype string, cmd *exec.Cmd) {
	m.literal[mimetype] = &cmdMinifier{cmd}
}

// AddCmdRegexp adds a minify function to the mimetype => function map (unsafe for concurrent use) that executes a command to process the minification.
// It allows the use of external tools like ClosureCompiler, UglifyCSS, etc. for a specific mimetype regular expression.
// Be aware that running external tools will slow down minification a lot!
func (m *M) AddCmdPattern(pattern *regexp.Regexp, cmd *exec.Cmd) {
	m.pattern = append(m.pattern, patternMinifier{pattern, &cmdMinifier{cmd}})
}

// Minify minifies the content of a Reader and writes it to a Writer (safe for concurrent use).
// An error is returned when no such mimetype exists (ErrNotExist) or when an error occurred in the minifier function.
// Mimetype may take the form of 'text/plain', 'text/*' or '*/*'.
func (m *M) Minify(w io.Writer, r io.Reader, mimetype string, params map[string]string) error {
	if minifier, ok := m.literal[mimetype]; ok {
		if err := minifier.Minify(m, w, r, params); err != nil {
			return err
		}
		return nil
	}
	for _, minifier := range m.pattern {
		if minifier.pattern.MatchString(mimetype) {
			if err := minifier.Minify(m, w, r, params); err != nil {
				return err
			}
			return nil
		}
	}
	return ErrNotExist
}

// Bytes minifies an array of bytes (safe for concurrent use). When an error occurs it return the original array and the error.
// It returns an error when no such mimetype exists (ErrNotExist) or any error occurred in the minifier function.
func (m *M) Bytes(v []byte, mimetype string, params map[string]string) ([]byte, error) {
	out := buffer.NewWriter(make([]byte, 0, len(v)))
	if err := m.Minify(out, buffer.NewReader(v), mimetype, params); err != nil {
		return v, err
	}
	return out.Bytes(), nil
}

// String minifies a string (safe for concurrent use). When an error occurs it return the original string and the error.
// It returns an error when no such mimetype exists (ErrNotExist) or any error occurred in the minifier function.
func (m *M) String(v string, mimetype string, params map[string]string) (string, error) {
	out := buffer.NewWriter(make([]byte, 0, len(v)))
	if err := m.Minify(out, buffer.NewReader([]byte(v)), mimetype, params); err != nil {
		return v, err
	}
	return string(out.Bytes()), nil
}
<commit_msg>Comments update<commit_after>// Package minify relates MIME type to minifiers. Several minifiers are provided in the subpackages.
package minify // import "github.com/tdewolff/minify"

import (
	"errors"
	"io"
	"os/exec"
	"regexp"

	"github.com/tdewolff/buffer"
)

// ErrNotExist is returned when no minifier exists for a given mimetype.
var ErrNotExist = errors.New("minify function does not exist for mimetype")

////////////////////////////////////////////////////////////////

type minifierFunc func(*M, io.Writer, io.Reader, map[string]string) error

func (f minifierFunc) Minify(m *M, w io.Writer, r io.Reader, params map[string]string) error {
	return f(m, w, r, params)
}

// Minifier is the interface for minifiers.
// The *M parameter is used for minifying embedded resources, such as JS within HTML.
// The map[string]string is for parameter passing (charset=UTF-8 for example).
type Minifier interface {
	Minify(*M, io.Writer, io.Reader, map[string]string) error
}

////////////////////////////////////////////////////////////////

type patternMinifier struct {
	pattern *regexp.Regexp
	Minifier
}

type cmdMinifier struct {
	cmd *exec.Cmd
}

func (c *cmdMinifier) Minify(_ *M, w io.Writer, r io.Reader, _ map[string]string) error {
	cmd := &exec.Cmd{}
	*cmd = *c.cmd // concurrency safety
	cmd.Stdout = w
	cmd.Stdin = r
	return cmd.Run()
}

////////////////////////////////////////////////////////////////

// M holds a map of mimetype => function to allow recursive minifier calls of the minifier functions.
type M struct {
	literal map[string]Minifier
	pattern []patternMinifier
}

// New returns a new M.
func New() *M {
	return &M{
		map[string]Minifier{},
		[]patternMinifier{},
	}
}

// Add adds a minifier to the mimetype => function map (unsafe for concurrent use).
func (m *M) Add(mimetype string, minifier Minifier) {
	m.literal[mimetype] = minifier
}

// AddFunc adds a minify function to the mimetype => function map (unsafe for concurrent use).
func (m *M) AddFunc(mimetype string, minifier minifierFunc) {
	m.literal[mimetype] = minifier
}

// AddPattern adds a minifier to the mimetype => function map (unsafe for concurrent use).
func (m *M) AddPattern(pattern *regexp.Regexp, minifier Minifier) {
	m.pattern = append(m.pattern, patternMinifier{pattern, minifier})
}

// AddFuncPattern adds a minify function to the mimetype => function map (unsafe for concurrent use).
func (m *M) AddFuncPattern(pattern *regexp.Regexp, minifier minifierFunc) {
	m.pattern = append(m.pattern, patternMinifier{pattern, minifier})
}

// AddCmd adds a minify function to the mimetype => function map (unsafe for concurrent use) that executes a command to process the minification.
// It allows the use of external tools like ClosureCompiler, UglifyCSS, etc. for a specific mimetype.
func (m *M) AddCmd(mimetype string, cmd *exec.Cmd) {
	m.literal[mimetype] = &cmdMinifier{cmd}
}

// AddCmdRegexp adds a minify function to the mimetype => function map (unsafe for concurrent use) that executes a command to process the minification.
// It allows the use of external tools like ClosureCompiler, UglifyCSS, etc. for a specific mimetype regular expression.
func (m *M) AddCmdPattern(pattern *regexp.Regexp, cmd *exec.Cmd) {
	m.pattern = append(m.pattern, patternMinifier{pattern, &cmdMinifier{cmd}})
}

// Minify minifies the content of a Reader and writes it to a Writer (safe for concurrent use).
// An error is returned when no such mimetype exists (ErrNotExist) or when an error occurred in the minifier function.
// Mimetype may take the form of 'text/plain', 'text/*' or '*/*'.
func (m *M) Minify(w io.Writer, r io.Reader, mimetype string, params map[string]string) error {
	if minifier, ok := m.literal[mimetype]; ok {
		if err := minifier.Minify(m, w, r, params); err != nil {
			return err
		}
		return nil
	}
	for _, minifier := range m.pattern {
		if minifier.pattern.MatchString(mimetype) {
			if err := minifier.Minify(m, w, r, params); err != nil {
				return err
			}
			return nil
		}
	}
	return ErrNotExist
}

// Bytes minifies an array of bytes (safe for concurrent use). When an error occurs it return the original array and the error.
// It returns an error when no such mimetype exists (ErrNotExist) or any error occurred in the minifier function.
func (m *M) Bytes(v []byte, mimetype string, params map[string]string) ([]byte, error) {
	out := buffer.NewWriter(make([]byte, 0, len(v)))
	if err := m.Minify(out, buffer.NewReader(v), mimetype, params); err != nil {
		return v, err
	}
	return out.Bytes(), nil
}

// String minifies a string (safe for concurrent use). When an error occurs it return the original string and the error.
// It returns an error when no such mimetype exists (ErrNotExist) or any error occurred in the minifier function.
func (m *M) String(v string, mimetype string, params map[string]string) (string, error) {
	out := buffer.NewWriter(make([]byte, 0, len(v)))
	if err := m.Minify(out, buffer.NewReader([]byte(v)), mimetype, params); err != nil {
		return v, err
	}
	return string(out.Bytes()), nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

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

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

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

package framework

import (
	"fmt"
	"net"
	"net/http"
	"time"

	"vitess.io/vitess/go/vt/log"
	"vitess.io/vitess/go/vt/topo"
	"vitess.io/vitess/go/yaml2"

	"vitess.io/vitess/go/vt/topo/memorytopo"
	"vitess.io/vitess/go/vt/vterrors"

	"context"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/vt/dbconfigs"
	"vitess.io/vitess/go/vt/vtgate/fakerpcvtgateconn"
	"vitess.io/vitess/go/vt/vtgate/vtgateconn"
	"vitess.io/vitess/go/vt/vttablet/tabletserver"
	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"

	querypb "vitess.io/vitess/go/vt/proto/query"
	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)

var (
	// Target is the target info for the server.
	Target *querypb.Target
	// Server is the TabletServer for the framework.
	Server *tabletserver.TabletServer
	// ServerAddress is the http URL for the server.
	ServerAddress string
	// ResolveChan is the channel that sends dtids that are to be resolved.
	ResolveChan = make(chan string, 1)
	// TopoServer is the topology for the server
	TopoServer *topo.Server
)

// StartCustomServer starts the server and initializes
// all the global variables. This function should only be called
// once at the beginning of the test.
func StartCustomServer(connParams, connAppDebugParams mysql.ConnParams, dbName string, config *tabletenv.TabletConfig) error {
	// Setup a fake vtgate server.
	protocol := "resolveTest"
	*vtgateconn.VtgateProtocol = protocol
	vtgateconn.RegisterDialer(protocol, func(context.Context, string) (vtgateconn.Impl, error) {
		return &txResolver{
			FakeVTGateConn: fakerpcvtgateconn.FakeVTGateConn{},
		}, nil
	})

	dbcfgs := dbconfigs.NewTestDBConfigs(connParams, connAppDebugParams, dbName)

	Target = &querypb.Target{
		Keyspace:   "vttest",
		Shard:      "0",
		TabletType: topodatapb.TabletType_MASTER,
	}
	TopoServer = memorytopo.NewServer("")

	Server = tabletserver.NewTabletServer("", config, TopoServer, &topodatapb.TabletAlias{})
	Server.Register()
	err := Server.StartService(Target, dbcfgs, nil /* mysqld */)
	if err != nil {
		return vterrors.Wrap(err, "could not start service")
	}

	// Start http service.
	ln, err := net.Listen("tcp", ":0")
	if err != nil {
		return vterrors.Wrap(err, "could not start listener")
	}
	ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String())
	go http.Serve(ln, nil)
	for {
		time.Sleep(10 * time.Millisecond)
		response, err := http.Get(fmt.Sprintf("%s/debug/vars", ServerAddress))
		if err == nil {
			response.Body.Close()
			break
		}
	}
	return nil
}

// StartServer starts the server and initializes
// all the global variables. This function should only be called
// once at the beginning of the test.
func StartServer(connParams, connAppDebugParams mysql.ConnParams, dbName string) error {
	config := tabletenv.NewDefaultConfig()
	config.StrictTableACL = true
	config.TwoPCEnable = true
	config.TwoPCAbandonAge = 1
	config.TwoPCCoordinatorAddress = "fake"
	config.HotRowProtection.Mode = tabletenv.Enable
	config.TrackSchemaVersions = true
	config.GracePeriods.ShutdownSeconds = 2
	config.SchemaReloadIntervalSeconds = tabletenv.Seconds(2.1)
	config.SignalSchemaChangeReloadIntervalSeconds = tabletenv.Seconds(5)
	config.SignalWhenSchemaChange = true
	gotBytes, _ := yaml2.Marshal(config)
	log.Infof("Config:\n%s", gotBytes)
	return StartCustomServer(connParams, connAppDebugParams, dbName, config)
}

// StopServer must be called once all the tests are done.
func StopServer() {
	Server.StopService()
}

// txReolver transmits dtids to be resolved through ResolveChan.
type txResolver struct {
	fakerpcvtgateconn.FakeVTGateConn
}

func (conn *txResolver) ResolveTransaction(ctx context.Context, dtid string) error {
	select {
	case ResolveChan <- dtid:
	default:
	}
	return nil
}
<commit_msg>reload schema more often during e2e tests<commit_after>/*
Copyright 2019 The Vitess Authors.

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

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

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

package framework

import (
	"fmt"
	"net"
	"net/http"
	"time"

	"vitess.io/vitess/go/vt/log"
	"vitess.io/vitess/go/vt/topo"
	"vitess.io/vitess/go/yaml2"

	"vitess.io/vitess/go/vt/topo/memorytopo"
	"vitess.io/vitess/go/vt/vterrors"

	"context"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/vt/dbconfigs"
	"vitess.io/vitess/go/vt/vtgate/fakerpcvtgateconn"
	"vitess.io/vitess/go/vt/vtgate/vtgateconn"
	"vitess.io/vitess/go/vt/vttablet/tabletserver"
	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"

	querypb "vitess.io/vitess/go/vt/proto/query"
	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)

var (
	// Target is the target info for the server.
	Target *querypb.Target
	// Server is the TabletServer for the framework.
	Server *tabletserver.TabletServer
	// ServerAddress is the http URL for the server.
	ServerAddress string
	// ResolveChan is the channel that sends dtids that are to be resolved.
	ResolveChan = make(chan string, 1)
	// TopoServer is the topology for the server
	TopoServer *topo.Server
)

// StartCustomServer starts the server and initializes
// all the global variables. This function should only be called
// once at the beginning of the test.
func StartCustomServer(connParams, connAppDebugParams mysql.ConnParams, dbName string, config *tabletenv.TabletConfig) error {
	// Setup a fake vtgate server.
	protocol := "resolveTest"
	*vtgateconn.VtgateProtocol = protocol
	vtgateconn.RegisterDialer(protocol, func(context.Context, string) (vtgateconn.Impl, error) {
		return &txResolver{
			FakeVTGateConn: fakerpcvtgateconn.FakeVTGateConn{},
		}, nil
	})

	dbcfgs := dbconfigs.NewTestDBConfigs(connParams, connAppDebugParams, dbName)

	Target = &querypb.Target{
		Keyspace:   "vttest",
		Shard:      "0",
		TabletType: topodatapb.TabletType_MASTER,
	}
	TopoServer = memorytopo.NewServer("")

	Server = tabletserver.NewTabletServer("", config, TopoServer, &topodatapb.TabletAlias{})
	Server.Register()
	err := Server.StartService(Target, dbcfgs, nil /* mysqld */)
	if err != nil {
		return vterrors.Wrap(err, "could not start service")
	}

	// Start http service.
	ln, err := net.Listen("tcp", ":0")
	if err != nil {
		return vterrors.Wrap(err, "could not start listener")
	}
	ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String())
	go http.Serve(ln, nil)
	for {
		time.Sleep(10 * time.Millisecond)
		response, err := http.Get(fmt.Sprintf("%s/debug/vars", ServerAddress))
		if err == nil {
			response.Body.Close()
			break
		}
	}
	return nil
}

// StartServer starts the server and initializes
// all the global variables. This function should only be called
// once at the beginning of the test.
func StartServer(connParams, connAppDebugParams mysql.ConnParams, dbName string) error {
	config := tabletenv.NewDefaultConfig()
	config.StrictTableACL = true
	config.TwoPCEnable = true
	config.TwoPCAbandonAge = 1
	config.TwoPCCoordinatorAddress = "fake"
	config.HotRowProtection.Mode = tabletenv.Enable
	config.TrackSchemaVersions = true
	config.GracePeriods.ShutdownSeconds = 2
	config.SignalSchemaChangeReloadIntervalSeconds = tabletenv.Seconds(2.1)
	config.SignalWhenSchemaChange = true
	gotBytes, _ := yaml2.Marshal(config)
	log.Infof("Config:\n%s", gotBytes)
	return StartCustomServer(connParams, connAppDebugParams, dbName, config)
}

// StopServer must be called once all the tests are done.
func StopServer() {
	Server.StopService()
}

// txReolver transmits dtids to be resolved through ResolveChan.
type txResolver struct {
	fakerpcvtgateconn.FakeVTGateConn
}

func (conn *txResolver) ResolveTransaction(ctx context.Context, dtid string) error {
	select {
	case ResolveChan <- dtid:
	default:
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

const (
	Version         = "0.1.0"
	ExitCodeSuccess = 0
	ExitCodeError   = 1
)

type Mock struct {
	Name    string
	Meta    Meta
	Screens []Screen
	Launch  Launch
	Colors  []Color
	Strings []String
}

type Meta struct {
	Android Android
}

type Android struct {
	Package             string
	GradlePluginVersion string `json:"gradle_plugin_version"`
	BuildToolsVersion   string `json:"build_tools_version"`
	MinSdkVersion       int    `json:"min_sdk_version"`
	TargetSdkVersion    int    `json:"target_sdk_version"`
	CompileSdkVersion   string `json:"compile_sdk_version"`
	VersionCode         int    `json:"version_code"`
	VersionName         string `json:"version_name"`
}

type Screen struct {
	Id        string
	Name      string
	Layout    Layout
	Behaviors []Behavior
}

type Layout struct {
	Views []View
}

type View struct {
	Id     string
	Type   string
	Label  string
	SizeW  string `json:"size_w"`
	SizeH  string `json:"size_h"`
	AlignH string `json:"align_h"`
	AlignV string `json:"align_v"`
}

type Behavior struct {
	Trigger Trigger
	Action  Action
}

type Trigger struct {
	Type   string
	Widget string
}

type Action struct {
	Type    string
	Transit string
}

type Launch struct {
	Screen string
}

type Color struct {
	Id    string
	Value string
}

type String struct {
	Lang string
	Defs []Def
}

type Def struct {
	Id    string
	Value string
}

func main() {
	// Parse command
	if len(os.Args) == 1 {
		printUsage()
		os.Exit(ExitCodeError)
	}
	switch os.Args[1] {
	case "gen":
	case "version":
		printVersion()
		os.Exit(ExitCodeSuccess)
	case "help":
		fallthrough
	default:
		printUsage()
		os.Exit(ExitCodeError)
	}

	if len(os.Args) < 3 {
		printUsage()
		os.Exit(ExitCodeError)
	}
	genId := os.Args[2]

	mock := parseConfigs()
	gen(&mock, genId)
}

func printUsage() {
	fmt.Println(`mocker is a mock up framework for mobile apps.

Usage:
	mocker command [options]

Command:
	gen      generate source code (see 'Generator')
	help     show this help
	version  show version of mocker

Generator:
	mocker gen ID

	ID:
		ios  Objective-C code for iOS app
`)
}

func printVersion() {
	fmt.Println("mocker version \"" + Version + "\"")
}

func parseConfigs() (mock Mock) {
	filename := "Mockerfile"
	xmlFile, err := os.Open(filename)
	if err != nil {
		fmt.Println("Error opening file", err)
		return
	}
	defer xmlFile.Close()

	b, _ := ioutil.ReadAll(xmlFile)
	err = json.Unmarshal(b, &mock)
	if err != nil {
		fmt.Println("Error unmarshaling Mockerfile", err)
		return
	}

	return
}

func gen(mock *Mock, genId string) {
	switch genId {
	case "ios":
		genIos(mock)
	case "android":
		genAndroid(mock)
	default:
		fmt.Println("Invalid gen ID")
		printUsage()
		os.Exit(ExitCodeError)
	}
}

func genAndroid(mock *Mock) {
	// TODO
	fmt.Printf("%+v\n", mock)

	outDir := "out"
	srcDir := filepath.Join(outDir, "src")
	mainDir := filepath.Join(srcDir, "main")
	javaDir := filepath.Join(mainDir, "java")
	packageDir := filepath.Join(javaDir, strings.Replace(mock.Meta.Android.Package, ".", string(os.PathSeparator), -1))
	resDir := filepath.Join(mainDir, "res")
	layoutDir := filepath.Join(resDir, "layout")
	valuesDir := filepath.Join(resDir, "values")

	// Generate base file set using android command
	cmd := exec.Command("android", "create", "project", "-n", "mock", "-v", mock.Meta.Android.GradlePluginVersion, "-g", "-k", mock.Meta.Android.Package, "-a", "DummyActivity", "-t", "android-19", "-p", outDir)
	err := cmd.Run()
	if err != nil {
		fmt.Printf("Error while generating project")
	}

	// Remove unecessery directories and files
	os.RemoveAll(filepath.Join(srcDir, "androidTest"))
	os.Remove(filepath.Join(packageDir, "DummyActivity.java"))
	os.Remove(filepath.Join(layoutDir, "main.xml"))

	// Generate Manifest
	genAndroidManifest(mock, mainDir)

	// Generate build.gradle
	genAndroidGradle(mock, outDir)

	// Generate Activities
	for i := range mock.Screens {
		screen := mock.Screens[i]
		genAndroidActivity(mock, packageDir, screen)
		genAndroidActivityLayout(mock, layoutDir, screen)
	}

	// Generate resources
	genAndroidStrings(mock, valuesDir)
	genAndroidLocalizedStrings(mock, resDir)
	genAndroidColors(mock, valuesDir)
}

func genIos(mock *Mock) {
	// TODO
	fmt.Printf("%+v\n", mock)
}

func genAndroidManifest(mock *Mock, outDir string) {
	filename := filepath.Join(outDir, "AndroidManifest.xml")
	f := createFile(filename)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="%s" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
`, mock.Meta.Android.Package))

	launcherId := mock.Launch.Screen
	for i := range mock.Screens {
		screen := mock.Screens[i]
		activityId := strings.Title(screen.Id)
		if screen.Id == launcherId {
			// Launcher
			f.WriteString(fmt.Sprintf(`        <activity
            android:label="@string/activity_title_%s"
            android:name=".%sActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
`, screen.Id, activityId))
		} else {
			f.WriteString(fmt.Sprintf(`        <activity
            android:label="@string/activity_title_%s"
            android:name=".%sActivity" />
`, screen.Id, activityId))
		}
	}

	f.WriteString(`    </application>

</manifest>
`)
	f.Close()
}

func genAndroidGradle(mock *Mock, outDir string) {
	filename := filepath.Join(outDir, "build.gradle")
	f := createFile(filename)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:%s'
    }
}
`, mock.Meta.Android.GradlePluginVersion))
	f.WriteString(fmt.Sprintf(`apply plugin: 'com.android.application'

android {
    compileSdkVersion '%s'
    buildToolsVersion '%s'

    defaultConfig {
        applicationId "%s"
        minSdkVersion %d
        targetSdkVersion %d
        versionCode %d
        versionName "%s"
    }

    buildTypes {
        release {
            runProguard false
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }
    }
}
`,
		mock.Meta.Android.CompileSdkVersion,
		mock.Meta.Android.BuildToolsVersion,
		mock.Meta.Android.Package,
		mock.Meta.Android.MinSdkVersion,
		mock.Meta.Android.TargetSdkVersion,
		mock.Meta.Android.VersionCode,
		mock.Meta.Android.VersionName))

	f.Close()
}

func genAndroidActivity(mock *Mock, packageDir string, screen Screen) {
	activityId := strings.Title(screen.Id)
	filename := filepath.Join(packageDir, activityId+"Activity.java")
	f := createFile(filename)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`package %s;

import android.os.Bundle;

public class %sActivity extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_%s);
		init();
	}

	private void init() {
	}

}
`, mock.Meta.Android.Package, activityId, screen.Id))
	f.Close()
}

func genAndroidActivityLayout(mock *Mock, layoutDir string, screen Screen) {
	filename := filepath.Join(layoutDir, "activity_"+screen.Id+".xml")
	f := createFile(filename)
	defer f.Close()
	xmlns := `xmlns:android="http://schemas.android.com/apk/res/android"`
	f.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<LinearLayout %s
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp" >
`, xmlns))

	for i := range screen.Layout.Views {
		view := screen.Layout.Views[i]
		switch view.Type {
		case "button":
			f.WriteString(fmt.Sprintf(`
    <Button
        android:id="@+id/%s"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/%s"
        android:textColor="#FF8800"
        android:textSize="30dp" />
`, view.Id, view.Label))
		default:
		}
	}
	f.WriteString(`</LinearLayout>
`)

	f.Close()
}

func genAndroidStrings(mock *Mock, valuesDir string) {
	filename := filepath.Join(valuesDir, "strings_app.xml")
	f := createFile(filename)
	defer f.Close()

	// App name
	f.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">%s</app_name>
`, mock.Name))

	// Activity title
	for i := range mock.Screens {
		screen := mock.Screens[i]
		f.WriteString(fmt.Sprintf(`    <string name="activity_title_%s">%s</string>
`, screen.Id, screen.Name))
	}

	f.WriteString(`</resources>
`)
	f.Close()
}

func genAndroidLocalizedStrings(mock *Mock, resDir string) {
	for i := range mock.Strings {
		s := mock.Strings[i]
		lang := s.Lang
		suffix := "-" + lang
		if strings.ToLower(lang) == "base" {
			suffix = ""
		}
		valuesDir := filepath.Join(resDir, "values"+suffix)
		os.MkdirAll(valuesDir, 0777)
		filename := filepath.Join(valuesDir, "strings.xml")
		f := createFile(filename)
		defer f.Close()
		f.WriteString(`<?xml version="1.0" encoding="utf-8"?>
<resources>
`)
		for j := range s.Defs {
			def := s.Defs[j]
			f.WriteString(fmt.Sprintf(`    <string name="%s">%s</string>
`, def.Id, def.Value))
		}
		f.WriteString(`</resources>
`)
		f.Close()
	}
}

func genAndroidColors(mock *Mock, valuesDir string) {
	filename := filepath.Join(valuesDir, "colors.xml")
	f := createFile(filename)
	defer f.Close()

	f.WriteString(`<?xml version="1.0" encoding="utf-8"?>
<resources>
`)

	for i := range mock.Colors {
		c := mock.Colors[i]
		f.WriteString(fmt.Sprintf(`    <color name="%s">%s</color>
`, c.Id, c.Value))
	}

	f.WriteString(`</resources>
`)
	f.Close()
}

// Overwrite and create new file
func createFile(filename string) (f *os.File) {
	if fileExists(filename) {
		os.Remove(filename)
	}
	f, _ = os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
	return
}

func fileExists(filename string) bool {
	if _, err := os.Stat(filename); err != nil && os.IsNotExist(err) {
		return false
	}
	return true
}
<commit_msg>Fixed parameter layout for readability.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

const (
	Version         = "0.1.0"
	ExitCodeSuccess = 0
	ExitCodeError   = 1
)

type Mock struct {
	Name    string
	Meta    Meta
	Screens []Screen
	Launch  Launch
	Colors  []Color
	Strings []String
}

type Meta struct {
	Android Android
}

type Android struct {
	Package             string
	GradlePluginVersion string `json:"gradle_plugin_version"`
	BuildToolsVersion   string `json:"build_tools_version"`
	MinSdkVersion       int    `json:"min_sdk_version"`
	TargetSdkVersion    int    `json:"target_sdk_version"`
	CompileSdkVersion   string `json:"compile_sdk_version"`
	VersionCode         int    `json:"version_code"`
	VersionName         string `json:"version_name"`
}

type Screen struct {
	Id        string
	Name      string
	Layout    Layout
	Behaviors []Behavior
}

type Layout struct {
	Views []View
}

type View struct {
	Id     string
	Type   string
	Label  string
	SizeW  string `json:"size_w"`
	SizeH  string `json:"size_h"`
	AlignH string `json:"align_h"`
	AlignV string `json:"align_v"`
}

type Behavior struct {
	Trigger Trigger
	Action  Action
}

type Trigger struct {
	Type   string
	Widget string
}

type Action struct {
	Type    string
	Transit string
}

type Launch struct {
	Screen string
}

type Color struct {
	Id    string
	Value string
}

type String struct {
	Lang string
	Defs []Def
}

type Def struct {
	Id    string
	Value string
}

func main() {
	// Parse command
	if len(os.Args) == 1 {
		printUsage()
		os.Exit(ExitCodeError)
	}
	switch os.Args[1] {
	case "gen":
	case "version":
		printVersion()
		os.Exit(ExitCodeSuccess)
	case "help":
		fallthrough
	default:
		printUsage()
		os.Exit(ExitCodeError)
	}

	if len(os.Args) < 3 {
		printUsage()
		os.Exit(ExitCodeError)
	}
	genId := os.Args[2]

	mock := parseConfigs()
	gen(&mock, genId)
}

func printUsage() {
	fmt.Println(`mocker is a mock up framework for mobile apps.

Usage:
	mocker command [options]

Command:
	gen      generate source code (see 'Generator')
	help     show this help
	version  show version of mocker

Generator:
	mocker gen ID

	ID:
		ios  Objective-C code for iOS app
`)
}

func printVersion() {
	fmt.Println("mocker version \"" + Version + "\"")
}

func parseConfigs() (mock Mock) {
	filename := "Mockerfile"
	xmlFile, err := os.Open(filename)
	if err != nil {
		fmt.Println("Error opening file", err)
		return
	}
	defer xmlFile.Close()

	b, _ := ioutil.ReadAll(xmlFile)
	err = json.Unmarshal(b, &mock)
	if err != nil {
		fmt.Println("Error unmarshaling Mockerfile", err)
		return
	}

	return
}

func gen(mock *Mock, genId string) {
	switch genId {
	case "ios":
		genIos(mock)
	case "android":
		genAndroid(mock)
	default:
		fmt.Println("Invalid gen ID")
		printUsage()
		os.Exit(ExitCodeError)
	}
}

func genAndroid(mock *Mock) {
	// TODO
	fmt.Printf("%+v\n", mock)

	outDir := "out"
	srcDir := filepath.Join(outDir, "src")
	mainDir := filepath.Join(srcDir, "main")
	javaDir := filepath.Join(mainDir, "java")
	packageDir := filepath.Join(javaDir, strings.Replace(mock.Meta.Android.Package, ".", string(os.PathSeparator), -1))
	resDir := filepath.Join(mainDir, "res")
	layoutDir := filepath.Join(resDir, "layout")
	valuesDir := filepath.Join(resDir, "values")

	// Generate base file set using android command
	cmd := exec.Command("android", "create", "project",
		"-n", "mock",
		"-v", mock.Meta.Android.GradlePluginVersion,
		"-g",
		"-k", mock.Meta.Android.Package,
		"-a", "DummyActivity",
		"-t", "android-19",
		"-p", outDir)
	err := cmd.Run()
	if err != nil {
		fmt.Printf("Error while generating project")
	}

	// Remove unecessery directories and files
	os.RemoveAll(filepath.Join(srcDir, "androidTest"))
	os.Remove(filepath.Join(packageDir, "DummyActivity.java"))
	os.Remove(filepath.Join(layoutDir, "main.xml"))

	// Generate Manifest
	genAndroidManifest(mock, mainDir)

	// Generate build.gradle
	genAndroidGradle(mock, outDir)

	// Generate Activities
	for i := range mock.Screens {
		screen := mock.Screens[i]
		genAndroidActivity(mock, packageDir, screen)
		genAndroidActivityLayout(mock, layoutDir, screen)
	}

	// Generate resources
	genAndroidStrings(mock, valuesDir)
	genAndroidLocalizedStrings(mock, resDir)
	genAndroidColors(mock, valuesDir)
}

func genIos(mock *Mock) {
	// TODO
	fmt.Printf("%+v\n", mock)
}

func genAndroidManifest(mock *Mock, outDir string) {
	filename := filepath.Join(outDir, "AndroidManifest.xml")
	f := createFile(filename)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="%s" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
`, mock.Meta.Android.Package))

	launcherId := mock.Launch.Screen
	for i := range mock.Screens {
		screen := mock.Screens[i]
		activityId := strings.Title(screen.Id)
		if screen.Id == launcherId {
			// Launcher
			f.WriteString(fmt.Sprintf(`        <activity
            android:label="@string/activity_title_%s"
            android:name=".%sActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
`, screen.Id, activityId))
		} else {
			f.WriteString(fmt.Sprintf(`        <activity
            android:label="@string/activity_title_%s"
            android:name=".%sActivity" />
`, screen.Id, activityId))
		}
	}

	f.WriteString(`    </application>

</manifest>
`)
	f.Close()
}

func genAndroidGradle(mock *Mock, outDir string) {
	filename := filepath.Join(outDir, "build.gradle")
	f := createFile(filename)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:%s'
    }
}
`, mock.Meta.Android.GradlePluginVersion))
	f.WriteString(fmt.Sprintf(`apply plugin: 'com.android.application'

android {
    compileSdkVersion '%s'
    buildToolsVersion '%s'

    defaultConfig {
        applicationId "%s"
        minSdkVersion %d
        targetSdkVersion %d
        versionCode %d
        versionName "%s"
    }

    buildTypes {
        release {
            runProguard false
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }
    }
}
`,
		mock.Meta.Android.CompileSdkVersion,
		mock.Meta.Android.BuildToolsVersion,
		mock.Meta.Android.Package,
		mock.Meta.Android.MinSdkVersion,
		mock.Meta.Android.TargetSdkVersion,
		mock.Meta.Android.VersionCode,
		mock.Meta.Android.VersionName))

	f.Close()
}

func genAndroidActivity(mock *Mock, packageDir string, screen Screen) {
	activityId := strings.Title(screen.Id)
	filename := filepath.Join(packageDir, activityId+"Activity.java")
	f := createFile(filename)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`package %s;

import android.os.Bundle;

public class %sActivity extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_%s);
		init();
	}

	private void init() {
	}

}
`, mock.Meta.Android.Package, activityId, screen.Id))
	f.Close()
}

func genAndroidActivityLayout(mock *Mock, layoutDir string, screen Screen) {
	filename := filepath.Join(layoutDir, "activity_"+screen.Id+".xml")
	f := createFile(filename)
	defer f.Close()
	xmlns := `xmlns:android="http://schemas.android.com/apk/res/android"`
	f.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<LinearLayout %s
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp" >
`, xmlns))

	for i := range screen.Layout.Views {
		view := screen.Layout.Views[i]
		switch view.Type {
		case "button":
			f.WriteString(fmt.Sprintf(`
    <Button
        android:id="@+id/%s"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/%s"
        android:textColor="#FF8800"
        android:textSize="30dp" />
`, view.Id, view.Label))
		default:
		}
	}
	f.WriteString(`</LinearLayout>
`)

	f.Close()
}

func genAndroidStrings(mock *Mock, valuesDir string) {
	filename := filepath.Join(valuesDir, "strings_app.xml")
	f := createFile(filename)
	defer f.Close()

	// App name
	f.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">%s</app_name>
`, mock.Name))

	// Activity title
	for i := range mock.Screens {
		screen := mock.Screens[i]
		f.WriteString(fmt.Sprintf(`    <string name="activity_title_%s">%s</string>
`, screen.Id, screen.Name))
	}

	f.WriteString(`</resources>
`)
	f.Close()
}

func genAndroidLocalizedStrings(mock *Mock, resDir string) {
	for i := range mock.Strings {
		s := mock.Strings[i]
		lang := s.Lang
		suffix := "-" + lang
		if strings.ToLower(lang) == "base" {
			suffix = ""
		}
		valuesDir := filepath.Join(resDir, "values"+suffix)
		os.MkdirAll(valuesDir, 0777)
		filename := filepath.Join(valuesDir, "strings.xml")
		f := createFile(filename)
		defer f.Close()
		f.WriteString(`<?xml version="1.0" encoding="utf-8"?>
<resources>
`)
		for j := range s.Defs {
			def := s.Defs[j]
			f.WriteString(fmt.Sprintf(`    <string name="%s">%s</string>
`, def.Id, def.Value))
		}
		f.WriteString(`</resources>
`)
		f.Close()
	}
}

func genAndroidColors(mock *Mock, valuesDir string) {
	filename := filepath.Join(valuesDir, "colors.xml")
	f := createFile(filename)
	defer f.Close()

	f.WriteString(`<?xml version="1.0" encoding="utf-8"?>
<resources>
`)

	for i := range mock.Colors {
		c := mock.Colors[i]
		f.WriteString(fmt.Sprintf(`    <color name="%s">%s</color>
`, c.Id, c.Value))
	}

	f.WriteString(`</resources>
`)
	f.Close()
}

// Overwrite and create new file
func createFile(filename string) (f *os.File) {
	if fileExists(filename) {
		os.Remove(filename)
	}
	f, _ = os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
	return
}

func fileExists(filename string) bool {
	if _, err := os.Stat(filename); err != nil && os.IsNotExist(err) {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>/*
 * Ferret
 * Copyright (c) 2016 Yieldbot, Inc.
 * For the full copyright and license information, please view the LICENSE.txt file.
 */

// Package github implements AnswerHub provider
package github

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"

	"golang.org/x/net/context"
)

// Register registers the provider
func Register(f func(name string, provider interface{}) error) {
	// Init the provider
	var p = Provider{
		url:        strings.TrimSuffix(os.Getenv("FERRET_GITHUB_URL"), "/"),
		token:      os.Getenv("FERRET_GITHUB_TOKEN"),
		searchUser: os.Getenv("FERRET_GITHUB_SEARCH_USER"),
	}

	// Register the provider
	if err := f("github", &p); err != nil {
		panic(err)
	}
}

// Provider represents the provider
type Provider struct {
	url        string
	token      string
	searchUser string
}

// SearchResult represent the structure of the search result
type SearchResult struct {
	TotalCount        int  `json:"total_count"`
	IncompleteResults bool `json:"incomplete_results"`
	Items             []*SearchResultItems
}

// SearchResultItems represent the structure of the search result items
type SearchResultItems struct {
	Name        string                         `json:"name"`
	Path        string                         `json:"path"`
	HTMLUrl     string                         `json:"html_url"`
	Repository  *SearchResultItemsRepository   `json:"repository"`
	TextMatches []*SearchResultItemTextMatches `json:"text_matches"`
}

// SearchResultItemsRepository represent the structure of the search result items repository
type SearchResultItemsRepository struct {
	Fullname    string `json:"full_name"`
	Description string `json:"description"`
}

// SearchResultItemTextMatches represent the structure of the search result items text matches field
type SearchResultItemTextMatches struct {
	Fragment string `json:"fragment"`
}

// Search makes a search
func (provider *Provider) Search(ctx context.Context, args map[string]interface{}) ([]map[string]interface{}, error) {

	results := []map[string]interface{}{}
	page, ok := args["page"].(int)
	if page < 1 || !ok {
		page = 1
	}
	keyword, ok := args["keyword"].(string)

	var u = fmt.Sprintf("%s/search/code?page=%d&per_page=10&q=%s", provider.url, page, url.QueryEscape(keyword))
	if provider.searchUser != "" {
		u += fmt.Sprintf("+user:%s", url.QueryEscape(provider.searchUser))
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return nil, errors.New("failed to prepare request. Error: " + err.Error())
	}
	if provider.token != "" {
		req.Header.Set("Authorization", "token "+provider.token)
	}
	req.Header.Set("Accept", "application/vnd.github.v3.text-match+json")

	err = DoWithContext(ctx, nil, req, func(res *http.Response, err error) error {

		if err != nil {
			return errors.New("failed to fetch data. Error: " + err.Error())
		} else if res.StatusCode < 200 || res.StatusCode > 299 {
			return errors.New("bad response: " + fmt.Sprintf("%d", res.StatusCode))
		}
		defer res.Body.Close()
		data, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		var sr SearchResult
		if err = json.Unmarshal(data, &sr); err != nil {
			return errors.New("failed to unmarshal JSON data. Error: " + err.Error())
		}
		for _, v := range sr.Items {
			var d string
			if len(v.TextMatches) > 0 {
				for _, tm := range v.TextMatches {
					d = d + tm.Fragment + "..."
				}
			} else {
				d = v.Repository.Description
			}
			d = strings.TrimSpace(strings.TrimSuffix(d, "..."))
			if len(d) > 255 {
				d = d[0:252] + "..."
			}
			ri := map[string]interface{}{
				"Link":        v.HTMLUrl,
				"Title":       fmt.Sprintf("%s/%s", v.Repository.Fullname, strings.TrimPrefix(v.Path, "/")),
				"Description": d,
			}
			results = append(results, ri)
		}

		return nil
	})

	return results, err
}

// DoWithContext makes a HTTP request with the given context
func DoWithContext(ctx context.Context, client *http.Client, req *http.Request, f func(*http.Response, error) error) error {
	tr := &http.Transport{}
	if client == nil {
		client = &http.Client{Transport: tr}
	}
	c := make(chan error, 1)
	go func() {
		c <- f(client.Do(req))
	}()
	select {
	case <-ctx.Done():
		tr.CancelRequest(req)
		<-c
		return ctx.Err()
	case err := <-c:
		return err
	}
}
<commit_msg>Update struct tags<commit_after>/*
 * Ferret
 * Copyright (c) 2016 Yieldbot, Inc.
 * For the full copyright and license information, please view the LICENSE.txt file.
 */

// Package github implements AnswerHub provider
package github

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"

	"golang.org/x/net/context"
)

// Register registers the provider
func Register(f func(name string, provider interface{}) error) {
	// Init the provider
	var p = Provider{
		url:        strings.TrimSuffix(os.Getenv("FERRET_GITHUB_URL"), "/"),
		token:      os.Getenv("FERRET_GITHUB_TOKEN"),
		searchUser: os.Getenv("FERRET_GITHUB_SEARCH_USER"),
	}

	// Register the provider
	if err := f("github", &p); err != nil {
		panic(err)
	}
}

// Provider represents the provider
type Provider struct {
	url        string
	token      string
	searchUser string
}

// SearchResult represent the structure of the search result
type SearchResult struct {
	TotalCount        int                  `json:"total_count"`
	IncompleteResults bool                 `json:"incomplete_results"`
	Items             []*SearchResultItems `json:"items"`
}

// SearchResultItems represent the structure of the search result items
type SearchResultItems struct {
	Name        string                         `json:"name"`
	Path        string                         `json:"path"`
	HTMLUrl     string                         `json:"html_url"`
	Repository  *SearchResultItemsRepository   `json:"repository"`
	TextMatches []*SearchResultItemTextMatches `json:"text_matches"`
}

// SearchResultItemsRepository represent the structure of the search result items repository
type SearchResultItemsRepository struct {
	Fullname    string `json:"full_name"`
	Description string `json:"description"`
}

// SearchResultItemTextMatches represent the structure of the search result items text matches field
type SearchResultItemTextMatches struct {
	Fragment string `json:"fragment"`
}

// Search makes a search
func (provider *Provider) Search(ctx context.Context, args map[string]interface{}) ([]map[string]interface{}, error) {

	results := []map[string]interface{}{}
	page, ok := args["page"].(int)
	if page < 1 || !ok {
		page = 1
	}
	keyword, ok := args["keyword"].(string)

	var u = fmt.Sprintf("%s/search/code?page=%d&per_page=10&q=%s", provider.url, page, url.QueryEscape(keyword))
	if provider.searchUser != "" {
		u += fmt.Sprintf("+user:%s", url.QueryEscape(provider.searchUser))
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return nil, errors.New("failed to prepare request. Error: " + err.Error())
	}
	if provider.token != "" {
		req.Header.Set("Authorization", "token "+provider.token)
	}
	req.Header.Set("Accept", "application/vnd.github.v3.text-match+json")

	err = DoWithContext(ctx, nil, req, func(res *http.Response, err error) error {

		if err != nil {
			return errors.New("failed to fetch data. Error: " + err.Error())
		} else if res.StatusCode < 200 || res.StatusCode > 299 {
			return errors.New("bad response: " + fmt.Sprintf("%d", res.StatusCode))
		}
		defer res.Body.Close()
		data, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		var sr SearchResult
		if err = json.Unmarshal(data, &sr); err != nil {
			return errors.New("failed to unmarshal JSON data. Error: " + err.Error())
		}
		for _, v := range sr.Items {
			var d string
			if len(v.TextMatches) > 0 {
				for _, tm := range v.TextMatches {
					d = d + tm.Fragment + "..."
				}
			} else {
				d = v.Repository.Description
			}
			d = strings.TrimSpace(strings.TrimSuffix(d, "..."))
			if len(d) > 255 {
				d = d[0:252] + "..."
			}
			ri := map[string]interface{}{
				"Link":        v.HTMLUrl,
				"Title":       fmt.Sprintf("%s/%s", v.Repository.Fullname, strings.TrimPrefix(v.Path, "/")),
				"Description": d,
			}
			results = append(results, ri)
		}

		return nil
	})

	return results, err
}

// DoWithContext makes a HTTP request with the given context
func DoWithContext(ctx context.Context, client *http.Client, req *http.Request, f func(*http.Response, error) error) error {
	tr := &http.Transport{}
	if client == nil {
		client = &http.Client{Transport: tr}
	}
	c := make(chan error, 1)
	go func() {
		c <- f(client.Do(req))
	}()
	select {
	case <-ctx.Done():
		tr.CancelRequest(req)
		<-c
		return ctx.Err()
	case err := <-c:
		return err
	}
}
<|endoftext|>


<commit_before>package proxy

import (
	"errors"

	"github.com/fagongzi/gateway/conf"
	"github.com/valyala/fasthttp"
)

var (
	ErrValidationFailure = errors.New("request validation failure")
)

// ValidationFilter validation request
type ValidationFilter struct {
	baseFilter
	config *conf.Conf
	proxy  *Proxy
}

func newValidationFilter(config *conf.Conf, proxy *Proxy) Filter {
	return ValidationFilter{
		config: config,
		proxy:  proxy,
	}
}

// Name return name of this filter
func (v ValidationFilter) Name() string {
	return FilterValidation
}

func (v ValidationFilter) Pre(c *filterContext) (statusCode int, err error) {
	if c.result.Node.Validate(c.outreq) {
		return v.baseFilter.Pre(c)
	}

	return fasthttp.StatusBadRequest, ErrValidationFailure
}
<commit_msg>fix code warn<commit_after>package proxy

import (
	"errors"

	"github.com/fagongzi/gateway/conf"
	"github.com/valyala/fasthttp"
)

var (
	// ErrValidationFailure validation failure
	ErrValidationFailure = errors.New("request validation failure")
)

// ValidationFilter validation request
type ValidationFilter struct {
	baseFilter
	config *conf.Conf
	proxy  *Proxy
}

func newValidationFilter(config *conf.Conf, proxy *Proxy) Filter {
	return ValidationFilter{
		config: config,
		proxy:  proxy,
	}
}

// Name return name of this filter
func (v ValidationFilter) Name() string {
	return FilterValidation
}

// Pre pre filter, before proxy reuqest
func (v ValidationFilter) Pre(c *filterContext) (statusCode int, err error) {
	if c.result.Node.Validate(c.outreq) {
		return v.baseFilter.Pre(c)
	}

	return fasthttp.StatusBadRequest, ErrValidationFailure
}
<|endoftext|>


<commit_before>package impulse

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
)

type rawModule struct {
	MagicString   [4]byte
	SongName      [26]byte
	PHilight      [2]byte
	OrdNum        uint16
	InsNum        uint16
	SmpNum        uint16
	PatNum        uint16
	Cwtv          [2]byte
	Cmwt          [2]byte
	Flags         uint16
	Special       uint16
	GV, MV        uint8
	IS, IT        uint8
	Sep, PWD      uint8
	MsgLgth       uint16
	MessageOffset uint32
	_             uint32
	ChnlPan       [64]byte
	ChnlVol       [64]byte
}

// Module is an Impulse Tracker module.
type Module struct {
	SongName        string // max 26 bytes
	GlobalVolume    uint8  // range 0->128
	MixingVolume    uint8  // range 0->128
	InitialSpeed    uint8
	InitialTempo    uint8
	Separation      uint8 // range 0->128
	PitchWheelDepth uint8
	ChannelPanning  []uint8 // range 0->64
	ChannelVolume   []uint8 // range 0->64
	OrderList       []uint8 // range 0->199, 254, 255
	Samples         []*Sample
}

func moduleFromRaw(raw *rawModule, r io.ReadSeeker) (*Module, error) {
	m := &Module{
		SongName:        string(bytes.Trim(raw.SongName[:], "\x00")),
		GlobalVolume:    raw.GV,
		MixingVolume:    raw.MV,
		InitialSpeed:    raw.IS,
		InitialTempo:    raw.IT,
		Separation:      raw.Sep,
		PitchWheelDepth: raw.PWD,
		ChannelPanning:  make([]uint8, 64),
		ChannelVolume:   make([]uint8, 64),
		OrderList:       make([]uint8, raw.OrdNum),
		Samples:         make([]*Sample, raw.SmpNum),
	}

	for i := range m.ChannelPanning {
		m.ChannelPanning[i] = raw.ChnlPan[i]
	}
	for i := range m.ChannelVolume {
		m.ChannelVolume[i] = raw.ChnlVol[i]
	}
	if _, err := r.Read(m.OrderList); err != nil {
		return nil, err
	}
	for i := range m.Samples {
		var err error
		ptrOffset := 0xc0 + int64(raw.OrdNum+raw.InsNum*4) + int64(i*4)
		if _, err = r.Seek(ptrOffset, 0); err != nil {
			return nil, err
		}
		var smpOffset uint32
		binary.Read(r, binary.LittleEndian, &smpOffset)
		if _, err = r.Seek(int64(smpOffset), 0); err != nil {
			return nil, err
		}
		if m.Samples[i], err = ReadSample(r); err != nil {
			return nil, err
		}
	}

	return m, nil
}

// ReadModule reads a Module in IT format from r.
func ReadModule(r io.ReadSeeker) (*Module, error) {
	raw := new(rawModule)
	if err := binary.Read(r, binary.LittleEndian, raw); err != nil {
		return nil, err
	}
	if string(raw.MagicString[:]) != "IMPM" {
		return nil, errors.New("data is not Impulse Tracker module")
	}
	return moduleFromRaw(raw, r)
}
<commit_msg>Read instruments into module<commit_after>package impulse

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
)

type rawModule struct {
	MagicString   [4]byte
	SongName      [26]byte
	PHilight      [2]byte
	OrdNum        uint16
	InsNum        uint16
	SmpNum        uint16
	PatNum        uint16
	Cwtv          [2]byte
	Cmwt          [2]byte
	Flags         uint16
	Special       uint16
	GV, MV        uint8
	IS, IT        uint8
	Sep, PWD      uint8
	MsgLgth       uint16
	MessageOffset uint32
	_             uint32
	ChnlPan       [64]byte
	ChnlVol       [64]byte
}

// Module is an Impulse Tracker module.
type Module struct {
	SongName        string // max 26 bytes
	GlobalVolume    uint8  // range 0->128
	MixingVolume    uint8  // range 0->128
	InitialSpeed    uint8
	InitialTempo    uint8
	Separation      uint8 // range 0->128
	PitchWheelDepth uint8
	ChannelPanning  []uint8 // range 0->64
	ChannelVolume   []uint8 // range 0->64
	OrderList       []uint8 // range 0->199, 254, 255
	Samples         []*Sample
	Instruments     []*Instrument
}

func moduleFromRaw(raw *rawModule, r io.ReadSeeker) (*Module, error) {
	m := &Module{
		SongName:        string(bytes.Trim(raw.SongName[:], "\x00")),
		GlobalVolume:    raw.GV,
		MixingVolume:    raw.MV,
		InitialSpeed:    raw.IS,
		InitialTempo:    raw.IT,
		Separation:      raw.Sep,
		PitchWheelDepth: raw.PWD,
		ChannelPanning:  make([]uint8, 64),
		ChannelVolume:   make([]uint8, 64),
		OrderList:       make([]uint8, raw.OrdNum),
		Samples:         make([]*Sample, raw.SmpNum),
	}

	for i := range m.ChannelPanning {
		m.ChannelPanning[i] = raw.ChnlPan[i]
	}
	for i := range m.ChannelVolume {
		m.ChannelVolume[i] = raw.ChnlVol[i]
	}
	if _, err := r.Read(m.OrderList); err != nil {
		return nil, err
	}

	for i := range m.Samples {
		var err error
		ptrOffset := 0xc0 + int64(raw.OrdNum+raw.InsNum*4) + int64(i*4)
		if _, err = r.Seek(ptrOffset, 0); err != nil {
			return nil, err
		}
		var smpOffset uint32
		binary.Read(r, binary.LittleEndian, &smpOffset)
		if _, err = r.Seek(int64(smpOffset), 0); err != nil {
			return nil, err
		}
		if m.Samples[i], err = ReadSample(r); err != nil {
			return nil, err
		}
	}
	for i := range m.Instruments {
		var err error
		ptrOffset := 0xc0 + int64(raw.OrdNum) + int64(i*4)
		if _, err = r.Seek(ptrOffset, 0); err != nil {
			return nil, err
		}
		var insOffset uint32
		binary.Read(r, binary.LittleEndian, &insOffset)
		if _, err = r.Seek(int64(insOffset), 0); err != nil {
			return nil, err
		}
		if m.Instruments[i], err = ReadInstrument(r); err != nil {
			return nil, err
		}
	}

	return m, nil
}

// ReadModule reads a Module in IT format from r.
func ReadModule(r io.ReadSeeker) (*Module, error) {
	raw := new(rawModule)
	if err := binary.Read(r, binary.LittleEndian, raw); err != nil {
		return nil, err
	}
	if string(raw.MagicString[:]) != "IMPM" {
		return nil, errors.New("data is not Impulse Tracker module")
	}
	return moduleFromRaw(raw, r)
}
<|endoftext|>


<commit_before>package js

import (
	"context"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat/lib"
	"github.com/loadimpact/speedboat/stats"
	"github.com/robertkrimen/otto"
	"math"
	"net"
	"net/http"
	"strconv"
	"sync"
	"time"
)

const (
	DefaultMaxRedirect = 10
)

var ErrDefaultExport = errors.New("you must export a 'default' function")

const entrypoint = "__$$entrypoint$$__"

type Runner struct {
	Runtime      *Runtime
	DefaultGroup *lib.Group
	Groups       []*lib.Group
	Tests        []*lib.Test

	HTTPTransport *http.Transport

	groupIDCounter int64
	groupsMutex    sync.Mutex
	testIDCounter  int64
	testsMutex     sync.Mutex
}

func NewRunner(runtime *Runtime, exports otto.Value) (*Runner, error) {
	expObj := exports.Object()
	if expObj == nil {
		return nil, ErrDefaultExport
	}

	// Values "remember" which VM they belong to, so to get a callable that works across VM copies,
	// we have to stick it in the global scope, then retrieve it again from the new instance.
	callable, err := expObj.Get("default")
	if err != nil {
		return nil, err
	}
	if !callable.IsFunction() {
		return nil, ErrDefaultExport
	}
	if err := runtime.VM.Set(entrypoint, callable); err != nil {
		return nil, err
	}

	r := &Runner{
		Runtime: runtime,
		HTTPTransport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   10 * time.Second,
				KeepAlive: 60 * time.Second,
				DualStack: true,
			}).DialContext,
			MaxIdleConns:        math.MaxInt32,
			MaxIdleConnsPerHost: math.MaxInt32,
		},
	}
	r.DefaultGroup = lib.NewGroup("", nil, nil)
	r.Groups = []*lib.Group{r.DefaultGroup}

	return r, nil
}

func (r *Runner) NewVU() (lib.VU, error) {
	u := &VU{
		runner: r,
		vm:     r.Runtime.VM.Copy(),
		group:  r.DefaultGroup,
	}

	u.HTTPClient = &http.Client{
		Transport:     r.HTTPTransport,
		CheckRedirect: u.checkRedirect,
	}

	callable, err := u.vm.Get(entrypoint)
	if err != nil {
		return nil, err
	}
	u.callable = callable

	if err := u.vm.Set("__jsapi__", JSAPI{u}); err != nil {
		return nil, err
	}

	return u, nil
}

func (r *Runner) GetGroups() []*lib.Group {
	return r.Groups
}

func (r *Runner) GetTests() []*lib.Test {
	return r.Tests
}

type VU struct {
	ID       int64
	IDString string
	Samples  []stats.Sample

	runner   *Runner
	vm       *otto.Otto
	callable otto.Value

	HTTPClient   *http.Client
	MaxRedirects int

	ctx   context.Context
	group *lib.Group
}

func (u *VU) RunOnce(ctx context.Context) ([]stats.Sample, error) {
	u.MaxRedirects = DefaultMaxRedirect

	u.ctx = ctx
	if _, err := u.callable.Call(otto.UndefinedValue()); err != nil {
		u.ctx = nil
		return nil, err
	}
	u.ctx = nil

	samples := u.Samples
	u.Samples = nil
	return samples, nil
}

func (u *VU) Reconfigure(id int64) error {
	u.ID = id
	u.IDString = strconv.FormatInt(u.ID, 10)
	return nil
}

func (u *VU) checkRedirect(req *http.Request, via []*http.Request) error {
	log.WithFields(log.Fields{
		"from": via[len(via)-1].URL.String(),
		"to":   req.URL.String(),
	}).Debug("-> Redirect")
	if len(via) >= u.MaxRedirects {
		return errors.New(fmt.Sprintf("stopped after %d redirects", u.MaxRedirects))
	}
	return nil
}
<commit_msg>[feat] Horribly inefficient cookie jar<commit_after>package js

import (
	"context"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat/lib"
	"github.com/loadimpact/speedboat/stats"
	"github.com/robertkrimen/otto"
	"math"
	"net"
	"net/http"
	"net/http/cookiejar"
	"strconv"
	"sync"
	"time"
)

const (
	DefaultMaxRedirect = 10
)

var ErrDefaultExport = errors.New("you must export a 'default' function")

const entrypoint = "__$$entrypoint$$__"

type Runner struct {
	Runtime      *Runtime
	DefaultGroup *lib.Group
	Groups       []*lib.Group
	Tests        []*lib.Test

	HTTPTransport *http.Transport

	groupIDCounter int64
	groupsMutex    sync.Mutex
	testIDCounter  int64
	testsMutex     sync.Mutex
}

func NewRunner(runtime *Runtime, exports otto.Value) (*Runner, error) {
	expObj := exports.Object()
	if expObj == nil {
		return nil, ErrDefaultExport
	}

	// Values "remember" which VM they belong to, so to get a callable that works across VM copies,
	// we have to stick it in the global scope, then retrieve it again from the new instance.
	callable, err := expObj.Get("default")
	if err != nil {
		return nil, err
	}
	if !callable.IsFunction() {
		return nil, ErrDefaultExport
	}
	if err := runtime.VM.Set(entrypoint, callable); err != nil {
		return nil, err
	}

	r := &Runner{
		Runtime: runtime,
		HTTPTransport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   10 * time.Second,
				KeepAlive: 60 * time.Second,
				DualStack: true,
			}).DialContext,
			MaxIdleConns:        math.MaxInt32,
			MaxIdleConnsPerHost: math.MaxInt32,
		},
	}
	r.DefaultGroup = lib.NewGroup("", nil, nil)
	r.Groups = []*lib.Group{r.DefaultGroup}

	return r, nil
}

func (r *Runner) NewVU() (lib.VU, error) {
	u := &VU{
		runner: r,
		vm:     r.Runtime.VM.Copy(),
		group:  r.DefaultGroup,
	}

	u.HTTPClient = &http.Client{
		Transport:     r.HTTPTransport,
		CheckRedirect: u.checkRedirect,
	}

	callable, err := u.vm.Get(entrypoint)
	if err != nil {
		return nil, err
	}
	u.callable = callable

	if err := u.vm.Set("__jsapi__", JSAPI{u}); err != nil {
		return nil, err
	}

	return u, nil
}

func (r *Runner) GetGroups() []*lib.Group {
	return r.Groups
}

func (r *Runner) GetTests() []*lib.Test {
	return r.Tests
}

type VU struct {
	ID       int64
	IDString string
	Samples  []stats.Sample

	runner   *Runner
	vm       *otto.Otto
	callable otto.Value

	HTTPClient   *http.Client
	MaxRedirects int

	ctx   context.Context
	group *lib.Group
}

func (u *VU) RunOnce(ctx context.Context) ([]stats.Sample, error) {
	u.MaxRedirects = DefaultMaxRedirect

	// TODO: Stop reallocating this on every VU iteration!!
	jarOptions := cookiejar.Options{}
	jar, err := cookiejar.New(&jarOptions)
	if err != nil {
		return nil, err
	}
	u.HTTPClient.Jar = jar

	u.ctx = ctx
	if _, err := u.callable.Call(otto.UndefinedValue()); err != nil {
		u.ctx = nil
		return nil, err
	}
	u.ctx = nil

	samples := u.Samples
	u.Samples = nil
	return samples, nil
}

func (u *VU) Reconfigure(id int64) error {
	u.ID = id
	u.IDString = strconv.FormatInt(u.ID, 10)
	return nil
}

func (u *VU) checkRedirect(req *http.Request, via []*http.Request) error {
	log.WithFields(log.Fields{
		"from": via[len(via)-1].URL.String(),
		"to":   req.URL.String(),
	}).Debug("-> Redirect")
	if len(via) >= u.MaxRedirects {
		return errors.New(fmt.Sprintf("stopped after %d redirects", u.MaxRedirects))
	}
	return nil
}
<|endoftext|>