<commit_before>package testutil

import (
	"context"
	"database/sql"
	"fmt"
	"os"
	"reflect"
	"testing"

	"github.com/jackc/pgx"
	"github.com/jackc/pgx/pgtype"
	_ "github.com/jackc/pgx/stdlib"
	_ "github.com/lib/pq"
)

func MustConnectDatabaseSQL(t testing.TB, driverName string) *sql.DB {
	var sqlDriverName string
	switch driverName {
	case "github.com/lib/pq":
		sqlDriverName = "postgres"
	case "github.com/jackc/pgx/stdlib":
		sqlDriverName = "pgx"
	default:
		t.Fatalf("Unknown driver %v", driverName)
	}

	db, err := sql.Open(sqlDriverName, os.Getenv("PGX_TEST_DATABASE"))
	if err != nil {
		t.Fatal(err)
	}

	return db
}

func MustConnectPgx(t testing.TB) *pgx.Conn {
	conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
	if err != nil {
		t.Fatal(err)
	}

	return conn
}

func MustClose(t testing.TB, conn interface {
	Close() error
}) {
	err := conn.Close()
	if err != nil {
		t.Fatal(err)
	}
}

func MustCloseContext(t testing.TB, conn interface {
	Close(context.Context) error
}) {
	err := conn.Close(context.Background())
	if err != nil {
		t.Fatal(err)
	}
}

type forceTextEncoder struct {
	e pgtype.TextEncoder
}

func (f forceTextEncoder) EncodeText(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
	return f.e.EncodeText(ci, buf)
}

type forceBinaryEncoder struct {
	e pgtype.BinaryEncoder
}

func (f forceBinaryEncoder) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
	return f.e.EncodeBinary(ci, buf)
}

func ForceEncoder(e interface{}, formatCode int16) interface{} {
	switch formatCode {
	case pgx.TextFormatCode:
		if e, ok := e.(pgtype.TextEncoder); ok {
			return forceTextEncoder{e: e}
		}
	case pgx.BinaryFormatCode:
		if e, ok := e.(pgtype.BinaryEncoder); ok {
			return forceBinaryEncoder{e: e.(pgtype.BinaryEncoder)}
		}
	}
	return nil
}

func TestSuccessfulTranscode(t testing.TB, pgTypeName string, values []interface{}) {
	TestSuccessfulTranscodeEqFunc(t, pgTypeName, values, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
	}
}

func TestPgxSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustCloseContext(t, conn)

	ps, err := conn.Prepare("test", fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, v := range values {
		for _, fc := range formats {
			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			vEncoder := ForceEncoder(v, fc.formatCode)
			if vEncoder == nil {
				t.Logf("Skipping: %#v does not implement %v", v, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := v
			refVal := reflect.ValueOf(v)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err := conn.QueryRow(context.Background(), "test", ForceEncoder(v, fc.formatCode)).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustCloseContext(t, conn)

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := conn.QueryRow(
			context.Background(),
			fmt.Sprintf("select ($1)::%s", pgTypeName),
			&pgx.QueryExOptions{SimpleProtocol: true},
			v,
		).Scan(result.Interface())
		if err != nil {
			t.Errorf("Simple protocol %d: %v", i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("Simple protocol %d: expected %v, got %v", i, derefV, result.Elem().Interface())
		}
	}
}

func TestDatabaseSQLSuccessfulTranscodeEqFunc(t testing.TB, driverName, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	ps, err := conn.Prepare(fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := ps.QueryRow(v).Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}

type NormalizeTest struct {
	SQL   string
	Value interface{}
}

func TestSuccessfulNormalize(t testing.TB, tests []NormalizeTest) {
	TestSuccessfulNormalizeEqFunc(t, tests, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulNormalizeEqFunc(t, tests, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulNormalizeEqFunc(t, driverName, tests, eqFunc)
	}
}

func TestPgxSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustCloseContext(t, conn)

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, tt := range tests {
		for _, fc := range formats {
			psName := fmt.Sprintf("test%d", i)
			ps, err := conn.Prepare(psName, tt.SQL)
			if err != nil {
				t.Fatal(err)
			}

			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			if ForceEncoder(tt.Value, fc.formatCode) == nil {
				t.Logf("Skipping: %#v does not implement %v", tt.Value, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := tt.Value
			refVal := reflect.ValueOf(tt.Value)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err = conn.QueryRow(context.Background(), psName).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestDatabaseSQLSuccessfulNormalizeEqFunc(t testing.TB, driverName string, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	for i, tt := range tests {
		ps, err := conn.Prepare(tt.SQL)
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		// Derefence value if it is a pointer
		derefV := tt.Value
		refVal := reflect.ValueOf(tt.Value)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err = ps.QueryRow().Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}
<commit_msg>Fix encode empty value<commit_after>package testutil

import (
	"context"
	"database/sql"
	"fmt"
	"os"
	"reflect"
	"testing"

	"github.com/jackc/pgx"
	"github.com/jackc/pgx/pgtype"
	_ "github.com/jackc/pgx/stdlib"
	_ "github.com/lib/pq"
)

func MustConnectDatabaseSQL(t testing.TB, driverName string) *sql.DB {
	var sqlDriverName string
	switch driverName {
	case "github.com/lib/pq":
		sqlDriverName = "postgres"
	case "github.com/jackc/pgx/stdlib":
		sqlDriverName = "pgx"
	default:
		t.Fatalf("Unknown driver %v", driverName)
	}

	db, err := sql.Open(sqlDriverName, os.Getenv("PGX_TEST_DATABASE"))
	if err != nil {
		t.Fatal(err)
	}

	return db
}

func MustConnectPgx(t testing.TB) *pgx.Conn {
	conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
	if err != nil {
		t.Fatal(err)
	}

	return conn
}

func MustClose(t testing.TB, conn interface {
	Close() error
}) {
	err := conn.Close()
	if err != nil {
		t.Fatal(err)
	}
}

func MustCloseContext(t testing.TB, conn interface {
	Close(context.Context) error
}) {
	err := conn.Close(context.Background())
	if err != nil {
		t.Fatal(err)
	}
}

type forceTextEncoder struct {
	e pgtype.TextEncoder
}

func (f forceTextEncoder) EncodeText(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
	return f.e.EncodeText(ci, buf)
}

type forceBinaryEncoder struct {
	e pgtype.BinaryEncoder
}

func (f forceBinaryEncoder) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
	return f.e.EncodeBinary(ci, buf)
}

func ForceEncoder(e interface{}, formatCode int16) interface{} {
	switch formatCode {
	case pgx.TextFormatCode:
		if e, ok := e.(pgtype.TextEncoder); ok {
			return forceTextEncoder{e: e}
		}
	case pgx.BinaryFormatCode:
		if e, ok := e.(pgtype.BinaryEncoder); ok {
			return forceBinaryEncoder{e: e.(pgtype.BinaryEncoder)}
		}
	}
	return nil
}

func TestSuccessfulTranscode(t testing.TB, pgTypeName string, values []interface{}) {
	TestSuccessfulTranscodeEqFunc(t, pgTypeName, values, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
	}
}

func TestPgxSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustCloseContext(t, conn)

	ps, err := conn.Prepare("test", fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, v := range values {
		for _, fc := range formats {
			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			vEncoder := ForceEncoder(v, fc.formatCode)
			if vEncoder == nil {
				t.Logf("Skipping: %#v does not implement %v", v, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := v
			refVal := reflect.ValueOf(v)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))

			err := conn.QueryRow(context.Background(), "test", vEncoder).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustCloseContext(t, conn)

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := conn.QueryRow(
			context.Background(),
			fmt.Sprintf("select ($1)::%s", pgTypeName),
			&pgx.QueryExOptions{SimpleProtocol: true},
			v,
		).Scan(result.Interface())
		if err != nil {
			t.Errorf("Simple protocol %d: %v", i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("Simple protocol %d: expected %v, got %v", i, derefV, result.Elem().Interface())
		}
	}
}

func TestDatabaseSQLSuccessfulTranscodeEqFunc(t testing.TB, driverName, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	ps, err := conn.Prepare(fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := ps.QueryRow(v).Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}

type NormalizeTest struct {
	SQL   string
	Value interface{}
}

func TestSuccessfulNormalize(t testing.TB, tests []NormalizeTest) {
	TestSuccessfulNormalizeEqFunc(t, tests, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulNormalizeEqFunc(t, tests, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulNormalizeEqFunc(t, driverName, tests, eqFunc)
	}
}

func TestPgxSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustCloseContext(t, conn)

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, tt := range tests {
		for _, fc := range formats {
			psName := fmt.Sprintf("test%d", i)
			ps, err := conn.Prepare(psName, tt.SQL)
			if err != nil {
				t.Fatal(err)
			}

			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			if ForceEncoder(tt.Value, fc.formatCode) == nil {
				t.Logf("Skipping: %#v does not implement %v", tt.Value, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := tt.Value
			refVal := reflect.ValueOf(tt.Value)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err = conn.QueryRow(context.Background(), psName).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestDatabaseSQLSuccessfulNormalizeEqFunc(t testing.TB, driverName string, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	for i, tt := range tests {
		ps, err := conn.Prepare(tt.SQL)
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		// Derefence value if it is a pointer
		derefV := tt.Value
		refVal := reflect.ValueOf(tt.Value)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err = ps.QueryRow().Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}
<|endoftext|>


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

package github

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
)

func TestAdminUsers_Create(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users", func(w http.ResponseWriter, r *http.Request) {
		v := new(createUserRequest)
		json.NewDecoder(r.Body).Decode(v)

		testMethod(t, r, "POST")
		want := &createUserRequest{Login: String("github"), Email: String("email@domain.com")}
		if !cmp.Equal(v, want) {
			t.Errorf("Request body = %+v, want %+v", v, want)
		}

		fmt.Fprint(w, `{"login":"github","id":1}`)
	})

	ctx := context.Background()
	org, _, err := client.Admin.CreateUser(ctx, "github", "email@domain.com")
	if err != nil {
		t.Errorf("Admin.CreateUser returned error: %v", err)
	}

	want := &User{ID: Int64(1), Login: String("github")}
	if !cmp.Equal(org, want) {
		t.Errorf("Admin.CreateUser returned %+v, want %+v", org, want)
	}

	const methodName = "CreateUser"
	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		got, resp, err := client.Admin.CreateUser(ctx, "github", "email@domain.com")
		if got != nil {
			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
		}
		return resp, err
	})
}

func TestAdminUsers_Delete(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users/github", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "DELETE")
	})

	ctx := context.Background()
	_, err := client.Admin.DeleteUser(ctx, "github")
	if err != nil {
		t.Errorf("Admin.DeleteUser returned error: %v", err)
	}

	const methodName = "DeleteUser"
	testBadOptions(t, methodName, func() (err error) {
		_, err = client.Admin.DeleteUser(ctx, "\n")
		return err
	})

	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		return client.Admin.DeleteUser(ctx, "github")
	})
}

func TestUserImpersonation_Create(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users/github/authorizations", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "POST")
		testBody(t, r, `{"scopes":["repo"]}`+"\n")
		fmt.Fprint(w, `{"id": 1234,
		"url": "https://git.company.com/api/v3/authorizations/1234",
		"app": {
		  "name": "GitHub Site Administrator",
		  "url": "https://docs.github.com/en/free-pro-team@latest/rest/reference/enterprise/users/",
		  "client_id": "1234"
		},
		"token": "1234",
		"hashed_token": "1234",
		"token_last_eight": "1234",
		"note": null,
		"note_url": null,
		"created_at": "2018-01-01T00:00:00Z",
		"updated_at": "2018-01-01T00:00:00Z",
		"scopes": [
		  "repo"
		],
		"fingerprint": null}`)
	})

	opt := &ImpersonateUserOptions{Scopes: []string{"repo"}}
	ctx := context.Background()
	auth, _, err := client.Admin.CreateUserImpersonation(ctx, "github", opt)
	if err != nil {
		t.Errorf("Admin.CreateUserImpersonation returned error: %v", err)
	}

	date := Timestamp{Time: time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}
	want := &UserAuthorization{
		ID:  Int64(1234),
		URL: String("https://git.company.com/api/v3/authorizations/1234"),
		App: &OAuthAPP{
			Name:     String("GitHub Site Administrator"),
			URL:      String("https://docs.github.com/en/free-pro-team@latest/rest/reference/enterprise/users/"),
			ClientID: String("1234"),
		},
		Token:          String("1234"),
		HashedToken:    String("1234"),
		TokenLastEight: String("1234"),
		Note:           nil,
		NoteURL:        nil,
		CreatedAt:      &date,
		UpdatedAt:      &date,
		Scopes:         []string{"repo"},
		Fingerprint:    nil,
	}
	if !cmp.Equal(auth, want) {
		t.Errorf("Admin.CreateUserImpersonation returned %+v, want %+v", auth, want)
	}

	const methodName = "CreateUserImpersonation"
	testBadOptions(t, methodName, func() (err error) {
		_, _, err = client.Admin.CreateUserImpersonation(ctx, "\n", opt)
		return err
	})

	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		got, resp, err := client.Admin.CreateUserImpersonation(ctx, "github", opt)
		if got != nil {
			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
		}
		return resp, err
	})
}

func TestUserImpersonation_Delete(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users/github/authorizations", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "DELETE")
	})

	ctx := context.Background()
	_, err := client.Admin.DeleteUserImpersonation(ctx, "github")
	if err != nil {
		t.Errorf("Admin.DeleteUserImpersonation returned error: %v", err)
	}

	const methodName = "DeleteUserImpersonation"
	testBadOptions(t, methodName, func() (err error) {
		_, err = client.Admin.DeleteUserImpersonation(ctx, "\n")
		return err
	})

	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		return client.Admin.DeleteUserImpersonation(ctx, "github")
	})
}
<commit_msg>Add test cases for JSON resource marshaling (#1923)<commit_after>// Copyright 2019 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
)

func TestAdminUsers_Create(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users", func(w http.ResponseWriter, r *http.Request) {
		v := new(createUserRequest)
		json.NewDecoder(r.Body).Decode(v)

		testMethod(t, r, "POST")
		want := &createUserRequest{Login: String("github"), Email: String("email@domain.com")}
		if !cmp.Equal(v, want) {
			t.Errorf("Request body = %+v, want %+v", v, want)
		}

		fmt.Fprint(w, `{"login":"github","id":1}`)
	})

	ctx := context.Background()
	org, _, err := client.Admin.CreateUser(ctx, "github", "email@domain.com")
	if err != nil {
		t.Errorf("Admin.CreateUser returned error: %v", err)
	}

	want := &User{ID: Int64(1), Login: String("github")}
	if !cmp.Equal(org, want) {
		t.Errorf("Admin.CreateUser returned %+v, want %+v", org, want)
	}

	const methodName = "CreateUser"
	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		got, resp, err := client.Admin.CreateUser(ctx, "github", "email@domain.com")
		if got != nil {
			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
		}
		return resp, err
	})
}

func TestAdminUsers_Delete(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users/github", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "DELETE")
	})

	ctx := context.Background()
	_, err := client.Admin.DeleteUser(ctx, "github")
	if err != nil {
		t.Errorf("Admin.DeleteUser returned error: %v", err)
	}

	const methodName = "DeleteUser"
	testBadOptions(t, methodName, func() (err error) {
		_, err = client.Admin.DeleteUser(ctx, "\n")
		return err
	})

	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		return client.Admin.DeleteUser(ctx, "github")
	})
}

func TestUserImpersonation_Create(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users/github/authorizations", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "POST")
		testBody(t, r, `{"scopes":["repo"]}`+"\n")
		fmt.Fprint(w, `{"id": 1234,
		"url": "https://git.company.com/api/v3/authorizations/1234",
		"app": {
		  "name": "GitHub Site Administrator",
		  "url": "https://docs.github.com/en/free-pro-team@latest/rest/reference/enterprise/users/",
		  "client_id": "1234"
		},
		"token": "1234",
		"hashed_token": "1234",
		"token_last_eight": "1234",
		"note": null,
		"note_url": null,
		"created_at": "2018-01-01T00:00:00Z",
		"updated_at": "2018-01-01T00:00:00Z",
		"scopes": [
		  "repo"
		],
		"fingerprint": null}`)
	})

	opt := &ImpersonateUserOptions{Scopes: []string{"repo"}}
	ctx := context.Background()
	auth, _, err := client.Admin.CreateUserImpersonation(ctx, "github", opt)
	if err != nil {
		t.Errorf("Admin.CreateUserImpersonation returned error: %v", err)
	}

	date := Timestamp{Time: time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}
	want := &UserAuthorization{
		ID:  Int64(1234),
		URL: String("https://git.company.com/api/v3/authorizations/1234"),
		App: &OAuthAPP{
			Name:     String("GitHub Site Administrator"),
			URL:      String("https://docs.github.com/en/free-pro-team@latest/rest/reference/enterprise/users/"),
			ClientID: String("1234"),
		},
		Token:          String("1234"),
		HashedToken:    String("1234"),
		TokenLastEight: String("1234"),
		Note:           nil,
		NoteURL:        nil,
		CreatedAt:      &date,
		UpdatedAt:      &date,
		Scopes:         []string{"repo"},
		Fingerprint:    nil,
	}
	if !cmp.Equal(auth, want) {
		t.Errorf("Admin.CreateUserImpersonation returned %+v, want %+v", auth, want)
	}

	const methodName = "CreateUserImpersonation"
	testBadOptions(t, methodName, func() (err error) {
		_, _, err = client.Admin.CreateUserImpersonation(ctx, "\n", opt)
		return err
	})

	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		got, resp, err := client.Admin.CreateUserImpersonation(ctx, "github", opt)
		if got != nil {
			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
		}
		return resp, err
	})
}

func TestUserImpersonation_Delete(t *testing.T) {
	client, mux, _, teardown := setup()
	defer teardown()

	mux.HandleFunc("/admin/users/github/authorizations", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "DELETE")
	})

	ctx := context.Background()
	_, err := client.Admin.DeleteUserImpersonation(ctx, "github")
	if err != nil {
		t.Errorf("Admin.DeleteUserImpersonation returned error: %v", err)
	}

	const methodName = "DeleteUserImpersonation"
	testBadOptions(t, methodName, func() (err error) {
		_, err = client.Admin.DeleteUserImpersonation(ctx, "\n")
		return err
	})

	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
		return client.Admin.DeleteUserImpersonation(ctx, "github")
	})
}

func TestCreateUserRequest_Marshal(t *testing.T) {
	testJSONMarshal(t, &createUserRequest{}, "{}")

	u := &createUserRequest{
		Login: String("l"),
		Email: String("e"),
	}

	want := `{
		"login": "l",
		"email": "e"
	}`

	testJSONMarshal(t, u, want)
}

func TestImpersonateUserOptions_Marshal(t *testing.T) {
	testJSONMarshal(t, &ImpersonateUserOptions{}, "{}")

	u := &ImpersonateUserOptions{
		Scopes: []string{
			"s",
		},
	}

	want := `{
		"scopes": ["s"]
	}`

	testJSONMarshal(t, u, want)
}

func TestOAuthAPP_Marshal(t *testing.T) {
	testJSONMarshal(t, &OAuthAPP{}, "{}")

	u := &OAuthAPP{
		URL:      String("u"),
		Name:     String("n"),
		ClientID: String("cid"),
	}

	want := `{
		"url": "u",
		"name": "n",
		"client_id": "cid"
	}`

	testJSONMarshal(t, u, want)
}

func TestUserAuthorization_Marshal(t *testing.T) {
	testJSONMarshal(t, &UserAuthorization{}, "{}")

	u := &UserAuthorization{
		ID:  Int64(1),
		URL: String("u"),
		Scopes: []string{
			"s",
		},
		Token:          String("t"),
		TokenLastEight: String("tle"),
		HashedToken:    String("ht"),
		App: &OAuthAPP{
			URL:      String("u"),
			Name:     String("n"),
			ClientID: String("cid"),
		},
		Note:        String("n"),
		NoteURL:     String("nu"),
		UpdatedAt:   &Timestamp{referenceTime},
		CreatedAt:   &Timestamp{referenceTime},
		Fingerprint: String("f"),
	}

	want := `{
		"id": 1,
		"url": "u",
		"scopes": ["s"],
		"token": "t",
		"token_last_eight": "tle",
		"hashed_token": "ht",
		"app": {
			"url": "u",
			"name": "n",
			"client_id": "cid"
		},
		"note": "n",
		"note_url": "nu",
		"updated_at": ` + referenceTimeStr + `,
		"created_at": ` + referenceTimeStr + `,
		"fingerprint": "f"
	}`

	testJSONMarshal(t, u, want)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	log "github.com/gonet2/libs/nsq-logger"
	. "github.com/gonet2/libs/services/proto"
)

import (
	. "types"
)

var (
	ERROR_NOT_AUTHORIZED = errors.New("User not authorized")
)

// forward messages to game server
func forward(sess *Session, p []byte) error {
	frame := &Game_Frame{
		Type:    Game_Message,
		Message: p,
	}

	if sess.Flag&SESS_AUTHORIZED != 0 {
		// send the packet
		if err := sess.Stream.Send(frame); err != nil {
			log.Error(err)
			return err
		}
		return nil
	}
	return ERROR_NOT_AUTHORIZED
}
<commit_msg>import service<commit_after>package main

import (
	"errors"
	log "github.com/gonet2/libs/nsq-logger"
	_ "github.com/gonet2/libs/services"
	. "github.com/gonet2/libs/services/proto"
)

import (
	. "types"
)

var (
	ERROR_NOT_AUTHORIZED = errors.New("User not authorized")
)

// forward messages to game server
func forward(sess *Session, p []byte) error {
	frame := &Game_Frame{
		Type:    Game_Message,
		Message: p,
	}

	if sess.Flag&SESS_AUTHORIZED != 0 {
		// send the packet
		if err := sess.Stream.Send(frame); err != nil {
			log.Error(err)
			return err
		}
		return nil
	}
	return ERROR_NOT_AUTHORIZED
}
<|endoftext|>


<commit_before><commit_msg>Fix bug - not throwing paste_ in output<commit_after><|endoftext|>


<commit_before>package signal

import (
	"fmt"
	"os"
	gosignal "os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"sync/atomic"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
)

// Trap sets up a simplified signal "trap", appropriate for common
// behavior expected from a vanilla unix command-line tool in general
// (and the Docker engine in particular).
//
// * If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated.
// * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is
//   skipped and the process is terminated immediately (allows force quit of stuck daemon)
// * A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit.
// * Ignore SIGPIPE events. These are generated by systemd when journald is restarted while
//   the docker daemon is not restarted and also running under systemd.
//   Fixes https://github.com/docker/docker/issues/19728
//
func Trap(cleanup func()) {
	c := make(chan os.Signal, 1)
	// we will handle INT, TERM, QUIT, SIGPIPE here
	signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE}
	gosignal.Notify(c, signals...)
	go func() {
		interruptCount := uint32(0)
		for sig := range c {
			if sig == syscall.SIGPIPE {
				continue
			}

			go func(sig os.Signal) {
				logrus.Infof("Processing signal '%v'", sig)
				switch sig {
				case os.Interrupt, syscall.SIGTERM:
					if atomic.LoadUint32(&interruptCount) < 3 {
						// Initiate the cleanup only once
						if atomic.AddUint32(&interruptCount, 1) == 1 {
							// Call the provided cleanup handler
							cleanup()
							os.Exit(0)
						} else {
							return
						}
					} else {
						// 3 SIGTERM/INT signals received; force exit without cleanup
						logrus.Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received")
					}
				case syscall.SIGQUIT:
					DumpStacks("")
					logrus.Info("Forcing docker daemon shutdown without cleanup on SIGQUIT")
				}
				//for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal #
				os.Exit(128 + int(sig.(syscall.Signal)))
			}(sig)
		}
	}()
}

const stacksLogNameTemplate = "goroutine-stacks-%s.log"

// DumpStacks appends the runtime stack into file in dir and returns full path
// to that file.
func DumpStacks(dir string) (string, error) {
	var (
		buf       []byte
		stackSize int
	)
	bufferLen := 16384
	for stackSize == len(buf) {
		buf = make([]byte, bufferLen)
		stackSize = runtime.Stack(buf, true)
		bufferLen *= 2
	}
	buf = buf[:stackSize]
	var f *os.File
	if dir != "" {
		path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1)))
		var err error
		f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
		if err != nil {
			return "", errors.Wrap(err, "failed to open file to write the goroutine stacks")
		}
		defer f.Close()
		defer f.Sync()
	} else {
		f = os.Stderr
	}
	if _, err := f.Write(buf); err != nil {
		return "", errors.Wrap(err, "failed to write goroutine stacks")
	}
	return f.Name(), nil
}
<commit_msg>Update logrus to v1.0.1<commit_after>package signal

import (
	"fmt"
	"os"
	gosignal "os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"sync/atomic"
	"syscall"
	"time"

	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// Trap sets up a simplified signal "trap", appropriate for common
// behavior expected from a vanilla unix command-line tool in general
// (and the Docker engine in particular).
//
// * If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated.
// * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is
//   skipped and the process is terminated immediately (allows force quit of stuck daemon)
// * A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit.
// * Ignore SIGPIPE events. These are generated by systemd when journald is restarted while
//   the docker daemon is not restarted and also running under systemd.
//   Fixes https://github.com/docker/docker/issues/19728
//
func Trap(cleanup func()) {
	c := make(chan os.Signal, 1)
	// we will handle INT, TERM, QUIT, SIGPIPE here
	signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE}
	gosignal.Notify(c, signals...)
	go func() {
		interruptCount := uint32(0)
		for sig := range c {
			if sig == syscall.SIGPIPE {
				continue
			}

			go func(sig os.Signal) {
				logrus.Infof("Processing signal '%v'", sig)
				switch sig {
				case os.Interrupt, syscall.SIGTERM:
					if atomic.LoadUint32(&interruptCount) < 3 {
						// Initiate the cleanup only once
						if atomic.AddUint32(&interruptCount, 1) == 1 {
							// Call the provided cleanup handler
							cleanup()
							os.Exit(0)
						} else {
							return
						}
					} else {
						// 3 SIGTERM/INT signals received; force exit without cleanup
						logrus.Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received")
					}
				case syscall.SIGQUIT:
					DumpStacks("")
					logrus.Info("Forcing docker daemon shutdown without cleanup on SIGQUIT")
				}
				//for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal #
				os.Exit(128 + int(sig.(syscall.Signal)))
			}(sig)
		}
	}()
}

const stacksLogNameTemplate = "goroutine-stacks-%s.log"

// DumpStacks appends the runtime stack into file in dir and returns full path
// to that file.
func DumpStacks(dir string) (string, error) {
	var (
		buf       []byte
		stackSize int
	)
	bufferLen := 16384
	for stackSize == len(buf) {
		buf = make([]byte, bufferLen)
		stackSize = runtime.Stack(buf, true)
		bufferLen *= 2
	}
	buf = buf[:stackSize]
	var f *os.File
	if dir != "" {
		path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1)))
		var err error
		f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
		if err != nil {
			return "", errors.Wrap(err, "failed to open file to write the goroutine stacks")
		}
		defer f.Close()
		defer f.Sync()
	} else {
		f = os.Stderr
	}
	if _, err := f.Write(buf); err != nil {
		return "", errors.Wrap(err, "failed to write goroutine stacks")
	}
	return f.Name(), nil
}
<|endoftext|>


<commit_before>// leisp
// Copyright 2016 Zongmin Lei <leizongmin@gmail.com>. All rights reserved.
// Under the MIT License

package interpreter

import (
	"fmt"
	"leisp/types"
	"os"
)

func builtinTypeOf(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	if len(args) != 1 {
		return types.NewErrorMessageAtom(`invalid arguments number for type-of`)
	}
	a := args[0]
	if a.IsError() {
		return types.NewAtom(types.NewStringValue("error"))
	}
	return types.NewAtom(types.NewStringValue(a.Value.GetType()))
}

func builtinDefvar(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	if len(args) != 2 {
		return types.NewErrorMessageAtom(`invalid arguments number for def`)
	}
	n := args[0]
	v := args[1]
	if !n.IsValue() {
		return n
	}
	if !v.IsValue() {
		return v
	}
	sym, ok := n.Value.(*types.SymbolValue)
	if !ok {
		return types.NewErrorAtom(fmt.Errorf("invalid type of variable name: %s", n.ToString()))
	}

	if err := s.Declare(sym.ToString(), v.Value); err != nil {
		return types.NewErrorAtom(err)
	}

	return v
}

func builtinNewScope(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	argc := len(args)
	if argc > 1 {
		return types.NewErrorMessageAtom(`invalid arguments number for new-scope`)
	}
	if argc == 0 {
		return types.NewAtom(types.NewScopeValue(types.NewScope(nil)))
	}
	a, err := getAtomFinalValue(s, args[0])
	if err != nil {
		return types.NewErrorAtom(err)
	}
	if s2, ok := a.(*types.ScopeValue); ok {
		return types.NewAtom(types.NewScopeValue(types.NewScope(s2.Value)))
	}
	return types.NewErrorAtom(fmt.Errorf("%s is not a scope: %s", a.GetType(), a.ToString()))
}

func builtinLambda(s *types.Scope, list []*types.AST) *types.Atom {

	argc := len(list)
	if argc < 2 {
		return types.NewErrorMessageAtom("invalid arguments number for lambda")
	}

	first := list[0]
	if !first.IsList() {
		return types.NewErrorAtom(fmt.Errorf("lambda arguments must be a list: %s", first.ToString()))
	}

	names := make([]string, len(first.Children))
	for i, v := range first.Children {
		if !v.IsValue() {
			return types.NewErrorAtom(fmt.Errorf("lambda argument must be symbol: %s", v.ToString()))
		}
		if n, ok := v.Value.(*types.SymbolValue); ok {
			names[i] = n.Value
		} else {
			return types.NewErrorAtom(fmt.Errorf("invalid arguments type: %s", v.ToString()))
		}
	}

	body := make([]*types.ExpressionValue, argc-1)
	for i, v := range list[1:] {
		body[i] = types.NewExpressionValue(v)
	}
	lam := types.NewLambdaValue(types.NewLambdaValueInfo(s, names, body, "no source"))

	return types.NewAtom(lam)
}

func builtinDefn(s *types.Scope, list []*types.AST) *types.Atom {

	argc := len(list)
	if argc < 3 {
		return types.NewErrorMessageAtom("invalid arguments number for defn")
	}

	first := list[0]
	if !first.IsValue() {
		return types.NewErrorAtom(fmt.Errorf("function name must be symbol: %s", first.ToString()))
	}
	name, ok := first.Value.(*types.SymbolValue)
	if !ok {
		return types.NewErrorAtom(fmt.Errorf("function name must be symbol: %s", name.ToString()))
	}

	lam := builtinLambda(s, list[1:])
	if lam.IsError() {
		return lam
	}

	if err := s.Declare(name.Value, lam.Value); err != nil {
		return types.NewErrorAtom(err)
	}

	return lam
}

func builtinExit(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	var exitCode int = 0
	if len(args) > 0 {
		first := args[0]
		code, ok := first.Value.(*types.IntegerValue)
		if !ok {
			return types.NewErrorAtom(fmt.Errorf("exit code must be type integer: actually type is %s", first.Value.GetType()))
		}
		exitCode = int(code.Value)
	}
	os.Exit(exitCode)

	return types.NewEmptyAtom()
}

func builtinValue(s *types.Scope, list []*types.AST) *types.Atom {

	if len(list) != 1 {
		return types.NewErrorMessageAtom("invalid arguments number for value")
	}

	first := list[0]
	if first.IsValue() {
		if sym, ok := first.Value.(*types.SymbolValue); ok {
			val, err := s.Get(sym.Value)
			if err != nil {
				return types.NewErrorAtom(err)
			}
			return types.NewAtom(val)
		}
		return types.NewAtom(first.Value)
	}

	return types.NewAtom(types.NewExpressionValue(first))
}

func init() {

	RegisterBuiltinFunction("lambda", builtinLambda)
	RegisterBuiltinFunction("defn", builtinDefn)

	RegisterBuiltinFunction("typeof", builtinTypeOf)
	RegisterBuiltinFunction("defvar", builtinDefvar)
	RegisterBuiltinFunction("value", builtinValue)
	//RegisterBuiltinFunction("value*", builtinValueByName)

	RegisterBuiltinFunction("new-scope", builtinNewScope)
	RegisterBuiltinFunction("exit", builtinExit)

}
<commit_msg>builtin.value*<commit_after>// leisp
// Copyright 2016 Zongmin Lei <leizongmin@gmail.com>. All rights reserved.
// Under the MIT License

package interpreter

import (
	"fmt"
	"leisp/types"
	"os"
)

func builtinTypeOf(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	if len(args) != 1 {
		return types.NewErrorMessageAtom(`invalid arguments number for type-of`)
	}
	a := args[0]
	if a.IsError() {
		return types.NewAtom(types.NewStringValue("error"))
	}
	return types.NewAtom(types.NewStringValue(a.Value.GetType()))
}

func builtinDefvar(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	if len(args) != 2 {
		return types.NewErrorMessageAtom(`invalid arguments number for def`)
	}
	n := args[0]
	v := args[1]
	if !n.IsValue() {
		return n
	}
	if !v.IsValue() {
		return v
	}
	sym, ok := n.Value.(*types.SymbolValue)
	if !ok {
		return types.NewErrorAtom(fmt.Errorf("invalid type of variable name: %s", n.ToString()))
	}

	if err := s.Declare(sym.ToString(), v.Value); err != nil {
		return types.NewErrorAtom(err)
	}

	return v
}

func builtinNewScope(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	argc := len(args)
	if argc > 1 {
		return types.NewErrorMessageAtom(`invalid arguments number for new-scope`)
	}
	if argc == 0 {
		return types.NewAtom(types.NewScopeValue(types.NewScope(nil)))
	}
	a, err := getAtomFinalValue(s, args[0])
	if err != nil {
		return types.NewErrorAtom(err)
	}
	if s2, ok := a.(*types.ScopeValue); ok {
		return types.NewAtom(types.NewScopeValue(types.NewScope(s2.Value)))
	}
	return types.NewErrorAtom(fmt.Errorf("%s is not a scope: %s", a.GetType(), a.ToString()))
}

func builtinLambda(s *types.Scope, list []*types.AST) *types.Atom {

	argc := len(list)
	if argc < 2 {
		return types.NewErrorMessageAtom("invalid arguments number for lambda")
	}

	first := list[0]
	if !first.IsList() {
		return types.NewErrorAtom(fmt.Errorf("lambda arguments must be a list: %s", first.ToString()))
	}

	names := make([]string, len(first.Children))
	for i, v := range first.Children {
		if !v.IsValue() {
			return types.NewErrorAtom(fmt.Errorf("lambda argument must be symbol: %s", v.ToString()))
		}
		if n, ok := v.Value.(*types.SymbolValue); ok {
			names[i] = n.Value
		} else {
			return types.NewErrorAtom(fmt.Errorf("invalid arguments type: %s", v.ToString()))
		}
	}

	body := make([]*types.ExpressionValue, argc-1)
	for i, v := range list[1:] {
		body[i] = types.NewExpressionValue(v)
	}
	lam := types.NewLambdaValue(types.NewLambdaValueInfo(s, names, body, "no source"))

	return types.NewAtom(lam)
}

func builtinDefn(s *types.Scope, list []*types.AST) *types.Atom {

	argc := len(list)
	if argc < 3 {
		return types.NewErrorMessageAtom("invalid arguments number for defn")
	}

	first := list[0]
	if !first.IsValue() {
		return types.NewErrorAtom(fmt.Errorf("function name must be symbol: %s", first.ToString()))
	}
	name, ok := first.Value.(*types.SymbolValue)
	if !ok {
		return types.NewErrorAtom(fmt.Errorf("function name must be symbol: %s", name.ToString()))
	}

	lam := builtinLambda(s, list[1:])
	if lam.IsError() {
		return lam
	}

	if err := s.Declare(name.Value, lam.Value); err != nil {
		return types.NewErrorAtom(err)
	}

	return lam
}

func builtinExit(s *types.Scope, list []*types.AST) *types.Atom {

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	exitCode := 0
	if len(args) > 0 {
		first := args[0]
		code, ok := first.Value.(*types.IntegerValue)
		if !ok {
			return types.NewErrorAtom(fmt.Errorf("exit code must be type integer: actually type is %s", first.Value.GetType()))
		}
		exitCode = int(code.Value)
	}
	os.Exit(exitCode)

	return types.NewEmptyAtom()
}

func builtinValue(s *types.Scope, list []*types.AST) *types.Atom {

	if len(list) != 1 {
		return types.NewErrorMessageAtom("invalid arguments number for value")
	}

	first := list[0]
	if first.IsValue() {
		if sym, ok := first.Value.(*types.SymbolValue); ok {
			val, err := s.Get(sym.Value)
			if err != nil {
				return types.NewErrorAtom(err)
			}
			return types.NewAtom(val)
		}
		return types.NewAtom(first.Value)
	}

	return types.NewAtom(types.NewExpressionValue(first))
}

func builtinValueByName(s *types.Scope, list []*types.AST) *types.Atom {

	if len(list) != 1 {
		return types.NewErrorMessageAtom("invalid arguments number for value")
	}

	args, errAtom := astListToAtomList(s, list)
	if errAtom != nil {
		return errAtom
	}

	first := args[0]
	str, ok := first.Value.(*types.StringValue)
	if !ok {
		return types.NewErrorAtom(fmt.Errorf("invalid arguments type for value*, expected string actually %s", first.Value.GetType()))
	}

	val, err := s.Get(str.Value)
	if err != nil {
		return types.NewErrorAtom(err)
	}

	return types.NewAtom(val)
}

func init() {

	RegisterBuiltinFunction("lambda", builtinLambda)
	RegisterBuiltinFunction("defn", builtinDefn)

	RegisterBuiltinFunction("typeof", builtinTypeOf)
	RegisterBuiltinFunction("defvar", builtinDefvar)
	RegisterBuiltinFunction("value", builtinValue)
	RegisterBuiltinFunction("value*", builtinValueByName)

	RegisterBuiltinFunction("new-scope", builtinNewScope)
	RegisterBuiltinFunction("exit", builtinExit)

}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/coreos/fuze/third_party/github.com/coreos/ignition/config"
	"github.com/coreos/fuze/third_party/github.com/go-yaml/yaml"
)

func stderr(f string, a ...interface{}) {
	out := fmt.Sprintf(f, a...)
	fmt.Fprintln(os.Stderr, strings.TrimSuffix(out, "\n"))
}

func main() {
	flags := struct {
		help    bool
		pretty  bool
		inFile  string
		outFile string
	}{}

	flag.BoolVar(&flags.help, "help", false, "print help and exit")
	flag.BoolVar(&flags.pretty, "pretty", false, "print help and exit")
	flag.StringVar(&flags.inFile, "in-file", "/dev/stdin", "input file (YAML)")
	flag.StringVar(&flags.outFile, "out-file", "/dev/stdout", "output file (JSON)")

	flag.Parse()

	if flags.help {
		flag.Usage()
		return
	}

	cfg := config.Config{}
	dataIn, err := ioutil.ReadFile(flags.inFile)
	if err != nil {
		stderr("Failed to read: %v", err)
		os.Exit(1)
	}

	if err := yaml.Unmarshal(dataIn, &cfg); err != nil {
		stderr("Failed to unmarshal input: %v", err)
		os.Exit(1)
	}

	var dataOut []byte
	if flags.pretty {
		dataOut, err = json.MarshalIndent(&cfg, "", "  ")
		dataOut = append(dataOut, '\n')
	} else {
		dataOut, err = json.Marshal(&cfg)
	}
	if err != nil {
		stderr("Failed to marshal output: %v", err)
		os.Exit(1)
	}

	if err := ioutil.WriteFile(flags.outFile, dataOut, 0640); err != nil {
		stderr("Failed to write: %v", err)
		os.Exit(1)
	}
}
<commit_msg>main: fix description of --pretty flag<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/coreos/fuze/third_party/github.com/coreos/ignition/config"
	"github.com/coreos/fuze/third_party/github.com/go-yaml/yaml"
)

func stderr(f string, a ...interface{}) {
	out := fmt.Sprintf(f, a...)
	fmt.Fprintln(os.Stderr, strings.TrimSuffix(out, "\n"))
}

func main() {
	flags := struct {
		help    bool
		pretty  bool
		inFile  string
		outFile string
	}{}

	flag.BoolVar(&flags.help, "help", false, "print help and exit")
	flag.BoolVar(&flags.pretty, "pretty", false, "indent the output file")
	flag.StringVar(&flags.inFile, "in-file", "/dev/stdin", "input file (YAML)")
	flag.StringVar(&flags.outFile, "out-file", "/dev/stdout", "output file (JSON)")

	flag.Parse()

	if flags.help {
		flag.Usage()
		return
	}

	cfg := config.Config{}
	dataIn, err := ioutil.ReadFile(flags.inFile)
	if err != nil {
		stderr("Failed to read: %v", err)
		os.Exit(1)
	}

	if err := yaml.Unmarshal(dataIn, &cfg); err != nil {
		stderr("Failed to unmarshal input: %v", err)
		os.Exit(1)
	}

	var dataOut []byte
	if flags.pretty {
		dataOut, err = json.MarshalIndent(&cfg, "", "  ")
		dataOut = append(dataOut, '\n')
	} else {
		dataOut, err = json.Marshal(&cfg)
	}
	if err != nil {
		stderr("Failed to marshal output: %v", err)
		os.Exit(1)
	}

	if err := ioutil.WriteFile(flags.outFile, dataOut, 0640); err != nil {
		stderr("Failed to write: %v", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

const SEP = string(os.PathSeparator)

// Reading files requires checking most calls for errors.
// This helper will streamline our error checks below.
func check(e error) {
	if e != nil {
		panic(e)

	}
}

//Converts date into a more convient format
func convertDate(date *string) {

	const shortForm = "02-Jan-2006"
	t, _ := time.Parse(shortForm, *date)
	timeString := t.String()
	*date = strings.Split(timeString, " ")[0]

}

//Copy files

func cp(src, dst string) error {
	s, err := os.Open(src)
	if err != nil {
		return err
	}
	// no need to check errors on read only file, we already got everything
	// we need from the filesystem, so nothing can go wrong now.
	defer s.Close()
	d, err := os.Create(dst)
	if err != nil {
		return err
	}
	if _, err := io.Copy(d, s); err != nil {
		d.Close()
		return err
	}
	return d.Close()
}

type FCSFile struct {
	version  string
	txtStart int
	txtEnd   int
	txtDict  map[string]string
	f        *os.File
}

func (self *FCSFile) InitFCS(path string) {

	//Open the binary FCS file for parsing by
	//using byte offsets.
	f, err := os.Open(path)
	self.f = f
	self.readTextSegment(f) //Populates txtDict with paramters from TEXT segment.
	check(err)
	defer f.Close()

}

//Reads the TEXT segment of the FCS binary and creates
//a dictionary map of the key-value pairs in that
//segment
func (self *FCSFile) readTextSegment(f *os.File) {

	//Offsets based on FCS specs
	self.version = self.readBytes(f, 6, 0)
	tmp := self.readBytes(f, 8, 10)
	self.txtStart, _ = strconv.Atoi(tmp)
	tmp = self.readBytes(f, 8, 18)
	self.txtEnd, _ = strconv.Atoi(tmp)

	//Size of the TEXT segment in the FCS file
	txtSize := self.txtEnd - self.txtStart

	//Stores the content of the TEXT Segment after reading
	txtContent := self.readBytes(f, int64(txtSize), int64(self.txtStart))

	//Data from TEXT segment contained in continous array
	pairs := strings.Split(txtContent, string(12))

	self.txtDict = map[string]string{}

	//Construct a dictionary of parameters and their values
	for i := 1; i < len(pairs); i = i + 2 {

		x, y := pairs[i-1], pairs[i]
		self.cleanString(&x, true)  //Take away any $ or spaces from keys
		self.cleanString(&y, false) //Trims spaces from values
		self.txtDict[x] = y

	}

}

//Removes $ (replaced with "") and spaces from string (replaced with "_") for
//only keys (key == true). All strings are trimed
func (self *FCSFile) cleanString(s *string, key bool) {

	if key == true {
		*s = strings.Replace(*s, "$", "", -1)
		*s = strings.Replace(*s, " ", "_", -1)
	}

	*s = strings.TrimSpace(*s) //Trims whitespace

}

//Reads a particular size of bytes (byteSize) starting at a certain part of the file (f)
// (offset).  Returns a cleaned string value.
func (self *FCSFile) readBytes(f *os.File, byteSize int64, offset int64) string {

	readBytes := make([]byte, byteSize)
	f.ReadAt(readBytes, offset)
	byteValue := strings.TrimSpace(string(readBytes)) //Bytes into string conversion

	return byteValue

}

/*****************************************************************************
**   This is the END of the FCSFile defintion and methods.					**
******************************************************************************/

type FCSInfo struct {
	oldFN    string //Numeric file names ex. 10203030202302.fcs
	newFN    string //New Filename ex. EXP_Name_
	expName  string //Name is experiment as read from TEXT segment of FCS
	expDate  string //Date of experiment as read from TEXT segment of FCS
	expSrc   string //Specimen name as read from TEXT segment of FCS
	expTube  string //Experimental Tube
	expUser  string //Export username (person who conducted the experiment)
	filePath string //Where the file should be located
}

func (self *FCSInfo) InitFCSInfo(fcs *FCSFile) {

	self.expName = fcs.txtDict["EXPERIMENT_NAME"]
	self.expTube = fcs.txtDict["TUBE_NAME"]
	self.oldFN = fcs.f.Name()
	self.expSrc = fcs.txtDict["SRC"]
	self.expUser = fcs.txtDict["EXPORT_USER_NAME"]

	self.expDate = fcs.txtDict["DATE"]
	convertDate(&self.expDate) //Coverts date to a better string format

	self.newFN = self.expName + "_" + self.expSrc + "_" + self.expTube + ".fcs"
	self.cleanName(&self.newFN, true)

	self.filePath = SEP + self.expUser + SEP + self.expName + SEP + self.expSrc
	self.expName = self.expDate + " " + self.expName

}
func (self *FCSInfo) cleanName(s *string, isFile bool) {

	if isFile == true {
		*s = strings.Replace(*s, "/", "-", -1)
		*s = strings.Replace(*s, "\\", "-", -1)
	}

}

type Path struct {
	srcPath string //Source Path - This is where the BDData file is located
	desPath string //Destination Path - Where the recovered files will be placed
}

func (self *Path) SetPath(src string, des string) {
	self.srcPath = src
	self.desPath = des
}

func (self *Path) GlobIt() []string {
	os.Chdir(self.srcPath)
	f, err := filepath.Glob("*.fcs")

	check(err)

	return f

}

func (self *Path) RenameMove(fcsInfo *FCSInfo) {
	os.MkdirAll(self.desPath+fcsInfo.filePath, 0777)
	cwd, _ := os.Getwd()
	fmt.Println(cp(filepath.Join(cwd, fcsInfo.oldFN), filepath.Join(self.desPath, fcsInfo.filePath, fcsInfo.newFN)))

}

func main() {

	paths := &Path{}
	paths.SetPath("/Users/sivabalanmanivannan/Desktop/BDData", "/Users/sivabalanmanivannan/TempData")
	files := paths.GlobIt()

	newFile := &FCSFile{}
	fileInfo := &FCSInfo{}

	for _, fileName := range files {

		newFile.InitFCS(fileName)
		fileInfo.InitFCSInfo(newFile)
		paths.RenameMove(fileInfo)
	}

}
<commit_msg>Updated<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

const SEP = string(os.PathSeparator)

// Reading files requires checking most calls for errors.
// This helper will streamline our error checks below.
func check(e error) {
	if e != nil {
		panic(e)

	}
}

//Converts date into a more convient format
func convertDate(date *string) {

	const shortForm = "02-Jan-2006"
	t, _ := time.Parse(shortForm, *date)
	timeString := t.String()
	*date = strings.Split(timeString, " ")[0]

}

//Copy files

func cp(src, dst string) error {
	s, err := os.Open(src)
	if err != nil {
		return err
	}
	// no need to check errors on read only file, we already got everything
	// we need from the filesystem, so nothing can go wrong now.
	defer s.Close()
	d, err := os.Create(dst)
	if err != nil {
		return err
	}
	if _, err := io.Copy(d, s); err != nil {
		d.Close()
		return err
	}
	return d.Close()
}

type FCSFile struct {
	version  string
	txtStart int
	txtEnd   int
	txtDict  map[string]string
	f        *os.File
}

func (self *FCSFile) InitFCS(path string) {

	//Open the binary FCS file for parsing by
	//using byte offsets.
	f, err := os.Open(path)
	self.f = f
	self.readTextSegment(f) //Populates txtDict with paramters from TEXT segment.
	check(err)
	defer f.Close()

}

//Reads the TEXT segment of the FCS binary and creates
//a dictionary map of the key-value pairs in that
//segment
func (self *FCSFile) readTextSegment(f *os.File) {

	//Offsets based on FCS specs
	self.version = self.readBytes(f, 6, 0)
	tmp := self.readBytes(f, 8, 10)
	self.txtStart, _ = strconv.Atoi(tmp)
	tmp = self.readBytes(f, 8, 18)
	self.txtEnd, _ = strconv.Atoi(tmp)

	//Size of the TEXT segment in the FCS file
	txtSize := self.txtEnd - self.txtStart

	//Stores the content of the TEXT Segment after reading
	txtContent := self.readBytes(f, int64(txtSize), int64(self.txtStart))

	//Data from TEXT segment contained in continous array
	pairs := strings.Split(txtContent, string(12))

	self.txtDict = map[string]string{}

	//Construct a dictionary of parameters and their values
	for i := 1; i < len(pairs); i = i + 2 {

		x, y := pairs[i-1], pairs[i]
		self.cleanString(&x, true)  //Take away any $ or spaces from keys
		self.cleanString(&y, false) //Trims spaces from values
		self.txtDict[x] = y

	}

}

//Removes $ (replaced with "") and spaces from string (replaced with "_") for
//only keys (key == true). All strings are trimed
func (self *FCSFile) cleanString(s *string, key bool) {

	if key == true {
		*s = strings.Replace(*s, "$", "", -1)
		*s = strings.Replace(*s, " ", "_", -1)
	}

	*s = strings.TrimSpace(*s) //Trims whitespace

}

//Reads a particular size of bytes (byteSize) starting at a certain part of the file (f)
// (offset).  Returns a cleaned string value.
func (self *FCSFile) readBytes(f *os.File, byteSize int64, offset int64) string {

	readBytes := make([]byte, byteSize)
	f.ReadAt(readBytes, offset)
	byteValue := strings.TrimSpace(string(readBytes)) //Bytes into string conversion

	return byteValue

}

/*****************************************************************************
**   This is the END of the FCSFile defintion and methods.					**
******************************************************************************/

type FCSInfo struct {
	oldFN    string //Numeric file names ex. 10203030202302.fcs
	newFN    string //New Filename ex. EXP_Name_
	expName  string //Name is experiment as read from TEXT segment of FCS
	expDate  string //Date of experiment as read from TEXT segment of FCS
	expSrc   string //Specimen name as read from TEXT segment of FCS
	expTube  string //Experimental Tube
	expUser  string //Export username (person who conducted the experiment)
	filePath string //Where the file should be located
}

func (self *FCSInfo) InitFCSInfo(fcs *FCSFile) {

	self.expName = fcs.txtDict["EXPERIMENT_NAME"]
	self.expTube = fcs.txtDict["TUBE_NAME"]
	self.oldFN = fcs.f.Name()
	git self.expSrc = fcs.txtDict["SRC"]
	self.expUser = fcs.txtDict["EXPORT_USER_NAME"]

	self.expDate = fcs.txtDict["DATE"]
	convertDate(&self.expDate) //Coverts date to a better string format

	self.newFN = self.expName + "_" + self.expSrc + "_" + self.expTube + ".fcs"
	self.cleanName(&self.newFN, true)

	self.filePath = SEP + self.expUser + SEP + self.expName + SEP + self.expSrc
	self.expName = self.expDate + " " + self.expName

}
//Cleans file names of "/" and "\" characters that might
//interfer with output.
func (self *FCSInfo) cleanName(s *string, isFile bool) {

	if isFile == true {
		*s = strings.Replace(*s, "/", "-", -1)
		*s = strings.Replace(*s, "\\", "-", -1)
	}

}
/*****************************************************************************
**   This is the END of the FCSInfo defintion and methods.					**
******************************************************************************/
type Path struct {
	srcPath string //Source Path - This is where the BDData file is located
	desPath string //Destination Path - Where the recovered files will be placed
}

//Set the path of the BDData directory and the destiantion  of the recovered files.
func (self *Path) SetPath(src string, des string) {
	self.srcPath = src
	self.desPath = des
}

//Reads the the names of all *.fcs files and puts them in
//a slice and returns the slice.
func (self *Path) GlobIt() []string {
	os.Chdir(self.srcPath)
	f, err := filepath.Glob("*.fcs")

	check(err)

	return f

}
//Copies files and moves them to the desination directory.
func (self *Path) RenameMove(fcsInfo *FCSInfo) {
	os.MkdirAll(self.desPath+fcsInfo.filePath, 0777)
	cwd, _ := os.Getwd()
	fmt.Println(cp(filepath.Join(cwd, fcsInfo.oldFN), filepath.Join(self.desPath, fcsInfo.filePath, fcsInfo.newFN)))

}
/*****************************************************************************
**   This is the END of the Path defintion and methods.					**
******************************************************************************/

func main() {

	paths := &Path{}
	paths.SetPath("/Users/sivabalanmanivannan/Desktop/BDData", "/Users/sivabalanmanivannan/TempData")
	files := paths.GlobIt()

	newFile := &FCSFile{}
	fileInfo := &FCSInfo{}

	for _, fileName := range files {

		newFile.InitFCS(fileName)
		fileInfo.InitFCSInfo(newFile)
		paths.RenameMove(fileInfo)
	}

}
<|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 servenv

import (
	"flag"
	"fmt"
	"runtime"
	"strconv"
	"time"

	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"

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

	"vitess.io/vitess/go/vt/sqlparser"

	"vitess.io/vitess/go/stats"
)

var (
	// MySQLServerVersion is what Vitess will present as it's version during the connection handshake,
	// and as the value to the @@version system variable. If nothing is provided, Vitess will report itself as
	// a specific MySQL version with the vitess version appended to it
	MySQLServerVersion = flag.String("mysql_server_version", "", "MySQL server version to advertise.")

	buildHost             = ""
	buildUser             = ""
	buildTime             = ""
	buildGitRev           = ""
	buildGitBranch        = ""
	jenkinsBuildNumberStr = ""

	// Version registers the command line flag to expose build info.
	Version = flag.Bool("version", false, "print binary version")
)

// AppVersion is the struct to store build info.
var AppVersion versionInfo

type versionInfo struct {
	buildHost          string
	buildUser          string
	buildTime          int64
	buildTimePretty    string
	buildGitRev        string
	buildGitBranch     string
	jenkinsBuildNumber int64
	goVersion          string
	goOS               string
	goArch             string
	version            string
}

func (v *versionInfo) Print() {
	fmt.Println(v)
}

func (v *versionInfo) String() string {
	jenkins := ""
	if v.jenkinsBuildNumber != 0 {
		jenkins = fmt.Sprintf(" (Jenkins build %d)", v.jenkinsBuildNumber)
	}
	return fmt.Sprintf("Version: %s%s (Git revision %s branch '%s') built on %s by %s@%s using %s %s/%s",
		v.version, jenkins, v.buildGitRev, v.buildGitBranch, v.buildTimePretty, v.buildUser, v.buildHost, v.goVersion, v.goOS, v.goArch)
}

func (v *versionInfo) MySQLVersion() string {
	if *MySQLServerVersion != "" {
		return *MySQLServerVersion
	}
	return "5.7.9-vitess-" + v.version
}

func init() {
	t, err := time.Parse(time.UnixDate, buildTime)
	if buildTime != "" && err != nil {
		panic(fmt.Sprintf("Couldn't parse build timestamp %q: %v", buildTime, err))
	}

	jenkinsBuildNumber, err := strconv.ParseInt(jenkinsBuildNumberStr, 10, 64)
	if err != nil {
		jenkinsBuildNumber = 0
	}

	AppVersion = versionInfo{
		buildHost:          buildHost,
		buildUser:          buildUser,
		buildTime:          t.Unix(),
		buildTimePretty:    buildTime,
		buildGitRev:        buildGitRev,
		buildGitBranch:     buildGitBranch,
		jenkinsBuildNumber: jenkinsBuildNumber,
		goVersion:          runtime.Version(),
		goOS:               runtime.GOOS,
		goArch:             runtime.GOARCH,
		version:            versionName,
	}
	var convVersion string
	convVersion, err = convertMySQLVersionToCommentVersion(AppVersion.MySQLVersion())
	if err != nil {
		log.Error(err)
	} else {
		sqlparser.MySQLVersion = convVersion
	}
	stats.NewString("BuildHost").Set(AppVersion.buildHost)
	stats.NewString("BuildUser").Set(AppVersion.buildUser)
	stats.NewGauge("BuildTimestamp", "build timestamp").Set(AppVersion.buildTime)
	stats.NewString("BuildGitRev").Set(AppVersion.buildGitRev)
	stats.NewString("BuildGitBranch").Set(AppVersion.buildGitBranch)
	stats.NewGauge("BuildNumber", "build number").Set(AppVersion.jenkinsBuildNumber)
	stats.NewString("GoVersion").Set(AppVersion.goVersion)
	stats.NewString("GoOS").Set(AppVersion.goOS)
	stats.NewString("GoArch").Set(AppVersion.goArch)

	buildLabels := []string{"BuildHost", "BuildUser", "BuildTimestamp", "BuildGitRev", "BuildGitBranch", "BuildNumber"}
	buildValues := []string{
		AppVersion.buildHost,
		AppVersion.buildUser,
		fmt.Sprintf("%v", AppVersion.buildTime),
		AppVersion.buildGitRev,
		AppVersion.buildGitBranch,
		fmt.Sprintf("%v", AppVersion.jenkinsBuildNumber),
	}
	stats.NewGaugesWithMultiLabels("BuildInformation", "build information exposed via label", buildLabels).Set(buildValues, 1)
}

// convertMySQLVersionToCommentVersion converts the MySQL version into comment version format.
func convertMySQLVersionToCommentVersion(version string) (string, error) {
	var res = make([]int, 3)
	idx := 0
	val := ""
	for _, c := range version {
		if c <= '9' && c >= '0' {
			val += string(c)
		} else if c == '.' {
			v, err := strconv.Atoi(val)
			if err != nil {
				return "", err
			}
			val = ""
			res[idx] = v
			idx++
			if idx == 3 {
				break
			}
		} else {
			break
		}
	}
	if val != "" {
		v, err := strconv.Atoi(val)
		if err != nil {
			return "", err
		}
		res[idx] = v
		idx++
	}
	if idx == 0 {
		return "", vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "MySQL version not correctly setup - %s.", version)
	}

	return fmt.Sprintf("%01d%02d%02d", res[0], res[1], res[2]), nil
}
<commit_msg>make sure flags have been parsed before trying to read them<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 servenv

import (
	"flag"
	"fmt"
	"runtime"
	"strconv"
	"time"

	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"

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

	"vitess.io/vitess/go/vt/sqlparser"

	"vitess.io/vitess/go/stats"
)

var (
	// MySQLServerVersion is what Vitess will present as it's version during the connection handshake,
	// and as the value to the @@version system variable. If nothing is provided, Vitess will report itself as
	// a specific MySQL version with the vitess version appended to it
	MySQLServerVersion = flag.String("mysql_server_version", "", "MySQL server version to advertise.")

	buildHost             = ""
	buildUser             = ""
	buildTime             = ""
	buildGitRev           = ""
	buildGitBranch        = ""
	jenkinsBuildNumberStr = ""

	// Version registers the command line flag to expose build info.
	Version = flag.Bool("version", false, "print binary version")
)

// AppVersion is the struct to store build info.
var AppVersion versionInfo

type versionInfo struct {
	buildHost          string
	buildUser          string
	buildTime          int64
	buildTimePretty    string
	buildGitRev        string
	buildGitBranch     string
	jenkinsBuildNumber int64
	goVersion          string
	goOS               string
	goArch             string
	version            string
}

func (v *versionInfo) Print() {
	fmt.Println(v)
}

func (v *versionInfo) String() string {
	jenkins := ""
	if v.jenkinsBuildNumber != 0 {
		jenkins = fmt.Sprintf(" (Jenkins build %d)", v.jenkinsBuildNumber)
	}
	return fmt.Sprintf("Version: %s%s (Git revision %s branch '%s') built on %s by %s@%s using %s %s/%s",
		v.version, jenkins, v.buildGitRev, v.buildGitBranch, v.buildTimePretty, v.buildUser, v.buildHost, v.goVersion, v.goOS, v.goArch)
}

func (v *versionInfo) MySQLVersion() string {
	if *MySQLServerVersion != "" {
		return *MySQLServerVersion
	}
	return "5.7.9-vitess-" + v.version
}

func init() {
	flag.Parse()
	t, err := time.Parse(time.UnixDate, buildTime)
	if buildTime != "" && err != nil {
		panic(fmt.Sprintf("Couldn't parse build timestamp %q: %v", buildTime, err))
	}

	jenkinsBuildNumber, err := strconv.ParseInt(jenkinsBuildNumberStr, 10, 64)
	if err != nil {
		jenkinsBuildNumber = 0
	}

	AppVersion = versionInfo{
		buildHost:          buildHost,
		buildUser:          buildUser,
		buildTime:          t.Unix(),
		buildTimePretty:    buildTime,
		buildGitRev:        buildGitRev,
		buildGitBranch:     buildGitBranch,
		jenkinsBuildNumber: jenkinsBuildNumber,
		goVersion:          runtime.Version(),
		goOS:               runtime.GOOS,
		goArch:             runtime.GOARCH,
		version:            versionName,
	}
	var convVersion string
	convVersion, err = convertMySQLVersionToCommentVersion(AppVersion.MySQLVersion())
	if err != nil {
		log.Error(err)
	} else {
		sqlparser.MySQLVersion = convVersion
	}
	stats.NewString("BuildHost").Set(AppVersion.buildHost)
	stats.NewString("BuildUser").Set(AppVersion.buildUser)
	stats.NewGauge("BuildTimestamp", "build timestamp").Set(AppVersion.buildTime)
	stats.NewString("BuildGitRev").Set(AppVersion.buildGitRev)
	stats.NewString("BuildGitBranch").Set(AppVersion.buildGitBranch)
	stats.NewGauge("BuildNumber", "build number").Set(AppVersion.jenkinsBuildNumber)
	stats.NewString("GoVersion").Set(AppVersion.goVersion)
	stats.NewString("GoOS").Set(AppVersion.goOS)
	stats.NewString("GoArch").Set(AppVersion.goArch)

	buildLabels := []string{"BuildHost", "BuildUser", "BuildTimestamp", "BuildGitRev", "BuildGitBranch", "BuildNumber"}
	buildValues := []string{
		AppVersion.buildHost,
		AppVersion.buildUser,
		fmt.Sprintf("%v", AppVersion.buildTime),
		AppVersion.buildGitRev,
		AppVersion.buildGitBranch,
		fmt.Sprintf("%v", AppVersion.jenkinsBuildNumber),
	}
	stats.NewGaugesWithMultiLabels("BuildInformation", "build information exposed via label", buildLabels).Set(buildValues, 1)
}

// convertMySQLVersionToCommentVersion converts the MySQL version into comment version format.
func convertMySQLVersionToCommentVersion(version string) (string, error) {
	var res = make([]int, 3)
	idx := 0
	val := ""
	for _, c := range version {
		if c <= '9' && c >= '0' {
			val += string(c)
		} else if c == '.' {
			v, err := strconv.Atoi(val)
			if err != nil {
				return "", err
			}
			val = ""
			res[idx] = v
			idx++
			if idx == 3 {
				break
			}
		} else {
			break
		}
	}
	if val != "" {
		v, err := strconv.Atoi(val)
		if err != nil {
			return "", err
		}
		res[idx] = v
		idx++
	}
	if idx == 0 {
		return "", vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "MySQL version not correctly setup - %s.", version)
	}

	return fmt.Sprintf("%01d%02d%02d", res[0], res[1], res[2]), nil
}
<|endoftext|>


<commit_before>package editor

import (
	"github.com/dcbishop/fileaccessor"
	"github.com/dcbishop/jkl/buffer"
)

// Editor contains buffers and performs actions on them.
type Editor interface {
	OpenFiles(filenames []string)
	OpenFile(filename string)
	AddBuffer(buffer buffer.Buffer) buffer.Buffer
	LastBuffer() buffer.Buffer
	SetCurrentBuffer(buffer buffer.Buffer)
	Buffers() []buffer.Buffer
}

// Jkl is the standard implementation of Editor
type Jkl struct {
	buffers       []buffer.Buffer
	currentBuffer buffer.Buffer
	fa            fileaccessor.FileAccessor
}

// New constructs a new editor
func New(fileaccessor fileaccessor.FileAccessor) Jkl {
	return Jkl{fa: fileaccessor}
}

// OpenFiles opens a list of files into buffers and sets the current buffer to the first of the new buffers.
func (editor *Jkl) OpenFiles(filenames []string) {
	for i, filename := range filenames {
		buffer := editor.openFile(filename)
		buffer = editor.AddBuffer(buffer)

		if i == 0 {
			editor.SetCurrentBuffer(buffer)
		}
	}
}

// openFile reads a file, loads it into a new buffer and adds it to the list of buffers
func (editor *Jkl) openFile(filename string) buffer.Buffer {
	buffer := buffer.New()

	buffer.SetFilename(filename)

	if data, err := editor.fa.ReadFile(filename); err == nil {
		buffer.SetData(data)
	} else {
		buffer.SetData([]byte{})
	}

	return &buffer
}

// OpenFile opens a file and sets it to the current buffer.
func (editor *Jkl) OpenFile(filename string) {
	editor.OpenFiles([]string{filename})
}

// AddBuffer adds a buffer to the list of buffers
func (editor *Jkl) AddBuffer(buffer buffer.Buffer) buffer.Buffer {
	editor.buffers = append(editor.buffers, buffer)
	return editor.LastBuffer()
}

// LastBuffer returns a pointer to the last buffer in the list of buffers
func (editor *Jkl) LastBuffer() buffer.Buffer {
	return editor.buffers[len(editor.buffers)-1]
}

// SetCurrentBuffer sets the currently visible buffer
func (editor *Jkl) SetCurrentBuffer(buffer buffer.Buffer) {
	editor.currentBuffer = buffer
}

// Buffers returns a slice containing the buffers.
func (editor *Jkl) Buffers() []buffer.Buffer {
	return editor.buffers
}
<commit_msg>Add Editor.CurrentBuffer().<commit_after>package editor

import (
	"github.com/dcbishop/fileaccessor"
	"github.com/dcbishop/jkl/buffer"
)

// Editor contains buffers and performs actions on them.
type Editor interface {
	OpenFiles(filenames []string)
	OpenFile(filename string)
	AddBuffer(buffer buffer.Buffer) buffer.Buffer
	LastBuffer() buffer.Buffer
	CurrentBuffer() buffer.Buffer
	SetCurrentBuffer(buffer buffer.Buffer)
	Buffers() []buffer.Buffer
}

// Jkl is the standard implementation of Editor
type Jkl struct {
	buffers       []buffer.Buffer
	currentBuffer buffer.Buffer
	fa            fileaccessor.FileAccessor
}

// New constructs a new editor
func New(fileaccessor fileaccessor.FileAccessor) Jkl {
	return Jkl{fa: fileaccessor}
}

// OpenFiles opens a list of files into buffers and sets the current buffer to the first of the new buffers.
func (editor *Jkl) OpenFiles(filenames []string) {
	for i, filename := range filenames {
		buffer := editor.openFile(filename)
		buffer = editor.AddBuffer(buffer)

		if i == 0 {
			editor.SetCurrentBuffer(buffer)
		}
	}
}

// openFile reads a file, loads it into a new buffer and adds it to the list of buffers
func (editor *Jkl) openFile(filename string) buffer.Buffer {
	buffer := buffer.New()

	buffer.SetFilename(filename)

	if data, err := editor.fa.ReadFile(filename); err == nil {
		buffer.SetData(data)
	} else {
		buffer.SetData([]byte{})
	}

	return &buffer
}

// OpenFile opens a file and sets it to the current buffer.
func (editor *Jkl) OpenFile(filename string) {
	editor.OpenFiles([]string{filename})
}

// AddBuffer adds a buffer to the list of buffers
func (editor *Jkl) AddBuffer(buffer buffer.Buffer) buffer.Buffer {
	editor.buffers = append(editor.buffers, buffer)
	return editor.LastBuffer()
}

// LastBuffer returns a pointer to the last buffer in the list of buffers
func (editor *Jkl) LastBuffer() buffer.Buffer {
	return editor.buffers[len(editor.buffers)-1]
}

// CurrentBuffer returns the current buffer.
func (editor *Jkl) CurrentBuffer() buffer.Buffer {
	return editor.currentBuffer
}

// SetCurrentBuffer sets the currently visible buffer.
func (editor *Jkl) SetCurrentBuffer(buffer buffer.Buffer) {
	editor.currentBuffer = buffer
}

// Buffers returns a slice containing the buffers.
func (editor *Jkl) Buffers() []buffer.Buffer {
	return editor.buffers
}
<|endoftext|>


<commit_before>package simra

import (
	"image/color"
	"runtime"

	"github.com/pankona/gomo-simra/simra/fps"
	"github.com/pankona/gomo-simra/simra/image"
	"github.com/pankona/gomo-simra/simra/internal/peer"
	"github.com/pankona/gomo-simra/simra/simlog"
)

// Simraer represents an interface of simra instance
type Simraer interface {
	// Start needs to call to enable all function belong to simra package.
	Start(driver Driver)
	// SetScene sets a driver as a scene.
	// If a driver is already set, it is replaced with new one.
	SetScene(driver Driver)
	// NewSprite returns an instance of Spriter
	NewSprite() Spriter
	// AddSprite adds a sprite to current scene with empty texture.
	AddSprite(s Spriter)
	// RemoveSprite removes specified sprite from current scene.
	// Removed sprite will be disappeared.
	RemoveSprite(s Spriter)
	// SetDesiredScreenSize configures virtual screen size.
	// This function must be called at least once before calling Start.
	SetDesiredScreenSize(w, h float32)
	// AddTouchListener registers a listener for notifying touch event.
	// Event is notified when "screen" is touched.
	AddTouchListener(listener peer.TouchListener)
	// RemoveTouchListener unregisters a listener for notifying touch event.
	RemoveTouchListener(listener peer.TouchListener)
	// AddCollisionListener add a callback function that is called on
	// collision is detected between c1 and c2.
	AddCollisionListener(c1, c2 Collider, listener CollisionListener)
	// RemoveAllCollisionListener removes all registered listeners
	RemoveAllCollisionListener()
	// NewImageTexture returns a texture instance of image
	NewImageTexture(assetName string, rect image.Rectangle) *Texture
	// NewImageTexture returns a texture instance of text
	NewTextTexture(text string, fontsize float64, fontcolor color.RGBA, rect image.Rectangle) *Texture
}

type collisionMap struct {
	c1       Collider
	c2       Collider
	listener CollisionListener
}

// Simra is a struct that provides API interface of simra
type simra struct {
	driver          Driver
	comap           []*collisionMap
	gl              peer.GLer
	spritecontainer peer.SpriteContainerer
}

// NewSimra returns an instance of Simraer
func NewSimra() Simraer {
	return &simra{
		comap: make([]*collisionMap, 0),
	}
}

func (sim *simra) onUpdate() {
	if sim.driver != nil {
		sim.driver.Drive()
	}
	sim.collisionCheckAndNotify()
	sim.gl.Update(sim.spritecontainer)
}

func (sim *simra) onGomoStart(glc *peer.GLContext) {
	sim.gl.Initialize(glc)
	sim.SetScene(sim.driver)
}

func (sim *simra) onGomoStop() {
	sim.spritecontainer.Initialize(sim.gl)
	sim.gl.Finalize()
}

// Start starts to run gomobile and set specified scene as first driver
func (sim *simra) Start(driver Driver) {
	simlog.FuncIn()

	gl := peer.NewGLPeer()
	sc := peer.GetSpriteContainer()
	sc.Initialize(gl)
	sim.gl = gl
	sim.spritecontainer = sc
	sim.driver = driver
	gomo := peer.GetGomo()
	gomo.Initialize(sim.onGomoStart, sim.onGomoStop, sim.onUpdate)
	gomo.Start()

	simlog.FuncOut()
}

// SetScene sets a driver as a scene.
// If a driver is already set, it is replaced with new one.
func (sim *simra) SetScene(driver Driver) {
	simlog.FuncIn()

	sim.spritecontainer.RemoveSprites()
	sim.gl.Reset()
	sim.spritecontainer.Initialize(sim.gl)
	peer.GetTouchPeer().RemoveAllTouchListeners()
	sim.spritecontainer.RemoveSprites()

	sim.driver = driver
	sim.spritecontainer.Initialize(sim.gl)
	err := sim.spritecontainer.AddSprite(&peer.Sprite{}, nil, fps.Progress)
	if err != nil {
		simlog.Errorf("failed to add sprite. err: %s", err.Error())
		return
	}

	driver.Initialize(sim)

	simlog.FuncOut()
}

// NewSprite returns an instance of Sprite
func (sim *simra) NewSprite() Spriter {
	return &sprite{
		simra:         sim,
		animationSets: map[string]*AnimationSet{},
	}
}

// AddSprite adds a sprite to current scene with empty texture.
func (sim *simra) AddSprite(s Spriter) {
	sp := s.(*sprite)
	err := sim.spritecontainer.AddSprite(&sp.Sprite, nil, nil)
	if err != nil {
		simlog.Errorf("failed to add sprite. err: %s", err.Error())
	}

}

// RemoveSprite removes specified sprite from current scene.
// Removed sprite will be disappeared.
func (sim *simra) RemoveSprite(s Spriter) {
	sp := s.(*sprite)
	sp.texture = nil
	sim.spritecontainer.RemoveSprite(&sp.Sprite)
}

// SetDesiredScreenSize configures virtual screen size.
// This function must be called at least once before calling Start.
func (sim *simra) SetDesiredScreenSize(w, h float32) {
	ss := peer.GetScreenSizePeer()
	ss.SetDesiredScreenSize(w, h)
}

// AddTouchListener registers a listener for notifying touch event.
// Event is notified when "screen" is touched.
func (sim *simra) AddTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().AddTouchListener(listener)
}

// RemoveTouchListener unregisters a listener for notifying touch event.
func (sim *simra) RemoveTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().RemoveTouchListener(listener)
}

// AddCollisionListener add a callback function that is called on
// collision is detected between c1 and c2.
func (sim *simra) AddCollisionListener(c1, c2 Collider, listener CollisionListener) {
	// TODO: exclusiveee control
	simlog.FuncIn()
	sim.comap = append(sim.comap, &collisionMap{c1, c2, listener})
	simlog.FuncOut()
}

func (sim *simra) removeCollisionMap(c *collisionMap) {
	result := []*collisionMap{}

	for _, v := range sim.comap {
		if c.c1 != v.c1 && c.c2 != v.c2 && v != c {
			result = append(result, v)
		}
	}

	sim.comap = result
}

// RemoveAllCollisionListener removes all registered listeners
func (sim *simra) RemoveAllCollisionListener() {
	simlog.FuncIn()
	sim.comap = nil
	simlog.FuncOut()
}

// NewImageTexture allocates a texture from asset image
func (sim *simra) NewImageTexture(assetName string, rect image.Rectangle) *Texture {
	simlog.FuncIn()

	gl := sim.gl
	tex := gl.LoadTexture(assetName, rect.Rectangle)
	t := &Texture{
		simra:   sim,
		texture: gl.NewTexture(tex),
	}
	runtime.SetFinalizer(t, (*Texture).release)

	simlog.FuncOut()
	return t
}

// NewTextTexture allocates a texture from specified text
func (sim *simra) NewTextTexture(text string, fontsize float64, fontcolor color.RGBA, rect image.Rectangle) *Texture {
	simlog.FuncIn()

	gl := sim.gl
	tex := gl.MakeTextureByText(text, fontsize, fontcolor, rect.Rectangle)
	t := &Texture{
		simra:   sim,
		texture: gl.NewTexture(tex),
	}
	runtime.SetFinalizer(t, (*Texture).release)

	simlog.FuncOut()
	return t
}

type point struct {
	x, y float32
}

func (sim *simra) collisionCheckAndNotify() {
	// check collision
	for _, v := range sim.comap {
		// TODO: refactoring around here...
		x1, y1, w1, h1 := v.c1.GetXYWH()
		x2, y2, w2, h2 := v.c2.GetXYWH()
		ps := []*point{
			&point{x1 - w1/2, y1 + h1/2},
			&point{x1 + w1/2, y1 + h1/2},
			&point{x1 - w1/2, y1 - h1/2},
			&point{x1 + w1/2, y1 - h1/2},
		}
		for _, p := range ps {
			if p.x >= (x2-w2/2) && p.x <= (x2+w2/2) &&
				p.y >= (y2-h2/2) && p.y <= (y2+h2/2) {
				v.listener.OnCollision(v.c1, v.c2)
				return
			}
		}
	}
}

// RemoveCollisionListener removes a collision map by specified collider instance.
func (sim *simra) RemoveCollisionListener(c1, c2 Collider) {
	// TODO: exclusive control
	simlog.FuncIn()
	sim.removeCollisionMap(&collisionMap{c1, c2, nil})
	simlog.FuncOut()
}

func (sim *simra) comapLength() int {
	return len(sim.comap)
}
<commit_msg>[#125] add function to set onStop callback function<commit_after>package simra

import (
	"image/color"
	"runtime"

	"github.com/pankona/gomo-simra/simra/fps"
	"github.com/pankona/gomo-simra/simra/image"
	"github.com/pankona/gomo-simra/simra/internal/peer"
	"github.com/pankona/gomo-simra/simra/simlog"
)

// Simraer represents an interface of simra instance
type Simraer interface {
	// Start needs to call to enable all function belong to simra package.
	Start(driver Driver)
	// SetScene sets a driver as a scene.
	// If a driver is already set, it is replaced with new one.
	SetScene(driver Driver)
	// NewSprite returns an instance of Spriter
	NewSprite() Spriter
	// AddSprite adds a sprite to current scene with empty texture.
	AddSprite(s Spriter)
	// RemoveSprite removes specified sprite from current scene.
	// Removed sprite will be disappeared.
	RemoveSprite(s Spriter)
	// SetDesiredScreenSize configures virtual screen size.
	// This function must be called at least once before calling Start.
	SetDesiredScreenSize(w, h float32)
	// AddTouchListener registers a listener for notifying touch event.
	// Event is notified when "screen" is touched.
	AddTouchListener(listener peer.TouchListener)
	// RemoveTouchListener unregisters a listener for notifying touch event.
	RemoveTouchListener(listener peer.TouchListener)
	// AddCollisionListener add a callback function that is called on
	// collision is detected between c1 and c2.
	AddCollisionListener(c1, c2 Collider, listener CollisionListener)
	// RemoveAllCollisionListener removes all registered listeners
	RemoveAllCollisionListener()
	// NewImageTexture returns a texture instance of image
	NewImageTexture(assetName string, rect image.Rectangle) *Texture
	// NewImageTexture returns a texture instance of text
	NewTextTexture(text string, fontsize float64, fontcolor color.RGBA, rect image.Rectangle) *Texture
	// SetOnStopCallback sets a callback function that will be called on application goes invisible
	SetOnStopCallback(f func())
}

type collisionMap struct {
	c1       Collider
	c2       Collider
	listener CollisionListener
}

// Simra is a struct that provides API interface of simra
type simra struct {
	driver          Driver
	comap           []*collisionMap
	gl              peer.GLer
	spritecontainer peer.SpriteContainerer
	onStop          func()
}

// NewSimra returns an instance of Simraer
func NewSimra() Simraer {
	return &simra{
		comap: make([]*collisionMap, 0),
	}
}

func (sim *simra) onUpdate() {
	if sim.driver != nil {
		sim.driver.Drive()
	}
	sim.collisionCheckAndNotify()
	sim.gl.Update(sim.spritecontainer)
}

func (sim *simra) onGomoStart(glc *peer.GLContext) {
	sim.gl.Initialize(glc)
	sim.SetScene(sim.driver)
}

func (sim *simra) onGomoStop() {
	if sim.onStop != nil {
		sim.onStop()
	}
	sim.spritecontainer.Initialize(sim.gl)
	sim.gl.Finalize()
}

// Start starts to run gomobile and set specified scene as first driver
func (sim *simra) Start(driver Driver) {
	simlog.FuncIn()

	gl := peer.NewGLPeer()
	sc := peer.GetSpriteContainer()
	sc.Initialize(gl)
	sim.gl = gl
	sim.spritecontainer = sc
	sim.driver = driver
	gomo := peer.GetGomo()
	gomo.Initialize(sim.onGomoStart, sim.onGomoStop, sim.onUpdate)
	gomo.Start()

	simlog.FuncOut()
}

// SetScene sets a driver as a scene.
// If a driver is already set, it is replaced with new one.
func (sim *simra) SetScene(driver Driver) {
	simlog.FuncIn()

	sim.spritecontainer.RemoveSprites()
	sim.gl.Reset()
	sim.spritecontainer.Initialize(sim.gl)
	peer.GetTouchPeer().RemoveAllTouchListeners()
	sim.spritecontainer.RemoveSprites()

	sim.driver = driver
	sim.spritecontainer.Initialize(sim.gl)
	err := sim.spritecontainer.AddSprite(&peer.Sprite{}, nil, fps.Progress)
	if err != nil {
		simlog.Errorf("failed to add sprite. err: %s", err.Error())
		return
	}

	driver.Initialize(sim)

	simlog.FuncOut()
}

// NewSprite returns an instance of Sprite
func (sim *simra) NewSprite() Spriter {
	return &sprite{
		simra:         sim,
		animationSets: map[string]*AnimationSet{},
	}
}

// AddSprite adds a sprite to current scene with empty texture.
func (sim *simra) AddSprite(s Spriter) {
	sp := s.(*sprite)
	err := sim.spritecontainer.AddSprite(&sp.Sprite, nil, nil)
	if err != nil {
		simlog.Errorf("failed to add sprite. err: %s", err.Error())
	}

}

// RemoveSprite removes specified sprite from current scene.
// Removed sprite will be disappeared.
func (sim *simra) RemoveSprite(s Spriter) {
	sp := s.(*sprite)
	sp.texture = nil
	sim.spritecontainer.RemoveSprite(&sp.Sprite)
}

// SetDesiredScreenSize configures virtual screen size.
// This function must be called at least once before calling Start.
func (sim *simra) SetDesiredScreenSize(w, h float32) {
	ss := peer.GetScreenSizePeer()
	ss.SetDesiredScreenSize(w, h)
}

// AddTouchListener registers a listener for notifying touch event.
// Event is notified when "screen" is touched.
func (sim *simra) AddTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().AddTouchListener(listener)
}

// RemoveTouchListener unregisters a listener for notifying touch event.
func (sim *simra) RemoveTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().RemoveTouchListener(listener)
}

// AddCollisionListener add a callback function that is called on
// collision is detected between c1 and c2.
func (sim *simra) AddCollisionListener(c1, c2 Collider, listener CollisionListener) {
	// TODO: exclusiveee control
	simlog.FuncIn()
	sim.comap = append(sim.comap, &collisionMap{c1, c2, listener})
	simlog.FuncOut()
}

func (sim *simra) removeCollisionMap(c *collisionMap) {
	result := []*collisionMap{}

	for _, v := range sim.comap {
		if c.c1 != v.c1 && c.c2 != v.c2 && v != c {
			result = append(result, v)
		}
	}

	sim.comap = result
}

// RemoveAllCollisionListener removes all registered listeners
func (sim *simra) RemoveAllCollisionListener() {
	simlog.FuncIn()
	sim.comap = nil
	simlog.FuncOut()
}

// NewImageTexture allocates a texture from asset image
func (sim *simra) NewImageTexture(assetName string, rect image.Rectangle) *Texture {
	simlog.FuncIn()

	gl := sim.gl
	tex := gl.LoadTexture(assetName, rect.Rectangle)
	t := &Texture{
		simra:   sim,
		texture: gl.NewTexture(tex),
	}
	runtime.SetFinalizer(t, (*Texture).release)

	simlog.FuncOut()
	return t
}

// NewTextTexture allocates a texture from specified text
func (sim *simra) NewTextTexture(text string, fontsize float64, fontcolor color.RGBA, rect image.Rectangle) *Texture {
	simlog.FuncIn()

	gl := sim.gl
	tex := gl.MakeTextureByText(text, fontsize, fontcolor, rect.Rectangle)
	t := &Texture{
		simra:   sim,
		texture: gl.NewTexture(tex),
	}
	runtime.SetFinalizer(t, (*Texture).release)

	simlog.FuncOut()
	return t
}

type point struct {
	x, y float32
}

func (sim *simra) collisionCheckAndNotify() {
	// check collision
	for _, v := range sim.comap {
		// TODO: refactoring around here...
		x1, y1, w1, h1 := v.c1.GetXYWH()
		x2, y2, w2, h2 := v.c2.GetXYWH()
		ps := []*point{
			&point{x1 - w1/2, y1 + h1/2},
			&point{x1 + w1/2, y1 + h1/2},
			&point{x1 - w1/2, y1 - h1/2},
			&point{x1 + w1/2, y1 - h1/2},
		}
		for _, p := range ps {
			if p.x >= (x2-w2/2) && p.x <= (x2+w2/2) &&
				p.y >= (y2-h2/2) && p.y <= (y2+h2/2) {
				v.listener.OnCollision(v.c1, v.c2)
				return
			}
		}
	}
}

// RemoveCollisionListener removes a collision map by specified collider instance.
func (sim *simra) RemoveCollisionListener(c1, c2 Collider) {
	// TODO: exclusive control
	simlog.FuncIn()
	sim.removeCollisionMap(&collisionMap{c1, c2, nil})
	simlog.FuncOut()
}

func (sim *simra) comapLength() int {
	return len(sim.comap)
}

func (sim *simra) SetOnStopCallback(f func()) {
	sim.onStop = f
}
<|endoftext|>


<commit_before>package editor

import (
	"github.com/elpinal/coco3/editor/register"
	"github.com/elpinal/coco3/screen"
)

type visual struct {
	nvCommon

	start int
}

func newVisual(s streamSet, e *editor) *visual {
	return &visual{
		nvCommon: nvCommon{
			streamSet: s,
			editor:    e,
		},

		start: e.pos,
	}
}

func (v *visual) Mode() mode {
	return modeVisual
}

func (v *visual) Runes() []rune {
	return v.buf
}

func (v *visual) Position() int {
	return v.pos
}

func (v *visual) Message() []rune {
	return []rune("-- VISUAL --")
}

func (v *visual) Highlight() *screen.Hi {
	return &screen.Hi{
		Left:  min(v.start, v.pos),
		Right: constrain(max(v.start, v.pos)+1, 0, len(v.buf)),
	}
}

func (v *visual) Run() (end continuity, next mode, err error) {
	next = modeVisual
	r, _, err := v.in.ReadRune()
	if err != nil {
		return end, next, err
	}
	for ('1' <= r && r <= '9') || (v.count != 0 && r == '0') {
		v.count = v.count*10 + int(r-'0')
		r1, _, err := v.streamSet.in.ReadRune()
		if err != nil {
			return end, next, err
		}
		r = r1
	}
	if v.count == 0 {
		v.count = 1
	}
	cmd, ok := visualCommands[r]
	if !ok {
		return
	}
	if m := cmd(v, r); m != 0 {
		next = m
	}
	if next != modeInsert && v.pos == len(v.buf) {
		v.move(v.pos - 1)
	}
	v.count = 0
	return
}

type visualCommand = func(*visual, rune) mode

var visualCommands = map[rune]visualCommand{
	CharEscape: (*visual).escape,
	'$':        (*visual).endline,
	'0':        (*visual).beginline,
	'B':        (*visual).wordBack,
	'F':        (*visual).searchBackward,
	'U':        (*visual).toUpper,
	'b':        (*visual).wordBack,
	'c':        (*visual).change,
	'd':        (*visual).delete,
	'f':        (*visual).search,
	'h':        (*visual).left,
	'l':        (*visual).right,
	'r':        (*visual).replace,
	'o':        (*visual).swap,
	'u':        (*visual).toLower,
	'y':        (*visual).yank,
}

func (v *visual) escape(_ rune) mode {
	return modeNormal
}

func (v *visual) delete(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.delete(hi.Left, hi.Right)
	return modeNormal
}

func (v *visual) change(r rune) mode {
	_ = v.delete(r)
	return modeInsert
}

func (v *visual) swap(_ rune) (_ mode) {
	v.start, v.pos = v.pos, v.start
	return
}

func (v *visual) yank(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.yank(register.Unnamed, hi.Left, hi.Right)
	v.move(hi.Left)
	return modeNormal
}

func (v *visual) replace(_ rune) mode {
	r, _, _ := v.in.ReadRune()
	hi := v.Highlight()
	rs := make([]rune, hi.Right-hi.Left)
	for i := range rs {
		rs[i] = r
	}
	v.nvCommon.replace(rs, hi.Left)
	return modeNormal
}

func (v *visual) toUpper(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.toUpper(hi.Left, hi.Right)
	return modeNormal
}

func (v *visual) toLower(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.toLower(hi.Left, hi.Right)
	return modeNormal
}
<commit_msg>Support v_w / v_W commands<commit_after>package editor

import (
	"github.com/elpinal/coco3/editor/register"
	"github.com/elpinal/coco3/screen"
)

type visual struct {
	nvCommon

	start int
}

func newVisual(s streamSet, e *editor) *visual {
	return &visual{
		nvCommon: nvCommon{
			streamSet: s,
			editor:    e,
		},

		start: e.pos,
	}
}

func (v *visual) Mode() mode {
	return modeVisual
}

func (v *visual) Runes() []rune {
	return v.buf
}

func (v *visual) Position() int {
	return v.pos
}

func (v *visual) Message() []rune {
	return []rune("-- VISUAL --")
}

func (v *visual) Highlight() *screen.Hi {
	return &screen.Hi{
		Left:  min(v.start, v.pos),
		Right: constrain(max(v.start, v.pos)+1, 0, len(v.buf)),
	}
}

func (v *visual) Run() (end continuity, next mode, err error) {
	next = modeVisual
	r, _, err := v.in.ReadRune()
	if err != nil {
		return end, next, err
	}
	for ('1' <= r && r <= '9') || (v.count != 0 && r == '0') {
		v.count = v.count*10 + int(r-'0')
		r1, _, err := v.streamSet.in.ReadRune()
		if err != nil {
			return end, next, err
		}
		r = r1
	}
	if v.count == 0 {
		v.count = 1
	}
	cmd, ok := visualCommands[r]
	if !ok {
		return
	}
	if m := cmd(v, r); m != 0 {
		next = m
	}
	if next != modeInsert && v.pos == len(v.buf) {
		v.move(v.pos - 1)
	}
	v.count = 0
	return
}

type visualCommand = func(*visual, rune) mode

var visualCommands = map[rune]visualCommand{
	CharEscape: (*visual).escape,
	'$':        (*visual).endline,
	'0':        (*visual).beginline,
	'B':        (*visual).wordBack,
	'F':        (*visual).searchBackward,
	'U':        (*visual).toUpper,
	'W':        (*visual).word,
	'b':        (*visual).wordBack,
	'c':        (*visual).change,
	'd':        (*visual).delete,
	'f':        (*visual).search,
	'h':        (*visual).left,
	'l':        (*visual).right,
	'r':        (*visual).replace,
	'o':        (*visual).swap,
	'u':        (*visual).toLower,
	'w':        (*visual).word,
	'y':        (*visual).yank,
}

func (v *visual) escape(_ rune) mode {
	return modeNormal
}

func (v *visual) delete(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.delete(hi.Left, hi.Right)
	return modeNormal
}

func (v *visual) change(r rune) mode {
	_ = v.delete(r)
	return modeInsert
}

func (v *visual) swap(_ rune) (_ mode) {
	v.start, v.pos = v.pos, v.start
	return
}

func (v *visual) yank(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.yank(register.Unnamed, hi.Left, hi.Right)
	v.move(hi.Left)
	return modeNormal
}

func (v *visual) replace(_ rune) mode {
	r, _, _ := v.in.ReadRune()
	hi := v.Highlight()
	rs := make([]rune, hi.Right-hi.Left)
	for i := range rs {
		rs[i] = r
	}
	v.nvCommon.replace(rs, hi.Left)
	return modeNormal
}

func (v *visual) toUpper(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.toUpper(hi.Left, hi.Right)
	return modeNormal
}

func (v *visual) toLower(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.toLower(hi.Left, hi.Right)
	return modeNormal
}

func (v *visual) word(r rune) (_ mode) {
	var f func()
	switch r {
	case 'w':
		f = v.nvCommon.wordForward
	case 'W':
		f = v.nvCommon.wordForwardNonBlank
	}
	for i := 0; i < v.count; i++ {
		f()
	}
	return
}
<|endoftext|>