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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the frame primitive functions.

package golisp

import (
	"fmt"
)

func RegisterFramePrimitives() {
	MakePrimitiveFunction("make-frame", -1, MakeFrameImpl)
	MakePrimitiveFunction("has-slot?", 2, HasSlotImpl)
	MakePrimitiveFunction("get-slot", 2, GetSlotImpl)
	MakePrimitiveFunction("get-slot-or-nil", 2, GetSlotOrNilImpl)
	MakePrimitiveFunction("remove-slot!", 2, RemoveSlotImpl)
	MakePrimitiveFunction("set-slot!", 3, SetSlotImpl)
	MakePrimitiveFunction("send", -1, SendImpl)
	MakePrimitiveFunction("send-super", -1, SendSuperImpl)
	MakePrimitiveFunction("clone", 1, CloneImpl)
	MakePrimitiveFunction("json->lisp", 1, JsonToLispImpl)
	MakePrimitiveFunction("lisp->json", 1, LispToJsonImpl)
	MakePrimitiveFunction("keys", 1, KeysImpl)
	MakePrimitiveFunction("vals", 1, ValsImpl)
}

func MakeFrameImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	if Length(args)%2 != 0 {
		err = ProcessError("Frames must be initialized with an even number of arguments.", env)
	}
	m := make(FrameMap)
	for c := args; NotNilP(c); c = Cddr(c) {
		k := Car(c)
		if !NakedP(k) {
			err = ProcessError(fmt.Sprintf("Frame keys must be naked symbols, but was given %s.", String(k)), env)
			return
		}
		v, e := Eval(Cadr(c), env)
		if e != nil {
			return nil, e
		}
		m[StringValue(k)] = v
	}
	return FrameWithValue(&m), nil
}

func HasSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("has-slot? requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("has-slot? requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	return BooleanWithValue(FrameValue(f).HasSlot(StringValue(k))), nil
}

func GetSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("get-slot requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	if FrameValue(f) == nil {
		err = ProcessError("get-slot received a nil frame.", env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("get-slot requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	if !FrameValue(f).HasSlot(StringValue(k)) {
		err = ProcessError(fmt.Sprintf("get-slot requires an existing slot, but was given %s.", String(k)), env)
		return
	}

	return FrameValue(f).Get(StringValue(k)), nil
}

func GetSlotOrNilImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("get-slot-or-nil requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("get-slot-or-nil requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	return FrameValue(f).Get(StringValue(k)), nil
}

func RemoveSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	if NilP(f) {
		return LispFalse, nil
	}

	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("remove-slot! requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("remove-slot! requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	return BooleanWithValue(FrameValue(f).Remove(StringValue(k))), nil
}

func SetSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("set-slot! requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !NakedP(k) {
		err = ProcessError(fmt.Sprintf("set-slot! requires a naked symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	v, err := Eval(Caddr(args), env)
	if err != nil {
		return
	}

	return FrameValue(f).Set(StringValue(k), v), nil
}

func SendImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("send requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("send requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	if !FrameValue(f).HasSlot(StringValue(k)) {
		err = ProcessError(fmt.Sprintf("send requires an existing slot, but was given %s.", String(k)), env)
		return
	}

	fun := FrameValue(f).Get(StringValue(k))
	if !FunctionP(fun) {
		err = ProcessError(fmt.Sprintf("send requires a function slot, but was given a slot containing a %s.", TypeName(TypeOf(fun))), env)
		return
	}

	params := Cddr(args)
	return FunctionValue(fun).ApplyWithFrame(params, env, FrameValue(f))
}

func getSuperFunction(selector string, env *SymbolTableFrame) *Data {
	f := env.Frame
	if f == nil {
		return nil
	}

	for _, p := range f.Parents() {
		fun := p.Get(selector)
		if fun != nil {
			return fun
		}
	}

	return nil
}

func SendSuperImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	if !env.HasFrame() {
		err = ProcessError("send-super can only be used within the context of a frame.", env)
		return
	}

	selector, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !SymbolP(selector) {
		err = ProcessError(fmt.Sprintf("Selector must be a symbol but was %s.", TypeName(TypeOf(selector))), env)
		return
	}

	fun := getSuperFunction(StringValue(selector), env)
	if fun == nil || !FunctionP(fun) {
		err = ProcessError(fmt.Sprintf("Message sent must select a function slot but was %s.", TypeName(TypeOf(fun))), env)
		return
	}

	params := Cdr(args)
	frameEnv := NewSymbolTableFrameBelowWithFrame(env, env.Frame)
	frameEnv.BindLocallyTo(SymbolWithName("self"), FrameWithValue(env.Frame))
	return FunctionValue(fun).Apply(params, frameEnv)
}

func CloneImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("clone requires a frame as it's argument, but was given %s.", String(f)), env)
		return
	}

	return FrameWithValue(FrameValue(f).Clone()), nil
}

func JsonToLispImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	j, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !StringP(j) {
		err = ProcessError(fmt.Sprintf("json->lisp requires a string as it's argument, but was given %s.", String(j)), env)
		return
	}

	return JsonStringToLispWithFrames(StringValue(j)), nil
}

func LispToJsonImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	l, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	return StringWithValue(LispWithFramesToJsonString(l)), nil
}

func KeysImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("keys requires a frame as it's argument, but was given %s.", String(f)), env)
		return
	}

	return ArrayToList(FrameValue(f).Keys()), nil
}

func ValsImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("vals requires a frame as it's argument, but was given %s.", String(f)), env)
		return
	}

	return ArrayToList(FrameValue(f).Values()), nil
}
<commit_msg>rename keys & gals to frame-keys & frame-values<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the frame primitive functions.

package golisp

import (
	"fmt"
)

func RegisterFramePrimitives() {
	MakePrimitiveFunction("make-frame", -1, MakeFrameImpl)
	MakePrimitiveFunction("has-slot?", 2, HasSlotImpl)
	MakePrimitiveFunction("get-slot", 2, GetSlotImpl)
	MakePrimitiveFunction("get-slot-or-nil", 2, GetSlotOrNilImpl)
	MakePrimitiveFunction("remove-slot!", 2, RemoveSlotImpl)
	MakePrimitiveFunction("set-slot!", 3, SetSlotImpl)
	MakePrimitiveFunction("send", -1, SendImpl)
	MakePrimitiveFunction("send-super", -1, SendSuperImpl)
	MakePrimitiveFunction("clone", 1, CloneImpl)
	MakePrimitiveFunction("json->lisp", 1, JsonToLispImpl)
	MakePrimitiveFunction("lisp->json", 1, LispToJsonImpl)
	MakePrimitiveFunction("frame-keys", 1, FrameKeysImpl)
	MakePrimitiveFunction("frame-values", 1, FrameValuesImpl)
}

func MakeFrameImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	if Length(args)%2 != 0 {
		err = ProcessError("Frames must be initialized with an even number of arguments.", env)
	}
	m := make(FrameMap)
	for c := args; NotNilP(c); c = Cddr(c) {
		k := Car(c)
		if !NakedP(k) {
			err = ProcessError(fmt.Sprintf("Frame keys must be naked symbols, but was given %s.", String(k)), env)
			return
		}
		v, e := Eval(Cadr(c), env)
		if e != nil {
			return nil, e
		}
		m[StringValue(k)] = v
	}
	return FrameWithValue(&m), nil
}

func HasSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("has-slot? requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("has-slot? requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	return BooleanWithValue(FrameValue(f).HasSlot(StringValue(k))), nil
}

func GetSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("get-slot requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	if FrameValue(f) == nil {
		err = ProcessError("get-slot received a nil frame.", env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("get-slot requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	if !FrameValue(f).HasSlot(StringValue(k)) {
		err = ProcessError(fmt.Sprintf("get-slot requires an existing slot, but was given %s.", String(k)), env)
		return
	}

	return FrameValue(f).Get(StringValue(k)), nil
}

func GetSlotOrNilImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("get-slot-or-nil requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("get-slot-or-nil requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	return FrameValue(f).Get(StringValue(k)), nil
}

func RemoveSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	if NilP(f) {
		return LispFalse, nil
	}

	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("remove-slot! requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("remove-slot! requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	return BooleanWithValue(FrameValue(f).Remove(StringValue(k))), nil
}

func SetSlotImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("set-slot! requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !NakedP(k) {
		err = ProcessError(fmt.Sprintf("set-slot! requires a naked symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	v, err := Eval(Caddr(args), env)
	if err != nil {
		return
	}

	return FrameValue(f).Set(StringValue(k), v), nil
}

func SendImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("send requires a frame as it's first argument, but was given %s.", String(f)), env)
		return
	}

	k, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !SymbolP(k) {
		err = ProcessError(fmt.Sprintf("send requires a symbol as it's second argument, but was given %s.", String(k)), env)
		return
	}

	if !FrameValue(f).HasSlot(StringValue(k)) {
		err = ProcessError(fmt.Sprintf("send requires an existing slot, but was given %s.", String(k)), env)
		return
	}

	fun := FrameValue(f).Get(StringValue(k))
	if !FunctionP(fun) {
		err = ProcessError(fmt.Sprintf("send requires a function slot, but was given a slot containing a %s.", TypeName(TypeOf(fun))), env)
		return
	}

	params := Cddr(args)
	return FunctionValue(fun).ApplyWithFrame(params, env, FrameValue(f))
}

func getSuperFunction(selector string, env *SymbolTableFrame) *Data {
	f := env.Frame
	if f == nil {
		return nil
	}

	for _, p := range f.Parents() {
		fun := p.Get(selector)
		if fun != nil {
			return fun
		}
	}

	return nil
}

func SendSuperImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	if !env.HasFrame() {
		err = ProcessError("send-super can only be used within the context of a frame.", env)
		return
	}

	selector, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !SymbolP(selector) {
		err = ProcessError(fmt.Sprintf("Selector must be a symbol but was %s.", TypeName(TypeOf(selector))), env)
		return
	}

	fun := getSuperFunction(StringValue(selector), env)
	if fun == nil || !FunctionP(fun) {
		err = ProcessError(fmt.Sprintf("Message sent must select a function slot but was %s.", TypeName(TypeOf(fun))), env)
		return
	}

	params := Cdr(args)
	frameEnv := NewSymbolTableFrameBelowWithFrame(env, env.Frame)
	frameEnv.BindLocallyTo(SymbolWithName("self"), FrameWithValue(env.Frame))
	return FunctionValue(fun).Apply(params, frameEnv)
}

func CloneImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("clone requires a frame as it's argument, but was given %s.", String(f)), env)
		return
	}

	return FrameWithValue(FrameValue(f).Clone()), nil
}

func JsonToLispImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	j, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !StringP(j) {
		err = ProcessError(fmt.Sprintf("json->lisp requires a string as it's argument, but was given %s.", String(j)), env)
		return
	}

	return JsonStringToLispWithFrames(StringValue(j)), nil
}

func LispToJsonImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	l, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	return StringWithValue(LispWithFramesToJsonString(l)), nil
}

func FrameKeysImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("keys requires a frame as it's argument, but was given %s.", String(f)), env)
		return
	}

	return ArrayToList(FrameValue(f).Keys()), nil
}

func FrameValuesImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !FrameP(f) {
		err = ProcessError(fmt.Sprintf("vals requires a frame as it's argument, but was given %s.", String(f)), env)
		return
	}

	return ArrayToList(FrameValue(f).Values()), nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/ajm188/advent_of_code/pkg/cli"
)

type coordinate struct{ X, Y int }

func (p *coordinate) String() string { return fmt.Sprintf("(%d, %d)", p.X, p.Y) }

type vent struct{ P1, P2 *coordinate }

func main() {
	path := flag.String("path", "input.txt", "")
	flag.Parse()

	data, err := cli.GetInput(*path)
	cli.ExitOnError(err)

	lines := strings.Split(string(data), "\n")
	if lines[len(lines)-1] == "" {
		lines = lines[:len(lines)-1]
	}

	errmsg := "bad input format: %q (line:%d) does not match format 'x1,y1 -> x2,y2'"
	parseErrMsg := "failed to parse coordinate in %q (line:%d): %w"

	vents := make([]*vent, len(lines))
	for i, line := range lines {
		parts := strings.Split(strings.ReplaceAll(line, " ", ""), "->")
		if len(parts) != 2 {
			cli.ExitOnError(fmt.Errorf(errmsg, line, i))
		}

		p1parts := strings.Split(parts[0], ",")
		if len(p1parts) != 2 {
			cli.ExitOnError(fmt.Errorf(errmsg, line, i))
		}

		x1, err := strconv.ParseInt(p1parts[0], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p1parts[0], i, err))
		}

		y1, err := strconv.ParseInt(p1parts[1], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p1parts[1], i, err))
		}

		p2parts := strings.Split(parts[1], ",")
		if len(p2parts) != 2 {
			cli.ExitOnError(fmt.Errorf(errmsg, line, i))
		}

		x2, err := strconv.ParseInt(p2parts[0], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p2parts[0], i, err))
		}

		y2, err := strconv.ParseInt(p2parts[1], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p2parts[1], i, err))
		}

		vents[i] = &vent{
			P1: &coordinate{X: int(x1), Y: int(y1)},
			P2: &coordinate{X: int(x2), Y: int(y2)},
		}
	}

	hitmap := map[string]int{}
	for _, vent := range vents {
		if vent.P1.Y == vent.P2.Y {
			xrange := []int{vent.P1.X, vent.P2.X}
			sort.Ints(xrange)
			for x := xrange[0]; x <= xrange[1]; x++ {
				p := &coordinate{
					X: x,
					Y: vent.P1.Y,
				}

				hitmap[p.String()]++
			}
		}

		if vent.P1.X == vent.P2.X {
			yrange := []int{vent.P1.Y, vent.P2.Y}
			sort.Ints(yrange)
			for y := yrange[0]; y <= yrange[1]; y++ {
				p := &coordinate{
					X: vent.P1.X,
					Y: y,
				}

				hitmap[p.String()]++
			}
		}
	}

	var count int
	for _, hits := range hitmap {
		if hits > 1 {
			count++
		}
	}

	fmt.Println(count)
}
<commit_msg>day5 part2, gross!<commit_after>package main

import (
	"flag"
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/ajm188/advent_of_code/pkg/cli"
)

type coordinate struct{ X, Y int }

func (p *coordinate) String() string { return fmt.Sprintf("(%d, %d)", p.X, p.Y) }

type vent struct{ P1, P2 *coordinate }

func main() {
	path := flag.String("path", "input.txt", "")
	flag.Parse()

	data, err := cli.GetInput(*path)
	cli.ExitOnError(err)

	lines := strings.Split(string(data), "\n")
	if lines[len(lines)-1] == "" {
		lines = lines[:len(lines)-1]
	}

	errmsg := "bad input format: %q (line:%d) does not match format 'x1,y1 -> x2,y2'"
	parseErrMsg := "failed to parse coordinate in %q (line:%d): %w"

	vents := make([]*vent, len(lines))
	for i, line := range lines {
		parts := strings.Split(strings.ReplaceAll(line, " ", ""), "->")
		if len(parts) != 2 {
			cli.ExitOnError(fmt.Errorf(errmsg, line, i))
		}

		p1parts := strings.Split(parts[0], ",")
		if len(p1parts) != 2 {
			cli.ExitOnError(fmt.Errorf(errmsg, line, i))
		}

		x1, err := strconv.ParseInt(p1parts[0], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p1parts[0], i, err))
		}

		y1, err := strconv.ParseInt(p1parts[1], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p1parts[1], i, err))
		}

		p2parts := strings.Split(parts[1], ",")
		if len(p2parts) != 2 {
			cli.ExitOnError(fmt.Errorf(errmsg, line, i))
		}

		x2, err := strconv.ParseInt(p2parts[0], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p2parts[0], i, err))
		}

		y2, err := strconv.ParseInt(p2parts[1], 10, 64)
		if err != nil {
			cli.ExitOnError(fmt.Errorf(parseErrMsg, p2parts[1], i, err))
		}

		vents[i] = &vent{
			P1: &coordinate{X: int(x1), Y: int(y1)},
			P2: &coordinate{X: int(x2), Y: int(y2)},
		}
	}

	hitmap2D := map[string]int{}
	hitmap := map[string]int{}
	for _, vent := range vents {
		xrange := []int{vent.P1.X, vent.P2.X}
		yrange := []int{vent.P1.Y, vent.P2.Y}
		sort.Ints(xrange)
		sort.Ints(yrange)

		if vent.P1.Y == vent.P2.Y {
			for x := xrange[0]; x <= xrange[1]; x++ {
				p := &coordinate{
					X: x,
					Y: vent.P1.Y,
				}

				hitmap2D[p.String()]++
				hitmap[p.String()]++
			}
		} else if vent.P1.X == vent.P2.X {
			for y := yrange[0]; y <= yrange[1]; y++ {
				p := &coordinate{
					X: vent.P1.X,
					Y: y,
				}

				hitmap2D[p.String()]++
				hitmap[p.String()]++
			}
		} else {
			var (
				xstep, ystep func(int) int
				xstop, ystop func(int) bool
			)
			if vent.P1.X < vent.P2.X {
				xstep = func(x int) int { return x + 1 }
				xstop = func(x int) bool { return x <= vent.P2.X }
			} else {
				xstep = func(x int) int { return x - 1 }
				xstop = func(x int) bool { return x >= vent.P2.X }
			}

			if vent.P1.Y < vent.P2.Y {
				ystep = func(y int) int { return y + 1 }
				ystop = func(y int) bool { return y <= vent.P2.Y }
			} else {
				ystep = func(y int) int { return y - 1 }
				ystop = func(y int) bool { return y >= vent.P2.Y }
			}

			for x, y := vent.P1.X, vent.P1.Y; xstop(x) && ystop(y); x, y = xstep(x), ystep(y) {
				p := &coordinate{x, y}
				hitmap[p.String()]++
			}
		}
	}

	var count2D int
	for _, hits := range hitmap2D {
		if hits > 1 {
			count2D++
		}
	}

	var count int
	for _, hits := range hitmap {
		if hits > 1 {
			count++
		}
	}

	fmt.Println(count2D)
	fmt.Println(count)
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"encoding/json"
	"fmt"

	"github.com/fatih/color"
)

// Group ...
type Group struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

// DeleteGroup ...
func (m *Manager) DeleteGroup(token string, group string) error {
	_, _, err := m.doRequest("/api/groups/"+group, "DELETE", []byte(""), token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Group " + group + " deleted")
	return nil
}

// CreateGroup ...
func (m *Manager) CreateGroup(token string, group string) error {
	payload := []byte(`{"name": "` + group + `"}`)
	_, _, err := m.doRequest("/api/groups/", "POST", payload, token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Group " + group + " created")
	return nil
}

// ListGroups ...
func (m *Manager) ListGroups(token string) (groups []Group, err error) {
	body, _, err := m.doRequest("/api/groups/", "GET", []byte(""), token, "")
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal([]byte(body), &groups)
	if err != nil {
		return nil, err
	}
	return groups, err
}

// GroupAddUser ...
func (m *Manager) GroupAddUser(token string, userid string, groupid string) error {
	payload := []byte(`{"userid": "` + userid + `", "groupid": "` + groupid + `"}`)
	_, _, err := m.doRequest("/api/groups/"+groupid+"/users/", "POST", payload, token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Added user " + userid + " to group " + groupid)
	return nil
}

// GroupRemoveUser ...
func (m *Manager) GroupRemoveUser(token string, userid string, groupid string) error {
	_, _, err := m.doRequest("/api/groups/"+groupid+"/users/"+userid, "DELETE", []byte(""), token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Removed user " + userid + " from group " + groupid)
	return nil
}

// GroupAddDatacenter ...
func (m *Manager) GroupAddDatacenter(token string, datacenterid string, groupid string) error {
	payload := []byte(`{"userid": "` + datacenterid + `", "groupid": "` + groupid + `"}`)
	_, _, err := m.doRequest("/api/groups/"+groupid+"/users/", "POST", payload, token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Added datacenter " + datacenterid + " to group " + groupid)
	return nil
}

// GroupRemoveDatacenter ...
func (m *Manager) GroupRemoveDatacenter(token string, datacenterid string, groupid string) error {
	_, _, err := m.doRequest("/api/groups/"+groupid+"/users/"+datacenterid, "DELETE", []byte(""), token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Removed datacenter " + datacenterid + " from group " + groupid)
	return nil
}
<commit_msg>Fix url when adding and removing datacenters<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"encoding/json"
	"fmt"

	"github.com/fatih/color"
)

// Group ...
type Group struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

// DeleteGroup ...
func (m *Manager) DeleteGroup(token string, group string) error {
	_, _, err := m.doRequest("/api/groups/"+group, "DELETE", []byte(""), token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Group " + group + " deleted")
	return nil
}

// CreateGroup ...
func (m *Manager) CreateGroup(token string, group string) error {
	payload := []byte(`{"name": "` + group + `"}`)
	_, _, err := m.doRequest("/api/groups/", "POST", payload, token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Group " + group + " created")
	return nil
}

// ListGroups ...
func (m *Manager) ListGroups(token string) (groups []Group, err error) {
	body, _, err := m.doRequest("/api/groups/", "GET", []byte(""), token, "")
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal([]byte(body), &groups)
	if err != nil {
		return nil, err
	}
	return groups, err
}

// GroupAddUser ...
func (m *Manager) GroupAddUser(token string, userid string, groupid string) error {
	payload := []byte(`{"userid": "` + userid + `", "groupid": "` + groupid + `"}`)
	_, _, err := m.doRequest("/api/groups/"+groupid+"/users/", "POST", payload, token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Added user " + userid + " to group " + groupid)
	return nil
}

// GroupRemoveUser ...
func (m *Manager) GroupRemoveUser(token string, userid string, groupid string) error {
	_, _, err := m.doRequest("/api/groups/"+groupid+"/users/"+userid, "DELETE", []byte(""), token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Removed user " + userid + " from group " + groupid)
	return nil
}

// GroupAddDatacenter ...
func (m *Manager) GroupAddDatacenter(token string, datacenterid string, groupid string) error {
	payload := []byte(`{"userid": "` + datacenterid + `", "groupid": "` + groupid + `"}`)
	_, _, err := m.doRequest("/api/groups/"+groupid+"/datacenters/", "POST", payload, token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Added datacenter " + datacenterid + " to group " + groupid)
	return nil
}

// GroupRemoveDatacenter ...
func (m *Manager) GroupRemoveDatacenter(token string, datacenterid string, groupid string) error {
	_, _, err := m.doRequest("/api/groups/"+groupid+"/datacenters/"+datacenterid, "DELETE", []byte(""), token, "")
	if err != nil {
		fmt.Println(err)
		return err
	}
	color.Green("SUCCESS: Removed datacenter " + datacenterid + " from group " + groupid)
	return nil
}
<|endoftext|>


<commit_before>package config

import (
	"reflect"
	"testing"
	"time"

	"github.com/mitchellh/packer/template/interpolate"
)

func TestDecode(t *testing.T) {
	type Target struct {
		Name    string
		Address string
		Time    time.Duration
	}

	cases := map[string]struct {
		Input  []interface{}
		Output *Target
		Opts   *DecodeOpts
	}{
		"basic": {
			[]interface{}{
				map[string]interface{}{
					"name": "bar",
					"time": "5s",
				},
			},
			&Target{
				Name: "bar",
				Time: 5 * time.Second,
			},
			nil,
		},

		"variables": {
			[]interface{}{
				map[string]interface{}{
					"name": "{{user `name`}}",
				},
				map[string]interface{}{
					"packer_user_variables": map[string]string{
						"name": "bar",
					},
				},
			},
			&Target{
				Name: "bar",
			},
			nil,
		},

		"filter": {
			[]interface{}{
				map[string]interface{}{
					"name":    "{{user `name`}}",
					"address": "{{user `name`}}",
				},
				map[string]interface{}{
					"packer_user_variables": map[string]string{
						"name": "bar",
					},
				},
			},
			&Target{
				Name:    "bar",
				Address: "{{user `name`}}",
			},
			&DecodeOpts{
				Interpolate: true,
				InterpolateFilter: &interpolate.RenderFilter{
					Include: []string{"name"},
				},
			},
		},
	}

	for k, tc := range cases {
		var result Target
		err := Decode(&result, tc.Opts, tc.Input...)
		if err != nil {
			t.Fatalf("err: %s\n\n%s", k, err)
		}

		if !reflect.DeepEqual(&result, tc.Output) {
			t.Fatalf("bad:\n\n%#v\n\n%#v", &result, tc.Output)
		}
	}
}
<commit_msg>helper/config: tests<commit_after>package config

import (
	"reflect"
	"testing"
	"time"

	"github.com/mitchellh/packer/template/interpolate"
)

func TestDecode(t *testing.T) {
	type Target struct {
		Name    string
		Address string
		Time    time.Duration
	}

	cases := map[string]struct {
		Input  []interface{}
		Output *Target
		Opts   *DecodeOpts
	}{
		"basic": {
			[]interface{}{
				map[string]interface{}{
					"name": "bar",
					"time": "5s",
				},
			},
			&Target{
				Name: "bar",
				Time: 5 * time.Second,
			},
			nil,
		},

		"variables": {
			[]interface{}{
				map[string]interface{}{
					"name": "{{user `name`}}",
				},
				map[string]interface{}{
					"packer_user_variables": map[string]string{
						"name": "bar",
					},
				},
			},
			&Target{
				Name: "bar",
			},
			nil,
		},

		"filter": {
			[]interface{}{
				map[string]interface{}{
					"name":    "{{user `name`}}",
					"address": "{{user `name`}}",
				},
				map[string]interface{}{
					"packer_user_variables": map[string]string{
						"name": "bar",
					},
				},
			},
			&Target{
				Name:    "bar",
				Address: "{{user `name`}}",
			},
			&DecodeOpts{
				Interpolate: true,
				InterpolateFilter: &interpolate.RenderFilter{
					Include: []string{"name"},
				},
			},
		},

		"build name": {
			[]interface{}{
				map[string]interface{}{
					"name": "{{build_name}}",
				},
				map[string]interface{}{
					"packer_build_name": "foo",
				},
			},
			&Target{
				Name: "foo",
			},
			nil,
		},

		"build type": {
			[]interface{}{
				map[string]interface{}{
					"name": "{{build_type}}",
				},
				map[string]interface{}{
					"packer_builder_type": "foo",
				},
			},
			&Target{
				Name: "foo",
			},
			nil,
		},
	}

	for k, tc := range cases {
		var result Target
		err := Decode(&result, tc.Opts, tc.Input...)
		if err != nil {
			t.Fatalf("err: %s\n\n%s", k, err)
		}

		if !reflect.DeepEqual(&result, tc.Output) {
			t.Fatalf("bad:\n\n%#v\n\n%#v", &result, tc.Output)
		}
	}
}
<|endoftext|>


<commit_before>package simple

import (
	"github.com/loadimpact/speedboat/runner"
	"golang.org/x/net/context"
	"net/http"
	"time"
)

type SimpleRunner struct {
	URL    string
	Client *http.Client
}

func New() *SimpleRunner {
	return &SimpleRunner{
		Client: &http.Client{
			Transport: &http.Transport{
				DisableKeepAlives: true,
			},
		},
	}
}

func (r *SimpleRunner) Run(ctx context.Context) <-chan runner.Result {
	ch := make(chan runner.Result)

	go func() {
		defer close(ch)

		for {
			// Note that we abort if we cannot create a request. This means we're either out of
			// memory, or we have invalid user input, neither of which are recoverable.
			req, err := http.NewRequest("GET", r.URL, nil)
			if err != nil {
				ch <- runner.Result{Error: err}
				return
			}
			req.Close = true
			req.Cancel = ctx.Done()

			startTime := time.Now()
			res, err := r.Client.Do(req)
			duration := time.Since(startTime)

			select {
			case <-ctx.Done():
				return
			default:
				if err != nil {
					ch <- runner.Result{Error: err, Time: duration}
					continue
				}
				res.Body.Close()
				ch <- runner.Result{Time: duration}
			}
		}
	}()

	return ch
}
<commit_msg>fasthttp<commit_after>package simple

import (
	"github.com/loadimpact/speedboat/runner"
	"github.com/valyala/fasthttp"
	"golang.org/x/net/context"
	"time"
)

type SimpleRunner struct {
	URL    string
	Client *fasthttp.Client
}

func New() *SimpleRunner {
	return &SimpleRunner{
		Client: &fasthttp.Client{
		// MaxIdleConnDuration: time.Duration(0),
		},
	}
}

func (r *SimpleRunner) Run(ctx context.Context) <-chan runner.Result {
	ch := make(chan runner.Result)

	go func() {
		defer close(ch)

		result := make(chan runner.Result, 1)
		for {
			go func() {
				req := fasthttp.AcquireRequest()
				defer fasthttp.ReleaseRequest(req)

				res := fasthttp.AcquireResponse()
				defer fasthttp.ReleaseResponse(res)

				req.SetRequestURI(r.URL)

				startTime := time.Now()
				err := r.Client.Do(req, res)
				duration := time.Since(startTime)

				result <- runner.Result{Error: err, Time: duration}
			}()

			select {
			case <-ctx.Done():
				return
			case res := <-result:
				ch <- res
			}
		}
	}()

	return ch
}
<|endoftext|>


<commit_before>// +build linux

package native

import "github.com/opencontainers/runc/libcontainer/configs"

var defaultSeccompProfile = &configs.Seccomp{
	DefaultAction: configs.Allow,
	Syscalls: []*configs.Syscall{
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "acct",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "add_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Similar to clock_settime and settimeofday
			// Time/Date is not namespaced
			Name:   "adjtimex",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_adjtime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_settime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny cloning new namespaces
			Name:   "clone",
			Action: configs.Errno,
			Args: []*configs.Arg{
				{
					// flags from sched.h
					// CLONE_NEWUTS		0x04000000
					// CLONE_NEWIPC		0x08000000
					// CLONE_NEWUSER	0x10000000
					// CLONE_NEWPID		0x20000000
					// CLONE_NEWNET		0x40000000
					Index: 0,
					Value: uint64(0x04000000),
					Op:    configs.GreaterThanOrEqualTo,
				},
				{
					// flags from sched.h
					// CLONE_NEWNS		0x00020000
					Index: 0,
					Value: uint64(0x00020000),
					Op:    configs.EqualTo,
				},
			},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "create_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "delete_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "finit_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny retrieval of exported kernel and module symbols
			Name:   "get_kernel_syms",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "get_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny getting the list of robust futexes
			Name:   "get_robust_list",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "init_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "ioperm",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "iopl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Sister syscall of kexec_load that does the same thing,
			// slightly different arguments
			Name:   "kexec_file_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading a new kernel for later execution
			Name:   "kexec_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "keyctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "lookup_dcookie",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "mbind",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "migrate_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Old syscall only used in 16-bit code,
			// and a potential information leak
			Name:   "modify_ldt",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny mount
			Name:   "mount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "move_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny interaction with the kernel nfs daemon
			Name:   "nfsservctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Cause of an old container breakout,
			// might as well restrict it to be on the safe side
			Name:   "open_by_handle_at",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "perf_event_open",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent container from enabling BSD emulation.
			// Not inherently dangerous, but poorly tested,
			// potential for a lot of kernel vulns in this.
			Name:   "personality",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny pivot_root
			Name:   "pivot_root",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Already blocked by dropping CAP_PTRACE
			Name:   "ptrace",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "query_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "quotactl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers reboot the host
			Name:   "reboot",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers restart a syscall.
			// Possible seccomp bypass, see: https://code.google.com/p/chromium/issues/detail?id=408827.
			Name:   "restart_syscall",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "request_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// meta, deny seccomp
			Name:   "seccomp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "set_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// deny associating a thread with a namespace
			Name:   "setns",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny setting the list of robust futexes
			Name:   "set_robust_list",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "settimeofday",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "stime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapon",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapoff",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny read/write system parameters
			Name:   "_sysctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount2",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Same as clone
			Name:   "unshare",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Older syscall related to shared libraries, unused for a long time
			Name:   "uselib",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
	},
}
<commit_msg>Allow use of robust list syscalls<commit_after>// +build linux

package native

import "github.com/opencontainers/runc/libcontainer/configs"

var defaultSeccompProfile = &configs.Seccomp{
	DefaultAction: configs.Allow,
	Syscalls: []*configs.Syscall{
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "acct",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "add_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Similar to clock_settime and settimeofday
			// Time/Date is not namespaced
			Name:   "adjtimex",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_adjtime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_settime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny cloning new namespaces
			Name:   "clone",
			Action: configs.Errno,
			Args: []*configs.Arg{
				{
					// flags from sched.h
					// CLONE_NEWUTS		0x04000000
					// CLONE_NEWIPC		0x08000000
					// CLONE_NEWUSER	0x10000000
					// CLONE_NEWPID		0x20000000
					// CLONE_NEWNET		0x40000000
					Index: 0,
					Value: uint64(0x04000000),
					Op:    configs.GreaterThanOrEqualTo,
				},
				{
					// flags from sched.h
					// CLONE_NEWNS		0x00020000
					Index: 0,
					Value: uint64(0x00020000),
					Op:    configs.EqualTo,
				},
			},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "create_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "delete_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "finit_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny retrieval of exported kernel and module symbols
			Name:   "get_kernel_syms",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "get_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "init_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "ioperm",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "iopl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Sister syscall of kexec_load that does the same thing,
			// slightly different arguments
			Name:   "kexec_file_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading a new kernel for later execution
			Name:   "kexec_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "keyctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "lookup_dcookie",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "mbind",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "migrate_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Old syscall only used in 16-bit code,
			// and a potential information leak
			Name:   "modify_ldt",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny mount
			Name:   "mount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "move_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny interaction with the kernel nfs daemon
			Name:   "nfsservctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Cause of an old container breakout,
			// might as well restrict it to be on the safe side
			Name:   "open_by_handle_at",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "perf_event_open",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent container from enabling BSD emulation.
			// Not inherently dangerous, but poorly tested,
			// potential for a lot of kernel vulns in this.
			Name:   "personality",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny pivot_root
			Name:   "pivot_root",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Already blocked by dropping CAP_PTRACE
			Name:   "ptrace",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "query_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "quotactl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers reboot the host
			Name:   "reboot",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers restart a syscall.
			// Possible seccomp bypass, see: https://code.google.com/p/chromium/issues/detail?id=408827.
			Name:   "restart_syscall",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "request_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// meta, deny seccomp
			Name:   "seccomp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "set_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// deny associating a thread with a namespace
			Name:   "setns",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "settimeofday",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "stime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapon",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapoff",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny read/write system parameters
			Name:   "_sysctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount2",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Same as clone
			Name:   "unshare",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Older syscall related to shared libraries, unused for a long time
			Name:   "uselib",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
	},
}
<|endoftext|>


<commit_before>package utils

import (
	"strconv"
	"time"
)

func UnixMicroStringToTime(s string) (time.Time, error) {
	validate := NewValidate()
	validate.RegisterValidation("unixmicro", IsTimeUnixMicro)
	if err := validate.Var(s, "unixmicro"); err != nil {
		return time.Time{}, err
	}

	sec, _ := strconv.ParseInt(s[:10], 10, 64)
	nsec, _ := strconv.ParseInt(s[10:], 10, 64)

	return time.Unix(sec, nsec), nil
}
<commit_msg>Fix utils.UnixMicroStringToTime<commit_after>package utils

import (
	"strconv"
	"time"
)

func UnixMicroStringToTime(s string) (time.Time, error) {
	validate := NewValidate()
	validate.RegisterValidation("unixmicro", IsTimeUnixMicro)
	if err := validate.Var(s, "unixmicro"); err != nil {
		return time.Time{}, err
	}

	sec, _ := strconv.ParseInt(s[:10], 10, 64)
	nsec, _ := strconv.ParseInt(s[10:], 10, 64)

	return time.Unix(sec, nsec*1000), nil
}
<|endoftext|>


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

// The image package implements a basic 2-D image library.
package image

// An Image is a rectangular grid of Colors drawn from a ColorModel.
type Image interface {
	ColorModel() ColorModel;
	Width() int;
	Height() int;
	// At(0, 0) returns the upper-left pixel of the grid.
	// At(Width()-1, Height()-1) returns the lower-right pixel.
	At(x, y int) Color;
}

// An RGBA is an in-memory image backed by a 2-D slice of RGBAColor values.
type RGBA struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]RGBAColor;
}

func (p *RGBA) ColorModel() ColorModel	{ return RGBAColorModel }

func (p *RGBA) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *RGBA) Height() int	{ return len(p.Pixel) }

func (p *RGBA) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *RGBA) Set(x, y int, c Color)	{ p.Pixel[y][x] = toRGBAColor(c).(RGBAColor) }

// NewRGBA returns a new RGBA with the given width and height.
func NewRGBA(w, h int) *RGBA {
	pixel := make([][]RGBAColor, h);
	for y := 0; y < int(h); y++ {
		pixel[y] = make([]RGBAColor, w)
	}
	return &RGBA{pixel};
}

// An RGBA64 is an in-memory image backed by a 2-D slice of RGBA64Color values.
type RGBA64 struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]RGBA64Color;
}

func (p *RGBA64) ColorModel() ColorModel	{ return RGBA64ColorModel }

func (p *RGBA64) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *RGBA64) Height() int	{ return len(p.Pixel) }

func (p *RGBA64) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *RGBA64) Set(x, y int, c Color)	{ p.Pixel[y][x] = toRGBA64Color(c).(RGBA64Color) }

// NewRGBA64 returns a new RGBA64 with the given width and height.
func NewRGBA64(w, h int) *RGBA64 {
	pixel := make([][]RGBA64Color, h);
	for y := 0; y < int(h); y++ {
		pixel[y] = make([]RGBA64Color, w)
	}
	return &RGBA64{pixel};
}

// A NRGBA is an in-memory image backed by a 2-D slice of NRGBAColor values.
type NRGBA struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]NRGBAColor;
}

func (p *NRGBA) ColorModel() ColorModel	{ return NRGBAColorModel }

func (p *NRGBA) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *NRGBA) Height() int	{ return len(p.Pixel) }

func (p *NRGBA) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *NRGBA) Set(x, y int, c Color)	{ p.Pixel[y][x] = toNRGBAColor(c).(NRGBAColor) }

// NewNRGBA returns a new NRGBA with the given width and height.
func NewNRGBA(w, h int) *NRGBA {
	pixel := make([][]NRGBAColor, h);
	for y := 0; y < int(h); y++ {
		pixel[y] = make([]NRGBAColor, w)
	}
	return &NRGBA{pixel};
}

// A NRGBA64 is an in-memory image backed by a 2-D slice of NRGBA64Color values.
type NRGBA64 struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]NRGBA64Color;
}

func (p *NRGBA64) ColorModel() ColorModel	{ return NRGBA64ColorModel }

func (p *NRGBA64) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *NRGBA64) Height() int	{ return len(p.Pixel) }

func (p *NRGBA64) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *NRGBA64) Set(x, y int, c Color)	{ p.Pixel[y][x] = toNRGBA64Color(c).(NRGBA64Color) }

// NewNRGBA64 returns a new NRGBA64 with the given width and height.
func NewNRGBA64(w, h int) *NRGBA64 {
	pixel := make([][]NRGBA64Color, h);
	for y := 0; y < int(h); y++ {
		pixel[y] = make([]NRGBA64Color, w)
	}
	return &NRGBA64{pixel};
}

// A PalettedColorModel represents a fixed palette of colors.
type PalettedColorModel []Color

func diff(a, b uint32) uint32 {
	if a > b {
		return a - b
	}
	return b - a;
}

// Convert returns the palette color closest to c in Euclidean R,G,B space.
func (p PalettedColorModel) Convert(c Color) Color {
	if len(p) == 0 {
		return nil
	}
	// TODO(nigeltao): Revisit the "pick the palette color which minimizes sum-squared-difference"
	// algorithm when the premultiplied vs unpremultiplied issue is resolved.
	// Currently, we only compare the R, G and B values, and ignore A.
	cr, cg, cb, _ := c.RGBA();
	// Shift by 17 bits to avoid potential uint32 overflow in sum-squared-difference.
	cr >>= 17;
	cg >>= 17;
	cb >>= 17;
	result := Color(nil);
	bestSSD := uint32(1<<32 - 1);
	for _, v := range p {
		vr, vg, vb, _ := v.RGBA();
		vr >>= 17;
		vg >>= 17;
		vb >>= 17;
		dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb);
		ssd := (dr * dr) + (dg * dg) + (db * db);
		if ssd < bestSSD {
			bestSSD = ssd;
			result = v;
		}
	}
	return result;
}

// A Paletted is an in-memory image backed by a 2-D slice of uint8 values and a PalettedColorModel.
type Paletted struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Palette[Pixel[y][x]].
	Pixel	[][]uint8;
	Palette	PalettedColorModel;
}

func (p *Paletted) ColorModel() ColorModel	{ return p.Palette }

func (p *Paletted) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *Paletted) Height() int	{ return len(p.Pixel) }

func (p *Paletted) At(x, y int) Color	{ return p.Palette[p.Pixel[y][x]] }

func (p *Paletted) ColorIndexAt(x, y int) uint8 {
	return p.Pixel[y][x]
}

func (p *Paletted) SetColorIndex(x, y int, index uint8) {
	p.Pixel[y][x] = index
}

// NewPaletted returns a new Paletted with the given width, height and palette.
func NewPaletted(w, h int, m PalettedColorModel) *Paletted {
	pixel := make([][]uint8, h);
	for y := 0; y < int(h); y++ {
		pixel[y] = make([]uint8, w)
	}
	return &Paletted{pixel, m};
}
<commit_msg>Remove unnecessary int(h) casts in image.go.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The image package implements a basic 2-D image library.
package image

// An Image is a rectangular grid of Colors drawn from a ColorModel.
type Image interface {
	ColorModel() ColorModel;
	Width() int;
	Height() int;
	// At(0, 0) returns the upper-left pixel of the grid.
	// At(Width()-1, Height()-1) returns the lower-right pixel.
	At(x, y int) Color;
}

// An RGBA is an in-memory image backed by a 2-D slice of RGBAColor values.
type RGBA struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]RGBAColor;
}

func (p *RGBA) ColorModel() ColorModel	{ return RGBAColorModel }

func (p *RGBA) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *RGBA) Height() int	{ return len(p.Pixel) }

func (p *RGBA) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *RGBA) Set(x, y int, c Color)	{ p.Pixel[y][x] = toRGBAColor(c).(RGBAColor) }

// NewRGBA returns a new RGBA with the given width and height.
func NewRGBA(w, h int) *RGBA {
	pixel := make([][]RGBAColor, h);
	for y := 0; y < h; y++ {
		pixel[y] = make([]RGBAColor, w)
	}
	return &RGBA{pixel};
}

// An RGBA64 is an in-memory image backed by a 2-D slice of RGBA64Color values.
type RGBA64 struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]RGBA64Color;
}

func (p *RGBA64) ColorModel() ColorModel	{ return RGBA64ColorModel }

func (p *RGBA64) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *RGBA64) Height() int	{ return len(p.Pixel) }

func (p *RGBA64) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *RGBA64) Set(x, y int, c Color)	{ p.Pixel[y][x] = toRGBA64Color(c).(RGBA64Color) }

// NewRGBA64 returns a new RGBA64 with the given width and height.
func NewRGBA64(w, h int) *RGBA64 {
	pixel := make([][]RGBA64Color, h);
	for y := 0; y < h; y++ {
		pixel[y] = make([]RGBA64Color, w)
	}
	return &RGBA64{pixel};
}

// A NRGBA is an in-memory image backed by a 2-D slice of NRGBAColor values.
type NRGBA struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]NRGBAColor;
}

func (p *NRGBA) ColorModel() ColorModel	{ return NRGBAColorModel }

func (p *NRGBA) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *NRGBA) Height() int	{ return len(p.Pixel) }

func (p *NRGBA) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *NRGBA) Set(x, y int, c Color)	{ p.Pixel[y][x] = toNRGBAColor(c).(NRGBAColor) }

// NewNRGBA returns a new NRGBA with the given width and height.
func NewNRGBA(w, h int) *NRGBA {
	pixel := make([][]NRGBAColor, h);
	for y := 0; y < h; y++ {
		pixel[y] = make([]NRGBAColor, w)
	}
	return &NRGBA{pixel};
}

// A NRGBA64 is an in-memory image backed by a 2-D slice of NRGBA64Color values.
type NRGBA64 struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x].
	Pixel [][]NRGBA64Color;
}

func (p *NRGBA64) ColorModel() ColorModel	{ return NRGBA64ColorModel }

func (p *NRGBA64) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *NRGBA64) Height() int	{ return len(p.Pixel) }

func (p *NRGBA64) At(x, y int) Color	{ return p.Pixel[y][x] }

func (p *NRGBA64) Set(x, y int, c Color)	{ p.Pixel[y][x] = toNRGBA64Color(c).(NRGBA64Color) }

// NewNRGBA64 returns a new NRGBA64 with the given width and height.
func NewNRGBA64(w, h int) *NRGBA64 {
	pixel := make([][]NRGBA64Color, h);
	for y := 0; y < h; y++ {
		pixel[y] = make([]NRGBA64Color, w)
	}
	return &NRGBA64{pixel};
}

// A PalettedColorModel represents a fixed palette of colors.
type PalettedColorModel []Color

func diff(a, b uint32) uint32 {
	if a > b {
		return a - b
	}
	return b - a;
}

// Convert returns the palette color closest to c in Euclidean R,G,B space.
func (p PalettedColorModel) Convert(c Color) Color {
	if len(p) == 0 {
		return nil
	}
	// TODO(nigeltao): Revisit the "pick the palette color which minimizes sum-squared-difference"
	// algorithm when the premultiplied vs unpremultiplied issue is resolved.
	// Currently, we only compare the R, G and B values, and ignore A.
	cr, cg, cb, _ := c.RGBA();
	// Shift by 17 bits to avoid potential uint32 overflow in sum-squared-difference.
	cr >>= 17;
	cg >>= 17;
	cb >>= 17;
	result := Color(nil);
	bestSSD := uint32(1<<32 - 1);
	for _, v := range p {
		vr, vg, vb, _ := v.RGBA();
		vr >>= 17;
		vg >>= 17;
		vb >>= 17;
		dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb);
		ssd := (dr * dr) + (dg * dg) + (db * db);
		if ssd < bestSSD {
			bestSSD = ssd;
			result = v;
		}
	}
	return result;
}

// A Paletted is an in-memory image backed by a 2-D slice of uint8 values and a PalettedColorModel.
type Paletted struct {
	// The Pixel field's indices are y first, then x, so that At(x, y) == Palette[Pixel[y][x]].
	Pixel	[][]uint8;
	Palette	PalettedColorModel;
}

func (p *Paletted) ColorModel() ColorModel	{ return p.Palette }

func (p *Paletted) Width() int {
	if len(p.Pixel) == 0 {
		return 0
	}
	return len(p.Pixel[0]);
}

func (p *Paletted) Height() int	{ return len(p.Pixel) }

func (p *Paletted) At(x, y int) Color	{ return p.Palette[p.Pixel[y][x]] }

func (p *Paletted) ColorIndexAt(x, y int) uint8 {
	return p.Pixel[y][x]
}

func (p *Paletted) SetColorIndex(x, y int, index uint8) {
	p.Pixel[y][x] = index
}

// NewPaletted returns a new Paletted with the given width, height and palette.
func NewPaletted(w, h int, m PalettedColorModel) *Paletted {
	pixel := make([][]uint8, h);
	for y := 0; y < h; y++ {
		pixel[y] = make([]uint8, w)
	}
	return &Paletted{pixel, m};
}
<|endoftext|>


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

// Marshalling and unmarshalling of
// JSON data into Go structs using reflection.

package json

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"
)

type structBuilder struct {
	val reflect.Value

	// if map_ != nil, write val to map_[key] on each change
	map_ *reflect.MapValue
	key  reflect.Value
}

var nobuilder *structBuilder

func isfloat(v reflect.Value) bool {
	switch v.(type) {
	case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		return true
	}
	return false
}

func setfloat(v reflect.Value, f float64) {
	switch v := v.(type) {
	case *reflect.FloatValue:
		v.Set(float(f))
	case *reflect.Float32Value:
		v.Set(float32(f))
	case *reflect.Float64Value:
		v.Set(float64(f))
	}
}

func setint(v reflect.Value, i int64) {
	switch v := v.(type) {
	case *reflect.IntValue:
		v.Set(int(i))
	case *reflect.Int8Value:
		v.Set(int8(i))
	case *reflect.Int16Value:
		v.Set(int16(i))
	case *reflect.Int32Value:
		v.Set(int32(i))
	case *reflect.Int64Value:
		v.Set(int64(i))
	case *reflect.UintValue:
		v.Set(uint(i))
	case *reflect.Uint8Value:
		v.Set(uint8(i))
	case *reflect.Uint16Value:
		v.Set(uint16(i))
	case *reflect.Uint32Value:
		v.Set(uint32(i))
	case *reflect.Uint64Value:
		v.Set(uint64(i))
	}
}

// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
	if b == nil {
		return
	}
	if b.map_ != nil {
		b.map_.SetElem(b.key, b.val)
	}
}

func (b *structBuilder) Int64(i int64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, i)
	}
}

func (b *structBuilder) Uint64(i uint64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, int64(i))
	}
}

func (b *structBuilder) Float64(f float64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, f)
	} else {
		setint(v, int64(f))
	}
}

func (b *structBuilder) Null() {}

func (b *structBuilder) String(s string) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.StringValue); ok {
		v.Set(s)
	}
}

func (b *structBuilder) Bool(tf bool) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.BoolValue); ok {
		v.Set(tf)
	}
}

func (b *structBuilder) Array() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.SliceValue); ok {
		if v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
		}
	}
}

func (b *structBuilder) Elem(i int) Builder {
	if b == nil || i < 0 {
		return nobuilder
	}
	switch v := b.val.(type) {
	case *reflect.ArrayValue:
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	case *reflect.SliceValue:
		if i >= v.Cap() {
			n := v.Cap()
			if n < 8 {
				n = 8
			}
			for n <= i {
				n *= 2
			}
			nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
			reflect.ArrayCopy(nv, v)
			v.Set(nv)
		}
		if v.Len() <= i && i < v.Cap() {
			v.SetLen(i + 1)
		}
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	}
	return nobuilder
}

func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}

func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			if strings.ToLower(t.Field(i).Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}

// Unmarshal parses the JSON syntax string s and fills in
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val.  Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string;
//		Addr string;
//	}
//
//	type Result struct {
//		Name string;
//		Phone string;
//		Email []Email
//	}
//
//	var r = Result{ "name", "phone", nil }
//
// unmarshalling the JSON syntax string
//
//	{
//	  "email": [
//	    {
//	      "where": "home",
//	      "addr": "gre@example.com"
//	    },
//	    {
//	      "where": "work",
//	      "addr": "gre@work.com"
//	    }
//	  ],
//	  "name": "Grace R. Emlin",
//	  "address": "123 Main Street"
//	}
//
// via Unmarshal(s, &r) is equivalent to assigning
//
//	r = Result{
//		"Grace R. Emlin",	// name
//		"phone",		// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the JSON field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match JSON field names to struct field names.
//
// To unmarshal a top-level JSON array, pass in a pointer to an empty
// slice of the correct type.
//
// On success, Unmarshal returns with ok set to true.
// On a syntax error, it returns with ok set to false and errtok
// set to the offending token.
func Unmarshal(s string, val interface{}) (ok bool, errtok string) {
	v := reflect.NewValue(val)
	var b *structBuilder

	// If val is a pointer to a slice, we append to the slice.
	if ptr, ok := v.(*reflect.PtrValue); ok {
		if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
			b = &structBuilder{val: slice}
		}
	}

	if b == nil {
		b = &structBuilder{val: v}
	}

	ok, _, errtok = Parse(s, b)
	if !ok {
		return false, errtok
	}
	return true, ""
}

type MarshalError struct {
	T reflect.Type
}

func (e *MarshalError) String() string {
	return "json cannot encode value of type " + e.T.String()
}

type writeState struct {
	bytes.Buffer
	indent   string
	newlines bool
	depth    int
}

func (s *writeState) descend(bra byte) {
	s.depth++
	s.WriteByte(bra)
}

func (s *writeState) ascend(ket byte) {
	s.depth--
	s.writeIndent()
	s.WriteByte(ket)
}

func (s *writeState) writeIndent() {
	if s.newlines {
		s.WriteByte('\n')
	}
	for i := 0; i < s.depth; i++ {
		s.WriteString(s.indent)
	}
}

func (s *writeState) writeArrayOrSlice(val reflect.ArrayOrSliceValue) {
	s.descend('[')

	for i := 0; i < val.Len(); i++ {
		s.writeIndent()
		s.writeValue(val.Elem(i))
		if i < val.Len()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend(']')
}

func (s *writeState) writeMap(val *reflect.MapValue) {
	key := val.Type().(*reflect.MapType).Key()
	if _, ok := key.(*reflect.StringType); !ok {
		panic(&MarshalError{val.Type()})
	}

	s.descend('{')

	keys := val.Keys()
	for i := 0; i < len(keys); i++ {
		s.writeIndent()
		fmt.Fprintf(s, "%s:", Quote(keys[i].(*reflect.StringValue).Get()))
		s.writeValue(val.Elem(keys[i]))
		if i < len(keys)-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
}

func (s *writeState) writeStruct(val *reflect.StructValue) {
	s.descend('{')

	typ := val.Type().(*reflect.StructType)

	for i := 0; i < val.NumField(); i++ {
		s.writeIndent()
		fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name))
		s.writeValue(val.Field(i))
		if i < val.NumField()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
}

func (s *writeState) writeValue(val reflect.Value) {
	if val == nil {
		fmt.Fprint(s, "null")
		return
	}

	switch v := val.(type) {
	case *reflect.StringValue:
		fmt.Fprint(s, Quote(v.Get()))
	case *reflect.ArrayValue:
		s.writeArrayOrSlice(v)
	case *reflect.SliceValue:
		s.writeArrayOrSlice(v)
	case *reflect.MapValue:
		s.writeMap(v)
	case *reflect.StructValue:
		s.writeStruct(v)
	case *reflect.ChanValue,
		*reflect.UnsafePointerValue,
		*reflect.FuncValue:
		panic(&MarshalError{val.Type()})
	case *reflect.InterfaceValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			s.writeValue(v.Elem())
		}
	case *reflect.PtrValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			s.writeValue(v.Elem())
		}
	case *reflect.UintptrValue:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint64Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint32Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint16Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint8Value:
		fmt.Fprintf(s, "%d", v.Get())
	default:
		value := val.(reflect.Value)
		fmt.Fprintf(s, "%#v", value.Interface())
	}
}

func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) {
	defer func() {
		if e := recover(); e != nil {
			err = e.(*MarshalError)
		}
	}()
	s.writeValue(reflect.NewValue(val))
	if s.newlines {
		s.WriteByte('\n')
	}
	_, err = s.WriteTo(w)
	return
}

// Marshal writes the JSON encoding of val to w.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func Marshal(w io.Writer, val interface{}) os.Error {
	s := &writeState{indent: "", newlines: false, depth: 0}
	return s.marshal(w, val)
}

// MarshalIndent writes the JSON encoding of val to w,
// indenting nested values using the indent string.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func MarshalIndent(w io.Writer, val interface{}, indent string) os.Error {
	s := &writeState{indent: indent, newlines: true, depth: 0}
	return s.marshal(w, val)
}
<commit_msg>json: update documentation to match current coding style<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Marshalling and unmarshalling of
// JSON data into Go structs using reflection.

package json

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"
)

type structBuilder struct {
	val reflect.Value

	// if map_ != nil, write val to map_[key] on each change
	map_ *reflect.MapValue
	key  reflect.Value
}

var nobuilder *structBuilder

func isfloat(v reflect.Value) bool {
	switch v.(type) {
	case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		return true
	}
	return false
}

func setfloat(v reflect.Value, f float64) {
	switch v := v.(type) {
	case *reflect.FloatValue:
		v.Set(float(f))
	case *reflect.Float32Value:
		v.Set(float32(f))
	case *reflect.Float64Value:
		v.Set(float64(f))
	}
}

func setint(v reflect.Value, i int64) {
	switch v := v.(type) {
	case *reflect.IntValue:
		v.Set(int(i))
	case *reflect.Int8Value:
		v.Set(int8(i))
	case *reflect.Int16Value:
		v.Set(int16(i))
	case *reflect.Int32Value:
		v.Set(int32(i))
	case *reflect.Int64Value:
		v.Set(int64(i))
	case *reflect.UintValue:
		v.Set(uint(i))
	case *reflect.Uint8Value:
		v.Set(uint8(i))
	case *reflect.Uint16Value:
		v.Set(uint16(i))
	case *reflect.Uint32Value:
		v.Set(uint32(i))
	case *reflect.Uint64Value:
		v.Set(uint64(i))
	}
}

// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
	if b == nil {
		return
	}
	if b.map_ != nil {
		b.map_.SetElem(b.key, b.val)
	}
}

func (b *structBuilder) Int64(i int64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, i)
	}
}

func (b *structBuilder) Uint64(i uint64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, int64(i))
	}
}

func (b *structBuilder) Float64(f float64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, f)
	} else {
		setint(v, int64(f))
	}
}

func (b *structBuilder) Null() {}

func (b *structBuilder) String(s string) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.StringValue); ok {
		v.Set(s)
	}
}

func (b *structBuilder) Bool(tf bool) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.BoolValue); ok {
		v.Set(tf)
	}
}

func (b *structBuilder) Array() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.SliceValue); ok {
		if v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
		}
	}
}

func (b *structBuilder) Elem(i int) Builder {
	if b == nil || i < 0 {
		return nobuilder
	}
	switch v := b.val.(type) {
	case *reflect.ArrayValue:
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	case *reflect.SliceValue:
		if i >= v.Cap() {
			n := v.Cap()
			if n < 8 {
				n = 8
			}
			for n <= i {
				n *= 2
			}
			nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
			reflect.ArrayCopy(nv, v)
			v.Set(nv)
		}
		if v.Len() <= i && i < v.Cap() {
			v.SetLen(i + 1)
		}
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	}
	return nobuilder
}

func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}

func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			if strings.ToLower(t.Field(i).Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}

// Unmarshal parses the JSON syntax string s and fills in
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val.  Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string
//		Addr string
//	}
//
//	type Result struct {
//		Name string
//		Phone string
//		Email []Email
//	}
//
//	var r = Result{ "name", "phone", nil }
//
// unmarshalling the JSON syntax string
//
//	{
//	  "email": [
//	    {
//	      "where": "home",
//	      "addr": "gre@example.com"
//	    },
//	    {
//	      "where": "work",
//	      "addr": "gre@work.com"
//	    }
//	  ],
//	  "name": "Grace R. Emlin",
//	  "address": "123 Main Street"
//	}
//
// via Unmarshal(s, &r) is equivalent to assigning
//
//	r = Result{
//		"Grace R. Emlin",	// name
//		"phone",		// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" },
//		},
//	}
//
// Note that the field r.Phone has not been modified and
// that the JSON field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match JSON field names to struct field names.
//
// To unmarshal a top-level JSON array, pass in a pointer to an empty
// slice of the correct type.
//
// On success, Unmarshal returns with ok set to true.
// On a syntax error, it returns with ok set to false and errtok
// set to the offending token.
func Unmarshal(s string, val interface{}) (ok bool, errtok string) {
	v := reflect.NewValue(val)
	var b *structBuilder

	// If val is a pointer to a slice, we append to the slice.
	if ptr, ok := v.(*reflect.PtrValue); ok {
		if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
			b = &structBuilder{val: slice}
		}
	}

	if b == nil {
		b = &structBuilder{val: v}
	}

	ok, _, errtok = Parse(s, b)
	if !ok {
		return false, errtok
	}
	return true, ""
}

type MarshalError struct {
	T reflect.Type
}

func (e *MarshalError) String() string {
	return "json cannot encode value of type " + e.T.String()
}

type writeState struct {
	bytes.Buffer
	indent   string
	newlines bool
	depth    int
}

func (s *writeState) descend(bra byte) {
	s.depth++
	s.WriteByte(bra)
}

func (s *writeState) ascend(ket byte) {
	s.depth--
	s.writeIndent()
	s.WriteByte(ket)
}

func (s *writeState) writeIndent() {
	if s.newlines {
		s.WriteByte('\n')
	}
	for i := 0; i < s.depth; i++ {
		s.WriteString(s.indent)
	}
}

func (s *writeState) writeArrayOrSlice(val reflect.ArrayOrSliceValue) {
	s.descend('[')

	for i := 0; i < val.Len(); i++ {
		s.writeIndent()
		s.writeValue(val.Elem(i))
		if i < val.Len()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend(']')
}

func (s *writeState) writeMap(val *reflect.MapValue) {
	key := val.Type().(*reflect.MapType).Key()
	if _, ok := key.(*reflect.StringType); !ok {
		panic(&MarshalError{val.Type()})
	}

	s.descend('{')

	keys := val.Keys()
	for i := 0; i < len(keys); i++ {
		s.writeIndent()
		fmt.Fprintf(s, "%s:", Quote(keys[i].(*reflect.StringValue).Get()))
		s.writeValue(val.Elem(keys[i]))
		if i < len(keys)-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
}

func (s *writeState) writeStruct(val *reflect.StructValue) {
	s.descend('{')

	typ := val.Type().(*reflect.StructType)

	for i := 0; i < val.NumField(); i++ {
		s.writeIndent()
		fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name))
		s.writeValue(val.Field(i))
		if i < val.NumField()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
}

func (s *writeState) writeValue(val reflect.Value) {
	if val == nil {
		fmt.Fprint(s, "null")
		return
	}

	switch v := val.(type) {
	case *reflect.StringValue:
		fmt.Fprint(s, Quote(v.Get()))
	case *reflect.ArrayValue:
		s.writeArrayOrSlice(v)
	case *reflect.SliceValue:
		s.writeArrayOrSlice(v)
	case *reflect.MapValue:
		s.writeMap(v)
	case *reflect.StructValue:
		s.writeStruct(v)
	case *reflect.ChanValue,
		*reflect.UnsafePointerValue,
		*reflect.FuncValue:
		panic(&MarshalError{val.Type()})
	case *reflect.InterfaceValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			s.writeValue(v.Elem())
		}
	case *reflect.PtrValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			s.writeValue(v.Elem())
		}
	case *reflect.UintptrValue:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint64Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint32Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint16Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint8Value:
		fmt.Fprintf(s, "%d", v.Get())
	default:
		value := val.(reflect.Value)
		fmt.Fprintf(s, "%#v", value.Interface())
	}
}

func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) {
	defer func() {
		if e := recover(); e != nil {
			err = e.(*MarshalError)
		}
	}()
	s.writeValue(reflect.NewValue(val))
	if s.newlines {
		s.WriteByte('\n')
	}
	_, err = s.WriteTo(w)
	return
}

// Marshal writes the JSON encoding of val to w.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func Marshal(w io.Writer, val interface{}) os.Error {
	s := &writeState{indent: "", newlines: false, depth: 0}
	return s.marshal(w, val)
}

// MarshalIndent writes the JSON encoding of val to w,
// indenting nested values using the indent string.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func MarshalIndent(w io.Writer, val interface{}, indent string) os.Error {
	s := &writeState{indent: indent, newlines: true, depth: 0}
	return s.marshal(w, val)
}
<|endoftext|>


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

// Command ptype prints Go types from a binary using DWARF info.
package main

import (
	"debug/dwarf"
	"debug/elf"
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"
	"unicode/utf8"
)

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

	// Parse type regexp args.
	regexps := []*regexp.Regexp{}
	for _, tre := range flag.Args()[1:] {
		re, err := regexp.Compile("^" + tre)
		if err != nil {
			fmt.Fprintf(os.Stderr, "bad regexp %q: %s", tre, err)
			os.Exit(1)
		}
		regexps = append(regexps, re)
	}
	if len(regexps) == 0 {
		regexps = append(regexps, regexp.MustCompile(".*"))
	}

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

	// Find all of the named types.
	r := d.Reader()
	for {
		ent, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if ent == nil {
			break
		}

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

		name, ok := ent.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}

		// Do we want this type?
		matched := false
		for _, re := range regexps {
			if re.MatchString(name) {
				matched = true
				break
			}
		}
		if isBuiltinName(name) || !matched {
			r.SkipChildren()
			continue
		}

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

		typ, err := d.Type(base)
		if err != nil {
			log.Fatal(err)
		}

		pkg := ""
		if i := strings.LastIndex(name, "."); i >= 0 {
			pkg = name[:i+1]
		}

		p := &typePrinter{pkg: pkg}
		p.fmt("type %s ", name)
		p.printType(typ)
		p.fmt("\n\n")

		r.SkipChildren()
	}
}

func isBuiltinName(typeName string) bool {
	switch typeName {
	case "string":
		return true
	}
	return strings.HasPrefix(typeName, "map[") ||
		strings.HasPrefix(typeName, "func(") ||
		strings.HasPrefix(typeName, "chan ") ||
		strings.HasPrefix(typeName, "chan<- ") ||
		strings.HasPrefix(typeName, "<-chan ")
}

type typePrinter struct {
	offset []int64
	depth  int
	nameOk int
	pkg    string

	// pos is the current character position on this line.
	pos int

	// lineComment is a comment to print at the end of this line.
	lineComment string
}

func (p *typePrinter) fmt(f string, args ...interface{}) {
	b := fmt.Sprintf(f, args...)
	if strings.IndexAny(b, "\n\t") < 0 {
		fmt.Printf("%s", b)
		p.pos += utf8.RuneCountInString(b)
		return
	}
	lines := strings.Split(b, "\n")
	for i, line := range lines {
		hasNL := i < len(lines)-1
		if p.lineComment == "" && hasNL {
			// Fast path for complete lines with no comment.
			fmt.Printf("%s\n", line)
			p.pos = 0
			continue
		}

		for _, r := range line {
			if r == '\t' {
				p.pos = (p.pos + 8) &^ 7
			} else {
				p.pos++
			}
		}
		fmt.Printf("%s", line)
		if hasNL {
			if p.lineComment != "" {
				space := 50 - p.pos
				if space < 1 {
					space = 1
				}
				fmt.Printf("%*s// %s", space, "", p.lineComment)
				p.lineComment = ""
			}
			fmt.Printf("\n")
			p.pos = 0
		}
	}
}

func (p *typePrinter) setLineComment(f string, args ...interface{}) {
	if p.lineComment != "" {
		panic("multiple line comments")
	}
	p.lineComment = fmt.Sprintf(f, args...)
}

func (p *typePrinter) stripPkg(name string) string {
	if p.pkg != "" && strings.HasPrefix(name, p.pkg) {
		return name[len(p.pkg):]
	}
	return name
}

func (p *typePrinter) printType(typ dwarf.Type) {
	if p.offset == nil {
		p.offset = []int64{0}
	}

	if p.nameOk > 0 && typ.Common().Name != "" {
		p.fmt("%s", p.stripPkg(typ.Common().Name))
		p.offset[len(p.offset)-1] += typ.Size()
		return
	}

	switch typ := typ.(type) {
	case *dwarf.ArrayType:
		if typ.Count < 0 {
			p.fmt("[incomplete]")
		} else {
			p.fmt("[%d]", typ.Count)
		}
		if typ.StrideBitSize > 0 {
			p.fmt("/* %d bit element */", typ.StrideBitSize)
		}
		origOffset := p.offset
		p.offset = append(p.offset, typ.Type.Size(), 0)
		p.printType(typ.Type)
		p.offset = origOffset

	case *dwarf.StructType:
		if typ.StructName != "" && (p.nameOk > 0 || isBuiltinName(typ.StructName)) {
			p.fmt("%s", p.stripPkg(typ.StructName))
			break
		}

		if strings.HasPrefix(typ.StructName, "[]") {
			p.fmt("[]")
			elem := typ.Field[0].Type
			origOffset := p.offset
			p.offset = append(p.offset, elem.Size(), 0)
			p.printType(elem)
			p.offset = origOffset
			break
		}

		if typ.StructName == "runtime.eface" {
			p.fmt("interface{}")
			break
		} else if typ.StructName == "runtime.iface" {
			p.fmt("interface{ ... }")
			break
		}

		isUnion := typ.Kind == "union"
		p.fmt("%s {", typ.Kind)
		if typ.Incomplete {
			p.fmt(" incomplete ")
		}
		p.depth++
		startOffset := p.offset[len(p.offset)-1]
		var prevEnd int64
		for i, f := range typ.Field {
			indent := "\n" + strings.Repeat("\t", p.depth)
			p.fmt(indent)
			// TODO: Bit offsets?
			if !isUnion {
				offset := startOffset + f.ByteOffset
				if i > 0 && prevEnd < offset {
					p.fmt("// %d byte gap", offset-prevEnd)
					p.fmt(indent)
				}
				p.offset[len(p.offset)-1] = offset
				p.setLineComment("offset %s", p.strOffset())
				if f.Type.Size() < 0 {
					// Who knows. Give up.
					// TODO: This happens for funcs.
					prevEnd = (1 << 31) - 1
				} else {
					prevEnd = offset + f.Type.Size()
				}
			}
			p.fmt("%s ", f.Name)
			p.printType(f.Type)
			if f.BitSize != 0 {
				p.fmt(" : %d", f.BitSize)
			}
		}
		p.offset[len(p.offset)-1] = startOffset
		p.depth--
		if len(typ.Field) == 0 {
			p.fmt("}")
		} else {
			p.fmt("\n%s}", strings.Repeat("\t", p.depth))
		}

	case *dwarf.EnumType:
		p.fmt("enum") // TODO

	case *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.FloatType, *dwarf.IntType, *dwarf.UcharType, *dwarf.UintType:
		// Basic types.
		p.fmt("%s", typ.String())

	case *dwarf.PtrType:
		origOffset := p.offset
		p.offset = []int64{0}
		p.nameOk++
		p.fmt("*")
		p.printType(typ.Type)
		p.nameOk--
		p.offset = origOffset

	case *dwarf.FuncType:
		// TODO: Expand ourselves so we can clean up argument
		// types, etc.
		p.fmt(typ.String())

	case *dwarf.QualType:
		p.fmt("/* %s */ ", typ.Qual)
		p.printType(typ.Type)

	case *dwarf.TypedefType:
		n := typ.Common().Name
		if isBuiltinName(n) {
			// TODO: Make Go-ifying optional.
			//
			// TODO: Expand map types ourselves if
			// possible so we can clean up the type names.
			p.fmt("%s", n)
			return
		}

		real := typ.Type
		for {
			if real2, ok := real.(*dwarf.TypedefType); ok {
				real = real2.Type
			} else {
				break
			}
		}
		if str, ok := real.(*dwarf.StructType); ok {
			switch str.StructName {
			case "runtime.iface", "runtime.eface":
				// Named interface type.
				p.fmt(p.stripPkg(n))
				return
			}
		}

		// TODO: If it's "type x map..." or similar, we never
		// see the "map[...]" style name and only see that x's
		// underlying type is a pointer to a struct named
		// "hash<...>".

		p.fmt("/* %s */ ", p.stripPkg(n))
		p.printType(real)

	case *dwarf.UnspecifiedType:
		p.fmt("unspecified")

	case *dwarf.VoidType:
		p.fmt("void")
	}

	p.offset[len(p.offset)-1] += typ.Size()
}

func (p *typePrinter) strOffset() string {
	buf := fmt.Sprintf("%d", p.offset[0])
	for i, idx := 1, 'i'; i < len(p.offset); i, idx = i+2, idx+1 {
		buf += fmt.Sprintf(" + %d*%c", p.offset[i], idx)
		if p.offset[i+1] != 0 {
			buf += fmt.Sprintf(" + %d", p.offset[i+1])
		}
	}
	return buf
}
<commit_msg>ptype: print struct sizes<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Command ptype prints Go types from a binary using DWARF info.
package main

import (
	"debug/dwarf"
	"debug/elf"
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"
	"unicode/utf8"
)

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

	// Parse type regexp args.
	regexps := []*regexp.Regexp{}
	for _, tre := range flag.Args()[1:] {
		re, err := regexp.Compile("^" + tre)
		if err != nil {
			fmt.Fprintf(os.Stderr, "bad regexp %q: %s", tre, err)
			os.Exit(1)
		}
		regexps = append(regexps, re)
	}
	if len(regexps) == 0 {
		regexps = append(regexps, regexp.MustCompile(".*"))
	}

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

	// Find all of the named types.
	r := d.Reader()
	for {
		ent, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if ent == nil {
			break
		}

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

		name, ok := ent.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}

		// Do we want this type?
		matched := false
		for _, re := range regexps {
			if re.MatchString(name) {
				matched = true
				break
			}
		}
		if isBuiltinName(name) || !matched {
			r.SkipChildren()
			continue
		}

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

		typ, err := d.Type(base)
		if err != nil {
			log.Fatal(err)
		}

		pkg := ""
		if i := strings.LastIndex(name, "."); i >= 0 {
			pkg = name[:i+1]
		}

		p := &typePrinter{pkg: pkg}
		p.fmt("type %s ", name)
		p.printType(typ)
		p.fmt("\n\n")

		r.SkipChildren()
	}
}

func isBuiltinName(typeName string) bool {
	switch typeName {
	case "string":
		return true
	}
	return strings.HasPrefix(typeName, "map[") ||
		strings.HasPrefix(typeName, "func(") ||
		strings.HasPrefix(typeName, "chan ") ||
		strings.HasPrefix(typeName, "chan<- ") ||
		strings.HasPrefix(typeName, "<-chan ")
}

type typePrinter struct {
	offset []int64
	depth  int
	nameOk int
	pkg    string

	// pos is the current character position on this line.
	pos int

	// lineComment is a comment to print at the end of this line.
	lineComment string
}

func (p *typePrinter) fmt(f string, args ...interface{}) {
	b := fmt.Sprintf(f, args...)
	if strings.IndexAny(b, "\n\t") < 0 {
		fmt.Printf("%s", b)
		p.pos += utf8.RuneCountInString(b)
		return
	}
	lines := strings.Split(b, "\n")
	for i, line := range lines {
		hasNL := i < len(lines)-1
		if p.lineComment == "" && hasNL {
			// Fast path for complete lines with no comment.
			fmt.Printf("%s\n", line)
			p.pos = 0
			continue
		}

		for _, r := range line {
			if r == '\t' {
				p.pos = (p.pos + 8) &^ 7
			} else {
				p.pos++
			}
		}
		fmt.Printf("%s", line)
		if hasNL {
			if p.lineComment != "" {
				space := 50 - p.pos
				if space < 1 {
					space = 1
				}
				fmt.Printf("%*s// %s", space, "", p.lineComment)
				p.lineComment = ""
			}
			fmt.Printf("\n")
			p.pos = 0
		}
	}
}

func (p *typePrinter) setLineComment(f string, args ...interface{}) {
	if p.lineComment != "" {
		panic("multiple line comments")
	}
	p.lineComment = fmt.Sprintf(f, args...)
}

func (p *typePrinter) stripPkg(name string) string {
	if p.pkg != "" && strings.HasPrefix(name, p.pkg) {
		return name[len(p.pkg):]
	}
	return name
}

func (p *typePrinter) printType(typ dwarf.Type) {
	if p.offset == nil {
		p.offset = []int64{0}
	}

	if p.nameOk > 0 && typ.Common().Name != "" {
		p.fmt("%s", p.stripPkg(typ.Common().Name))
		p.offset[len(p.offset)-1] += typ.Size()
		return
	}

	switch typ := typ.(type) {
	case *dwarf.ArrayType:
		if typ.Count < 0 {
			p.fmt("[incomplete]")
		} else {
			p.fmt("[%d]", typ.Count)
		}
		if typ.StrideBitSize > 0 {
			p.fmt("/* %d bit element */", typ.StrideBitSize)
		}
		origOffset := p.offset
		p.offset = append(p.offset, typ.Type.Size(), 0)
		p.printType(typ.Type)
		p.offset = origOffset

	case *dwarf.StructType:
		if typ.StructName != "" && (p.nameOk > 0 || isBuiltinName(typ.StructName)) {
			p.fmt("%s", p.stripPkg(typ.StructName))
			break
		}

		if strings.HasPrefix(typ.StructName, "[]") {
			p.fmt("[]")
			elem := typ.Field[0].Type
			origOffset := p.offset
			p.offset = append(p.offset, elem.Size(), 0)
			p.printType(elem)
			p.offset = origOffset
			break
		}

		if typ.StructName == "runtime.eface" {
			p.fmt("interface{}")
			break
		} else if typ.StructName == "runtime.iface" {
			p.fmt("interface{ ... }")
			break
		}

		isUnion := typ.Kind == "union"
		p.fmt("%s {", typ.Kind)
		if typ.Incomplete {
			p.fmt(" incomplete }")
			break
		}
		p.depth++
		indent := "\n" + strings.Repeat("\t", p.depth)
		p.fmt("%s// %d byte %s", indent, typ.Size(), typ.Kind)
		startOffset := p.offset[len(p.offset)-1]
		var prevEnd int64
		for i, f := range typ.Field {
			p.fmt(indent)
			// TODO: Bit offsets?
			if !isUnion {
				offset := startOffset + f.ByteOffset
				if i > 0 && prevEnd < offset {
					p.fmt("// %d byte gap", offset-prevEnd)
					p.fmt(indent)
				}
				p.offset[len(p.offset)-1] = offset
				p.setLineComment("offset %s", p.strOffset())
				if f.Type.Size() < 0 {
					// Who knows. Give up.
					// TODO: This happens for funcs.
					prevEnd = (1 << 31) - 1
				} else {
					prevEnd = offset + f.Type.Size()
				}
			}
			p.fmt("%s ", f.Name)
			p.printType(f.Type)
			if f.BitSize != 0 {
				p.fmt(" : %d", f.BitSize)
			}
		}
		p.offset[len(p.offset)-1] = startOffset
		p.depth--
		p.fmt("\n%s}", strings.Repeat("\t", p.depth))

	case *dwarf.EnumType:
		p.fmt("enum") // TODO

	case *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.FloatType, *dwarf.IntType, *dwarf.UcharType, *dwarf.UintType:
		// Basic types.
		p.fmt("%s", typ.String())

	case *dwarf.PtrType:
		origOffset := p.offset
		p.offset = []int64{0}
		p.nameOk++
		p.fmt("*")
		p.printType(typ.Type)
		p.nameOk--
		p.offset = origOffset

	case *dwarf.FuncType:
		// TODO: Expand ourselves so we can clean up argument
		// types, etc.
		p.fmt(typ.String())

	case *dwarf.QualType:
		p.fmt("/* %s */ ", typ.Qual)
		p.printType(typ.Type)

	case *dwarf.TypedefType:
		n := typ.Common().Name
		if isBuiltinName(n) {
			// TODO: Make Go-ifying optional.
			//
			// TODO: Expand map types ourselves if
			// possible so we can clean up the type names.
			p.fmt("%s", n)
			return
		}

		real := typ.Type
		for {
			if real2, ok := real.(*dwarf.TypedefType); ok {
				real = real2.Type
			} else {
				break
			}
		}
		if str, ok := real.(*dwarf.StructType); ok {
			switch str.StructName {
			case "runtime.iface", "runtime.eface":
				// Named interface type.
				p.fmt(p.stripPkg(n))
				return
			}
		}

		// TODO: If it's "type x map..." or similar, we never
		// see the "map[...]" style name and only see that x's
		// underlying type is a pointer to a struct named
		// "hash<...>".

		p.fmt("/* %s */ ", p.stripPkg(n))
		p.printType(real)

	case *dwarf.UnspecifiedType:
		p.fmt("unspecified")

	case *dwarf.VoidType:
		p.fmt("void")
	}

	p.offset[len(p.offset)-1] += typ.Size()
}

func (p *typePrinter) strOffset() string {
	buf := fmt.Sprintf("%d", p.offset[0])
	for i, idx := 1, 'i'; i < len(p.offset); i, idx = i+2, idx+1 {
		buf += fmt.Sprintf(" + %d*%c", p.offset[i], idx)
		if p.offset[i+1] != 0 {
			buf += fmt.Sprintf(" + %d", p.offset[i+1])
		}
	}
	return buf
}
<|endoftext|>