<commit_before>package fruits

import (
	"encoding/json"
	"net/http"
	"path"
)

var (
	fruits map[string]interface{} = make(map[string]interface{})
)

func FruitServer() http.Handler {
	mux := http.NewServeMux()

	mux.HandleFunc("/fruits", handleFruitList)
	mux.HandleFunc("/fruits/", handleFruit)

	return mux
}

func handleFruitList(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		ret := make([]string, 0)
		for k, _ := range fruits {
			ret = append(ret, k)
		}

		b, err := json.Marshal(ret)
		if err != nil {
			panic(err)
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(b)

	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

func handleFruit(w http.ResponseWriter, r *http.Request) {
	_, name := path.Split(r.URL.Path)

	switch r.Method {
	case "GET":
		if data, ok := fruits[name]; ok {
			b, err := json.Marshal(data)
			if err != nil {
				panic(err)
			}

			w.Header().Set("Content-Type", "application/json")
			w.Write(b)
		} else {
			w.WriteHeader(http.StatusNotFound)
		}

	case "PUT":
		var data map[string]interface{}
		if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
			panic(err)
		}

		fruits[name] = data
		w.WriteHeader(http.StatusNoContent)

	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}
<commit_msg>Document example<commit_after>// Package fruits is usage example for httpexpect.
package fruits

import (
	"encoding/json"
	"net/http"
	"path"
)

var (
	fruits map[string]interface{} = make(map[string]interface{})
)

// FruitServer creates http.Handler for fruits server.
//
// Implemented API:
//  GET /fruits           get fruit list
//  GET /fruits/{name}    get fruit
//  PUT /fruits/{name}    add or update fruit
func FruitServer() http.Handler {
	mux := http.NewServeMux()

	mux.HandleFunc("/fruits", handleFruitList)
	mux.HandleFunc("/fruits/", handleFruit)

	return mux
}

func handleFruitList(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		ret := make([]string, 0)
		for k, _ := range fruits {
			ret = append(ret, k)
		}

		b, err := json.Marshal(ret)
		if err != nil {
			panic(err)
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(b)

	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

func handleFruit(w http.ResponseWriter, r *http.Request) {
	_, name := path.Split(r.URL.Path)

	switch r.Method {
	case "GET":
		if data, ok := fruits[name]; ok {
			b, err := json.Marshal(data)
			if err != nil {
				panic(err)
			}

			w.Header().Set("Content-Type", "application/json")
			w.Write(b)
		} else {
			w.WriteHeader(http.StatusNotFound)
		}

	case "PUT":
		var data map[string]interface{}
		if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
			panic(err)
		}

		fruits[name] = data
		w.WriteHeader(http.StatusNoContent)

	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}
<|endoftext|>


<commit_before>package app

// VERSION is the current api version
var VERSION = "2.0.4"
<commit_msg>Release 2.1.1<commit_after>package app

// VERSION is the current api version
var VERSION = "2.1.1"
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/urfave/cli"
)

func runApp() {
	app := cli.NewApp()

	app.Name = "alpinepass"
	app.Version = "0.0.0"
	app.Author = "appPlant GmbH"
	app.Usage = "Manage system environment information."

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "passwords, p",
			Usage: "Include passwords in the output.",
		},
	}

	app.Action = func(c *cli.Context) error {
		data := readFile()
		yamlData := parseData(data)
		configs := []Config{}

		for _, definition := range yamlData.Defs {
			config := createConfig(definition)
			config = filterConfig(config)
			configs = append(configs, config)

		}

		writeJSON(configs)
		return nil
	}

	app.Run(os.Args)
}
<commit_msg>Running the application without any command shows the help page, introduce show and out commands<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/urfave/cli"
)

func runApp() {
	app := cli.NewApp()

	app.Name = "alpinepass"
	app.Version = "0.0.0"
	app.Author = "appPlant GmbH"
	app.Usage = "Manage system environment information."

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "passwords, p",
			Usage: "Include passwords in the output.",
		},
	}

	app.Commands = []cli.Command{
		cli.Command{
			Name:        "show",
			Description: "Print the filtered and unconverted system data to the console.",
			Action: func(c *cli.Context) error {
				fmt.Println("Running the show command!")
				return nil
			},
		},
		cli.Command{
			Name:        "out",
			Description: "Save the system data as a file in the specified output format.",
			Action: func(c *cli.Context) error {
				fmt.Println("Running the out command!")

				data := readFile()
				yamlData := parseData(data)
				configs := []Config{}

				for _, definition := range yamlData.Defs {
					config := createConfig(definition)
					config = filterConfig(config)
					configs = append(configs, config)
				}

				writeJSON(configs)

				return nil
			},
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/hoisie/web"
	"github.com/xyproto/genericsite"
	"github.com/xyproto/instapage"
	"github.com/xyproto/permissions2"
	"github.com/xyproto/siteengines"
	"github.com/xyproto/webhandle"
)

const JQUERY_VERSION = "2.0.0"

func hello(val string) string {
	return instapage.Message("root page", "hello: "+val)
}

func helloHandle(ctx *web.Context, name string) string {
	return "Hello, " + name
}

func notFound2(ctx *web.Context, val string) {
	ctx.ResponseWriter.WriteHeader(404)
	ctx.ResponseWriter.Write([]byte(webhandle.NotFound(ctx, val)))
}

func ServeEngines(userState permissions.UserStateKeeper, mainMenuEntries genericsite.MenuEntries) {
	// The user engine
	userEngine := siteengines.NewUserEngine(userState)
	userEngine.ServePages("archlinux.no")

	// The admin engine
	adminEngine := siteengines.NewAdminEngine(userState)
	adminEngine.ServePages(ArchBaseCP, mainMenuEntries)

	// TODO: Move this one to roboticoverlords instead
	// The dynamic IP webpage (returns an *IPState)
	ipEngine := siteengines.NewIPEngine(userState)
	ipEngine.ServePages()

	// The chat system (see also the menu entry in ArchBaseCP)
	chatEngine := siteengines.NewChatEngine(userState)
	chatEngine.ServePages(ArchBaseCP, mainMenuEntries)

	// Wiki engine
	wikiEngine := siteengines.NewWikiEngine(userState)
	wikiEngine.ServePages(ArchBaseCP, mainMenuEntries)

	// Blog engine
	//blogEngine := NewBlogEngine(userState)
	//blogEngine.ServePages(ArchBaseCP, mainMenuEntries)
}

// TODO: One database per site
func main() {

	// UserState with a Redis Connection Pool
	userState := permissions.NewUserState(0, true, ":6379")
	userState.SetPasswordAlgo("sha256")

	defer userState.Close()

	// The archlinux.no webpage,
	mainMenuEntries := ServeArchlinuxNo(userState, "/js/jquery-"+JQUERY_VERSION+".min.js")

	ServeEngines(userState, mainMenuEntries)

	// Compilation errors, vim-compatible filename
	web.Get("/error", webhandle.GenerateErrorHandle("errors.err"))
	web.Get("/errors", webhandle.GenerateErrorHandle("errors.err"))

	// Various .php and .asp urls that showed up in the log
	genericsite.ServeForFun()

	// TODO: Incorporate this check into web.go, to only return
	// stuff in the header when the HEAD method is requested:
	// if ctx.Request.Method == "HEAD" { return }
	// See also: curl -I

	// Serve on port 3009 for the Nginx instance to use
	web.Run("0.0.0.0:3009")
}
<commit_msg>Encrypting new passwords with bcrypt.<commit_after>package main

import (
	"github.com/hoisie/web"
	"github.com/xyproto/genericsite"
	"github.com/xyproto/instapage"
	"github.com/xyproto/permissions2"
	"github.com/xyproto/siteengines"
	"github.com/xyproto/webhandle"
)

const JQUERY_VERSION = "2.0.0"

func hello(val string) string {
	return instapage.Message("root page", "hello: "+val)
}

func helloHandle(ctx *web.Context, name string) string {
	return "Hello, " + name
}

func notFound2(ctx *web.Context, val string) {
	ctx.ResponseWriter.WriteHeader(404)
	ctx.ResponseWriter.Write([]byte(webhandle.NotFound(ctx, val)))
}

func ServeEngines(userState permissions.UserStateKeeper, mainMenuEntries genericsite.MenuEntries) {
	// The user engine
	userEngine := siteengines.NewUserEngine(userState)
	userEngine.ServePages("archlinux.no")

	// The admin engine
	adminEngine := siteengines.NewAdminEngine(userState)
	adminEngine.ServePages(ArchBaseCP, mainMenuEntries)

	// TODO: Move this one to roboticoverlords instead
	// The dynamic IP webpage (returns an *IPState)
	ipEngine := siteengines.NewIPEngine(userState)
	ipEngine.ServePages()

	// The chat system (see also the menu entry in ArchBaseCP)
	chatEngine := siteengines.NewChatEngine(userState)
	chatEngine.ServePages(ArchBaseCP, mainMenuEntries)

	// Wiki engine
	wikiEngine := siteengines.NewWikiEngine(userState)
	wikiEngine.ServePages(ArchBaseCP, mainMenuEntries)

	// Blog engine
	//blogEngine := NewBlogEngine(userState)
	//blogEngine.ServePages(ArchBaseCP, mainMenuEntries)
}

// TODO: One database per site
func main() {

	// UserState with a Redis Connection Pool
	userState := permissions.NewUserState(0, true, ":6379")
	userState.SetPasswordAlgo("any")

	defer userState.Close()

	// The archlinux.no webpage,
	mainMenuEntries := ServeArchlinuxNo(userState, "/js/jquery-"+JQUERY_VERSION+".min.js")

	ServeEngines(userState, mainMenuEntries)

	// Compilation errors, vim-compatible filename
	web.Get("/error", webhandle.GenerateErrorHandle("errors.err"))
	web.Get("/errors", webhandle.GenerateErrorHandle("errors.err"))

	// Various .php and .asp urls that showed up in the log
	genericsite.ServeForFun()

	// TODO: Incorporate this check into web.go, to only return
	// stuff in the header when the HEAD method is requested:
	// if ctx.Request.Method == "HEAD" { return }
	// See also: curl -I

	// Serve on port 3009 for the Nginx instance to use
	web.Run("0.0.0.0:3009")
}
<|endoftext|>


<commit_before>package gorm

import (
	"errors"
	"fmt"
	"reflect"
)

type Association struct {
	Scope      *Scope
	PrimaryKey interface{}
	Column     string
	Error      error
	Field      *Field
}

func (association *Association) setErr(err error) *Association {
	if err != nil {
		association.Error = err
	}
	return association
}

func (association *Association) Find(value interface{}) *Association {
	association.Scope.related(value, association.Column)
	return association.setErr(association.Scope.db.Error)
}

func (association *Association) Append(values ...interface{}) *Association {
	scope := association.Scope
	field := association.Field

	for _, value := range values {
		reflectvalue := reflect.Indirect(reflect.ValueOf(value))
		if reflectvalue.Kind() == reflect.Struct {
			field.Set(reflect.Append(field.Field, reflectvalue))
		} else if reflectvalue.Kind() == reflect.Slice {
			field.Set(reflect.AppendSlice(field.Field, reflectvalue))
		} else {
			association.setErr(errors.New("invalid association type"))
		}
	}
	scope.Search.Select(association.Column)
	scope.callCallbacks(scope.db.parent.callback.updates)
	return association.setErr(scope.db.Error)
}

func (association *Association) getPrimaryKeys(values ...interface{}) []interface{} {
	primaryKeys := []interface{}{}
	scope := association.Scope

	for _, value := range values {
		reflectValue := reflect.Indirect(reflect.ValueOf(value))
		if reflectValue.Kind() == reflect.Slice {
			for i := 0; i < reflectValue.Len(); i++ {
				if primaryField := scope.New(reflectValue.Index(i).Interface()).PrimaryField(); !primaryField.IsBlank {
					primaryKeys = append(primaryKeys, primaryField.Field.Interface())
				}
			}
		} else if reflectValue.Kind() == reflect.Struct {
			if primaryField := scope.New(value).PrimaryField(); !primaryField.IsBlank {
				primaryKeys = append(primaryKeys, primaryField.Field.Interface())
			}
		}
	}
	return primaryKeys
}

func (association *Association) Delete(values ...interface{}) *Association {
	primaryKeys := association.getPrimaryKeys(values...)

	if len(primaryKeys) == 0 {
		association.setErr(errors.New("no primary key found"))
	} else {
		scope := association.Scope
		relationship := association.Field.Relationship
		// many to many
		if relationship.Kind == "many_to_many" {
			sql := fmt.Sprintf("%v = ? AND %v IN (?)", scope.Quote(relationship.ForeignDBName), scope.Quote(relationship.AssociationForeignDBName))
			query := scope.NewDB().Where(sql, association.PrimaryKey, primaryKeys)
			if err := relationship.JoinTableHandler.Delete(query, relationship); err == nil {
				leftValues := reflect.Zero(association.Field.Field.Type())
				for i := 0; i < association.Field.Field.Len(); i++ {
					value := association.Field.Field.Index(i)
					if primaryField := association.Scope.New(value.Interface()).PrimaryField(); primaryField != nil {
						var included = false
						for _, primaryKey := range primaryKeys {
							if equalAsString(primaryKey, primaryField.Field.Interface()) {
								included = true
							}
						}
						if !included {
							leftValues = reflect.Append(leftValues, value)
						}
					}
				}
				association.Field.Set(leftValues)
			}
		} else {
			association.setErr(errors.New("delete only support many to many"))
		}
	}
	return association
}

func (association *Association) Replace(values ...interface{}) *Association {
	relationship := association.Field.Relationship
	scope := association.Scope
	if relationship.Kind == "many_to_many" {
		field := association.Field.Field

		oldPrimaryKeys := association.getPrimaryKeys(field.Interface())
		association.Field.Set(reflect.Zero(association.Field.Field.Type()))
		association.Append(values...)
		newPrimaryKeys := association.getPrimaryKeys(field.Interface())

		var addedPrimaryKeys = []interface{}{}
		for _, newKey := range newPrimaryKeys {
			hasEqual := false
			for _, oldKey := range oldPrimaryKeys {
				if reflect.DeepEqual(newKey, oldKey) {
					hasEqual = true
					break
				}
			}
			if !hasEqual {
				addedPrimaryKeys = append(addedPrimaryKeys, newKey)
			}
		}
		for _, primaryKey := range association.getPrimaryKeys(values...) {
			addedPrimaryKeys = append(addedPrimaryKeys, primaryKey)
		}

		sql := fmt.Sprintf("%v = ? AND %v NOT IN (?)", scope.Quote(relationship.ForeignDBName), scope.Quote(relationship.AssociationForeignDBName))
		query := scope.NewDB().Where(sql, association.PrimaryKey, addedPrimaryKeys)
		association.setErr(relationship.JoinTableHandler.Delete(query, relationship))
	} else {
		association.setErr(errors.New("replace only support many to many"))
	}
	return association
}

func (association *Association) Clear() *Association {
	relationship := association.Field.Relationship
	scope := association.Scope
	if relationship.Kind == "many_to_many" {
		sql := fmt.Sprintf("%v = ?", scope.Quote(relationship.ForeignDBName))
		query := scope.NewDB().Where(sql, association.PrimaryKey)
		if err := relationship.JoinTableHandler.Delete(query, relationship); err == nil {
			association.Field.Set(reflect.Zero(association.Field.Field.Type()))
		} else {
			association.setErr(err)
		}
	} else {
		association.setErr(errors.New("clear only support many to many"))
	}
	return association
}

func (association *Association) Count() int {
	count := -1
	relationship := association.Field.Relationship
	scope := association.Scope
	newScope := scope.New(association.Field.Field.Interface())

	if relationship.Kind == "many_to_many" {
		relationship.JoinTableHandler.JoinWith(scope.NewDB(), association.Scope.Value).Table(newScope.TableName()).Count(&count)
	} else if relationship.Kind == "has_many" || relationship.Kind == "has_one" {
		whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName))
		countScope := scope.DB().Table(newScope.TableName()).Where(whereSql, association.PrimaryKey)
		if relationship.PolymorphicType != "" {
			countScope = countScope.Where(fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.PolymorphicDBName)), scope.TableName())
		}
		countScope.Count(&count)
	} else if relationship.Kind == "belongs_to" {
		if v, ok := scope.FieldByName(association.Column); ok {
			whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName))
			scope.DB().Table(newScope.TableName()).Where(whereSql, v).Count(&count)
		}
	}

	return count
}
<commit_msg>Don't need to delete join table records if no record added<commit_after>package gorm

import (
	"errors"
	"fmt"
	"reflect"
)

type Association struct {
	Scope      *Scope
	PrimaryKey interface{}
	Column     string
	Error      error
	Field      *Field
}

func (association *Association) setErr(err error) *Association {
	if err != nil {
		association.Error = err
	}
	return association
}

func (association *Association) Find(value interface{}) *Association {
	association.Scope.related(value, association.Column)
	return association.setErr(association.Scope.db.Error)
}

func (association *Association) Append(values ...interface{}) *Association {
	scope := association.Scope
	field := association.Field

	for _, value := range values {
		reflectvalue := reflect.Indirect(reflect.ValueOf(value))
		if reflectvalue.Kind() == reflect.Struct {
			field.Set(reflect.Append(field.Field, reflectvalue))
		} else if reflectvalue.Kind() == reflect.Slice {
			field.Set(reflect.AppendSlice(field.Field, reflectvalue))
		} else {
			association.setErr(errors.New("invalid association type"))
		}
	}
	scope.Search.Select(association.Column)
	scope.callCallbacks(scope.db.parent.callback.updates)
	return association.setErr(scope.db.Error)
}

func (association *Association) getPrimaryKeys(values ...interface{}) []interface{} {
	primaryKeys := []interface{}{}
	scope := association.Scope

	for _, value := range values {
		reflectValue := reflect.Indirect(reflect.ValueOf(value))
		if reflectValue.Kind() == reflect.Slice {
			for i := 0; i < reflectValue.Len(); i++ {
				if primaryField := scope.New(reflectValue.Index(i).Interface()).PrimaryField(); !primaryField.IsBlank {
					primaryKeys = append(primaryKeys, primaryField.Field.Interface())
				}
			}
		} else if reflectValue.Kind() == reflect.Struct {
			if primaryField := scope.New(value).PrimaryField(); !primaryField.IsBlank {
				primaryKeys = append(primaryKeys, primaryField.Field.Interface())
			}
		}
	}
	return primaryKeys
}

func (association *Association) Delete(values ...interface{}) *Association {
	primaryKeys := association.getPrimaryKeys(values...)

	if len(primaryKeys) == 0 {
		association.setErr(errors.New("no primary key found"))
	} else {
		scope := association.Scope
		relationship := association.Field.Relationship
		// many to many
		if relationship.Kind == "many_to_many" {
			sql := fmt.Sprintf("%v = ? AND %v IN (?)", scope.Quote(relationship.ForeignDBName), scope.Quote(relationship.AssociationForeignDBName))
			query := scope.NewDB().Where(sql, association.PrimaryKey, primaryKeys)
			if err := relationship.JoinTableHandler.Delete(query, relationship); err == nil {
				leftValues := reflect.Zero(association.Field.Field.Type())
				for i := 0; i < association.Field.Field.Len(); i++ {
					value := association.Field.Field.Index(i)
					if primaryField := association.Scope.New(value.Interface()).PrimaryField(); primaryField != nil {
						var included = false
						for _, primaryKey := range primaryKeys {
							if equalAsString(primaryKey, primaryField.Field.Interface()) {
								included = true
							}
						}
						if !included {
							leftValues = reflect.Append(leftValues, value)
						}
					}
				}
				association.Field.Set(leftValues)
			}
		} else {
			association.setErr(errors.New("delete only support many to many"))
		}
	}
	return association
}

func (association *Association) Replace(values ...interface{}) *Association {
	relationship := association.Field.Relationship
	scope := association.Scope
	if relationship.Kind == "many_to_many" {
		field := association.Field.Field

		oldPrimaryKeys := association.getPrimaryKeys(field.Interface())
		association.Field.Set(reflect.Zero(association.Field.Field.Type()))
		association.Append(values...)
		newPrimaryKeys := association.getPrimaryKeys(field.Interface())

		var addedPrimaryKeys = []interface{}{}
		for _, newKey := range newPrimaryKeys {
			hasEqual := false
			for _, oldKey := range oldPrimaryKeys {
				if reflect.DeepEqual(newKey, oldKey) {
					hasEqual = true
					break
				}
			}
			if !hasEqual {
				addedPrimaryKeys = append(addedPrimaryKeys, newKey)
			}
		}
		for _, primaryKey := range association.getPrimaryKeys(values...) {
			addedPrimaryKeys = append(addedPrimaryKeys, primaryKey)
		}

		if len(addedPrimaryKeys) > 0 {
			sql := fmt.Sprintf("%v = ? AND %v NOT IN (?)", scope.Quote(relationship.ForeignDBName), scope.Quote(relationship.AssociationForeignDBName))
			query := scope.NewDB().Where(sql, association.PrimaryKey, addedPrimaryKeys)
			association.setErr(relationship.JoinTableHandler.Delete(query, relationship))
		}
	} else {
		association.setErr(errors.New("replace only support many to many"))
	}
	return association
}

func (association *Association) Clear() *Association {
	relationship := association.Field.Relationship
	scope := association.Scope
	if relationship.Kind == "many_to_many" {
		sql := fmt.Sprintf("%v = ?", scope.Quote(relationship.ForeignDBName))
		query := scope.NewDB().Where(sql, association.PrimaryKey)
		if err := relationship.JoinTableHandler.Delete(query, relationship); err == nil {
			association.Field.Set(reflect.Zero(association.Field.Field.Type()))
		} else {
			association.setErr(err)
		}
	} else {
		association.setErr(errors.New("clear only support many to many"))
	}
	return association
}

func (association *Association) Count() int {
	count := -1
	relationship := association.Field.Relationship
	scope := association.Scope
	newScope := scope.New(association.Field.Field.Interface())

	if relationship.Kind == "many_to_many" {
		relationship.JoinTableHandler.JoinWith(scope.NewDB(), association.Scope.Value).Table(newScope.TableName()).Count(&count)
	} else if relationship.Kind == "has_many" || relationship.Kind == "has_one" {
		whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName))
		countScope := scope.DB().Table(newScope.TableName()).Where(whereSql, association.PrimaryKey)
		if relationship.PolymorphicType != "" {
			countScope = countScope.Where(fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.PolymorphicDBName)), scope.TableName())
		}
		countScope.Count(&count)
	} else if relationship.Kind == "belongs_to" {
		if v, ok := scope.FieldByName(association.Column); ok {
			whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName))
			scope.DB().Table(newScope.TableName()).Where(whereSql, v).Count(&count)
		}
	}

	return count
}
<|endoftext|>


<commit_before>package main

import "time"

func main() {
	time.Sleep(100 * time.Millisecond)
	ch := make(chan int)
	go func() {
		time.Sleep(200 * time.Millisecond)
		ch <- 42
		time.Sleep(100 * time.Millisecond)
	}()
	<-ch
	time.Sleep(100 * time.Millisecond)
}
<commit_msg>Add block example<commit_after>package main

import "math"
import "time"

func main() {
	time.Sleep(10 * time.Millisecond)
	ch := make(chan int)
	go func() {
		time.Sleep(10 * time.Millisecond)
		for i := 0; i < 10000000; i++ {
			j := math.Sqrt(float64(i * i))
			j *= j * float64(i)
			_ = j
		}
		ch <- 42
		time.Sleep(10 * time.Millisecond)
	}()
	<-ch
	time.Sleep(100 * time.Millisecond)
}
<|endoftext|>


<commit_before>//Package gtf is used to read gtf features.
// ref: http://mblab.wustl.edu/GTF22.html
package gtf

import (
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/shenwei356/breader"
)

// Version is the GTF version
const Version = 2.2

// Feature is the gff feature struct
type Feature struct {
	SeqName    string
	Source     string
	Feature    string
	Start      int
	End        int
	Score      *float64
	Strand     *string
	Frame      *int
	Attributes []Attribute
}

// Attribute is the attribute
type Attribute struct {
	Tag, Value string
}

// Threads for bread.NewBufferedReader()
var Threads = runtime.NumCPU()

// ReadFeatures returns gtf features of a file
func ReadFeatures(file string) ([]Feature, error) {
	return ReadFilteredFeatures(file, []string{}, []string{})
}

// ReadFilteredFeatures returns gtf features of specific chrs in a file
func ReadFilteredFeatures(file string, chrs []string, feats []string) ([]Feature, error) {
	if _, err := os.Stat(file); os.IsNotExist(err) {
		return nil, err
	}
	chrsMap := make(map[string]struct{}, len(chrs))
	for _, chr := range chrs {
		chrsMap[strings.ToLower(chr)] = struct{}{}
	}

	featsMap := make(map[string]struct{}, len(feats))
	for _, f := range feats {
		featsMap[strings.ToLower(f)] = struct{}{}
	}

	fn := func(line string) (interface{}, bool, error) {
		if len(line) == 0 || line[0] == '#' {
			return nil, false, nil
		}
		line = strings.TrimRight(line, "\r\n")
		items := strings.Split(line, "\t")
		if len(items) != 9 {
			return nil, false, nil
		}

		if len(chrs) > 0 { // selected chrs
			if _, ok := chrsMap[strings.ToLower(items[0])]; !ok {
				return nil, false, nil
			}
		}

		if len(feats) > 0 { // selected features
			if _, ok := featsMap[strings.ToLower(items[2])]; !ok {
				return nil, false, nil
			}
		}

		var err error

		start, err := strconv.Atoi(items[3])
		if err != nil {
			return nil, false, fmt.Errorf("bad start: %s", items[3])
		}

		end, err := strconv.Atoi(items[4])
		if err != nil {
			return nil, false, fmt.Errorf("bad end: %s", items[4])
		}

		var score *float64
		if items[5] != "." {
			s, err := strconv.ParseFloat(items[5], 64)
			if err != nil {
				return nil, false, fmt.Errorf("bad score: %s", items[5])
			}
			score = &s
		}

		var strand *string
		if items[6] != "." {
			s := items[6]
			if !(s == "+" || s == "-") {
				return nil, false, fmt.Errorf("illigal strand: %s", s)
			}
			strand = &s
		}

		var frame *int
		if items[7] != "." {
			f, err := strconv.Atoi(items[7])
			if err != nil {
				return nil, false, fmt.Errorf("bad frame: %s", items[7])
			}
			if !(f == 0 || f == 1 || f == 2) {
				return nil, false, fmt.Errorf("illigal frame: %d", f)
			}
			frame = &f
		}

		feature := Feature{items[0], items[1], items[2], start, end, score, strand, frame, nil}

		tagValues := strings.Split(items[8], "; ")
		if len(tagValues) > 0 {
			feature.Attributes = []Attribute{}
			for _, tagValue := range tagValues[0 : len(tagValues)-1] {
				items2 := strings.Split(tagValue, " ")
				tag := items2[0]
				value := items2[1]
				// if value[len(value)-1] == ';' {
				// 	value = value[0 : len(value)-1]
				// }
				if len(value) > 2 {
					value = value[1 : len(value)-1]
				} else {
					value = ""
				}
				feature.Attributes = append(feature.Attributes, Attribute{tag, value})
			}
		}
		return feature, true, nil
	}
	reader, err := breader.NewBufferedReader(file, Threads, 100, fn)
	if err != nil {
		return nil, err
	}
	features := []Feature{}
	for chunk := range reader.Ch {
		if chunk.Err != nil {
			return nil, chunk.Err
		}
		for _, data := range chunk.Data {
			features = append(features, data.(Feature))
		}
	}
	return features, nil
}
<commit_msg>forgotten change<commit_after>//Package gtf is used to read gtf features.
// ref: http://mblab.wustl.edu/GTF22.html
package gtf

import (
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/shenwei356/breader"
)

// Version is the GTF version
const Version = 2.2

// Feature is the gff feature struct
type Feature struct {
	SeqName    string
	Source     string
	Feature    string
	Start      int
	End        int
	Score      *float64
	Strand     *string
	Frame      *int
	Attributes []Attribute
}

// Attribute is the attribute
type Attribute struct {
	Tag, Value string
}

// Threads for bread.NewBufferedReader()
var Threads = runtime.NumCPU()

// ReadFeatures returns gtf features of a file
func ReadFeatures(file string) ([]Feature, error) {
	return ReadFilteredFeatures(file, []string{}, []string{})
}

// ReadFilteredFeatures returns gtf features of specific chrs in a file
func ReadFilteredFeatures(file string, chrs []string, feats []string) ([]Feature, error) {
	if _, err := os.Stat(file); os.IsNotExist(err) {
		return nil, err
	}
	chrsMap := make(map[string]struct{}, len(chrs))
	for _, chr := range chrs {
		chrsMap[strings.ToLower(chr)] = struct{}{}
	}

	featsMap := make(map[string]struct{}, len(feats))
	for _, f := range feats {
		featsMap[strings.ToLower(f)] = struct{}{}
	}

	fn := func(line string) (interface{}, bool, error) {
		if len(line) == 0 || line[0] == '#' {
			return nil, false, nil
		}
		line = strings.TrimRight(line, "\r\n")
		items := strings.Split(line, "\t")

		if len(items) != 9 {
			return nil, false, nil
		}

		if len(chrs) > 0 { // selected chrs
			if _, ok := chrsMap[strings.ToLower(items[0])]; !ok {
				return nil, false, nil
			}
		}

		if len(feats) > 0 { // selected features
			if _, ok := featsMap[strings.ToLower(items[2])]; !ok {
				return nil, false, nil
			}
		}
		var err error

		start, err := strconv.Atoi(items[3])
		if err != nil {
			return nil, false, fmt.Errorf("bad start: %s", items[3])
		}

		end, err := strconv.Atoi(items[4])
		if err != nil {
			return nil, false, fmt.Errorf("bad end: %s", items[4])
		}

		var score *float64
		if items[5] != "." {
			s, err := strconv.ParseFloat(items[5], 64)
			if err != nil {
				return nil, false, fmt.Errorf("bad score: %s", items[5])
			}
			score = &s
		}

		var strand *string
		if items[6] != "." {
			s := items[6]
			if !(s == "+" || s == "-") {
				return nil, false, fmt.Errorf("illigal strand: %s", s)
			}
			strand = &s
		}

		var frame *int
		if items[7] != "." {
			f, err := strconv.Atoi(items[7])
			if err != nil {
				return nil, false, fmt.Errorf("bad frame: %s", items[7])
			}
			if !(f == 0 || f == 1 || f == 2) {
				return nil, false, fmt.Errorf("illigal frame: %d", f)
			}
			frame = &f
		}

		feature := Feature{items[0], items[1], items[2], start, end, score, strand, frame, nil}

		tagValues := strings.Split(items[8], "; ")
		if len(tagValues) > 0 {
			feature.Attributes = []Attribute{}
			for _, tagValue := range tagValues[0 : len(tagValues)-1] {
				items2 := strings.Split(tagValue, " ")
				tag := items2[0]
				value := items2[1]
				// if value[len(value)-1] == ';' {
				// 	value = value[0 : len(value)-1]
				// }
				if len(value) > 2 {
					value = value[1 : len(value)-1]
				} else {
					value = ""
				}
				feature.Attributes = append(feature.Attributes, Attribute{tag, value})
			}
		}
		return feature, true, nil
	}
	reader, err := breader.NewBufferedReader(file, Threads, 100, fn)
	if err != nil {
		return nil, err
	}
	features := []Feature{}
	for chunk := range reader.Ch {
		if chunk.Err != nil {
			return nil, chunk.Err
		}
		for _, data := range chunk.Data {
			features = append(features, data.(Feature))
		}
	}
	return features, nil
}
<|endoftext|>


<commit_before>package jsoniter

import (
	"io"
	"reflect"
	"sync/atomic"
	"unsafe"
	"errors"
)

type Config struct {
	IndentionStep                 int
	MarshalFloatWith6Digits       bool
	SupportUnexportedStructFields bool
	EscapeHtml                    bool
	SortMapKeys                   bool
}

type frozenConfig struct {
	configBeforeFrozen Config
	sortMapKeys        bool
	indentionStep      int
	decoderCache       unsafe.Pointer
	encoderCache       unsafe.Pointer
	extensions         []ExtensionFunc
	streamPool         chan *Stream
	iteratorPool       chan *Iterator
}

var ConfigDefault = Config{}.Froze()

// Trying to be 100% compatible with standard library behavior
var ConfigCompatibleWithStandardLibrary = Config{
	EscapeHtml:  true,
	SortMapKeys: true,
}.Froze()

var ConfigFastest = Config{
	MarshalFloatWith6Digits: true,
}.Froze()

func (cfg Config) Froze() *frozenConfig {
	frozenConfig := &frozenConfig{
		sortMapKeys:   cfg.SortMapKeys,
		indentionStep: cfg.IndentionStep,
		streamPool:    make(chan *Stream, 16),
		iteratorPool:  make(chan *Iterator, 16),
	}
	atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
	atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
	if cfg.MarshalFloatWith6Digits {
		frozenConfig.marshalFloatWith6Digits()
	}
	if cfg.SupportUnexportedStructFields {
		frozenConfig.supportUnexportedStructFields()
	}
	if cfg.EscapeHtml {
		frozenConfig.escapeHtml()
	}
	frozenConfig.configBeforeFrozen = cfg
	return frozenConfig
}

// RegisterExtension can register a custom extension
func (cfg *frozenConfig) registerExtension(extension ExtensionFunc) {
	cfg.extensions = append(cfg.extensions, extension)
}

func (cfg *frozenConfig) supportUnexportedStructFields() {
	cfg.registerExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, EncoderFunc, DecoderFunc) {
		return []string{field.Name}, nil, nil
	})
}

// EnableLossyFloatMarshalling keeps 10**(-6) precision
// for float variables for better performance.
func (cfg *frozenConfig) marshalFloatWith6Digits() {
	// for better performance
	cfg.addEncoderToCache(reflect.TypeOf((*float32)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
		val := *((*float32)(ptr))
		stream.WriteFloat32Lossy(val)
	}})
	cfg.addEncoderToCache(reflect.TypeOf((*float64)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
		val := *((*float64)(ptr))
		stream.WriteFloat64Lossy(val)
	}})
}

func (cfg *frozenConfig) escapeHtml() {
	// for better performance
	cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
		val := *((*string)(ptr))
		stream.WriteStringWithHtmlEscaped(val)
	}})
}

func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
	done := false
	for !done {
		ptr := atomic.LoadPointer(&cfg.decoderCache)
		cache := *(*map[reflect.Type]Decoder)(ptr)
		copied := map[reflect.Type]Decoder{}
		for k, v := range cache {
			copied[k] = v
		}
		copied[cacheKey] = decoder
		done = atomic.CompareAndSwapPointer(&cfg.decoderCache, ptr, unsafe.Pointer(&copied))
	}
}

func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder Encoder) {
	done := false
	for !done {
		ptr := atomic.LoadPointer(&cfg.encoderCache)
		cache := *(*map[reflect.Type]Encoder)(ptr)
		copied := map[reflect.Type]Encoder{}
		for k, v := range cache {
			copied[k] = v
		}
		copied[cacheKey] = encoder
		done = atomic.CompareAndSwapPointer(&cfg.encoderCache, ptr, unsafe.Pointer(&copied))
	}
}

func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) Decoder {
	ptr := atomic.LoadPointer(&cfg.decoderCache)
	cache := *(*map[reflect.Type]Decoder)(ptr)
	return cache[cacheKey]
}

func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) Encoder {
	ptr := atomic.LoadPointer(&cfg.encoderCache)
	cache := *(*map[reflect.Type]Encoder)(ptr)
	return cache[cacheKey]
}

// CleanDecoders cleans decoders registered or cached
func (cfg *frozenConfig) CleanDecoders() {
	typeDecoders = map[string]Decoder{}
	fieldDecoders = map[string]Decoder{}
	atomic.StorePointer(&cfg.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
}

// CleanEncoders cleans encoders registered or cached
func (cfg *frozenConfig) CleanEncoders() {
	typeEncoders = map[string]Encoder{}
	fieldEncoders = map[string]Encoder{}
	atomic.StorePointer(&cfg.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
}

func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
	stream := cfg.borrowStream()
	defer cfg.returnStream(stream)
	stream.WriteVal(v)
	if stream.Error != nil {
		return nil, stream.Error
	}
	return string(stream.Buffer()), nil
}

func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
	stream := cfg.borrowStream()
	defer cfg.returnStream(stream)
	stream.WriteVal(v)
	if stream.Error != nil {
		return nil, stream.Error
	}
	result := stream.Buffer()
	copied := make([]byte, len(result))
	copy(copied, result)
	return copied, nil
}

func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func (cfg *frozenConfig) UnmarshalAnyFromString(str string) (Any, error) {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
	}
	return nil, iter.Error
}

func (cfg *frozenConfig) UnmarshalAny(data []byte) (Any, error) {
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
	}
	return any, iter.Error
}

func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	typ := reflect.TypeOf(v)
	if typ.Kind() != reflect.Ptr {
		// return non-pointer error
		return errors.New("the second param must be ptr type")
	}
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("Unmarshal", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func (cfg *frozenConfig) NewEncoder(writer io.Writer) *AdaptedEncoder {
	stream := NewStream(cfg, writer, 512)
	return &AdaptedEncoder{stream}
}

func (cfg *frozenConfig) NewDecoder(reader io.Reader) *AdaptedDecoder {
	iter := Parse(cfg, reader, 512)
	return &AdaptedDecoder{iter}
}
<commit_msg>#57 copy bytes<commit_after>package jsoniter

import (
	"io"
	"reflect"
	"sync/atomic"
	"unsafe"
	"errors"
)

type Config struct {
	IndentionStep                 int
	MarshalFloatWith6Digits       bool
	SupportUnexportedStructFields bool
	EscapeHtml                    bool
	SortMapKeys                   bool
}

type frozenConfig struct {
	configBeforeFrozen Config
	sortMapKeys        bool
	indentionStep      int
	decoderCache       unsafe.Pointer
	encoderCache       unsafe.Pointer
	extensions         []ExtensionFunc
	streamPool         chan *Stream
	iteratorPool       chan *Iterator
}

var ConfigDefault = Config{}.Froze()

// Trying to be 100% compatible with standard library behavior
var ConfigCompatibleWithStandardLibrary = Config{
	EscapeHtml:  true,
	SortMapKeys: true,
}.Froze()

var ConfigFastest = Config{
	MarshalFloatWith6Digits: true,
}.Froze()

func (cfg Config) Froze() *frozenConfig {
	frozenConfig := &frozenConfig{
		sortMapKeys:   cfg.SortMapKeys,
		indentionStep: cfg.IndentionStep,
		streamPool:    make(chan *Stream, 16),
		iteratorPool:  make(chan *Iterator, 16),
	}
	atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
	atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
	if cfg.MarshalFloatWith6Digits {
		frozenConfig.marshalFloatWith6Digits()
	}
	if cfg.SupportUnexportedStructFields {
		frozenConfig.supportUnexportedStructFields()
	}
	if cfg.EscapeHtml {
		frozenConfig.escapeHtml()
	}
	frozenConfig.configBeforeFrozen = cfg
	return frozenConfig
}

// RegisterExtension can register a custom extension
func (cfg *frozenConfig) registerExtension(extension ExtensionFunc) {
	cfg.extensions = append(cfg.extensions, extension)
}

func (cfg *frozenConfig) supportUnexportedStructFields() {
	cfg.registerExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, EncoderFunc, DecoderFunc) {
		return []string{field.Name}, nil, nil
	})
}

// EnableLossyFloatMarshalling keeps 10**(-6) precision
// for float variables for better performance.
func (cfg *frozenConfig) marshalFloatWith6Digits() {
	// for better performance
	cfg.addEncoderToCache(reflect.TypeOf((*float32)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
		val := *((*float32)(ptr))
		stream.WriteFloat32Lossy(val)
	}})
	cfg.addEncoderToCache(reflect.TypeOf((*float64)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
		val := *((*float64)(ptr))
		stream.WriteFloat64Lossy(val)
	}})
}

func (cfg *frozenConfig) escapeHtml() {
	// for better performance
	cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
		val := *((*string)(ptr))
		stream.WriteStringWithHtmlEscaped(val)
	}})
}

func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
	done := false
	for !done {
		ptr := atomic.LoadPointer(&cfg.decoderCache)
		cache := *(*map[reflect.Type]Decoder)(ptr)
		copied := map[reflect.Type]Decoder{}
		for k, v := range cache {
			copied[k] = v
		}
		copied[cacheKey] = decoder
		done = atomic.CompareAndSwapPointer(&cfg.decoderCache, ptr, unsafe.Pointer(&copied))
	}
}

func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder Encoder) {
	done := false
	for !done {
		ptr := atomic.LoadPointer(&cfg.encoderCache)
		cache := *(*map[reflect.Type]Encoder)(ptr)
		copied := map[reflect.Type]Encoder{}
		for k, v := range cache {
			copied[k] = v
		}
		copied[cacheKey] = encoder
		done = atomic.CompareAndSwapPointer(&cfg.encoderCache, ptr, unsafe.Pointer(&copied))
	}
}

func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) Decoder {
	ptr := atomic.LoadPointer(&cfg.decoderCache)
	cache := *(*map[reflect.Type]Decoder)(ptr)
	return cache[cacheKey]
}

func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) Encoder {
	ptr := atomic.LoadPointer(&cfg.encoderCache)
	cache := *(*map[reflect.Type]Encoder)(ptr)
	return cache[cacheKey]
}

// CleanDecoders cleans decoders registered or cached
func (cfg *frozenConfig) CleanDecoders() {
	typeDecoders = map[string]Decoder{}
	fieldDecoders = map[string]Decoder{}
	atomic.StorePointer(&cfg.decoderCache, unsafe.Pointer(&map[string]Decoder{}))
}

// CleanEncoders cleans encoders registered or cached
func (cfg *frozenConfig) CleanEncoders() {
	typeEncoders = map[string]Encoder{}
	fieldEncoders = map[string]Encoder{}
	atomic.StorePointer(&cfg.encoderCache, unsafe.Pointer(&map[string]Encoder{}))
}

func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
	stream := cfg.borrowStream()
	defer cfg.returnStream(stream)
	stream.WriteVal(v)
	if stream.Error != nil {
		return "", stream.Error
	}
	return string(stream.Buffer()), nil
}

func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
	stream := cfg.borrowStream()
	defer cfg.returnStream(stream)
	stream.WriteVal(v)
	if stream.Error != nil {
		return nil, stream.Error
	}
	result := stream.Buffer()
	copied := make([]byte, len(result))
	copy(copied, result)
	return copied, nil
}

func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func (cfg *frozenConfig) UnmarshalAnyFromString(str string) (Any, error) {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
	}
	return nil, iter.Error
}

func (cfg *frozenConfig) UnmarshalAny(data []byte) (Any, error) {
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
	}
	return any, iter.Error
}

func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
	data = data[:lastNotSpacePos(data)]
	iter := cfg.borrowIterator(data)
	defer cfg.returnIterator(iter)
	typ := reflect.TypeOf(v)
	if typ.Kind() != reflect.Ptr {
		// return non-pointer error
		return errors.New("the second param must be ptr type")
	}
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("Unmarshal", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func (cfg *frozenConfig) NewEncoder(writer io.Writer) *AdaptedEncoder {
	stream := NewStream(cfg, writer, 512)
	return &AdaptedEncoder{stream}
}

func (cfg *frozenConfig) NewDecoder(reader io.Reader) *AdaptedDecoder {
	iter := Parse(cfg, reader, 512)
	return &AdaptedDecoder{iter}
}
<|endoftext|>


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

import (
	"bytes"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
	"github.com/aliyun/aliyun-cli/cli"
	"github.com/aliyun/aliyun-cli/config"
	"github.com/aliyun/aliyun-cli/i18n"
	"github.com/aliyun/aliyun-cli/meta"

	"encoding/json"
	"fmt"
	"io"
	"strings"
)

// main entrance of aliyun cli
type Commando struct {
	profile config.Profile
	library *Library
}

var hookdo = func(fn func() (*responses.CommonResponse, error)) func() (*responses.CommonResponse, error) {
	return fn
}

func NewCommando(w io.Writer, profile config.Profile) *Commando {
	r := &Commando{
		profile: profile,
	}
	r.library = NewLibrary(w, profile.Language) //TODO: load from local repository
	return r
}

func (c *Commando) InitWithCommand(cmd *cli.Command) {
	cmd.Run = c.main
	cmd.Help = c.help
	cmd.AutoComplete = c.complete
}

//
func (c *Commando) main(ctx *cli.Context, args []string) error {
	//
	// aliyun
	if len(args) == 0 {
		c.printUsage(ctx)
		return nil
	}

	// update current `Profile` with flags
	var err error
	c.profile, err = config.LoadProfileWithContext(ctx)
	if err != nil {
		return cli.NewErrorWithTip(err, "Configuration failed, use `aliyun configure` to configure it")
	}
	err = c.profile.Validate()
	if err != nil {
		return cli.NewErrorWithTip(err, "Configuration failed, use `aliyun configure` to configure it.")
	}
	i18n.SetLanguage(c.profile.Language)

	// process following commands:
	// 	 aliyun <productCode>
	//   aliyun <productCode> <method> --param1 value1
	//   aliyun <productCode> GET <path>
	productName := args[0]
	if len(args) == 1 {
		// aliyun <productCode>
		// TODO: aliyun pluginName ...
		return c.library.PrintProductUsage(productName, true)
	} else if len(args) == 2 {
		// rpc or restful call
		// aliyun <productCode> <method> --param1 value1
		product, _ := c.library.GetProduct(args[0])
		if product.Code != "" {
			if version, _ := ctx.Flags().Get("version").GetValue(); version != "" {
				if style, ok := c.library.GetStyle(productName, version); ok {
					product.ApiStyle = style
				} else {
					return cli.NewErrorWithTip(fmt.Errorf("unchecked version %s", version),
						"Please contact the customer support to get more info about API version")
				}
			}
		}
		if product.ApiStyle == "restful" {
			api, _ := c.library.GetApi(product.Code, product.Version, args[1])
			ctx.Command().Name = args[1]
			return c.processInvoke(ctx, productName, api.Method, api.PathPattern)
		}

		return c.processInvoke(ctx, productName, args[1], "")
	} else if len(args) == 3 {
		// restful call
		// aliyun <productCode> {GET|PUT|POST|DELETE} <path> --
		return c.processInvoke(ctx, productName, args[1], args[2])
	} else {
		return cli.NewErrorWithTip(fmt.Errorf("too many arguments"),
			"Use `aliyun --help` to show usage")
	}
}

func (c *Commando) processInvoke(ctx *cli.Context, productCode string, apiOrMethod string, path string) error {
	// create specific invoker
	invoker, err := c.createInvoker(ctx, productCode, apiOrMethod, path)
	if err != nil {
		return err
	}
	err = invoker.Prepare(ctx)
	if err != nil {
		return err
	}

	// process --dryrun
	if DryRunFlag(ctx.Flags()).IsAssigned() {
		invoker.getRequest().TransToAcsRequest()
		invoker.getClient().BuildRequestWithSigner(invoker.getRequest(), nil)
		cli.Printf(ctx.Writer(), "Skip invoke in dry-run mode, request is:\n------------------------------------\n%s\n",
			invoker.getRequest().String())
		return nil
	}

	// if invoke with helper
	out, err, ok := c.invokeWithHelper(invoker)

	// cli.Printf("invoker %v %v \n", invoker, reflect.TypeOf(invoker))
	if ok {
		if err != nil { // call with helper failed
			return err
		}
	} else {
		resp, err := hookdo(invoker.Call)()
		if err != nil {
			// if unmarshal failed,
			if !strings.Contains(strings.ToLower(err.Error()), "unmarshal") {
				return err
			}
		}
		out = resp.GetHttpContentString()
	}

	// if `--quiet` assigned. do not print anything
	if QuietFlag(ctx.Flags()).IsAssigned() {
		return nil
	}

	// process `--output ...`
	if filter := GetOutputFilter(ctx); filter != nil {
		out, err = filter.FilterOutput(out)
		if err != nil {
			return err
		}
	}

	out = sortJSON(out)

	cli.Println(ctx.Writer(), out)
	return nil
}

func sortJSON(content string) string {
	var v interface{}
	err := json.Unmarshal([]byte(content), &v)
	if err != nil {
		return content
	}
	buf := new(bytes.Buffer)
	encoder := json.NewEncoder(buf)
	encoder.SetEscapeHTML(false)
	encoder.SetIndent("", "\t")
	err = encoder.Encode(v)
	if err != nil {
		return content
	}
	return strings.TrimSuffix(buf.String(), "\n")
}

// invoke with helper
func (c *Commando) invokeWithHelper(invoker Invoker) (resp string, err error, ok bool) {
	if pager := GetPager(); pager != nil {
		// cli.Printf("call with pager")
		resp, err = pager.CallWith(invoker)
		ok = true
		return
	}

	if waiter := GetWaiter(); waiter != nil {
		// cli.Printf("call with waiter")
		resp, err = waiter.CallWith(invoker)
		ok = true
		return
	}

	ok = false
	return
}

//
// create invoker for specific case
// rpc: RpcInvoker, ForceRpcInvoker
// restful: RestfulInvoker
func (c *Commando) createInvoker(ctx *cli.Context, productCode string, apiOrMethod string, path string) (Invoker, error) {
	force := ForceFlag(ctx.Flags()).IsAssigned()
	basicInvoker := NewBasicInvoker(&c.profile)

	//
	// get product info
	if product, ok := c.library.GetProduct(productCode); ok {
		err := basicInvoker.Init(ctx, &product)
		if err != nil {
			return nil, err
		}
		if force {
			if version, _ := ctx.Flags().Get("version").GetValue(); version != "" {
				if style, ok := c.library.GetStyle(productCode, version); ok {
					product.ApiStyle = style
				} else {
					return nil, cli.NewErrorWithTip(fmt.Errorf("uncheked version %s", version),
						"Please contact the customer support to get more info about API version")
				}
			}
		}
		if strings.ToLower(product.ApiStyle) == "rpc" {
			//
			// Rpc call
			if path != "" {
				return nil, cli.NewErrorWithTip(fmt.Errorf("invalid argument %s", path),
					"Use `aliyun help %s` see more information.", product.GetLowerCode())
			}
			if force {
				return &ForceRpcInvoker{
					basicInvoker,
					apiOrMethod,
				}, nil
			}
			if api, ok := c.library.GetApi(product.Code, product.Version, apiOrMethod); ok {
				return &RpcInvoker{
					basicInvoker,
					&api,
				}, nil
			}
			return nil, &InvalidApiError{apiOrMethod, &product}

		}
		//
		// Restful Call
		// aliyun cs GET /clusters
		// aliyun cs /clusters --roa GET
		ok, method, path, err := checkRestfulMethod(ctx, apiOrMethod, path)
		if err != nil {
			return nil, err
		}
		if !ok {
			return nil, cli.NewErrorWithTip(fmt.Errorf("product '%s' need restful call", product.GetLowerCode()),
				"Use `aliyun %s {GET|PUT|POST|DELETE} <path> ...`", product.GetLowerCode())
		}
		if api, ok := c.library.GetApi(product.Code, product.Version, ctx.Command().Name); ok {
			return &RestfulInvoker{
				basicInvoker,
				method,
				path,
				force,
				&api,
			}, nil
		}
		return &RestfulInvoker{
			basicInvoker,
			method,
			path,
			force,
			nil,
		}, nil

	} else {
		if !force {
			return nil, &InvalidProductError{Code: productCode, library: c.library}
		}

		//
		// force call on unknown product, use temporary product info
		product = meta.Product{
			Code: productCode,
		}
		err := basicInvoker.Init(ctx, &product)
		if err != nil {
			return nil, err
		}

		//
		// Restful Call
		// aliyun cs GET /clusters
		// aliyun cs /clusters --roa GET
		ok, method, path, err := checkRestfulMethod(ctx, apiOrMethod, path)
		if err != nil {
			return nil, err
		}
		if ok {
			return &RestfulInvoker{
				basicInvoker,
				method,
				path,
				force,
				nil,
			}, nil
			// return invoker, nil
			// c.InvokeRestful(ctx, &product, method, path)
		}
		return &ForceRpcInvoker{
			basicInvoker,
			apiOrMethod,
		}, nil
		// c.InvokeRpcForce(ctx, &product, apiOrMethod)

	}
}

//
func (c *Commando) help(ctx *cli.Context, args []string) error {
	cmd := ctx.Command()
	//if err != nil {
	//	cli.Errorf("ERROR: %s\n", err.Error())
	//	printUsage(ctx.Command(), nil)
	// } else {
	if len(args) == 0 {
		cmd.PrintHead(ctx)
		cmd.PrintUsage(ctx)
		cmd.PrintFlags(ctx)
		cmd.PrintSample(ctx)
		c.library.PrintProducts()
		cmd.PrintTail(ctx)
		return nil
	} else if len(args) == 1 {
		cmd.PrintHead(ctx)
		return c.library.PrintProductUsage(args[0], true)
		// c.PrintFlags() TODO add later
	} else if len(args) == 2 {
		cmd.PrintHead(ctx)
		return c.library.PrintApiUsage(args[0], args[1])
		// c.PrintFlags() TODO add later
	} else {
		return fmt.Errorf("too many arguments: %d", len(args))
	}
}

//
func (c *Commando) complete(ctx *cli.Context, args []string) []string {
	w := ctx.Writer()

	r := make([]string, 0)
	//
	// aliyun
	if len(args) == 0 {
		// Case insensitive strings.ToLower()
		ctx.Command().ExecuteComplete(ctx, args)
		for _, p := range c.library.GetProducts() {
			if !strings.HasPrefix(p.GetLowerCode(), strings.ToLower(ctx.Completion().Current)) {
				continue
			}
			cli.PrintfWithColor(w, cli.ProductListColor(), "%s\n", p.GetLowerCode())
		}
		return r
	}

	product, ok := c.library.GetProduct(args[0])
	if !ok {
		return r
	}

	if product.ApiStyle == "rpc" {
		if len(args) == 1 {
			for _, name := range product.ApiNames {
				if !strings.HasPrefix(strings.ToLower(name), strings.ToLower(ctx.Completion().Current)) {
					continue
				}
				cli.PrintfWithColor(w, cli.APIListColor(), "%s\n", name)
			}
			return r
		}
		api, ok := c.library.GetApi(product.Code, product.Version, args[1])
		if !ok {
			return r
		}

		api.ForeachParameters(func(s string, p meta.Parameter) {
			if strings.HasPrefix("--"+strings.ToLower(s), strings.ToLower(ctx.Completion().Current)) && !p.Hidden {
				cli.Printf(ctx.Writer(), "--%s\n", s)
			}
		})
	} else if product.ApiStyle == "restful" {
		if len(args) == 1 {
			cli.PrintfWithColor(w, cli.APIListColor(), "GET\n")
			cli.PrintfWithColor(w, cli.APIListColor(), "POST\n")
			cli.PrintfWithColor(w, cli.APIListColor(), "DELETE\n")
			cli.PrintfWithColor(w, cli.APIListColor(), "PUT\n")

			return r
		}
	}

	return r
}

func (c *Commando) printUsage(ctx *cli.Context) {
	cmd := ctx.Command()
	cmd.PrintHead(ctx)
	cmd.PrintUsage(ctx)
	cmd.PrintSubCommands(ctx)
	cmd.PrintFlags(ctx)
	cmd.PrintSample(ctx)
	//if configError != nil {
	//	cli.Printf("Configuration Invailed: %s\n", configError)
	//	cli.Printf("Run `aliyun configure` first:\n  %s\n", configureCommand.Usage)
	//}
	cmd.PrintTail(ctx)
}
<commit_msg>improve: support --style for force call<commit_after>// Copyright (c) 2009-present, Alibaba Cloud All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package openapi

import (
	"bytes"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
	"github.com/aliyun/aliyun-cli/cli"
	"github.com/aliyun/aliyun-cli/config"
	"github.com/aliyun/aliyun-cli/i18n"
	"github.com/aliyun/aliyun-cli/meta"

	"encoding/json"
	"fmt"
	"io"
	"strings"
)

// main entrance of aliyun cli
type Commando struct {
	profile config.Profile
	library *Library
}

var hookdo = func(fn func() (*responses.CommonResponse, error)) func() (*responses.CommonResponse, error) {
	return fn
}

func NewCommando(w io.Writer, profile config.Profile) *Commando {
	r := &Commando{
		profile: profile,
	}
	r.library = NewLibrary(w, profile.Language) //TODO: load from local repository
	return r
}

func (c *Commando) InitWithCommand(cmd *cli.Command) {
	cmd.Run = c.main
	cmd.Help = c.help
	cmd.AutoComplete = c.complete
}

//
func (c *Commando) main(ctx *cli.Context, args []string) error {
	//
	// aliyun
	if len(args) == 0 {
		c.printUsage(ctx)
		return nil
	}

	// update current `Profile` with flags
	var err error
	c.profile, err = config.LoadProfileWithContext(ctx)
	if err != nil {
		return cli.NewErrorWithTip(err, "Configuration failed, use `aliyun configure` to configure it")
	}
	err = c.profile.Validate()
	if err != nil {
		return cli.NewErrorWithTip(err, "Configuration failed, use `aliyun configure` to configure it.")
	}
	i18n.SetLanguage(c.profile.Language)

	// process following commands:
	// 	 aliyun <productCode>
	//   aliyun <productCode> <method> --param1 value1
	//   aliyun <productCode> GET <path>
	productName := args[0]
	if len(args) == 1 {
		// aliyun <productCode>
		// TODO: aliyun pluginName ...
		return c.library.PrintProductUsage(productName, true)
	} else if len(args) == 2 {
		// rpc or restful call
		// aliyun <productCode> <method> --param1 value1
		product, _ := c.library.GetProduct(args[0])
		if product.Code != "" {
			if version, _ := ctx.Flags().Get("version").GetValue(); version != "" {
				if style, ok := c.library.GetStyle(productName, version); ok {
					product.ApiStyle = style
				} else {
					return cli.NewErrorWithTip(fmt.Errorf("unchecked version %s", version),
						"Please contact the customer support to get more info about API version")
				}
			}
		}
		if product.ApiStyle == "restful" {
			api, _ := c.library.GetApi(product.Code, product.Version, args[1])
			ctx.Command().Name = args[1]
			return c.processInvoke(ctx, productName, api.Method, api.PathPattern)
		}

		return c.processInvoke(ctx, productName, args[1], "")
	} else if len(args) == 3 {
		// restful call
		// aliyun <productCode> {GET|PUT|POST|DELETE} <path> --
		return c.processInvoke(ctx, productName, args[1], args[2])
	} else {
		return cli.NewErrorWithTip(fmt.Errorf("too many arguments"),
			"Use `aliyun --help` to show usage")
	}
}

func (c *Commando) processInvoke(ctx *cli.Context, productCode string, apiOrMethod string, path string) error {
	// create specific invoker
	invoker, err := c.createInvoker(ctx, productCode, apiOrMethod, path)
	if err != nil {
		return err
	}
	err = invoker.Prepare(ctx)
	if err != nil {
		return err
	}

	// process --dryrun
	if DryRunFlag(ctx.Flags()).IsAssigned() {
		invoker.getRequest().TransToAcsRequest()
		invoker.getClient().BuildRequestWithSigner(invoker.getRequest(), nil)
		cli.Printf(ctx.Writer(), "Skip invoke in dry-run mode, request is:\n------------------------------------\n%s\n",
			invoker.getRequest().String())
		return nil
	}

	// if invoke with helper
	out, err, ok := c.invokeWithHelper(invoker)

	// cli.Printf("invoker %v %v \n", invoker, reflect.TypeOf(invoker))
	if ok {
		if err != nil { // call with helper failed
			return err
		}
	} else {
		resp, err := hookdo(invoker.Call)()
		if err != nil {
			// if unmarshal failed,
			if !strings.Contains(strings.ToLower(err.Error()), "unmarshal") {
				return err
			}
		}
		out = resp.GetHttpContentString()
	}

	// if `--quiet` assigned. do not print anything
	if QuietFlag(ctx.Flags()).IsAssigned() {
		return nil
	}

	// process `--output ...`
	if filter := GetOutputFilter(ctx); filter != nil {
		out, err = filter.FilterOutput(out)
		if err != nil {
			return err
		}
	}

	out = sortJSON(out)

	cli.Println(ctx.Writer(), out)
	return nil
}

func sortJSON(content string) string {
	var v interface{}
	err := json.Unmarshal([]byte(content), &v)
	if err != nil {
		return content
	}
	buf := new(bytes.Buffer)
	encoder := json.NewEncoder(buf)
	encoder.SetEscapeHTML(false)
	encoder.SetIndent("", "\t")
	err = encoder.Encode(v)
	if err != nil {
		return content
	}
	return strings.TrimSuffix(buf.String(), "\n")
}

// invoke with helper
func (c *Commando) invokeWithHelper(invoker Invoker) (resp string, err error, ok bool) {
	if pager := GetPager(); pager != nil {
		// cli.Printf("call with pager")
		resp, err = pager.CallWith(invoker)
		ok = true
		return
	}

	if waiter := GetWaiter(); waiter != nil {
		// cli.Printf("call with waiter")
		resp, err = waiter.CallWith(invoker)
		ok = true
		return
	}

	ok = false
	return
}

//
// create invoker for specific case
// rpc: RpcInvoker, ForceRpcInvoker
// restful: RestfulInvoker
func (c *Commando) createInvoker(ctx *cli.Context, productCode string, apiOrMethod string, path string) (Invoker, error) {
	force := ForceFlag(ctx.Flags()).IsAssigned()
	basicInvoker := NewBasicInvoker(&c.profile)

	//
	// get product info
	if product, ok := c.library.GetProduct(productCode); ok {
		err := basicInvoker.Init(ctx, &product)
		if err != nil {
			return nil, err
		}
		if force {
			if version, _ := ctx.Flags().Get("version").GetValue(); version != "" {
				if style, ok := c.library.GetStyle(productCode, version); ok {
					product.ApiStyle = style
				} else {
					// 没有在 versions.json 中配置的版本可以通过 --style 自行指定
					style, _ := ctx.Flags().Get("style").GetValue()
					if style == "" {
						return nil, cli.NewErrorWithTip(fmt.Errorf("uncheked version %s", version),
							"Please use --style to speicify API sytle, rpc or restful.")
					}
					product.ApiStyle = style
				}
			}
		}
		if strings.ToLower(product.ApiStyle) == "rpc" {
			//
			// Rpc call
			if path != "" {
				return nil, cli.NewErrorWithTip(fmt.Errorf("invalid argument %s", path),
					"Use `aliyun help %s` see more information.", product.GetLowerCode())
			}
			if force {
				return &ForceRpcInvoker{
					basicInvoker,
					apiOrMethod,
				}, nil
			}
			if api, ok := c.library.GetApi(product.Code, product.Version, apiOrMethod); ok {
				return &RpcInvoker{
					basicInvoker,
					&api,
				}, nil
			}
			return nil, &InvalidApiError{apiOrMethod, &product}

		}
		//
		// Restful Call
		// aliyun cs GET /clusters
		// aliyun cs /clusters --roa GET
		ok, method, path, err := checkRestfulMethod(ctx, apiOrMethod, path)
		if err != nil {
			return nil, err
		}
		if !ok {
			return nil, cli.NewErrorWithTip(fmt.Errorf("product '%s' need restful call", product.GetLowerCode()),
				"Use `aliyun %s {GET|PUT|POST|DELETE} <path> ...`", product.GetLowerCode())
		}
		if api, ok := c.library.GetApi(product.Code, product.Version, ctx.Command().Name); ok {
			return &RestfulInvoker{
				basicInvoker,
				method,
				path,
				force,
				&api,
			}, nil
		}
		return &RestfulInvoker{
			basicInvoker,
			method,
			path,
			force,
			nil,
		}, nil

	} else {
		if !force {
			return nil, &InvalidProductError{Code: productCode, library: c.library}
		}

		//
		// force call on unknown product, use temporary product info
		product = meta.Product{
			Code: productCode,
		}
		err := basicInvoker.Init(ctx, &product)
		if err != nil {
			return nil, err
		}

		//
		// Restful Call
		// aliyun cs GET /clusters
		// aliyun cs /clusters --roa GET
		ok, method, path, err := checkRestfulMethod(ctx, apiOrMethod, path)
		if err != nil {
			return nil, err
		}
		if ok {
			return &RestfulInvoker{
				basicInvoker,
				method,
				path,
				force,
				nil,
			}, nil
			// return invoker, nil
			// c.InvokeRestful(ctx, &product, method, path)
		}
		return &ForceRpcInvoker{
			basicInvoker,
			apiOrMethod,
		}, nil
		// c.InvokeRpcForce(ctx, &product, apiOrMethod)

	}
}

//
func (c *Commando) help(ctx *cli.Context, args []string) error {
	cmd := ctx.Command()
	//if err != nil {
	//	cli.Errorf("ERROR: %s\n", err.Error())
	//	printUsage(ctx.Command(), nil)
	// } else {
	if len(args) == 0 {
		cmd.PrintHead(ctx)
		cmd.PrintUsage(ctx)
		cmd.PrintFlags(ctx)
		cmd.PrintSample(ctx)
		c.library.PrintProducts()
		cmd.PrintTail(ctx)
		return nil
	} else if len(args) == 1 {
		cmd.PrintHead(ctx)
		return c.library.PrintProductUsage(args[0], true)
		// c.PrintFlags() TODO add later
	} else if len(args) == 2 {
		cmd.PrintHead(ctx)
		return c.library.PrintApiUsage(args[0], args[1])
		// c.PrintFlags() TODO add later
	} else {
		return fmt.Errorf("too many arguments: %d", len(args))
	}
}

//
func (c *Commando) complete(ctx *cli.Context, args []string) []string {
	w := ctx.Writer()

	r := make([]string, 0)
	//
	// aliyun
	if len(args) == 0 {
		// Case insensitive strings.ToLower()
		ctx.Command().ExecuteComplete(ctx, args)
		for _, p := range c.library.GetProducts() {
			if !strings.HasPrefix(p.GetLowerCode(), strings.ToLower(ctx.Completion().Current)) {
				continue
			}
			cli.PrintfWithColor(w, cli.ProductListColor(), "%s\n", p.GetLowerCode())
		}
		return r
	}

	product, ok := c.library.GetProduct(args[0])
	if !ok {
		return r
	}

	if product.ApiStyle == "rpc" {
		if len(args) == 1 {
			for _, name := range product.ApiNames {
				if !strings.HasPrefix(strings.ToLower(name), strings.ToLower(ctx.Completion().Current)) {
					continue
				}
				cli.PrintfWithColor(w, cli.APIListColor(), "%s\n", name)
			}
			return r
		}
		api, ok := c.library.GetApi(product.Code, product.Version, args[1])
		if !ok {
			return r
		}

		api.ForeachParameters(func(s string, p meta.Parameter) {
			if strings.HasPrefix("--"+strings.ToLower(s), strings.ToLower(ctx.Completion().Current)) && !p.Hidden {
				cli.Printf(ctx.Writer(), "--%s\n", s)
			}
		})
	} else if product.ApiStyle == "restful" {
		if len(args) == 1 {
			cli.PrintfWithColor(w, cli.APIListColor(), "GET\n")
			cli.PrintfWithColor(w, cli.APIListColor(), "POST\n")
			cli.PrintfWithColor(w, cli.APIListColor(), "DELETE\n")
			cli.PrintfWithColor(w, cli.APIListColor(), "PUT\n")

			return r
		}
	}

	return r
}

func (c *Commando) printUsage(ctx *cli.Context) {
	cmd := ctx.Command()
	cmd.PrintHead(ctx)
	cmd.PrintUsage(ctx)
	cmd.PrintSubCommands(ctx)
	cmd.PrintFlags(ctx)
	cmd.PrintSample(ctx)
	//if configError != nil {
	//	cli.Printf("Configuration Invailed: %s\n", configError)
	//	cli.Printf("Run `aliyun configure` first:\n  %s\n", configureCommand.Usage)
	//}
	cmd.PrintTail(ctx)
}
<|endoftext|>


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

// Command findtypes compares checkmarks failures with the types in a
// binary to find likely matches.
//
// findtypes deduces the likely pointer/scalar map from the output of
// a checkmarks failure and compares it against the pointer/scalar
// maps of all types in a binary. The output is a scored and ranked
// list of the most closely matching types, along with their
// pointer/scalar maps.
package main

import (
	"bufio"
	"debug/dwarf"
	"debug/elf"
	"flag"
	"fmt"
	"io"
	"log"
	"math/big"
	"os"
	"regexp"
	"sort"
	"strconv"
)

const ptrSize = 8 // TODO: Get from DWARF.

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s failure binary\n", os.Args[0])
	}
	flag.Parse()
	if flag.NArg() != 2 {
		flag.Usage()
		os.Exit(1)
	}
	failPath, binPath := flag.Arg(0), flag.Arg(1)

	// Parse greyobject failure.
	failFile, err := os.Open(failPath)
	if err != nil {
		log.Fatal(err)
	}
	failure := parseGreyobject(failFile)
	failFile.Close()
	if failure.words == nil {
		log.Fatal("failed to parse failure message in %s", failPath)
	}
	fmt.Print("failure:")
	for i, known := range failure.words {
		if i%32 == 0 {
			fmt.Printf("\n\t")
		} else if i%16 == 0 {
			fmt.Printf(" ")
		}
		switch known {
		case 0:
			fmt.Print("S")
		case 1:
			fmt.Print("P")
		case 2:
			fmt.Print("?")
		}
	}
	fmt.Println()

	// Parse binary.
	f, err := elf.Open(binPath)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	d, err := f.DWARF()
	if err != nil {
		log.Fatal(err)
	}

	// Find all of the types.
	type comparison struct {
		ti    *typeInfo
		score float64
	}
	var results []comparison
	r := d.Reader()
	for {
		ent, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if ent == nil {
			break
		}

		if ent.Tag != dwarf.TagTypedef {
			continue
		}

		name, ok := ent.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}
		base, ok := ent.Val(dwarf.AttrType).(dwarf.Offset)
		if !ok {
			log.Printf("type %s has unknown underlying type", name)
			continue
		}

		typ, err := d.Type(base)
		if err != nil {
			log.Fatal(err)
		}
		ti := &typeInfo{name: name, words: int(typ.Size()+ptrSize-1) / ptrSize}
		ti.processType(typ, 0)
		if ti.incomplete {
			log.Printf("ignoring incomplete type %s", ti.name)
			continue
		}

		score := failure.compare(ti)
		results = append(results, comparison{ti, score})
	}

	// Print results.
	sort.Slice(results, func(i, j int) bool {
		return results[i].score < results[j].score
	})
	if len(results) > 10 {
		results = results[len(results)-10:]
	}
	for _, c := range results {
		fmt.Print(c.score, " ", c.ti.name)
		failure.printCompare(c.ti)
	}
}

type typeInfo struct {
	name       string
	ptr        big.Int
	words      int
	incomplete bool
}

func (t *typeInfo) processType(typ dwarf.Type, offset int) {
	switch typ := typ.(type) {
	case *dwarf.ArrayType:
		if typ.Count < 0 || typ.StrideBitSize > 0 {
			t.incomplete = true
			return
		}
		for i := 0; i < int(typ.Count); i++ {
			// TODO: Alignment?
			t.processType(typ.Type, offset+i*int(typ.Type.Size()))
		}

	case *dwarf.StructType:
		if typ.Kind == "union" {
			t.incomplete = true
			log.Printf("encountered union")
			return
		}
		if typ.Incomplete {
			t.incomplete = true
			return
		}
		for _, f := range typ.Field {
			if f.BitSize != 0 {
				t.incomplete = true
				log.Printf("encountered bit field")
				return
			}
			t.processType(f.Type, offset+int(f.ByteOffset))
		}

	case *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType,
		*dwarf.EnumType, *dwarf.FloatType, *dwarf.IntType,
		*dwarf.UcharType, *dwarf.UintType:
		// Nothing

	case *dwarf.PtrType:
		if typ.Size() != ptrSize {
			log.Fatalf("funny PtrSize size: %d", typ.Size())
		}
		if offset%ptrSize != 0 {
			log.Fatal("unaligned pointer")
		}
		t.ptr.SetBit(&t.ptr, offset/ptrSize, 1)

	case *dwarf.FuncType:
		// Size is -1.
		if offset%ptrSize != 0 {
			log.Fatal("unaligned pointer")
		}
		t.ptr.SetBit(&t.ptr, offset/ptrSize, 1)

	case *dwarf.QualType:
		t.processType(typ.Type, offset)

	case *dwarf.TypedefType:
		t.processType(typ.Type, offset)

	case *dwarf.UnspecifiedType:
		t.incomplete = true
		log.Printf("encountered UnspecifiedType")

	case *dwarf.VoidType:
		t.incomplete = true
		log.Printf("encountered VoidType")
	}
}

type greyobjectFailure struct {
	words []int // 0 scalar, 1 pointer, 2 unknown
}

var (
	spanRe = regexp.MustCompile(`base=.* s\.elemsize=(\d+)`)
	baseRe = regexp.MustCompile(`\*\(base\+(\d+)\) = (0x[0-9a-f]+)$`)
)

func parseGreyobject(r io.Reader) *greyobjectFailure {
	var failure greyobjectFailure
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		l := scanner.Text()

		subs := spanRe.FindStringSubmatch(l)
		if subs != nil {
			elemsize, _ := strconv.Atoi(subs[1])
			failure.words = make([]int, elemsize/ptrSize)
			for i := range failure.words {
				failure.words[i] = 2
			}
			continue
		}

		subs = baseRe.FindStringSubmatch(l)
		if subs == nil {
			continue
		}

		offset, _ := strconv.ParseInt(subs[1], 0, 64)
		val, _ := strconv.ParseInt(subs[2], 0, 64)

		known := 2
		if val>>32 == 0xc4 {
			known = 1
		} else if val != 0 {
			known = 0
		}

		failure.words[offset/ptrSize] = known
	}
	if err := scanner.Err(); err != nil {
		log.Fatal("reading greyobject output:", err)
	}
	return &failure
}

func (f *greyobjectFailure) compare(ti *typeInfo) float64 {
	score, denom := 0.0, 0.0
	for i, known := range f.words {
		if known == 2 {
			continue
		}
		denom++
		if ti.words < i {
			score -= 1
		} else if int(ti.ptr.Bit(i)) == known {
			score += 1
		} else {
			score -= 1
		}
	}
	if ti.words > len(f.words) {
		score -= float64(ti.words - len(f.words))
	}
	return score / denom
}

func (f *greyobjectFailure) printCompare(ti *typeInfo) {
	l := ti.words
	if len(f.words) > l {
		l = len(f.words)
	}
	for i := 0; i < l; i++ {
		if i%32 == 0 {
			fmt.Printf("\n\t")
		} else if i%16 == 0 {
			fmt.Printf(" ")
		}

		have := int(ti.ptr.Bit(i))

		var want int
		if i < len(f.words) {
			want = f.words[i]
		} else {
			want = 1 - have
		}

		switch {
		case want == 2:
			fmt.Print("?")
		case have == want:
			if have == 0 {
				fmt.Print("S")
			} else {
				fmt.Print("P")
			}
		case have != want:
			if have == 0 {
				fmt.Print("s")
			} else {
				fmt.Print("p")
			}
		}
	}
	fmt.Println()
}
<commit_msg>findtypes: fix parsing of <== line<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Command findtypes compares checkmarks failures with the types in a
// binary to find likely matches.
//
// findtypes deduces the likely pointer/scalar map from the output of
// a checkmarks failure and compares it against the pointer/scalar
// maps of all types in a binary. The output is a scored and ranked
// list of the most closely matching types, along with their
// pointer/scalar maps.
package main

import (
	"bufio"
	"debug/dwarf"
	"debug/elf"
	"flag"
	"fmt"
	"io"
	"log"
	"math/big"
	"os"
	"regexp"
	"sort"
	"strconv"
)

const ptrSize = 8 // TODO: Get from DWARF.

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s failure binary\n", os.Args[0])
	}
	flag.Parse()
	if flag.NArg() != 2 {
		flag.Usage()
		os.Exit(1)
	}
	failPath, binPath := flag.Arg(0), flag.Arg(1)

	// Parse greyobject failure.
	failFile, err := os.Open(failPath)
	if err != nil {
		log.Fatal(err)
	}
	failure := parseGreyobject(failFile)
	failFile.Close()
	if failure.words == nil {
		log.Fatal("failed to parse failure message in %s", failPath)
	}
	fmt.Print("failure:")
	for i, known := range failure.words {
		if i%32 == 0 {
			fmt.Printf("\n\t")
		} else if i%16 == 0 {
			fmt.Printf(" ")
		}
		switch known {
		case 0:
			fmt.Print("S")
		case 1:
			fmt.Print("P")
		case 2:
			fmt.Print("?")
		}
	}
	fmt.Println()

	// Parse binary.
	f, err := elf.Open(binPath)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	d, err := f.DWARF()
	if err != nil {
		log.Fatal(err)
	}

	// Find all of the types.
	type comparison struct {
		ti    *typeInfo
		score float64
	}
	var results []comparison
	r := d.Reader()
	for {
		ent, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if ent == nil {
			break
		}

		if ent.Tag != dwarf.TagTypedef {
			continue
		}

		name, ok := ent.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}
		base, ok := ent.Val(dwarf.AttrType).(dwarf.Offset)
		if !ok {
			log.Printf("type %s has unknown underlying type", name)
			continue
		}

		typ, err := d.Type(base)
		if err != nil {
			log.Fatal(err)
		}
		ti := &typeInfo{name: name, words: int(typ.Size()+ptrSize-1) / ptrSize}
		ti.processType(typ, 0)
		if ti.incomplete {
			log.Printf("ignoring incomplete type %s", ti.name)
			continue
		}

		score := failure.compare(ti)
		results = append(results, comparison{ti, score})
	}

	// Print results.
	sort.Slice(results, func(i, j int) bool {
		return results[i].score < results[j].score
	})
	if len(results) > 10 {
		results = results[len(results)-10:]
	}
	for _, c := range results {
		fmt.Print(c.score, " ", c.ti.name)
		failure.printCompare(c.ti)
	}
}

type typeInfo struct {
	name       string
	ptr        big.Int
	words      int
	incomplete bool
}

func (t *typeInfo) processType(typ dwarf.Type, offset int) {
	switch typ := typ.(type) {
	case *dwarf.ArrayType:
		if typ.Count < 0 || typ.StrideBitSize > 0 {
			t.incomplete = true
			return
		}
		for i := 0; i < int(typ.Count); i++ {
			// TODO: Alignment?
			t.processType(typ.Type, offset+i*int(typ.Type.Size()))
		}

	case *dwarf.StructType:
		if typ.Kind == "union" {
			t.incomplete = true
			log.Printf("encountered union")
			return
		}
		if typ.Incomplete {
			t.incomplete = true
			return
		}
		for _, f := range typ.Field {
			if f.BitSize != 0 {
				t.incomplete = true
				log.Printf("encountered bit field")
				return
			}
			t.processType(f.Type, offset+int(f.ByteOffset))
		}

	case *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType,
		*dwarf.EnumType, *dwarf.FloatType, *dwarf.IntType,
		*dwarf.UcharType, *dwarf.UintType:
		// Nothing

	case *dwarf.PtrType:
		if typ.Size() != ptrSize {
			log.Fatalf("funny PtrSize size: %d", typ.Size())
		}
		if offset%ptrSize != 0 {
			log.Fatal("unaligned pointer")
		}
		t.ptr.SetBit(&t.ptr, offset/ptrSize, 1)

	case *dwarf.FuncType:
		// Size is -1.
		if offset%ptrSize != 0 {
			log.Fatal("unaligned pointer")
		}
		t.ptr.SetBit(&t.ptr, offset/ptrSize, 1)

	case *dwarf.QualType:
		t.processType(typ.Type, offset)

	case *dwarf.TypedefType:
		t.processType(typ.Type, offset)

	case *dwarf.UnspecifiedType:
		t.incomplete = true
		log.Printf("encountered UnspecifiedType")

	case *dwarf.VoidType:
		t.incomplete = true
		log.Printf("encountered VoidType")
	}
}

type greyobjectFailure struct {
	words []int // 0 scalar, 1 pointer, 2 unknown
}

var (
	spanRe = regexp.MustCompile(`base=.* s\.elemsize=(\d+)`)
	baseRe = regexp.MustCompile(`\*\(base\+(\d+)\) = (0x[0-9a-f]+)( <==)?$`)
)

func parseGreyobject(r io.Reader) *greyobjectFailure {
	var failure greyobjectFailure
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		l := scanner.Text()

		subs := spanRe.FindStringSubmatch(l)
		if subs != nil {
			elemsize, _ := strconv.Atoi(subs[1])
			failure.words = make([]int, elemsize/ptrSize)
			for i := range failure.words {
				failure.words[i] = 2
			}
			continue
		}

		subs = baseRe.FindStringSubmatch(l)
		if subs == nil {
			continue
		}

		offset, _ := strconv.ParseInt(subs[1], 0, 64)
		val, _ := strconv.ParseInt(subs[2], 0, 64)

		// TODO: This only recognizes heap pointers. Maybe
		// look at the binary to figure out reasonable global
		// pointers?
		known := 2
		if val>>32 == 0xc4 {
			known = 1
		} else if val != 0 {
			known = 0
		}

		failure.words[offset/ptrSize] = known
	}
	if err := scanner.Err(); err != nil {
		log.Fatal("reading greyobject output:", err)
	}
	return &failure
}

func (f *greyobjectFailure) compare(ti *typeInfo) float64 {
	score, denom := 0.0, 0.0
	for i, known := range f.words {
		if known == 2 {
			continue
		}
		denom++
		if ti.words < i {
			score -= 1
		} else if int(ti.ptr.Bit(i)) == known {
			score += 1
		} else {
			score -= 1
		}
	}
	if ti.words > len(f.words) {
		score -= float64(ti.words - len(f.words))
	}
	return score / denom
}

func (f *greyobjectFailure) printCompare(ti *typeInfo) {
	l := ti.words
	if len(f.words) > l {
		l = len(f.words)
	}
	for i := 0; i < l; i++ {
		if i%32 == 0 {
			fmt.Printf("\n\t")
		} else if i%16 == 0 {
			fmt.Printf(" ")
		}

		have := int(ti.ptr.Bit(i))

		var want int
		if i < len(f.words) {
			want = f.words[i]
		} else {
			want = 1 - have
		}

		switch {
		case want == 2:
			fmt.Print("?")
		case have == want:
			if have == 0 {
				fmt.Print("S")
			} else {
				fmt.Print("P")
			}
		case have != want:
			if have == 0 {
				fmt.Print("s")
			} else {
				fmt.Print("p")
			}
		}
	}
	fmt.Println()
}
<|endoftext|>


<commit_before>package inbloom

import (
	"bytes"
	"encoding/gob"
	"errors"
	"hash"
	"hash/fnv"
	"io"
	"math"
)

type BloomFilter struct {
	vector         []byte
	baseHashFn     hash.Hash64
	numberOfHashes uint64
}

func (self *BloomFilter) Add(obj *[]byte) error {

	hashValues, err := self.getHashVector(obj)

	for i := 0; i < len(hashValues); i++ {
		hashVal := hashValues[i]
		self.vector[hashVal] = 1
	}
	return err
}

func (self *BloomFilter) getHashVector(obj *[]byte) ([]uint64, error) {

	defer self.baseHashFn.Reset()

	_, e1 := self.baseHashFn.Write(*obj)

	if e1 != nil {
		empty := make([]uint64, 0)
		return empty, errors.New("failed to add object to filter")
	}

	seed1 := self.baseHashFn.Sum64()
	// simulate output of two hash functions that will serve as base hashes for simulating the output of n hash functions
	upperBits := seed1 >> 32 << 32
	lowerBits := seed1 >> 32 << 32
	hashValues := make([]uint64, self.numberOfHashes)
	for i := uint64(0); i < self.numberOfHashes; i++ {

		h := (upperBits + lowerBits*i) % self.numberOfHashes
		hashValues[i] = h
	}

	return hashValues, nil
}

func (self *BloomFilter) Test(obj *[]byte) (bool, error) {

	hashVales, e := self.getHashVector(obj)

	for i := 0; i < len(hashVales); i++ {
		hashVal := hashVales[i]
		if self.vector[hashVal] == 0 {
			return false, e
		}
	}

	return true, e
}

//NewFilter creates a new BloomFilter. p is the error rate
//and n is the estimated number of elements that will be handled by the filter
func NewFilter(p float64, n int64) BloomFilter {

	/*
		Given:

		n: how many items you expect to have in your filter (e.g. 216,553)
		p: your acceptable false positive rate {0..1} (e.g. 0.01 → 1%)
		we want to calculate:

		m: the number of bits needed in the bloom filter
		k: the number of hash functions we should apply
		The formulas:

		m = -n*ln(p) / (ln(2)^2) the number of bits
		k = m/n * ln(2) the number of hash functions

	*/

	m := -float64(n) * math.Log(p) / math.Pow(math.Ln2, 2)
	k := uint64(m / float64(n) * math.Ln2)

	return BloomFilter{vector: make([]byte, int64(m)),
		baseHashFn:     fnv.New64(),
		numberOfHashes: k}
}

func Inflate(reader io.Reader) *BloomFilter {

	var filter BloomFilter
	dec := gob.NewDecoder(reader)
	dec.Decode(&filter)
	return &filter
}

func Deflate(filter *BloomFilter) []byte {

	var buffer bytes.Buffer
	enc := gob.NewEncoder(&buffer)
	enc.Encode(filter)

	return buffer.Bytes()
}
<commit_msg>added documentation to exported members<commit_after>package inbloom

import (
	"bytes"
	"encoding/gob"
	"errors"
	"hash"
	"hash/fnv"
	"io"
	"math"
)

//BloomFilter is a space-efficient probabilistic data structure, conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set.
type BloomFilter struct {
	vector         []byte
	baseHashFn     hash.Hash64
	numberOfHashes uint64
}

//Add an object to the set
func (filter *BloomFilter) Add(obj *[]byte) error {

	hashValues, err := filter.getHashVector(obj)

	for i := 0; i < len(hashValues); i++ {
		hashVal := hashValues[i]
		filter.vector[hashVal] = 1
	}
	return err
}

func (filter *BloomFilter) getHashVector(obj *[]byte) ([]uint64, error) {

	defer filter.baseHashFn.Reset()

	_, e1 := filter.baseHashFn.Write(*obj)

	if e1 != nil {
		empty := make([]uint64, 0)
		return empty, errors.New("failed to add object to filter")
	}

	seed1 := filter.baseHashFn.Sum64()
	// simulate output of two hash functions that will serve as base hashes for simulating the output of n hash functions
	upperBits := seed1 >> 32 << 32
	lowerBits := seed1 >> 32 << 32
	hashValues := make([]uint64, filter.numberOfHashes)
	for i := uint64(0); i < filter.numberOfHashes; i++ {

		h := (upperBits + lowerBits*i) % filter.numberOfHashes
		hashValues[i] = h
	}

	return hashValues, nil
}

//Test if an element is in the set
func (filter *BloomFilter) Test(obj *[]byte) (bool, error) {

	hashVales, e := filter.getHashVector(obj)

	for i := 0; i < len(hashVales); i++ {
		hashVal := hashVales[i]
		if filter.vector[hashVal] == 0 {
			return false, e
		}
	}

	return true, e
}

//NewFilter creates a new BloomFilter. p is the error rate
//and n is the estimated number of elements that will be handled by the filter
func NewFilter(p float64, n int64) BloomFilter {

	/*
		Given:

		n: how many items you expect to have in your filter (e.g. 216,553)
		p: your acceptable false positive rate {0..1} (e.g. 0.01 → 1%)
		we want to calculate:

		m: the number of bits needed in the bloom filter
		k: the number of hash functions we should apply
		The formulas:

		m = -n*ln(p) / (ln(2)^2) the number of bits
		k = m/n * ln(2) the number of hash functions

	*/

	m := -float64(n) * math.Log(p) / math.Pow(math.Ln2, 2)
	k := uint64(m / float64(n) * math.Ln2)

	return BloomFilter{vector: make([]byte, int64(m)),
		baseHashFn:     fnv.New64(),
		numberOfHashes: k}
}

//Inflate a deflated BloomFilter from the io.Reader
func Inflate(reader io.Reader) *BloomFilter {

	var filter BloomFilter
	dec := gob.NewDecoder(reader)
	dec.Decode(&filter)
	return &filter
}

//Deflate an instance of a BloomFilter into a byte array
func Deflate(filter *BloomFilter) []byte {

	var buffer bytes.Buffer
	enc := gob.NewEncoder(&buffer)
	enc.Encode(filter)

	return buffer.Bytes()
}
<|endoftext|>


<commit_before>// Package board holds the struct and related methods that model the game board
package board

import (
	"github.com/svera/acquire/interfaces"
	"sort"
)

var letters = [9]string{"A", "B", "C", "D", "E", "F", "G", "H", "I"}

// Board maps tiles on every position on board
type Board struct {
	grid *[13]map[string]interfaces.Owner
}

type sortableCorporations []interfaces.Corporation

func (s sortableCorporations) Len() int           { return len(s) }
func (s sortableCorporations) Less(i, j int) bool { return s[i].Size() < s[j].Size() }
func (s sortableCorporations) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

// New initialises and returns a Board instance
func New() *Board {
	brd := Board{
		grid: new([13]map[string]interfaces.Owner),
	}

	for number := 1; number < 13; number++ {
		brd.grid[number] = make(map[string]interfaces.Owner)
		for _, letter := range letters {
			brd.grid[number][letter] = Empty{}
		}
	}

	return &brd
}

// Cell returns a board cell content
func (b *Board) Cell(number int, letter string) interfaces.Owner {
	return b.grid[number][letter]
}

// TileFoundCorporation checks if the passed tile founds a new corporation, returns a slice of tiles
// composing this corporation
func (b *Board) TileFoundCorporation(t interfaces.Tile) (bool, []interfaces.Tile) {
	var newCorporationTiles []interfaces.Tile
	adjacent := b.adjacentTiles(t.Number(), t.Letter())
	for _, adjacentTile := range adjacent {
		if adjacentTile.Type() == "corporation" {
			return false, []interfaces.Tile{}
		}
		newCorporationTiles = append(newCorporationTiles, adjacentTile.(interfaces.Tile))
	}
	if len(newCorporationTiles) > 0 {
		newCorporationTiles = append(newCorporationTiles, t)
		return true, newCorporationTiles
	}
	return false, newCorporationTiles
}

// TileMergeCorporations checks if the passed tile merges two or more corporations, returns a map of
// corporations categorized between "acquirer" and "defunct"
func (b *Board) TileMergeCorporations(t interfaces.Tile) (bool, map[string][]interfaces.Corporation) {
	var corporations []interfaces.Corporation

	adjacent := b.adjacentCorporationTiles(t.Number(), t.Letter())
	for _, adjacentCell := range adjacent {
		corp, _ := adjacentCell.(interfaces.Corporation)
		corporations = append(corporations, corp)
	}
	if len(corporations) > 1 {
		return true, categorizeMerge(corporations)
	}
	return false, map[string][]interfaces.Corporation{}
}

// Distributes the corporation in a merge between acquirers and defuncts
func categorizeMerge(corporations []interfaces.Corporation) map[string][]interfaces.Corporation {
	var sortedCorps sortableCorporations
	sortedCorps = corporations
	sort.Sort(sort.Reverse(sortedCorps))

	merge := map[string][]interfaces.Corporation{
		"acquirer": []interfaces.Corporation{sortedCorps[0]},
		"defunct":  []interfaces.Corporation{},
	}

	for i := 1; i < len(sortedCorps); i++ {
		if sortedCorps[i].Size() == sortedCorps[0].Size() {
			merge["acquirer"] = append(merge["acquirer"], sortedCorps[i])
		} else {
			merge["defunct"] = append(merge["defunct"], sortedCorps[i])
		}
	}

	return merge
}

// TileGrowCorporation checks if the passed tile grows a corporation.
// Returns true if that's the case, the tiles to append to the corporation and
// the ID of the corporation which grows
func (b *Board) TileGrowCorporation(tl interfaces.Tile) (bool, []interfaces.Tile, interfaces.Corporation) {
	tilesToAppend := []interfaces.Tile{tl}
	var nullCorporation interfaces.Corporation
	corporationToGrow := nullCorporation
	adjacent := b.adjacentTiles(tl.Number(), tl.Letter())
	for _, adjacentCell := range adjacent {
		if adjacentCell.Type() != "unincorporated" {
			if corporationToGrow != nullCorporation {
				return false, []interfaces.Tile{}, nullCorporation
			}
			corporationToGrow = adjacentCell.(interfaces.Corporation)
		} else {
			tilesToAppend = append(tilesToAppend, adjacentCell.(interfaces.Tile))
		}
	}
	if corporationToGrow == nullCorporation {
		return false, []interfaces.Tile{}, nullCorporation
	}
	return true, tilesToAppend, corporationToGrow
}

// PutTile puts the passed tile on the board
func (b *Board) PutTile(t interfaces.Tile) interfaces.Board {
	b.grid[t.Number()][t.Letter()] = t
	return b
}

// AdjacentCells returns all cells adjacent to the passed one
func (b *Board) AdjacentCells(number int, letter string) []interfaces.Owner {
	var adjacent []interfaces.Owner

	if letter > "A" {
		adjacent = append(adjacent, b.grid[number][previousLetter(letter)])
	}
	if letter < "I" {
		adjacent = append(adjacent, b.grid[number][nextLetter(letter)])
	}
	if number > 1 {
		adjacent = append(adjacent, b.grid[number-1][letter])
	}
	if number < 12 {
		adjacent = append(adjacent, b.grid[number+1][letter])
	}
	return adjacent
}

func (b *Board) adjacentCellsWithFilter(number int, letter string, filter func(interfaces.Owner) bool) []interfaces.Owner {
	var adjacentFilteredCells []interfaces.Owner
	adjacent := b.AdjacentCells(number, letter)

	for _, adjacentCell := range adjacent {
		if filter(adjacentCell) {
			adjacentFilteredCells = append(adjacentFilteredCells, adjacentCell)
		}
	}
	return adjacentFilteredCells
}

func (b *Board) adjacentTiles(number int, letter string) []interfaces.Owner {
	return b.adjacentCellsWithFilter(
		number,
		letter,
		func(o interfaces.Owner) bool {
			if o.Type() != "empty" {
				return true
			}
			return false
		},
	)
}

func (b *Board) adjacentCorporationTiles(number int, letter string) []interfaces.Owner {
	return b.adjacentCellsWithFilter(
		number,
		letter,
		func(o interfaces.Owner) bool {
			if o.Type() == "corporation" {
				return true
			}
			return false
		},
	)
}

func adjacentLetter(letter string, delta int) string {
	for i, currentLetter := range letters {
		if currentLetter == letter {
			return letters[i+delta]
		}
	}
	return ""
}

func previousLetter(letter string) string {
	return adjacentLetter(letter, -1)
}

func nextLetter(letter string) string {
	return adjacentLetter(letter, +1)
}

// SetOwner sets tiles on board as belonging to the passed corporation
func (b *Board) SetOwner(cp interfaces.Corporation, tiles []interfaces.Tile) interfaces.Board {
	for _, tl := range tiles {
		b.grid[tl.Number()][tl.Letter()] = cp
	}
	return b
}

// ChangeOwner changes ownership of tiles belonging to oldOrder to newOrder
func (b *Board) ChangeOwner(oldOwner interfaces.Corporation, newOwner interfaces.Corporation) interfaces.Board {
	for number := 1; number < 13; number++ {
		for _, letter := range letters {
			if b.grid[number][letter] == oldOwner {
				b.grid[number][letter] = newOwner
			}
		}
	}
	return b
}
<commit_msg>Removed useless lines<commit_after>// Package board holds the struct and related methods that model the game board
package board

import (
	"github.com/svera/acquire/interfaces"
	"sort"
)

var letters = [9]string{"A", "B", "C", "D", "E", "F", "G", "H", "I"}

// Board maps tiles on every position on board
type Board struct {
	grid *[13]map[string]interfaces.Owner
}

type sortableCorporations []interfaces.Corporation

func (s sortableCorporations) Len() int           { return len(s) }
func (s sortableCorporations) Less(i, j int) bool { return s[i].Size() < s[j].Size() }
func (s sortableCorporations) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

// New initialises and returns a Board instance
func New() *Board {
	brd := Board{
		grid: new([13]map[string]interfaces.Owner),
	}

	for number := 1; number < 13; number++ {
		brd.grid[number] = make(map[string]interfaces.Owner)
		for _, letter := range letters {
			brd.grid[number][letter] = Empty{}
		}
	}

	return &brd
}

// Cell returns a board cell content
func (b *Board) Cell(number int, letter string) interfaces.Owner {
	return b.grid[number][letter]
}

// TileFoundCorporation checks if the passed tile founds a new corporation, returns a slice of tiles
// composing this corporation
func (b *Board) TileFoundCorporation(t interfaces.Tile) (bool, []interfaces.Tile) {
	var newCorporationTiles []interfaces.Tile
	adjacent := b.adjacentTiles(t.Number(), t.Letter())
	for _, adjacentTile := range adjacent {
		if adjacentTile.Type() == "corporation" {
			return false, []interfaces.Tile{}
		}
		newCorporationTiles = append(newCorporationTiles, adjacentTile.(interfaces.Tile))
	}
	if len(newCorporationTiles) > 0 {
		newCorporationTiles = append(newCorporationTiles, t)
		return true, newCorporationTiles
	}
	return false, newCorporationTiles
}

// TileMergeCorporations checks if the passed tile merges two or more corporations, returns a map of
// corporations categorized between "acquirer" and "defunct"
func (b *Board) TileMergeCorporations(t interfaces.Tile) (bool, map[string][]interfaces.Corporation) {
	var corporations []interfaces.Corporation

	adjacent := b.adjacentCorporationTiles(t.Number(), t.Letter())
	for _, adjacentCell := range adjacent {
		corp, _ := adjacentCell.(interfaces.Corporation)
		corporations = append(corporations, corp)
	}
	if len(corporations) > 1 {
		return true, categorizeMerge(corporations)
	}
	return false, map[string][]interfaces.Corporation{}
}

// Distributes the corporation in a merge between acquirers and defuncts
func categorizeMerge(corporations []interfaces.Corporation) map[string][]interfaces.Corporation {
	sort.Sort(sort.Reverse(corporations))

	merge := map[string][]interfaces.Corporation{
		"acquirer": []interfaces.Corporation{corporations[0]},
		"defunct":  []interfaces.Corporation{},
	}

	for i := 1; i < len(corporations); i++ {
		if corporations[i].Size() == corporations[0].Size() {
			merge["acquirer"] = append(merge["acquirer"], corporations[i])
		} else {
			merge["defunct"] = append(merge["defunct"], corporations[i])
		}
	}

	return merge
}

// TileGrowCorporation checks if the passed tile grows a corporation.
// Returns true if that's the case, the tiles to append to the corporation and
// the ID of the corporation which grows
func (b *Board) TileGrowCorporation(tl interfaces.Tile) (bool, []interfaces.Tile, interfaces.Corporation) {
	tilesToAppend := []interfaces.Tile{tl}
	var nullCorporation interfaces.Corporation
	corporationToGrow := nullCorporation
	adjacent := b.adjacentTiles(tl.Number(), tl.Letter())
	for _, adjacentCell := range adjacent {
		if adjacentCell.Type() != "unincorporated" {
			if corporationToGrow != nullCorporation {
				return false, []interfaces.Tile{}, nullCorporation
			}
			corporationToGrow = adjacentCell.(interfaces.Corporation)
		} else {
			tilesToAppend = append(tilesToAppend, adjacentCell.(interfaces.Tile))
		}
	}
	if corporationToGrow == nullCorporation {
		return false, []interfaces.Tile{}, nullCorporation
	}
	return true, tilesToAppend, corporationToGrow
}

// PutTile puts the passed tile on the board
func (b *Board) PutTile(t interfaces.Tile) interfaces.Board {
	b.grid[t.Number()][t.Letter()] = t
	return b
}

// AdjacentCells returns all cells adjacent to the passed one
func (b *Board) AdjacentCells(number int, letter string) []interfaces.Owner {
	var adjacent []interfaces.Owner

	if letter > "A" {
		adjacent = append(adjacent, b.grid[number][previousLetter(letter)])
	}
	if letter < "I" {
		adjacent = append(adjacent, b.grid[number][nextLetter(letter)])
	}
	if number > 1 {
		adjacent = append(adjacent, b.grid[number-1][letter])
	}
	if number < 12 {
		adjacent = append(adjacent, b.grid[number+1][letter])
	}
	return adjacent
}

func (b *Board) adjacentCellsWithFilter(number int, letter string, filter func(interfaces.Owner) bool) []interfaces.Owner {
	var adjacentFilteredCells []interfaces.Owner
	adjacent := b.AdjacentCells(number, letter)

	for _, adjacentCell := range adjacent {
		if filter(adjacentCell) {
			adjacentFilteredCells = append(adjacentFilteredCells, adjacentCell)
		}
	}
	return adjacentFilteredCells
}

func (b *Board) adjacentTiles(number int, letter string) []interfaces.Owner {
	return b.adjacentCellsWithFilter(
		number,
		letter,
		func(o interfaces.Owner) bool {
			if o.Type() != "empty" {
				return true
			}
			return false
		},
	)
}

func (b *Board) adjacentCorporationTiles(number int, letter string) []interfaces.Owner {
	return b.adjacentCellsWithFilter(
		number,
		letter,
		func(o interfaces.Owner) bool {
			if o.Type() == "corporation" {
				return true
			}
			return false
		},
	)
}

func adjacentLetter(letter string, delta int) string {
	for i, currentLetter := range letters {
		if currentLetter == letter {
			return letters[i+delta]
		}
	}
	return ""
}

func previousLetter(letter string) string {
	return adjacentLetter(letter, -1)
}

func nextLetter(letter string) string {
	return adjacentLetter(letter, +1)
}

// SetOwner sets tiles on board as belonging to the passed corporation
func (b *Board) SetOwner(cp interfaces.Corporation, tiles []interfaces.Tile) interfaces.Board {
	for _, tl := range tiles {
		b.grid[tl.Number()][tl.Letter()] = cp
	}
	return b
}

// ChangeOwner changes ownership of tiles belonging to oldOrder to newOrder
func (b *Board) ChangeOwner(oldOwner interfaces.Corporation, newOwner interfaces.Corporation) interfaces.Board {
	for number := 1; number < 13; number++ {
		for _, letter := range letters {
			if b.grid[number][letter] == oldOwner {
				b.grid[number][letter] = newOwner
			}
		}
	}
	return b
}
<|endoftext|>