<commit_before>// Package tail implements a plugin to tail files and notify new lines on all channels.
package tail

import (
	"bufio"
	"io"
	"log"
	"os"
	"strings"
	"time"

	"github.com/StalkR/goircbot/bot"
)

// Tail watches a file and calls callback for every new line.
// File can be truncated but it does not detect if file is renamed.
func Tail(path string, cb func(line string)) {
	var f *os.File
	for {
		fp, err := os.Open(path)
		if err == nil {
			f = fp
			break
		}
		log.Println("tail: error open", path, err)
		time.Sleep(time.Minute)
	}
	defer f.Close()

	r := bufio.NewReader(f)
	for {
		if _, err := r.ReadString('\n'); err != nil {
			break
		}
	}
	var line string
	for {
		time.Sleep(time.Second)
		for {
			buf, err := r.ReadString('\n')
			line += buf
			if err == io.EOF {
				break
			} else if err == nil {
				cb(strings.TrimSpace(line))
				line = ""
			}
		}
		f.Seek(0, os.SEEK_END) // catch when file is truncated
	}
}

func notify(b *bot.Bot, line string) {
	if !b.Conn.Connected() {
		return
	}
	for _, channel := range b.Conn.Me().Channels() {
		b.Conn.Privmsg(channel.Name, line)
	}
}

// Register registers the plugin with a bot.
func Register(b *bot.Bot, paths []string) {
	for _, path := range paths {
		go Tail(path, func(line string) { notify(b, line) })
	}
}
<commit_msg>plugins: tail: minor changes<commit_after>// Package tail implements a plugin to tail files and notify new lines on all channels.
package tail

import (
	"bufio"
	"io"
	"log"
	"os"
	"strings"
	"time"

	"github.com/StalkR/goircbot/bot"
)

// Tail watches a file and calls notify for every new line.
// File can be truncated but it does not detect if file is renamed.
func Tail(path string, notify func(string)) {
	var f *os.File
	for ; ; time.Sleep(time.Minute) {
		fp, err := os.Open(path)
		if err == nil {
			f = fp
			break
		}
		log.Println("tail: error open", path, err)
	}
	defer f.Close()

	r := bufio.NewReader(f)
	for {
		if _, err := r.ReadString('\n'); err != nil {
			break
		}
	}
	var line string
	for ; ; time.Sleep(time.Second) {
		for {
			buf, err := r.ReadString('\n')
			line += buf
			if err == io.EOF {
				break
			} else if err == nil {
				notify(strings.TrimSpace(line))
				line = ""
			}
		}
		f.Seek(0, os.SEEK_END) // catch when file is truncated
	}
}

func notify(b *bot.Bot, line string) {
	if !b.Conn.Connected() {
		return
	}
	for _, channel := range b.Conn.Me().Channels() {
		b.Conn.Privmsg(channel.Name, line)
	}
}

// Register registers the plugin with a bot.
func Register(b *bot.Bot, paths []string) {
	for _, path := range paths {
		go Tail(path, func(line string) { notify(b, line) })
	}
}
<|endoftext|>


<commit_before>/*
 * MinIO Cloud Storage, (C) 2019 MinIO, Inc.
 *
 * 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 cmd

import (
	"bytes"
	"context"
	"encoding/hex"
	"fmt"
	"hash"
	"io"
	"time"

	"github.com/minio/minio/cmd/logger"
	"github.com/minio/minio/pkg/env"
	xioutil "github.com/minio/minio/pkg/ioutil"
)

type errHashMismatch struct {
	message string
}

func (err *errHashMismatch) Error() string {
	return err.message
}

// Calculates bitrot in chunks and writes the hash into the stream.
type streamingBitrotWriter struct {
	iow       io.WriteCloser
	h         hash.Hash
	shardSize int64
	canClose  chan struct{} // Needed to avoid race explained in Close() call.
}

func (b *streamingBitrotWriter) Write(p []byte) (int, error) {
	if len(p) == 0 {
		return 0, nil
	}
	b.h.Reset()
	b.h.Write(p)
	hashBytes := b.h.Sum(nil)
	_, err := b.iow.Write(hashBytes)
	if err != nil {
		return 0, err
	}
	return b.iow.Write(p)
}

func (b *streamingBitrotWriter) Close() error {
	err := b.iow.Close()
	// Wait for all data to be written before returning else it causes race conditions.
	// Race condition is because of io.PipeWriter implementation. i.e consider the following
	// sequent of operations:
	// 1) pipe.Write()
	// 2) pipe.Close()
	// Now pipe.Close() can return before the data is read on the other end of the pipe and written to the disk
	// Hence an immediate Read() on the file can return incorrect data.
	<-b.canClose
	return err
}

var (
	ioDeadline, _ = time.ParseDuration(env.Get("MINIO_IO_DEADLINE", ""))
)

// Returns streaming bitrot writer implementation.
func newStreamingBitrotWriter(disk StorageAPI, volume, filePath string, length int64, algo BitrotAlgorithm, shardSize int64, heal bool) io.Writer {
	r, w := io.Pipe()
	h := algo.New()

	var wc io.WriteCloser = w
	if ioDeadline > 0 && !heal {
		wc = xioutil.NewDeadlineWriter(w, ioDeadline)
	}

	bw := &streamingBitrotWriter{wc, h, shardSize, make(chan struct{})}
	go func() {
		totalFileSize := int64(-1) // For compressed objects length will be unknown (represented by length=-1)
		if length != -1 {
			bitrotSumsTotalSize := ceilFrac(length, shardSize) * int64(h.Size()) // Size used for storing bitrot checksums.
			totalFileSize = bitrotSumsTotalSize + length
		}
		r.CloseWithError(disk.CreateFile(context.TODO(), volume, filePath, totalFileSize, r))
		close(bw.canClose)
	}()
	return bw
}

// ReadAt() implementation which verifies the bitrot hash available as part of the stream.
type streamingBitrotReader struct {
	disk       StorageAPI
	data       []byte
	rc         io.Reader
	volume     string
	filePath   string
	tillOffset int64
	currOffset int64
	h          hash.Hash
	shardSize  int64
	hashBytes  []byte
}

func (b *streamingBitrotReader) Close() error {
	if b.rc == nil {
		return nil
	}
	if closer, ok := b.rc.(io.Closer); ok {
		return closer.Close()
	}
	return nil
}

func (b *streamingBitrotReader) ReadAt(buf []byte, offset int64) (int, error) {
	var err error
	if offset%b.shardSize != 0 {
		// Offset should always be aligned to b.shardSize
		// Can never happen unless there are programmer bugs
		return 0, errUnexpected
	}
	if b.rc == nil {
		// For the first ReadAt() call we need to open the stream for reading.
		b.currOffset = offset
		streamOffset := (offset/b.shardSize)*int64(b.h.Size()) + offset
		if len(b.data) == 0 {
			b.rc, err = b.disk.ReadFileStream(context.TODO(), b.volume, b.filePath, streamOffset, b.tillOffset-streamOffset)
		} else {
			b.rc = io.NewSectionReader(bytes.NewReader(b.data), streamOffset, b.tillOffset-streamOffset)
		}
		if err != nil {
			return 0, err
		}
	}

	if offset != b.currOffset {
		// Can never happen unless there are programmer bugs
		return 0, errUnexpected
	}
	b.h.Reset()
	_, err = io.ReadFull(b.rc, b.hashBytes)
	if err != nil {
		return 0, err
	}
	_, err = io.ReadFull(b.rc, buf)
	if err != nil {
		return 0, err
	}
	b.h.Write(buf)

	if !bytes.Equal(b.h.Sum(nil), b.hashBytes) {
		logger.LogIf(GlobalContext, fmt.Errorf("Disk: %s  -> %s/%s - content hash does not match - expected %s, got %s",
			b.disk, b.volume, b.filePath, hex.EncodeToString(b.hashBytes), hex.EncodeToString(b.h.Sum(nil))))
		return 0, errFileCorrupt
	}
	b.currOffset += int64(len(buf))
	return len(buf), nil
}

// Returns streaming bitrot reader implementation.
func newStreamingBitrotReader(disk StorageAPI, data []byte, volume, filePath string, tillOffset int64, algo BitrotAlgorithm, shardSize int64) *streamingBitrotReader {
	h := algo.New()
	return &streamingBitrotReader{
		disk,
		data,
		nil,
		volume,
		filePath,
		ceilFrac(tillOffset, shardSize)*int64(h.Size()) + tillOffset,
		0,
		h,
		shardSize,
		make([]byte, h.Size()),
	}
}
<commit_msg>remove MINIO_IO_DEADLINE support (#11841)<commit_after>/*
 * MinIO Cloud Storage, (C) 2019 MinIO, Inc.
 *
 * 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 cmd

import (
	"bytes"
	"context"
	"encoding/hex"
	"fmt"
	"hash"
	"io"

	"github.com/minio/minio/cmd/logger"
)

type errHashMismatch struct {
	message string
}

func (err *errHashMismatch) Error() string {
	return err.message
}

// Calculates bitrot in chunks and writes the hash into the stream.
type streamingBitrotWriter struct {
	iow       io.WriteCloser
	h         hash.Hash
	shardSize int64
	canClose  chan struct{} // Needed to avoid race explained in Close() call.
}

func (b *streamingBitrotWriter) Write(p []byte) (int, error) {
	if len(p) == 0 {
		return 0, nil
	}
	b.h.Reset()
	b.h.Write(p)
	hashBytes := b.h.Sum(nil)
	_, err := b.iow.Write(hashBytes)
	if err != nil {
		return 0, err
	}
	return b.iow.Write(p)
}

func (b *streamingBitrotWriter) Close() error {
	err := b.iow.Close()
	// Wait for all data to be written before returning else it causes race conditions.
	// Race condition is because of io.PipeWriter implementation. i.e consider the following
	// sequent of operations:
	// 1) pipe.Write()
	// 2) pipe.Close()
	// Now pipe.Close() can return before the data is read on the other end of the pipe and written to the disk
	// Hence an immediate Read() on the file can return incorrect data.
	<-b.canClose
	return err
}

// Returns streaming bitrot writer implementation.
func newStreamingBitrotWriter(disk StorageAPI, volume, filePath string, length int64, algo BitrotAlgorithm, shardSize int64, heal bool) io.Writer {
	r, w := io.Pipe()
	h := algo.New()

	bw := &streamingBitrotWriter{w, h, shardSize, make(chan struct{})}
	go func() {
		totalFileSize := int64(-1) // For compressed objects length will be unknown (represented by length=-1)
		if length != -1 {
			bitrotSumsTotalSize := ceilFrac(length, shardSize) * int64(h.Size()) // Size used for storing bitrot checksums.
			totalFileSize = bitrotSumsTotalSize + length
		}
		r.CloseWithError(disk.CreateFile(context.TODO(), volume, filePath, totalFileSize, r))
		close(bw.canClose)
	}()
	return bw
}

// ReadAt() implementation which verifies the bitrot hash available as part of the stream.
type streamingBitrotReader struct {
	disk       StorageAPI
	data       []byte
	rc         io.Reader
	volume     string
	filePath   string
	tillOffset int64
	currOffset int64
	h          hash.Hash
	shardSize  int64
	hashBytes  []byte
}

func (b *streamingBitrotReader) Close() error {
	if b.rc == nil {
		return nil
	}
	if closer, ok := b.rc.(io.Closer); ok {
		return closer.Close()
	}
	return nil
}

func (b *streamingBitrotReader) ReadAt(buf []byte, offset int64) (int, error) {
	var err error
	if offset%b.shardSize != 0 {
		// Offset should always be aligned to b.shardSize
		// Can never happen unless there are programmer bugs
		return 0, errUnexpected
	}
	if b.rc == nil {
		// For the first ReadAt() call we need to open the stream for reading.
		b.currOffset = offset
		streamOffset := (offset/b.shardSize)*int64(b.h.Size()) + offset
		if len(b.data) == 0 {
			b.rc, err = b.disk.ReadFileStream(context.TODO(), b.volume, b.filePath, streamOffset, b.tillOffset-streamOffset)
		} else {
			b.rc = io.NewSectionReader(bytes.NewReader(b.data), streamOffset, b.tillOffset-streamOffset)
		}
		if err != nil {
			return 0, err
		}
	}

	if offset != b.currOffset {
		// Can never happen unless there are programmer bugs
		return 0, errUnexpected
	}
	b.h.Reset()
	_, err = io.ReadFull(b.rc, b.hashBytes)
	if err != nil {
		return 0, err
	}
	_, err = io.ReadFull(b.rc, buf)
	if err != nil {
		return 0, err
	}
	b.h.Write(buf)

	if !bytes.Equal(b.h.Sum(nil), b.hashBytes) {
		logger.LogIf(GlobalContext, fmt.Errorf("Disk: %s  -> %s/%s - content hash does not match - expected %s, got %s",
			b.disk, b.volume, b.filePath, hex.EncodeToString(b.hashBytes), hex.EncodeToString(b.h.Sum(nil))))
		return 0, errFileCorrupt
	}
	b.currOffset += int64(len(buf))
	return len(buf), nil
}

// Returns streaming bitrot reader implementation.
func newStreamingBitrotReader(disk StorageAPI, data []byte, volume, filePath string, tillOffset int64, algo BitrotAlgorithm, shardSize int64) *streamingBitrotReader {
	h := algo.New()
	return &streamingBitrotReader{
		disk,
		data,
		nil,
		volume,
		filePath,
		ceilFrac(tillOffset, shardSize)*int64(h.Size()) + tillOffset,
		0,
		h,
		shardSize,
		make([]byte, h.Size()),
	}
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	// "github.com/gorilla/websocket"
	"github.com/zballs/go_resonate/bigchain"
	"github.com/zballs/go_resonate/coala"
	"github.com/zballs/go_resonate/types"
	. "github.com/zballs/go_resonate/util"
	"net/http"
)

type Api struct {
	logger types.Logger
	priv   *PrivateKey
	pub    *PublicKey
	user   *types.User
	userId string
}

func NewApi() *Api {
	return &Api{
		logger: types.NewLogger("api"),
	}
}

func (api *Api) AddRoutes(mux *http.ServeMux) {
	mux.HandleFunc("/login", api.Login)
	mux.HandleFunc("/new_project", api.NewProject)
	mux.HandleFunc("/register_user", api.RegisterUser)
}

func Respond(w http.ResponseWriter, response interface{}) {
	json := MarshalJSON(response)
	w.Header().Set("Content-Type", "application/json")
	_, err := w.Write(json)
	Check(err)
}

func (api *Api) RegisterUser(w http.ResponseWriter, req *http.Request) {
	// Should be POST request
	if req.Method != http.MethodPost {
		http.Error(w, fmt.Sprintf("Expected POST request; got %s request", req.Method), http.StatusBadRequest)
		return
	}
	// Get request data
	values, err := UrlValues(req)
	if err != nil {
		http.Error(w, "Failed to read request data", http.StatusBadRequest)
		return
	}
	email := values.Get("email")
	password := values.Get("password")
	_type := values.Get("type")
	username := values.Get("username")
	// New user
	user := types.NewUser(email, password, username, _type)
	// Generate keypair from password
	priv, pub := GenerateKeypair(password)
	data := make(map[string]interface{})
	// Sign user bytes
	json := MarshalJSON(user)
	data["user_signature"] = priv.Sign(json).ToB58()
	// send request to IPDB
	t := bigchain.GenerateTransaction(data, pub)
	t.Fulfill(priv, pub)
	fmt.Println(string(MarshalJSON(t)))
	id, err := bigchain.PostTransaction(t)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	userInfo := NewUserInfo(id, priv, pub)
	Respond(w, userInfo)
}

func (api *Api) Login(w http.ResponseWriter, req *http.Request) {
	// Should be POST request
	if req.Method != http.MethodPost {
		http.Error(w, fmt.Sprintf("Expected POST request; got %s request", req.Method), http.StatusBadRequest)
		return
	}
	// Get request data
	values, err := UrlValues(req)
	if err != nil {
		http.Error(w, "Failed to read request data", http.StatusBadRequest)
		return
	}
	// PrivKey
	priv := new(PrivateKey)
	keystr := values.Get("private_key")
	if err = priv.FromB58(keystr); err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	// User Id
	userId := values.Get("user_id")
	// Check that transaction with id exists
	t, err := bigchain.GetTransaction(userId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	// Get user signature
	data := t.GetData()
	sig := new(Signature)
	if err := sig.FromB58(data["user_signature"].(string)); err != nil {
		http.Error(w, Error("Failed to verify user signature").Error(), http.StatusUnauthorized)
		return
	}
	// User
	email := values.Get("email")
	password := values.Get("password")
	_type := values.Get("type")
	username := values.Get("username")
	// New user
	user := types.NewUser(email, username, password, _type)
	json := MarshalJSON(user)
	pub := priv.Public()
	if !pub.Verify(json, sig) {
		http.Error(w, Error("Failed to verify user signature").Error(), http.StatusUnauthorized)
		return
	}
	api.priv = priv
	api.pub = pub
	api.user = user
	api.userId = userId
	Respond(w, "Logged in!")
}

func (api *Api) NewProject(w http.ResponseWriter, req *http.Request) {
	// Should be POST request
	if req.Method != http.MethodPost {
		http.Error(w, fmt.Sprintf("Expected POST request; got %s request", req.Method), http.StatusBadRequest)
		return
	}
	// Make sure we're logged in
	if api.priv == nil {
		http.Error(w, "Privkey is not set", http.StatusUnauthorized)
		return
	}
	if api.pub == nil {
		http.Error(w, "Pubkey is not set", http.StatusUnauthorized)
		return
	}
	if api.user == nil {
		http.Error(w, "User is not set", http.StatusUnauthorized)
		return
	}
	if api.userId == "" {
		http.Error(w, "User Id is not set", http.StatusUnauthorized)
		return
	}
	// Get request data
	form, err := MultipartForm(req)
	if err != nil {
		http.Error(w, "Failed to read request data", http.StatusBadRequest)
		return
	}
	// Name of the project
	name := form.Value["name"][0]
	// Create new work
	data := coala.NewWork("", name, api.user.Name)
	// Generate and send transaction to IPDB
	t := bigchain.GenerateTransaction(data, api.pub)
	t.Fulfill(api.priv, api.pub)
	projectId, err := bigchain.PostTransaction(t)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	// Just one song for now
	// .. Eventually iterate through list of songs
	name = form.Value["names"][0]
	place := form.Value["place"][0]
	// Should we have example, as specified in coalaip??
	// .. What should url be?
	data = coala.NewDigitalManifestation("", name, "", true, projectId, DateString(), place, req.RemoteAddr)
	// Generate and send transaction to IPDB
	t = bigchain.GenerateTransaction(data, api.pub)
	songId, err := bigchain.PostTransaction(t)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	// TODO: save project_id and song_ids to disk
	projectInfo := NewProjectInfo(projectId, []string{songId})
	Respond(w, projectInfo)
}
<commit_msg>streaming<commit_after>package api

import (
	"github.com/zballs/go_resonate/bigchain"
	"github.com/zballs/go_resonate/coala"
	"github.com/zballs/go_resonate/types"
	. "github.com/zballs/go_resonate/util"
	"net/http"
	"os"
	"strings"
)

type Api struct {
	logger types.Logger
	priv   *PrivateKey
	pub    *PublicKey
	serv   *types.HttpService
	user   *types.User
	userId string
}

func NewApi() *Api {
	return &Api{
		logger: types.NewLogger("api"),
	}
}

func (api *Api) Configure(dir string, mux *http.ServeMux) {
	mux.HandleFunc("/new_project", api.NewProject)
	mux.HandleFunc("/user_login", api.UserLogin)
	mux.HandleFunc("/user_register", api.UserRegister)
	api.serv = types.NewHttpService(dir, mux)
}

func Respond(w http.ResponseWriter, response interface{}) {
	json := MarshalJSON(response)
	w.Header().Set("Content-Type", "application/json")
	w.Write(json)
}

func (api *Api) UserRegister(w http.ResponseWriter, req *http.Request) {
	// Should be POST request
	if req.Method != http.MethodPost {
		http.Error(w, Sprintf("Expected POST request; got %s request", req.Method), http.StatusBadRequest)
		return
	}
	// Get request data
	values, err := UrlValues(req)
	if err != nil {
		http.Error(w, "Failed to read request data", http.StatusBadRequest)
		return
	}
	email := values.Get("email")
	password := values.Get("password")
	_type := values.Get("type")
	username := values.Get("username")
	// New user
	user := types.NewUser(email, password, username, _type)
	// Generate keypair from password
	priv, pub := GenerateKeypair(password)
	data := make(map[string]interface{})
	// Sign user bytes
	json := MarshalJSON(user)
	data["user_signature"] = priv.Sign(json).ToB58()
	// send request to IPDB
	t := bigchain.GenerateTransaction(data, pub)
	t.Fulfill(priv, pub)
	Println(string(MarshalJSON(t)))
	id, err := bigchain.PostTransaction(t)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	userInfo := NewUserInfo(id, priv, pub)
	Respond(w, userInfo)
}

func (api *Api) UserLogin(w http.ResponseWriter, req *http.Request) {
	// Should be POST request
	if req.Method != http.MethodPost {
		http.Error(w, Sprintf("Expected POST request; got %s request", req.Method), http.StatusBadRequest)
		return
	}
	// Get request data
	values, err := UrlValues(req)
	if err != nil {
		http.Error(w, "Failed to read request data", http.StatusBadRequest)
		return
	}
	// PrivKey
	priv := new(PrivateKey)
	keystr := values.Get("private_key")
	if err = priv.FromB58(keystr); err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	// User Id
	userId := values.Get("user_id")
	// Check that transaction with id exists
	t, err := bigchain.GetTransaction(userId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	// Get user signature
	data := t.GetData()
	sig := new(Signature)
	if err := sig.FromB58(data["user_signature"].(string)); err != nil {
		http.Error(w, Error("Failed to verify user signature").Error(), http.StatusUnauthorized)
		return
	}
	// User
	email := values.Get("email")
	password := values.Get("password")
	_type := values.Get("type")
	username := values.Get("username")
	// New user
	user := types.NewUser(email, username, password, _type)
	json := MarshalJSON(user)
	pub := priv.Public()
	if !pub.Verify(json, sig) {
		http.Error(w, Error("Failed to verify user signature").Error(), http.StatusUnauthorized)
		return
	}
	api.priv = priv
	api.pub = pub
	api.user = user
	api.userId = userId
	Respond(w, "Logged in!")
}

func (api *Api) NewProject(w http.ResponseWriter, req *http.Request) {
	// Should be POST request
	if req.Method != http.MethodPost {
		http.Error(w, Sprintf("Expected POST request; got %s request", req.Method), http.StatusBadRequest)
		return
	}
	// Make sure we're logged in
	if api.priv == nil {
		http.Error(w, "Privkey is not set", http.StatusUnauthorized)
		return
	}
	if api.pub == nil {
		http.Error(w, "Pubkey is not set", http.StatusUnauthorized)
		return
	}
	if api.user == nil {
		http.Error(w, "User is not set", http.StatusUnauthorized)
		return
	}
	if api.userId == "" {
		http.Error(w, "User Id is not set", http.StatusUnauthorized)
		return
	}
	// Get request data
	form, err := MultipartForm(req)
	if err != nil {
		http.Error(w, "Failed to read request data", http.StatusBadRequest)
		return
	}
	// Project title
	projectTitle := form.Value["project_title"][0]
	// Create new work
	data := coala.NewWork(projectTitle, api.user.Name)
	// Generate and send transaction to IPDB
	t := bigchain.GenerateTransaction(data, api.pub)
	t.Fulfill(api.priv, api.pub)
	projectId, err := bigchain.PostTransaction(t)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	projectPlace := form.Value["project_place"][0]
	songs := form.File["songs"]
	songIds := make([]string, len(songs))
	for i, song := range songs {
		songTitle := strings.SplitN(song.Filename, ".", 2)[0]
		// What should example and url be?
		data = coala.NewDigitalManifestation(songTitle, "", true, projectId, DateString(), projectPlace, req.RemoteAddr)
		// Generate and send transaction to IPDB
		t = bigchain.GenerateTransaction(data, api.pub)
		songIds[i], err = bigchain.PostTransaction(t)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		// Store file
		path := api.serv.Path(projectTitle, song.Filename)
		file, err := os.Create(path)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		_file, err := song.Open()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		Copy(file, _file)
	}
	projectInfo := NewProjectInfo(projectId, songIds)
	Respond(w, projectInfo)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	rest "github.com/emicklei/go-restful"
)

func main() {
	// Create the storage directories on disk
	err := os.MkdirAll(filepath.Join(STORAGEDIR, "files"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the files dir: %v\n", err.Error())
		return
	}
	err = os.MkdirAll(filepath.Join(STORAGEDIR, "meta"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the meta dir: %v\n", err.Error())
		return
	}

	// Create and start the API server
	ws := new(rest.WebService)
	ws.Filter(rest.NoBrowserCacheFilter)
	ws.Route(ws.GET("/branch_history").To(branchHistory))
	ws.Route(ws.GET("/branch_list").To(branchList))
	ws.Route(ws.PUT("/db_upload").To(dbUpload))
	ws.Route(ws.GET("/db_download").To(dbDownload))
	ws.Route(ws.GET("/db_list").To(dbList))
	rest.Add(ws)
	http.ListenAndServe(":8080", nil)
}

// Returns the history for a branch.
// Can be tested with: curl -H "Name: a.db" -H "Branch: master" http://localhost:8080/branch_history
func branchHistory(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Name")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the requested branch exists in the database
	id, ok := branches[branchName]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Walk the commit history, assembling it into something useful
	var history []commit
	c, err := getCommit(id)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	history = append(history, c)
	for c.Parent != "" {
		c, err = getCommit(c.Parent)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		history = append(history, c)
	}
	w.WriteAsJson(history)
}

// Returns the list of branch heads for a database.
// Can be tested with: curl -H "Name: a.db" http://localhost:8080/branch_list
func branchList(r *rest.Request, w *rest.Response) {
	// Retrieve the database name
	dbName := r.Request.Header.Get("Name")

	// TODO: Validate the database name

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Return the list of branch heads
	w.WriteAsJson(branches)
}

// Upload a database.
// Can be tested with: curl -T a.db -H "Name: a.db" -w \%{response_code} -D headers.out http://localhost:8080/db_upload
func dbUpload(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Name")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Default to "master" if no branch name was given
	if branchName == "" {
		branchName = "master"
	}

	// Read the database into a buffer
	var buf bytes.Buffer
	buf.ReadFrom(r.Request.Body)
	sha := sha256.Sum256(buf.Bytes())

	// Create a dbTree entry for the individual database file
	var e dbTreeEntry
	e.AType = DATABASE
	e.Sha256 = hex.EncodeToString(sha[:])
	e.Name = dbName
	e.Last_Modified = time.Now()
	e.Size = buf.Len()

	// Create a dbTree structure for the database entry
	var t dbTree
	t.Entries = append(t.Entries, e)
	t.ID = createDBTreeID(t.Entries)

	// Construct a commit structure pointing to the tree
	var c commit
	c.AuthorEmail = "justin@postgresql.org" // TODO: Author and Committer info should come from the client, so we
	c.AuthorName = "Justin Clift"           // TODO  hard code these for now.  Proper auth will need adding later
	c.Timestamp = time.Now()                // TODO: Would it be better to accept a timestamp from the client?
	c.Tree = t.ID

	// Check if the database already exists
	var err error
	var branches map[string]string
	if dbExists(dbName) {
		// Load the existing branchHeads from disk
		branches, err = getBranches(dbName)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// We check if the desired branch already exists.  If it does, we use the commit ID from that as the
		// "parent" for our new commit.  Then we update the branch with the commit created for this new
		// database upload
		if id, ok := branches[branchName]; ok {
			c.Parent = id
		}
		c.ID = createCommitID(c)
		branches[branchName] = c.ID
	} else {
		// No existing branches, so this will be the first
		c.ID = createCommitID(c)
		branches = make(map[string]string)
		branches[branchName] = c.ID
	}

	// Write the database to disk
	err = storeDatabase(buf.Bytes())
	if err != nil {
		log.Printf("Error when writing database '%s' to disk: %v\n", dbName, err.Error())

		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the tree to disk
	err = storeTree(t)
	if err != nil {
		log.Printf("Something went wrong when storing the tree file: %v\n", err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the commit to disk
	err = storeCommit(c)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the updated branchHeads to disk
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Log the upload
	log.Printf("Database uploaded.  Name: '%s', size: %d bytes, branch: '%s'\n", dbName, buf.Len(),
		branchName)

	// Send a 201 "Created" response, along with the location of the URL for working with the (new) database
	w.AddHeader("Location", "/"+dbName)
	w.WriteHeader(http.StatusCreated)
}

// Download a database
func dbDownload(r *rest.Request, w *rest.Response) {
	log.Println("dbDownload() called")
}

// Get a list of databases
func dbList(r *rest.Request, w *rest.Response) {
	log.Println("dbList() called")
}
<commit_msg>Creating new branches (/branch_create) now works<commit_after>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	rest "github.com/emicklei/go-restful"
)

func main() {
	// Create the storage directories on disk
	err := os.MkdirAll(filepath.Join(STORAGEDIR, "files"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the files dir: %v\n", err.Error())
		return
	}
	err = os.MkdirAll(filepath.Join(STORAGEDIR, "meta"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the meta dir: %v\n", err.Error())
		return
	}

	// Create and start the API server
	ws := new(rest.WebService)
	ws.Filter(rest.NoBrowserCacheFilter)
	ws.Route(ws.POST("/branch_create").Consumes("application/x-www-form-urlencoded").To(branchCreate))
	ws.Route(ws.GET("/branch_history").To(branchHistory))
	ws.Route(ws.GET("/branch_list").To(branchList))
	ws.Route(ws.PUT("/db_upload").To(dbUpload))
	ws.Route(ws.GET("/db_download").To(dbDownload))
	ws.Route(ws.GET("/db_list").To(dbList))
	rest.Add(ws)
	http.ListenAndServe(":8080", nil)
}

// Creates a new branch for a database.
// Can be tested with: curl -d database=a.db -d from-branch=master -d new-branch=mynewbranch http://localhost:8080/branch_create
func branchCreate(r *rest.Request, w *rest.Response) {
	// We do this such that a branch can only fork from an existing branch head of the database. The alternative
	// would be to allow giving a direct commit ID for branching from, but that seems like it would be a security
	// problem due to being able to potentially point at other people's commits in our multi-user environment

	// Retrieve the database and branch names
	err := r.Request.ParseForm()
	if err != nil {
		w.WriteErrorString(http.StatusBadRequest, err.Error())
		return
	}
	dbName := r.Request.FormValue("database")
	fromBranch := r.Request.FormValue("from-branch")
	newBranch := r.Request.FormValue("new-branch")

	// Sanity check the inputs
	if dbName == "" || fromBranch == "" || newBranch == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// TODO: Validate the database and branch names

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the "from" branch exists in the database
	fromId, ok := branches[fromBranch]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Ensure the new branch doesn't already exist in the database
	_, ok = branches[newBranch]
	if ok {
		w.WriteHeader(http.StatusConflict)
		return
	}

	// Add the new branch
	branches[newBranch] = fromId
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// Returns the history for a branch.
// Can be tested with: curl -H "Database: a.db" -H "Branch: master" http://localhost:8080/branch_history
func branchHistory(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Database")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the requested branch exists in the database
	id, ok := branches[branchName]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Walk the commit history, assembling it into something useful
	var history []commit
	c, err := getCommit(id)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	history = append(history, c)
	for c.Parent != "" {
		c, err = getCommit(c.Parent)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		history = append(history, c)
	}
	w.WriteAsJson(history)
}

// Returns the list of branch heads for a database.
// Can be tested with: curl -H "Database: a.db" http://localhost:8080/branch_list
func branchList(r *rest.Request, w *rest.Response) {
	// Retrieve the database name
	dbName := r.Request.Header.Get("Database")

	// TODO: Validate the database name

	// Sanity check the input
	if dbName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Return the list of branch heads
	w.WriteAsJson(branches)
}

// Upload a database.
// Can be tested with: curl -T a.db -H "Name: a.db" -w \%{response_code} -D headers.out http://localhost:8080/db_upload
func dbUpload(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Name")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Default to "master" if no branch name was given
	if branchName == "" {
		branchName = "master"
	}

	// Read the database into a buffer
	var buf bytes.Buffer
	buf.ReadFrom(r.Request.Body)
	sha := sha256.Sum256(buf.Bytes())

	// Create a dbTree entry for the individual database file
	var e dbTreeEntry
	e.AType = DATABASE
	e.Sha256 = hex.EncodeToString(sha[:])
	e.Name = dbName
	e.Last_Modified = time.Now()
	e.Size = buf.Len()

	// Create a dbTree structure for the database entry
	var t dbTree
	t.Entries = append(t.Entries, e)
	t.ID = createDBTreeID(t.Entries)

	// Construct a commit structure pointing to the tree
	var c commit
	c.AuthorEmail = "justin@postgresql.org" // TODO: Author and Committer info should come from the client, so we
	c.AuthorName = "Justin Clift"           // TODO  hard code these for now.  Proper auth will need adding later
	c.Timestamp = time.Now()                // TODO: Would it be better to accept a timestamp from the client?
	c.Tree = t.ID

	// Check if the database already exists
	var err error
	var branches map[string]string
	if dbExists(dbName) {
		// Load the existing branchHeads from disk
		branches, err = getBranches(dbName)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// We check if the desired branch already exists.  If it does, we use the commit ID from that as the
		// "parent" for our new commit.  Then we update the branch with the commit created for this new
		// database upload
		if id, ok := branches[branchName]; ok {
			c.Parent = id
		}
		c.ID = createCommitID(c)
		branches[branchName] = c.ID
	} else {
		// No existing branches, so this will be the first
		c.ID = createCommitID(c)
		branches = make(map[string]string)
		branches[branchName] = c.ID
	}

	// Write the database to disk
	err = storeDatabase(buf.Bytes())
	if err != nil {
		log.Printf("Error when writing database '%s' to disk: %v\n", dbName, err.Error())

		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the tree to disk
	err = storeTree(t)
	if err != nil {
		log.Printf("Something went wrong when storing the tree file: %v\n", err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the commit to disk
	err = storeCommit(c)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the updated branch heads to disk
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Log the upload
	log.Printf("Database uploaded.  Name: '%s', size: %d bytes, branch: '%s'\n", dbName, buf.Len(),
		branchName)

	// Send a 201 "Created" response, along with the location of the URL for working with the (new) database
	w.AddHeader("Location", "/"+dbName)
	w.WriteHeader(http.StatusCreated)
}

// Download a database
func dbDownload(r *rest.Request, w *rest.Response) {
	log.Println("dbDownload() called")
}

// Get a list of databases
func dbList(r *rest.Request, w *rest.Response) {
	log.Println("dbList() called")
}
<|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.

// Parse input AST and prepare Prog structure.

package main

import (
	"fmt"
	"go/ast"
	"go/doc"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
	"strings"
)

func parse(name string, flags uint) *ast.File {
	ast1, err := parser.ParseFile(fset, name, nil, flags)
	if err != nil {
		if list, ok := err.(scanner.ErrorList); ok {
			// If err is a scanner.ErrorList, its String will print just
			// the first error and then (+n more errors).
			// Instead, turn it into a new Error that will return
			// details for all the errors.
			for _, e := range list {
				fmt.Fprintln(os.Stderr, e)
			}
			os.Exit(2)
		}
		fatal("parsing %s: %s", name, err)
	}
	return ast1
}

// ReadGo populates f with information learned from reading the
// Go source file with the given file name.  It gathers the C preamble
// attached to the import "C" comment, a list of references to C.xxx,
// a list of exported functions, and the actual AST, to be rewritten and
// printed.
func (f *File) ReadGo(name string) {
	// Two different parses: once with comments, once without.
	// The printer is not good enough at printing comments in the
	// right place when we start editing the AST behind its back,
	// so we use ast1 to look for the doc comments on import "C"
	// and on exported functions, and we use ast2 for translating
	// and reprinting.
	ast1 := parse(name, parser.ParseComments)
	ast2 := parse(name, 0)

	f.Package = ast1.Name.Name
	f.Name = make(map[string]*Name)

	// In ast1, find the import "C" line and get any extra C preamble.
	sawC := false
	for _, decl := range ast1.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			continue
		}
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				continue
			}
			sawC = true
			if s.Name != nil {
				error(s.Path.Pos(), `cannot rename import "C"`)
			}
			if s.Doc != nil {
				f.Preamble += doc.CommentText(s.Doc) + "\n"
			} else if len(d.Specs) == 1 && d.Doc != nil {
				f.Preamble += doc.CommentText(d.Doc) + "\n"
			}
		}
	}
	if !sawC {
		error(token.NoPos, `cannot find import "C"`)
	}

	// In ast2, strip the import "C" line.
	w := 0
	for _, decl := range ast2.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			ast2.Decls[w] = decl
			w++
			continue
		}
		ws := 0
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				d.Specs[ws] = spec
				ws++
			}
		}
		if ws == 0 {
			continue
		}
		d.Specs = d.Specs[0:ws]
		ast2.Decls[w] = d
		w++
	}
	ast2.Decls = ast2.Decls[0:w]

	// Accumulate pointers to uses of C.x.
	if f.Ref == nil {
		f.Ref = make([]*Ref, 0, 8)
	}
	f.walk(ast2, "prog", (*File).saveRef)

	// Accumulate exported functions.
	// The comments are only on ast1 but we need to
	// save the function bodies from ast2.
	// The first walk fills in ExpFunc, and the
	// second walk changes the entries to
	// refer to ast2 instead.
	f.walk(ast1, "prog", (*File).saveExport)
	f.walk(ast2, "prog", (*File).saveExport2)

	f.AST = ast2
}

// Save references to C.xxx for later processing.
func (f *File) saveRef(x interface{}, context string) {
	n, ok := x.(*ast.Expr)
	if !ok {
		return
	}
	if sel, ok := (*n).(*ast.SelectorExpr); ok {
		// For now, assume that the only instance of capital C is
		// when used as the imported package identifier.
		// The parser should take care of scoping in the future,
		// so that we will be able to distinguish a "top-level C"
		// from a local C.
		if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
			if context == "as2" {
				context = "expr"
			}
			goname := sel.Sel.Name
			name := f.Name[goname]
			if name == nil {
				name = &Name{
					Go: goname,
				}
				f.Name[goname] = name
			}
			f.Ref = append(f.Ref, &Ref{
				Name:    name,
				Expr:    n,
				Context: context,
			})
			return
		}
	}
}

// If a function should be exported add it to ExpFunc.
func (f *File) saveExport(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	if n.Doc == nil {
		return
	}
	for _, c := range n.Doc.List {
		if string(c.Text[0:9]) != "//export " {
			continue
		}

		name := strings.TrimSpace(string(c.Text[9:]))
		if name == "" {
			error(c.Pos(), "export missing name")
		}

		f.ExpFunc = append(f.ExpFunc, &ExpFunc{
			Func:    n,
			ExpName: name,
		})
		break
	}
}

// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
func (f *File) saveExport2(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	for _, exp := range f.ExpFunc {
		if exp.Func.Name.Name == n.Name.Name {
			exp.Func = n
			break
		}
	}
}

// walk walks the AST x, calling visit(f, x, context) for each node.
func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
	visit(f, x, context)
	switch n := x.(type) {
	case *ast.Expr:
		f.walk(*n, context, visit)

	// everything else just recurs
	default:
		error(token.NoPos, "unexpected type %T in walk", x, visit)
		panic("unexpected type")

	case nil:

	// These are ordered and grouped to match ../../pkg/go/ast/ast.go
	case *ast.Field:
		f.walk(&n.Type, "type", visit)
	case *ast.FieldList:
		for _, field := range n.List {
			f.walk(field, context, visit)
		}
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.Ellipsis:
	case *ast.BasicLit:
	case *ast.FuncLit:
		f.walk(n.Type, "type", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.CompositeLit:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Elts, "expr", visit)
	case *ast.ParenExpr:
		f.walk(&n.X, context, visit)
	case *ast.SelectorExpr:
		f.walk(&n.X, "selector", visit)
	case *ast.IndexExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Index, "expr", visit)
	case *ast.SliceExpr:
		f.walk(&n.X, "expr", visit)
		if n.Low != nil {
			f.walk(&n.Low, "expr", visit)
		}
		if n.High != nil {
			f.walk(&n.High, "expr", visit)
		}
	case *ast.TypeAssertExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Type, "type", visit)
	case *ast.CallExpr:
		if context == "as2" {
			f.walk(&n.Fun, "call2", visit)
		} else {
			f.walk(&n.Fun, "call", visit)
		}
		f.walk(n.Args, "expr", visit)
	case *ast.StarExpr:
		f.walk(&n.X, context, visit)
	case *ast.UnaryExpr:
		f.walk(&n.X, "expr", visit)
	case *ast.BinaryExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Y, "expr", visit)
	case *ast.KeyValueExpr:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)

	case *ast.ArrayType:
		f.walk(&n.Len, "expr", visit)
		f.walk(&n.Elt, "type", visit)
	case *ast.StructType:
		f.walk(n.Fields, "field", visit)
	case *ast.FuncType:
		f.walk(n.Params, "field", visit)
		if n.Results != nil {
			f.walk(n.Results, "field", visit)
		}
	case *ast.InterfaceType:
		f.walk(n.Methods, "field", visit)
	case *ast.MapType:
		f.walk(&n.Key, "type", visit)
		f.walk(&n.Value, "type", visit)
	case *ast.ChanType:
		f.walk(&n.Value, "type", visit)

	case *ast.BadStmt:
	case *ast.DeclStmt:
		f.walk(n.Decl, "decl", visit)
	case *ast.EmptyStmt:
	case *ast.LabeledStmt:
		f.walk(n.Stmt, "stmt", visit)
	case *ast.ExprStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.IncDecStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.AssignStmt:
		f.walk(n.Lhs, "expr", visit)
		if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
			f.walk(n.Rhs, "as2", visit)
		} else {
			f.walk(n.Rhs, "expr", visit)
		}
	case *ast.GoStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.DeferStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.ReturnStmt:
		f.walk(n.Results, "expr", visit)
	case *ast.BranchStmt:
	case *ast.BlockStmt:
		f.walk(n.List, "stmt", visit)
	case *ast.IfStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Body, "stmt", visit)
		f.walk(n.Else, "stmt", visit)
	case *ast.CaseClause:
		f.walk(n.Values, "expr", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Tag, "expr", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.TypeCaseClause:
		f.walk(n.Types, "type", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.TypeSwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(n.Assign, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.CommClause:
		f.walk(n.Lhs, "expr", visit)
		f.walk(n.Rhs, "expr", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SelectStmt:
		f.walk(n.Body, "stmt", visit)
	case *ast.ForStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Post, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.RangeStmt:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)
		f.walk(&n.X, "expr", visit)
		f.walk(n.Body, "stmt", visit)

	case *ast.ImportSpec:
	case *ast.ValueSpec:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Values, "expr", visit)
	case *ast.TypeSpec:
		f.walk(&n.Type, "type", visit)

	case *ast.BadDecl:
	case *ast.GenDecl:
		f.walk(n.Specs, "spec", visit)
	case *ast.FuncDecl:
		if n.Recv != nil {
			f.walk(n.Recv, "field", visit)
		}
		f.walk(n.Type, "type", visit)
		if n.Body != nil {
			f.walk(n.Body, "stmt", visit)
		}

	case *ast.File:
		f.walk(n.Decls, "decl", visit)

	case *ast.Package:
		for _, file := range n.Files {
			f.walk(file, "file", visit)
		}

	case []ast.Decl:
		for _, d := range n {
			f.walk(d, context, visit)
		}
	case []ast.Expr:
		for i := range n {
			f.walk(&n[i], context, visit)
		}
	case []ast.Stmt:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	case []ast.Spec:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	}
}
<commit_msg>cgo: disallow use of C.errno<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.

// Parse input AST and prepare Prog structure.

package main

import (
	"fmt"
	"go/ast"
	"go/doc"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
	"strings"
)

func parse(name string, flags uint) *ast.File {
	ast1, err := parser.ParseFile(fset, name, nil, flags)
	if err != nil {
		if list, ok := err.(scanner.ErrorList); ok {
			// If err is a scanner.ErrorList, its String will print just
			// the first error and then (+n more errors).
			// Instead, turn it into a new Error that will return
			// details for all the errors.
			for _, e := range list {
				fmt.Fprintln(os.Stderr, e)
			}
			os.Exit(2)
		}
		fatal("parsing %s: %s", name, err)
	}
	return ast1
}

// ReadGo populates f with information learned from reading the
// Go source file with the given file name.  It gathers the C preamble
// attached to the import "C" comment, a list of references to C.xxx,
// a list of exported functions, and the actual AST, to be rewritten and
// printed.
func (f *File) ReadGo(name string) {
	// Two different parses: once with comments, once without.
	// The printer is not good enough at printing comments in the
	// right place when we start editing the AST behind its back,
	// so we use ast1 to look for the doc comments on import "C"
	// and on exported functions, and we use ast2 for translating
	// and reprinting.
	ast1 := parse(name, parser.ParseComments)
	ast2 := parse(name, 0)

	f.Package = ast1.Name.Name
	f.Name = make(map[string]*Name)

	// In ast1, find the import "C" line and get any extra C preamble.
	sawC := false
	for _, decl := range ast1.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			continue
		}
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				continue
			}
			sawC = true
			if s.Name != nil {
				error(s.Path.Pos(), `cannot rename import "C"`)
			}
			if s.Doc != nil {
				f.Preamble += doc.CommentText(s.Doc) + "\n"
			} else if len(d.Specs) == 1 && d.Doc != nil {
				f.Preamble += doc.CommentText(d.Doc) + "\n"
			}
		}
	}
	if !sawC {
		error(token.NoPos, `cannot find import "C"`)
	}

	// In ast2, strip the import "C" line.
	w := 0
	for _, decl := range ast2.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			ast2.Decls[w] = decl
			w++
			continue
		}
		ws := 0
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				d.Specs[ws] = spec
				ws++
			}
		}
		if ws == 0 {
			continue
		}
		d.Specs = d.Specs[0:ws]
		ast2.Decls[w] = d
		w++
	}
	ast2.Decls = ast2.Decls[0:w]

	// Accumulate pointers to uses of C.x.
	if f.Ref == nil {
		f.Ref = make([]*Ref, 0, 8)
	}
	f.walk(ast2, "prog", (*File).saveRef)

	// Accumulate exported functions.
	// The comments are only on ast1 but we need to
	// save the function bodies from ast2.
	// The first walk fills in ExpFunc, and the
	// second walk changes the entries to
	// refer to ast2 instead.
	f.walk(ast1, "prog", (*File).saveExport)
	f.walk(ast2, "prog", (*File).saveExport2)

	f.AST = ast2
}

// Save references to C.xxx for later processing.
func (f *File) saveRef(x interface{}, context string) {
	n, ok := x.(*ast.Expr)
	if !ok {
		return
	}
	if sel, ok := (*n).(*ast.SelectorExpr); ok {
		// For now, assume that the only instance of capital C is
		// when used as the imported package identifier.
		// The parser should take care of scoping in the future,
		// so that we will be able to distinguish a "top-level C"
		// from a local C.
		if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
			if context == "as2" {
				context = "expr"
			}
			goname := sel.Sel.Name
			if goname == "errno" {
				error(sel.Pos(), "cannot refer to errno directly; see documentation")
				return
			}
			name := f.Name[goname]
			if name == nil {
				name = &Name{
					Go: goname,
				}
				f.Name[goname] = name
			}
			f.Ref = append(f.Ref, &Ref{
				Name:    name,
				Expr:    n,
				Context: context,
			})
			return
		}
	}
}

// If a function should be exported add it to ExpFunc.
func (f *File) saveExport(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	if n.Doc == nil {
		return
	}
	for _, c := range n.Doc.List {
		if string(c.Text[0:9]) != "//export " {
			continue
		}

		name := strings.TrimSpace(string(c.Text[9:]))
		if name == "" {
			error(c.Pos(), "export missing name")
		}

		f.ExpFunc = append(f.ExpFunc, &ExpFunc{
			Func:    n,
			ExpName: name,
		})
		break
	}
}

// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
func (f *File) saveExport2(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	for _, exp := range f.ExpFunc {
		if exp.Func.Name.Name == n.Name.Name {
			exp.Func = n
			break
		}
	}
}

// walk walks the AST x, calling visit(f, x, context) for each node.
func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
	visit(f, x, context)
	switch n := x.(type) {
	case *ast.Expr:
		f.walk(*n, context, visit)

	// everything else just recurs
	default:
		error(token.NoPos, "unexpected type %T in walk", x, visit)
		panic("unexpected type")

	case nil:

	// These are ordered and grouped to match ../../pkg/go/ast/ast.go
	case *ast.Field:
		f.walk(&n.Type, "type", visit)
	case *ast.FieldList:
		for _, field := range n.List {
			f.walk(field, context, visit)
		}
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.Ellipsis:
	case *ast.BasicLit:
	case *ast.FuncLit:
		f.walk(n.Type, "type", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.CompositeLit:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Elts, "expr", visit)
	case *ast.ParenExpr:
		f.walk(&n.X, context, visit)
	case *ast.SelectorExpr:
		f.walk(&n.X, "selector", visit)
	case *ast.IndexExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Index, "expr", visit)
	case *ast.SliceExpr:
		f.walk(&n.X, "expr", visit)
		if n.Low != nil {
			f.walk(&n.Low, "expr", visit)
		}
		if n.High != nil {
			f.walk(&n.High, "expr", visit)
		}
	case *ast.TypeAssertExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Type, "type", visit)
	case *ast.CallExpr:
		if context == "as2" {
			f.walk(&n.Fun, "call2", visit)
		} else {
			f.walk(&n.Fun, "call", visit)
		}
		f.walk(n.Args, "expr", visit)
	case *ast.StarExpr:
		f.walk(&n.X, context, visit)
	case *ast.UnaryExpr:
		f.walk(&n.X, "expr", visit)
	case *ast.BinaryExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Y, "expr", visit)
	case *ast.KeyValueExpr:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)

	case *ast.ArrayType:
		f.walk(&n.Len, "expr", visit)
		f.walk(&n.Elt, "type", visit)
	case *ast.StructType:
		f.walk(n.Fields, "field", visit)
	case *ast.FuncType:
		f.walk(n.Params, "field", visit)
		if n.Results != nil {
			f.walk(n.Results, "field", visit)
		}
	case *ast.InterfaceType:
		f.walk(n.Methods, "field", visit)
	case *ast.MapType:
		f.walk(&n.Key, "type", visit)
		f.walk(&n.Value, "type", visit)
	case *ast.ChanType:
		f.walk(&n.Value, "type", visit)

	case *ast.BadStmt:
	case *ast.DeclStmt:
		f.walk(n.Decl, "decl", visit)
	case *ast.EmptyStmt:
	case *ast.LabeledStmt:
		f.walk(n.Stmt, "stmt", visit)
	case *ast.ExprStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.IncDecStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.AssignStmt:
		f.walk(n.Lhs, "expr", visit)
		if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
			f.walk(n.Rhs, "as2", visit)
		} else {
			f.walk(n.Rhs, "expr", visit)
		}
	case *ast.GoStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.DeferStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.ReturnStmt:
		f.walk(n.Results, "expr", visit)
	case *ast.BranchStmt:
	case *ast.BlockStmt:
		f.walk(n.List, "stmt", visit)
	case *ast.IfStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Body, "stmt", visit)
		f.walk(n.Else, "stmt", visit)
	case *ast.CaseClause:
		f.walk(n.Values, "expr", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Tag, "expr", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.TypeCaseClause:
		f.walk(n.Types, "type", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.TypeSwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(n.Assign, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.CommClause:
		f.walk(n.Lhs, "expr", visit)
		f.walk(n.Rhs, "expr", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SelectStmt:
		f.walk(n.Body, "stmt", visit)
	case *ast.ForStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Post, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.RangeStmt:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)
		f.walk(&n.X, "expr", visit)
		f.walk(n.Body, "stmt", visit)

	case *ast.ImportSpec:
	case *ast.ValueSpec:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Values, "expr", visit)
	case *ast.TypeSpec:
		f.walk(&n.Type, "type", visit)

	case *ast.BadDecl:
	case *ast.GenDecl:
		f.walk(n.Specs, "spec", visit)
	case *ast.FuncDecl:
		if n.Recv != nil {
			f.walk(n.Recv, "field", visit)
		}
		f.walk(n.Type, "type", visit)
		if n.Body != nil {
			f.walk(n.Body, "stmt", visit)
		}

	case *ast.File:
		f.walk(n.Decls, "decl", visit)

	case *ast.Package:
		for _, file := range n.Files {
			f.walk(file, "file", visit)
		}

	case []ast.Decl:
		for _, d := range n {
			f.walk(d, context, visit)
		}
	case []ast.Expr:
		for i := range n {
			f.walk(&n[i], context, visit)
		}
	case []ast.Stmt:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	case []ast.Spec:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	}
}
<|endoftext|>


<commit_before>// Package vec3 contains a 3D float32 vector type T and functions.
package vec3

import (
	"fmt"

	math "github.com/barnex/fmath"
	"github.com/ungerik/go3d/generic"
)

var (
	// Zero holds a zero vector.
	Zero = T{}

	// UnitX holds a vector with X set to one.
	UnitX = T{1, 0, 0}
	// UnitY holds a vector with Y set to one.
	UnitY = T{0, 1, 0}
	// UnitZ holds a vector with Z set to one.
	UnitZ = T{0, 0, 1}
	// UnitXYZ holds a vector with X, Y, Z set to one.
	UnitXYZ = T{1, 1, 1}

	// Red holds the color red.
	Red = T{1, 0, 0}
	// Green holds the color green.
	Green = T{0, 1, 0}
	// Blue holds the color black.
	Blue = T{0, 0, 1}
	// Black holds the color black.
	Black = T{0, 0, 0}
	// White holds the color white.
	White = T{1, 1, 1}

	// MinVal holds a vector with the smallest possible component values.
	MinVal = T{-math.MaxFloat32, -math.MaxFloat32, -math.MaxFloat32}
	// MaxVal holds a vector with the highest possible component values.
	MaxVal = T{+math.MaxFloat32, +math.MaxFloat32, +math.MaxFloat32}
)

// T represents a 3D vector.
type T [3]float32

// From copies a T from a generic.T implementation.
func From(other generic.T) T {
	switch other.Size() {
	case 2:
		return T{other.Get(0, 0), other.Get(0, 1), 0}
	case 3, 4:
		return T{other.Get(0, 0), other.Get(0, 1), other.Get(0, 2)}
	default:
		panic("Unsupported type")
	}
}

// Parse parses T from a string. See also String()
func Parse(s string) (r T, err error) {
	_, err = fmt.Sscan(s, &r[0], &r[1], &r[2])
	return r, err
}

// String formats T as string. See also Parse().
func (vec *T) String() string {
	return fmt.Sprint(vec[0], vec[1], vec[2])
}

// Rows returns the number of rows of the vector.
func (vec *T) Rows() int {
	return 3
}

// Cols returns the number of columns of the vector.
func (vec *T) Cols() int {
	return 1
}

// Size returns the number elements of the vector.
func (vec *T) Size() int {
	return 3
}

// Slice returns the elements of the vector as slice.
func (vec *T) Slice() []float32 {
	return vec[:]
}

// Get returns one element of the vector.
func (vec *T) Get(col, row int) float32 {
	return vec[row]
}

// IsZero checks if all elements of the vector are zero.
func (vec *T) IsZero() bool {
	return vec[0] == 0 && vec[1] == 0 && vec[2] == 0
}

// Length returns the length of the vector.
// See also LengthSqr and Normalize.
func (vec *T) Length() float32 {
	return float32(math.Sqrt(vec.LengthSqr()))
}

// LengthSqr returns the squared length of the vector.
// See also Length and Normalize.
func (vec *T) LengthSqr() float32 {
	return vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]
}

// Scale multiplies all element of the vector by f and returns vec.
func (vec *T) Scale(f float32) *T {
	vec[0] *= f
	vec[1] *= f
	vec[2] *= f

	return vec
}

// Scaled returns a copy of vec with all elements multiplies by f.
func (vec *T) Scaled(f float32) T {
	return T{vec[0] * f, vec[1] * f, vec[2] * f}
}

// Invert inverts the vector.
func (vec *T) Invert() *T {
	vec[0] = -vec[0]
	vec[1] = -vec[1]
	vec[2] = -vec[2]
	return vec
}

// Inverted returns an inverted copy of the vector.
func (vec *T) Inverted() T {
	return T{-vec[0], -vec[1], -vec[2]}
}

// Abs sets every component of the vector to its absolute value.
func (vec *T) Abs() *T {
	vec[0] = math.Abs(vec[0])
	vec[1] = math.Abs(vec[1])
	vec[2] = math.Abs(vec[2])
	return vec
}

// Absed returns a copy of the vector containing the absolute values.
func (vec *T) Absed() T {
	return T{math.Abs(vec[0]), math.Abs(vec[1]), math.Abs(vec[2])}
}

// Normalize normalizes the vector to unit length.
func (vec *T) Normalize() *T {
	sl := vec.LengthSqr()
	if sl == 0 || sl == 1 {
		return vec
	}
	vec.Scale(1 / math.Sqrt(sl))
	return vec
}

// Normalized returns a unit length normalized copy of the vector.
func (vec *T) Normalized() T {
	v := *vec
	v.Normalize()
	return v
}

// Normal returns an orthogonal vector.
func (vec *T) Normal() T {
	n := Cross(vec, &UnitZ)
	if n.IsZero() {
		return UnitX
	}
	return n.Normalized()
}

// Add adds another vector to vec.
func (vec *T) Add(v *T) *T {
	vec[0] += v[0]
	vec[1] += v[1]
	vec[2] += v[2]
	return vec
}

// Sub subtracts another vector from vec.
func (vec *T) Sub(v *T) *T {
	vec[0] -= v[0]
	vec[1] -= v[1]
	vec[2] -= v[2]
	return vec
}

// Mul multiplies the components of the vector with the respective components of v.
func (vec *T) Mul(v *T) *T {
	vec[0] *= v[0]
	vec[1] *= v[1]
	vec[2] *= v[2]
	return vec
}

// Add returns the sum of two vectors.
func Add(a, b *T) T {
	return T{a[0] + b[0], a[1] + b[1], a[2] + b[2]}
}

// Squared Distance between two vectors
func SquareDistance(a, b *T) float32 {
	d := Sub(a, b)
	return d.LengthSqr()
}

// Distance between two vectors
func Distance(a, b *T) float32 {
	d := Sub(a, b)
	return d.Length()
}

// Sub returns the difference of two vectors.
func Sub(a, b *T) T {
	return T{a[0] - b[0], a[1] - b[1], a[2] - b[2]}
}

// Mul returns the component wise product of two vectors.
func Mul(a, b *T) T {
	return T{a[0] * b[0], a[1] * b[1], a[2] * b[2]}
}

// Dot returns the dot product of two vectors.
func Dot(a, b *T) float32 {
	return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
}

// Cross returns the cross product of two vectors.
func Cross(a, b *T) T {
	return T{
		a[1]*b[2] - a[2]*b[1],
		a[2]*b[0] - a[0]*b[2],
		a[0]*b[1] - a[1]*b[0],
	}
}

// Angle returns the angle between two vectors.
func Angle(a, b *T) float32 {
	v := Dot(a, b) / (a.Length() * b.Length())
	// prevent NaN
	if v > 1. {
		v = v - 2
	} else if v < -1. {
		v = v + 2
	}
	return math.Acos(v)
}

// Min returns the component wise minimum of two vectors.
func Min(a, b *T) T {
	min := *a
	if b[0] < min[0] {
		min[0] = b[0]
	}
	if b[1] < min[1] {
		min[1] = b[1]
	}
	if b[2] < min[2] {
		min[2] = b[2]
	}
	return min
}

// Max returns the component wise maximum of two vectors.
func Max(a, b *T) T {
	max := *a
	if b[0] > max[0] {
		max[0] = b[0]
	}
	if b[1] > max[1] {
		max[1] = b[1]
	}
	if b[2] > max[2] {
		max[2] = b[2]
	}
	return max
}

// Interpolate interpolates between a and b at t (0,1).
func Interpolate(a, b *T, t float32) T {
	t1 := 1 - t
	return T{
		a[0]*t1 + b[0]*t,
		a[1]*t1 + b[1]*t,
		a[2]*t1 + b[2]*t,
	}
}

// Clamp clamps the vector's components to be in the range of min to max.
func (vec *T) Clamp(min, max *T) *T {
	for i := range vec {
		if vec[i] < min[i] {
			vec[i] = min[i]
		} else if vec[i] > max[i] {
			vec[i] = max[i]
		}
	}
	return vec
}

// Clamped returns a copy of the vector with the components clamped to be in the range of min to max.
func (vec *T) Clamped(min, max *T) T {
	result := *vec
	result.Clamp(min, max)
	return result
}

// Clamp01 clamps the vector's components to be in the range of 0 to 1.
func (vec *T) Clamp01() *T {
	return vec.Clamp(&Zero, &UnitXYZ)
}

// Clamped01 returns a copy of the vector with the components clamped to be in the range of 0 to 1.
func (vec *T) Clamped01() T {
	result := *vec
	result.Clamp01()
	return result
}
<commit_msg>Add vec3 AddScaled<commit_after>// Package vec3 contains a 3D float32 vector type T and functions.
package vec3

import (
	"fmt"

	math "github.com/barnex/fmath"
	"github.com/ungerik/go3d/generic"
)

var (
	// Zero holds a zero vector.
	Zero = T{}

	// UnitX holds a vector with X set to one.
	UnitX = T{1, 0, 0}
	// UnitY holds a vector with Y set to one.
	UnitY = T{0, 1, 0}
	// UnitZ holds a vector with Z set to one.
	UnitZ = T{0, 0, 1}
	// UnitXYZ holds a vector with X, Y, Z set to one.
	UnitXYZ = T{1, 1, 1}

	// Red holds the color red.
	Red = T{1, 0, 0}
	// Green holds the color green.
	Green = T{0, 1, 0}
	// Blue holds the color black.
	Blue = T{0, 0, 1}
	// Black holds the color black.
	Black = T{0, 0, 0}
	// White holds the color white.
	White = T{1, 1, 1}

	// MinVal holds a vector with the smallest possible component values.
	MinVal = T{-math.MaxFloat32, -math.MaxFloat32, -math.MaxFloat32}
	// MaxVal holds a vector with the highest possible component values.
	MaxVal = T{+math.MaxFloat32, +math.MaxFloat32, +math.MaxFloat32}
)

// T represents a 3D vector.
type T [3]float32

// From copies a T from a generic.T implementation.
func From(other generic.T) T {
	switch other.Size() {
	case 2:
		return T{other.Get(0, 0), other.Get(0, 1), 0}
	case 3, 4:
		return T{other.Get(0, 0), other.Get(0, 1), other.Get(0, 2)}
	default:
		panic("Unsupported type")
	}
}

// Parse parses T from a string. See also String()
func Parse(s string) (r T, err error) {
	_, err = fmt.Sscan(s, &r[0], &r[1], &r[2])
	return r, err
}

// String formats T as string. See also Parse().
func (vec *T) String() string {
	return fmt.Sprint(vec[0], vec[1], vec[2])
}

// Rows returns the number of rows of the vector.
func (vec *T) Rows() int {
	return 3
}

// Cols returns the number of columns of the vector.
func (vec *T) Cols() int {
	return 1
}

// Size returns the number elements of the vector.
func (vec *T) Size() int {
	return 3
}

// Slice returns the elements of the vector as slice.
func (vec *T) Slice() []float32 {
	return vec[:]
}

// Get returns one element of the vector.
func (vec *T) Get(col, row int) float32 {
	return vec[row]
}

// IsZero checks if all elements of the vector are zero.
func (vec *T) IsZero() bool {
	return vec[0] == 0 && vec[1] == 0 && vec[2] == 0
}

// Length returns the length of the vector.
// See also LengthSqr and Normalize.
func (vec *T) Length() float32 {
	return float32(math.Sqrt(vec.LengthSqr()))
}

// LengthSqr returns the squared length of the vector.
// See also Length and Normalize.
func (vec *T) LengthSqr() float32 {
	return vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]
}

// Scale multiplies all element of the vector by f and returns vec.
func (vec *T) Scale(f float32) *T {
	vec[0] *= f
	vec[1] *= f
	vec[2] *= f

	return vec
}

// Scaled returns a copy of vec with all elements multiplies by f.
func (vec *T) Scaled(f float32) T {
	return T{vec[0] * f, vec[1] * f, vec[2] * f}
}

// Invert inverts the vector.
func (vec *T) Invert() *T {
	vec[0] = -vec[0]
	vec[1] = -vec[1]
	vec[2] = -vec[2]
	return vec
}

// Inverted returns an inverted copy of the vector.
func (vec *T) Inverted() T {
	return T{-vec[0], -vec[1], -vec[2]}
}

// Abs sets every component of the vector to its absolute value.
func (vec *T) Abs() *T {
	vec[0] = math.Abs(vec[0])
	vec[1] = math.Abs(vec[1])
	vec[2] = math.Abs(vec[2])
	return vec
}

// Absed returns a copy of the vector containing the absolute values.
func (vec *T) Absed() T {
	return T{math.Abs(vec[0]), math.Abs(vec[1]), math.Abs(vec[2])}
}

// Normalize normalizes the vector to unit length.
func (vec *T) Normalize() *T {
	sl := vec.LengthSqr()
	if sl == 0 || sl == 1 {
		return vec
	}
	vec.Scale(1 / math.Sqrt(sl))
	return vec
}

// Normalized returns a unit length normalized copy of the vector.
func (vec *T) Normalized() T {
	v := *vec
	v.Normalize()
	return v
}

// Normal returns an orthogonal vector.
func (vec *T) Normal() T {
	n := Cross(vec, &UnitZ)
	if n.IsZero() {
		return UnitX
	}
	return n.Normalized()
}

// Add adds another vector to vec.
func (vec *T) Add(v *T) *T {
	vec[0] += v[0]
	vec[1] += v[1]
	vec[2] += v[2]
	return vec
}

// Add adds another vector to vec.
func (vec *T) AddScaled(v *T, scale float32) *T {
	vec[0] += scale * v[0]
	vec[1] += scale * v[1]
	vec[2] += scale * v[2]
	return vec
}

// Sub subtracts another vector from vec.
func (vec *T) Sub(v *T) *T {
	vec[0] -= v[0]
	vec[1] -= v[1]
	vec[2] -= v[2]
	return vec
}

// Mul multiplies the components of the vector with the respective components of v.
func (vec *T) Mul(v *T) *T {
	vec[0] *= v[0]
	vec[1] *= v[1]
	vec[2] *= v[2]
	return vec
}

// Add returns the sum of two vectors.
func Add(a, b *T) T {
	return T{a[0] + b[0], a[1] + b[1], a[2] + b[2]}
}

// Squared Distance between two vectors
func SquareDistance(a, b *T) float32 {
	d := Sub(a, b)
	return d.LengthSqr()
}

// Distance between two vectors
func Distance(a, b *T) float32 {
	d := Sub(a, b)
	return d.Length()
}

// Sub returns the difference of two vectors.
func Sub(a, b *T) T {
	return T{a[0] - b[0], a[1] - b[1], a[2] - b[2]}
}

// Mul returns the component wise product of two vectors.
func Mul(a, b *T) T {
	return T{a[0] * b[0], a[1] * b[1], a[2] * b[2]}
}

// Dot returns the dot product of two vectors.
func Dot(a, b *T) float32 {
	return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
}

// Cross returns the cross product of two vectors.
func Cross(a, b *T) T {
	return T{
		a[1]*b[2] - a[2]*b[1],
		a[2]*b[0] - a[0]*b[2],
		a[0]*b[1] - a[1]*b[0],
	}
}

// Angle returns the angle between two vectors.
func Angle(a, b *T) float32 {
	v := Dot(a, b) / (a.Length() * b.Length())
	// prevent NaN
	if v > 1. {
		v = v - 2
	} else if v < -1. {
		v = v + 2
	}
	return math.Acos(v)
}

// Min returns the component wise minimum of two vectors.
func Min(a, b *T) T {
	min := *a
	if b[0] < min[0] {
		min[0] = b[0]
	}
	if b[1] < min[1] {
		min[1] = b[1]
	}
	if b[2] < min[2] {
		min[2] = b[2]
	}
	return min
}

// Max returns the component wise maximum of two vectors.
func Max(a, b *T) T {
	max := *a
	if b[0] > max[0] {
		max[0] = b[0]
	}
	if b[1] > max[1] {
		max[1] = b[1]
	}
	if b[2] > max[2] {
		max[2] = b[2]
	}
	return max
}

// Interpolate interpolates between a and b at t (0,1).
func Interpolate(a, b *T, t float32) T {
	t1 := 1 - t
	return T{
		a[0]*t1 + b[0]*t,
		a[1]*t1 + b[1]*t,
		a[2]*t1 + b[2]*t,
	}
}

// Clamp clamps the vector's components to be in the range of min to max.
func (vec *T) Clamp(min, max *T) *T {
	for i := range vec {
		if vec[i] < min[i] {
			vec[i] = min[i]
		} else if vec[i] > max[i] {
			vec[i] = max[i]
		}
	}
	return vec
}

// Clamped returns a copy of the vector with the components clamped to be in the range of min to max.
func (vec *T) Clamped(min, max *T) T {
	result := *vec
	result.Clamp(min, max)
	return result
}

// Clamp01 clamps the vector's components to be in the range of 0 to 1.
func (vec *T) Clamp01() *T {
	return vec.Clamp(&Zero, &UnitXYZ)
}

// Clamped01 returns a copy of the vector with the components clamped to be in the range of 0 to 1.
func (vec *T) Clamped01() T {
	result := *vec
	result.Clamp01()
	return result
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

const INF = math.MaxInt32

func main() {
	sc := bufio.NewScanner(os.Stdin)
	buf := make([]byte, 0)
	sc.Buffer(buf, 1010000)
	sc.Split(bufio.ScanWords)

	N := nextInt(sc)
	W := nextInt(sc)
	WS := make([]int, N)
	VS := make([]int, N)
	dp := make([][]int, N+1)
	vMax := 100100
	defaltL := make([]int, vMax+1)
	for i := 0; i < vMax+1; i++ {
		defaltL[i] = INF
	}
	dp[0] = make([]int, vMax+1)
	copy(dp[0], defaltL)
	for i := 0; i < N; i++ {
		WS[i] = nextInt(sc)
		VS[i] = nextInt(sc)
		dp[i+1] = make([]int, vMax+1)
		copy(dp[i+1], defaltL)
	}
	dp[0][0] = 0

	for i := 0; i < N; i++ {
		for v := 0; v < vMax; v++ {
			// 品物を選ばない場合
			dp[i+1][v] = min(dp[i+1][v], dp[i][v])

			// 品物を選ぶ場合の重さ
			if v-VS[i] >= 0 {
				dp[i+1][v] = min(dp[i+1][v], WS[i]+dp[i][v-VS[i]])
			}
		}
	}

	res := 0
	for v := 0; v < vMax; v++ {
		if dp[N][v] <= W {
			res = v
		}
	}
	fmt.Println(res)
}

// ----------
// ----------

// table
func createTable(h int, w int) [][]int {
	table := make([][]int, h)
	for i := 0; i < h; i++ {
		table[i] = make([]int, w)
	}
	return table
}

// Slice

func removeByte(slice []byte, s int) []byte {
	return append(slice[:s], slice[s+1:]...)
}

func removeInt(slice []int, s int) []int {
	return append(slice[:s], slice[s+1:]...)
}

// Pair

type Pair struct {
	First  int
	Second int
}

type SIPair struct {
	First  string
	Second int
}

type LLPair struct {
	First  int64
	Second int64
}

// Set

type IntSet map[int]struct{}

func NewIntSet() IntSet {
	return map[int]struct{}{}
}
func (set IntSet) put(x int) {
	set[x] = struct{}{}
}

type StringSet map[string]struct{}

func NewStringSet() StringSet {
	return map[string]struct{}{}
}
func (set StringSet) append(s string) {
	set[s] = struct{}{}
}

// Priority Queue
type Item struct {
	value    int64
	priority int64
	index    int
}
type PriorityQueue []*Item

func (q PriorityQueue) Len() int { return len(q) }

func (q PriorityQueue) Less(i, j int) bool { return q[i].priority > q[j].priority }

func (q PriorityQueue) Swap(i, j int) {
	q[i], q[j] = q[j], q[i]
	q[i].index = i
	q[j].index = j
}

func (q *PriorityQueue) Push(x interface{}) {
	n := len(*q)
	item := x.(*Item)
	item.index = n
	*q = append(*q, item)
}

func (q *PriorityQueue) Pop() interface{} {
	old := *q
	n := len(old)
	item := old[n-1]
	old[n-1] = nil
	item.index = -1
	*q = old[0 : n-1]
	return item
}

// Convert

func toInt(s string) int {
	x, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return x
}

func toInt64(s string) int64 {
	x, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		panic(err)
	}
	return x
}

// Combination
//
// nCk
//   combi := pascalTriangle(n)
//   combi[n][k]
func pascalTriangle(n int) [][]int {
	pt := make([][]int, n+1)
	for i := 0; i < n+1; i++ {
		pt[i] = make([]int, i+1)
		pt[i][0] = 1
		pt[i][i] = 1
		for j := 1; j < i; j++ {
			pt[i][j] = pt[i-1][j-1] + pt[i-1][j]
		}
	}
	return pt
}

// Permutations
// nPn
func permutations(arr []byte) [][]byte {
	var helper func([]byte, int)
	res := [][]byte{}

	helper = func(arr []byte, n int) {
		if n == 1 {
			tmp := make([]byte, len(arr))
			copy(tmp, arr)
			res = append(res, tmp)
		} else {
			for i := 0; i < n; i++ {
				helper(arr, n-1)
				if n%2 == 1 {
					tmp := arr[i]
					arr[i] = arr[n-1]
					arr[n-1] = tmp
				} else {
					tmp := arr[0]
					arr[0] = arr[n-1]
					arr[n-1] = tmp
				}
			}
		}
	}
	helper(arr, len(arr))
	return res
}

// Utilities

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func minInt64(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func maxInt64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func pow(a, b int) int {
	return int(math.Pow(float64(a), float64(b)))
}

func abs(a int) int {
	if a < 0 {
		return -1 * a
	}
	return a
}

// Scans

func nextString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextNumber(sc *bufio.Scanner) float64 {
	sc.Scan()
	f, err := strconv.ParseFloat(sc.Text(), 32)
	if err != nil {
		panic(err)
	}
	return f
}

func nextInt(sc *bufio.Scanner) int {
	sc.Scan()
	n, err := strconv.Atoi(sc.Text())
	if err != nil {
		panic(err)
	}
	return n
}

func nextInt64(sc *bufio.Scanner) int64 {
	sc.Scan()
	n, err := strconv.ParseInt(sc.Text(), 10, 64)
	if err != nil {
		panic(err)
	}
	return n
}

// Debug print

func printArray(xs []int) {
	fmt.Println(strings.Trim(fmt.Sprint(xs), "[]"))
}

func debugPrintArray(xs []int) {
	fmt.Fprintln(os.Stderr, strings.Trim(fmt.Sprint(xs), "[]"))
}

func debugPrintTable(table [][]int) {
	for i := 0; i < len(table); i++ {
		debugPrintArray(table[i])
	}
}

func debugPrintf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stdout, format, a...)
}
<commit_msg>update DP_Contest A<commit_after>package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

const INF = math.MaxInt32

func main() {
	sc := bufio.NewScanner(os.Stdin)
	buf := make([]byte, 0)
	sc.Buffer(buf, 1010000)
	sc.Split(bufio.ScanWords)

	N := nextInt(sc)
	W := nextInt(sc)

	vMax := 100000
	ws := makeInts(N+1, 0)
	vs := makeInts(N+1, 0)
	dp := make([][]int, N+1)
	dp[0] = makeInts(vMax+1, INF)
	for i := 1; i <= N; i++ {
		dp[i] = makeInts(vMax+1, INF)
		ws[i] = nextInt(sc)
		vs[i] = nextInt(sc)
	}

	dp[0][0] = 0
	for i := 1; i <= N; i++ {
		for sumV := 0; sumV <= vMax; sumV++ {
			// i番目を選ぶ場合の容量
			if sumV-vs[i] >= 0 {
				dp[i][sumV] = min(dp[i][sumV], dp[i-1][sumV-vs[i]]+ws[i])
			}
			// i番目を選ばない場合の容量
			dp[i][sumV] = min(dp[i][sumV], dp[i-1][sumV])
		}
	}
	ans := 0
	for sumV := 0; sumV <= vMax; sumV++ {
		if dp[N][sumV] <= W {
			ans = sumV
		}
	}
	fmt.Println(ans)
}

// ----------
// ----------

// Scans

func nextString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextNumber(sc *bufio.Scanner) float64 {
	sc.Scan()
	f, err := strconv.ParseFloat(sc.Text(), 32)
	if err != nil {
		panic(err)
	}
	return f
}

func nextInt(sc *bufio.Scanner) int {
	sc.Scan()
	n, err := strconv.Atoi(sc.Text())
	if err != nil {
		panic(err)
	}
	return n
}

func nextInt64(sc *bufio.Scanner) int64 {
	sc.Scan()
	n, err := strconv.ParseInt(sc.Text(), 10, 64)
	if err != nil {
		panic(err)
	}
	return n
}

// Convert

func toInt(s string) int {
	x, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return x
}

func toInt64(s string) int64 {
	x, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		panic(err)
	}
	return x
}

// table
func createTable(h int, w int) [][]int {
	table := make([][]int, h)
	for i := 0; i < h; i++ {
		table[i] = make([]int, w)
	}
	return table
}

// Slice

func removeByte(slice []byte, s int) []byte {
	return append(slice[:s], slice[s+1:]...)
}

func removeInt(slice []int, s int) []int {
	return append(slice[:s], slice[s+1:]...)
}

// key以上の要素のうちMINである要素の添字を返す
// ref. https://gist.github.com/bati11/1fa106711d17ddea6ab39c43e989fea3
func lowerBound(xs []int, key int) int {
	if len(xs) == 0 {
		return 0
	}
	l, r := 0, len(xs)-1
	if xs[r] < key {
		// key以上の要素が存在しない
		return r + 1
	}
	for r-l > 1 {
		mid := l + (r-l)/2
		v := xs[mid]
		if key <= v {
			r = mid
		} else {
			l = mid
		}
	}
	if xs[l] >= key {
		return l
	}
	return r
}

// keyより大きな要素のうちMINである要素の添字を返す
// ref. https://gist.github.com/bati11/1fa106711d17ddea6ab39c43e989fea3
func upperBound(xs []int, key int) int {
	if len(xs) == 0 {
		return 0
	}
	l, r := 0, len(xs)-1
	if xs[r] <= key {
		// keyより大きい要素が存在しない
		return r + 1
	}
	for r-l > 1 {
		mid := l + (r-l)/2
		v := xs[mid]
		if key < v {
			r = mid
		} else {
			l = mid
		}
	}
	if xs[l] > key {
		return l
	}
	return r
}

// Pair

type Pair struct {
	First  int
	Second int
}

type SIPair struct {
	First  string
	Second int
}

type LLPair struct {
	First  int64
	Second int64
}

// Set

type IntSet map[int]struct{}

func NewIntSet() IntSet {
	return map[int]struct{}{}
}
func (set IntSet) put(x int) {
	set[x] = struct{}{}
}

type StringSet map[string]struct{}

func NewStringSet() StringSet {
	return map[string]struct{}{}
}
func (set StringSet) append(s string) {
	set[s] = struct{}{}
}

// Priority Queue
type Item struct {
	value    int64
	priority int64
	index    int
}
type PriorityQueue []*Item

func (q PriorityQueue) Len() int { return len(q) }

func (q PriorityQueue) Less(i, j int) bool { return q[i].priority > q[j].priority }

func (q PriorityQueue) Swap(i, j int) {
	q[i], q[j] = q[j], q[i]
	q[i].index = i
	q[j].index = j
}

func (q *PriorityQueue) Push(x interface{}) {
	n := len(*q)
	item := x.(*Item)
	item.index = n
	*q = append(*q, item)
}

func (q *PriorityQueue) Pop() interface{} {
	old := *q
	n := len(old)
	item := old[n-1]
	old[n-1] = nil
	item.index = -1
	*q = old[0 : n-1]
	return item
}

// Union-Find
type UnionFind struct {
	parents []int
	size    []int
}

func (u *UnionFind) root(x int) int {
	if u.parents[x] == -1 {
		return x
	}
	p := u.root(u.parents[x])
	// 親を根で置き換えてしまう
	//   経路圧縮で効率化 O(N) -> O(logN)
	u.parents[x] = p
	return p
}

func (u *UnionFind) Unite(x, y int) {
	xRoot := u.root(x)
	yRoot := u.root(y)
	// 既に同じグループの場合は何もしない
	if xRoot == yRoot {
		return
	}
	// サイズが小さい方のグループを大きい方のグループに統合する
	//   union by size による効率化 O(logN) -> O(α(N))
	if u.size[xRoot] > u.size[yRoot] {
		u.parents[yRoot] = xRoot
		u.size[xRoot] = u.size[xRoot] + u.size[yRoot]
	} else {
		u.parents[xRoot] = yRoot
		u.size[yRoot] = u.size[yRoot] + u.size[xRoot]
	}
}

func (u *UnionFind) Same(x, y int) bool {
	return u.root(x) == u.root(y)
}

func NewUnionFind(n int) *UnionFind {
	parents := make([]int, n)
	for i := 0; i < n; i++ {
		parents[i] = -1
	}
	// sizeの大小比較ができれば良いので特に初期化していないが、
	// 値自体に意味がある場合は 1 で初期化する
	size := make([]int, n)
	return &UnionFind{parents: parents, size: size}
}

// Combination
//
// nCk
//   combi := pascalTriangle(n)
//   combi[n][k]
func pascalTriangle(n int) [][]int {
	pt := make([][]int, n+1)
	for i := 0; i < n+1; i++ {
		pt[i] = make([]int, i+1)
		pt[i][0] = 1
		pt[i][i] = 1
		for j := 1; j < i; j++ {
			pt[i][j] = pt[i-1][j-1] + pt[i-1][j]
		}
	}
	return pt
}

// Permutations
// nPn
func permutations(arr []byte) [][]byte {
	var helper func([]byte, int)
	res := [][]byte{}

	helper = func(arr []byte, n int) {
		if n == 1 {
			tmp := make([]byte, len(arr))
			copy(tmp, arr)
			res = append(res, tmp)
		} else {
			for i := 0; i < n; i++ {
				helper(arr, n-1)
				if n%2 == 1 {
					tmp := arr[i]
					arr[i] = arr[n-1]
					arr[n-1] = tmp
				} else {
					tmp := arr[0]
					arr[0] = arr[n-1]
					arr[n-1] = tmp
				}
			}
		}
	}
	helper(arr, len(arr))
	return res
}

// Utilities

func makeInts(n int, defaultValue int) []int {
	result := make([]int, n)
	if defaultValue != 0 {
		for i := 0; i < n; i++ {
			result[i] = defaultValue
		}
	}
	return result
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func minInt64(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func maxInt64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func pow(a, b int) int {
	return int(math.Pow(float64(a), float64(b)))
}

func abs(a int) int {
	if a < 0 {
		return -1 * a
	}
	return a
}

// Debug print

func printArray(xs []int) {
	fmt.Println(strings.Trim(fmt.Sprint(xs), "[]"))
}

func debugPrintArray(xs []int) {
	fmt.Fprintln(os.Stderr, strings.Trim(fmt.Sprint(xs), "[]"))
}

func debugPrintTable(table [][]int) {
	for i := 0; i < len(table); i++ {
		debugPrintArray(table[i])
	}
}

func debugPrintf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/pprof"

	"github.com/lflux/eve-sdeloader/bsd"
)

var (
	cpuprofile string
	dbPort     int
	dbUser     string
	dbHost     string
	dbName     string
	dbPassword string
	memprofile string
	singleFile string
)

func init() {
	flag.IntVar(&dbPort, "dbport", 5432, "Database port")
	flag.StringVar(&dbUser, "dbuser", "sdetest", "Database username")
	flag.StringVar(&dbHost, "dbhost", "localhost", "Database host")
	flag.StringVar(&dbName, "dbname", "sdetest", "Database name")
	flag.StringVar(&dbPassword, "dbpassword", "", "Database password")
	flag.StringVar(&singleFile, "singlefile", "", "Import only one file")
	flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile `file`")
	flag.StringVar(&memprofile, "memprofile", "", "write memory profile to `file`")

}

func main() {
	flag.Parse()
	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatal("could not create CPU profile: ", err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal("could not start CPU profile: ", err)
		}
		defer pprof.StopCPUProfile()
	}

	connStr := fmt.Sprintf("user=%s dbname=%s host=%s port=%d sslmode=disable",
		dbUser,
		dbName,
		dbHost,
		dbPort,
	)
	if dbPassword != "" {
		connStr += " password=" + dbPassword
	}

	db, err := sql.Open("postgres", connStr)
	if err != nil {
		log.Fatalf("Could not connect to database with connection string `%s`: %s", connStr, err)
	}
	defer func() {
		_ = db.Close()
	}()
	i := bsd.Importer{DB: db}
	err = i.Import("/Users/ian/go/src/github.com/lflux/eve-sdeloader/sde/bsd", singleFile)
	if err != nil {
		log.Fatal(err)
	}

	if memprofile != "" {
		f, err := os.Create(memprofile)
		if err != nil {
			log.Fatal("could not create memory profile: ", err)
		}
		runtime.GC() // get up-to-date statistics
		if err := pprof.WriteHeapProfile(f); err != nil {
			log.Fatal("could not write memory profile: ", err)
		}
		f.Close()
	}

}
<commit_msg>Remove bsd importer<commit_after><|endoftext|>