<commit_before>package main

import (
	"bytes"
	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestBuild(t *testing.T) {
	dst := filepath.Join("_test", "tmp", "bin")
	os.Remove(dst)

	Convey("Should build the source to the target location", t, func() {
		src := filepath.Join("_test", "fixtures", "exit15.go")
		err := Build(dst, src)
		So(err, ShouldBeNil)
		_, err = os.Stat(dst)
		So(err, ShouldBeNil)
	})

	Convey("Should only allow .go filenames for source", t, func() {
		src := filepath.Join("_test", "fixtures", "exit15")
		err := Build(dst, src)
		So(err, ShouldNotBeNil)
		So(err.Error(), ShouldContainSubstring, "go")
		So(err.Error(), ShouldContainSubstring, "ext")
	})

	os.Remove(dst)
}

// This is hard to test, due to GetTempPaths using filepath.Abs()
// So for now we're just checking the format.
func TestGetTempPaths(t *testing.T) {
	Convey("Should return the bin destination", t, func() {
		b, _, err := GetTempPaths("foo", "bar")
		So(err, ShouldBeNil)
		So(b, ShouldStartWith, "bar")
	})

	Convey("Should return the source destination", t, func() {
		_, s, err := GetTempPaths("foo", "bar")
		So(err, ShouldBeNil)
		So(s, ShouldStartWith, "bar")
		So(s, ShouldEndWith, ".go")
	})
}

func TestRunExec(t *testing.T) {
	Convey("Should return exit status", t, func() {
		e := filepath.Join("_test", "fixtures", "exit15.bash")
		exit, err := RunExec(e, []string{},
			nil, ioutil.Discard, ioutil.Discard)
		So(err, ShouldBeNil)
		So(exit, ShouldEqual, 15)
	})

	Convey("Should pass args to the bin", t, func() {
		e := filepath.Join("_test", "fixtures", "exitarg.bash")
		exit, err := RunExec(e, []string{"25"},
			nil, ioutil.Discard, ioutil.Discard)
		So(err, ShouldBeNil)
		So(exit, ShouldEqual, 25)
	})

	Convey("Should pipe stdout and stderr", t, func() {
		e := filepath.Join("_test", "fixtures", "exit15.bash")
		var stdo bytes.Buffer
		var stde bytes.Buffer
		RunExec(e, []string{}, nil, &stdo, &stde)
		So(stdo.String(), ShouldEqual, "STDOUT: Exiting 15")
		So(stde.String(), ShouldEqual, "STDERR: Exiting 15")
	})

	Convey("Should pipe stdin", t, func() {
		e := filepath.Join("_test", "fixtures", "echoinput.bash")
		var i bytes.Buffer
		var o bytes.Buffer
		fmt.Fprint(&i, "Writing to STDIN")
		RunExec(e, []string{}, &i, &o, ioutil.Discard)
		So(o.String(), ShouldEqual, "Echoing Writing to STDIN")
	})
}

func TestRunScriptWithOpts(t *testing.T) {
	Convey("Should copy the source to absolute hashed", t, nil)
}
<commit_msg>Added RunScriptWithOptions test<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestBuild(t *testing.T) {
	dst := filepath.Join("_test", "tmp", "bin")
	os.Remove(dst)

	Convey("Should build the source to the target location", t, func() {
		src := filepath.Join("_test", "fixtures", "exit15.go")
		err := Build(dst, src)
		So(err, ShouldBeNil)
		_, err = os.Stat(dst)
		So(err, ShouldBeNil)
	})

	Convey("Should only allow .go filenames for source", t, func() {
		src := filepath.Join("_test", "fixtures", "exit15")
		err := Build(dst, src)
		So(err, ShouldNotBeNil)
		So(err.Error(), ShouldContainSubstring, "go")
		So(err.Error(), ShouldContainSubstring, "ext")
	})

	os.Remove(dst)
}

// This is hard to test, due to GetTempPaths using filepath.Abs()
// So for now we're just checking the format.
func TestGetTempPaths(t *testing.T) {
	Convey("Should return the bin destination", t, func() {
		b, _, err := GetTempPaths("foo", "bar")
		So(err, ShouldBeNil)
		So(b, ShouldStartWith, "bar")
	})

	Convey("Should return the source destination", t, func() {
		_, s, err := GetTempPaths("foo", "bar")
		So(err, ShouldBeNil)
		So(s, ShouldStartWith, "bar")
		So(s, ShouldEndWith, ".go")
	})
}

func TestRunExec(t *testing.T) {
	Convey("Should return exit status", t, func() {
		e := filepath.Join("_test", "fixtures", "exit15.bash")
		exit, err := RunExec(e, []string{},
			nil, ioutil.Discard, ioutil.Discard)
		So(err, ShouldBeNil)
		So(exit, ShouldEqual, 15)
	})

	Convey("Should pass args to the bin", t, func() {
		e := filepath.Join("_test", "fixtures", "exitarg.bash")
		exit, err := RunExec(e, []string{"25"},
			nil, ioutil.Discard, ioutil.Discard)
		So(err, ShouldBeNil)
		So(exit, ShouldEqual, 25)
	})

	Convey("Should pipe stdout and stderr", t, func() {
		e := filepath.Join("_test", "fixtures", "exit15.bash")
		var stdo bytes.Buffer
		var stde bytes.Buffer
		RunExec(e, []string{}, nil, &stdo, &stde)
		So(stdo.String(), ShouldEqual, "STDOUT: Exiting 15")
		So(stde.String(), ShouldEqual, "STDERR: Exiting 15")
	})

	Convey("Should pipe stdin", t, func() {
		e := filepath.Join("_test", "fixtures", "echoinput.bash")
		var i bytes.Buffer
		var o bytes.Buffer
		fmt.Fprint(&i, "Writing to STDIN")
		RunExec(e, []string{}, &i, &o, ioutil.Discard)
		So(o.String(), ShouldEqual, "Echoing Writing to STDIN")
	})
}

func TestRunScriptWithOpts(t *testing.T) {
	dst := filepath.Join("_test", "tmp")

	Convey("Should run a .go file", t, func() {
		e := filepath.Join("_test", "fixtures", "exit15.go")
		opts := ScriptOptions{dst, nil, ioutil.Discard, ioutil.Discard}
		exit, err := RunScriptWithOpts(e, []string{}, opts)
		So(err, ShouldBeNil)
		So(exit, ShouldEqual, 15)
	})

	Convey("Should run a no-ext go file", t, func() {
		e := filepath.Join("_test", "fixtures", "exit15")
		opts := ScriptOptions{dst, nil, ioutil.Discard, ioutil.Discard}
		exit, err := RunScriptWithOpts(e, []string{}, opts)
		So(err, ShouldBeNil)
		So(exit, ShouldEqual, 15)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/db"
	"github.com/MG-RAST/Shock/shock-server/node"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	dirExp, _ = regexp.Compile("[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{32}$")
)

func reload(source string) (err error) {
	fmt.Println("source:", conf.RELOAD)
	if strings.HasPrefix(conf.RELOAD, "http://") {
		fmt.Println("source-type: url")
		if err = reloadDB(); err != nil {
			return err
		}
		return reloadFromUrl(source)
	} else {
		fmt.Println("source-type: dir")
		if source == conf.Conf["data-path"] {
			fmt.Println("source dir is the same as conf data dir: db reload only.")
		} else {
			return errors.New("source dir is not the same as conf data dir: copy not implemented yet")
		}
		if err = reloadDB(); err != nil {
			return err
		}
		return filepath.Walk(source, reloadFromDir)
	}
	return
}

func reloadDB() (err error) {
	fmt.Printf("dropping & re-initializing database...")
	if err = db.Drop(); err != nil {
		return err
	}
	db.Initialize()
	fmt.Printf("done\n")
	return
}

func reloadFromUrl(url string) error {
	return errors.New("reload from url not implemented yet")
}

func reloadFromDir(path string, info os.FileInfo, err error) error {
	if dirExp.MatchString(path) {
		id := filepath.Base(path)
		fmt.Printf(id + "...")
		if err := node.ReloadFromDisk(path); err != nil {
			return err
		}
		fmt.Printf("done\n")
	}
	return nil
}
<commit_msg>fix reload regex for uuidv4<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/db"
	"github.com/MG-RAST/Shock/shock-server/node"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	dirExp, _ = regexp.Compile("(?i)([a-f0-9]{2}/){3}[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$")
)

func reload(source string) (err error) {
	fmt.Println("source:", conf.RELOAD)
	if strings.HasPrefix(conf.RELOAD, "http://") {
		fmt.Println("source-type: url")
		if err = reloadDB(); err != nil {
			return err
		}
		return reloadFromUrl(source)
	} else {
		fmt.Println("source-type: dir")
		if source == conf.Conf["data-path"] {
			fmt.Println("source dir is the same as conf data dir: db reload only.")
		} else {
			return errors.New("source dir is not the same as conf data dir: copy not implemented yet")
		}
		if err = reloadDB(); err != nil {
			return err
		}
		return filepath.Walk(source, reloadFromDir)
	}
	return
}

func reloadDB() (err error) {
	fmt.Printf("dropping & re-initializing database...")
	if err = db.Drop(); err != nil {
		return err
	}
	db.Initialize()
	fmt.Printf("done\n")
	return
}

func reloadFromUrl(url string) error {
	return errors.New("reload from url not implemented yet")
}

func reloadFromDir(path string, info os.FileInfo, err error) error {
	if dirExp.MatchString(path) {
		id := filepath.Base(path)
		fmt.Printf(id + "...")
		if err := node.ReloadFromDisk(path); err != nil {
			return err
		}
		fmt.Printf("done\n")
	}
	return nil
}
<|endoftext|>


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

package gcsproxy

import (
	"fmt"
	"io"

	"github.com/googlecloudplatform/gcsfuse/lease"
	"github.com/googlecloudplatform/gcsfuse/mutable"
	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
)

// Safe for concurrent access.
type ObjectSyncer interface {
	// Given an object record and content that was originally derived from that
	// object's contents (and potentially modified):
	//
	// *   If the content has not been modified, return a nil read lease and a
	//     nil new object.
	//
	// *   Otherwise, write out a new generation in the bucket (failing with
	//     *gcs.PreconditionError if the source generation is no longer current)
	//     and return a read lease for that object's contents.
	//
	// In the second case, the mutable.Content is destroyed. Otherwise, including
	// when this function fails, it is guaranteed to still be valid.
	SyncObject(
		ctx context.Context,
		srcObject *gcs.Object,
		content mutable.Content) (rl lease.ReadLease, o *gcs.Object, err error)
}

// Create an object syncer that syncs into the supplied bucket.
//
// When the source object has been changed only by appending, and the source
// object's size is at least appendThreshold, we will "append" to it by writing
// out a temporary blob and composing it with the source object.
//
// Temporary blobs have names beginning with tmpObjectPrefix. We make an effort
// to delete them, but if we are interrupted for some reason we may not be able
// to do so. Therefore the user should arrange for garbage collection.
func NewObjectSyncer(
	appendThreshold int64,
	tmpObjectPrefix string,
	bucket gcs.Bucket) (os ObjectSyncer) {
	// Create the object creators.
	fullCreator := &fullObjectCreator{
		bucket: bucket,
	}

	appendCreator := newAppendObjectCreator(
		tmpObjectPrefix,
		bucket)

	// And the object syncer.
	os = newObjectSyncer(appendThreshold, fullCreator, appendCreator)

	return
}

////////////////////////////////////////////////////////////////////////
// fullObjectCreator
////////////////////////////////////////////////////////////////////////

type fullObjectCreator struct {
	bucket gcs.Bucket
}

func (oc *fullObjectCreator) Create(
	ctx context.Context,
	srcObject *gcs.Object,
	r io.Reader) (o *gcs.Object, err error) {
	req := &gcs.CreateObjectRequest{
		Name: srcObject.Name,
		GenerationPrecondition: &srcObject.Generation,
		Contents:               r,
	}

	o, err = oc.bucket.CreateObject(ctx, req)
	if err != nil {
		err = fmt.Errorf("CreateObject: %v", err)
		return
	}

	return
}

////////////////////////////////////////////////////////////////////////
// objectSyncer
////////////////////////////////////////////////////////////////////////

// An implementation detail of objectSyncer. See notes on
// newObjectSyncer.
type objectCreator interface {
	Create(
		ctx context.Context,
		srcObject *gcs.Object,
		r io.Reader) (o *gcs.Object, err error)
}

// Create an object syncer that stats the mutable content to see if it's dirty
// before calling through to one of two object creators if the content is dirty:
//
// *   fullCreator accepts the source object and the full contents with which it
//     should be overwritten.
//
// *   appendCreator accepts the source object and the contents that should be
//     "appended" to it.
//
// appendThreshold controls the source object length at which we consider it
// worthwhile to make the append optimization. It should be set to a value on
// the order of the bandwidth to GCS times three times the round trip latency
// to GCS (for a small create, a compose, and a delete).
func newObjectSyncer(
	appendThreshold int64,
	fullCreator objectCreator,
	appendCreator objectCreator) (os ObjectSyncer) {
	os = &objectSyncer{
		appendThreshold: appendThreshold,
		fullCreator:     fullCreator,
		appendCreator:   appendCreator,
	}

	return
}

type objectSyncer struct {
	appendThreshold int64
	fullCreator     objectCreator
	appendCreator   objectCreator
}

func (os *objectSyncer) SyncObject(
	ctx context.Context,
	srcObject *gcs.Object,
	content mutable.Content) (rl lease.ReadLease, o *gcs.Object, err error) {
	// Stat the content.
	sr, err := content.Stat(ctx)
	if err != nil {
		err = fmt.Errorf("Stat: %v", err)
		return
	}

	// Make sure the dirty threshold makes sense.
	srcSize := int64(srcObject.Size)
	if sr.DirtyThreshold > srcSize {
		err = fmt.Errorf(
			"Stat returned weird DirtyThreshold field: %d vs. %d",
			sr.DirtyThreshold,
			srcObject.Size)

		return
	}

	// If the content hasn't been dirtied (i.e. it is the same size as the source
	// object, and no bytes within the source object have been dirtied), we're
	// done.
	if sr.Size == srcSize && sr.DirtyThreshold == srcSize {
		return
	}

	// Otherwise, we need to create a new generation. If the source object is
	// long enough, hasn't been dirtied, and has a low enough component count,
	// then we can make the optimization of not rewriting its contents.
	if srcSize >= os.appendThreshold &&
		sr.DirtyThreshold == srcSize &&
		srcObject.ComponentCount < gcs.MaxComponentCount {
		o, err = os.appendCreator.Create(
			ctx,
			srcObject,
			&mutableContentReader{
				Ctx:     ctx,
				Content: content,
				Offset:  srcSize,
			})
	} else {
		o, err = os.fullCreator.Create(
			ctx,
			srcObject,
			&mutableContentReader{
				Ctx:     ctx,
				Content: content,
			})
	}

	// Deal with errors.
	if err != nil {
		// Special case: don't mess with precondition errors.
		if _, ok := err.(*gcs.PreconditionError); ok {
			return
		}

		err = fmt.Errorf("Create: %v", err)
		return
	}

	// Yank out the contents.
	rl = content.Release().Downgrade()

	return
}

////////////////////////////////////////////////////////////////////////
// mutableContentReader
////////////////////////////////////////////////////////////////////////

// An io.Reader that wraps a mutable.Content object, reading starting from a
// base offset.
type mutableContentReader struct {
	Ctx     context.Context
	Content mutable.Content
	Offset  int64
}

func (mcr *mutableContentReader) Read(p []byte) (n int, err error) {
	n, err = mcr.Content.ReadAt(mcr.Ctx, p, mcr.Offset)
	mcr.Offset += int64(n)
	return
}
<commit_msg>Don't mangle precondition errors.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gcsproxy

import (
	"fmt"
	"io"

	"github.com/googlecloudplatform/gcsfuse/lease"
	"github.com/googlecloudplatform/gcsfuse/mutable"
	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
)

// Safe for concurrent access.
type ObjectSyncer interface {
	// Given an object record and content that was originally derived from that
	// object's contents (and potentially modified):
	//
	// *   If the content has not been modified, return a nil read lease and a
	//     nil new object.
	//
	// *   Otherwise, write out a new generation in the bucket (failing with
	//     *gcs.PreconditionError if the source generation is no longer current)
	//     and return a read lease for that object's contents.
	//
	// In the second case, the mutable.Content is destroyed. Otherwise, including
	// when this function fails, it is guaranteed to still be valid.
	SyncObject(
		ctx context.Context,
		srcObject *gcs.Object,
		content mutable.Content) (rl lease.ReadLease, o *gcs.Object, err error)
}

// Create an object syncer that syncs into the supplied bucket.
//
// When the source object has been changed only by appending, and the source
// object's size is at least appendThreshold, we will "append" to it by writing
// out a temporary blob and composing it with the source object.
//
// Temporary blobs have names beginning with tmpObjectPrefix. We make an effort
// to delete them, but if we are interrupted for some reason we may not be able
// to do so. Therefore the user should arrange for garbage collection.
func NewObjectSyncer(
	appendThreshold int64,
	tmpObjectPrefix string,
	bucket gcs.Bucket) (os ObjectSyncer) {
	// Create the object creators.
	fullCreator := &fullObjectCreator{
		bucket: bucket,
	}

	appendCreator := newAppendObjectCreator(
		tmpObjectPrefix,
		bucket)

	// And the object syncer.
	os = newObjectSyncer(appendThreshold, fullCreator, appendCreator)

	return
}

////////////////////////////////////////////////////////////////////////
// fullObjectCreator
////////////////////////////////////////////////////////////////////////

type fullObjectCreator struct {
	bucket gcs.Bucket
}

func (oc *fullObjectCreator) Create(
	ctx context.Context,
	srcObject *gcs.Object,
	r io.Reader) (o *gcs.Object, err error) {
	req := &gcs.CreateObjectRequest{
		Name: srcObject.Name,
		GenerationPrecondition: &srcObject.Generation,
		Contents:               r,
	}

	o, err = oc.bucket.CreateObject(ctx, req)
	if err != nil {
		// Don't mangle precondition errors.
		if _, ok := err.(*gcs.PreconditionError); ok {
			return
		}

		err = fmt.Errorf("CreateObject: %v", err)
		return
	}

	return
}

////////////////////////////////////////////////////////////////////////
// objectSyncer
////////////////////////////////////////////////////////////////////////

// An implementation detail of objectSyncer. See notes on
// newObjectSyncer.
type objectCreator interface {
	Create(
		ctx context.Context,
		srcObject *gcs.Object,
		r io.Reader) (o *gcs.Object, err error)
}

// Create an object syncer that stats the mutable content to see if it's dirty
// before calling through to one of two object creators if the content is dirty:
//
// *   fullCreator accepts the source object and the full contents with which it
//     should be overwritten.
//
// *   appendCreator accepts the source object and the contents that should be
//     "appended" to it.
//
// appendThreshold controls the source object length at which we consider it
// worthwhile to make the append optimization. It should be set to a value on
// the order of the bandwidth to GCS times three times the round trip latency
// to GCS (for a small create, a compose, and a delete).
func newObjectSyncer(
	appendThreshold int64,
	fullCreator objectCreator,
	appendCreator objectCreator) (os ObjectSyncer) {
	os = &objectSyncer{
		appendThreshold: appendThreshold,
		fullCreator:     fullCreator,
		appendCreator:   appendCreator,
	}

	return
}

type objectSyncer struct {
	appendThreshold int64
	fullCreator     objectCreator
	appendCreator   objectCreator
}

func (os *objectSyncer) SyncObject(
	ctx context.Context,
	srcObject *gcs.Object,
	content mutable.Content) (rl lease.ReadLease, o *gcs.Object, err error) {
	// Stat the content.
	sr, err := content.Stat(ctx)
	if err != nil {
		err = fmt.Errorf("Stat: %v", err)
		return
	}

	// Make sure the dirty threshold makes sense.
	srcSize := int64(srcObject.Size)
	if sr.DirtyThreshold > srcSize {
		err = fmt.Errorf(
			"Stat returned weird DirtyThreshold field: %d vs. %d",
			sr.DirtyThreshold,
			srcObject.Size)

		return
	}

	// If the content hasn't been dirtied (i.e. it is the same size as the source
	// object, and no bytes within the source object have been dirtied), we're
	// done.
	if sr.Size == srcSize && sr.DirtyThreshold == srcSize {
		return
	}

	// Otherwise, we need to create a new generation. If the source object is
	// long enough, hasn't been dirtied, and has a low enough component count,
	// then we can make the optimization of not rewriting its contents.
	if srcSize >= os.appendThreshold &&
		sr.DirtyThreshold == srcSize &&
		srcObject.ComponentCount < gcs.MaxComponentCount {
		o, err = os.appendCreator.Create(
			ctx,
			srcObject,
			&mutableContentReader{
				Ctx:     ctx,
				Content: content,
				Offset:  srcSize,
			})
	} else {
		o, err = os.fullCreator.Create(
			ctx,
			srcObject,
			&mutableContentReader{
				Ctx:     ctx,
				Content: content,
			})
	}

	// Deal with errors.
	if err != nil {
		// Special case: don't mess with precondition errors.
		if _, ok := err.(*gcs.PreconditionError); ok {
			return
		}

		err = fmt.Errorf("Create: %v", err)
		return
	}

	// Yank out the contents.
	rl = content.Release().Downgrade()

	return
}

////////////////////////////////////////////////////////////////////////
// mutableContentReader
////////////////////////////////////////////////////////////////////////

// An io.Reader that wraps a mutable.Content object, reading starting from a
// base offset.
type mutableContentReader struct {
	Ctx     context.Context
	Content mutable.Content
	Offset  int64
}

func (mcr *mutableContentReader) Read(p []byte) (n int, err error) {
	n, err = mcr.Content.ReadAt(mcr.Ctx, p, mcr.Offset)
	mcr.Offset += int64(n)
	return
}
<|endoftext|>


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

package spath

import (
	"bytes"
	"fmt"
	"hash"

	//log "github.com/inconshreveable/log15"

	"github.com/scionproto/scion/go/lib/common"
	"github.com/scionproto/scion/go/lib/util"
)

type HopField struct {
	data        common.RawBytes
	Xover       bool
	VerifyOnly  bool
	ForwardOnly bool
	Recurse     bool
	ExpTime     uint8
	Ingress     common.IFIDType
	Egress      common.IFIDType
	Mac         common.RawBytes
	length      int
}

const (
	HopFieldVerifyFlags = 0x4 // Forward-only
	HopFieldLength      = common.LineLen
	DefaultHopFExpiry   = 63
	MacLen              = 3
	ErrorHopFTooShort   = "HopF too short"
	ErrorHopFBadMac     = "Bad HopF MAC"
)

func NewHopField(b common.RawBytes, in common.IFIDType, out common.IFIDType) *HopField {
	h := &HopField{}
	h.data = b
	h.ExpTime = DefaultHopFExpiry
	h.Ingress = in
	h.Egress = out
	h.Write()
	return h
}

func HopFFromRaw(b []byte) (*HopField, error) {
	if len(b) < HopFieldLength {
		return nil, common.NewBasicError(ErrorHopFTooShort, nil,
			"min", HopFieldLength, "actual", len(b))
	}
	h := &HopField{}
	h.data = b[:HopFieldLength]
	flags := h.data[0]
	h.Xover = flags&0x1 != 0
	h.VerifyOnly = flags&0x2 != 0
	h.ForwardOnly = flags&0x4 != 0
	h.Recurse = flags&0x8 != 0
	offset := 1
	h.ExpTime = h.data[offset]
	offset += 1
	// Interface IDs are 12b each, encoded into 3B
	h.Ingress = common.IFIDType(int(h.data[offset])<<4 | int(h.data[offset+1])>>4)
	h.Egress = common.IFIDType((int(h.data[offset+1])&0xF)<<8 | int(h.data[offset+2]))
	offset += 3
	h.Mac = h.data[offset:]
	h.length = common.LineLen
	return h, nil
}

// Len returns the length (in bytes)
func (h *HopField) Len() int {
	return h.length
}

func (h *HopField) Write() {
	var flags uint8
	if h.Xover {
		flags |= 0x1
	}
	if h.VerifyOnly {
		flags |= 0x2
	}
	if h.ForwardOnly {
		flags |= 0x4
	}
	if h.Recurse {
		flags |= 0x8
	}
	h.data[0] = flags
	h.data[1] = h.ExpTime
	// Interface IDs are 12b each, encoded into 3B
	h.data[2] = byte(h.Ingress >> 4)
	h.data[3] = byte((h.Ingress&0x0F)<<4 | h.Egress>>4)
	h.data[4] = byte(h.Egress & 0xFF)
	copy(h.data[5:], h.Mac)
}

func (h *HopField) String() string {
	return fmt.Sprintf(
		"Ingress: %v Egress: %v ExpTime: %v Xover: %v VerifyOnly: %v ForwardOnly: %v Mac: %v",
		h.Ingress, h.Egress, h.ExpTime, h.Xover, h.VerifyOnly, h.ForwardOnly, h.Mac)
}

func (h *HopField) Verify(mac hash.Hash, tsInt uint32, prev common.RawBytes) error {
	if mac, err := h.CalcMac(mac, tsInt, prev); err != nil {
		return err
	} else if !bytes.Equal(h.Mac, mac) {
		return common.NewBasicError(ErrorHopFBadMac, nil, "expected", h.Mac, "actual", mac)
	}
	return nil
}

// CalcMac calculates the MAC of a Hop Field and its preceeding Hop Field, if any.
func (h *HopField) CalcMac(mac hash.Hash, tsInt uint32,
	prev common.RawBytes) (common.RawBytes, error) {
	all := make(common.RawBytes, macInputLen)
	common.Order.PutUint32(all, tsInt)
	all[4] = h.data[0] & HopFieldVerifyFlags
	copy(all[5:], h.data[1:5])
	copy(all[9:], prev)
	tag, err := util.Mac(mac, all)
	return tag[:MacLen], err
}
<commit_msg>Fix hop field serialization for large IFIDs (#1508)<commit_after>// Copyright 2016 ETH Zurich
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package spath

import (
	"bytes"
	"fmt"
	"hash"

	//log "github.com/inconshreveable/log15"

	"github.com/scionproto/scion/go/lib/common"
	"github.com/scionproto/scion/go/lib/util"
)

type HopField struct {
	data        common.RawBytes
	Xover       bool
	VerifyOnly  bool
	ForwardOnly bool
	Recurse     bool
	ExpTime     uint8
	Ingress     common.IFIDType
	Egress      common.IFIDType
	Mac         common.RawBytes
	length      int
}

const (
	HopFieldVerifyFlags = 0x4 // Forward-only
	HopFieldLength      = common.LineLen
	DefaultHopFExpiry   = 63
	MacLen              = 3
	ErrorHopFTooShort   = "HopF too short"
	ErrorHopFBadMac     = "Bad HopF MAC"
)

func NewHopField(b common.RawBytes, in common.IFIDType, out common.IFIDType) *HopField {
	h := &HopField{}
	h.data = b
	h.ExpTime = DefaultHopFExpiry
	h.Ingress = in
	h.Egress = out
	h.Write()
	return h
}

func HopFFromRaw(b []byte) (*HopField, error) {
	if len(b) < HopFieldLength {
		return nil, common.NewBasicError(ErrorHopFTooShort, nil,
			"min", HopFieldLength, "actual", len(b))
	}
	h := &HopField{}
	h.data = b[:HopFieldLength]
	flags := h.data[0]
	h.Xover = flags&0x1 != 0
	h.VerifyOnly = flags&0x2 != 0
	h.ForwardOnly = flags&0x4 != 0
	h.Recurse = flags&0x8 != 0
	offset := 1
	h.ExpTime = h.data[offset]
	offset += 1
	// Interface IDs are 12b each, encoded into 3B
	h.Ingress = common.IFIDType(int(h.data[offset])<<4 | int(h.data[offset+1])>>4)
	h.Egress = common.IFIDType((int(h.data[offset+1])&0xF)<<8 | int(h.data[offset+2]))
	offset += 3
	h.Mac = h.data[offset:]
	h.length = common.LineLen
	return h, nil
}

// Len returns the length (in bytes)
func (h *HopField) Len() int {
	return h.length
}

func (h *HopField) Write() {
	var flags uint8
	if h.Xover {
		flags |= 0x1
	}
	if h.VerifyOnly {
		flags |= 0x2
	}
	if h.ForwardOnly {
		flags |= 0x4
	}
	if h.Recurse {
		flags |= 0x8
	}
	h.data[0] = flags
	h.data[1] = h.ExpTime
	// Interface IDs are 12b each, encoded into 3B
	h.data[2] = byte(h.Ingress >> 4)
	h.data[3] = byte((h.Ingress&0x0F)<<4 | h.Egress>>8)
	h.data[4] = byte(h.Egress & 0xFF)
	copy(h.data[5:], h.Mac)
}

func (h *HopField) String() string {
	return fmt.Sprintf(
		"Ingress: %v Egress: %v ExpTime: %v Xover: %v VerifyOnly: %v ForwardOnly: %v Mac: %v",
		h.Ingress, h.Egress, h.ExpTime, h.Xover, h.VerifyOnly, h.ForwardOnly, h.Mac)
}

func (h *HopField) Verify(mac hash.Hash, tsInt uint32, prev common.RawBytes) error {
	if mac, err := h.CalcMac(mac, tsInt, prev); err != nil {
		return err
	} else if !bytes.Equal(h.Mac, mac) {
		return common.NewBasicError(ErrorHopFBadMac, nil, "expected", h.Mac, "actual", mac)
	}
	return nil
}

// CalcMac calculates the MAC of a Hop Field and its preceeding Hop Field, if any.
func (h *HopField) CalcMac(mac hash.Hash, tsInt uint32,
	prev common.RawBytes) (common.RawBytes, error) {
	all := make(common.RawBytes, macInputLen)
	common.Order.PutUint32(all, tsInt)
	all[4] = h.data[0] & HopFieldVerifyFlags
	copy(all[5:], h.data[1:5])
	copy(all[9:], prev)
	tag, err := util.Mac(mac, all)
	return tag[:MacLen], err
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package libkb

// Version is the current version (should be MAJOR.MINOR.PATCH)
const Version = "1.0.39"
<commit_msg>v1.0.40<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package libkb

// Version is the current version (should be MAJOR.MINOR.PATCH)
const Version = "1.0.40"
<|endoftext|>


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

package types

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/exact"
)

// TODO(gri) Document factory, accessor methods, and fields. General clean-up.

// An Object describes a named language entity such as a package,
// constant, type, variable, function (incl. methods), or label.
// All objects implement the Object interface.
//
type Object interface {
	Parent() *Scope   // scope in which this object is declared
	Pos() token.Pos   // position of object identifier in declaration
	Pkg() *Package    // nil for objects in the Universe scope and labels
	Name() string     // package local object name
	Type() Type       // object type
	IsExported() bool // reports whether the name starts with a capital letter
	Id() string       // object id (see Id below)

	// String returns a human-readable string of the object.
	String() string

	// isUsed reports whether the object was marked as 'used'.
	isUsed() bool

	// setParent sets the parent scope of the object.
	setParent(*Scope)

	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
	sameId(pkg *Package, name string) bool
}

// Id returns name if it is exported, otherwise it
// returns the name qualified with the package path.
func Id(pkg *Package, name string) string {
	if ast.IsExported(name) {
		return name
	}
	// unexported names need the package path for differentiation
	// (if there's no package, make sure we don't start with '.'
	// as that may change the order of methods between a setup
	// inside a package and outside a package - which breaks some
	// tests)
	path := "_"
	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
	// if pkg == nil {
	// 	panic("nil package in lookup of unexported name")
	// }
	if pkg != nil {
		path = pkg.path
		if path == "" {
			path = "_"
		}
	}
	return path + "." + name
}

// An object implements the common parts of an Object.
type object struct {
	parent *Scope
	pos    token.Pos
	pkg    *Package
	name   string
	typ    Type
	used   bool
}

func (obj *object) Parent() *Scope   { return obj.parent }
func (obj *object) Pos() token.Pos   { return obj.pos }
func (obj *object) Pkg() *Package    { return obj.pkg }
func (obj *object) Name() string     { return obj.name }
func (obj *object) Type() Type       { return obj.typ }
func (obj *object) IsExported() bool { return ast.IsExported(obj.name) }
func (obj *object) Id() string       { return Id(obj.pkg, obj.name) }
func (obj *object) String() string   { panic("abstract") }

func (obj *object) isUsed() bool { return obj.used }

func (obj *object) setParent(parent *Scope) { obj.parent = parent }

func (obj *object) sameId(pkg *Package, name string) bool {
	// spec:
	// "Two identifiers are different if they are spelled differently,
	// or if they appear in different packages and are not exported.
	// Otherwise, they are the same."
	if name != obj.name {
		return false
	}
	// obj.Name == name
	if obj.IsExported() {
		return true
	}
	// not exported, so packages must be the same (pkg == nil for
	// fields in Universe scope; this can only happen for types
	// introduced via Eval)
	if pkg == nil || obj.pkg == nil {
		return pkg == obj.pkg
	}
	// pkg != nil && obj.pkg != nil
	return pkg.path == obj.pkg.path
}

// A PkgName represents an imported Go package.
type PkgName struct {
	object
}

func NewPkgName(pos token.Pos, pkg *Package, name string) *PkgName {
	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], false}}
}

// A Const represents a declared constant.
type Const struct {
	object
	val exact.Value

	visited bool // for initialization cycle detection
}

func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
	return &Const{object: object{nil, pos, pkg, name, typ, false}, val: val}
}

func (obj *Const) Val() exact.Value { return obj.val }

// A TypeName represents a declared type.
type TypeName struct {
	object
}

func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
	return &TypeName{object{nil, pos, pkg, name, typ, false}}
}

// A Variable represents a declared variable (including function parameters and results, and struct fields).
type Var struct {
	object

	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
	visited   bool // for initialization cycle detection
	isField   bool // var is struct field
}

func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}}
}

func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, true}} // parameters are always 'used'
}

func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}, anonymous: anonymous, isField: true}
}

func (obj *Var) Anonymous() bool { return obj.anonymous }

func (obj *Var) IsField() bool { return obj.isField }

// A Func represents a declared function, concrete method, or abstract
// (interface) method.  Its Type() is always a *Signature.
// An abstract method may belong to many interfaces due to embedding.
type Func struct {
	object
}

func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
	// don't store a nil signature
	var typ Type
	if sig != nil {
		typ = sig
	}
	return &Func{object{nil, pos, pkg, name, typ, false}}
}

// FullName returns the package- or receiver-type-qualified name of
// function or method obj.
func (obj *Func) FullName() string {
	var buf bytes.Buffer
	writeFuncName(&buf, nil, obj)
	return buf.String()
}

// A Label represents a declared label.
type Label struct {
	object
}

func NewLabel(pos token.Pos, name string) *Label {
	return &Label{object{pos: pos, name: name, typ: Typ[Invalid]}}
}

// A Builtin represents a built-in function.
// Builtins don't have a valid type.
type Builtin struct {
	object

	id builtinId
}

func newBuiltin(id builtinId) *Builtin {
	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
}

// Nil represents the predeclared value nil.
type Nil struct {
	object
}

func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
	typ := obj.Type()
	switch obj := obj.(type) {
	case *PkgName:
		buf.WriteString("package")
		typ = nil

	case *Const:
		buf.WriteString("const")

	case *TypeName:
		buf.WriteString("type")
		typ = typ.Underlying()

	case *Var:
		if obj.isField {
			buf.WriteString("field")
		} else {
			buf.WriteString("var")
		}

	case *Func:
		buf.WriteString("func ")
		writeFuncName(buf, this, obj)
		if typ != nil {
			writeSignature(buf, this, typ.(*Signature))
		}
		return

	case *Label:
		buf.WriteString("label")
		typ = nil

	case *Builtin:
		buf.WriteString("builtin")
		typ = nil

	case *Nil:
		buf.WriteString("nil")
		return

	default:
		panic(fmt.Sprintf("writeObject(%T)", obj))
	}

	buf.WriteByte(' ')

	// For package-level objects, package-qualify the name,
	// except for intra-package references (this != nil).
	if pkg := obj.Pkg(); pkg != nil && this != pkg && pkg.scope.Lookup(obj.Name()) == obj {
		buf.WriteString(pkg.path)
		buf.WriteByte('.')
	}
	buf.WriteString(obj.Name())
	if typ != nil {
		buf.WriteByte(' ')
		WriteType(buf, this, typ)
	}
}

// ObjectString returns the string form of obj.
// Object and type names are printed package-qualified
// only if they do not belong to this package.
//
func ObjectString(this *Package, obj Object) string {
	var buf bytes.Buffer
	writeObject(&buf, this, obj)
	return buf.String()
}

func (obj *PkgName) String() string  { return ObjectString(nil, obj) }
func (obj *Const) String() string    { return ObjectString(nil, obj) }
func (obj *TypeName) String() string { return ObjectString(nil, obj) }
func (obj *Var) String() string      { return ObjectString(nil, obj) }
func (obj *Func) String() string     { return ObjectString(nil, obj) }
func (obj *Label) String() string    { return ObjectString(nil, obj) }
func (obj *Builtin) String() string  { return ObjectString(nil, obj) }
func (obj *Nil) String() string      { return ObjectString(nil, obj) }

func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
	if f.typ != nil {
		sig := f.typ.(*Signature)
		if recv := sig.Recv(); recv != nil {
			buf.WriteByte('(')
			if _, ok := recv.Type().(*Interface); ok {
				// gcimporter creates abstract methods of
				// named interfaces using the interface type
				// (not the named type) as the receiver.
				// Don't print it in full.
				buf.WriteString("interface")
			} else {
				WriteType(buf, this, recv.Type())
			}
			buf.WriteByte(')')
			buf.WriteByte('.')
		} else if f.pkg != nil && f.pkg != this {
			buf.WriteString(f.pkg.path)
			buf.WriteByte('.')
		}
	}
	buf.WriteString(f.name)
}
<commit_msg>go.tools/go/types: introduce Func.Scope()<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/exact"
)

// TODO(gri) Document factory, accessor methods, and fields. General clean-up.

// An Object describes a named language entity such as a package,
// constant, type, variable, function (incl. methods), or label.
// All objects implement the Object interface.
//
type Object interface {
	Parent() *Scope   // scope in which this object is declared
	Pos() token.Pos   // position of object identifier in declaration
	Pkg() *Package    // nil for objects in the Universe scope and labels
	Name() string     // package local object name
	Type() Type       // object type
	IsExported() bool // reports whether the name starts with a capital letter
	Id() string       // object id (see Id below)

	// String returns a human-readable string of the object.
	String() string

	// isUsed reports whether the object was marked as 'used'.
	isUsed() bool

	// setParent sets the parent scope of the object.
	setParent(*Scope)

	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
	sameId(pkg *Package, name string) bool
}

// Id returns name if it is exported, otherwise it
// returns the name qualified with the package path.
func Id(pkg *Package, name string) string {
	if ast.IsExported(name) {
		return name
	}
	// unexported names need the package path for differentiation
	// (if there's no package, make sure we don't start with '.'
	// as that may change the order of methods between a setup
	// inside a package and outside a package - which breaks some
	// tests)
	path := "_"
	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
	// if pkg == nil {
	// 	panic("nil package in lookup of unexported name")
	// }
	if pkg != nil {
		path = pkg.path
		if path == "" {
			path = "_"
		}
	}
	return path + "." + name
}

// An object implements the common parts of an Object.
type object struct {
	parent *Scope
	pos    token.Pos
	pkg    *Package
	name   string
	typ    Type
	used   bool
}

func (obj *object) Parent() *Scope   { return obj.parent }
func (obj *object) Pos() token.Pos   { return obj.pos }
func (obj *object) Pkg() *Package    { return obj.pkg }
func (obj *object) Name() string     { return obj.name }
func (obj *object) Type() Type       { return obj.typ }
func (obj *object) IsExported() bool { return ast.IsExported(obj.name) }
func (obj *object) Id() string       { return Id(obj.pkg, obj.name) }
func (obj *object) String() string   { panic("abstract") }

func (obj *object) isUsed() bool { return obj.used }

func (obj *object) setParent(parent *Scope) { obj.parent = parent }

func (obj *object) sameId(pkg *Package, name string) bool {
	// spec:
	// "Two identifiers are different if they are spelled differently,
	// or if they appear in different packages and are not exported.
	// Otherwise, they are the same."
	if name != obj.name {
		return false
	}
	// obj.Name == name
	if obj.IsExported() {
		return true
	}
	// not exported, so packages must be the same (pkg == nil for
	// fields in Universe scope; this can only happen for types
	// introduced via Eval)
	if pkg == nil || obj.pkg == nil {
		return pkg == obj.pkg
	}
	// pkg != nil && obj.pkg != nil
	return pkg.path == obj.pkg.path
}

// A PkgName represents an imported Go package.
type PkgName struct {
	object
}

func NewPkgName(pos token.Pos, pkg *Package, name string) *PkgName {
	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], false}}
}

// A Const represents a declared constant.
type Const struct {
	object
	val exact.Value

	visited bool // for initialization cycle detection
}

func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
	return &Const{object: object{nil, pos, pkg, name, typ, false}, val: val}
}

func (obj *Const) Val() exact.Value { return obj.val }

// A TypeName represents a declared type.
type TypeName struct {
	object
}

func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
	return &TypeName{object{nil, pos, pkg, name, typ, false}}
}

// A Variable represents a declared variable (including function parameters and results, and struct fields).
type Var struct {
	object

	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
	visited   bool // for initialization cycle detection
	isField   bool // var is struct field
}

func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}}
}

func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, true}} // parameters are always 'used'
}

func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}, anonymous: anonymous, isField: true}
}

func (obj *Var) Anonymous() bool { return obj.anonymous }

func (obj *Var) IsField() bool { return obj.isField }

// A Func represents a declared function, concrete method, or abstract
// (interface) method.  Its Type() is always a *Signature.
// An abstract method may belong to many interfaces due to embedding.
type Func struct {
	object
}

func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
	// don't store a nil signature
	var typ Type
	if sig != nil {
		typ = sig
	}
	return &Func{object{nil, pos, pkg, name, typ, false}}
}

// FullName returns the package- or receiver-type-qualified name of
// function or method obj.
func (obj *Func) FullName() string {
	var buf bytes.Buffer
	writeFuncName(&buf, nil, obj)
	return buf.String()
}

func (obj *Func) Scope() *Scope {
	return obj.typ.(*Signature).scope
}

// A Label represents a declared label.
type Label struct {
	object
}

func NewLabel(pos token.Pos, name string) *Label {
	return &Label{object{pos: pos, name: name, typ: Typ[Invalid]}}
}

// A Builtin represents a built-in function.
// Builtins don't have a valid type.
type Builtin struct {
	object

	id builtinId
}

func newBuiltin(id builtinId) *Builtin {
	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
}

// Nil represents the predeclared value nil.
type Nil struct {
	object
}

func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
	typ := obj.Type()
	switch obj := obj.(type) {
	case *PkgName:
		buf.WriteString("package")
		typ = nil

	case *Const:
		buf.WriteString("const")

	case *TypeName:
		buf.WriteString("type")
		typ = typ.Underlying()

	case *Var:
		if obj.isField {
			buf.WriteString("field")
		} else {
			buf.WriteString("var")
		}

	case *Func:
		buf.WriteString("func ")
		writeFuncName(buf, this, obj)
		if typ != nil {
			writeSignature(buf, this, typ.(*Signature))
		}
		return

	case *Label:
		buf.WriteString("label")
		typ = nil

	case *Builtin:
		buf.WriteString("builtin")
		typ = nil

	case *Nil:
		buf.WriteString("nil")
		return

	default:
		panic(fmt.Sprintf("writeObject(%T)", obj))
	}

	buf.WriteByte(' ')

	// For package-level objects, package-qualify the name,
	// except for intra-package references (this != nil).
	if pkg := obj.Pkg(); pkg != nil && this != pkg && pkg.scope.Lookup(obj.Name()) == obj {
		buf.WriteString(pkg.path)
		buf.WriteByte('.')
	}
	buf.WriteString(obj.Name())
	if typ != nil {
		buf.WriteByte(' ')
		WriteType(buf, this, typ)
	}
}

// ObjectString returns the string form of obj.
// Object and type names are printed package-qualified
// only if they do not belong to this package.
//
func ObjectString(this *Package, obj Object) string {
	var buf bytes.Buffer
	writeObject(&buf, this, obj)
	return buf.String()
}

func (obj *PkgName) String() string  { return ObjectString(nil, obj) }
func (obj *Const) String() string    { return ObjectString(nil, obj) }
func (obj *TypeName) String() string { return ObjectString(nil, obj) }
func (obj *Var) String() string      { return ObjectString(nil, obj) }
func (obj *Func) String() string     { return ObjectString(nil, obj) }
func (obj *Label) String() string    { return ObjectString(nil, obj) }
func (obj *Builtin) String() string  { return ObjectString(nil, obj) }
func (obj *Nil) String() string      { return ObjectString(nil, obj) }

func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
	if f.typ != nil {
		sig := f.typ.(*Signature)
		if recv := sig.Recv(); recv != nil {
			buf.WriteByte('(')
			if _, ok := recv.Type().(*Interface); ok {
				// gcimporter creates abstract methods of
				// named interfaces using the interface type
				// (not the named type) as the receiver.
				// Don't print it in full.
				buf.WriteString("interface")
			} else {
				WriteType(buf, this, recv.Type())
			}
			buf.WriteByte(')')
			buf.WriteByte('.')
		} else if f.pkg != nil && f.pkg != this {
			buf.WriteString(f.pkg.path)
			buf.WriteByte('.')
		}
	}
	buf.WriteString(f.name)
}
<|endoftext|>


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

package sqlite3

/*
#include "sqlite3.h"

int shell_main(int, void*);
*/
import "C"

import (
	"bytes"
	"fmt"
	"os"
	"reflect"
	"unsafe"
)

// NamedArgs is a name/value map of arguments passed to a prepared statement
// that uses ?NNN, :AAA, @AAA, and/or $AAA parameter formats. Name matching is
// case-sensitive and the prefix character (one of [?:@$]) must be included in
// the name. Names that are missing from the map are treated as NULL. Names that
// are not used in the prepared statement are ignored.
//
// It is not possible to mix named and anonymous ("?") parameters in the same
// statement.
// [http://www.sqlite.org/lang_expr.html#varparam]
type NamedArgs map[string]interface{}

// RowMap may be passed as the last (or only) argument to Stmt.Scan to create a
// map of all remaining column/value pairs in the current row. The map is not
// cleared before being populated with new column values. Assignment is
// performed in left-to-right column order, and values may be overwritten if the
// query returns two or more columns with identical names.
type RowMap map[string]interface{}

// RawString and RawBytes are special string and []byte types that may be used
// for database input and output without the cost of an extra copy operation.
//
// When used as an argument to a statement, the contents are bound using
// SQLITE_STATIC instead of SQLITE_TRANSIENT flag. This requires the contents to
// remain valid and unmodified until the end of statement execution. In
// particular, the caller must keep a reference to the value to prevent it from
// being garbage collected.
//
// When used for retrieving query output, the internal string/[]byte pointer is
// set to reference memory belonging to SQLite. The memory remains valid until
// another method is called on the Stmt object and should not be modified.
type (
	RawString string
	RawBytes  []byte
)

// Copy returns a Go-owned copy of s.
func (s RawString) Copy() string {
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len))
}

// Copy returns a Go-owned copy of b.
func (b RawBytes) Copy() []byte {
	h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	return C.GoBytes(unsafe.Pointer(h.Data), C.int(h.Len))
}

// ZeroBlob is a special argument type used to allocate a zero-filled BLOB of
// the specified length. The BLOB can then be opened for incremental I/O to
// efficiently transfer a large amount of data. The maximum BLOB size can be
// queried with Conn.Limit(LIMIT_LENGTH, -1).
type ZeroBlob int

// BusyFunc is a callback function invoked by SQLite when it is unable to
// acquire a lock on a table. Count is the number of times that the callback has
// been invoked for this locking event so far. If the function returns false,
// then the operation is aborted. Otherwise, the function should block for a
// while before returning true and letting SQLite make another locking attempt.
type BusyFunc func(count int) (retry bool)

// CommitFunc is a callback function invoked by SQLite before a transaction is
// committed. If the function returns true, the transaction is rolled back.
type CommitFunc func() (abort bool)

// RollbackFunc is a callback function invoked by SQLite when a transaction is
// rolled back.
type RollbackFunc func()

// UpdateFunc is a callback function invoked by SQLite when a row is updated,
// inserted, or deleted.
type UpdateFunc func(op int, db, tbl RawString, row int64)

// Error is returned for all SQLite API result codes other than OK, ROW, and
// DONE.
type Error struct {
	rc  int
	msg string
}

// libErr reports an error originating in SQLite. The error message is obtained
// from the database connection when possible, which may include some additional
// information. Otherwise, the result code is translated to a generic message.
func libErr(rc C.int, db *C.sqlite3) error {
	if db != nil && rc == C.sqlite3_errcode(db) {
		return &Error{int(rc), C.GoString(C.sqlite3_errmsg(db))}
	}
	return &Error{int(rc), C.GoString(C.sqlite3_errstr(rc))}
}

// pkgErr reports an error originating in this package.
func pkgErr(rc int, msg string, v ...interface{}) error {
	if len(v) == 0 {
		return &Error{rc, msg}
	}
	return &Error{rc, fmt.Sprintf(msg, v...)}
}

// Code returns the SQLite extended result code.
func (err *Error) Code() int {
	return err.rc
}

// Error implements the error interface.
func (err *Error) Error() string {
	return fmt.Sprintf("sqlite3: %s [%d]", err.msg, err.rc)
}

// Errors returned for access attempts to closed or invalid objects.
var (
	ErrBadConn   = &Error{MISUSE, "closed or invalid connection"}
	ErrBadStmt   = &Error{MISUSE, "closed or invalid statement"}
	ErrBadIO     = &Error{MISUSE, "closed or invalid incremental I/O operation"}
	ErrBadBackup = &Error{MISUSE, "closed or invalid backup operation"}
)

// Shell is deprecated and will be removed in the near future. Don't use it!
func Shell(args ...string) int {
	if initErr != nil {
		return 127
	}
	args = append([]string{os.Args[0]}, args...)

	// Copy all arguments into a single []byte, terminating each one with '\0'
	buf := make([]byte, 0, 256)
	for _, arg := range args {
		buf = append(append(buf, arg...), 0)
	}

	// Fill argv with pointers to the start of each null-terminated string
	argv := make([]uintptr, len(args))
	base := uintptr(cBytes(buf))
	for i, arg := range args {
		argv[i] = base
		base += uintptr(len(arg)) + 1
	}
	return int(C.shell_main(C.int(len(args)), unsafe.Pointer(&argv[0])))
}

// Complete returns true if sql appears to contain a complete statement that is
// ready to be parsed. This does not validate the statement syntax.
// [http://www.sqlite.org/c3ref/complete.html]
func Complete(sql string) bool {
	if initErr != nil {
		return false
	}
	sql += "\x00"
	return C.sqlite3_complete(cStr(sql)) == 1
}

// ReleaseMemory attempts to free n bytes of heap memory by deallocating
// non-essential memory held by the SQLite library. It returns the number of
// bytes actually freed.
//
// This function is currently a no-op because SQLite is not compiled with the
// SQLITE_ENABLE_MEMORY_MANAGEMENT option.
// [http://www.sqlite.org/c3ref/release_memory.html]
func ReleaseMemory(n int) int {
	if initErr != nil {
		return 0
	}
	return int(C.sqlite3_release_memory(C.int(n)))
}

// SingleThread returns true if the SQLite library was compiled with
// -DSQLITE_THREADSAFE=0. With this threading mode, all mutex code is omitted
// and this package becomes unsafe for concurrent access, even to separate
// database connections.
//
// This function was needed in Go 1.0 when the package was dynamically linked
// with the system's SQLite library on *nix. As of Go 1.1, the SQLite
// amalgamation is compiled into the package with -DSQLITE_THREADSAFE=2, so this
// function always returns false and is kept only for backward compatibility.
// [http://www.sqlite.org/threadsafe.html]
func SingleThread() bool {
	return initErr == nil && C.sqlite3_threadsafe() == 0
}

// SoftHeapLimit sets and/or queries the soft limit on the amount of heap memory
// that may be allocated by SQLite. A negative value for n keeps the current
// limit, while 0 removes the limit. The previous limit value is returned, with
// negative values indicating an error.
// [http://www.sqlite.org/c3ref/soft_heap_limit64.html]
func SoftHeapLimit(n int64) int64 {
	if initErr != nil {
		return -1
	}
	return int64(C.sqlite3_soft_heap_limit64(C.sqlite3_int64(n)))
}

// SourceId returns the check-in identifier of SQLite within its configuration
// management system (e.g. "2013-01-09 11:53:05
// c0e09560d26f0a6456be9dd3447f5311eb4f238f").
// [http://www.sqlite.org/c3ref/c_source_id.html]
func SourceId() string {
	if initErr != nil {
		return ""
	}
	return C.GoString(C.sqlite3_sourceid())
}

// Status returns the current and peak values of a core performance
// counter, specified by one of the STATUS constants. If reset is true, the peak
// value is reset back down to the current value after retrieval.
// [http://www.sqlite.org/c3ref/status.html]
func Status(op int, reset bool) (cur, peak int, err error) {
	if initErr != nil {
		return 0, 0, initErr
	}
	var cCur, cPeak C.int
	rc := C.sqlite3_status(C.int(op), &cCur, &cPeak, cBool(reset))
	if rc != OK {
		return 0, 0, pkgErr(MISUSE, "invalid status op (%d)", op)
	}
	return int(cCur), int(cPeak), nil
}

// Version returns the SQLite version as a string in the format "X.Y.Z[.N]".
// [http://www.sqlite.org/c3ref/libversion.html]
func Version() string {
	if initErr != nil {
		return ""
	}
	return C.GoString(C.sqlite3_libversion())
}

// VersionNum returns the SQLite version as an integer in the format X*1000000 +
// Y*1000 + Z, where X is the major version, Y is the minor version, and Z is
// the release number.
func VersionNum() int {
	if initErr != nil {
		return 0
	}
	return int(C.sqlite3_libversion_number())
}

// Print prints out all rows returned by a query. This function is intended as a
// debugging aid and may be removed or altered in the future. Do not use it in
// production applications.
func Print(s *Stmt) error {
	if s == nil || s.NumColumns() == 0 {
		return nil
	}
	var err error
	if !s.Busy() {
		if err = s.Query(); err != nil {
			return err
		}
	}
	cols := s.Columns()
	buf := bytes.NewBuffer(make([]byte, 0, len(cols)*10))
	row := make(RowMap, len(cols))

	buf.WriteByte('~')
	for _, col := range cols {
		fmt.Fprintf(buf, " %s ~", col)
	}
	fmt.Println(buf)
	for ; err == nil; err = s.Next() {
		if err = s.Scan(row); err != nil {
			return err
		}
		buf.Reset()
		buf.WriteByte('|')
		for _, col := range cols {
			fmt.Fprintf(buf, " %*v |", len(col), row[col])
		}
		fmt.Println(buf)
	}
	return err
}

// cStr returns a pointer to the first byte in s, which must be a
// null-terminated string.
func cStr(s string) *C.char {
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	return (*C.char)(unsafe.Pointer(h.Data))
}

// cStrOffset returns the offset of p in s, which must be a null-terminated
// string. It panics if p is not a pointer into s.
func cStrOffset(s string, p *C.char) int {
	start := (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
	if n := uintptr(unsafe.Pointer(p)) - start; n < uintptr(len(s)) {
		return int(n)
	}
	panic("sqlite3: p is not a pointer into s")
}

// cBytes returns a pointer to the first byte in b.
func cBytes(b []byte) unsafe.Pointer {
	return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data)
}

// cBool returns an integer representation of a bool (false = 0, true = 1).
func cBool(b bool) C.int {
	if b {
		return 1
	}
	return 0
}

// goStr returns a Go string representation of a null-terminated C string.
func goStr(p *C.char) (s string) {
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	h.Data = uintptr(unsafe.Pointer(p))
	h.Len = int(^uint(0) >> 1)
	n := 0
	for s[n] != 0 {
		n++
	}
	if n == 0 {
		return "" // Don't keep a pointer to an unused string
	}
	h.Len = n
	return
}

// goStrN returns a Go string representation of an n-byte C string.
func goStrN(p *C.char, n C.int) (s string) {
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	h.Data = uintptr(unsafe.Pointer(p))
	h.Len = int(n)
	return
}

// goBytes returns a []byte representation of an n-byte C array.
func goBytes(p unsafe.Pointer, n C.int) (b []byte) {
	h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	h.Data = uintptr(p)
	h.Len = int(n)
	h.Cap = int(n)
	return
}

//export go_busy_handler
func go_busy_handler(conn unsafe.Pointer, count C.int) C.int {
	retry := false
	if c := (*Conn)(conn); c != nil && c.db != nil && c.busy != nil {
		retry = c.busy(int(count))
	}
	return cBool(retry)
}

//export go_commit_hook
func go_commit_hook(conn unsafe.Pointer) C.int {
	abort := false
	if c := (*Conn)(conn); c != nil && c.db != nil && c.commit != nil {
		abort = c.commit()
	}
	return cBool(abort)
}

//export go_rollback_hook
func go_rollback_hook(conn unsafe.Pointer) {
	if c := (*Conn)(conn); c != nil && c.db != nil && c.rollback != nil {
		c.rollback()
	}
}

//export go_update_hook
func go_update_hook(conn unsafe.Pointer, op C.int, db, tbl *C.char, row C.sqlite3_int64) {
	if c := (*Conn)(conn); c != nil && c.db != nil && c.update != nil {
		c.update(int(op), RawString(goStr(db)), RawString(goStr(tbl)), int64(row))
	}
}
<commit_msg>Utility function tweaks.<commit_after>// Copyright 2013 The Go-SQLite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlite3

/*
#include "sqlite3.h"

int shell_main(int,void*);
*/
import "C"

import (
	"bytes"
	"fmt"
	"os"
	"reflect"
	"unsafe"
)

// NamedArgs is a name/value map of arguments passed to a prepared statement
// that uses ?NNN, :AAA, @AAA, and/or $AAA parameter formats. Name matching is
// case-sensitive and the prefix character (one of [?:@$]) must be included in
// the name. Names that are missing from the map are treated as NULL. Names that
// are not used in the prepared statement are ignored.
//
// It is not possible to mix named and anonymous ("?") parameters in the same
// statement.
// [http://www.sqlite.org/lang_expr.html#varparam]
type NamedArgs map[string]interface{}

// RowMap may be passed as the last (or only) argument to Stmt.Scan to create a
// map of all remaining column/value pairs in the current row. The map is not
// cleared before being populated with new column values. Assignment is
// performed in left-to-right column order, and values may be overwritten if the
// query returns two or more columns with identical names.
type RowMap map[string]interface{}

// RawString and RawBytes are special string and []byte types that may be used
// for database input and output without the cost of an extra copy operation.
//
// When used as an argument to a statement, the contents are bound using
// SQLITE_STATIC instead of SQLITE_TRANSIENT flag. This requires the contents to
// remain valid and unmodified until the end of statement execution. In
// particular, the caller must keep a reference to the value to prevent it from
// being garbage collected.
//
// When used for retrieving query output, the internal string/[]byte pointer is
// set to reference memory belonging to SQLite. The memory remains valid until
// another method is called on the Stmt object and should not be modified.
type (
	RawString string
	RawBytes  []byte
)

// Copy returns a Go-managed copy of s.
func (s RawString) Copy() string {
	if s == "" {
		return ""
	}
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len))
}

// Copy returns a Go-managed copy of b.
func (b RawBytes) Copy() []byte {
	if len(b) == 0 {
		if b == nil {
			return nil
		}
		return []byte("")
	}
	h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	return C.GoBytes(unsafe.Pointer(h.Data), C.int(h.Len))
}

// ZeroBlob is a special argument type used to allocate a zero-filled BLOB of
// the specified length. The BLOB can then be opened for incremental I/O to
// efficiently transfer a large amount of data. The maximum BLOB size can be
// queried with Conn.Limit(LIMIT_LENGTH, -1).
type ZeroBlob int

// BusyFunc is a callback function invoked by SQLite when it is unable to
// acquire a lock on a table. Count is the number of times that the callback has
// been invoked for this locking event so far. If the function returns false,
// then the operation is aborted. Otherwise, the function should block for a
// while before returning true and letting SQLite make another locking attempt.
type BusyFunc func(count int) (retry bool)

// CommitFunc is a callback function invoked by SQLite before a transaction is
// committed. If the function returns true, the transaction is rolled back.
type CommitFunc func() (abort bool)

// RollbackFunc is a callback function invoked by SQLite when a transaction is
// rolled back.
type RollbackFunc func()

// UpdateFunc is a callback function invoked by SQLite when a row is updated,
// inserted, or deleted.
type UpdateFunc func(op int, db, tbl RawString, row int64)

// Error is returned for all SQLite API result codes other than OK, ROW, and
// DONE.
type Error struct {
	rc  int
	msg string
}

// libErr reports an error originating in SQLite. The error message is obtained
// from the database connection when possible, which may include some additional
// information. Otherwise, the result code is translated to a generic message.
func libErr(rc C.int, db *C.sqlite3) error {
	if db != nil && rc == C.sqlite3_errcode(db) {
		return &Error{int(rc), C.GoString(C.sqlite3_errmsg(db))}
	}
	return &Error{int(rc), C.GoString(C.sqlite3_errstr(rc))}
}

// pkgErr reports an error originating in this package.
func pkgErr(rc int, msg string, v ...interface{}) error {
	if len(v) == 0 {
		return &Error{rc, msg}
	}
	return &Error{rc, fmt.Sprintf(msg, v...)}
}

// Code returns the SQLite extended result code.
func (err *Error) Code() int {
	return err.rc
}

// Error implements the error interface.
func (err *Error) Error() string {
	return fmt.Sprintf("sqlite3: %s [%d]", err.msg, err.rc)
}

// Errors returned for access attempts to closed or invalid objects.
var (
	ErrBadConn   = &Error{MISUSE, "closed or invalid connection"}
	ErrBadStmt   = &Error{MISUSE, "closed or invalid statement"}
	ErrBadIO     = &Error{MISUSE, "closed or invalid incremental I/O operation"}
	ErrBadBackup = &Error{MISUSE, "closed or invalid backup operation"}
)

// Shell is deprecated and will be removed in the near future. Don't use it!
func Shell(args ...string) int {
	if initErr != nil {
		return 127
	}
	args = append([]string{os.Args[0]}, args...)

	// Copy all arguments into a single []byte, terminating each one with '\0'
	buf := make([]byte, 0, 256)
	for _, arg := range args {
		buf = append(append(buf, arg...), 0)
	}

	// Fill argv with pointers to the start of each null-terminated string
	argv := make([]uintptr, len(args))
	base := uintptr(cBytes(buf))
	for i, arg := range args {
		argv[i] = base
		base += uintptr(len(arg)) + 1
	}
	return int(C.shell_main(C.int(len(args)), unsafe.Pointer(&argv[0])))
}

// Complete returns true if sql appears to contain a complete statement that is
// ready to be parsed. This does not validate the statement syntax.
// [http://www.sqlite.org/c3ref/complete.html]
func Complete(sql string) bool {
	if initErr != nil {
		return false
	}
	sql += "\x00"
	return C.sqlite3_complete(cStr(sql)) == 1
}

// ReleaseMemory attempts to free n bytes of heap memory by deallocating
// non-essential memory held by the SQLite library. It returns the number of
// bytes actually freed.
//
// This function is currently a no-op because SQLite is not compiled with the
// SQLITE_ENABLE_MEMORY_MANAGEMENT option.
// [http://www.sqlite.org/c3ref/release_memory.html]
func ReleaseMemory(n int) int {
	if initErr != nil {
		return 0
	}
	return int(C.sqlite3_release_memory(C.int(n)))
}

// SingleThread returns true if the SQLite library was compiled with
// -DSQLITE_THREADSAFE=0. In this threading mode all mutex code is omitted and
// the package becomes unsafe for concurrent access, even to separate database
// connections.
//
// The SQLite source that's part of this package is compiled with
// -DSQLITE_THREADSAFE=2, so this function should always return false. It is
// kept for backward compatibility when dynamic linking was supported in Go 1.0.
// [http://www.sqlite.org/threadsafe.html]
func SingleThread() bool {
	return initErr == nil && C.sqlite3_threadsafe() == 0
}

// SoftHeapLimit sets and/or queries the soft limit on the amount of heap memory
// that may be allocated by SQLite. A negative value for n keeps the current
// limit, while 0 removes the limit. The previous limit value is returned, with
// negative values indicating an error.
// [http://www.sqlite.org/c3ref/soft_heap_limit64.html]
func SoftHeapLimit(n int64) int64 {
	if initErr != nil {
		return -1
	}
	return int64(C.sqlite3_soft_heap_limit64(C.sqlite3_int64(n)))
}

// SourceId returns the check-in identifier of SQLite within its configuration
// management system.
// [http://www.sqlite.org/c3ref/c_source_id.html]
func SourceId() string {
	if initErr != nil {
		return ""
	}
	return C.GoString(C.sqlite3_sourceid())
}

// Status returns the current and peak values of a core performance
// counter, specified by one of the STATUS constants. If reset is true, the peak
// value is reset back down to the current value after retrieval.
// [http://www.sqlite.org/c3ref/status.html]
func Status(op int, reset bool) (cur, peak int, err error) {
	if initErr != nil {
		return 0, 0, initErr
	}
	var cCur, cPeak C.int
	rc := C.sqlite3_status(C.int(op), &cCur, &cPeak, cBool(reset))
	if rc != OK {
		return 0, 0, pkgErr(MISUSE, "invalid status op (%d)", op)
	}
	return int(cCur), int(cPeak), nil
}

// Version returns the SQLite version as a string in the format "X.Y.Z[.N]".
// [http://www.sqlite.org/c3ref/libversion.html]
func Version() string {
	if initErr != nil {
		return ""
	}
	return goStr(C.sqlite3_libversion())
}

// VersionNum returns the SQLite version as an integer in the format X*1000000 +
// Y*1000 + Z, where X is the major version, Y is the minor version, and Z is
// the release number.
func VersionNum() int {
	if initErr != nil {
		return 0
	}
	return int(C.sqlite3_libversion_number())
}

// Print prints out all rows returned by a query. This function is intended as a
// debugging aid and may be removed or altered in the future. Do not use it in
// production applications.
func Print(s *Stmt) error {
	if s == nil || s.NumColumns() == 0 {
		return nil
	}
	var err error
	if !s.Busy() {
		if err = s.Query(); err != nil {
			return err
		}
	}
	cols := s.Columns()
	buf := bytes.NewBuffer(make([]byte, 0, len(cols)*10))
	row := make(RowMap, len(cols))

	buf.WriteByte('~')
	for _, col := range cols {
		fmt.Fprintf(buf, " %s ~", col)
	}
	fmt.Println(buf)
	for ; err == nil; err = s.Next() {
		if err = s.Scan(row); err != nil {
			return err
		}
		buf.Reset()
		buf.WriteByte('|')
		for _, col := range cols {
			fmt.Fprintf(buf, " %*v |", len(col), row[col])
		}
		fmt.Println(buf)
	}
	return err
}

// cStr returns a pointer to the first byte in s.
func cStr(s string) *C.char {
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	return (*C.char)(unsafe.Pointer(h.Data))
}

// cStrOffset returns the offset of p in s or -1 if p doesn't point into s.
func cStrOffset(s string, p *C.char) int {
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
	if off := uintptr(unsafe.Pointer(p)) - h.Data; off < uintptr(h.Len) {
		return int(off)
	}
	return -1
}

// cBytes returns a pointer to the first byte in b.
func cBytes(b []byte) unsafe.Pointer {
	return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data)
}

// cBool returns a C representation of a Go bool (false = 0, true = 1).
func cBool(b bool) C.int {
	if b {
		return 1
	}
	return 0
}

// goStr returns a Go representation of a null-terminated C string.
func goStr(p *C.char) (s string) {
	if p != nil && *p != 0 {
		h := (*reflect.StringHeader)(unsafe.Pointer(&s))
		h.Data = uintptr(unsafe.Pointer(p))
		for *p != 0 {
			p = (*C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++
		}
		h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data)
	}
	return
}

// goStrN returns a Go representation of an n-byte C string.
func goStrN(p *C.char, n C.int) (s string) {
	if n > 0 {
		h := (*reflect.StringHeader)(unsafe.Pointer(&s))
		h.Data = uintptr(unsafe.Pointer(p))
		h.Len = int(n)
	}
	return
}

// goBytes returns a Go representation of an n-byte C array.
func goBytes(p unsafe.Pointer, n C.int) (b []byte) {
	if n > 0 {
		h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
		h.Data = uintptr(p)
		h.Len = int(n)
		h.Cap = int(n)
	}
	return
}

//export go_busy_handler
func go_busy_handler(conn unsafe.Pointer, count C.int) C.int {
	retry := false
	if c := (*Conn)(conn); c != nil && c.db != nil && c.busy != nil {
		retry = c.busy(int(count))
	}
	return cBool(retry)
}

//export go_commit_hook
func go_commit_hook(conn unsafe.Pointer) C.int {
	abort := false
	if c := (*Conn)(conn); c != nil && c.db != nil && c.commit != nil {
		abort = c.commit()
	}
	return cBool(abort)
}

//export go_rollback_hook
func go_rollback_hook(conn unsafe.Pointer) {
	if c := (*Conn)(conn); c != nil && c.db != nil && c.rollback != nil {
		c.rollback()
	}
}

//export go_update_hook
func go_update_hook(conn unsafe.Pointer, op C.int, db, tbl *C.char, row C.sqlite3_int64) {
	if c := (*Conn)(conn); c != nil && c.db != nil && c.update != nil {
		c.update(int(op), RawString(goStr(db)), RawString(goStr(tbl)), int64(row))
	}
}
<|endoftext|>


<commit_before>// USAGE
// import (
//	sr "go_simple_router"
//	"log"
// 	"fmt"
// )
//
// Embed BasicHandler to implement all stub methods of CustomHttpHandler interface
// type Index struct{ *sr.BasicHandler }
//
// func (*Index) Get(w http.ResponseWriter, r *http.Request) {
//	fmt.Fprintln(w, "This is Index Get")
//}
//
// func (*Index) Post(w http.ResponseWriter, r *http.Request) {
//	fmt.Fprintln(w, "This is Index Post")
// }
// ...
// func main() {
// 	http.HandleFunc("/", sr.R{&Index{}}.RouteByMethod)
//	log.Println("Listen port 8000")
//	log.Fatal(http.ListenAndServe(":8000", nil))
// }

package go_simple_router

import (
	"net/http"
	"log"
)

// Basic routing struct with
// RouteByMethod() - main method to handle request methods and route them
// Must be initialized with specified handler struct with Get(), Post(), Put(), Patch(), Delete()
type R struct {
	Handler CustomHttpHandler // implementation of specific handler
}

func (rtr R) RouteByMethod(w http.ResponseWriter, r *http.Request) {
	log.Println("Handler Handle Func")

	if r.Method == "POST" {
		rtr.Handler.Post(w, r)
		return
	}

	if r.Method == "PUT" {
		rtr.Handler.Post(w, r)
		return
	}

	if r.Method == "PATCH" {
		rtr.Handler.Patch(w, r)
		return
	}

	if r.Method == "Delete" {
		rtr.Handler.Delete(w, r)
		return
	}

	rtr.Handler.Get(w, r)
}

// Interface with list of necessary methods
type CustomHttpHandler interface {
	Get (w http.ResponseWriter, r *http.Request)
	Post (w http.ResponseWriter, r *http.Request)
	Put (w http.ResponseWriter, r *http.Request)
	Patch (w http.ResponseWriter, r *http.Request)
	Delete (w http.ResponseWriter, r *http.Request)
}

// Struct to implement stub methods
// Embed it when you want to implement CustomHttpHandler interface
type BasicHandlers struct{}

func (*BasicHandlers) Get(w http.ResponseWriter, r *http.Request) {
	log.Println("Get Stub")
}

func (*BasicHandlers) Post(w http.ResponseWriter, r *http.Request) {
	log.Println("Post Stub")
}

func (*BasicHandlers) Put(w http.ResponseWriter, r *http.Request) {
	log.Println("Put Stub")
}

func (*BasicHandlers) Patch(w http.ResponseWriter, r *http.Request) {
	log.Println("Patch Stub")
}

func (*BasicHandlers) Delete (w http.ResponseWriter, r *http.Request) {
	log.Println("Delete Stub")
}

<commit_msg>usage comment updated<commit_after>// USAGE
// import (
//	sr "github.com/nordorn/go_simple_router"
//	"log"
// 	"fmt"
// )
//
// Embed BasicHandlers to implement all stub methods of CustomHttpHandler interface
// type Index struct{ *sr.BasicHandlers }
//
// func (*Index) Get(w http.ResponseWriter, r *http.Request) {
//	fmt.Fprintln(w, "This is Index Get")
//}
//
// func (*Index) Post(w http.ResponseWriter, r *http.Request) {
//	fmt.Fprintln(w, "This is Index Post")
// }
// ...
// func main() {
// 	http.HandleFunc("/", sr.R{&Index{}}.RouteByMethod)
//	log.Println("Listen port 8000")
//	log.Fatal(http.ListenAndServe(":8000", nil))
// }

package go_simple_router

import (
	"net/http"
	"log"
)

// Basic routing struct with
// RouteByMethod() - main method to handle request methods and route them
// Must be initialized with specified handler struct with Get(), Post(), Put(), Patch(), Delete()
type R struct {
	Handler CustomHttpHandler // implementation of specific handler
}

func (rtr R) RouteByMethod(w http.ResponseWriter, r *http.Request) {
	log.Println("Handler Handle Func")

	if r.Method == "POST" {
		rtr.Handler.Post(w, r)
		return
	}

	if r.Method == "PUT" {
		rtr.Handler.Post(w, r)
		return
	}

	if r.Method == "PATCH" {
		rtr.Handler.Patch(w, r)
		return
	}

	if r.Method == "Delete" {
		rtr.Handler.Delete(w, r)
		return
	}

	rtr.Handler.Get(w, r)
}

// Interface with list of necessary methods
type CustomHttpHandler interface {
	Get (w http.ResponseWriter, r *http.Request)
	Post (w http.ResponseWriter, r *http.Request)
	Put (w http.ResponseWriter, r *http.Request)
	Patch (w http.ResponseWriter, r *http.Request)
	Delete (w http.ResponseWriter, r *http.Request)
}

// Struct to implement stub methods
// Embed it when you want to implement CustomHttpHandler interface
type BasicHandlers struct{}

func (*BasicHandlers) Get(w http.ResponseWriter, r *http.Request) {
	log.Println("Get Stub")
}

func (*BasicHandlers) Post(w http.ResponseWriter, r *http.Request) {
	log.Println("Post Stub")
}

func (*BasicHandlers) Put(w http.ResponseWriter, r *http.Request) {
	log.Println("Put Stub")
}

func (*BasicHandlers) Patch(w http.ResponseWriter, r *http.Request) {
	log.Println("Patch Stub")
}

func (*BasicHandlers) Delete(w http.ResponseWriter, r *http.Request) {
	log.Println("Delete Stub")
}

<|endoftext|>


<commit_before>package goat

import (
	"encoding/hex"
	"strconv"
	"time"
)

// AnnounceLog represents an announce, to be logged to storage
type AnnounceLog struct {
	ID         int
	InfoHash   string `db:"info_hash"`
	Passkey    string
	Key        string
	IP         string
	Port       int
	UDP        bool
	Uploaded   int64
	Downloaded int64
	Left       int64
	Event      string
	Client     string
	Time       int64
}

// Save AnnounceLog to storage
func (a AnnounceLog) Save() bool {
	// Open database connection
	db, err := DBConnect()
	if err != nil {
		Static.LogChan <- err.Error()
		return false
	}

	// Store announce log
	query := "INSERT INTO announce_log " +
		"(`info_hash`, `passkey`, `key`, `ip`, `port`, `udp`, `uploaded`, `downloaded`, `left`, `event`, `client`, `time`) " +
		"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, UNIX_TIMESTAMP());"

	// Create database transaction, do insert, commit
	tx := db.MustBegin()
	tx.Execl(query, a.InfoHash, a.Passkey, a.Key, a.IP, a.Port, a.UDP, a.Uploaded, a.Downloaded, a.Left, a.Event, a.Client)
	tx.Commit()

	return true
}

// Load AnnounceLog from storage
func (a AnnounceLog) Load(id interface{}, col string) AnnounceLog {
	// Open database connection
	db, err := DBConnect()
	if err != nil {
		Static.LogChan <- err.Error()
		return a
	}

	// Fetch announce log into struct
	a = AnnounceLog{}
	db.Get(&a, "SELECT * FROM announce_log WHERE `"+col+"`=?", id)

	return a
}

// FromMap generates an AnnounceLog struct from a query map
func (a AnnounceLog) FromMap(query map[string]string) AnnounceLog {
	a = AnnounceLog{}

	// Required parameters

	// info_hash
	a.InfoHash = hex.EncodeToString([]byte(query["info_hash"]))

	// passkey
	a.Passkey = query["passkey"]

	// key
	a.Key = query["key"]

	// ip
	a.IP = query["ip"]

	// Note: integers previously validated

	// port
	port, _ := strconv.Atoi(query["port"])
	a.Port = port

	// udp
	if query["udp"] == "1" {
		a.UDP = true
	} else {
		a.UDP = false
	}

	// uploaded
	uploaded, _ := strconv.ParseInt(query["uploaded"], 10, 64)
	a.Uploaded = uploaded

	// downloaded
	downloaded, _ := strconv.ParseInt(query["downloaded"], 10, 64)
	a.Downloaded = downloaded

	// left
	left, _ := strconv.ParseInt(query["left"], 10, 64)
	a.Left = left

	// Optional parameters

	// event
	if event, ok := query["event"]; ok {
		a.Event = event
	}

	// BitTorrent client, User-Agent header
	a.Client = query["client"]

	// Current UNIX timestamp
	a.Time = time.Now().Unix()

	// Return the created announce
	return a
}
<commit_msg>Improve error handling in announceLog.go<commit_after>package goat

import (
	"encoding/hex"
	"strconv"
	"time"
)

// AnnounceLog represents an announce, to be logged to storage
type AnnounceLog struct {
	ID         int
	InfoHash   string `db:"info_hash"`
	Passkey    string
	Key        string
	IP         string
	Port       int
	UDP        bool
	Uploaded   int64
	Downloaded int64
	Left       int64
	Event      string
	Client     string
	Time       int64
}

// Save AnnounceLog to storage
func (a AnnounceLog) Save() bool {
	// Open database connection
	db, err := DBConnect()
	if err != nil {
		Static.LogChan <- err.Error()
		return false
	}

	// Store announce log
	query := "INSERT INTO announce_log " +
		"(`info_hash`, `passkey`, `key`, `ip`, `port`, `udp`, `uploaded`, `downloaded`, `left`, `event`, `client`, `time`) " +
		"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, UNIX_TIMESTAMP());"

	// Create database transaction, do insert, commit
	tx := db.MustBegin()
	tx.Execl(query, a.InfoHash, a.Passkey, a.Key, a.IP, a.Port, a.UDP, a.Uploaded, a.Downloaded, a.Left, a.Event, a.Client)
	tx.Commit()

	return true
}

// Load AnnounceLog from storage
func (a AnnounceLog) Load(id interface{}, col string) AnnounceLog {
	// Open database connection
	db, err := DBConnect()
	if err != nil {
		Static.LogChan <- err.Error()
		return AnnounceLog{}
	}

	// Fetch announce log into struct
	a = AnnounceLog{}
	err = db.Get(&a, "SELECT * FROM announce_log WHERE `"+col+"`=?", id)
	if err != nil {
		Static.LogChan <- err.Error()
		return AnnounceLog{}
	}

	return a
}

// FromMap generates an AnnounceLog struct from a query map
func (a AnnounceLog) FromMap(query map[string]string) AnnounceLog {
	a = AnnounceLog{}

	// Required parameters

	// info_hash
	a.InfoHash = hex.EncodeToString([]byte(query["info_hash"]))

	// passkey
	a.Passkey = query["passkey"]

	// key
	a.Key = query["key"]

	// ip
	a.IP = query["ip"]

	// udp
	if query["udp"] == "1" {
		a.UDP = true
	} else {
		a.UDP = false
	}

	// port
	port, err := strconv.Atoi(query["port"])
	if err != nil {
		Static.LogChan <- err.Error()
		return AnnounceLog{}
	}
	a.Port = port

	// uploaded
	uploaded, err := strconv.ParseInt(query["uploaded"], 10, 64)
	if err != nil {
		Static.LogChan <- err.Error()
		return AnnounceLog{}
	}
	a.Uploaded = uploaded

	// downloaded
	downloaded, err := strconv.ParseInt(query["downloaded"], 10, 64)
	if err != nil {
		Static.LogChan <- err.Error()
		return AnnounceLog{}
	}
	a.Downloaded = downloaded

	// left
	left, err := strconv.ParseInt(query["left"], 10, 64)
	if err != nil {
		Static.LogChan <- err.Error()
		return AnnounceLog{}
	}
	a.Left = left

	// Optional parameters

	// event
	if event, ok := query["event"]; ok {
		a.Event = event
	}

	// BitTorrent client, User-Agent header
	a.Client = query["client"]

	// Current UNIX timestamp
	a.Time = time.Now().Unix()

	// Return the created announce
	return a
}
<|endoftext|>