<commit_before>// Copyright (c) 2012-2015 José Carlos Nieto, https://menteslibres.net/xiam
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Package exif provides bindings for libexif.
package exif

/*
#cgo LDFLAGS: -lexif

#include <stdlib.h>
#include <libexif/exif-data.h>
#include <libexif/exif-loader.h>
#include "_cgo/types.h"

exif_value_t* pop_exif_value(exif_stack_t *);
void free_exif_value(exif_value_t* n);
exif_stack_t* exif_dump(ExifData *);

*/
import "C"

import (
	"errors"
	"fmt"
	"runtime"
	"strings"
	"unsafe"
)

// Error messages.
var (
	ErrNoExifData      = errors.New(`No EXIF data found.`)
	ErrFoundExifInData = errors.New(`Found EXIF header. OK to call Parse.`)
)

// Data stores the EXIF tags of a file.
type Data struct {
	exifLoader *C.ExifLoader
	Tags       map[string]string
}

// New creates and returns a new exif.Data object.
func New() *Data {
	data := &Data{
		Tags: make(map[string]string),
	}
	return data
}

// Read attempts to read EXIF data from a file.
func Read(file string) (*Data, error) {
	data := New()
	if err := data.Open(file); err != nil {
		return nil, err
	}
	return data, nil
}

// Open opens a file path and loads its EXIF data.
func (d *Data) Open(file string) error {

	cfile := C.CString(file)
	defer C.free(unsafe.Pointer(cfile))

	exifData := C.exif_data_new_from_file(cfile)

	if exifData == nil {
		return ErrNoExifData
	}
	defer C.exif_data_unref(exifData)

	return d.parseExifData(exifData)
}

func (d *Data) parseExifData(exifData *C.ExifData) error {
	values := C.exif_dump(exifData)
	defer C.free(unsafe.Pointer(values))

	for {
		value := C.pop_exif_value(values)
		if value == nil {
			break
		} else {
			d.Tags[strings.Trim(C.GoString((*value).name), " ")] = strings.Trim(C.GoString((*value).value), " ")
		}
		C.free_exif_value(value)
	}

	return nil
}

// Write writes bytes to the exif loader. Sends ErrFoundExifInData error when
// enough bytes have been sent.
func (d *Data) Write(p []byte) (n int, err error) {
	if d.exifLoader == nil {
		d.exifLoader = C.exif_loader_new()
		runtime.SetFinalizer(d, (*Data).cleanup)
	}

	res := C.exif_loader_write(d.exifLoader, (*C.uchar)(unsafe.Pointer(&p[0])), C.uint(len(p)))

	if res == 1 {
		return len(p), nil
	}
	return len(p), ErrFoundExifInData
}

// Parse finalizes the data loader and sets the tags
func (d *Data) Parse() error {
	defer d.cleanup()

	exifData := C.exif_loader_get_data(d.exifLoader)
	if exifData == nil {
		return fmt.Errorf(ErrNoExifData.Error(), "")
	}

	defer func() {
		C.exif_data_unref(exifData)
	}()

	return d.parseExifData(exifData)
}

func (d *Data) cleanup() {
	if d.exifLoader != nil {
		C.exif_loader_unref(d.exifLoader)
		d.exifLoader = nil
	}
}
<commit_msg>Fix include with pkg-config<commit_after>// Copyright (c) 2012-2015 José Carlos Nieto, https://menteslibres.net/xiam
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Package exif provides bindings for libexif.
package exif

/*
#cgo LDFLAGS: -lexif
#cgo pkg-config: libexif

#include <stdlib.h>
#include <libexif/exif-data.h>
#include <libexif/exif-loader.h>
#include "_cgo/types.h"

exif_value_t* pop_exif_value(exif_stack_t *);
void free_exif_value(exif_value_t* n);
exif_stack_t* exif_dump(ExifData *);

*/
import "C"

import (
	"errors"
	"fmt"
	"runtime"
	"strings"
	"unsafe"
)

// Error messages.
var (
	ErrNoExifData      = errors.New(`No EXIF data found.`)
	ErrFoundExifInData = errors.New(`Found EXIF header. OK to call Parse.`)
)

// Data stores the EXIF tags of a file.
type Data struct {
	exifLoader *C.ExifLoader
	Tags       map[string]string
}

// New creates and returns a new exif.Data object.
func New() *Data {
	data := &Data{
		Tags: make(map[string]string),
	}
	return data
}

// Read attempts to read EXIF data from a file.
func Read(file string) (*Data, error) {
	data := New()
	if err := data.Open(file); err != nil {
		return nil, err
	}
	return data, nil
}

// Open opens a file path and loads its EXIF data.
func (d *Data) Open(file string) error {

	cfile := C.CString(file)
	defer C.free(unsafe.Pointer(cfile))

	exifData := C.exif_data_new_from_file(cfile)

	if exifData == nil {
		return ErrNoExifData
	}
	defer C.exif_data_unref(exifData)

	return d.parseExifData(exifData)
}

func (d *Data) parseExifData(exifData *C.ExifData) error {
	values := C.exif_dump(exifData)
	defer C.free(unsafe.Pointer(values))

	for {
		value := C.pop_exif_value(values)
		if value == nil {
			break
		} else {
			d.Tags[strings.Trim(C.GoString((*value).name), " ")] = strings.Trim(C.GoString((*value).value), " ")
		}
		C.free_exif_value(value)
	}

	return nil
}

// Write writes bytes to the exif loader. Sends ErrFoundExifInData error when
// enough bytes have been sent.
func (d *Data) Write(p []byte) (n int, err error) {
	if d.exifLoader == nil {
		d.exifLoader = C.exif_loader_new()
		runtime.SetFinalizer(d, (*Data).cleanup)
	}

	res := C.exif_loader_write(d.exifLoader, (*C.uchar)(unsafe.Pointer(&p[0])), C.uint(len(p)))

	if res == 1 {
		return len(p), nil
	}
	return len(p), ErrFoundExifInData
}

// Parse finalizes the data loader and sets the tags
func (d *Data) Parse() error {
	defer d.cleanup()

	exifData := C.exif_loader_get_data(d.exifLoader)
	if exifData == nil {
		return fmt.Errorf(ErrNoExifData.Error(), "")
	}

	defer func() {
		C.exif_data_unref(exifData)
	}()

	return d.parseExifData(exifData)
}

func (d *Data) cleanup() {
	if d.exifLoader != nil {
		C.exif_loader_unref(d.exifLoader)
		d.exifLoader = nil
	}
}
<|endoftext|>


<commit_before>/*
 * echoserver
 * James McDonald <james@jamesmcdonald.com>
 *
 * Echo the URI path in the request back to the client.
 */

package main

import (
    "fmt"
    "log"
    "net/http"
)

func Handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, r.URL.Path)
}

func main() {
    http.HandleFunc("/", Handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>Ran echoserver through gofmt<commit_after>/*
 * echoserver
 * James McDonald <james@jamesmcdonald.com>
 *
 * Echo the URI path in the request back to the client.
 */

package main

import (
	"fmt"
	"log"
	"net/http"
)

func Handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, r.URL.Path)
}

func main() {
	http.HandleFunc("/", Handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<|endoftext|>


<commit_before>package edifact

import (
	"bytes"
	"errors"
	"fmt"
	"unicode/utf8"
)

// Unmarshals a byte slice like this: UNA~|.?^'
func unmarshalUNA(data []byte) (int, *EDIFACT, error) {
	if len(data) < 3 {
		return 0, nil, errors.New("Length of data is too small")
	}

	// Return the default UNA delimiters
	if !bytes.Equal(data[:3], []byte(UNA_SEGMENT_CODE)) {
		return 0, NewDefault(), nil
	}

	return 9, &EDIFACT{
		ComponentDelimiter: data[3],
		DataDelimiter:      data[4],
		Decimal:            data[5],
		ReleaseIndicator:   data[6],
		ReservedDelimiter:  data[7],
		SegmentTerminator:  data[8],
	}, nil
}

func Unmarshal(data []byte) ([]Segment, error) {
	var segments []Segment

	n, ef, err := unmarshalUNA(data)
	if err != nil {
		return nil, err
	}

	// Skip UNA header if there is one
	data = data[n:]

	if data[len(data)-1] != ef.SegmentTerminator {
		return nil, errors.New(fmt.Sprintf("Data is not terminated by the segment terminator: %c", ef.SegmentTerminator))
	}

	byteSegments := splitWithEscape(data, []byte{ef.SegmentTerminator}, []byte{ef.ReleaseIndicator})

	// Because of the way split works, and a segment is terminated
	// and not delimited, we will have a blank segment at the end.
	// Remove it.
	byteSegments = byteSegments[:len(byteSegments)-1]

	// By the spec, we 4 segments are mandatory, but we'll be
	// forgiving and test for only one, since we can still parse
	// it.
	if len(byteSegments) < 1 {
		return nil, errors.New("Data does not contain any segments")
	}

	for _, byteSegment := range byteSegments {
		var segment Segment
		byteDataSlice := splitWithEscape(byteSegment, []byte{ef.DataDelimiter}, []byte{ef.ReleaseIndicator})

		for _, byteData := range byteDataSlice {
			//var components []string
			//fmt.Printf("%q\n", byteData)

			delimiter := ef.ComponentDelimiter

			// rn := bytes.IndexByte(byteData, ef.ReservedDelimiter)
			// if rn != -1 && rn > 0 && byteData[rn-1] != ef.ReleaseIndicator {
			//   delimiter = ef.ReservedDelimiter
			// }

			components := splitWithEscape(byteData, []byte{delimiter}, []byte{ef.ReleaseIndicator})
			if len(components) == 0 {
				segment = append(segment, "")
			} else if len(components) == 1 {
				segment = append(segment, string(removeEscape(components[0], []byte{ef.ReleaseIndicator})))
			}

			//fmt.Printf("%q\n", components)
		}

		segments = append(segments, segment)
	}

	return segments, nil
}

// Removes an escape character. If the escape character
// is itself escaped, then one is left.
func removeEscape(s, escape []byte) []byte {
	if len(s) == 0 {
		return []byte("")
	}

	ec := bytes.Count(s, escape)
	ec = ec - bytes.Count(s, append(escape, escape...))
	s2 := make([]byte, len(s)-(len(escape)*ec))

	for i, i2 := 0, 0; i < len(s) && i2 < len(s2); i, i2 = i+1, i2+1 {
		if s[i] == escape[0] && (len(escape) == 1 || bytes.Equal(s[i:i+len(escape)], escape)) {
			if len(s) > (i+2*len(escape)) && bytes.Equal(s[i+len(escape):i+2*len(escape)], escape) {
				s2[i] = s[i]
				continue
			}
			i2 -= 1
		} else {
			s2[i2] = s[i]
		}
	}

	return s2
}

// explode splits s into an array of UTF-8 sequences, one per Unicode character (still arrays of bytes),
// up to a maximum of n byte arrays. Invalid UTF-8 sequences are chopped into individual bytes.
func explode(s []byte, n int) [][]byte {
	if n <= 0 {
		n = len(s)
	}
	a := make([][]byte, n)
	var size int
	na := 0
	for len(s) > 0 {
		if na+1 >= n {
			a[na] = s
			na++
			break
		}
		_, size = utf8.DecodeRune(s)
		a[na] = s[0:size]
		s = s[size:]
		na++
	}
	return a[0:na]
}

// Splits a []byte by the given seperator, and honoring
// the escape []byte. If an escape comes right before the
// separator, then it is not split at that junction.
// You can use escape to escape itself, in which case if an
// escape is escaped right before a separator, then it will
// be split at that junction.
func splitWithEscape(s, sep []byte, escape []byte) [][]byte {
	sepSave := 0
	n := -1

	if n == 0 {
		return nil
	}
	if len(sep) == 0 {
		return explode(s, n)
	}
	if n < 0 {
		n = bytes.Count(s, sep) + 1
		// subtract separators that are escaped
		n = n - bytes.Count(s, append(escape, sep...)) + 1
	}
	c := sep[0]
	start := 0
	a := make([][]byte, n)
	na := 0

	escapeCount := 0
	for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
		foundEscape := i+len(escape) < len(s) && bytes.Equal(s[i:i+len(escape)], escape)
		if foundEscape {
			escapeCount++
		}

		if s[i] == c && (len(sep) == 1 || bytes.Equal(s[i:i+len(sep)], sep)) && escapeCount == 0 {
			a[na] = s[start : i+sepSave]
			na++
			start = i + len(sep)
			i += len(sep) - 1
		}

		// Reset if we didn't find an escape.
		// Reset if the escapeCount is 2, because this means
		// the escape escaped itself.
		if !foundEscape || escapeCount == 2 {
			escapeCount = 0
		}
	}
	a[na] = s[start:]
	return a[0 : na+1]
}
<commit_msg>Removed unused edifact dir<commit_after><|endoftext|>


<commit_before>package expr

import (
	"gopkg.in/antonmedv/expr.v2/checker"
	"gopkg.in/antonmedv/expr.v2/compiler"
	"gopkg.in/antonmedv/expr.v2/parser"
	"gopkg.in/antonmedv/expr.v2/vm"
	"reflect"
)

// Eval parses, compiles and runs given input.
func Eval(input string, env interface{}) (interface{}, error) {
	tree, err := parser.Parse(input)
	if err != nil {
		return nil, err
	}

	program, err := compiler.Compile(tree)
	if err != nil {
		return nil, err
	}

	output, err := vm.Run(program, env)
	if err != nil {
		return nil, err
	}

	return output, nil
}

type config struct {
	mapEnv bool
	types  checker.TypesTable
}

// OptionFn for configuring expr.
type OptionFn func(c *config)

// Env specifies expected input of env for type checks.
// If struct is passed, all fields will be treated as variables,
// as well as all fields of embedded structs and struct itself.
// If map is passed, all items will be treated as variables.
// Methods defined on this type will be available as functions.
func Env(i interface{}) OptionFn {
	return func(c *config) {
		if _, ok := i.(map[string]interface{}); ok {
			c.mapEnv = true
		}
		c.types = checker.CreateTypesTable(i)
	}
}

// CompileType compiles input and returns program with output type, if Env was specified.
func CompileType(input string, ops ...OptionFn) (*vm.Program, reflect.Type, error) {
	c := &config{}

	for _, op := range ops {
		op(c)
	}

	tree, err := parser.Parse(input)
	if err != nil {
		return nil, nil, err
	}

	var t reflect.Type
	if c.types != nil {
		t, err = checker.Check(tree, c.types)
		if err != nil {
			return nil, nil, err
		}
	}

	compilerOps := make([]compiler.OptionFn, 0)
	if c.mapEnv {
		compilerOps = append(compilerOps, compiler.MapEnv())
	}

	program, err := compiler.Compile(tree, compilerOps...)
	if err != nil {
		return nil, nil, err
	}

	return program, t, nil
}

// Compile parses and compiles given input expression to bytecode program.
func Compile(input string, ops ...OptionFn) (*vm.Program, error) {
	program, _, err := CompileType(input, ops...)
	return program, err
}

// Run evaluates given bytecode program.
func Run(program *vm.Program, env interface{}) (interface{}, error) {
	return vm.Run(program, env)
}
<commit_msg>Remove redundant CompileType func<commit_after>package expr

import (
	"gopkg.in/antonmedv/expr.v2/checker"
	"gopkg.in/antonmedv/expr.v2/compiler"
	"gopkg.in/antonmedv/expr.v2/parser"
	"gopkg.in/antonmedv/expr.v2/vm"
	"reflect"
)

// Eval parses, compiles and runs given input.
func Eval(input string, env interface{}) (interface{}, error) {
	tree, err := parser.Parse(input)
	if err != nil {
		return nil, err
	}

	program, err := compiler.Compile(tree)
	if err != nil {
		return nil, err
	}

	output, err := vm.Run(program, env)
	if err != nil {
		return nil, err
	}

	return output, nil
}

type config struct {
	mapEnv bool
	types  checker.TypesTable
}

// OptionFn for configuring expr.
type OptionFn func(c *config)

// Env specifies expected input of env for type checks.
// If struct is passed, all fields will be treated as variables,
// as well as all fields of embedded structs and struct itself.
// If map is passed, all items will be treated as variables.
// Methods defined on this type will be available as functions.
func Env(i interface{}) OptionFn {
	return func(c *config) {
		if _, ok := i.(map[string]interface{}); ok {
			c.mapEnv = true
		}
		c.types = checker.CreateTypesTable(i)
	}
}

// Compile parses and compiles given input expression to bytecode program.
func Compile(input string, ops ...OptionFn) (*vm.Program, reflect.Type, error) {
	c := &config{}

	for _, op := range ops {
		op(c)
	}

	tree, err := parser.Parse(input)
	if err != nil {
		return nil, nil, err
	}

	var t reflect.Type
	if c.types != nil {
		t, err = checker.Check(tree, c.types)
		if err != nil {
			return nil, nil, err
		}
	}

	compilerOps := make([]compiler.OptionFn, 0)
	if c.mapEnv {
		compilerOps = append(compilerOps, compiler.MapEnv())
	}

	program, err := compiler.Compile(tree, compilerOps...)
	if err != nil {
		return nil, nil, err
	}

	return program, t, nil
}

// Run evaluates given bytecode program.
func Run(program *vm.Program, env interface{}) (interface{}, error) {
	return vm.Run(program, env)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"runtime"
	"sync"

	"github.com/kisielk/whisper-go/whisper"
	"github.com/urfave/cli"
)

var (
	fillJobs int
	maxFills int
	fillLock *sync.Mutex
)

type Dirstate struct {
	Location string
	Contents map[string][]string
}

type Overlap struct {
	Source      string
	Destination string
	Contents    map[string][]string
}

func backFill(src string, dst string) error {
	// open our file handles
	sDb, sErr := whisper.Open(src)
	dDb, dErr := whisper.Open(dst)
	// check our error status
	if sErr != nil {
		return sErr
	} else if dErr != nil {
		return dErr
	}
	// defer db closes
	defer sDb.Close()
	defer dDb.Close()

	// now for each archive in src, if there's one that matches in dst, let's backfill
	for sIdx, sArc := range sDb.Header.Archives {
		for dIdx, dArc := range dDb.Header.Archives {
			// if we hit this we have found a compatible archive
			if sArc.Points == dArc.Points && sArc.SecondsPerPoint == dArc.SecondsPerPoint {
				sp, se := sDb.DumpArchive(sIdx)
				if se != nil {
					return se
				}
				dp, de := dDb.DumpArchive(dIdx)
				if de != nil {
					return de
				}
				// for every point in the src archive
				for sidx := 0; sidx < len(sp); sidx++ {
					// check all the points in the dst archive
					for didx := 0; didx < len(dp); didx++ {
						// if any dst point has the same timestamp
						if sp[sidx].Timestamp == dp[didx].Timestamp {
							// and the values aren't the same
							if dp[didx].Value != sp[sidx].Value {
								// update the dst
								dp[didx].Value = sp[sidx].Value
							}
						}
					}
				}
			}
		}
	}

	// and finally let the caller know nothing went wrong.
	return nil
}

func BackFill(c *cli.Context) {
	if len(c.Args()) < 2 {
		fmt.Println("You fucked up, look at the help output.")
	} else {
		srcArg := c.Args().Get(0)
		dstArg := c.Args().Get(1)
		// if we requested more jobs than the default, make sure we update that
		if c.Int("j") > maxFills {
			maxFills = c.Int("j")
		}
		// if both our arguments are files
		if isFile(srcArg) && isFile(dstArg) {
			NewInfo(fmt.Sprintf("Backfill: %s -> %s", srcArg, dstArg))
			backFill(srcArg, dstArg)
		} else if isDir(srcArg) && isDir(dstArg) {
			return
		} else {
			fmt.Println("You cannot mix files and directories as src and dst.")
			os.Exit(1)
		}
	}
	return
}

/*

func BackFill(c *cli.Context) {
	if len(c.Args()) < 2 {
		Error <- "Invalid arguments. See 'flustro help fill' for more information."
		os.Exit(1)
	} else {
		// declare our variables
		var srcObj Dirstate
		var dstObj Dirstate
		srcDir := c.Args().Get(0)
		dstDir := c.Args().Get(1)

		// Now let's do the heavy lifting
		if isDir(srcDir) && isDir(dstDir) {
			// First let's get our dir contents
			srcObj = ListDir(srcDir)
			dstObj = ListDir(dstDir)
			// then spawn our worker pool, and get to processing
			for i := 0; i < c.Int("j"); i++ {
				go Filler()
			}
			// next we'll start processing through our srcObj and dstObj lists and
			// backfill everything that's present in both locations
			overlap := Overlap{
				Source:      srcObj.Location,
				Destination: dstObj.Location,
				Contents:    make(map[string][]string),
			}
			overlap_c := 0
			for k, _ := range srcObj.Contents {
				if _, ok := dstObj.Contents[k]; ok {
					for _, v := range srcObj.Contents[k] {
						for _, dv := range dstObj.Contents[k] {
							if v == dv {
								if _, ok := overlap.Contents[k]; ok {
									overlap.Contents[k] = append(overlap.Contents[k], v)
									overlap_c++
								} else {
									overlap.Contents[k] = []string{v}
									overlap_c++
								}
							}
						}
					}
				}
			}
			Info <- fmt.Sprintf("%d entries shared between %s and %s.",
				overlap_c,
				overlap.Source,
				overlap.Destination)
			for k, v := range overlap.Contents {
				for _, f := range v {
					DataChan <- map[string]string{
						"Source":      fmt.Sprintf("%s/%s/%s", overlap.Source, k, f),
						"Destination": fmt.Sprintf("%s/%s/%s", overlap.Destination, k, f),
					}
				}
			}
		} else if isFile(srcDir) && isFile(dstDir) {
			// we only need one worker for this job
			go Filler()
			DataChan <- map[string]string{
				"Source":      srcDir,
				"Destination": dstDir,
			}
		} else {
			Error <- fmt.Sprintf("SRC and DST must be either both files or both dirs.")
		}

		time.Sleep(500 * time.Millisecond)
	}
	return
}

*/
func init() {
	fillJobs = 0
	maxFills = runtime.GOMAXPROCS(0) * 2
	fillLock = &sync.Mutex{}
	Commands = append(Commands, cli.Command{
		Name:        "fill",
		Aliases:     []string{"f"},
		Usage:       "Backfill datapoints in the dst from the src",
		Description: "Backfill datapoints in the dst from the src",
		ArgsUsage:   "<src(File|Dir)> <dst(File|Dir)>",
		Flags: []cli.Flag{
			cli.IntFlag{
				Name:  "j",
				Usage: "Number of workers (for directory recursion)",
				Value: runtime.GOMAXPROCS(0) * 2,
			},
		},
		SkipFlagParsing: false,
		HideHelp:        false,
		Hidden:          false,
		Action:          BackFill,
	})
}
<commit_msg>simple is better<commit_after>package main

import (
	"fmt"
	"os"
	"runtime"
	"sync"
	"time"

	"github.com/kisielk/whisper-go/whisper"
	"github.com/splatpm/subhuman"
	"github.com/urfave/cli"
)

var (
	fillJobs int
	doneJobs int
	maxFills int
	fillLock *sync.Mutex
)

type Dirstate struct {
	Location string
	Contents map[string][]string
}

type Overlap struct {
	Source      string
	Destination string
	Contents    map[string][]string
}

func backFill(src string, dst string) error {
	// get the lock on our jobs tracker
	fillLock.Lock()
	// increment the tracker
	fillJobs++
	// and release the lock
	fillLock.Unlock()

	// open our file handles
	sDb, sErr := whisper.Open(src)
	dDb, dErr := whisper.Open(dst)
	// check our error status
	if sErr != nil {
		return sErr
	} else if dErr != nil {
		return dErr
	}
	// defer db closes
	defer sDb.Close()
	defer dDb.Close()
	if sDb.Header.Metadata.ArchiveCount != dDb.Header.Metadata.ArchiveCount {
		return fmt.Errorf("The files have a mismatched set of archives.")
	} else {
		// Now we'll start processing the archives, checking as we go to see if they
		// are matched. That way we at least fill in what we can, possibly....
		for i, a := range sDb.Header.Archives {
			// The offset
			if a.Offset == dDb.Header.Archives[i].Offset {
				// and the number of points
				if a.Points == dDb.Header.Archives[i].Points {
					// and finally the interval
					if a.SecondsPerPoint == dDb.Header.Archives[i].SecondsPerPoint {
						// ok, now let's get rolling through the archives
						sp, se := sDb.DumpArchive(i)
						if se != nil {
							return se
						}
						dp, de := dDb.DumpArchive(i)
						if de != nil {
							return de
						}
						for idx := 0; idx < len(sp); idx++ {
							if sp[idx].Timestamp != 0 && sp[idx].Value != 0 {
								if dp[idx].Timestamp == 0 || dp[idx].Value == 0 {
									dp[idx].Timestamp = sp[idx].Timestamp
									dp[idx].Value = sp[idx].Value
									dDb.Update(dp[idx])
								}
							}
						}
					}
				}
			}
		}
	}
	fillLock.Lock()
	fillJobs--
	doneJobs++
	fillLock.Unlock()
	// and finally let the caller know nothing went wrong.
	return nil
}

func BackFill(c *cli.Context) {
	if len(c.Args()) < 2 {
		fmt.Println("You fucked up, look at the help output.")
	} else {
		srcArg := c.Args().Get(0)
		dstArg := c.Args().Get(1)
		// if we requested more jobs than the default, make sure we update that
		if c.Int("j") != maxFills {
			maxFills = c.Int("j")
		}
		// if both our arguments are files
		if isFile(srcArg) && isFile(dstArg) {
			// NewInfo(fmt.Sprintf("Backfill: %s -> %s", srcArg, dstArg))
			StartTime := time.Now().Unix()
			backFill(srcArg, dstArg)
			NewInfo(fmt.Sprintf("Filled %d of 1 files: %s", doneJobs, subhuman.HumanTimeColon(time.Now().Unix()-StartTime)))
		} else if isDir(srcArg) && isDir(dstArg) {
			// get our directory lists
			overlap, totFills := CollateDirs(srcArg, dstArg)
			Status(fmt.Sprintf("Filled %d of %d files (%3.02f%%): %s",
				doneJobs,
				totFills,
				((float32(doneJobs) / float32(totFills)) * 100.0),
				subhuman.HumanTimeColon(time.Now().Unix()-StartTime)))
			StartTime := time.Now().Unix()
			for k, v := range overlap.Contents {
				for _, f := range v {
					// this waits until there are free job slots
					for fillJobs >= maxFills {
						now := time.Now().Unix()
						rate := int64(float64(doneJobs) / (float64(now) - float64(StartTime)))
						Status(
							fmt.Sprintf("Filled %d of %d files (%3.02f%%): %s @ %d/sec eta: %s",
								doneJobs,
								totFills,
								((float32(doneJobs) / float32(totFills)) * 100.0),
								subhuman.HumanTimeColon(now-StartTime),
								rate,
								subhuman.HumanTimeColon(int64(totFills-doneJobs)/rate)))
						time.Sleep(200 * time.Millisecond)
					}
					go backFill(fmt.Sprintf("%s/%s/%s",
						overlap.Source, k, f),
						fmt.Sprintf("%s/%s/%s",
							overlap.Destination, k, f))
					time.Sleep(100 * time.Millisecond)
				}
			}
			// wait for any stray jobs to finish
			for doneJobs < totFills {
				time.Sleep(10 * time.Millisecond)
			}
			// and print the final status
			Status(fmt.Sprintf("Filled %d of %d files (%3.02f%%): %s",
				doneJobs,
				totFills,
				((float32(doneJobs) / float32(totFills)) * 100.0),
				subhuman.HumanTimeColon(time.Now().Unix()-StartTime)))
			fmt.Println("")
		} else {
			fmt.Println("You cannot mix files and directories as src and dst.")
			os.Exit(1)
		}
	}
	return
}

func init() {
	fillJobs = 0
	doneJobs = 0
	maxFills = runtime.GOMAXPROCS(0) - 2
	fillLock = &sync.Mutex{}
	Commands = append(Commands, cli.Command{
		Name:        "fill",
		Aliases:     []string{"f"},
		Usage:       "Backfill datapoints in the dst from the src",
		Description: "Backfill datapoints in the dst from the src",
		ArgsUsage:   "<src(File|Dir)> <dst(File|Dir)>",
		Flags: []cli.Flag{
			cli.IntFlag{
				Name:  "j",
				Usage: "Number of workers (for directory recursion)",
				Value: runtime.GOMAXPROCS(0) - 2,
			},
		},
		SkipFlagParsing: false,
		HideHelp:        false,
		Hidden:          false,
		Action:          BackFill,
	})
}
<|endoftext|>


<commit_before>// TODO(u): Evaluate storing the samples (and residuals) during frame audio
// decoding in a buffer allocated for the stream. This buffer would be allocated
// using BlockSize and NChannels from the StreamInfo block, and it could be
// reused in between calls to Next and ParseNext. This should reduce GC
// pressure.

// Package flac provides access to FLAC (Free Lossless Audio Codec) streams.
//
// A brief introduction of the FLAC stream format [1] follows. Each FLAC stream
// starts with a 32-bit signature ("fLaC"), followed by one or more metadata
// blocks, and then one or more audio frames. The first metadata block
// (StreamInfo) describes the basic properties of the audio stream and it is the
// only mandatory metadata block. Subsequent metadata blocks may appear in an
// arbitrary order.
//
// Please refer to the documentation of the meta [2] and the frame [3] packages
// for a brief introduction of their respective formats.
//
//    [1]: https://www.xiph.org/flac/format.html#stream
//    [2]: https://godoc.org/github.com/mewkiz/flac/meta
//    [3]: https://godoc.org/github.com/mewkiz/flac/frame
package flac

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"

	"github.com/mewkiz/flac/frame"
	"github.com/mewkiz/flac/meta"

	"github.com/mikkyang/id3-go/encodedbytes"
)

// A Stream contains the metadata blocks and provides access to the audio frames
// of a FLAC stream.
//
// ref: https://www.xiph.org/flac/format.html#stream
type Stream struct {
	// The StreamInfo metadata block describes the basic properties of the FLAC
	// audio stream.
	Info *meta.StreamInfo
	// Zero or more metadata blocks.
	Blocks []*meta.Block
	// Underlying io.Reader.
	r io.Reader
	// Underlying io.Closer of file if opened with Open and ParseFile, and nil
	// otherwise.
	c io.Closer
}

// New creates a new Stream for accessing the audio samples of r. It reads and
// parses the FLAC signature and the StreamInfo metadata block, but skips all
// other metadata blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
func New(r io.Reader) (stream *Stream, err error) {
	// Verify FLAC signature and parse the StreamInfo metadata block.
	br := bufio.NewReader(r)
	stream = &Stream{r: br}
	isLast, err := stream.parseStreamInfo()
	if err != nil {
		return nil, err
	}

	// Skip the remaining metadata blocks.
	for !isLast {
		block, err := meta.New(br)
		if err != nil && err != meta.ErrReservedType {
			return stream, err
		}
		if err = block.Skip(); err != nil {
			return stream, err
		}
		isLast = block.IsLast
	}

	return stream, nil
}

// flacSignature marks the beginning of a FLAC stream.
var flacSignature = []byte("fLaC")

// id3Signature marks the beginning of an ID3 stream, used to skip over ID3 data.
var id3Signature = []byte("ID3")

// parseStreamInfo verifies the signature which marks the beginning of a FLAC
// stream, and parses the StreamInfo metadata block. It returns a boolean value
// which specifies if the StreamInfo block was the last metadata block of the
// FLAC stream.
func (stream *Stream) parseStreamInfo() (isLast bool, err error) {
	// Verify FLAC signature.
	r := stream.r
	var buf [4]byte
	if _, err = io.ReadFull(r, buf[:]); err != nil {
		return false, err
	}

	// Skip prepended ID3v2 data.
	if bytes.Equal(buf[:3], id3Signature) {
		if err := stream.skipID3v2(); err != nil {
			return false, err
		}

		// Second attempt at verifying signature.
		if _, err = io.ReadFull(r, buf[:]); err != nil {
			return false, err
		}
	}

	if !bytes.Equal(buf[:], flacSignature) {
		return false, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", flacSignature, buf)
	}

	// Parse StreamInfo metadata block.
	block, err := meta.Parse(r)
	if err != nil {
		return false, err
	}
	si, ok := block.Body.(*meta.StreamInfo)
	if !ok {
		return false, fmt.Errorf("flac.parseStreamInfo: incorrect type of first metadata block; expected *meta.StreamInfo, got %T", si)
	}
	stream.Info = si
	return block.IsLast, nil
}

// skipId3v2 skips ID3v2 data prepended to flac files.
func (stream *Stream) skipID3v2() error {
	r := bufio.NewReader(stream.r)

	// Discard unnecessary data from the ID3v2 header.
	if _, err := r.Discard(2); err != nil {
		return err
	}

	// Read the size from the ID3v2 header.
	var sizeBuf [4]byte
	if _, err := r.Read(sizeBuf[:]); err != nil {
		return err
	}

	// The size is encoded as a synchsafe integer.
	size, err := encodedbytes.SynchInt(sizeBuf[:])
	if err != nil {
		return err
	}

	_, err = r.Discard(int(size))
	return err
}

// Parse creates a new Stream for accessing the metadata blocks and audio
// samples of r. It reads and parses the FLAC signature and all metadata blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
func Parse(r io.Reader) (stream *Stream, err error) {
	// Verify FLAC signature and parse the StreamInfo metadata block.
	br := bufio.NewReader(r)
	stream = &Stream{r: br}
	isLast, err := stream.parseStreamInfo()
	if err != nil {
		return nil, err
	}

	// Parse the remaining metadata blocks.
	for !isLast {
		block, err := meta.Parse(br)
		if err != nil {
			if err != meta.ErrReservedType {
				return stream, err
			}
			// Skip the body of unknown (reserved) metadata blocks, as stated by
			// the specification.
			//
			// ref: https://www.xiph.org/flac/format.html#format_overview
			if err = block.Skip(); err != nil {
				return stream, err
			}
		}
		stream.Blocks = append(stream.Blocks, block)
		isLast = block.IsLast
	}

	return stream, nil
}

// Open creates a new Stream for accessing the audio samples of path. It reads
// and parses the FLAC signature and the StreamInfo metadata block, but skips
// all other metadata blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
//
// Note: The Close method of the stream must be called when finished using it.
func Open(path string) (stream *Stream, err error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	stream, err = New(f)
	if err != nil {
		return nil, err
	}
	stream.c = f
	return stream, err
}

// ParseFile creates a new Stream for accessing the metadata blocks and audio
// samples of path. It reads and parses the FLAC signature and all metadata
// blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
//
// Note: The Close method of the stream must be called when finished using it.
func ParseFile(path string) (stream *Stream, err error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	stream, err = Parse(f)
	if err != nil {
		return nil, err
	}
	stream.c = f
	return stream, err
}

// Close closes the stream if opened through a call to Open or ParseFile, and
// performs no operation otherwise.
func (stream *Stream) Close() error {
	if stream.c != nil {
		return stream.c.Close()
	}
	return nil
}

// Next parses the frame header of the next audio frame. It returns io.EOF to
// signal a graceful end of FLAC stream.
//
// Call Frame.Parse to parse the audio samples of its subframes.
func (stream *Stream) Next() (f *frame.Frame, err error) {
	return frame.New(stream.r)
}

// ParseNext parses the entire next frame including audio samples. It returns
// io.EOF to signal a graceful end of FLAC stream.
func (stream *Stream) ParseNext() (f *frame.Frame, err error) {
	return frame.Parse(stream.r)
}

// Seek is not implement yet.
func (stream *Stream) Seek(offset int64, whence int) (read int64, err error) {
	return 0, nil
}
<commit_msg>flac: minor update of comment<commit_after>// TODO(u): Evaluate storing the samples (and residuals) during frame audio
// decoding in a buffer allocated for the stream. This buffer would be allocated
// using BlockSize and NChannels from the StreamInfo block, and it could be
// reused in between calls to Next and ParseNext. This should reduce GC
// pressure.

// Package flac provides access to FLAC (Free Lossless Audio Codec) streams.
//
// A brief introduction of the FLAC stream format [1] follows. Each FLAC stream
// starts with a 32-bit signature ("fLaC"), followed by one or more metadata
// blocks, and then one or more audio frames. The first metadata block
// (StreamInfo) describes the basic properties of the audio stream and it is the
// only mandatory metadata block. Subsequent metadata blocks may appear in an
// arbitrary order.
//
// Please refer to the documentation of the meta [2] and the frame [3] packages
// for a brief introduction of their respective formats.
//
//    [1]: https://www.xiph.org/flac/format.html#stream
//    [2]: https://godoc.org/github.com/mewkiz/flac/meta
//    [3]: https://godoc.org/github.com/mewkiz/flac/frame
package flac

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"

	"github.com/mewkiz/flac/frame"
	"github.com/mewkiz/flac/meta"

	"github.com/mikkyang/id3-go/encodedbytes"
)

// A Stream contains the metadata blocks and provides access to the audio frames
// of a FLAC stream.
//
// ref: https://www.xiph.org/flac/format.html#stream
type Stream struct {
	// The StreamInfo metadata block describes the basic properties of the FLAC
	// audio stream.
	Info *meta.StreamInfo
	// Zero or more metadata blocks.
	Blocks []*meta.Block
	// Underlying io.Reader.
	r io.Reader
	// Underlying io.Closer of file if opened with Open and ParseFile, and nil
	// otherwise.
	c io.Closer
}

// New creates a new Stream for accessing the audio samples of r. It reads and
// parses the FLAC signature and the StreamInfo metadata block, but skips all
// other metadata blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
func New(r io.Reader) (stream *Stream, err error) {
	// Verify FLAC signature and parse the StreamInfo metadata block.
	br := bufio.NewReader(r)
	stream = &Stream{r: br}
	isLast, err := stream.parseStreamInfo()
	if err != nil {
		return nil, err
	}

	// Skip the remaining metadata blocks.
	for !isLast {
		block, err := meta.New(br)
		if err != nil && err != meta.ErrReservedType {
			return stream, err
		}
		if err = block.Skip(); err != nil {
			return stream, err
		}
		isLast = block.IsLast
	}

	return stream, nil
}

// flacSignature marks the beginning of a FLAC stream.
var flacSignature = []byte("fLaC")

// id3Signature marks the beginning of an ID3 stream, used to skip over ID3 data.
var id3Signature = []byte("ID3")

// parseStreamInfo verifies the signature which marks the beginning of a FLAC
// stream, and parses the StreamInfo metadata block. It returns a boolean value
// which specifies if the StreamInfo block was the last metadata block of the
// FLAC stream.
func (stream *Stream) parseStreamInfo() (isLast bool, err error) {
	// Verify FLAC signature.
	r := stream.r
	var buf [4]byte
	if _, err = io.ReadFull(r, buf[:]); err != nil {
		return false, err
	}

	// Skip prepended ID3v2 data.
	if bytes.Equal(buf[:3], id3Signature) {
		if err := stream.skipID3v2(); err != nil {
			return false, err
		}

		// Second attempt at verifying signature.
		if _, err = io.ReadFull(r, buf[:]); err != nil {
			return false, err
		}
	}

	if !bytes.Equal(buf[:], flacSignature) {
		return false, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", flacSignature, buf)
	}

	// Parse StreamInfo metadata block.
	block, err := meta.Parse(r)
	if err != nil {
		return false, err
	}
	si, ok := block.Body.(*meta.StreamInfo)
	if !ok {
		return false, fmt.Errorf("flac.parseStreamInfo: incorrect type of first metadata block; expected *meta.StreamInfo, got %T", si)
	}
	stream.Info = si
	return block.IsLast, nil
}

// skipID3v2 skips ID3v2 data prepended to flac files.
func (stream *Stream) skipID3v2() error {
	r := bufio.NewReader(stream.r)

	// Discard unnecessary data from the ID3v2 header.
	if _, err := r.Discard(2); err != nil {
		return err
	}

	// Read the size from the ID3v2 header.
	var sizeBuf [4]byte
	if _, err := r.Read(sizeBuf[:]); err != nil {
		return err
	}

	// The size is encoded as a synchsafe integer.
	size, err := encodedbytes.SynchInt(sizeBuf[:])
	if err != nil {
		return err
	}

	_, err = r.Discard(int(size))
	return err
}

// Parse creates a new Stream for accessing the metadata blocks and audio
// samples of r. It reads and parses the FLAC signature and all metadata blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
func Parse(r io.Reader) (stream *Stream, err error) {
	// Verify FLAC signature and parse the StreamInfo metadata block.
	br := bufio.NewReader(r)
	stream = &Stream{r: br}
	isLast, err := stream.parseStreamInfo()
	if err != nil {
		return nil, err
	}

	// Parse the remaining metadata blocks.
	for !isLast {
		block, err := meta.Parse(br)
		if err != nil {
			if err != meta.ErrReservedType {
				return stream, err
			}
			// Skip the body of unknown (reserved) metadata blocks, as stated by
			// the specification.
			//
			// ref: https://www.xiph.org/flac/format.html#format_overview
			if err = block.Skip(); err != nil {
				return stream, err
			}
		}
		stream.Blocks = append(stream.Blocks, block)
		isLast = block.IsLast
	}

	return stream, nil
}

// Open creates a new Stream for accessing the audio samples of path. It reads
// and parses the FLAC signature and the StreamInfo metadata block, but skips
// all other metadata blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
//
// Note: The Close method of the stream must be called when finished using it.
func Open(path string) (stream *Stream, err error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	stream, err = New(f)
	if err != nil {
		return nil, err
	}
	stream.c = f
	return stream, err
}

// ParseFile creates a new Stream for accessing the metadata blocks and audio
// samples of path. It reads and parses the FLAC signature and all metadata
// blocks.
//
// Call Stream.Next to parse the frame header of the next audio frame, and call
// Stream.ParseNext to parse the entire next frame including audio samples.
//
// Note: The Close method of the stream must be called when finished using it.
func ParseFile(path string) (stream *Stream, err error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	stream, err = Parse(f)
	if err != nil {
		return nil, err
	}
	stream.c = f
	return stream, err
}

// Close closes the stream if opened through a call to Open or ParseFile, and
// performs no operation otherwise.
func (stream *Stream) Close() error {
	if stream.c != nil {
		return stream.c.Close()
	}
	return nil
}

// Next parses the frame header of the next audio frame. It returns io.EOF to
// signal a graceful end of FLAC stream.
//
// Call Frame.Parse to parse the audio samples of its subframes.
func (stream *Stream) Next() (f *frame.Frame, err error) {
	return frame.New(stream.r)
}

// ParseNext parses the entire next frame including audio samples. It returns
// io.EOF to signal a graceful end of FLAC stream.
func (stream *Stream) ParseNext() (f *frame.Frame, err error) {
	return frame.Parse(stream.r)
}

// Seek is not implement yet.
func (stream *Stream) Seek(offset int64, whence int) (read int64, err error) {
	return 0, nil
}
<|endoftext|>


<commit_before>package lispy

func Form(li *Lispy) string {
	if !li.Exist("action") {
		li.Set("action", li.Content)
	}

	str := `<form `

	if li.Exist("action") {
		str += `action="` + li.GetDel("action") + `" `
	}

	if li.Exist("method") {
		str += `method="` + li.GetDel("method") + `" `
	}

	if li.ExistDel("novalidate") {
		str += `novalidate `
	}

	str += li.GetParam()

	str += `/>`

	return str
}

func Input(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<input `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.Exist("value") {
		str += `value="` + li.GetDel("value") + `" `
	}

	if li.ExistDel("checked") {
		str += `checked `
	}

	if li.ExistRes("disabled") {
		str += `disabled `
	}

	if li.ExistDel("autofocus") {
		str += `autofocus `
	}

	if li.ExistDel("formnovalidate") {
		str += `formnovalidate `
	}

	if li.ExistDel("multiple") {
		str += `multiple `
	}

	if li.ExistDel("readonly") {
		str += `readonly `
	}

	if li.ExistDel("required") {
		str += `required `
	}

	str += li.GetParam()

	str += `/>`

	return str
}

func Textarea(li *Lispy) string {
	str := `<input `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.Exist("value") {
		str += `value="` + li.GetDel("value") + `" `
	}

	if li.ExistRes("disabled") {
		str += `disabled `
	}

	if li.ExistDel("autofocus") {
		str += `autofocus `
	}

	if li.ExistDel("multiple") {
		str += `multiple `
	}

	if li.ExistDel("readonly") {
		str += `readonly `
	}

	if li.ExistDel("required") {
		str += `required `
	}

	str += li.GetParam()

	str += `>`

	str += li.Content

	str += `</textarea>`

	return str
}

func Select(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<select `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.ExistRes("disabled") {
		str += `disabled `
	}

	if li.ExistDel("autofocus") {
		str += `autofocus `
	}

	if li.ExistDel("multiple") {
		str += `multiple `
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</select>`

	return str
}

func Option(li *Lispy) string {
	str := `<option `

	if li.Exist("value") {
		str += `value="` + li.GetDel("value") + `" `
	}

	if li.ExistRes("disabled") {
		str += `disabled `
	}

	if li.ExistDel("selected") {
		str += `selected `
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</option>`

	return str
}

func Output(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<output `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.Exist("for") {
		str += `for="` + li.GetDel("for") + `" `
	}

	str += li.GetParam()

	str += `>`

	str += `</output>`

	return str
}

func Label(li *Lispy) string {
	str := `<label `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.Exist("for") {
		str += `for="` + li.GetDel("for") + `" `
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</label>`

	return str
}

func FieldSet(li *Lispy) string {
	str := `<fieldset `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.ExistRes("disabled") {
		str += `disabled `
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</fieldset>`

	return str
}

func Keygen(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<fieldset `

	if li.Exist("name") {
		str += `name="` + li.GetDel("name") + `" `
	}

	if li.Exist("keytype") {
		str += `keytype="` + li.GetDel("keytype") + `" `
	}

	if li.ExistRes("disabled") {
		str += `disabled `
	}

	if li.ExistRes("challenge") {
		str += `challenge `
	}

	if li.ExistDel("autofocus") {
		str += `autofocus `
	}

	str += li.GetParam()

	str += `/>`

	return str
}
<commit_msg>Minor fix!<commit_after>package lispy

func Form(li *Lispy) string {
	if !li.Exist("action") {
		li.Set("action", li.Content)
	}

	str := `<form`

	if li.Exist("action") {
		str += ` action="` + li.GetDel("action") + `"`
	}

	if li.Exist("method") {
		str += ` method="` + li.GetDel("method") + `"`
	}

	if li.ExistDel("novalidate") {
		str += ` novalidate`
	}

	str += li.GetParam()

	str += `/>`

	return str
}

func Input(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<input`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.Exist("value") {
		str += ` value="` + li.GetDel("value") + `"`
	}

	if li.ExistDel("checked") {
		str += ` checked`
	}

	if li.ExistRes("disabled") {
		str += ` disabled`
	}

	if li.ExistDel("autofocus") {
		str += ` autofocus`
	}

	if li.ExistDel("formnovalidate") {
		str += ` formnovalidate`
	}

	if li.ExistDel("multiple") {
		str += ` multiple`
	}

	if li.ExistDel("readonly") {
		str += ` readonly`
	}

	if li.ExistDel("required") {
		str += ` required`
	}

	str += li.GetParam()

	str += `/>`

	return str
}

func Textarea(li *Lispy) string {
	str := `<input`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.Exist("value") {
		str += ` value="` + li.GetDel("value") + `"`
	}

	if li.ExistRes("disabled") {
		str += ` disabled`
	}

	if li.ExistDel("autofocus") {
		str += ` autofocus`
	}

	if li.ExistDel("multiple") {
		str += ` multiple`
	}

	if li.ExistDel("readonly") {
		str += ` readonly`
	}

	if li.ExistDel("required") {
		str += ` required`
	}

	str += li.GetParam()

	str += `>`

	str += li.Content

	str += `</textarea>`

	return str
}

func Select(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<select`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.ExistRes("disabled") {
		str += ` disabled`
	}

	if li.ExistDel("autofocus") {
		str += ` autofocus`
	}

	if li.ExistDel("multiple") {
		str += ` multiple`
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</select>`

	return str
}

func Option(li *Lispy) string {
	str := `<option`

	if li.Exist("value") {
		str += ` value="` + li.GetDel("value") + `"`
	}

	if li.ExistRes("disabled") {
		str += ` disabled`
	}

	if li.ExistDel("selected") {
		str += ` selected`
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</option>`

	return str
}

func Output(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<output`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.Exist("for") {
		str += ` for="` + li.GetDel("for") + `"`
	}

	str += li.GetParam()

	str += `>`

	str += `</output>`

	return str
}

func Label(li *Lispy) string {
	str := `<label`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.Exist("for") {
		str += ` for="` + li.GetDel("for") + `"`
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</label>`

	return str
}

func FieldSet(li *Lispy) string {
	str := `<fieldset`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.ExistRes("disabled") {
		str += ` disabled`
	}

	str += li.GetParam()

	str += `>`

	str += li.Render(li.Content)

	str += `</fieldset>`

	return str
}

func Keygen(li *Lispy) string {
	if !li.Exist("name") {
		li.Set("name", li.Content)
	}

	str := `<fieldset`

	if li.Exist("name") {
		str += ` name="` + li.GetDel("name") + `"`
	}

	if li.Exist("keytype") {
		str += ` keytype="` + li.GetDel("keytype") + `"`
	}

	if li.ExistRes("disabled") {
		str += ` disabled`
	}

	if li.ExistRes("challenge") {
		str += ` challenge`
	}

	if li.ExistDel("autofocus") {
		str += ` autofocus`
	}

	str += li.GetParam()

	str += `/>`

	return str
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"
	"net/http"

	cb "github.com/couchbaselabs/go-couchbase"
)

// Take a stream of namedFiles and clump them into batches of at most
// the specified size
func keyClumper(ch chan *namedFile, size int) chan []*namedFile {
	outch := make(chan []*namedFile)
	go func() {
		defer close(outch)
		res := make([]*namedFile, 0, size)
		for r := range ch {
			res = append(res, r)
			if len(res) == size {
				outch <- res
				res = make([]*namedFile, 0, size)
			}
		}
		if len(res) > 0 {
			outch <- res
		}
	}()

	return outch
}

func dofsck(w http.ResponseWriter, req *http.Request,
	path string) {

	errsOnly := req.FormValue("errsonly") != ""

	quit := make(chan bool)
	defer close(quit)
	ch := make(chan *namedFile)
	cherr := make(chan cb.ViewError)

	go pathGenerator(path, ch, cherr, quit)

	go func() {
		for e := range cherr {
			log.Printf("View error: %v", e)
		}
	}()

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(200)

	e := json.NewEncoder(w)
	type status struct {
		Path  string `json:"path"`
		OID   string `json:"oid,omitempty"`
		Reps  int    `json:"reps,omitempty"`
		EType string `json:"etype,omitempty"`
		Error string `json:"error,omitempty"`
	}

	for nfc := range keyClumper(ch, 1000) {
		keys := []string{}
		fnmap := map[string]string{}
		unprocessed := map[string]string{}

		for _, nf := range nfc {
			if nf.err != nil {
				if err := e.Encode(status{
					Path:  nf.name,
					OID:   nf.meta.OID,
					EType: "file",
					Error: nf.err.Error(),
				}); err != nil {
					log.Printf("Error encoding: %v", err)
					return
				}
			}
			keys = append(keys, "/"+nf.meta.OID)
			unprocessed[nf.name] = nf.meta.OID
			fnmap[nf.meta.OID] = nf.name
		}

		for k, v := range couchbase.GetBulk(keys) {
			name := fnmap[k[1:]]
			delete(unprocessed, name)

			ownership := BlobOwnership{}
			err := json.Unmarshal(v.Body, &ownership)
			if err != nil {
				if err = e.Encode(status{
					Path:  name,
					OID:   k[1:],
					EType: "blob",
					Error: err.Error(),
				}); err != nil {
					log.Printf("Error encoding: %v", err)
					return
				}
			}

			if !errsOnly {
				if err := e.Encode(status{
					Path: name,
					OID:  k[1:],
					Reps: len(ownership.Nodes),
				}); err != nil {
					log.Printf("Error encoding: %v", err)
					return
				}
			}
		}

		for k, v := range unprocessed {
			if err := e.Encode(status{
				Path:  k,
				OID:   v,
				EType: "blob",
				Error: "not found",
			}); err != nil {
				log.Printf("Error encoding: %v", err)
				return
			}
		}
	}
}
<commit_msg>oid -> filename map is 1:n<commit_after>package main

import (
	"encoding/json"
	"log"
	"net/http"

	cb "github.com/couchbaselabs/go-couchbase"
)

// Take a stream of namedFiles and clump them into batches of at most
// the specified size
func keyClumper(ch chan *namedFile, size int) chan []*namedFile {
	outch := make(chan []*namedFile)
	go func() {
		defer close(outch)
		res := make([]*namedFile, 0, size)
		for r := range ch {
			res = append(res, r)
			if len(res) == size {
				outch <- res
				res = make([]*namedFile, 0, size)
			}
		}
		if len(res) > 0 {
			outch <- res
		}
	}()

	return outch
}

func dofsck(w http.ResponseWriter, req *http.Request,
	path string) {

	errsOnly := req.FormValue("errsonly") != ""

	quit := make(chan bool)
	defer close(quit)
	ch := make(chan *namedFile)
	cherr := make(chan cb.ViewError)

	go pathGenerator(path, ch, cherr, quit)

	go func() {
		for e := range cherr {
			log.Printf("View error: %v", e)
		}
	}()

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(200)

	e := json.NewEncoder(w)
	type status struct {
		Path  string `json:"path"`
		OID   string `json:"oid,omitempty"`
		Reps  int    `json:"reps,omitempty"`
		EType string `json:"etype,omitempty"`
		Error string `json:"error,omitempty"`
	}

	for nfc := range keyClumper(ch, 1000) {
		keys := []string{}
		fnmap := map[string][]string{}
		unprocessed := map[string]string{}

		for _, nf := range nfc {
			if nf.err != nil {
				if err := e.Encode(status{
					Path:  nf.name,
					OID:   nf.meta.OID,
					EType: "file",
					Error: nf.err.Error(),
				}); err != nil {
					log.Printf("Error encoding: %v", err)
					return
				}
			}
			keys = append(keys, "/"+nf.meta.OID)
			unprocessed[nf.name] = nf.meta.OID

			a, ok := fnmap[nf.meta.OID]
			if ok {
				a = append(a, nf.name)
			} else {
				a = []string{nf.name}
			}
			fnmap[nf.meta.OID] = a
		}

		for k, v := range couchbase.GetBulk(keys) {
			names := fnmap[k[1:]]
			for _, name := range names {
				delete(unprocessed, name)
			}

			ownership := BlobOwnership{}
			err := json.Unmarshal(v.Body, &ownership)
			if err != nil {
				for _, name := range names {
					if err = e.Encode(status{
						Path:  name,
						OID:   k[1:],
						EType: "blob",
						Error: err.Error(),
					}); err != nil {
						log.Printf("Error encoding: %v", err)
						return
					}
				}
			}

			if !errsOnly {
				for _, name := range names {
					if err := e.Encode(status{
						Path: name,
						OID:  k[1:],
						Reps: len(ownership.Nodes),
					}); err != nil {
						log.Printf("Error encoding: %v", err)
						return
					}
				}
			}
		}

		for k, v := range unprocessed {
			if err := e.Encode(status{
				Path:  k,
				OID:   v,
				EType: "blob",
				Error: "not found",
			}); err != nil {
				log.Printf("Error encoding: %v", err)
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package donna

import (
        `bytes`
        `fmt`
	`math`
	`regexp`
)

const (
        CHECKMATE = float64(math.MaxInt16)
        MIN = float64(-math.MaxInt16)
        MAX = float64(math.MaxInt16)
        MATE = float64(math.MinInt32/10)
)

type Game struct {
	pieces	[64]Piece
	players	[2]*Player
        attacks *Attack
        current int
        nodes   int
}

func NewGame() *Game {
        game := new(Game)
        game.players[0] = NewPlayer(game, WHITE)
        game.players[1] = NewPlayer(game, BLACK)
        game.attacks = NewAttack()
        game.current = WHITE

        return game
}

func (g *Game) Setup(white, black string) *Game {
	re := regexp.MustCompile(`\W+`)
	whitePieces, blackPieces := re.Split(white, -1), re.Split(black, -1)
	return g.SetupSide(whitePieces, 0).SetupSide(blackPieces, 1)
}

func (g *Game) SetupSide(moves []string, color int) *Game {
	re := regexp.MustCompile(`([KQRBN]?)([a-h])([1-8])`)

	for _, move := range moves {
		arr := re.FindStringSubmatch(move)
		if len(arr) == 0 {
			fmt.Printf("Invalid move '%s' for %s\n", move, C(color))
			return g
		}
		name, col, row := arr[1], arr[2][0]-'a', arr[3][0]-'1'

		var piece Piece
		switch name {
		case `K`:
			piece = King(color)
		case `Q`:
			piece = Queen(color)
		case `R`:
			piece = Rook(color)
		case `B`:
			piece = Bishop(color)
		case `N`:
			piece = Knight(color)
		default:
			piece = Pawn(color)
		}
		g.Set(int(row), int(col), piece)
	}
	return g
}

func (g *Game) Set(row, col int, piece Piece) *Game {
        g.pieces[Index(row, col)] = piece

        return g
}

func (g *Game) InitialPosition() *Game {
        return g.Setup(`Ra1,Nb1,Bc1,Qd1,Ke1,Bf1,Ng1,Rh1,a2,b2,c2,d2,e2,f2,g2,h2`,
                       `Ra8,Nb8,Bc8,Qd8,Ke8,Bf8,Ng8,Rh8,a7,b7,c7,d7,e7,f7,g7,h7`)
}

func (g *Game) Think(maxDepth int) *Move {
        fmt.Println(`Depth     Nodes     Score     Best`)
        for i := 1; i <= maxDepth; i++ {
                score := g.Analyze(i)
                fmt.Printf("  %d      %6d   %7.1f     %v\n", i, g.nodes, score, best[0][0 : bestlen[0]])
        }
        fmt.Printf("Best move: %s\n", best[0][0])
        return best[0][0]
}

func (g *Game) Analyze(depth int) float64 {
        position := NewPosition(g, g.pieces, g.current, Bitmask(0))
        return position.AlphaBeta(depth*2, 0, -CHECKMATE, CHECKMATE)
}

func (g *Game) Search(depth int) *Move {
        g.Analyze(depth)
        return best[0][0]
}

func (g *Game)String() string {
	buffer := bytes.NewBufferString("  a b c d e f g h\n")
	for row := 7;  row >= 0;  row-- {
		buffer.WriteByte('1' + byte(row))
		for col := 0;  col <= 7; col++ {
			index := Index(row, col)
			buffer.WriteByte(' ')
			if piece := g.pieces[index]; piece != 0 {
				buffer.WriteString(piece.String())
			} else {
				buffer.WriteString("\u22C5")
			}
		}
		buffer.WriteByte('\n')
	}
	return buffer.String()
}
<commit_msg>Show nodes/second score<commit_after>package donna

import (
        `bytes`
        `fmt`
        `math`
        `regexp`
        `time`
)

const CHECKMATE = float64(math.MaxInt16)

type Game struct {
	pieces	[64]Piece
	players	[2]*Player
        attacks *Attack
        current int
        nodes   int
}

func NewGame() *Game {
        game := new(Game)
        game.players[0] = NewPlayer(game, WHITE)
        game.players[1] = NewPlayer(game, BLACK)
        game.attacks = NewAttack()
        game.current = WHITE

        return game
}

func (g *Game) Setup(white, black string) *Game {
	re := regexp.MustCompile(`\W+`)
	whitePieces, blackPieces := re.Split(white, -1), re.Split(black, -1)
	return g.SetupSide(whitePieces, 0).SetupSide(blackPieces, 1)
}

func (g *Game) SetupSide(moves []string, color int) *Game {
	re := regexp.MustCompile(`([KQRBN]?)([a-h])([1-8])`)

	for _, move := range moves {
		arr := re.FindStringSubmatch(move)
		if len(arr) == 0 {
			fmt.Printf("Invalid move '%s' for %s\n", move, C(color))
			return g
		}
		name, col, row := arr[1], arr[2][0]-'a', arr[3][0]-'1'

		var piece Piece
		switch name {
		case `K`:
			piece = King(color)
		case `Q`:
			piece = Queen(color)
		case `R`:
			piece = Rook(color)
		case `B`:
			piece = Bishop(color)
		case `N`:
			piece = Knight(color)
		default:
			piece = Pawn(color)
		}
		g.Set(int(row), int(col), piece)
	}
	return g
}

func (g *Game) Set(row, col int, piece Piece) *Game {
        g.pieces[Index(row, col)] = piece

        return g
}

func (g *Game) InitialPosition() *Game {
        return g.Setup(`Ra1,Nb1,Bc1,Qd1,Ke1,Bf1,Ng1,Rh1,a2,b2,c2,d2,e2,f2,g2,h2`,
                       `Ra8,Nb8,Bc8,Qd8,Ke8,Bf8,Ng8,Rh8,a7,b7,c7,d7,e7,f7,g7,h7`)
}

func (g *Game) Think(maxDepth int) *Move {
        fmt.Println(`Depth     Nodes     Nodes/s     Score     Best`)
        for depth := 1; depth <= maxDepth; depth++ {
                g.nodes = 0
                start := time.Now()
                score := g.Analyze(depth)
                fmt.Printf("  %d      %6d     %7.1f   %7.1f     %v\n",
                        depth, g.nodes, float64(g.nodes)/time.Since(start).Seconds(), score, best[0][0 : bestlen[0]])
        }
        fmt.Printf("Best move: %s\n", best[0][0])
        return best[0][0]
}

func (g *Game) Analyze(depth int) float64 {
        position := NewPosition(g, g.pieces, g.current, Bitmask(0))
        return position.AlphaBeta(depth*2, 0, -CHECKMATE, CHECKMATE)
}

func (g *Game) Search(depth int) *Move {
        g.Analyze(depth)
        return best[0][0]
}

func (g *Game)String() string {
	buffer := bytes.NewBufferString("  a b c d e f g h\n")
	for row := 7;  row >= 0;  row-- {
		buffer.WriteByte('1' + byte(row))
		for col := 0;  col <= 7; col++ {
			index := Index(row, col)
			buffer.WriteByte(' ')
			if piece := g.pieces[index]; piece != 0 {
				buffer.WriteString(piece.String())
			} else {
				buffer.WriteString("\u22C5")
			}
		}
		buffer.WriteByte('\n')
	}
	return buffer.String()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"time"
)

type Hub struct {
	Sessions   map[*Session]struct{}
	Redraw     chan struct{}
	Register   chan *Session
	Unregister chan *Session
}

func NewHub() Hub {
	return Hub{
		Sessions:   make(map[*Session]struct{}),
		Redraw:     make(chan struct{}),
		Register:   make(chan *Session),
		Unregister: make(chan *Session),
	}
}

func (h *Hub) Run(g *Game) {
	for {
		select {
		case <-h.Redraw:
			for s := range h.Sessions {
				g.Render(s)
			}
		case s := <-h.Register:
			h.Sessions[s] = struct{}{}
		case s := <-h.Unregister:
			if _, ok := h.Sessions[s]; ok {
				delete(h.Sessions, s)
			}
		}
	}
}

type Position struct {
	X float64
	Y float64
}

func (p Position) RoundX() int {
	return int(p.X + 0.5)
}

func (p Position) RoundY() int {
	return int(p.Y + 0.5)
}

type PlayerDirection int

const (
	verticalPlayerSpeed   = 0.007
	horizontalPlayerSpeed = 0.01

	playerUpRune    = '⇧'
	playerLeftRune  = '⇦'
	playerDownRune  = '⇩'
	playerRightRune = '⇨'

	PlayerUp PlayerDirection = iota
	PlayerLeft
	PlayerDown
	PlayerRight
)

type Player struct {
	Direction PlayerDirection
	Marker    rune
	Pos       *Position
}

func NewPlayer() *Player {
	return &Player{
		Marker:    playerDownRune,
		Direction: PlayerDown,
		Pos:       &Position{0, 0},
	}
}

func (p *Player) HandleUp() {
	p.Direction = PlayerUp
	p.Marker = playerUpRune
}

func (p *Player) HandleLeft() {
	p.Direction = PlayerLeft
	p.Marker = playerLeftRune
}

func (p *Player) HandleDown() {
	p.Direction = PlayerDown
	p.Marker = playerDownRune
}

func (p *Player) HandleRight() {
	p.Direction = PlayerRight
	p.Marker = playerRightRune
}

func (p *Player) Update(delta float64) {
	switch p.Direction {
	case PlayerUp:
		p.Pos.Y -= verticalPlayerSpeed * delta
	case PlayerLeft:
		p.Pos.X -= horizontalPlayerSpeed * delta
	case PlayerDown:
		p.Pos.Y += verticalPlayerSpeed * delta
	case PlayerRight:
		p.Pos.X += horizontalPlayerSpeed * delta
	}
}

type TileType int

const (
	TileGrass TileType = iota
	TileBlocker
)

type Tile struct {
	Type TileType
}

type Game struct {
	hub Hub

	Redraw chan struct{}

	// Top left is 0,0
	level [][]Tile
}

func NewGame(worldWidth, worldHeight int) *Game {
	g := &Game{
		hub:    NewHub(),
		Redraw: make(chan struct{}),
	}
	g.initalizeLevel(worldWidth, worldHeight)

	return g
}

func (g *Game) initalizeLevel(width, height int) {
	g.level = make([][]Tile, width)
	for x := range g.level {
		g.level[x] = make([]Tile, height)
	}

	// Default world to grass
	for x := range g.level {
		for y := range g.level[x] {
			g.setTileType(Position{float64(x), float64(y)}, TileGrass)
		}
	}
}

func (g *Game) setTileType(pos Position, tileType TileType) error {
	outOfBoundsErr := "The given %s value (%s) is out of bounds"
	if pos.RoundX() > len(g.level) || pos.RoundX() < 0 {
		return fmt.Errorf(outOfBoundsErr, "X", pos.X)
	} else if pos.RoundY() > len(g.level[pos.RoundX()]) || pos.RoundY() < 0 {
		return fmt.Errorf(outOfBoundsErr, "Y", pos.Y)
	}

	g.level[pos.RoundX()][pos.RoundY()].Type = tileType

	return nil
}

func (g *Game) players() map[*Player]struct{} {
	players := make(map[*Player]struct{})

	for session := range g.hub.Sessions {
		players[session.Player] = struct{}{}
	}

	return players
}

// Characters for rendering
const (
	verticalWall   = '┆'
	horizontalWall = '┄'
	topLeft        = '╭'
	topRight       = '╮'
	bottomRight    = '╯'
	bottomLeft     = '╰'

	grass   = ' '
	blocker = '■'
)

// Warning: this will only work with square worlds
func (g *Game) worldString() string {
	str := ""
	worldWidth := len(g.level)
	worldHeight := len(g.level[0])

	// Create two dimensional slice of runes to represent the world. It's two
	// characters larger in each direction to accomodate for walls.
	strWorld := make([][]rune, worldWidth+3)
	for x := range strWorld {
		strWorld[x] = make([]rune, worldHeight+3)
	}

	// Load the walls into the rune slice
	for x := 0; x < worldWidth+2; x++ {
		strWorld[x][0] = horizontalWall
		strWorld[x][worldHeight+1] = horizontalWall
	}
	for y := 0; y < worldHeight+2; y++ {
		strWorld[0][y] = verticalWall
		strWorld[worldWidth+1][y] = verticalWall
	}

	// Time for the edges!
	strWorld[0][0] = topLeft
	strWorld[worldWidth+1][0] = topRight
	strWorld[worldWidth+1][worldHeight+1] = bottomRight
	strWorld[0][worldHeight+1] = bottomLeft

	// Load the level into the rune slice
	for x := 0; x < worldWidth; x++ {
		for y := 0; y < worldHeight; y++ {
			tile := g.level[x][y]

			switch tile.Type {
			case TileGrass:
				strWorld[x+1][y+1] = grass
			case TileBlocker:
				strWorld[x+1][y+1] = blocker
			}
		}
	}

	// Load the players into the rune slice
	for player := range g.players() {
		pos := player.Pos
		strWorld[pos.RoundX()+1][pos.RoundY()+1] = player.Marker
	}

	// Convert the rune slice to a string
	for y := 0; y < len(strWorld[0]); y++ {
		for x := 0; x < len(strWorld); x++ {
			str += string(strWorld[x][y])
		}

		str += "\r\n"
	}

	return str
}

func (g *Game) Run() {
	// Proxy g.Redraw's channel to g.hub.Redraw
	go func() {
		for {
			g.hub.Redraw <- <-g.Redraw
		}
	}()

	// Run game loop
	go func() {
		var lastUpdate time.Time

		c := time.Tick(time.Second / 60)
		for now := range c {
			g.Update(float64(now.Sub(lastUpdate)) / float64(time.Millisecond))

			lastUpdate = now
		}
	}()

	// Redraw regularly.
	//
	// TODO: Implement diffing and only redraw when needed
	go func() {
		c := time.Tick(time.Second / 10)
		for range c {
			g.Redraw <- struct{}{}
		}
	}()

	g.hub.Run(g)
}

// Update is the main game logic loop. Delta is the time since the last update
// in milliseconds.
func (g *Game) Update(delta float64) {
	for player := range g.players() {
		player.Update(delta)
	}
}

func (g *Game) Render(w io.Writer) {
	worldStr := g.worldString()

	fmt.Fprintln(w)
	fmt.Fprint(w, worldStr)
}

func (g *Game) AddSession(s *Session) {
	g.hub.Register <- s
}

type Session struct {
	c io.ReadWriter

	Player *Player
}

func NewSession(c io.ReadWriter) *Session {
	s := Session{c: c}
	s.Player = NewPlayer()

	return &s
}

func (s *Session) Read(p []byte) (int, error) {
	return s.c.Read(p)
}

func (s *Session) Write(p []byte) (int, error) {
	return s.c.Write(p)
}
<commit_msg>Add lose condition<commit_after>package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"io"
	"time"
)

type Hub struct {
	Sessions   map[*Session]struct{}
	Redraw     chan struct{}
	Register   chan *Session
	Unregister chan *Session
}

func NewHub() Hub {
	return Hub{
		Sessions:   make(map[*Session]struct{}),
		Redraw:     make(chan struct{}),
		Register:   make(chan *Session),
		Unregister: make(chan *Session),
	}
}

func (h *Hub) Run(g *Game) {
	for {
		select {
		case <-h.Redraw:
			for s := range h.Sessions {
				g.Render(s)
			}
		case s := <-h.Register:
			h.Sessions[s] = struct{}{}
		case s := <-h.Unregister:
			if _, ok := h.Sessions[s]; ok {
				fmt.Fprint(s, "End of line.\r\n\r\n")
				delete(h.Sessions, s)
				s.c.Close()
			}
		}
	}
}

type Position struct {
	X float64
	Y float64
}

func (p Position) RoundX() int {
	return int(p.X + 0.5)
}

func (p Position) RoundY() int {
	return int(p.Y + 0.5)
}

type PlayerDirection int

const (
	verticalPlayerSpeed   = 0.007
	horizontalPlayerSpeed = 0.01

	playerUpRune    = '⇧'
	playerLeftRune  = '⇦'
	playerDownRune  = '⇩'
	playerRightRune = '⇨'

	PlayerUp PlayerDirection = iota
	PlayerLeft
	PlayerDown
	PlayerRight
)

type Player struct {
	Direction PlayerDirection
	Marker    rune
	Pos       *Position
}

func NewPlayer() *Player {
	return &Player{
		Marker:    playerDownRune,
		Direction: PlayerDown,
		Pos:       &Position{0, 0},
	}
}

func (p *Player) HandleUp() {
	p.Direction = PlayerUp
	p.Marker = playerUpRune
}

func (p *Player) HandleLeft() {
	p.Direction = PlayerLeft
	p.Marker = playerLeftRune
}

func (p *Player) HandleDown() {
	p.Direction = PlayerDown
	p.Marker = playerDownRune
}

func (p *Player) HandleRight() {
	p.Direction = PlayerRight
	p.Marker = playerRightRune
}

func (p *Player) Update(delta float64) {
	switch p.Direction {
	case PlayerUp:
		p.Pos.Y -= verticalPlayerSpeed * delta
	case PlayerLeft:
		p.Pos.X -= horizontalPlayerSpeed * delta
	case PlayerDown:
		p.Pos.Y += verticalPlayerSpeed * delta
	case PlayerRight:
		p.Pos.X += horizontalPlayerSpeed * delta
	}
}

type TileType int

const (
	TileGrass TileType = iota
	TileBlocker
)

type Tile struct {
	Type TileType
}

type Game struct {
	hub Hub

	Redraw chan struct{}

	// Top left is 0,0
	level [][]Tile
}

func NewGame(worldWidth, worldHeight int) *Game {
	g := &Game{
		hub:    NewHub(),
		Redraw: make(chan struct{}),
	}
	g.initalizeLevel(worldWidth, worldHeight)

	return g
}

func (g *Game) initalizeLevel(width, height int) {
	g.level = make([][]Tile, width)
	for x := range g.level {
		g.level[x] = make([]Tile, height)
	}

	// Default world to grass
	for x := range g.level {
		for y := range g.level[x] {
			g.setTileType(Position{float64(x), float64(y)}, TileGrass)
		}
	}
}

func (g *Game) setTileType(pos Position, tileType TileType) error {
	outOfBoundsErr := "The given %s value (%s) is out of bounds"
	if pos.RoundX() > len(g.level) || pos.RoundX() < 0 {
		return fmt.Errorf(outOfBoundsErr, "X", pos.X)
	} else if pos.RoundY() > len(g.level[pos.RoundX()]) || pos.RoundY() < 0 {
		return fmt.Errorf(outOfBoundsErr, "Y", pos.Y)
	}

	g.level[pos.RoundX()][pos.RoundY()].Type = tileType

	return nil
}

func (g *Game) players() map[*Player]*Session {
	players := make(map[*Player]*Session)

	for session := range g.hub.Sessions {
		players[session.Player] = session
	}

	return players
}

// Characters for rendering
const (
	verticalWall   = '┆'
	horizontalWall = '┄'
	topLeft        = '╭'
	topRight       = '╮'
	bottomRight    = '╯'
	bottomLeft     = '╰'

	grass   = ' '
	blocker = '■'
)

// Warning: this will only work with square worlds
func (g *Game) worldString() string {
	str := ""
	worldWidth := len(g.level)
	worldHeight := len(g.level[0])

	// Create two dimensional slice of runes to represent the world. It's two
	// characters larger in each direction to accomodate for walls.
	strWorld := make([][]rune, worldWidth+3)
	for x := range strWorld {
		strWorld[x] = make([]rune, worldHeight+3)
	}

	// Load the walls into the rune slice
	for x := 0; x < worldWidth+2; x++ {
		strWorld[x][0] = horizontalWall
		strWorld[x][worldHeight+1] = horizontalWall
	}
	for y := 0; y < worldHeight+2; y++ {
		strWorld[0][y] = verticalWall
		strWorld[worldWidth+1][y] = verticalWall
	}

	// Time for the edges!
	strWorld[0][0] = topLeft
	strWorld[worldWidth+1][0] = topRight
	strWorld[worldWidth+1][worldHeight+1] = bottomRight
	strWorld[0][worldHeight+1] = bottomLeft

	// Load the level into the rune slice
	for x := 0; x < worldWidth; x++ {
		for y := 0; y < worldHeight; y++ {
			tile := g.level[x][y]

			switch tile.Type {
			case TileGrass:
				strWorld[x+1][y+1] = grass
			case TileBlocker:
				strWorld[x+1][y+1] = blocker
			}
		}
	}

	// Load the players into the rune slice
	for player := range g.players() {
		pos := player.Pos
		strWorld[pos.RoundX()+1][pos.RoundY()+1] = player.Marker
	}

	// Convert the rune slice to a string
	for y := 0; y < len(strWorld[0]); y++ {
		for x := 0; x < len(strWorld); x++ {
			str += string(strWorld[x][y])
		}

		str += "\r\n"
	}

	return str
}

func (g *Game) Run() {
	// Proxy g.Redraw's channel to g.hub.Redraw
	go func() {
		for {
			g.hub.Redraw <- <-g.Redraw
		}
	}()

	// Run game loop
	go func() {
		var lastUpdate time.Time

		c := time.Tick(time.Second / 60)
		for now := range c {
			g.Update(float64(now.Sub(lastUpdate)) / float64(time.Millisecond))

			lastUpdate = now
		}
	}()

	// Redraw regularly.
	//
	// TODO: Implement diffing and only redraw when needed
	go func() {
		c := time.Tick(time.Second / 10)
		for range c {
			g.Redraw <- struct{}{}
		}
	}()

	g.hub.Run(g)
}

// Update is the main game logic loop. Delta is the time since the last update
// in milliseconds.
func (g *Game) Update(delta float64) {
	for player, session := range g.players() {
		player.Update(delta)

		// Kick player if they're out of bounds
		pos := player.Pos
		if pos.RoundX() < 0 || pos.RoundX() > len(g.level) ||
			pos.RoundY() < 0 || pos.RoundY() > len(g.level[0]) {
			g.hub.Unregister <- session
		}
	}
}

func (g *Game) Render(w io.Writer) {
	worldStr := g.worldString()

	fmt.Fprintln(w)
	fmt.Fprint(w, worldStr)
}

func (g *Game) AddSession(s *Session) {
	g.hub.Register <- s
}

type Session struct {
	c ssh.Channel

	Player *Player
}

func NewSession(c ssh.Channel) *Session {
	s := Session{c: c}
	s.Player = NewPlayer()

	return &s
}

func (s *Session) Read(p []byte) (int, error) {
	return s.c.Read(p)
}

func (s *Session) Write(p []byte) (int, error) {
	return s.c.Write(p)
}
<|endoftext|>


<commit_before>// Package gcfg reads "gitconfig-like" text-based configuration files with
// "name=value" pairs grouped into sections (gcfg files).
// Support for modifying and/or exporting gcfg files may be added later.
//
// See Parse and the examples to get an idea of how to use it.
//
// This package is still a work in progress, and both the supported syntax and
// the API is subject to change.
//
// The syntax is based on that used by git config:
// http://git-scm.com/docs/git-config#_syntax .
// Note that the gcfg syntax may diverge from that of git config in the future
// to a limited degree.
// Current differences (apart from TODOs listed below) are:
//  - gcfg files must use UTF-8 encoding (for now)
//  - include and "path" type is not supported at the package level
//  - `[sec.sub]` format is not allowed (deprecated in gitconfig)
//  - `[sec ""]` is not allowed
//    - `[sec]` is the equivalent (section name "sec" and empty subsection name)
//
// The package may be usable for handling some of the various "INI file" formats
// used by some programs and libraries, but achieving or maintaining
// compatibility with any of those is not a primary concern.
//
// TODO:
//  - docs
//    - format spec
//  - parsing
//    - define internal representation structure
//    - support multi-value variables
//    - non-regexp based parser
//    - support escaping in strings
//    - support multiple inputs (readers, strings, files)
//    - support declaring encoding (?)
//    - support pointer fields
//  - modifying / exporting gcfg files
//  - error handling
//    - include error context
//    - more helpful error messages
//    - error types / codes?
//    - limit input size?
//
package gcfg

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
	"regexp"
	"strings"
)

var (
	reCmnt    = regexp.MustCompile(`^([^;#"]*)[;#].*$`)
	reCmntQ   = regexp.MustCompile(`^([^;#"]*"[^"]*"[^;#"]*)[;#].*$`)
	reBlank   = regexp.MustCompile(`^\s*$`)
	reSect    = regexp.MustCompile(`^\s*\[\s*([^"\s]*)\s*\]\s*$`)
	reSectSub = regexp.MustCompile(`^\s*\[\s*([^"\s]*)\s*"([^"]+)"\s*\]\s*$`)
	reVar     = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*([^"\s]*)\s*$`)
	reVarQ    = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*"([^"\n\\]*)"\s*$`)
	reVarDflt = regexp.MustCompile(`^\s*\b(.*)\b\s*$`)
)

const (
	// Default value string in case a value for a variable isn't provided.
	DefaultValue = "true"
)

type gbool bool

var boolValues = map[string]interface{}{
	"true": true, "yes": true, "on": true, "1": true,
	"false": false, "no": false, "off": false, "0": false}

const (
	// initial size of buffer for ScanEnum
	scanEnumBufferHint = 16
)

func strEq(s1, s2 string, fold bool) bool {
	return fold && strings.EqualFold(s1, s2) || !fold && s1 == s2
}

// ScanEnum is a helper function to simplify the implementation of fmt.Scanner
// methods for "enum-like" types, that is, user-defined types where the set of
// values and string representations is fixed.
//
// State is the state passed to the implementation of the fmt.Scanner method.
// Values holds as map values the values of the type, with their string
// representations as keys.
// If fold is true, comparison of the string representation uses
// strings.EqualFold, otherwise the equal operator for strings.
//
// On a match, ScanEnum stops after reading the last rune of the matched string,
// and returns the corresponding value together with a nil error.
// On no match, ScanEnum attempts to unread the last rune (the first rune that
// could not potentially match any of the values), and returns a non-nil error,
// togetherwith a nil value for interface{}.
// On I/O error, ScanEnum returns the I/O error, together with a nil value for
// interface{}.
//
func ScanEnum(state fmt.ScanState, values map[string]interface{}, fold bool) (
	interface{}, error) {
	//
	rd := make([]rune, 0, scanEnumBufferHint)
	keys := make(map[string]struct{}, len(values)) // potential keys
	for s, _ := range values {
		keys[s] = struct{}{}
	}
	for {
		r, _, err := state.ReadRune()
		if err != nil {
			return nil, err
		}
		rd = append(rd, r)
		srd := string(rd)
		lrd := len(srd)
		for s, _ := range keys {
			if strEq(srd, s, fold) {
				return values[s], nil
			}
			if len(rd) < len(s) && !strEq(srd, s[:lrd], fold) {
				delete(keys, s)
			}
		}
		if len(keys) == 0 {
			state.UnreadRune()
			return nil, fmt.Errorf("unsupported value %q", srd)
		}
	}
	panic("never reached")
}

func (b *gbool) Scan(state fmt.ScanState, verb rune) error {
	v, err := ScanEnum(state, boolValues, true)
	switch bb := v.(type) {
	case bool:
		*b = gbool(bb)
		return err
	}
	return err
}

func fieldFold(v reflect.Value, name string) reflect.Value {
	n := strings.Replace(name, "-", "_", -1)
	return v.FieldByNameFunc(func(fieldName string) bool {
		return strings.EqualFold(n, fieldName)
	})
}

func set(cfg interface{}, sect, sub, name, value string) error {
	vDest := reflect.ValueOf(cfg).Elem()
	vSect := fieldFold(vDest, sect)
	if vSect.Kind() == reflect.Map {
		if vSect.IsNil() {
			vSect.Set(reflect.MakeMap(vSect.Type()))
		}
		k := reflect.ValueOf(sub)
		pv := vSect.MapIndex(k)
		if !pv.IsValid() {
			vType := vSect.Type().Elem().Elem()
			pv = reflect.New(vType)
			vSect.SetMapIndex(k, pv)
		}
		vSect = pv.Elem()
	} else if sub != "" {
		return fmt.Errorf("expected map; section %q subsection %q", sect, sub)
	}
	vName := fieldFold(vSect, name)
	vAddr := vName.Addr().Interface()
	switch v := vAddr.(type) {
	case *string:
		*v = value
		return nil
	case *bool:
		vAddr = (*gbool)(v)
	}
	// attempt to read an extra rune to make sure the value is consumed
	var r rune
	n, err := fmt.Sscanf(value, "%v%c", vAddr, &r)
	switch {
	case n < 1 || n == 1 && err != io.EOF:
		return fmt.Errorf("failed to parse %q as %#v: parse error %v", value,
			vName.Type(), err)
	case n > 1:
		return fmt.Errorf("failed to parse %q as %#v: extra characters", value,
			vName.Type())
	case n == 1 && err == io.EOF:
		return nil
	}
	panic("never reached")
}

// Parse reads gcfg formatted data from reader and sets the values into the
// corresponding fields in config.
//
// Config must be a pointer to a struct.
// Each section corresponds to a struct field in config, and each variable in a
// section corresponds to a data field in the section struct.
// The field names must match that of the section or the variable, ignoring
// case.
// Hyphens are replaced with underscores.
//
// For sections with subsections, the corresponding field in config must be a
// map, rather than a struct, with string keys and pointer-to-struct values.
// Values for subsection variables are stored in the map with the subsection
// name used as the map key.
// (Note that unlike section and variable names, subsection names are case
// sensitive.)
// When using a map, and there is a section with the same section name but
// without a subsection name, its values are stored with the empty string used
// as the key.
//
// The section structs in the config struct may contain arbitrary types.
// For string fields, the (unquoted and unescaped) value string is assigned to
// the field.
// For bool fields, the field is set to true if the value is "true", "yes", "on"
// or "1", and set to false if the value is "false", "no", "off" or "0",
// ignoring case.
// For all other types, fmt.Sscanf is used to parse the value and set it to the
// field.
// This means that built-in Go types are parseable using the standard format,
// and any user-defined types is parseable if it implements the fmt.Scanner
// interface.
//
// See ParseString for examples.
//
func Parse(config interface{}, reader io.Reader) error {
	r := bufio.NewReader(reader)
	sect := (*string)(nil)
	sectsub := ""
	for line := 1; true; line++ {
		l, pre, err := r.ReadLine()
		if err != nil && err != io.EOF {
			return err
		} else if pre {
			return errors.New("line too long")
		}
		// exclude comments
		if c := reCmnt.FindSubmatch(l); c != nil {
			l = c[1]
		} else if c := reCmntQ.FindSubmatch(l); c != nil {
			l = c[1]
		}
		if !reBlank.Match(l) {
			// "switch" based on line contents
			if sec := reSect.FindSubmatch(l); sec != nil {
				strsec := string(sec[1])
				sect, sectsub = &strsec, ""
			} else if sec := reSectSub.FindSubmatch(l); sec != nil {
				strsec := string(sec[1])
				strsub := string(sec[2])
				if strsub == "" {
					return errors.New("empty subsection not allowed")
				}
				sect, sectsub = &strsec, strsub
			} else if v, vq, vd := reVar.FindSubmatch(l),
				reVarQ.FindSubmatch(l), reVarDflt.FindSubmatch(l); //
			v != nil || vq != nil || vd != nil {
				if sect == nil {
					return errors.New("no section")
				}
				var name, value string
				if v != nil {
					name, value = string(v[1]), string(v[2])
				} else if vq != nil {
					name, value = string(vq[1]), string(vq[2])
				} else { // vd != nil
					name, value = string(vd[1]), DefaultValue
				}
				err := set(config, *sect, sectsub, name, value)
				if err != nil {
					return err
				}
			} else {
				return fmt.Errorf("invalid line %q", string(l))
			}
		}
		if err == io.EOF {
			break
		}
	}
	return nil
}

// ParseString reads gcfg formatted data from str and sets the values into the
// corresponding fields in config.
// See Parse(config, reader) for the details of the parsing rules.
func ParseString(config interface{}, str string) error {
	r := strings.NewReader(str)
	return Parse(config, r)
}

// ParseFile reads gcfg formatted data from the file filename and sets the
// values into the corresponding fields in config.
// See Parse(config, reader) for the details of the parsing rules.
func ParseFile(config interface{}, filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()
	return Parse(config, f)
}
<commit_msg>refactor bool<commit_after>// Package gcfg reads "gitconfig-like" text-based configuration files with
// "name=value" pairs grouped into sections (gcfg files).
// Support for modifying and/or exporting gcfg files may be added later.
//
// See Parse and the examples to get an idea of how to use it.
//
// This package is still a work in progress, and both the supported syntax and
// the API is subject to change.
//
// The syntax is based on that used by git config:
// http://git-scm.com/docs/git-config#_syntax .
// Note that the gcfg syntax may diverge from that of git config in the future
// to a limited degree.
// Current differences (apart from TODOs listed below) are:
//  - gcfg files must use UTF-8 encoding (for now)
//  - include and "path" type is not supported at the package level
//  - `[sec.sub]` format is not allowed (deprecated in gitconfig)
//  - `[sec ""]` is not allowed
//    - `[sec]` is the equivalent (section name "sec" and empty subsection name)
//
// The package may be usable for handling some of the various "INI file" formats
// used by some programs and libraries, but achieving or maintaining
// compatibility with any of those is not a primary concern.
//
// TODO:
//  - docs
//    - format spec
//  - parsing
//    - define internal representation structure
//    - support multi-value variables
//    - non-regexp based parser
//    - support escaping in strings
//    - support multiple inputs (readers, strings, files)
//    - support declaring encoding (?)
//    - support pointer fields
//  - modifying / exporting gcfg files
//  - error handling
//    - include error context
//    - more helpful error messages
//    - error types / codes?
//    - limit input size?
//
package gcfg

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
	"regexp"
	"strings"
)

var (
	reCmnt    = regexp.MustCompile(`^([^;#"]*)[;#].*$`)
	reCmntQ   = regexp.MustCompile(`^([^;#"]*"[^"]*"[^;#"]*)[;#].*$`)
	reBlank   = regexp.MustCompile(`^\s*$`)
	reSect    = regexp.MustCompile(`^\s*\[\s*([^"\s]*)\s*\]\s*$`)
	reSectSub = regexp.MustCompile(`^\s*\[\s*([^"\s]*)\s*"([^"]+)"\s*\]\s*$`)
	reVar     = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*([^"\s]*)\s*$`)
	reVarQ    = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*"([^"\n\\]*)"\s*$`)
	reVarDflt = regexp.MustCompile(`^\s*\b(.*)\b\s*$`)
)

const (
	// Default value string in case a value for a variable isn't provided.
	DefaultValue = "true"
)

type gbool bool

var gboolValues = map[string]interface{}{
	"true": true, "yes": true, "on": true, "1": true,
	"false": false, "no": false, "off": false, "0": false}

const (
	// initial size of buffer for ScanEnum
	scanEnumBufferHint = 16
)

func strEq(s1, s2 string, fold bool) bool {
	return fold && strings.EqualFold(s1, s2) || !fold && s1 == s2
}

// ScanEnum is a helper function to simplify the implementation of fmt.Scanner
// methods for "enum-like" types, that is, user-defined types where the set of
// values and string representations is fixed.
//
// State is the state passed to the implementation of the fmt.Scanner method.
// Values holds as map values the values of the type, with their string
// representations as keys.
// If fold is true, comparison of the string representation uses
// strings.EqualFold, otherwise the equal operator for strings.
//
// On a match, ScanEnum stops after reading the last rune of the matched string,
// and returns the corresponding value together with a nil error.
// On no match, ScanEnum attempts to unread the last rune (the first rune that
// could not potentially match any of the values), and returns a non-nil error,
// togetherwith a nil value for interface{}.
// On I/O error, ScanEnum returns the I/O error, together with a nil value for
// interface{}.
//
func ScanEnum(state fmt.ScanState, values map[string]interface{}, fold bool) (
	interface{}, error) {
	//
	rd := make([]rune, 0, scanEnumBufferHint)
	keys := make(map[string]struct{}, len(values)) // potential keys
	for s, _ := range values {
		keys[s] = struct{}{}
	}
	for {
		r, _, err := state.ReadRune()
		if err != nil {
			return nil, err
		}
		rd = append(rd, r)
		srd := string(rd)
		lrd := len(srd)
		for s, _ := range keys {
			if strEq(srd, s, fold) {
				return values[s], nil
			}
			if len(rd) < len(s) && !strEq(srd, s[:lrd], fold) {
				delete(keys, s)
			}
		}
		if len(keys) == 0 {
			state.UnreadRune()
			return nil, fmt.Errorf("unsupported value %q", srd)
		}
	}
	panic("never reached")
}

func (b *gbool) Scan(state fmt.ScanState, verb rune) error {
	v, err := ScanEnum(state, gboolValues, true)
	if err != nil {
		return err
	}
	switch bb := v.(type) {
	case bool:
		*b = gbool(bb)
		return nil
	}
	panic("never reached")
}

func fieldFold(v reflect.Value, name string) reflect.Value {
	n := strings.Replace(name, "-", "_", -1)
	return v.FieldByNameFunc(func(fieldName string) bool {
		return strings.EqualFold(n, fieldName)
	})
}

func set(cfg interface{}, sect, sub, name, value string) error {
	vDest := reflect.ValueOf(cfg).Elem()
	vSect := fieldFold(vDest, sect)
	if vSect.Kind() == reflect.Map {
		if vSect.IsNil() {
			vSect.Set(reflect.MakeMap(vSect.Type()))
		}
		k := reflect.ValueOf(sub)
		pv := vSect.MapIndex(k)
		if !pv.IsValid() {
			vType := vSect.Type().Elem().Elem()
			pv = reflect.New(vType)
			vSect.SetMapIndex(k, pv)
		}
		vSect = pv.Elem()
	} else if sub != "" {
		return fmt.Errorf("expected map; section %q subsection %q", sect, sub)
	}
	vName := fieldFold(vSect, name)
	vAddr := vName.Addr().Interface()
	switch v := vAddr.(type) {
	case *string:
		*v = value
		return nil
	case *bool:
		vAddr = (*gbool)(v)
	}
	// attempt to read an extra rune to make sure the value is consumed
	var r rune
	n, err := fmt.Sscanf(value, "%v%c", vAddr, &r)
	switch {
	case n < 1 || n == 1 && err != io.EOF:
		return fmt.Errorf("failed to parse %q as %#v: parse error %v", value,
			vName.Type(), err)
	case n > 1:
		return fmt.Errorf("failed to parse %q as %#v: extra characters", value,
			vName.Type())
	case n == 1 && err == io.EOF:
		return nil
	}
	panic("never reached")
}

// Parse reads gcfg formatted data from reader and sets the values into the
// corresponding fields in config.
//
// Config must be a pointer to a struct.
// Each section corresponds to a struct field in config, and each variable in a
// section corresponds to a data field in the section struct.
// The field names must match that of the section or the variable, ignoring
// case.
// Hyphens are replaced with underscores.
//
// For sections with subsections, the corresponding field in config must be a
// map, rather than a struct, with string keys and pointer-to-struct values.
// Values for subsection variables are stored in the map with the subsection
// name used as the map key.
// (Note that unlike section and variable names, subsection names are case
// sensitive.)
// When using a map, and there is a section with the same section name but
// without a subsection name, its values are stored with the empty string used
// as the key.
//
// The section structs in the config struct may contain arbitrary types.
// For string fields, the (unquoted and unescaped) value string is assigned to
// the field.
// For bool fields, the field is set to true if the value is "true", "yes", "on"
// or "1", and set to false if the value is "false", "no", "off" or "0",
// ignoring case.
// For all other types, fmt.Sscanf is used to parse the value and set it to the
// field.
// This means that built-in Go types are parseable using the standard format,
// and any user-defined types is parseable if it implements the fmt.Scanner
// interface.
//
// See ParseString for examples.
//
func Parse(config interface{}, reader io.Reader) error {
	r := bufio.NewReader(reader)
	sect := (*string)(nil)
	sectsub := ""
	for line := 1; true; line++ {
		l, pre, err := r.ReadLine()
		if err != nil && err != io.EOF {
			return err
		} else if pre {
			return errors.New("line too long")
		}
		// exclude comments
		if c := reCmnt.FindSubmatch(l); c != nil {
			l = c[1]
		} else if c := reCmntQ.FindSubmatch(l); c != nil {
			l = c[1]
		}
		if !reBlank.Match(l) {
			// "switch" based on line contents
			if sec := reSect.FindSubmatch(l); sec != nil {
				strsec := string(sec[1])
				sect, sectsub = &strsec, ""
			} else if sec := reSectSub.FindSubmatch(l); sec != nil {
				strsec := string(sec[1])
				strsub := string(sec[2])
				if strsub == "" {
					return errors.New("empty subsection not allowed")
				}
				sect, sectsub = &strsec, strsub
			} else if v, vq, vd := reVar.FindSubmatch(l),
				reVarQ.FindSubmatch(l), reVarDflt.FindSubmatch(l); //
			v != nil || vq != nil || vd != nil {
				if sect == nil {
					return errors.New("no section")
				}
				var name, value string
				if v != nil {
					name, value = string(v[1]), string(v[2])
				} else if vq != nil {
					name, value = string(vq[1]), string(vq[2])
				} else { // vd != nil
					name, value = string(vd[1]), DefaultValue
				}
				err := set(config, *sect, sectsub, name, value)
				if err != nil {
					return err
				}
			} else {
				return fmt.Errorf("invalid line %q", string(l))
			}
		}
		if err == io.EOF {
			break
		}
	}
	return nil
}

// ParseString reads gcfg formatted data from str and sets the values into the
// corresponding fields in config.
// See Parse(config, reader) for the details of the parsing rules.
func ParseString(config interface{}, str string) error {
	r := strings.NewReader(str)
	return Parse(config, r)
}

// ParseFile reads gcfg formatted data from the file filename and sets the
// values into the corresponding fields in config.
// See Parse(config, reader) for the details of the parsing rules.
func ParseFile(config interface{}, filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()
	return Parse(config, f)
}
<|endoftext|>


<commit_before>package gelf

import (
	"fmt"
	"net"
	"errors"
)

type Config struct {
	Enabled bool `json:"enabled"`
	Net string `json:"net"`
	Addr string `json:"addr"`
	Workers int `json:"workers"`
}

var gSendChannel chan []byte

func Start(config Config) error {
	if !config.Enabled {
		fmt.Printf("GELF logging is disabled\n")
		return nil
	}

	if len(config.Net) == 0 {
		return errors.New("Missing network family")
	}

	if len(config.Addr) == 0 {
		return errors.New("Missing address")
	}

	if config.Workers == 0 {
		config.Workers = 4
	} else if config.Workers < 1 || config.Workers > 16 {
		return fmt.Errorf("Bad worker count %d", config.Workers)
	}

	raddr, err := net.ResolveUDPAddr(config.Net, config.Addr)
	if err != nil {
		return err
	}

	conn, err := net.DialUDP(config.Net, nil, raddr)
	if err != nil {
		return err
	}

	gSendChannel = make(chan []byte, 16)

	for i := 0; i < config.Workers; i++ {
		go worker(gSendChannel, conn)
	}

	fmt.Printf("GELF logger start, net = %s, addr = %s\n", config.Net, config.Addr)

	return nil
}

func SendBytes(packet []byte) {
	if gSendChannel != nil {
		select {
			case gSendChannel <- packet:
		}
	}
}

func SendString(packet string) {
	SendBytes([]byte(packet))
}

func worker(c chan []byte, conn *net.UDPConn) {
	for {
		packet := <- c
		conn.Write(packet)
	}
}
<commit_msg>started adding json stuff, added compression<commit_after>package gelf

import (
	"bytes"
	"compress/zlib"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"os"
)

/* ----- */

const (
	VERSION_1_1 = "1.1"
)

/* ----- */

type Config struct {
	Enabled  bool   `json:"enabled"`
	Net      string `json:"net"`
	Addr     string `json:"addr"`
	Workers  int    `json:"workers"`
	Echo     bool   `json:"echo"`
	Host     string `json:"host"`
	Compress bool   `json:"compress"`
}

/* ----- */

type Event interface {
	ToJson() ([]byte, error)
}

type BaseEvent struct {
	Version      string `json:"version"`
	Host         string `json:"host"`
	ShortMessage string `json:"short_message"`
	FullMessage  string `json:"full_message,omitempty"`
}

func (e *BaseEvent) ToJson() ([]byte, error) {
	return json.Marshal(e)
}

/* ----- */

func NewBaseEvent() BaseEvent {
	return BaseEvent{Version: VERSION_1_1, Host: gHost}
}

func GetVersion() string {
	return VERSION_1_1
}

func GetHost() string {
	return gHost
}

/* ----- */

var gSendChannel chan []byte
var gHost string

func Start(config Config) (err error) {
	if !config.Enabled {
		fmt.Printf("GELF logging is disabled\n")
		return nil
	}

	if len(config.Net) == 0 {
		return errors.New("Missing network family")
	}

	if len(config.Addr) == 0 {
		return errors.New("Missing address")
	}

	if config.Workers == 0 {
		config.Workers = 4
	} else if config.Workers < 1 || config.Workers > 16 {
		return fmt.Errorf("Bad worker count %d", config.Workers)
	}

	raddr, err := net.ResolveUDPAddr(config.Net, config.Addr)
	if err != nil {
		return
	}

	conn, err := net.DialUDP(config.Net, nil, raddr)
	if err != nil {
		return
	}

	fmt.Printf("GELF logger start, net = %s, addr = %s\n", config.Net, config.Addr)

	if len(config.Host) == 0 {
		config.Host, err = os.Hostname()
		if err != nil {
			return
		}
		fmt.Printf("GELF host = %q\n", config.Host)
	}

	gSendChannel = make(chan []byte, 16)
	gHost = config.Host

	for i := 0; i < config.Workers; i++ {
		w, err := newWorker(gSendChannel, conn, config)
		if err != nil {
			return err
		}
		go w.run()
	}

	err = nil
	return
}

func SendBytes(packet []byte) {
	if gSendChannel != nil {
		select {
		case gSendChannel <- packet:
		}
	}
}

func SendString(packet string) {
	SendBytes([]byte(packet))
}

func SendEvent(event Event) {
	b, err := event.ToJson()
	if err != nil {
		reportError(err)
	}

	SendBytes(b)
}

/* ----- */

type worker struct {
	c      chan []byte
	conn   *net.UDPConn
	config Config

	zbuf  bytes.Buffer
	zcomp *zlib.Writer
}

func newWorker(c chan []byte, conn *net.UDPConn, config Config) (*worker, error) {
	// var err error
	w := &worker{c: gSendChannel, conn: conn, config: config}
	w.zcomp = zlib.NewWriter(&w.zbuf)
	// if err != nil {
	// 	return nil, err
	// }
	return w, nil
}

func (w *worker) run() {
	for {
		packet := <-w.c

		if w.config.Echo {
			fmt.Printf("gelf <- %s\n", string(packet))
		}

		var err error
		var tosend []byte
		if w.config.Compress {
			tosend, err = w.compress(packet)
			if err != nil {
				reportError(err)
				continue
			}
		} else {
			tosend = packet
		}

		w.conn.Write(tosend)
	}
}

func (w *worker) compress(src []byte) ([]byte, error) {
	w.zbuf.Reset()
	w.zcomp.Reset(&w.zbuf)

	n, err := w.zcomp.Write(src)
	if n != len(src) {
		return nil, fmt.Errorf("Could only write %d of %d bytes", n, len(src))
	}
	if err != nil {
		return nil, err
	}

	w.zcomp.Close()
	return w.zbuf.Bytes(), nil
}

func reportError(err error) {
	fmt.Println(err)
}
<|endoftext|>