<commit_before>package game

import (
	"time"

	"github.com/ivan1993spb/snake-server/engine"
	"github.com/ivan1993spb/snake-server/playground"
)

type World struct {
	pg       *playground.Playground
	chEvents chan *Event
	stop     chan struct{}
	timeout  time.Duration
}

func NewWorld(pg *playground.Playground, buffer uint, timeout time.Duration) *World {
	return &World{
		pg:       pg,
		chEvents: make(chan *Event, buffer),
		stop:     make(chan struct{}, 0),
		timeout:  timeout,
	}
}

// TODO: Create func ListenEvents with out channel <-chan *Event to provide multi listeners

func (w *World) event(event *Event) {
	go func() {
		var timer = time.NewTimer(w.timeout)
		defer timer.Stop()
		select {
		case w.chEvents <- event:
		case <-w.stop:
		case <-timer.C:
		}
	}()
}

func (w *World) Stop() {
	close(w.stop)
	close(w.chEvents)
}

func (w *World) ObjectExists(object interface{}) bool {
	return w.pg.ObjectExists(object)
}

func (w *World) LocationExists(location engine.Location) bool {
	return w.pg.LocationExists(location)
}

func (w *World) EntityExists(object interface{}, location engine.Location) bool {
	return w.pg.EntityExists(object, location)
}

func (w *World) GetObjectByLocation(location engine.Location) interface{} {
	return w.pg.GetObjectByLocation(location)
}

func (w *World) GetObjectByDot(dot *engine.Dot) interface{} {
	return w.pg.GetObjectByDot(dot)
}

func (w *World) GetEntityByDot(dot *engine.Dot) (interface{}, engine.Location) {
	return w.pg.GetEntityByDot(dot)
}

func (w *World) GetObjectsByDots(dots []*engine.Dot) []interface{} {
	return w.pg.GetObjectsByDots(dots)
}

func (w *World) CreateObject(object interface{}, location engine.Location) error {
	if err := w.pg.CreateObject(object, location); err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return nil
}

func (w *World) CreateObjectAvailableDots(object interface{}, location engine.Location) (engine.Location, *playground.ErrCreateObjectAvailableDots) {
	location, err := w.pg.CreateObjectAvailableDots(object, location)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return location, err
}

func (w *World) DeleteObject(object interface{}, location engine.Location) *playground.ErrDeleteObject {
	err := w.pg.DeleteObject(object, location)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return err
	}
	w.event(&Event{
		Type:    EventTypeObjectDelete,
		Payload: object,
	})
	return err
}

func (w *World) UpdateObject(object interface{}, old, new engine.Location) *playground.ErrUpdateObject {
	if err := w.pg.UpdateObject(object, old, new); err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return err
	}
	w.event(&Event{
		Type:    EventTypeObjectUpdate,
		Payload: object,
	})
	return nil
}

func (w *World) UpdateObjectAvailableDots(object interface{}, old, new engine.Location) (engine.Location, *playground.ErrUpdateObjectAvailableDots) {
	location, err := w.pg.UpdateObjectAvailableDots(object, old, new)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectUpdate,
		Payload: object,
	})
	return location, err
}

func (w *World) CreateObjectRandomDot(object interface{}) (engine.Location, error) {
	location, err := w.pg.CreateObjectRandomDot(object)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return location, err
}

func (w *World) CreateObjectRandomRect(object interface{}, rw, rh uint8) (engine.Location, error) {
	location, err := w.pg.CreateObjectRandomRect(object, rw, rh)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return location, err
}

func (w *World) Navigate(dot *engine.Dot, dir engine.Direction, dis uint8) (*engine.Dot, error) {
	return w.pg.Navigate(dot, dir, dis)
}

func (w *World) Size() uint16 {
	return w.pg.Size()
}

func (w *World) Width() uint8 {
	return w.pg.Width()
}

func (w *World) Height() uint8 {
	return w.pg.Height()
}
<commit_msg>Create default buffer size and timeout for world object<commit_after>package game

import (
	"time"

	"github.com/ivan1993spb/snake-server/engine"
	"github.com/ivan1993spb/snake-server/playground"
)

const worldEventsBufferSize = 512

const worldEventsTimeout = time.Second

type World struct {
	pg       *playground.Playground
	chEvents chan *Event
	stop     chan struct{}
	timeout  time.Duration
}

func NewWorld(pg *playground.Playground) *World {
	return &World{
		pg:       pg,
		chEvents: make(chan *Event, worldEventsBufferSize),
		stop:     make(chan struct{}, 0),
		timeout:  worldEventsTimeout,
	}
}

// TODO: Create func ListenEvents with out channel <-chan *Event to provide multi listeners

func (w *World) event(event *Event) {
	go func() {
		var timer = time.NewTimer(w.timeout)
		defer timer.Stop()
		select {
		case w.chEvents <- event:
		case <-w.stop:
		case <-timer.C:
		}
	}()
}

func (w *World) Stop() {
	close(w.stop)
	close(w.chEvents)
}

func (w *World) ObjectExists(object interface{}) bool {
	return w.pg.ObjectExists(object)
}

func (w *World) LocationExists(location engine.Location) bool {
	return w.pg.LocationExists(location)
}

func (w *World) EntityExists(object interface{}, location engine.Location) bool {
	return w.pg.EntityExists(object, location)
}

func (w *World) GetObjectByLocation(location engine.Location) interface{} {
	// TODO: Emit event?
	return w.pg.GetObjectByLocation(location)
}

func (w *World) GetObjectByDot(dot *engine.Dot) interface{} {
	// TODO: Emit event?
	return w.pg.GetObjectByDot(dot)
}

func (w *World) GetEntityByDot(dot *engine.Dot) (interface{}, engine.Location) {
	// TODO: Emit event?
	return w.pg.GetEntityByDot(dot)
}

func (w *World) GetObjectsByDots(dots []*engine.Dot) []interface{} {
	// TODO: Emit event?
	return w.pg.GetObjectsByDots(dots)
}

func (w *World) CreateObject(object interface{}, location engine.Location) error {
	if err := w.pg.CreateObject(object, location); err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return nil
}

func (w *World) CreateObjectAvailableDots(object interface{}, location engine.Location) (engine.Location, *playground.ErrCreateObjectAvailableDots) {
	location, err := w.pg.CreateObjectAvailableDots(object, location)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return location, err
}

func (w *World) DeleteObject(object interface{}, location engine.Location) *playground.ErrDeleteObject {
	err := w.pg.DeleteObject(object, location)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return err
	}
	w.event(&Event{
		Type:    EventTypeObjectDelete,
		Payload: object,
	})
	return err
}

func (w *World) UpdateObject(object interface{}, old, new engine.Location) *playground.ErrUpdateObject {
	if err := w.pg.UpdateObject(object, old, new); err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return err
	}
	w.event(&Event{
		Type:    EventTypeObjectUpdate,
		Payload: object,
	})
	return nil
}

func (w *World) UpdateObjectAvailableDots(object interface{}, old, new engine.Location) (engine.Location, *playground.ErrUpdateObjectAvailableDots) {
	location, err := w.pg.UpdateObjectAvailableDots(object, old, new)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectUpdate,
		Payload: object,
	})
	return location, err
}

func (w *World) CreateObjectRandomDot(object interface{}) (engine.Location, error) {
	location, err := w.pg.CreateObjectRandomDot(object)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return location, err
}

func (w *World) CreateObjectRandomRect(object interface{}, rw, rh uint8) (engine.Location, error) {
	location, err := w.pg.CreateObjectRandomRect(object, rw, rh)
	if err != nil {
		w.event(&Event{
			Type:    EventTypeError,
			Payload: err,
		})
		return nil, err
	}
	w.event(&Event{
		Type:    EventTypeObjectCreate,
		Payload: object,
	})
	return location, err
}

func (w *World) Navigate(dot *engine.Dot, dir engine.Direction, dis uint8) (*engine.Dot, error) {
	return w.pg.Navigate(dot, dir, dis)
}

func (w *World) Size() uint16 {
	return w.pg.Size()
}

func (w *World) Width() uint8 {
	return w.pg.Width()
}

func (w *World) Height() uint8 {
	return w.pg.Height()
}
<|endoftext|>


<commit_before>// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ingore

package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	flagRevert = flag.Bool("revert", false, "revert all changes")
)

var (
	targetVersion = GetGoProtobufTipVersion()
	targeFilename = `goprotobuf-` + targetVersion[:12] + `.tar.gz`
	targetURL     = `https://goprotobuf.googlecode.com/archive/` + targetVersion + `.tar.gz`
)

var convertMap = [][2]string{
	[2]string{
		`"code.google.com/p/goprotobuf/proto"`,
		`"github.com/chai2010/protorpc/proto"`,
	},
	[2]string{
		`"code.google.com/p/goprotobuf/protoc-gen-go/descriptor"`,
		`"github.com/chai2010/protorpc/protoc-gen-go/descriptor"`,
	},
	[2]string{
		`"code.google.com/p/goprotobuf/protoc-gen-go/generator"`,
		`"github.com/chai2010/protorpc/protoc-gen-go/generator"`,
	},
	[2]string{
		`"code.google.com/p/goprotobuf/protoc-gen-go/plugin"`,
		`"github.com/chai2010/protorpc/protoc-gen-go/plugin"`,
	},
}

func main() {
	flag.Parse()

	// try download goprotobuf
	if _, err := os.Stat(targeFilename); err != nil {
		downloadFile(targetURL, targeFilename)
	}

	// unpack proto and protoc-gen-go
	unpackSourceCode(targeFilename)

	// fix import path
	fixAllImportPath("proto")
	fixAllImportPath("protoc-gen-go")

	// save proto version
	saveProtoVersion()

	// Done
	fmt.Println("Done")
}

func downloadFile(targetURL, targeFilename string) {
	var (
		f    *os.File
		resp *http.Response
		err  error
	)

	if f, err = os.Create(targeFilename); err != nil {
		log.Fatalf("downloadFile: failed to create %s: %s", targeFilename, err)
	}
	defer f.Close()

	if resp, err = http.Get(targetURL); err != nil {
		log.Fatalf("downloadFile: failed to download %s: %s", targetURL, err)
	}
	defer resp.Body.Close()

	if _, err = io.Copy(f, resp.Body); err != nil {
		log.Fatalf("downloadFile: failed to write %s: %s", targeFilename, err)
	}
}

func unpackSourceCode(filename string) {
	baseName := filename[:len(filename)-len(".tar.gz")]

	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatalf("unpackSourceCode: ioutil.ReadFile filed, err = %v", err)
	}

	gzReader, err := gzip.NewReader(bytes.NewReader(data))
	if err != nil {
		log.Fatalf("unpackSourceCode: gzip.NewReader filed, err = %v", err)
	}
	defer gzReader.Close()

	trReader := tar.NewReader(gzReader)
	for {
		header, err := trReader.Next()
		if err != nil {
			if err != io.EOF {
				log.Fatalf("unpackSourceCode: trReader.Next filed, err = %v", err)
			}
			break
		}

		// skip other files
		if header.FileInfo().IsDir() {
			continue
		}

		// proto
		if strings.HasPrefix(header.Name, baseName+"/proto/") {
			name := header.Name[len(baseName+"/"):]
			os.MkdirAll(path.Dir(name), 0666)
			fw, err := os.Create(name)
			if err != nil {
				log.Fatalf("unpackSourceCode: os.Create filed, err = %v", err)
			}
			defer fw.Close()

			_, err = io.Copy(fw, trReader)
			if err != nil {
				log.Fatalf("unpackSourceCode: io.Copy filed, err = %v", err)
			}
		}

		// protoc-gen-go
		if strings.HasPrefix(header.Name, baseName+"/protoc-gen-go/") {
			name := header.Name[len(baseName+"/"):]
			os.MkdirAll(path.Dir(name), 0666)
			fw, err := os.Create(name)
			if err != nil {
				log.Fatalf("unpackSourceCode: os.Create filed, err = %v", err)
			}
			defer fw.Close()

			_, err = io.Copy(fw, trReader)
			if err != nil {
				log.Fatalf("unpackSourceCode: io.Copy filed, err = %v", err)
			}
		}
	}
}

func fixAllImportPath(dir string) {
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Fatal("filepath.Walk: ", err)
			return err
		}
		if info.IsDir() {
			return nil
		}
		if strings.HasSuffix(path, "gen_helper.go") {
			return nil
		}
		if strings.HasSuffix(path, ".go") {
			fixImportPath(path)
		}
		return nil
	})
}

func fixImportPath(filename string) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatal("ioutil.ReadFile: ", err)
	}

	for _, v := range convertMap {
		oldPath, newPath := v[0], v[1]
		if !*flagRevert {
			data = bytes.Replace(data, []byte(oldPath), []byte(newPath), -1)
		} else {
			data = bytes.Replace(data, []byte(newPath), []byte(oldPath), -1)
		}
	}

	if err = ioutil.WriteFile(filename, data, 0666); err != nil {
		log.Fatal("ioutil.WriteFile: ", err)
	}

	if !*flagRevert {
		fmt.Printf("convert %s ok\n", filename)
	} else {
		fmt.Printf("revert %s ok\n", filename)
	}
}

func GetGoProtobufTipVersion() string {
	resp, err := http.Get("https://code.google.com/p/goprotobuf/source/browse/")
	if err != nil {
		log.Fatalf("GetGoProtobufTipTarGzUrl: http.Get failed, %v", err)
	}
	defer resp.Body.Close()

	var buf bytes.Buffer
	if _, err = io.Copy(&buf, resp.Body); err != nil {
		log.Fatalf("GetGoProtobufTipTarGzUrl: io.Copy failed, %v", err)
	}

	// href="//goprotobuf.googlecode.com/archive/26b4b5c8a6ec0e0bc5a8d2807c9f42f7d1bb291a.tar.gz" rel="nofollow">tar.gz</a>
	re := regexp.MustCompile(`href\=\"//goprotobuf.googlecode.com/archive/[0-9a-z]+\.tar\.gz\"`)
	url := re.FindString(string(buf.Bytes()))
	if url == "" {
		log.Fatalf("GetGoProtobufTipTarGzUrl: re.FindString failed")
	}
	return url[len(`href="//goprotobuf.googlecode.com/archive/`) : len(url)-len(`.tar.gz"`)]
}

func saveProtoVersion() {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "goprotobuf: %s\n", targetURL)
	if err := ioutil.WriteFile("goprotobuf-version.txt", buf.Bytes(), 0666); err != nil {
		log.Fatal("ioutil.WriteFile: ", err)
	}
}
<commit_msg>improve go generate<commit_after>// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ingore

package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
)

var (
	flagRevert = flag.Bool("revert", false, "revert all changes")
)

var (
	targetVersion = `26b4b5c8a6ec0e0bc5a8d2807c9f42f7d1bb291a`
	targeFilename = `zz-goprotobuf-` + targetVersion[:12] + `.tar.gz`
	targetURL     = `https://goprotobuf.googlecode.com/archive/` + targetVersion + `.tar.gz`
)

var convertMap = [][2]string{
	[2]string{
		`"code.google.com/p/goprotobuf/proto"`,
		`"github.com/chai2010/protorpc/proto"`,
	},
	[2]string{
		`"code.google.com/p/goprotobuf/protoc-gen-go/descriptor"`,
		`"github.com/chai2010/protorpc/protoc-gen-go/descriptor"`,
	},
	[2]string{
		`"code.google.com/p/goprotobuf/protoc-gen-go/generator"`,
		`"github.com/chai2010/protorpc/protoc-gen-go/generator"`,
	},
	[2]string{
		`"code.google.com/p/goprotobuf/protoc-gen-go/plugin"`,
		`"github.com/chai2010/protorpc/protoc-gen-go/plugin"`,
	},
}

func main() {
	flag.Parse()

	// try download goprotobuf
	if !isValidTarGzFile(targeFilename) {
		os.Remove(targeFilename)
		if err := downloadTarGzFile(targetURL, targeFilename); err != nil {
			log.Fatalf("download %s failed, err = %v", `goprotobuf`, err)
		}
	}

	// unpack proto and protoc-gen-go
	unpackSourceCode(targeFilename)

	// fix import path
	fixAllImportPath("proto")
	fixAllImportPath("protoc-gen-go")

	// save proto version
	saveProtoVersion()

	// Done
	fmt.Println("Done")
}

func isValidTarGzFile(filename string) bool {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return false
	}
	gzReader, err := gzip.NewReader(bytes.NewReader(data))
	if err != nil {
		return false
	}
	defer gzReader.Close()

	trReader := tar.NewReader(gzReader)
	for {
		if _, err := trReader.Next(); err != nil {
			if err != io.EOF {
				return false
			}
			break
		}
	}

	return true
}
func downloadTarGzFile(url, filename string) (err error) {
	defer func() {
		if err != nil {
			os.Remove(filename)
		}
	}()

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

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

	_, err = io.Copy(f, resp.Body)
	return
}

func unpackSourceCode(filename string) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatalf("unpackSourceCode: ioutil.ReadFile filed, err = %v", err)
	}

	gzReader, err := gzip.NewReader(bytes.NewReader(data))
	if err != nil {
		log.Fatalf("unpackSourceCode: gzip.NewReader filed, err = %v", err)
	}
	defer gzReader.Close()

	trReader := tar.NewReader(gzReader)
	for {
		header, err := trReader.Next()
		if err != nil {
			if err != io.EOF {
				log.Fatalf("unpackSourceCode: trReader.Next filed, err = %v", err)
			}
			break
		}

		// skip other files
		if header.FileInfo().IsDir() {
			continue
		}

		// unpack proto and protoc-gen-go
		name := header.Name[strings.Index(header.Name, "/")+1:]
		if strings.HasPrefix(name, "proto/") || strings.HasPrefix(name, "protoc-gen-go/") {
			os.MkdirAll(path.Dir(name), 0666)
			fw, err := os.Create(name)
			if err != nil {
				log.Fatalf("unpackSourceCode: os.Create filed, err = %v", err)
			}
			defer fw.Close()

			_, err = io.Copy(fw, trReader)
			if err != nil {
				log.Fatalf("unpackSourceCode: io.Copy filed, err = %v", err)
			}
		}
	}
}

func fixAllImportPath(dir string) {
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Fatal("filepath.Walk: ", err)
			return err
		}
		if info.IsDir() {
			return nil
		}
		if strings.HasSuffix(path, "gen.go") {
			return nil
		}
		if strings.HasSuffix(path, "gen_helper.go") {
			return nil
		}
		if strings.HasSuffix(path, ".go") {
			fixImportPath(path)
		}
		return nil
	})
}

func fixImportPath(filename string) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatal("ioutil.ReadFile: ", err)
	}

	for _, v := range convertMap {
		oldPath, newPath := v[0], v[1]
		if !*flagRevert {
			data = bytes.Replace(data, []byte(oldPath), []byte(newPath), -1)
		} else {
			data = bytes.Replace(data, []byte(newPath), []byte(oldPath), -1)
		}
	}

	if err = ioutil.WriteFile(filename, data, 0666); err != nil {
		log.Fatal("ioutil.WriteFile: ", err)
	}

	if !*flagRevert {
		fmt.Printf("convert %s ok\n", filename)
	} else {
		fmt.Printf("revert %s ok\n", filename)
	}
}

func saveProtoVersion() {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "goprotobuf: %s\n", targetURL)
	if err := ioutil.WriteFile("goprotobuf-version.txt", buf.Bytes(), 0666); err != nil {
		log.Fatal("ioutil.WriteFile: ", err)
	}
}
<|endoftext|>


<commit_before>package mutan

import (
	"fmt"
	"regexp"
	"strings"
	"unicode"
	"unicode/utf8"
)

// This lexer is heavily inspired on Rob Pike's lexer

func isAlphaNumeric(t rune) bool {
	return unicode.IsLetter(t)
}

func isSpace(t rune) bool {
	return unicode.IsSpace(t)
}

func isNumber(t rune) bool {
	return unicode.IsNumber(t)
}

func isOperator(t rune) bool {
	return strings.IndexRune("=+-/*><^", t) >= 0
}

const eof = -1

type stateFn func(*Lexer) stateFn
type itemType int

const (
	itemEof          itemType = 0
	itemIdentifier            = ID
	itemEndStatement          = END_STMT
	itemNumber                = NUMBER
	itemAssign                = ASSIGN
	itemOp                    = OP
	itemDop                   = DOP /* Double op ++ -- */
	itemLeftBracket           = LEFT_BRACKET
	itemRightBracket          = RIGHT_BRACKET
	itemLeftBrace             = LEFT_BRACES
	itemRightBrace            = RIGHT_BRACES
	itemEqual                 = EQUAL
	itemIf                    = IF
	itemElse                  = ELSE
	itemFor                   = FOR
	itemStore                 = STORE
	itemReturn                = RETURN
	itemAsm                   = ASM
	itemInlineAsm             = INLINE_ASM
	itemLeftPar               = LEFT_PAR
	itemRightPar              = RIGHT_PAR
	itemStop                  = STOP
	itemAddr                  = ADDR
	itemOrigin                = ORIGIN
	itemCaller                = CALLER
	itemCallVal               = CALLVAL
	itemCallDataLoad          = CALLDATALOAD
	itemCallDataSize          = CALLDATASIZE
	itemDifficulty            = DIFFICULTY
	itemPrevHash              = PREVHASH
	itemTimeStamp             = TIMESTAMP
	itemGasPrice              = GASPRICE
	itemBlockNum              = BLOCKNUM
	itemCoinbase              = COINBASE
	itemGas                   = GAS
	itemDot                   = DOT
	itemThis                  = THIS
	itemArray                 = ARRAY
	itemVarType               = TYPE
	itemComma                 = COMMA
	itemCall                  = CALL
	itemSizeof                = SIZEOF
	itemQuote                 = QUOTE
	itemStr                   = STR
)

type item struct {
	typ itemType
	val string
}

func lexStatement(l *Lexer) stateFn {
	acceptance := Alpha
	l.acceptRun(acceptance)

	if l.accept("1234567890") {
		acceptance += "1234567890"
	}
	l.acceptRun(acceptance)

	switch l.blob() {
	case "if":
		l.emit(itemIf)
	case "else":
		l.emit(itemElse)
	case "for":
		l.emit(itemFor)
	case "asm":
		l.emit(itemAsm)

		return lexInsideAsm
	case "Exit":
		l.emit(itemStop)
	case "this":
		l.emit(itemThis)

		return lexClosureScope
	case "array":
		l.emit(itemArray)

		return lexArray
	case "int8", "int16", "int32", "int64", "int256", "big", "string", "addr":
		l.emit(itemVarType)
	case "call":
		l.emit(itemCall)
	case "return":
		l.emit(itemReturn)
	case "sizeof":
		l.emit(itemSizeof)
	default:
		l.emit(itemIdentifier)
	}

	return lexText
}

const Numbers = "1234567890"
const Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ"

func lexCall(l *Lexer) stateFn {
	if !l.accept("(") {
		l.err = fmt.Errorf("Expected '('")
		return nil
	}
	l.emit(itemLeftPar)

	return lexText
}

func lexArray(l *Lexer) stateFn {
	if !l.accept("(") {
		l.err = fmt.Errorf("Exepcted '('")
		return nil
	}

	l.emit(itemLeftPar)

	if !l.accept(Numbers) {
		l.err = fmt.Errorf("Expected number")
		return nil
	}

	l.acceptRun(Numbers)

	l.emit(itemNumber)

	if !l.accept(")") {
		l.err = fmt.Errorf("Expected ')'")
		return nil
	}

	l.emit(itemRightPar)

	return lexText
}

func lexClosureScope(l *Lexer) stateFn {
	if !l.accept(".") {
		l.err = fmt.Errorf("Expected '.'")

		return nil
	}

	l.emit(itemDot)

	acceptance := "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ"
	l.acceptRun(acceptance)
	switch l.blob() {
	case "caller":
		l.emit(itemCaller)
	case "origin":
		l.emit(itemOrigin)
	case "value":
		l.emit(itemCallVal)
	case "dataLoad":
		l.emit(itemCallDataLoad)
	case "data":
		l.emit(itemCallDataLoad)
	case "dataSize":
		l.emit(itemCallDataSize)
	case "gasPrice":
		l.emit(itemGasPrice)
	case "diff":
		l.emit(itemDifficulty)
	case "prevHash":
		l.emit(itemPrevHash)
	case "time":
		l.emit(itemTimeStamp)
	case "number":
		l.emit(itemBlockNum)
	case "coinbase":
		l.emit(itemCoinbase)
	case "gas":
		l.emit(itemGas)
	case "store":
		l.emit(itemStore)
	default:
		l.err = fmt.Errorf("Undefined '%s'", l.blob())

		return nil
	}

	return lexText
}

func lexNumber(l *Lexer) stateFn {
	digits := "0123456789"
	if l.accept("0") && l.accept("xX") {
		digits = "0123456789abcdefABCDEF"
	}

	l.acceptRun(digits)

	l.emit(itemNumber)

	return lexText
}

func lexInsideAsm(l *Lexer) stateFn {
out:
	for {
		switch r := l.next(); {
		case isSpace(r):
			l.ignore()
		case r == '(':
			l.emit(itemLeftPar)
		case r == ')':
			l.backup()

			break out
		default:
			l.acceptRunUntill(')')

			l.emit(itemInlineAsm)
		}
	}

	return lexText
}

/* TODO
func lexInsidePar(l *Lexer) stateFn {
	for {
		switch r := l.next(); {
		case isComma(r):
			l.ignore()
		case isAlphaNumeric(r):
			l.backup()

			return lexStatement
		}
	}
}
*/

func lexOperator(l *Lexer) stateFn {
	// The only special case there is, assignment

	acceptance := "="
	if !l.accept("=") {
		acceptance += "-/*+><^"
	}
	l.acceptRun(acceptance)

	switch l.blob() {
	case "=":
		l.emit(itemAssign)
	case "++", "--":
		l.emit(itemDop)
	default:
		l.emit(itemOp)
	}

	return lexText
}

func lexInsideString(l *Lexer) stateFn {
	l.acceptRunUntill('"')
	l.emit(itemStr)

	l.next()
	l.emit(itemQuote)

	return lexText
}

func lexComment(l *Lexer) stateFn {
	l.acceptRunUntill('\n')

	return lexText
}

var Lineno int

// Lex text attempts to identify the current state that *might*
// be and calls the appropriate lexing method. The lexing method
// should then take care of anything that is current (even validating)
func lexText(l *Lexer) stateFn {
	for {
		switch r := l.next(); {
		case r == '\n':
			l.ignore()

			Lineno++
		case isSpace(r): // Check whether this is a space (which we ignore)
			l.ignore()
		case isAlphaNumeric(r): // Check if it's alpha numeric (var, if, else etc)
			l.backup()

			return lexStatement
		case isNumber(r): // Check if it's a number (constant)
			l.backup()

			return lexNumber
		case r == '{': // Block check
			l.emit(itemLeftBrace)
		case r == '}':
			l.emit(itemRightBrace)
		case r == '[':
			l.emit(itemLeftBracket)
		case r == ']':
			l.emit(itemRightBracket)
		case r == '(':
			l.emit(itemLeftPar)
		case r == ')':
			l.emit(itemRightPar)
		case r == '.':
			l.emit(itemDot)
		case r == ',':
			l.emit(itemComma)
		case r == '"':
			l.emit(itemQuote)

			return lexInsideString
		case r == '/', r == '#':
			return lexComment
		case r == ';':
			l.emit(itemEndStatement)
		case isOperator(r):
			l.backup()

			return lexOperator
		default:
			return nil
		}
	}

	return nil
}

type Lexer struct {
	name   string
	input  string
	start  int
	pos    int
	width  int
	state  stateFn
	items  chan item
	err    error
	lineno int
}

func lexer(name, input string) *Lexer {
	l := &Lexer{
		name:  name,
		input: input,
		state: lexText,
		items: make(chan item, 5),
	}

	return l
}

// Grabs the current blob of text
func (l *Lexer) blob() string {
	return l.input[l.start:l.pos]
}

// Emits a new item on to item channel for processing
func (l *Lexer) emit(t itemType) {
	l.items <- item{t, l.blob()}
	l.start = l.pos
}

// Accepts checks whether the given input matches the next rune
func (l *Lexer) accept(valid string) bool {
	if strings.IndexRune(valid, l.next()) >= 0 {
		return true
	}

	l.backup()

	return false
}

// Continues *eating* the next rune until no longer valid
func (l *Lexer) acceptRegexp(valid string) bool {
	if MatchRegexp(valid, []byte(string(l.next()))) {
		return true
	}
	l.backup()

	return false
}

func MatchRegexp(reg string, str []byte) bool {
	ok, _ := regexp.Match(reg, str)
	return ok
}

func (l *Lexer) acceptRunRegexp(valid string) {
	for r := l.next(); MatchRegexp(valid, []byte(string(r))); {
	}
	l.backup()
}

func (l *Lexer) acceptRun(valid string) {
	for strings.IndexRune(valid, l.next()) >= 0 {
	}
	l.backup()
}

func (l *Lexer) acceptRunUntill(until rune) {
	// Continues running until a rune is found
	for strings.IndexRune(string(until), l.next()) == -1 {
	}
	l.backup()
}

// Grabs the next item of the channel and returns it, or nil if we're done
func (l *Lexer) nextItem() item {
	for {
		select {
		case item := <-l.items:
			return item
		default:
			if l.state == nil {
				return item{}
			}

			l.state = l.state(l)
		}
	}
	panic("not reached")
}

// Takes the next rune and returns it or returns EOF
func (l *Lexer) next() (rune rune) {
	if l.pos >= len(l.input) {
		l.width = 0

		return eof
	}
	rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
	l.pos += l.width

	return rune
}

// Look ahead
func (l *Lexer) peek() rune {
	rune := l.next()
	l.backup()
	return rune
}

// Backup a previous *next*
func (l *Lexer) backup() {
	l.pos -= l.width
}

// Ignore the current rune
func (l *Lexer) ignore() {
	l.start = l.pos
}

// yacc's lexing method
func (l *Lexer) Lex(lval *yySymType) int {
	item := l.nextItem()
	lval.str = item.val

	return int(item.typ)
}

func (l *Lexer) Error(s string) {
	l.err = fmt.Errorf("%s", s)
}
<commit_msg>Exit => exit<commit_after>package mutan

import (
	"fmt"
	"regexp"
	"strings"
	"unicode"
	"unicode/utf8"
)

// This lexer is heavily inspired on Rob Pike's lexer

func isAlphaNumeric(t rune) bool {
	return unicode.IsLetter(t)
}

func isSpace(t rune) bool {
	return unicode.IsSpace(t)
}

func isNumber(t rune) bool {
	return unicode.IsNumber(t)
}

func isOperator(t rune) bool {
	return strings.IndexRune("=+-/*><^", t) >= 0
}

const eof = -1

type stateFn func(*Lexer) stateFn
type itemType int

const (
	itemEof          itemType = 0
	itemIdentifier            = ID
	itemEndStatement          = END_STMT
	itemNumber                = NUMBER
	itemAssign                = ASSIGN
	itemOp                    = OP
	itemDop                   = DOP /* Double op ++ -- */
	itemLeftBracket           = LEFT_BRACKET
	itemRightBracket          = RIGHT_BRACKET
	itemLeftBrace             = LEFT_BRACES
	itemRightBrace            = RIGHT_BRACES
	itemEqual                 = EQUAL
	itemIf                    = IF
	itemElse                  = ELSE
	itemFor                   = FOR
	itemStore                 = STORE
	itemReturn                = RETURN
	itemAsm                   = ASM
	itemInlineAsm             = INLINE_ASM
	itemLeftPar               = LEFT_PAR
	itemRightPar              = RIGHT_PAR
	itemStop                  = STOP
	itemAddr                  = ADDR
	itemOrigin                = ORIGIN
	itemCaller                = CALLER
	itemCallVal               = CALLVAL
	itemCallDataLoad          = CALLDATALOAD
	itemCallDataSize          = CALLDATASIZE
	itemDifficulty            = DIFFICULTY
	itemPrevHash              = PREVHASH
	itemTimeStamp             = TIMESTAMP
	itemGasPrice              = GASPRICE
	itemBlockNum              = BLOCKNUM
	itemCoinbase              = COINBASE
	itemGas                   = GAS
	itemDot                   = DOT
	itemThis                  = THIS
	itemArray                 = ARRAY
	itemVarType               = TYPE
	itemComma                 = COMMA
	itemCall                  = CALL
	itemSizeof                = SIZEOF
	itemQuote                 = QUOTE
	itemStr                   = STR
)

type item struct {
	typ itemType
	val string
}

func lexStatement(l *Lexer) stateFn {
	acceptance := Alpha
	l.acceptRun(acceptance)

	if l.accept("1234567890") {
		acceptance += "1234567890"
	}
	l.acceptRun(acceptance)

	switch l.blob() {
	case "if":
		l.emit(itemIf)
	case "else":
		l.emit(itemElse)
	case "for":
		l.emit(itemFor)
	case "asm":
		l.emit(itemAsm)

		return lexInsideAsm
	case "exit":
		l.emit(itemStop)
	case "this":
		l.emit(itemThis)

		return lexClosureScope
	case "array":
		l.emit(itemArray)

		return lexArray
	case "int8", "int16", "int32", "int64", "int256", "big", "string", "addr":
		l.emit(itemVarType)
	case "call":
		l.emit(itemCall)
	case "return":
		l.emit(itemReturn)
	case "sizeof":
		l.emit(itemSizeof)
	default:
		l.emit(itemIdentifier)
	}

	return lexText
}

const Numbers = "1234567890"
const Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ"

func lexCall(l *Lexer) stateFn {
	if !l.accept("(") {
		l.err = fmt.Errorf("Expected '('")
		return nil
	}
	l.emit(itemLeftPar)

	return lexText
}

func lexArray(l *Lexer) stateFn {
	if !l.accept("(") {
		l.err = fmt.Errorf("Exepcted '('")
		return nil
	}

	l.emit(itemLeftPar)

	if !l.accept(Numbers) {
		l.err = fmt.Errorf("Expected number")
		return nil
	}

	l.acceptRun(Numbers)

	l.emit(itemNumber)

	if !l.accept(")") {
		l.err = fmt.Errorf("Expected ')'")
		return nil
	}

	l.emit(itemRightPar)

	return lexText
}

func lexClosureScope(l *Lexer) stateFn {
	if !l.accept(".") {
		l.err = fmt.Errorf("Expected '.'")

		return nil
	}

	l.emit(itemDot)

	acceptance := "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ"
	l.acceptRun(acceptance)
	switch l.blob() {
	case "caller":
		l.emit(itemCaller)
	case "origin":
		l.emit(itemOrigin)
	case "value":
		l.emit(itemCallVal)
	case "dataLoad":
		l.emit(itemCallDataLoad)
	case "data":
		l.emit(itemCallDataLoad)
	case "dataSize":
		l.emit(itemCallDataSize)
	case "gasPrice":
		l.emit(itemGasPrice)
	case "diff":
		l.emit(itemDifficulty)
	case "prevHash":
		l.emit(itemPrevHash)
	case "time":
		l.emit(itemTimeStamp)
	case "number":
		l.emit(itemBlockNum)
	case "coinbase":
		l.emit(itemCoinbase)
	case "gas":
		l.emit(itemGas)
	case "store":
		l.emit(itemStore)
	default:
		l.err = fmt.Errorf("Undefined '%s'", l.blob())

		return nil
	}

	return lexText
}

func lexNumber(l *Lexer) stateFn {
	digits := "0123456789"
	if l.accept("0") && l.accept("xX") {
		digits = "0123456789abcdefABCDEF"
	}

	l.acceptRun(digits)

	l.emit(itemNumber)

	return lexText
}

func lexInsideAsm(l *Lexer) stateFn {
out:
	for {
		switch r := l.next(); {
		case isSpace(r):
			l.ignore()
		case r == '(':
			l.emit(itemLeftPar)
		case r == ')':
			l.backup()

			break out
		default:
			l.acceptRunUntill(')')

			l.emit(itemInlineAsm)
		}
	}

	return lexText
}

/* TODO
func lexInsidePar(l *Lexer) stateFn {
	for {
		switch r := l.next(); {
		case isComma(r):
			l.ignore()
		case isAlphaNumeric(r):
			l.backup()

			return lexStatement
		}
	}
}
*/

func lexOperator(l *Lexer) stateFn {
	// The only special case there is, assignment

	acceptance := "="
	if !l.accept("=") {
		acceptance += "-/*+><^"
	}
	l.acceptRun(acceptance)

	switch l.blob() {
	case "=":
		l.emit(itemAssign)
	case "++", "--":
		l.emit(itemDop)
	default:
		l.emit(itemOp)
	}

	return lexText
}

func lexInsideString(l *Lexer) stateFn {
	l.acceptRunUntill('"')
	l.emit(itemStr)

	l.next()
	l.emit(itemQuote)

	return lexText
}

func lexComment(l *Lexer) stateFn {
	l.acceptRunUntill('\n')

	return lexText
}

var Lineno int

// Lex text attempts to identify the current state that *might*
// be and calls the appropriate lexing method. The lexing method
// should then take care of anything that is current (even validating)
func lexText(l *Lexer) stateFn {
	for {
		switch r := l.next(); {
		case r == '\n':
			l.ignore()

			Lineno++
		case isSpace(r): // Check whether this is a space (which we ignore)
			l.ignore()
		case isAlphaNumeric(r): // Check if it's alpha numeric (var, if, else etc)
			l.backup()

			return lexStatement
		case isNumber(r): // Check if it's a number (constant)
			l.backup()

			return lexNumber
		case r == '{': // Block check
			l.emit(itemLeftBrace)
		case r == '}':
			l.emit(itemRightBrace)
		case r == '[':
			l.emit(itemLeftBracket)
		case r == ']':
			l.emit(itemRightBracket)
		case r == '(':
			l.emit(itemLeftPar)
		case r == ')':
			l.emit(itemRightPar)
		case r == '.':
			l.emit(itemDot)
		case r == ',':
			l.emit(itemComma)
		case r == '"':
			l.emit(itemQuote)

			return lexInsideString
		case r == '/', r == '#':
			return lexComment
		case r == ';':
			l.emit(itemEndStatement)
		case isOperator(r):
			l.backup()

			return lexOperator
		default:
			return nil
		}
	}

	return nil
}

type Lexer struct {
	name   string
	input  string
	start  int
	pos    int
	width  int
	state  stateFn
	items  chan item
	err    error
	lineno int
}

func lexer(name, input string) *Lexer {
	l := &Lexer{
		name:  name,
		input: input,
		state: lexText,
		items: make(chan item, 5),
	}

	return l
}

// Grabs the current blob of text
func (l *Lexer) blob() string {
	return l.input[l.start:l.pos]
}

// Emits a new item on to item channel for processing
func (l *Lexer) emit(t itemType) {
	l.items <- item{t, l.blob()}
	l.start = l.pos
}

// Accepts checks whether the given input matches the next rune
func (l *Lexer) accept(valid string) bool {
	if strings.IndexRune(valid, l.next()) >= 0 {
		return true
	}

	l.backup()

	return false
}

// Continues *eating* the next rune until no longer valid
func (l *Lexer) acceptRegexp(valid string) bool {
	if MatchRegexp(valid, []byte(string(l.next()))) {
		return true
	}
	l.backup()

	return false
}

func MatchRegexp(reg string, str []byte) bool {
	ok, _ := regexp.Match(reg, str)
	return ok
}

func (l *Lexer) acceptRunRegexp(valid string) {
	for r := l.next(); MatchRegexp(valid, []byte(string(r))); {
	}
	l.backup()
}

func (l *Lexer) acceptRun(valid string) {
	for strings.IndexRune(valid, l.next()) >= 0 {
	}
	l.backup()
}

func (l *Lexer) acceptRunUntill(until rune) {
	// Continues running until a rune is found
	for strings.IndexRune(string(until), l.next()) == -1 {
	}
	l.backup()
}

// Grabs the next item of the channel and returns it, or nil if we're done
func (l *Lexer) nextItem() item {
	for {
		select {
		case item := <-l.items:
			return item
		default:
			if l.state == nil {
				return item{}
			}

			l.state = l.state(l)
		}
	}
	panic("not reached")
}

// Takes the next rune and returns it or returns EOF
func (l *Lexer) next() (rune rune) {
	if l.pos >= len(l.input) {
		l.width = 0

		return eof
	}
	rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
	l.pos += l.width

	return rune
}

// Look ahead
func (l *Lexer) peek() rune {
	rune := l.next()
	l.backup()
	return rune
}

// Backup a previous *next*
func (l *Lexer) backup() {
	l.pos -= l.width
}

// Ignore the current rune
func (l *Lexer) ignore() {
	l.start = l.pos
}

// yacc's lexing method
func (l *Lexer) Lex(lval *yySymType) int {
	item := l.nextItem()
	lval.str = item.val

	return int(item.typ)
}

func (l *Lexer) Error(s string) {
	l.err = fmt.Errorf("%s", s)
}
<|endoftext|>


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

// Package gg creates plots using the Grammar of Graphics.
//
// WARNING: This API is highly unstable. For now, please vendor this
// package.
//
// gg creates statistical visualizations. It's designed to help users
// quickly navigate and explore complex data in different ways, both
// in terms of what they're plotting and how they're plotting it. This
// focus on rapid exploration of complex data leads to a very
// different design than typical plotting packages.
//
// gg is heavily inspired by Wilkinson's Grammar of Graphics [1]. A
// key observation of the Grammar of Graphics is that there are many
// motifs across different types of plots. The Grammar of Graphics
// separates these motifs into orthogonal concerns that can be
// manipulated and extended independently, enabling the creation of
// traditional plot types from their fundamental components as well as
// the creation of entirely new plot types.
//
// Data model
//
// Central to gg is its data model. At the most basic level, the input
// data consists of a table with a set of named columns, with the rows
// organized into one or more groups. At a higher level, because gg
// makes it easy to restructure data before plotting it, it expects to
// start with regularized input data, where each column represents a
// distinct independent or dependent variable. In other words, any two
// values that make sense to plot on the same axis should be in the
// same column.
//
// For example, to express a line graph with several series of
// different colors in gg, you would say "plot column A against column
// B, grouped into series and colored according to column C". In
// contrast, typical plotting packages use a "spreadsheet" model,
// where each data series is a separate column, so expressing the same
// graph requires saying "plot column A against column B in color 1
// and plot column A against column C in color 2" and so on.
//
// gg's approach is suited to exploratory data analysis because you
// don't have to restructure the data to see it in a different way. In
// the traditional spreadsheet model, you have to structure the data
// to match the plot. In gg, you tell the plot what structure to
// extract from the data.
//
// Layers and scales
//
// To visualize data, gg provides a set of composable plot building
// blocks. There are no fixed "plot types" in gg. The main building
// block is a "layer", which transforms a data set into a set of
// visual marks, such as lines, points, or rectangles. Each layer is
// configured by mapping columns of the data set to different
// "aesthetics". An aesthetic is a generalization of a dimension: X
// and Y are aesthetics, but so are color and stroke width and point
// shape. Unlike typical plotting packages, these various aesthetics
// are treated symmetrically and any aesthetic can be fed from any
// column of the data.
//
// Layers work in close concert with "scales", which map from values
// in the data space to values in the visual space. Scales can map
// from continuous or discrete data values (such as numbers or
// strings) to continuous or discrete visual values (such as pixel
// offsets or point shapes). Each aesthetic has an associated scale.
// If the user hasn't provided a specific scale for an aesthetic, gg
// uses a default scale that guesses what to do based on the data type
// and aesthetic.
//
// Stats
//
// Data can be pre-processed prior to rendering it with a layer using
// a "stat". A stat can be an arbitrary data transformation, but it's
// typically used to compute statistical summaries, such as the
// five-number summary (e.g., for a box plot), a linear regression, or
// a density estimate.
//
// TODO: "Compound" layers?
//
// Facets
//
// TODO
//
// Related work
//
// gg draws ideas and inspiration from many sources. The core
// principle of a Grammar of Graphics was introduced by Wiklinson [1].
// There have been many implementations in many languages. The most
// popular is certainly Wickham's ggplot2 for R [2]. gg draws most
// heavily on Wickham's follow-up work on ggvis for R [3].
//
// [1] Leland Wilkinson, The Grammar of Graphics, Springer, 1999.
//
// [2] Hadley Wickham, ggplot2: Elegant Graphics for Data Analysis,
// Springer, 2009.
//
// [3] Hadley Wickham, ggvis, http://ggvis.rstudio.com/.
//
// TODO: Scale transforms, coordinate spaces.
package gg
<commit_msg>gg: document supported aesthetics<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gg creates plots using the Grammar of Graphics.
//
// WARNING: This API is highly unstable. For now, please vendor this
// package.
//
// gg creates statistical visualizations. It's designed to help users
// quickly navigate and explore complex data in different ways, both
// in terms of what they're plotting and how they're plotting it. This
// focus on rapid exploration of complex data leads to a very
// different design than typical plotting packages.
//
// gg is heavily inspired by Wilkinson's Grammar of Graphics [1]. A
// key observation of the Grammar of Graphics is that there are many
// motifs across different types of plots. The Grammar of Graphics
// separates these motifs into orthogonal concerns that can be
// manipulated and extended independently, enabling the creation of
// traditional plot types from their fundamental components as well as
// the creation of entirely new plot types.
//
// Data model
//
// Central to gg is its data model. At the most basic level, the input
// data consists of a table with a set of named columns, with the rows
// organized into one or more groups. At a higher level, because gg
// makes it easy to restructure data before plotting it, it expects to
// start with regularized input data, where each column represents a
// distinct independent or dependent variable. In other words, any two
// values that make sense to plot on the same axis should be in the
// same column.
//
// For example, to express a line graph with several series of
// different colors in gg, you would say "plot column A against column
// B, grouped into series and colored according to column C". In
// contrast, typical plotting packages use a "spreadsheet" model,
// where each data series is a separate column, so expressing the same
// graph requires saying "plot column A against column B in color 1
// and plot column A against column C in color 2" and so on.
//
// gg's approach is suited to exploratory data analysis because you
// don't have to restructure the data to see it in a different way. In
// the traditional spreadsheet model, you have to structure the data
// to match the plot. In gg, you tell the plot what structure to
// extract from the data.
//
// Layers and scales
//
// To visualize data, gg provides a set of composable plot building
// blocks. There are no fixed "plot types" in gg. The main building
// block is a "layer", which transforms a data set into a set of
// visual marks, such as lines, points, or rectangles. Each layer is
// configured by mapping columns of the data set to different
// "aesthetics". An aesthetic is a generalization of a dimension: X
// and Y are aesthetics, but so are color and stroke width and point
// shape. Unlike typical plotting packages, these various aesthetics
// are treated symmetrically and any aesthetic can be fed from any
// column of the data.
//
// Layers work in close concert with "scales", which map from values
// in the data space to values in the visual space. Scales can map
// from continuous or discrete data values (such as numbers or
// strings) to continuous or discrete visual values (such as pixel
// offsets or point shapes). Each aesthetic has an associated scale.
// If the user hasn't provided a specific scale for an aesthetic, gg
// uses a default scale that guesses what to do based on the data type
// and aesthetic.
//
// Stats
//
// Data can be pre-processed prior to rendering it with a layer using
// a "stat". A stat can be an arbitrary data transformation, but it's
// typically used to compute statistical summaries, such as the
// five-number summary (e.g., for a box plot), a linear regression, or
// a density estimate.
//
// TODO: "Compound" layers?
//
// Facets
//
// TODO.
//
// Aesthetics
//
// gg understands the following aesthetics.
//
// "x" and "y" give the offset from the lower-left corner of a plot.
// Their ranges are always set to the pixel coordinates of the X and Y
// axes, respectively, and cannot be overridden.
//
// "stroke" and "fill" give the stroke and fill colors of paths and
// points. Their ranger must have type color.Color. The default ranger
// returns a single-hue gradient for continuous data, or a categorical
// palette for discrete data.
//
// "opacity" gives the overall opacity of a mark. Its ranger must have
// type float64 and give values between 0 and 1, inclusive. The
// default ranger ranges from 10% opaque (0.1) to fully opaque (1.0).
//
// "size" gives the size of marks. Its ranger must have type float64
// and yields values that are relative to the smallest dimension of
// the plot area (e.g., a value of 0.5 creates a point that cover half
// of the plot width or height, whichever is smaller). The default
// ranger ranges from 1% (0.01) to 10% (0.1).
//
// Related work
//
// gg draws ideas and inspiration from many sources. The core
// principle of a Grammar of Graphics was introduced by Wiklinson [1].
// There have been many implementations in many languages. The most
// popular is certainly Wickham's ggplot2 for R [2]. gg draws most
// heavily on Wickham's follow-up work on ggvis for R [3].
//
// [1] Leland Wilkinson, The Grammar of Graphics, Springer, 1999.
//
// [2] Hadley Wickham, ggplot2: Elegant Graphics for Data Analysis,
// Springer, 2009.
//
// [3] Hadley Wickham, ggvis, http://ggvis.rstudio.com/.
//
// TODO: Scale transforms, coordinate spaces.
package gg
<|endoftext|>


<commit_before>/*

Command gherkinfmt is a command-line gherkin formater and pretty printer.

Usage

	gherkinfmt OPTIONS

	Formating Options
	  -centersteps[=false]       control step alignment
	  -nosteps[=false]           hide steps
	  -nocomments[=false]        hide comments
	  -noaligncomments[=false]   disable auto alignment of subsequent comments
	  -mincommentindent=NUM      use min indent for aligned comments

	IO Options
	  -[no]color                 explicitly enable/disable colors
	  -in PATH                   path to input file, defaults to stdin
	  -out PATH                  path to output file, defaults to stdout

	Misc Options
	  -version                   version: ...
	  -help                      this help

Examples

	$ gherkinfmt -in path/to/some.feature

	$ cat path/to/some.feature | gherkinfmt -centersteps

*/
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"

	"github.com/muhqu/go-gherkin"
	"github.com/muhqu/go-gherkin/formater"
	"github.com/pebbe/util"
)

var err error
var colors bool
var colorsYes bool
var colorsNo bool
var centerSteps bool
var skipSteps bool
var skipComments bool
var noCommentAlign bool
var commentAlignMinIndent int
var verbose bool
var runVersion bool
var inputPath string
var inputReader io.Reader
var outputPath string
var outputWriter io.Writer

func init() {
	flag.Usage = func() {
		self := path.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, `Usage: %[1]s OPTIONS

Formating Options
  -centersteps[=false]       control step alignment
  -nosteps[=false]           hide steps
  -nocomments[=false]        hide comments
  -noaligncomments[=false]   disable auto alignment of subsequent comments
  -mincommentindent=NUM      use min indent for aligned comments

IO Options
  -[no]color                 explicitly enable/disable colors
  -in PATH                   path to input file, defaults to stdin
  -out PATH                  path to output file, defaults to stdout
  -v                         more verbose error messages

Misc Options
  -version                   version: %[2]s  (go-gherkin: %[3]s)
  -help                      this help

Examples:

  $ %[1]s -in path/to/some.feature

  $ cat path/to/some.feature | %[1]s -centersteps

`, self, VERSION, gherkin.VERSION)
	}

	flag.BoolVar(&colorsYes, "color", false, "explicitly enable colors")
	flag.BoolVar(&colorsNo, "nocolor", false, "explicitly disable colors")
	flag.BoolVar(&centerSteps, "centersteps", false, "formating option, to control step alignment")
	flag.BoolVar(&skipSteps, "nosteps", false, "omit steps, just print scenario headlines")
	flag.BoolVar(&skipComments, "nocomments", false, "hide comments")
	flag.BoolVar(&noCommentAlign, "noaligncomments", false, "disable auto alignment of subsequent comments")
	flag.IntVar(&commentAlignMinIndent, "mincommentindent", 45, "use min indent for aligned comments")
	flag.BoolVar(&verbose, "v", false, "more verbose error messages")
	flag.StringVar(&inputPath, "in", "", "path to input file")
	flag.StringVar(&outputPath, "out", "", "path to output file")
	flag.BoolVar(&runVersion, "version", false, "version: "+VERSION+"  (go-gherkin: "+gherkin.VERSION+")")
	flag.Parse()

	if !verbose {
		log.SetOutput(ioutil.Discard)
	}
	log.Print("Initialized")
}

func usageErr(err error) {
	fmt.Fprintf(os.Stderr, "Error: %s\n       Use -h for help.\n", err.Error())
}

func usageErrWithVerboseHint(err error) {
	if verbose {
		usageErr(err)
	} else {
		fmt.Fprintf(os.Stderr, "Error: %s\n       Use -h for help or use -v to increase verbosity\n", err.Error())
	}
}

func main() {
	if runVersion {
		fmt.Fprintf(os.Stdout, "%s (go-gherkin %s)\n", VERSION, gherkin.VERSION)
		return
	}
	if inputPath != "" {
		inputReader, err = os.Open(inputPath)
		if err != nil {
			usageErr(err)
			return
		}
	} else {
		st, err := os.Stdin.Stat()
		if err != nil {
			usageErr(err)
			return
		}
		if st.Size() > 0 {
			inputReader = os.Stdin
		}
	}
	if inputReader == nil {
		usageErr(fmt.Errorf("Missing input (stdin OR -in flag)"))
		return
	}

	if outputPath != "" {
		outputWriter, err = os.Create(outputPath)
		if err != nil {
			usageErr(err)
			return
		}
	} else {
		outputWriter = os.Stdout
	}

	if colorsYes {
		colors = true
	} else if colorsNo {
		colors = false
	} else if outputWriter == os.Stdout {
		colors = util.IsTerminal(os.Stdout)
	}

	fmtr := &formater.GherkinPrettyFormater{
		AnsiColors:             colors,
		CenterSteps:            centerSteps,
		SkipSteps:              skipSteps,
		SkipComments:           skipComments,
		NoAlignComments:        noCommentAlign,
		AlignCommentsMinIndent: commentAlignMinIndent,
	}

	log.Printf("Formater Settings: %+v", fmtr)

	bytes, _ := ioutil.ReadAll(inputReader)
	content := string(bytes)
	gp := gherkin.NewGherkinDOMParser(content)
	gp.Init()
	err = gp.Parse()
	if err != nil {
		usageErrWithVerboseHint(fmt.Errorf("Parsing failed. invalid gherkin"))
		if verbose {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}
	fmtr.Format(gp, outputWriter)
}
<commit_msg>fix #2: default to color=off on windows<commit_after>/*

Command gherkinfmt is a command-line gherkin formater and pretty printer.

Usage

	gherkinfmt OPTIONS

	Formating Options
	  -centersteps[=false]       control step alignment
	  -nosteps[=false]           hide steps
	  -nocomments[=false]        hide comments
	  -noaligncomments[=false]   disable auto alignment of subsequent comments
	  -mincommentindent=NUM      use min indent for aligned comments

	IO Options
	  -[no]color                 explicitly enable/disable colors
	  -in PATH                   path to input file, defaults to stdin
	  -out PATH                  path to output file, defaults to stdout

	Misc Options
	  -version                   version: ...
	  -help                      this help

Examples

	$ gherkinfmt -in path/to/some.feature

	$ cat path/to/some.feature | gherkinfmt -centersteps

*/
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"runtime"

	"github.com/muhqu/go-gherkin"
	"github.com/muhqu/go-gherkin/formater"
	"github.com/pebbe/util"
)

var err error
var colors bool
var colorsYes bool
var colorsNo bool
var centerSteps bool
var skipSteps bool
var skipComments bool
var noCommentAlign bool
var commentAlignMinIndent int
var verbose bool
var runVersion bool
var inputPath string
var inputReader io.Reader
var outputPath string
var outputWriter io.Writer

func init() {
	flag.Usage = func() {
		self := path.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, `Usage: %[1]s OPTIONS

Formating Options
  -centersteps[=false]       control step alignment
  -nosteps[=false]           hide steps
  -nocomments[=false]        hide comments
  -noaligncomments[=false]   disable auto alignment of subsequent comments
  -mincommentindent=NUM      use min indent for aligned comments

IO Options
  -[no]color                 explicitly enable/disable colors
  -in PATH                   path to input file, defaults to stdin
  -out PATH                  path to output file, defaults to stdout
  -v                         more verbose error messages

Misc Options
  -version                   version: %[2]s  (go-gherkin: %[3]s)
  -help                      this help

Examples:

  $ %[1]s -in path/to/some.feature

  $ cat path/to/some.feature | %[1]s -centersteps

`, self, VERSION, gherkin.VERSION)
	}

	flag.BoolVar(&colorsYes, "color", false, "explicitly enable colors")
	flag.BoolVar(&colorsNo, "nocolor", false, "explicitly disable colors")
	flag.BoolVar(&centerSteps, "centersteps", false, "formating option, to control step alignment")
	flag.BoolVar(&skipSteps, "nosteps", false, "omit steps, just print scenario headlines")
	flag.BoolVar(&skipComments, "nocomments", false, "hide comments")
	flag.BoolVar(&noCommentAlign, "noaligncomments", false, "disable auto alignment of subsequent comments")
	flag.IntVar(&commentAlignMinIndent, "mincommentindent", 45, "use min indent for aligned comments")
	flag.BoolVar(&verbose, "v", false, "more verbose error messages")
	flag.StringVar(&inputPath, "in", "", "path to input file")
	flag.StringVar(&outputPath, "out", "", "path to output file")
	flag.BoolVar(&runVersion, "version", false, "version: "+VERSION+"  (go-gherkin: "+gherkin.VERSION+")")
	flag.Parse()

	if !verbose {
		log.SetOutput(ioutil.Discard)
	}
	log.Print("Initialized")
}

func usageErr(err error) {
	fmt.Fprintf(os.Stderr, "Error: %s\n       Use -h for help.\n", err.Error())
}

func usageErrWithVerboseHint(err error) {
	if verbose {
		usageErr(err)
	} else {
		fmt.Fprintf(os.Stderr, "Error: %s\n       Use -h for help or use -v to increase verbosity\n", err.Error())
	}
}

func main() {
	if runVersion {
		fmt.Fprintf(os.Stdout, "%s (go-gherkin %s)\n", VERSION, gherkin.VERSION)
		return
	}
	if inputPath != "" {
		inputReader, err = os.Open(inputPath)
		if err != nil {
			usageErr(err)
			return
		}
	} else {
		st, err := os.Stdin.Stat()
		if err != nil {
			usageErr(err)
			return
		}
		if st.Size() > 0 {
			inputReader = os.Stdin
		}
	}
	if inputReader == nil {
		usageErr(fmt.Errorf("Missing input (stdin OR -in flag)"))
		return
	}

	if outputPath != "" {
		outputWriter, err = os.Create(outputPath)
		if err != nil {
			usageErr(err)
			return
		}
	} else {
		outputWriter = os.Stdout
	}

	if colorsYes {
		colors = true
	} else if colorsNo {
		colors = false
	} else if outputWriter == os.Stdout {
		colors = util.IsTerminal(os.Stdout) && runtime.GOOS != "windows"
	}

	fmtr := &formater.GherkinPrettyFormater{
		AnsiColors:             colors,
		CenterSteps:            centerSteps,
		SkipSteps:              skipSteps,
		SkipComments:           skipComments,
		NoAlignComments:        noCommentAlign,
		AlignCommentsMinIndent: commentAlignMinIndent,
	}

	log.Printf("Formater Settings: %+v", fmtr)

	bytes, _ := ioutil.ReadAll(inputReader)
	content := string(bytes)
	gp := gherkin.NewGherkinDOMParser(content)
	gp.Init()
	err = gp.Parse()
	if err != nil {
		usageErrWithVerboseHint(fmt.Errorf("Parsing failed. invalid gherkin"))
		if verbose {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}
	fmtr.Format(gp, outputWriter)
}
<|endoftext|>


<commit_before>package identity

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"encoding/hex"
	"errors"

	ed "github.com/FactomProject/ed25519"
	"github.com/FactomProject/factom"
	"github.com/FactomProject/factomd/common/primitives"
)

type BlockSigningKey struct {
	version          []byte
	message          []byte
	rootChainID      []byte
	newPubKey        []byte
	timestamp        []byte
	identityPreimage []byte
	signiture        []byte

	subchain string
}

func MakeBlockSigningKeySeeded(rootChainIDStr string, subchainID string, privateKey *[64]byte, signingkey *[64]byte) (*BlockSigningKey, []byte, error) {
	block, _, err := MakeBlockSigningKeyFixed(rootChainIDStr, subchainID, privateKey, false)
	if err != nil {
		return nil, nil, err
	}

	block.newPubKey = signingkey[:32]
	block.newPubKey = signingkey[:32]

	return block, signingkey[32:], nil
}

func MakeBlockSigningKey(rootChainIDStr string, subchainID string, privateKey *[64]byte) (*BlockSigningKey, []byte, error) {
	a, b, c := MakeBlockSigningKeyFixed(rootChainIDStr, subchainID, privateKey, false)
	return a, b, c
}

// Creates a new BlockSigningKey type. Used to change keys in identity chain
func MakeBlockSigningKeyFixed(rootChainIDStr string, subchainID string, privateKey *[64]byte, random bool) (*BlockSigningKey, []byte, error) {
	rootChainID, err := hex.DecodeString(rootChainIDStr)
	if err != nil {
		return nil, nil, err
	}
	if bytes.Compare(rootChainID[:ProofOfWorkLength], ProofOfWorkChainID[:ProofOfWorkLength]) != 0 {
		return nil, nil, errors.New("Error making a new block signing key: Root ChainID invalid")
	}
	b := new(BlockSigningKey)
	b.version = []byte{0x00}
	b.message = []byte("New Block Signing Key")
	b.rootChainID = rootChainID
	b.subchain = subchainID

	pub, priv, err := ed.GenerateKey(rand.Reader)
	if err != nil {
		return nil, nil, err
	}
	if !random {
		buf := new(bytes.Buffer)
		buf.WriteString(rootChainIDStr)
		pub, priv, err = ed.GenerateKey(buf)
		if err != nil {
			return nil, nil, err
		}
	}
	b.newPubKey = pub[:32]
	t := primitives.NewTimestampNow().GetTimeSeconds()
	by := make([]byte, 8)
	binary.BigEndian.PutUint64(by, uint64(t))
	b.timestamp = by

	preI := make([]byte, 0)
	preI = append(preI, []byte{0x01}...)
	preI = append(preI, privateKey[32:]...)
	b.identityPreimage = preI

	sig := ed.Sign(privateKey, b.versionToTimestamp())
	b.signiture = sig[:]
	return b, priv[:], nil
}

func (b *BlockSigningKey) GetEntry() *factom.Entry {
	e := new(factom.Entry)
	e.ChainID = b.subchain
	e.Content = []byte{}
	e.ExtIDs = b.extIdList()

	return e
}

func (b *BlockSigningKey) versionToTimestamp() []byte {
	buf := new(bytes.Buffer)
	buf.Write(b.version)
	buf.Write(b.message)
	buf.Write(b.rootChainID)
	buf.Write(b.newPubKey)
	buf.Write(b.timestamp)

	return buf.Bytes()
}

func (b *BlockSigningKey) extIdList() [][]byte {
	list := make([][]byte, 0)
	list = append(list, b.version)
	list = append(list, b.message)
	list = append(list, b.rootChainID)
	list = append(list, b.newPubKey)
	list = append(list, b.timestamp)
	list = append(list, b.identityPreimage)
	list = append(list, b.signiture)

	return list
}
<commit_msg>Fixed signature on seeded new block signing key. Was not creating signature again<commit_after>package identity

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"encoding/hex"
	"errors"

	ed "github.com/FactomProject/ed25519"
	"github.com/FactomProject/factom"
	"github.com/FactomProject/factomd/common/primitives"
)

type BlockSigningKey struct {
	version          []byte
	message          []byte
	rootChainID      []byte
	newPubKey        []byte
	timestamp        []byte
	identityPreimage []byte
	signiture        []byte

	subchain string
}

func MakeBlockSigningKeySeeded(rootChainIDStr string, subchainID string, privateKey *[64]byte, signingkey *[64]byte) (*BlockSigningKey, []byte, error) {
	block, _, err := MakeBlockSigningKeyFixed(rootChainIDStr, subchainID, privateKey, false)
	if err != nil {
		return nil, nil, err
	}

	block.newPubKey = signingkey[32:]

	t := primitives.NewTimestampNow().GetTimeSeconds()
	by := make([]byte, 8)
	binary.BigEndian.PutUint64(by, uint64(t))
	block.timestamp = by

	preI := make([]byte, 0)
	preI = append(preI, []byte{0x01}...)
	preI = append(preI, privateKey[32:]...)
	block.identityPreimage = preI

	sig := ed.Sign(privateKey, block.versionToTimestamp())
	block.signiture = sig[:]

	return block, signingkey[:32], nil
}

func MakeBlockSigningKey(rootChainIDStr string, subchainID string, privateKey *[64]byte) (*BlockSigningKey, []byte, error) {
	a, b, c := MakeBlockSigningKeyFixed(rootChainIDStr, subchainID, privateKey, false)
	return a, b, c
}

// Creates a new BlockSigningKey type. Used to change keys in identity chain
func MakeBlockSigningKeyFixed(rootChainIDStr string, subchainID string, privateKey *[64]byte, random bool) (*BlockSigningKey, []byte, error) {
	rootChainID, err := hex.DecodeString(rootChainIDStr)
	if err != nil {
		return nil, nil, err
	}
	if bytes.Compare(rootChainID[:ProofOfWorkLength], ProofOfWorkChainID[:ProofOfWorkLength]) != 0 {
		return nil, nil, errors.New("Error making a new block signing key: Root ChainID invalid")
	}
	b := new(BlockSigningKey)
	b.version = []byte{0x00}
	b.message = []byte("New Block Signing Key")
	b.rootChainID = rootChainID
	b.subchain = subchainID

	pub, priv, err := ed.GenerateKey(rand.Reader)
	if err != nil {
		return nil, nil, err
	}
	if !random {
		buf := new(bytes.Buffer)
		buf.WriteString(rootChainIDStr)
		pub, priv, err = ed.GenerateKey(buf)
		if err != nil {
			return nil, nil, err
		}
	}
	b.newPubKey = pub[:32]
	t := primitives.NewTimestampNow().GetTimeSeconds()
	by := make([]byte, 8)
	binary.BigEndian.PutUint64(by, uint64(t))
	b.timestamp = by

	preI := make([]byte, 0)
	preI = append(preI, []byte{0x01}...)
	preI = append(preI, privateKey[32:]...)
	b.identityPreimage = preI

	sig := ed.Sign(privateKey, b.versionToTimestamp())
	b.signiture = sig[:]
	return b, priv[:], nil
}

func (b *BlockSigningKey) GetEntry() *factom.Entry {
	e := new(factom.Entry)
	e.ChainID = b.subchain
	e.Content = []byte{}
	e.ExtIDs = b.extIdList()

	return e
}

func (b *BlockSigningKey) versionToTimestamp() []byte {
	buf := new(bytes.Buffer)
	buf.Write(b.version)
	buf.Write(b.message)
	buf.Write(b.rootChainID)
	buf.Write(b.newPubKey)
	buf.Write(b.timestamp)

	return buf.Bytes()
}

func (b *BlockSigningKey) extIdList() [][]byte {
	list := make([][]byte, 0)
	list = append(list, b.version)
	list = append(list, b.message)
	list = append(list, b.rootChainID)
	list = append(list, b.newPubKey)
	list = append(list, b.timestamp)
	list = append(list, b.identityPreimage)
	list = append(list, b.signiture)

	return list
}
<|endoftext|>


<commit_before>package qiita

const version = "1.0.0"
<commit_msg>Update Version<commit_after>package qiita

const version = "1.0.1"
<|endoftext|>


<commit_before>package queue

import "time"
import "encoding/binary"

type Metrics interface {
	Executor() string
	BeginTime() time.Time
	FinishTime() time.Time

	Calculate(interface{})

	ElapsedTime() time.Duration
	MemoryUsage() int
}

func NewMetrics(executor string) Metrics { // {{{
	m := metricsPoolGet()
	m.executor = executor
	m.beginTime = time.Now()
	return m
} // }}}

type metrics struct {
	executor    string
	beginTime   time.Time
	finishTime  time.Time
	memoryUsage int
}

func (this *metrics) Reset() { // {{{
	this.executor = ""
	this.beginTime = time.Time{}
	this.finishTime = time.Time{}
	this.memoryUsage = 0
} // }}}

func (this *metrics) Release() { // {{{
	metricsPoolPut(this)
} // }}}

func (this *metrics) Executor() string { // {{{
	return this.executor
} // }}}

func (this *metrics) BeginTime() time.Time { // {{{
	return this.beginTime
} // }}}

func (this *metrics) FinishTime() time.Time { // {{{
	return this.finishTime
} // }}}

func (this *metrics) Calculate(v interface{}) { // {{{
	this.finishTime = time.Now()
	this.memoryUsage = binary.Size(v)
} // }}}

func (this *metrics) ElapsedTime() time.Duration { // {{{
	return this.finishTime.Sub(this.beginTime)
} // }}}

func (this *metrics) MemoryUsage() int { // {{{
	return this.memoryUsage
} // }}}
<commit_msg>Use unsafe.Sizeof to get size of struct<commit_after>package queue

import "time"
import "unsafe"

type Metrics interface {
	Executor() string
	BeginTime() time.Time
	FinishTime() time.Time

	Calculate(interface{})

	ElapsedTime() time.Duration
	MemoryUsage() uintptr
}

func NewMetrics(executor string) Metrics { // {{{
	m := metricsPoolGet()
	m.executor = executor
	m.beginTime = time.Now()
	return m
} // }}}

type metrics struct {
	executor    string
	beginTime   time.Time
	finishTime  time.Time
	memoryUsage uintptr
}

func (this *metrics) Reset() { // {{{
	this.executor = ""
	this.beginTime = time.Time{}
	this.finishTime = time.Time{}
	this.memoryUsage = 0
} // }}}

func (this *metrics) Release() { // {{{
	metricsPoolPut(this)
} // }}}

func (this *metrics) Executor() string { // {{{
	return this.executor
} // }}}

func (this *metrics) BeginTime() time.Time { // {{{
	return this.beginTime
} // }}}

func (this *metrics) FinishTime() time.Time { // {{{
	return this.finishTime
} // }}}

func (this *metrics) Calculate(v interface{}) { // {{{
	this.finishTime = time.Now()
	this.memoryUsage = unsafe.Sizeof(v)
} // }}}

func (this *metrics) ElapsedTime() time.Duration { // {{{
	return this.finishTime.Sub(this.beginTime)
} // }}}

func (this *metrics) MemoryUsage() uintptr { // {{{
	return this.memoryUsage
} // }}}
<|endoftext|>


<commit_before>// Copyright 2014, Joel Scoble, all rights reserved.
// Licensed under The MIT License. Please view the LICENSE file for more
// information.
//
package shuffler

import (
	"math/rand"

	"github.com/mohae/shuffler"
)

// Shuffle randomizes collections
func Shuffle(c shuffler.Shuffler) error {
    l := c.Len()
    for i := l - 1; i >= 0; i-- {
      j := rand.Intn(i + 1)
      c.Swap(i, j)
    }
    return nil
}

// ShuffleByte randomizes a byte slice.
func ShuffleByte(c []byte) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleComplex64 randomizes a complex64 slice.
func ShuffleComplex64(c []complex64) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleComplex129 randomizes a complex128 slice.
func ShuffleComplex128(c []complex128) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleFloat32 randomizes a float32 slice.
func ShuffleFloat32(c []float32) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleFloat64 randomizes a float64 slice.
func ShuffleFloat64(c []float64) error {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
    if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
	return nil
}

// ShuffleInt randomizes an int slice.
func ShuffleInt(c []int) error {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
    if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
	return nil
}

// ShuffleInt8 randomizes an int8 slice.
func ShuffleInt8(c []int8) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleInt16 randomizes an int16 slice.
func ShuffleInt16(c []int16) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleInt32 randomizes an int32 slice.
func ShuffleInt32(c []int32) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		c[j], c[i] = c[i], c[j]
	}
}

// ShuffleInt64 randomizes an int64 slice.
func ShuffleInt64(c []int64) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleString randomizes a strings slice.
func ShuffleString(c []string) error {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
    if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
	return nil
}

// ShuffleUint randomizes an uint slice.
func ShuffleUint(c []uint) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint8 randomizes an uint8 slice.
func ShuffleUint8(c []uint8) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint16 randomizes an uint16 slice.
func ShuffleUint16(c []uint16) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint32 randomizes an uint32 slice.
func ShuffleUint32(c []uint32) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint64 randomizes an uint64 slice.
func ShuffleUint64(c []uint64) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}
<commit_msg>change import from shuffler to shuffle<commit_after>// Copyright 2014, Joel Scoble, all rights reserved.
// Licensed under The MIT License. Please view the LICENSE file for more
// information.
//
package shuffler

import (
	"math/rand"

	"github.com/mohae/shuffle"
)

// Shuffle randomizes collections
func Shuffle(c shuffler.Shuffler) error {
	l := c.Len()
	for i := l - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		c.Swap(i, j)
	}
	return nil
}

// ShuffleByte randomizes a byte slice.
func ShuffleByte(c []byte) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleComplex64 randomizes a complex64 slice.
func ShuffleComplex64(c []complex64) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleComplex129 randomizes a complex128 slice.
func ShuffleComplex128(c []complex128) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleFloat32 randomizes a float32 slice.
func ShuffleFloat32(c []float32) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleFloat64 randomizes a float64 slice.
func ShuffleFloat64(c []float64) error {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
	return nil
}

// ShuffleInt randomizes an int slice.
func ShuffleInt(c []int) error {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
	return nil
}

// ShuffleInt8 randomizes an int8 slice.
func ShuffleInt8(c []int8) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleInt16 randomizes an int16 slice.
func ShuffleInt16(c []int16) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleInt32 randomizes an int32 slice.
func ShuffleInt32(c []int32) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		c[j], c[i] = c[i], c[j]
	}
}

// ShuffleInt64 randomizes an int64 slice.
func ShuffleInt64(c []int64) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleString randomizes a strings slice.
func ShuffleString(c []string) error {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
	return nil
}

// ShuffleUint randomizes an uint slice.
func ShuffleUint(c []uint) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint8 randomizes an uint8 slice.
func ShuffleUint8(c []uint8) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint16 randomizes an uint16 slice.
func ShuffleUint16(c []uint16) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint32 randomizes an uint32 slice.
func ShuffleUint32(c []uint32) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}

// ShuffleUint64 randomizes an uint64 slice.
func ShuffleUint64(c []uint64) {
	for i := len(c) - 1; i >= 0; i-- {
		j := rand.Intn(i + 1)
		if i != j {
			c[j], c[i] = c[i], c[j]
		}
	}
}
<|endoftext|>


<commit_before>package cfutil

import (
	"encoding/json"
	"github.com/jeffail/gabs"
	"github.com/satori/go.uuid"
	"os"
	"strings"
	"time"
)

type vcapApplication struct {
	ApplicationName    string    `json:"application_name"`
	ApplicationVersion string    `json:"application_version"`
	ApplicationUris    []string  `json:"application_uris"`
	Host               string    `json:"host"`
	Name               string    `json:"name"`
	InstanceId         string    `json:"instance_id"`
	InstanceIndex      int       `json:"instance_index"`
	Port               int       `json:"port"`
	Start              time.Time `json:"start"`
	StartedAt          time.Time `json:"started_at"`
	StartedTimestamp   int64     `json:"started_timestamp"`
	Uris               []string  `json:"uris"`
	Users              *[]string `json:"users"`
	Version            string    `json:"version"`
}

func LocalVcapApplication() string {
	appId := uuid.NewV4().String()

	va := &vcapApplication{
		ApplicationName:    "appname",
		ApplicationVersion: appId,
		Host:               "0.0.0.0",
		Port:               8080,
		ApplicationUris:    []string{"localhost:8080"},
		InstanceId:         "451f045fd16427bb99c895a2649b7b2a",
		InstanceIndex:      0,
		Name:               "appname",
		Start:              time.Now(),
		StartedAt:          time.Now(),
		StartedTimestamp:   time.Now().Unix(),
		Uris:               []string{"localhost:8080"},
		Version:            appId,
	}
	json, _ := json.Marshal(va)
	return string(json)
}

func LocalMemoryLimit() string {
	return "2G"
}

func LocalVcapServices() string {
	var supportedServices = []string{
		"postgres",
		"smtp",
	}
	jsonObj := gabs.New()
	for _, service := range supportedServices {
		env := "CF_LOCAL_" + strings.ToUpper(service)
		uri := os.Getenv(env)
		if uri != "" {
			jsonObj.Array(service)
			serviceJson := gabs.New()
			serviceJson.Set(uri, "credentials", "uri")
			serviceJson.Set(service, "name")
			jsonObj.ArrayAppendP(serviceJson.Data(), service)
		}
	}
	return jsonObj.String()
}
<commit_msg>Take PORT from environment if available<commit_after>package cfutil

import (
	"encoding/json"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/jeffail/gabs"
	"github.com/satori/go.uuid"
	"os"
	"strconv"
	"strings"
	"time"
)

type vcapApplication struct {
	ApplicationName    string    `json:"application_name"`
	ApplicationVersion string    `json:"application_version"`
	ApplicationUris    []string  `json:"application_uris"`
	Host               string    `json:"host"`
	Name               string    `json:"name"`
	InstanceId         string    `json:"instance_id"`
	InstanceIndex      int       `json:"instance_index"`
	Port               int       `json:"port"`
	Start              time.Time `json:"start"`
	StartedAt          time.Time `json:"started_at"`
	StartedTimestamp   int64     `json:"started_timestamp"`
	Uris               []string  `json:"uris"`
	Users              *[]string `json:"users"`
	Version            string    `json:"version"`
}

func LocalVcapApplication() string {
	appId := uuid.NewV4().String()
	port := 8080
	host := "localhost"
	if p, err := strconv.Atoi(os.Getenv("PORT")); err == nil {
		port = p
	}
	hostWithPort := fmt.Sprintf("%s:%d", host, port)

	va := &vcapApplication{
		ApplicationName:    "appname",
		ApplicationVersion: appId,
		Host:               "0.0.0.0",
		Port:               port,
		ApplicationUris:    []string{hostWithPort},
		InstanceId:         "451f045fd16427bb99c895a2649b7b2a",
		InstanceIndex:      0,
		Name:               "appname",
		Start:              time.Now(),
		StartedAt:          time.Now(),
		StartedTimestamp:   time.Now().Unix(),
		Uris:               []string{hostWithPort},
		Version:            appId,
	}
	json, _ := json.Marshal(va)
	return string(json)
}

func LocalMemoryLimit() string {
	return "2G"
}

func LocalVcapServices() string {
	var supportedServices = []string{
		"postgres",
		"smtp",
		"rabbitmq",
	}
	jsonObj := gabs.New()
	for _, service := range supportedServices {
		env := "CF_LOCAL_" + strings.ToUpper(service)
		uri := os.Getenv(env)
		if uri != "" {
			log.Printf("Adding service '%s'", service)
			jsonObj.Array(service)
			serviceJson := gabs.New()
			serviceJson.Set(uri, "credentials", "uri")
			serviceJson.Set(service, "name")
			log.Print("Local service: ", service)
			jsonObj.ArrayAppendP(serviceJson.Data(), service)
		}
	}
	return jsonObj.String()
}
<|endoftext|>


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

// Godoc comment extraction and comment -> HTML formatting.

package doc

import (
	"io"
	"regexp"
	"strings"
	"text/template" // for HTMLEscape
	"unicode"
	"unicode/utf8"
)

var (
	ldquo = []byte("“")
	rdquo = []byte("”")
)

// Escape comment text for HTML. If nice is set,
// also turn `` into “ and '' into ”.
func commentEscape(w io.Writer, text string, nice bool) {
	last := 0
	if nice {
		for i := 0; i < len(text)-1; i++ {
			ch := text[i]
			if ch == text[i+1] && (ch == '`' || ch == '\'') {
				template.HTMLEscape(w, []byte(text[last:i]))
				last = i + 2
				switch ch {
				case '`':
					w.Write(ldquo)
				case '\'':
					w.Write(rdquo)
				}
				i++ // loop will add one more
			}
		}
	}
	template.HTMLEscape(w, []byte(text[last:]))
}

const (
	// Regexp for Go identifiers
	identRx = `[a-zA-Z_][a-zA-Z_0-9]*` // TODO(gri) ASCII only for now - fix this

	// Regexp for URLs
	protocol = `(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero):`
	hostPart = `[a-zA-Z0-9_@\-]+`
	filePart = `[a-zA-Z0-9_?%#~&/\-+=]+`
	urlRx    = protocol + `//` + // http://
		hostPart + `([.:]` + hostPart + `)*/?` + // //www.google.com:8080/
		filePart + `([:.,]` + filePart + `)*`
)

var matchRx = regexp.MustCompile(`(` + identRx + `)|(` + urlRx + `)`)

var (
	html_a      = []byte(`<a href="`)
	html_aq     = []byte(`">`)
	html_enda   = []byte("")
	html_i      = []byte("")
	html_endi   = []byte("")
	html_p      = []byte("
\n")
	html_endp   = []byte("
\n")
	html_pre    = []byte("
")
	html_endpre = []byte("
\n")
	html_h      = []byte("
")
	html_endh   = []byte("
\n")
)

// Emphasize and escape a line of text for HTML. URLs are converted into links;
// if the URL also appears in the words map, the link is taken from the map (if
// the corresponding map value is the empty string, the URL is not converted
// into a link). Go identifiers that appear in the words map are italicized; if
// the corresponding map value is not the empty string, it is considered a URL
// and the word is converted into a link. If nice is set, the remaining text's
// appearance is improved where it makes sense (e.g., `` is turned into “
// and '' into ”).
func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
	for {
		m := matchRx.FindStringSubmatchIndex(line)
		if m == nil {
			break
		}
		// m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is identRx)

		// write text before match
		commentEscape(w, line[0:m[0]], nice)

		// analyze match
		match := line[m[0]:m[1]]
		url := ""
		italics := false
		if words != nil {
			url, italics = words[string(match)]
		}
		if m[2] < 0 {
			// didn't match against first parenthesized sub-regexp; must be match against urlRx
			if !italics {
				// no alternative URL in words list, use match instead
				url = string(match)
			}
			italics = false // don't italicize URLs
		}

		// write match
		if len(url) > 0 {
			w.Write(html_a)
			template.HTMLEscape(w, []byte(url))
			w.Write(html_aq)
		}
		if italics {
			w.Write(html_i)
		}
		commentEscape(w, match, nice)
		if italics {
			w.Write(html_endi)
		}
		if len(url) > 0 {
			w.Write(html_enda)
		}

		// advance
		line = line[m[1]:]
	}
	commentEscape(w, line, nice)
}

func indentLen(s string) int {
	i := 0
	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
		i++
	}
	return i
}

func isBlank(s string) bool {
	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
}

func commonPrefix(a, b string) string {
	i := 0
	for i < len(a) && i < len(b) && a[i] == b[i] {
		i++
	}
	return a[0:i]
}

func unindent(block []string) {
	if len(block) == 0 {
		return
	}

	// compute maximum common white prefix
	prefix := block[0][0:indentLen(block[0])]
	for _, line := range block {
		if !isBlank(line) {
			prefix = commonPrefix(prefix, line[0:indentLen(line)])
		}
	}
	n := len(prefix)

	// remove
	for i, line := range block {
		if !isBlank(line) {
			block[i] = line[n:]
		}
	}
}

// heading returns the trimmed line if it passes as a section heading;
// otherwise it returns the empty string.
func heading(line string) string {
	line = strings.TrimSpace(line)
	if len(line) == 0 {
		return ""
	}

	// a heading must start with an uppercase letter
	r, _ := utf8.DecodeRuneInString(line)
	if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
		return ""
	}

	// it must end in a letter or digit:
	r, _ = utf8.DecodeLastRuneInString(line)
	if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
		return ""
	}

	// exclude lines with illegal characters
	if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
		return ""
	}

	// allow "'" for possessive "'s" only
	for b := line; ; {
		i := strings.IndexRune(b, '\'')
		if i < 0 {
			break
		}
		if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
			return "" // not followed by "s "
		}
		b = b[i+2:]
	}

	return line
}

type op int

const (
	opPara op = iota
	opHead
	opPre
)

type block struct {
	op    op
	lines []string
}

// ToHTML converts comment text to formatted HTML.
// The comment was prepared by DocReader,
// so it is known not to have leading, trailing blank lines
// nor to have trailing spaces at the end of lines.
// The comment markers have already been removed.
//
// Turn each run of multiple \n into

.
// Turn each run of indented lines into a
 block without indent.
// Enclose headings with header tags.
//
// URLs in the comment text are converted into links; if the URL also appears
// in the words map, the link is taken from the map (if the corresponding map
// value is the empty string, the URL is not converted into a link).
//
// Go identifiers that appear in the words map are italicized; if the corresponding
// map value is not the empty string, it is considered a URL and the word is converted
// into a link.
func ToHTML(w io.Writer, text string, words map[string]string) {
	for _, b := range blocks(text) {
		switch b.op {
		case opPara:
			w.Write(html_p)
			for _, line := range b.lines {
				emphasize(w, line, words, true)
			}
			w.Write(html_endp)
		case opHead:
			w.Write(html_h)
			for _, line := range b.lines {
				commentEscape(w, line, true)
			}
			w.Write(html_endh)
		case opPre:
			w.Write(html_pre)
			for _, line := range b.lines {
				emphasize(w, line, nil, false)
			}
			w.Write(html_endpre)
		}
	}
}

func blocks(text string) []block {
	var (
		out  []block
		para []string

		lastWasBlank   = false
		lastWasHeading = false
	)

	close := func() {
		if para != nil {
			out = append(out, block{opPara, para})
			para = nil
		}
	}

	lines := strings.SplitAfter(text, "\n")
	unindent(lines)
	for i := 0; i < len(lines); {
		line := lines[i]
		if isBlank(line) {
			// close paragraph
			close()
			i++
			lastWasBlank = true
			continue
		}
		if indentLen(line) > 0 {
			// close paragraph
			close()

			// count indented or blank lines
			j := i + 1
			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
				j++
			}
			// but not trailing blank lines
			for j > i && isBlank(lines[j-1]) {
				j--
			}
			pre := lines[i:j]
			i = j

			unindent(pre)

			// put those lines in a pre block
			out = append(out, block{opPre, pre})
			lastWasHeading = false
			continue
		}

		if lastWasBlank && !lastWasHeading && i+2 < len(lines) &&
			isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 {
			// current line is non-blank, sourounded by blank lines
			// and the next non-blank line is not indented: this
			// might be a heading.
			if head := heading(line); head != "" {
				close()
				out = append(out, block{opHead, []string{head}})
				i += 2
				lastWasHeading = true
				continue
			}
		}

		// open paragraph
		lastWasBlank = false
		lastWasHeading = false
		para = append(para, lines[i])
		i++
	}
	close()

	return out
}

// ToText prepares comment text for presentation in textual output.
// It wraps paragraphs of text to width or fewer Unicode code points
// and then prefixes each line with the indent.  In preformatted sections
// (such as program text), it prefixes each non-blank line with preIndent.
func ToText(w io.Writer, text string, indent, preIndent string, width int) {
	l := lineWrapper{
		out:    w,
		width:  width,
		indent: indent,
	}
	for i, b := range blocks(text) {
		switch b.op {
		case opPara:
			if i > 0 {
				w.Write(nl)
			}
			for _, line := range b.lines {
				l.write(line)
			}
			l.flush()
		case opHead:
			w.Write(nl)
			for _, line := range b.lines {
				l.write(line + "\n")
			}
			l.flush()
		case opPre:
			w.Write(nl)
			for _, line := range b.lines {
				if !isBlank(line) {
					w.Write([]byte(preIndent))
					w.Write([]byte(line))
				}
			}
		}
	}
}

type lineWrapper struct {
	out       io.Writer
	printed   bool
	width     int
	indent    string
	n         int
	pendSpace int
}

var nl = []byte("\n")
var space = []byte(" ")

func (l *lineWrapper) write(text string) {
	if l.n == 0 && l.printed {
		l.out.Write(nl) // blank line before new paragraph
	}
	l.printed = true

	for _, f := range strings.Fields(text) {
		w := utf8.RuneCountInString(f)
		// wrap if line is too long
		if l.n > 0 && l.n+l.pendSpace+w > l.width {
			l.out.Write(nl)
			l.n = 0
			l.pendSpace = 0
		}
		if l.n == 0 {
			l.out.Write([]byte(l.indent))
		}
		l.out.Write(space[:l.pendSpace])
		l.out.Write([]byte(f))
		l.n += l.pendSpace + w
		l.pendSpace = 1
	}
}

func (l *lineWrapper) flush() {
	if l.n == 0 {
		return
	}
	l.out.Write(nl)
	l.pendSpace = 0
	l.n = 0
}
<commit_msg>go/doc: print only one newline between paragraphs Fixes issue 2595.<commit_after>// Copyright 2009 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.

// Godoc comment extraction and comment -> HTML formatting.

package doc

import (
	"io"
	"regexp"
	"strings"
	"text/template" // for HTMLEscape
	"unicode"
	"unicode/utf8"
)

var (
	ldquo = []byte("“")
	rdquo = []byte("”")
)

// Escape comment text for HTML. If nice is set,
// also turn `` into “ and '' into ”.
func commentEscape(w io.Writer, text string, nice bool) {
	last := 0
	if nice {
		for i := 0; i < len(text)-1; i++ {
			ch := text[i]
			if ch == text[i+1] && (ch == '`' || ch == '\'') {
				template.HTMLEscape(w, []byte(text[last:i]))
				last = i + 2
				switch ch {
				case '`':
					w.Write(ldquo)
				case '\'':
					w.Write(rdquo)
				}
				i++ // loop will add one more
			}
		}
	}
	template.HTMLEscape(w, []byte(text[last:]))
}

const (
	// Regexp for Go identifiers
	identRx = `[a-zA-Z_][a-zA-Z_0-9]*` // TODO(gri) ASCII only for now - fix this

	// Regexp for URLs
	protocol = `(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero):`
	hostPart = `[a-zA-Z0-9_@\-]+`
	filePart = `[a-zA-Z0-9_?%#~&/\-+=]+`
	urlRx    = protocol + `//` + // http://
		hostPart + `([.:]` + hostPart + `)*/?` + // //www.google.com:8080/
		filePart + `([:.,]` + filePart + `)*`
)

var matchRx = regexp.MustCompile(`(` + identRx + `)|(` + urlRx + `)`)

var (
	html_a      = []byte(`<a href="`)
	html_aq     = []byte(`">`)
	html_enda   = []byte("")
	html_i      = []byte("")
	html_endi   = []byte("")
	html_p      = []byte("
\n")
	html_endp   = []byte("
\n")
	html_pre    = []byte("
")
	html_endpre = []byte("
\n")
	html_h      = []byte("
")
	html_endh   = []byte("
\n")
)

// Emphasize and escape a line of text for HTML. URLs are converted into links;
// if the URL also appears in the words map, the link is taken from the map (if
// the corresponding map value is the empty string, the URL is not converted
// into a link). Go identifiers that appear in the words map are italicized; if
// the corresponding map value is not the empty string, it is considered a URL
// and the word is converted into a link. If nice is set, the remaining text's
// appearance is improved where it makes sense (e.g., `` is turned into “
// and '' into ”).
func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
	for {
		m := matchRx.FindStringSubmatchIndex(line)
		if m == nil {
			break
		}
		// m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is identRx)

		// write text before match
		commentEscape(w, line[0:m[0]], nice)

		// analyze match
		match := line[m[0]:m[1]]
		url := ""
		italics := false
		if words != nil {
			url, italics = words[string(match)]
		}
		if m[2] < 0 {
			// didn't match against first parenthesized sub-regexp; must be match against urlRx
			if !italics {
				// no alternative URL in words list, use match instead
				url = string(match)
			}
			italics = false // don't italicize URLs
		}

		// write match
		if len(url) > 0 {
			w.Write(html_a)
			template.HTMLEscape(w, []byte(url))
			w.Write(html_aq)
		}
		if italics {
			w.Write(html_i)
		}
		commentEscape(w, match, nice)
		if italics {
			w.Write(html_endi)
		}
		if len(url) > 0 {
			w.Write(html_enda)
		}

		// advance
		line = line[m[1]:]
	}
	commentEscape(w, line, nice)
}

func indentLen(s string) int {
	i := 0
	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
		i++
	}
	return i
}

func isBlank(s string) bool {
	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
}

func commonPrefix(a, b string) string {
	i := 0
	for i < len(a) && i < len(b) && a[i] == b[i] {
		i++
	}
	return a[0:i]
}

func unindent(block []string) {
	if len(block) == 0 {
		return
	}

	// compute maximum common white prefix
	prefix := block[0][0:indentLen(block[0])]
	for _, line := range block {
		if !isBlank(line) {
			prefix = commonPrefix(prefix, line[0:indentLen(line)])
		}
	}
	n := len(prefix)

	// remove
	for i, line := range block {
		if !isBlank(line) {
			block[i] = line[n:]
		}
	}
}

// heading returns the trimmed line if it passes as a section heading;
// otherwise it returns the empty string.
func heading(line string) string {
	line = strings.TrimSpace(line)
	if len(line) == 0 {
		return ""
	}

	// a heading must start with an uppercase letter
	r, _ := utf8.DecodeRuneInString(line)
	if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
		return ""
	}

	// it must end in a letter or digit:
	r, _ = utf8.DecodeLastRuneInString(line)
	if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
		return ""
	}

	// exclude lines with illegal characters
	if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
		return ""
	}

	// allow "'" for possessive "'s" only
	for b := line; ; {
		i := strings.IndexRune(b, '\'')
		if i < 0 {
			break
		}
		if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
			return "" // not followed by "s "
		}
		b = b[i+2:]
	}

	return line
}

type op int

const (
	opPara op = iota
	opHead
	opPre
)

type block struct {
	op    op
	lines []string
}

// ToHTML converts comment text to formatted HTML.
// The comment was prepared by DocReader,
// so it is known not to have leading, trailing blank lines
// nor to have trailing spaces at the end of lines.
// The comment markers have already been removed.
//
// Turn each run of multiple \n into

.
// Turn each run of indented lines into a
 block without indent.
// Enclose headings with header tags.
//
// URLs in the comment text are converted into links; if the URL also appears
// in the words map, the link is taken from the map (if the corresponding map
// value is the empty string, the URL is not converted into a link).
//
// Go identifiers that appear in the words map are italicized; if the corresponding
// map value is not the empty string, it is considered a URL and the word is converted
// into a link.
func ToHTML(w io.Writer, text string, words map[string]string) {
	for _, b := range blocks(text) {
		switch b.op {
		case opPara:
			w.Write(html_p)
			for _, line := range b.lines {
				emphasize(w, line, words, true)
			}
			w.Write(html_endp)
		case opHead:
			w.Write(html_h)
			for _, line := range b.lines {
				commentEscape(w, line, true)
			}
			w.Write(html_endh)
		case opPre:
			w.Write(html_pre)
			for _, line := range b.lines {
				emphasize(w, line, nil, false)
			}
			w.Write(html_endpre)
		}
	}
}

func blocks(text string) []block {
	var (
		out  []block
		para []string

		lastWasBlank   = false
		lastWasHeading = false
	)

	close := func() {
		if para != nil {
			out = append(out, block{opPara, para})
			para = nil
		}
	}

	lines := strings.SplitAfter(text, "\n")
	unindent(lines)
	for i := 0; i < len(lines); {
		line := lines[i]
		if isBlank(line) {
			// close paragraph
			close()
			i++
			lastWasBlank = true
			continue
		}
		if indentLen(line) > 0 {
			// close paragraph
			close()

			// count indented or blank lines
			j := i + 1
			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
				j++
			}
			// but not trailing blank lines
			for j > i && isBlank(lines[j-1]) {
				j--
			}
			pre := lines[i:j]
			i = j

			unindent(pre)

			// put those lines in a pre block
			out = append(out, block{opPre, pre})
			lastWasHeading = false
			continue
		}

		if lastWasBlank && !lastWasHeading && i+2 < len(lines) &&
			isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 {
			// current line is non-blank, sourounded by blank lines
			// and the next non-blank line is not indented: this
			// might be a heading.
			if head := heading(line); head != "" {
				close()
				out = append(out, block{opHead, []string{head}})
				i += 2
				lastWasHeading = true
				continue
			}
		}

		// open paragraph
		lastWasBlank = false
		lastWasHeading = false
		para = append(para, lines[i])
		i++
	}
	close()

	return out
}

// ToText prepares comment text for presentation in textual output.
// It wraps paragraphs of text to width or fewer Unicode code points
// and then prefixes each line with the indent.  In preformatted sections
// (such as program text), it prefixes each non-blank line with preIndent.
func ToText(w io.Writer, text string, indent, preIndent string, width int) {
	l := lineWrapper{
		out:    w,
		width:  width,
		indent: indent,
	}
	for _, b := range blocks(text) {
		switch b.op {
		case opPara:
			// l.write will add leading newline if required
			for _, line := range b.lines {
				l.write(line)
			}
			l.flush()
		case opHead:
			w.Write(nl)
			for _, line := range b.lines {
				l.write(line + "\n")
			}
			l.flush()
		case opPre:
			w.Write(nl)
			for _, line := range b.lines {
				if !isBlank(line) {
					w.Write([]byte(preIndent))
					w.Write([]byte(line))
				}
			}
		}
	}
}

type lineWrapper struct {
	out       io.Writer
	printed   bool
	width     int
	indent    string
	n         int
	pendSpace int
}

var nl = []byte("\n")
var space = []byte(" ")

func (l *lineWrapper) write(text string) {
	if l.n == 0 && l.printed {
		l.out.Write(nl) // blank line before new paragraph
	}
	l.printed = true

	for _, f := range strings.Fields(text) {
		w := utf8.RuneCountInString(f)
		// wrap if line is too long
		if l.n > 0 && l.n+l.pendSpace+w > l.width {
			l.out.Write(nl)
			l.n = 0
			l.pendSpace = 0
		}
		if l.n == 0 {
			l.out.Write([]byte(l.indent))
		}
		l.out.Write(space[:l.pendSpace])
		l.out.Write([]byte(f))
		l.n += l.pendSpace + w
		l.pendSpace = 1
	}
}

func (l *lineWrapper) flush() {
	if l.n == 0 {
		return
	}
	l.out.Write(nl)
	l.pendSpace = 0
	l.n = 0
}
<|endoftext|>