<commit_before>package main

import (
	_ "time"
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"encoding/json"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
)

const MESSAGE_QUEUE_SIZE = 10

var authKey = []byte("somesecretauth")
var store sessions.Store
var pool *Pool
var clients map[int64]*Client

var db *sql.DB
// var tv syscall.Timeval

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      int64
	client1 *Client
	client2 *Client
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 8)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 8 {
			return
		}
		crId, _ := binary.Varint(b)

		room := &Room{crId, c1, c2}

		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	var uid int64
	var b []byte

	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	uid, _ = binary.Varint(b)
	return uid, nil
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)
	http.ListenAndServe(":8080", nil)
}

type IdQuery struct {
    Id            int64      `json:"id"`

}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hey")
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

  	fmt.Println("uid: ", uid)
	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}
	clients[uid] = client
	pool.in <- client

	fmt.Println("added ", uid, " to queue")
	chatroom := <- retChan

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":", chatroom.id, "}")
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	fmt.Fprint(w, uid)
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println(uid)

	message := r.FormValue("s")

	// message := r.PostFormValue("message")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}-", message)
	} else {
		fmt.Fprint(w, "{\"status\":\"failure\"}-", message)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	client := clients[uid]

	if client != nil {
		fmt.Println("client found")
		select {
		case message, ok := <- clients[uid].in:
			fmt.Println("message pulled from channel")
			if ok {
				fmt.Fprint(w, "{\"status\":\"success\"}-", message)
			} else {
				fmt.Fprint(w, "{\"status\":\"failure\"}")
			}
		default:
			fmt.Println("default")
			fmt.Fprint(w, "")
		}

	} else {
		fmt.Println("client not found")
		fmt.Fprint(w, "{\"status\":\"failure\"}")
	}
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		iq := new(IdQuery)
		err := row.Scan(&iq.Id)

		if err != nil {
			_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, "{\"status\":\"failure\"}")
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&iq.Id)
				if err != nil {
					fmt.Fprint(w, "{\"status\":\"failure\"}")
					return
				}
			}

		}

		session, _ := store.Get(r, "session")
		session.Values["userid"] = iq.Id
		session.Save(r, w)

		fmt.Fprint(w, "{\"status\":\"success\"}")

	// 	if err == nil {
	// 		fmt.Fprint(w, "{\"status\":\"success\",\"uid\":", iq.Id, "}")
	// 	} else {
	// 		_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
	// 		if err == nil {
	// 			row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
	// 			err = row.Scan(&iq.Id)
	// 			if err == nil {
	// 				fmt.Fprint(w, "{\"status\":\"success\"},\"uid\":", iq.Id, "}")
	// 			} else {
	// 				fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 			}
	// 		} else {
	// 			fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 		}
	// 	}
	// } else {
	// 	fmt.Fprint(w, "{\"status\":\"failure\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>debug<commit_after>package main

import (
	_ "time"
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"encoding/json"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
)

const MESSAGE_QUEUE_SIZE = 10

var authKey = []byte("somesecretauth")
var store sessions.Store
var pool *Pool
var clients map[int64]*Client

var db *sql.DB
// var tv syscall.Timeval

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      int64
	client1 *Client
	client2 *Client
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 8)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 8 {
			return
		}
		crId, _ := binary.Varint(b)

		room := &Room{crId, c1, c2}

		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	var uid int64
	var b []byte

	fmt.Println("UIDFromSession: ", uid)

	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	uid, _ = binary.Varint(b)
	return uid, nil
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)
	http.ListenAndServe(":8080", nil)
}

type IdQuery struct {
    Id            int64      `json:"id"`

}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hey")
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

  	fmt.Println("uid: ", uid)
	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}
	clients[uid] = client
	pool.in <- client

	fmt.Println("added ", uid, " to queue")
	chatroom := <- retChan

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":", chatroom.id, "}")
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	fmt.Fprint(w, uid)
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println(uid)

	message := r.FormValue("s")

	// message := r.PostFormValue("message")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}-", message)
	} else {
		fmt.Fprint(w, "{\"status\":\"failure\"}-", message)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	client := clients[uid]

	if client != nil {
		fmt.Println("client found")
		select {
		case message, ok := <- clients[uid].in:
			fmt.Println("message pulled from channel")
			if ok {
				fmt.Fprint(w, "{\"status\":\"success\"}-", message)
			} else {
				fmt.Fprint(w, "{\"status\":\"failure\"}")
			}
		default:
			fmt.Println("default")
			fmt.Fprint(w, "")
		}

	} else {
		fmt.Println("client not found")
		fmt.Fprint(w, "{\"status\":\"failure\"}")
	}
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		iq := new(IdQuery)
		err := row.Scan(&iq.Id)

		if err != nil {
			_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, "{\"status\":\"failure\"}")
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&iq.Id)
				if err != nil {
					fmt.Fprint(w, "{\"status\":\"failure\"}")
					return
				}
			}

		}

		session, _ := store.Get(r, "session")
		session.Values["userid"] = iq.Id
		session.Save(r, w)

		fmt.Fprint(w, "{\"status\":\"success\"}")

	// 	if err == nil {
	// 		fmt.Fprint(w, "{\"status\":\"success\",\"uid\":", iq.Id, "}")
	// 	} else {
	// 		_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
	// 		if err == nil {
	// 			row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
	// 			err = row.Scan(&iq.Id)
	// 			if err == nil {
	// 				fmt.Fprint(w, "{\"status\":\"success\"},\"uid\":", iq.Id, "}")
	// 			} else {
	// 				fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 			}
	// 		} else {
	// 			fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 		}
	// 	}
	// } else {
	// 	fmt.Fprint(w, "{\"status\":\"failure\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>package main

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

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		fmt.Fprintf(os.Stderr, "usage: serve [dir]\n")
		os.Exit(1)
	}

	dir := args[0]

	fi, err := os.Stat(dir)
	if err != nil || !fi.IsDir() {
		fmt.Fprintf(os.Stderr, "Invalid directory: %s\n", dir)
		os.Exit(1)
	}

	log.Printf("Serving from dir: %s\n", dir)

	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir(dir))))
}
<commit_msg>Add banner and cleanup<commit_after>package main

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

const (
	BANNER = ` _____  _____  _____  __ __
 /  ___>/   __\/  _  \/  |  \
 |___  ||   __||  _  <\  |  /
 <_____/\_____/\__|\_/ \___/
	`
)

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		fmt.Fprintf(os.Stderr, "usage: serve [dir]\n")
		os.Exit(1)
	}

	dir := args[0]

	fi, err := os.Stat(dir)
	if err != nil || !fi.IsDir() {
		fmt.Fprintf(os.Stderr, "Invalid directory: %s\n", dir)
		os.Exit(1)
	}

	fmt.Printf("%s\n", BANNER)
	fmt.Printf("Serving from dir: %s\n", dir)

	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir(dir))))
}
<|endoftext|>


<commit_before>// Package sftp implements the SSH File Transfer Protocol as described in
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
package sftp

import (
	"fmt"

	"github.com/pkg/errors"
)

const (
	sshFxpInit          = 1
	sshFxpVersion       = 2
	sshFxpOpen          = 3
	sshFxpClose         = 4
	sshFxpRead          = 5
	sshFxpWrite         = 6
	sshFxpLstat         = 7
	sshFxpFstat         = 8
	sshFxpSetstat       = 9
	sshFxpFsetstat      = 10
	sshFxpOpendir       = 11
	sshFxpReaddir       = 12
	sshFxpRemove        = 13
	sshFxpMkdir         = 14
	sshFxpRmdir         = 15
	sshFxpRealpath      = 16
	sshFxpStat          = 17
	sshFxpRename        = 18
	sshFxpReadlink      = 19
	sshFxpSymlink       = 20
	sshFxpStatus        = 101
	sshFxpHandle        = 102
	sshFxpData          = 103
	sshFxpName          = 104
	sshFxpAttrs         = 105
	sshFxpExtended      = 200
	sshFxpExtendedReply = 201
)

const (
	sshFxOk               = 0
	sshFxEOF              = 1
	sshFxNoSuchFile       = 2
	sshFxPermissionDenied = 3
	sshFxFailure          = 4
	sshFxBadMessage       = 5
	sshFxNoConnection     = 6
	sshFxConnectionLost   = 7
	sshFxOPUnsupported    = 8

	// see draft-ietf-secsh-filexfer-13
	// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1
	sshFxInvalidHandle           = 9
	sshFxNoSuchPath              = 10
	sshFxFileAlreadyExists       = 11
	sshFxWriteProtect            = 12
	sshFxNoMedia                 = 13
	sshFxNoSpaceOnFilesystem     = 14
	sshFxQuotaExceeded           = 15
	sshFxUnlnownPrincipal        = 16
	sshFxLockConflict            = 17
	sshFxDitNotEmpty             = 18
	sshFxNotADirectory           = 19
	sshFxInvalidFilename         = 20
	sshFxLinkLoop                = 21
	sshFxCannotDelete            = 22
	sshFxInvalidParameter        = 23
	sshFxFileIsADirectory        = 24
	sshFxByteRangeLockConflict   = 25
	sshFxByteRangeLockRefused    = 26
	sshFxDeletePending           = 27
	sshFxFileCorrupt             = 28
	sshFxOwnerInvalid            = 29
	sshFxGroupInvalid            = 30
	sshFxNoMatchingByteRangeLock = 31
)

const (
	sshFxfRead   = 0x00000001
	sshFxfWrite  = 0x00000002
	sshFxfAppend = 0x00000004
	sshFxfCreat  = 0x00000008
	sshFxfTrunc  = 0x00000010
	sshFxfExcl   = 0x00000020
)

var (
	// supportedSFTPExtensions defines the supported extensions
	supportedSFTPExtensions = []sshExtensionPair{
		{"hardlink@openssh.com", "1"},
		{"posix-rename@openssh.com", "1"},
		{"statvfs@openssh.com", "2"},
	}
	sftpExtensions = supportedSFTPExtensions
)

type fxp uint8

func (f fxp) String() string {
	switch f {
	case sshFxpInit:
		return "SSH_FXP_INIT"
	case sshFxpVersion:
		return "SSH_FXP_VERSION"
	case sshFxpOpen:
		return "SSH_FXP_OPEN"
	case sshFxpClose:
		return "SSH_FXP_CLOSE"
	case sshFxpRead:
		return "SSH_FXP_READ"
	case sshFxpWrite:
		return "SSH_FXP_WRITE"
	case sshFxpLstat:
		return "SSH_FXP_LSTAT"
	case sshFxpFstat:
		return "SSH_FXP_FSTAT"
	case sshFxpSetstat:
		return "SSH_FXP_SETSTAT"
	case sshFxpFsetstat:
		return "SSH_FXP_FSETSTAT"
	case sshFxpOpendir:
		return "SSH_FXP_OPENDIR"
	case sshFxpReaddir:
		return "SSH_FXP_READDIR"
	case sshFxpRemove:
		return "SSH_FXP_REMOVE"
	case sshFxpMkdir:
		return "SSH_FXP_MKDIR"
	case sshFxpRmdir:
		return "SSH_FXP_RMDIR"
	case sshFxpRealpath:
		return "SSH_FXP_REALPATH"
	case sshFxpStat:
		return "SSH_FXP_STAT"
	case sshFxpRename:
		return "SSH_FXP_RENAME"
	case sshFxpReadlink:
		return "SSH_FXP_READLINK"
	case sshFxpSymlink:
		return "SSH_FXP_SYMLINK"
	case sshFxpStatus:
		return "SSH_FXP_STATUS"
	case sshFxpHandle:
		return "SSH_FXP_HANDLE"
	case sshFxpData:
		return "SSH_FXP_DATA"
	case sshFxpName:
		return "SSH_FXP_NAME"
	case sshFxpAttrs:
		return "SSH_FXP_ATTRS"
	case sshFxpExtended:
		return "SSH_FXP_EXTENDED"
	case sshFxpExtendedReply:
		return "SSH_FXP_EXTENDED_REPLY"
	default:
		return "unknown"
	}
}

type fx uint8

func (f fx) String() string {
	switch f {
	case sshFxOk:
		return "SSH_FX_OK"
	case sshFxEOF:
		return "SSH_FX_EOF"
	case sshFxNoSuchFile:
		return "SSH_FX_NO_SUCH_FILE"
	case sshFxPermissionDenied:
		return "SSH_FX_PERMISSION_DENIED"
	case sshFxFailure:
		return "SSH_FX_FAILURE"
	case sshFxBadMessage:
		return "SSH_FX_BAD_MESSAGE"
	case sshFxNoConnection:
		return "SSH_FX_NO_CONNECTION"
	case sshFxConnectionLost:
		return "SSH_FX_CONNECTION_LOST"
	case sshFxOPUnsupported:
		return "SSH_FX_OP_UNSUPPORTED"
	default:
		return "unknown"
	}
}

type unexpectedPacketErr struct {
	want, got uint8
}

func (u *unexpectedPacketErr) Error() string {
	return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got))
}

func unimplementedPacketErr(u uint8) error {
	return errors.Errorf("sftp: unimplemented packet type: got %v", fxp(u))
}

type unexpectedIDErr struct{ want, got uint32 }

func (u *unexpectedIDErr) Error() string {
	return fmt.Sprintf("sftp: unexpected id: want %d, got %d", u.want, u.got)
}

func unimplementedSeekWhence(whence int) error {
	return errors.Errorf("sftp: unimplemented seek whence %d", whence)
}

func unexpectedCount(want, got uint32) error {
	return errors.Errorf("sftp: unexpected count: want %d, got %d", want, got)
}

type unexpectedVersionErr struct{ want, got uint32 }

func (u *unexpectedVersionErr) Error() string {
	return fmt.Sprintf("sftp: unexpected server version: want %v, got %v", u.want, u.got)
}

// A StatusError is returned when an SFTP operation fails, and provides
// additional information about the failure.
type StatusError struct {
	Code      uint32
	msg, lang string
}

func (s *StatusError) Error() string {
	return fmt.Sprintf("sftp: %q (%v)", s.msg, fx(s.Code))
}

// FxCode returns the error code typed to match against the exported codes
func (s *StatusError) FxCode() fxerr {
	return fxerr(s.Code)
}

func getSupportedExtensionByName(extensionName string) (sshExtensionPair, error) {
	for _, supportedExtension := range supportedSFTPExtensions {
		if supportedExtension.Name == extensionName {
			return supportedExtension, nil
		}
	}
	return sshExtensionPair{}, fmt.Errorf("unsupported extension: %s", extensionName)
}

// SetSFTPExtensions allows to customize the supported server extensions.
// See the variable supportedSFTPExtensions for supported extensions.
// This method accepts a slice of sshExtensionPair names for example 'hardlink@openssh.com'.
// If an invalid extension is given an error will be returned and nothing will be changed
func SetSFTPExtensions(extensions ...string) error {
	tempExtensions := []sshExtensionPair{}
	for _, extension := range extensions {
		sftpExtension, err := getSupportedExtensionByName(extension)
		if err != nil {
			return err
		}
		tempExtensions = append(tempExtensions, sftpExtension)
	}
	sftpExtensions = tempExtensions
	return nil
}
<commit_msg>errors.Errorf over fmt.Errorf<commit_after>// Package sftp implements the SSH File Transfer Protocol as described in
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
package sftp

import (
	"fmt"

	"github.com/pkg/errors"
)

const (
	sshFxpInit          = 1
	sshFxpVersion       = 2
	sshFxpOpen          = 3
	sshFxpClose         = 4
	sshFxpRead          = 5
	sshFxpWrite         = 6
	sshFxpLstat         = 7
	sshFxpFstat         = 8
	sshFxpSetstat       = 9
	sshFxpFsetstat      = 10
	sshFxpOpendir       = 11
	sshFxpReaddir       = 12
	sshFxpRemove        = 13
	sshFxpMkdir         = 14
	sshFxpRmdir         = 15
	sshFxpRealpath      = 16
	sshFxpStat          = 17
	sshFxpRename        = 18
	sshFxpReadlink      = 19
	sshFxpSymlink       = 20
	sshFxpStatus        = 101
	sshFxpHandle        = 102
	sshFxpData          = 103
	sshFxpName          = 104
	sshFxpAttrs         = 105
	sshFxpExtended      = 200
	sshFxpExtendedReply = 201
)

const (
	sshFxOk               = 0
	sshFxEOF              = 1
	sshFxNoSuchFile       = 2
	sshFxPermissionDenied = 3
	sshFxFailure          = 4
	sshFxBadMessage       = 5
	sshFxNoConnection     = 6
	sshFxConnectionLost   = 7
	sshFxOPUnsupported    = 8

	// see draft-ietf-secsh-filexfer-13
	// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1
	sshFxInvalidHandle           = 9
	sshFxNoSuchPath              = 10
	sshFxFileAlreadyExists       = 11
	sshFxWriteProtect            = 12
	sshFxNoMedia                 = 13
	sshFxNoSpaceOnFilesystem     = 14
	sshFxQuotaExceeded           = 15
	sshFxUnlnownPrincipal        = 16
	sshFxLockConflict            = 17
	sshFxDitNotEmpty             = 18
	sshFxNotADirectory           = 19
	sshFxInvalidFilename         = 20
	sshFxLinkLoop                = 21
	sshFxCannotDelete            = 22
	sshFxInvalidParameter        = 23
	sshFxFileIsADirectory        = 24
	sshFxByteRangeLockConflict   = 25
	sshFxByteRangeLockRefused    = 26
	sshFxDeletePending           = 27
	sshFxFileCorrupt             = 28
	sshFxOwnerInvalid            = 29
	sshFxGroupInvalid            = 30
	sshFxNoMatchingByteRangeLock = 31
)

const (
	sshFxfRead   = 0x00000001
	sshFxfWrite  = 0x00000002
	sshFxfAppend = 0x00000004
	sshFxfCreat  = 0x00000008
	sshFxfTrunc  = 0x00000010
	sshFxfExcl   = 0x00000020
)

var (
	// supportedSFTPExtensions defines the supported extensions
	supportedSFTPExtensions = []sshExtensionPair{
		{"hardlink@openssh.com", "1"},
		{"posix-rename@openssh.com", "1"},
		{"statvfs@openssh.com", "2"},
	}
	sftpExtensions = supportedSFTPExtensions
)

type fxp uint8

func (f fxp) String() string {
	switch f {
	case sshFxpInit:
		return "SSH_FXP_INIT"
	case sshFxpVersion:
		return "SSH_FXP_VERSION"
	case sshFxpOpen:
		return "SSH_FXP_OPEN"
	case sshFxpClose:
		return "SSH_FXP_CLOSE"
	case sshFxpRead:
		return "SSH_FXP_READ"
	case sshFxpWrite:
		return "SSH_FXP_WRITE"
	case sshFxpLstat:
		return "SSH_FXP_LSTAT"
	case sshFxpFstat:
		return "SSH_FXP_FSTAT"
	case sshFxpSetstat:
		return "SSH_FXP_SETSTAT"
	case sshFxpFsetstat:
		return "SSH_FXP_FSETSTAT"
	case sshFxpOpendir:
		return "SSH_FXP_OPENDIR"
	case sshFxpReaddir:
		return "SSH_FXP_READDIR"
	case sshFxpRemove:
		return "SSH_FXP_REMOVE"
	case sshFxpMkdir:
		return "SSH_FXP_MKDIR"
	case sshFxpRmdir:
		return "SSH_FXP_RMDIR"
	case sshFxpRealpath:
		return "SSH_FXP_REALPATH"
	case sshFxpStat:
		return "SSH_FXP_STAT"
	case sshFxpRename:
		return "SSH_FXP_RENAME"
	case sshFxpReadlink:
		return "SSH_FXP_READLINK"
	case sshFxpSymlink:
		return "SSH_FXP_SYMLINK"
	case sshFxpStatus:
		return "SSH_FXP_STATUS"
	case sshFxpHandle:
		return "SSH_FXP_HANDLE"
	case sshFxpData:
		return "SSH_FXP_DATA"
	case sshFxpName:
		return "SSH_FXP_NAME"
	case sshFxpAttrs:
		return "SSH_FXP_ATTRS"
	case sshFxpExtended:
		return "SSH_FXP_EXTENDED"
	case sshFxpExtendedReply:
		return "SSH_FXP_EXTENDED_REPLY"
	default:
		return "unknown"
	}
}

type fx uint8

func (f fx) String() string {
	switch f {
	case sshFxOk:
		return "SSH_FX_OK"
	case sshFxEOF:
		return "SSH_FX_EOF"
	case sshFxNoSuchFile:
		return "SSH_FX_NO_SUCH_FILE"
	case sshFxPermissionDenied:
		return "SSH_FX_PERMISSION_DENIED"
	case sshFxFailure:
		return "SSH_FX_FAILURE"
	case sshFxBadMessage:
		return "SSH_FX_BAD_MESSAGE"
	case sshFxNoConnection:
		return "SSH_FX_NO_CONNECTION"
	case sshFxConnectionLost:
		return "SSH_FX_CONNECTION_LOST"
	case sshFxOPUnsupported:
		return "SSH_FX_OP_UNSUPPORTED"
	default:
		return "unknown"
	}
}

type unexpectedPacketErr struct {
	want, got uint8
}

func (u *unexpectedPacketErr) Error() string {
	return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got))
}

func unimplementedPacketErr(u uint8) error {
	return errors.Errorf("sftp: unimplemented packet type: got %v", fxp(u))
}

type unexpectedIDErr struct{ want, got uint32 }

func (u *unexpectedIDErr) Error() string {
	return fmt.Sprintf("sftp: unexpected id: want %d, got %d", u.want, u.got)
}

func unimplementedSeekWhence(whence int) error {
	return errors.Errorf("sftp: unimplemented seek whence %d", whence)
}

func unexpectedCount(want, got uint32) error {
	return errors.Errorf("sftp: unexpected count: want %d, got %d", want, got)
}

type unexpectedVersionErr struct{ want, got uint32 }

func (u *unexpectedVersionErr) Error() string {
	return fmt.Sprintf("sftp: unexpected server version: want %v, got %v", u.want, u.got)
}

// A StatusError is returned when an SFTP operation fails, and provides
// additional information about the failure.
type StatusError struct {
	Code      uint32
	msg, lang string
}

func (s *StatusError) Error() string {
	return fmt.Sprintf("sftp: %q (%v)", s.msg, fx(s.Code))
}

// FxCode returns the error code typed to match against the exported codes
func (s *StatusError) FxCode() fxerr {
	return fxerr(s.Code)
}

func getSupportedExtensionByName(extensionName string) (sshExtensionPair, error) {
	for _, supportedExtension := range supportedSFTPExtensions {
		if supportedExtension.Name == extensionName {
			return supportedExtension, nil
		}
	}
	return sshExtensionPair{}, errors.Errorf("unsupported extension: %s", extensionName)
}

// SetSFTPExtensions allows to customize the supported server extensions.
// See the variable supportedSFTPExtensions for supported extensions.
// This method accepts a slice of sshExtensionPair names for example 'hardlink@openssh.com'.
// If an invalid extension is given an error will be returned and nothing will be changed
func SetSFTPExtensions(extensions ...string) error {
	tempExtensions := []sshExtensionPair{}
	for _, extension := range extensions {
		sftpExtension, err := getSupportedExtensionByName(extension)
		if err != nil {
			return err
		}
		tempExtensions = append(tempExtensions, sftpExtension)
	}
	sftpExtensions = tempExtensions
	return nil
}
<|endoftext|>


<commit_before>package main

// copyright(c) 2014, Jason E. Aten
//
// goq : a simple queueing system in go; qsub replacement.
//

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"time"
)

// pass by value to avoid races
func (w *Worker) Shepard(jobPtr *Job) {

	// to avoid data races, make a copy of the job value
	j := *jobPtr

	// reset our input channel
	w.DrainTellShepPidKilled()

	go func() {
		myPid := 0

		defer func() {
			// if myPid set then ShepSaysJobStarted already signalled.
			// otherwise indicate error:
			if myPid == 0 {
				w.ShepSaysJobStarted <- 0
			}
			WPrintf("end of SHEP: just before w.ShepSaysJobDone <- j\n")
			w.ShepSaysJobDone <- &j
			WPrintf("end of SHEP: just after w.ShepSaysJobDone <- j\n")
		}()

		jid := j.Id
		dir := j.Dir
		cmd := j.Cmd
		args := j.Args
		env := CreateShepardedEnv(j.Env)
		if j.Out == nil {
			j.Out = make([]string, 0)
		}
		var origdir string
		var err error
		origdir, err = os.Getwd()
		if err != nil {
			panic(err)
		}

		if dir != "" {
			err = os.Chdir(dir)
			if err != nil {
				j.Out = append(j.Out, fmt.Sprintf("Shepard got error trying to move to submit directory with os.Chdir('%s'): %s", dir, err))
				return
			}
			// go back to our starting dir at the end of shepding this job.
			defer os.Chdir(origdir)
		}

		var path string
		var c *exec.Cmd
		path, err = MakeShellScript(cmd, args, dir)
		if err != nil {
			j.Out = append(j.Out, fmt.Sprintf("Shepard got error trying to create bash shell script in dir '%s': %s", dir, err))
			return
		}
		defer os.Remove(path)
		c = exec.Command(path)

		// old, not-run-in-shell style:
		//c = exec.Command(cmd, args...)

		c.Dir = dir
		c.Env = env

		var oe bytes.Buffer
		c.Stdout = &oe
		c.Stderr = &oe

		//	oe, err = c.CombinedOutput()
		err = c.Start()
		if err != nil {
			j.Out = append(j.Out, fmt.Sprintf("Shepard finds non-nil err on trying to Start() cmd '%s' in dir '%s': %s", cmd, dir, err))
			return
		}

		// no error/return should be possible between
		// setting myPid and w.ShepSaysJobStarted <- myPid
		myPid = c.Process.Pid
		j.Pid = int64(myPid)
		VPrintf("\n SHEP Shepard goroutine about to block on w.ShepSaysJobStarted <- j\n")
		w.ShepSaysJobStarted <- myPid
		VPrintf("\n SHEP Shepard goroutine about to block on c.Wait()\n")

		// this c.Wait() can be 15-20 seconds *slooooow*, so also wait on TellShepPidKilled
		//  to speed things up.
		err = nil
		// waitDone is buffered so this next short goro can exit immediately after c.Wait() finishes.
		// i.e. if TellShepPidKilled arrives first, then there will never be a receiver, so
		// without the buffering the channel and goroutine would be blocked, uncollectable, waiting-forever garbage/leak.
		waitDone := make(chan error, 1)
		go func() {
			err = c.Wait()
			waitDone <- err
		}()

		// back in shep goroutine:
		select {
		case err = <-waitDone:
		case killedPid := <-w.TellShepPidKilled:
			if killedPid != myPid {
				panic(fmt.Sprintf("SHEP error: mismatch in myPid(%d) vs killedPid(%d) received on w.TellShepPidKilled", myPid, killedPid))
			}
			j.Cancelled = true
			WPrintf("\n SHEP got notice from w.TellShepPidKilled, setting j.Cancelled = true\n")
		}

		// Now set j.Out based on which of the two cases we just saw:
		//  Either we saw w.TellShepPidKilled, in which case j.Cancelled == true and we want to exit quickly.
		//  Otherwise, we had a normal or fast c.Wait() exit, and we want to gather and send output on j.Out.
		//
		if j.Cancelled {
			j.Out = append(j.Out, fmt.Sprintf("cancelled/killed: job %d / pid %d ; cmd '%s' in dir '%s' on worker '%s' at '%s'", jid, myPid, cmd, dir, j.Workeraddr, time.Now()))

			// Don't wait around for output/etc.
			// Just skip down to ShepSaysJobDone and get out of here fast.

		} else {
			// Normal/Fast c.Wait() exit:
			WPrintf("\n SHEP DONE with WAIT, err: '%s'\n", err)
			if err != nil && err.Error() == "signal: killed" {
				WPrintf("\n SHEP found 'signal:killed', setting j.Cancelled = true\n")
				j.Cancelled = true
			}
			s := string(oe.Bytes())
			strings.Trim(s, "\n")
			slen := len(s)
			out := strings.Split(s, "\n")
			// if file ended in '\n' then we now have an extra empty line to eliminate.
			N := len(out)
			if slen > 0 && s[slen-1] == '\n' && N > 0 && out[N-1] == "" {
				out = out[:N-1]
			}
			j.Out = append(j.Out, out...)

			if err != nil {
				j.Out = append(j.Out, fmt.Sprintf("Shepard finds non-nil err on trying to Wait() on cmd '%s' in dir '%s': %s", cmd, dir, err))
			}
		}
	}()
}

func CreateShepardedEnv(jobenv []string) []string {
	// for now, ignore job sub-env and just use local worker env.
	return os.Environ()
}
<commit_msg>set job.Failed and job.Err if exec.Wait() returned non-nil err<commit_after>package main

// copyright(c) 2014, Jason E. Aten
//
// goq : a simple queueing system in go; qsub replacement.
//

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"time"
)

// pass by value to avoid races
func (w *Worker) Shepard(jobPtr *Job) {

	// to avoid data races, make a copy of the job value
	j := *jobPtr

	// reset our input channel
	w.DrainTellShepPidKilled()

	go func() {
		myPid := 0

		defer func() {
			// if myPid set then ShepSaysJobStarted already signalled.
			// otherwise indicate error:
			if myPid == 0 {
				w.ShepSaysJobStarted <- 0
			}
			WPrintf("end of SHEP: just before w.ShepSaysJobDone <- j\n")
			w.ShepSaysJobDone <- &j
			WPrintf("end of SHEP: just after w.ShepSaysJobDone <- j\n")
		}()

		jid := j.Id
		dir := j.Dir
		cmd := j.Cmd
		args := j.Args
		env := CreateShepardedEnv(j.Env)
		if j.Out == nil {
			j.Out = make([]string, 0)
		}
		var origdir string
		var err error
		origdir, err = os.Getwd()
		if err != nil {
			panic(err)
		}

		if dir != "" {
			err = os.Chdir(dir)
			if err != nil {
				j.Out = append(j.Out, fmt.Sprintf("Shepard got error trying to move to submit directory with os.Chdir('%s'): %s", dir, err))
				return
			}
			// go back to our starting dir at the end of shepding this job.
			defer os.Chdir(origdir)
		}

		var path string
		var c *exec.Cmd
		path, err = MakeShellScript(cmd, args, dir)
		if err != nil {
			j.Out = append(j.Out, fmt.Sprintf("Shepard got error trying to create bash shell script in dir '%s': %s", dir, err))
			return
		}
		defer os.Remove(path)
		c = exec.Command(path)

		// old, not-run-in-shell style:
		//c = exec.Command(cmd, args...)

		c.Dir = dir
		c.Env = env

		var oe bytes.Buffer
		c.Stdout = &oe
		c.Stderr = &oe

		//	oe, err = c.CombinedOutput()
		err = c.Start()
		if err != nil {
			j.Out = append(j.Out, fmt.Sprintf("Shepard finds non-nil err on trying to Start() cmd '%s' in dir '%s': %s", cmd, dir, err))
			return
		}

		// no error/return should be possible between
		// setting myPid and w.ShepSaysJobStarted <- myPid
		myPid = c.Process.Pid
		j.Pid = int64(myPid)
		VPrintf("\n SHEP Shepard goroutine about to block on w.ShepSaysJobStarted <- j\n")
		w.ShepSaysJobStarted <- myPid
		VPrintf("\n SHEP Shepard goroutine about to block on c.Wait()\n")

		// this c.Wait() can be 15-20 seconds *slooooow*, so also wait on TellShepPidKilled
		//  to speed things up.
		err = nil
		// waitDone is buffered so this next short goro can exit immediately after c.Wait() finishes.
		// i.e. if TellShepPidKilled arrives first, then there will never be a receiver, so
		// without the buffering the channel and goroutine would be blocked, uncollectable, waiting-forever garbage/leak.
		waitDone := make(chan error, 1)
		go func() {
			err = c.Wait()
			waitDone <- err
		}()

		// back in shep goroutine:
		select {
		case err = <-waitDone:
		case killedPid := <-w.TellShepPidKilled:
			if killedPid != myPid {
				panic(fmt.Sprintf("SHEP error: mismatch in myPid(%d) vs killedPid(%d) received on w.TellShepPidKilled", myPid, killedPid))
			}
			j.Cancelled = true
			WPrintf("\n SHEP got notice from w.TellShepPidKilled, setting j.Cancelled = true\n")
		}

		// Now set j.Out based on which of the two cases we just saw:
		//  Either we saw w.TellShepPidKilled, in which case j.Cancelled == true and we want to exit quickly.
		//  Otherwise, we had a normal or fast c.Wait() exit, and we want to gather and send output on j.Out.
		//
		if j.Cancelled {
			j.Out = append(j.Out, fmt.Sprintf("cancelled/killed: job %d / pid %d ; cmd '%s' in dir '%s' on worker '%s' at '%s'", jid, myPid, cmd, dir, j.Workeraddr, time.Now()))

			// Don't wait around for output/etc.
			// Just skip down to ShepSaysJobDone and get out of here fast.

		} else {
			// Normal/Fast c.Wait() exit:
			WPrintf("\n SHEP DONE with WAIT, err: '%s'\n", err)
			if err != nil && err.Error() == "signal: killed" {
				WPrintf("\n SHEP found 'signal:killed', setting j.Cancelled = true\n")
				j.Cancelled = true
			}
			if err != nil {
				j.Err = err.Error()
				j.Failed = true
			}
			s := string(oe.Bytes())
			strings.Trim(s, "\n")
			slen := len(s)
			out := strings.Split(s, "\n")
			// if file ended in '\n' then we now have an extra empty line to eliminate.
			N := len(out)
			if slen > 0 && s[slen-1] == '\n' && N > 0 && out[N-1] == "" {
				out = out[:N-1]
			}
			j.Out = append(j.Out, out...)

			if err != nil {
				j.Out = append(j.Out, fmt.Sprintf("Shepard finds non-nil err on trying to Wait() on cmd '%s' in dir '%s': %s", cmd, dir, err))
			}
		}
	}()
}

func CreateShepardedEnv(jobenv []string) []string {
	// for now, ignore job sub-env and just use local worker env.
	return os.Environ()
}
<|endoftext|>


<commit_before>package simp

import (
	"database/sql"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"
)

type DriverName string

const (
	MySQL      = DriverName("mysql")
	PostgreSQL = DriverName("postgres")

	defaultLocalAddress = "127.0.0.1"
	mysqlDefaultPort    = 3306
	postgresDefaultPort = 5432
)

func (dn DriverName) String() string {
	return string(dn)
}

type Dsn string
type DsnConf struct {
	UserName string
	Password string
	Protocol string
	Address  string
	Port     int
	DbName   string
	Params   map[string]string
}

func (dsn Dsn) String() string {
	return string(dsn)
}

func (dc DsnConf) DSN(dn DriverName) (dsn Dsn, err error) {
	switch {
	case len(dc.UserName) == 0:
		return "", errors.New("UserName is Empty")
	case (len(dc.Address) > 0 && dc.Address != "localhost" && dc.Address != defaultLocalAddress) &&
		len(dc.Password) == 0:
		return "", errors.New("Password is Empty")
	case len(dc.DbName) == 0:
		return "", errors.New("DbName is Empty")
	}
	switch dn {
	case MySQL:
		return Dsn(fmt.Sprintf(
			"%s%s@%s(%s:%d)/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Protocol) == 0 {
					return "tcp"
				} else {
					return dc.Protocol
				}
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return mysqlDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			func() string {
				var buf string
				if len(dc.Params) > 0 {
					for k, v := range dc.Params {
						buf += "&" + k + "=" + v
					}
					buf = strings.Replace(buf, "&", "?", 1)
				}
				return buf
			}(),
		)), nil
	case PostgreSQL:
		return Dsn(fmt.Sprintf(
			"postgres://%s%s@%s:%d/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return postgresDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			func() string {
				var buf string
				if len(dc.Params) > 0 {
					for k, v := range dc.Params {
						buf += "&" + k + "=" + v
					}
					buf = strings.Replace(buf, "&", "?", 1)
				}
				return buf
			}(),
		)), nil
	default:
		return "", errors.New("undefined driver name was used")
	}
}

// DB is a database object.
type DB struct {
	db  *sql.DB
	tx  *sql.Tx
	mx  sync.Mutex
	err error
}

// New returns a new *DB.
// If error, error is set in *DB.err.
// You can get *DB.err with *DB.Error ().
func New(dn DriverName, dsn Dsn) *DB {
	if db, err := sql.Open(dn.String(), dsn.String()); err != nil {
		return &DB{err: err}
	} else {
		return &DB{db: db}
	}
}

// Ping will check if it can connect to the specified database.
func (db *DB) Ping() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	return db.db.Ping()
}

// Begin starts transaction.
func (db *DB) Begin() error {
	var tx *sql.Tx
	tx, db.err = db.db.Begin()
	if db.err != nil {
		return db.err
	}
	db.mx.Lock()
	defer db.mx.Unlock()
	db.tx = tx
	return nil
}

// Close closes database.
func (db *DB) Close() {
	db.err = db.db.Close()
}

// Commit commits the transacrion.
// Begin needs to be executed before this method is executed.
func (db *DB) Commit() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Commit()
	db.tx = nil
	return err
}

// Rollback rolls back transaction.
// Begin needs to be executed before this method is executed.
func (db *DB) Rollback() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Rollback()
	db.tx = nil
	return err
}

// Exec executes a prepared statement with the specified arguments.
// And this method returns a Result summarizing the effect of the statement.
func (db *DB) Exec(query string, args ...interface{}) (ret sql.Result, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Exec(query, args...)
	default:
		return db.tx.Exec(query, args...)
	}
}

// The query executes a prepared query statement with the specified arguments
// and returns the query result as *sql.Rows.
func (db *DB) Query(query string, args ...interface{}) (ret *sql.Rows, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Query(query, args...)
	default:
		return db.tx.Query(query, args...)
	}
}

// QueryRow executes a prepared query statement with the specified arguments.
// Scans the first selected line and returns it as *sql.Row.
// It will be destroyed after that.
func (db *DB) QueryRow(query string, args ...interface{}) (ret *sql.Row) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret
	}

	switch db.tx {
	case nil:
		return db.db.QueryRow(query, args...)
	default:
		return db.tx.QueryRow(query, args...)
	}
}

// The error returns *DB.err.
func (db *DB) Error() error {
	return db.err
}

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
// Expired connections may be closed lazily before reuse.
// If d <= 0, connections are reused forever.
func (db *DB) SetConnMaxLifetime(d time.Duration) {
	db.db.SetConnMaxLifetime(d)
}

// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
// If n <= 0, no idle connections are retained.
func (db *DB) SetMaxIdleConns(n int) {
	db.db.SetMaxIdleConns(n)
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
// MaxIdleConns, then MaxIdleConns will be reduced to match the new
// MaxOpenConns limit
// If n <= 0, then there is no limit on the number of open connections.
// The default is 0 (unlimited).
func (db *DB) SetMaxOpenConns(n int) {
	db.db.SetMaxOpenConns(n)
}

// Prepare creates a prepared statement for later queries or executions.
func (db *DB) Prepare(query string, args ...interface{}) (*sql.Stmt, error) {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return db.db.Prepare(query)
	} else {
		return db.tx.Prepare(query)
	}
}
<commit_msg>added comments<commit_after>package simp

import (
	"database/sql"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"
)

type DriverName string

const (
	MySQL      = DriverName("mysql")
	PostgreSQL = DriverName("postgres")

	defaultLocalAddress = "127.0.0.1"
	mysqlDefaultPort    = 3306
	postgresDefaultPort = 5432
)

// String returns the converted string from of DriverName.
func (dn DriverName) String() string {
	return string(dn)
}

type Dsn string
type DsnConf struct {
	UserName string
	Password string
	Protocol string
	Address  string
	Port     int
	DbName   string
	Params   map[string]string
}

// String returns the converted string from of Dsn.
func (dsn Dsn) String() string {
	return string(dsn)
}

// DSN returns Dsn based on DsnConf and DriverName.
func (dc DsnConf) DSN(dn DriverName) (dsn Dsn, err error) {
	switch {
	case len(dc.UserName) == 0:
		return "", errors.New("UserName is Empty")
	case (len(dc.Address) > 0 && dc.Address != "localhost" && dc.Address != defaultLocalAddress) &&
		len(dc.Password) == 0:
		return "", errors.New("Password is Empty")
	case len(dc.DbName) == 0:
		return "", errors.New("DbName is Empty")
	}
	switch dn {
	case MySQL:
		return Dsn(fmt.Sprintf(
			"%s%s@%s(%s:%d)/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Protocol) == 0 {
					return "tcp"
				} else {
					return dc.Protocol
				}
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return mysqlDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			func() string {
				var buf string
				if len(dc.Params) > 0 {
					for k, v := range dc.Params {
						buf += "&" + k + "=" + v
					}
					buf = strings.Replace(buf, "&", "?", 1)
				}
				return buf
			}(),
		)), nil
	case PostgreSQL:
		return Dsn(fmt.Sprintf(
			"postgres://%s%s@%s:%d/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return postgresDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			func() string {
				var buf string
				if len(dc.Params) > 0 {
					for k, v := range dc.Params {
						buf += "&" + k + "=" + v
					}
					buf = strings.Replace(buf, "&", "?", 1)
				}
				return buf
			}(),
		)), nil
	default:
		return "", errors.New("undefined driver name was used")
	}
}

// DB is a database object.
type DB struct {
	db  *sql.DB
	tx  *sql.Tx
	mx  sync.Mutex
	err error
}

// New returns a new *DB.
// If error, error is set in *DB.err.
// You can get *DB.err with *DB.Error ().
func New(dn DriverName, dsn Dsn) *DB {
	if db, err := sql.Open(dn.String(), dsn.String()); err != nil {
		return &DB{err: err}
	} else {
		return &DB{db: db}
	}
}

// Ping will check if it can connect to the specified database.
func (db *DB) Ping() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	return db.db.Ping()
}

// Begin starts transaction.
func (db *DB) Begin() error {
	var tx *sql.Tx
	tx, db.err = db.db.Begin()
	if db.err != nil {
		return db.err
	}
	db.mx.Lock()
	defer db.mx.Unlock()
	db.tx = tx
	return nil
}

// Close closes database.
func (db *DB) Close() {
	db.err = db.db.Close()
}

// Commit commits the transacrion.
// Begin needs to be executed before this method is executed.
func (db *DB) Commit() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Commit()
	db.tx = nil
	return err
}

// Rollback rolls back transaction.
// Begin needs to be executed before this method is executed.
func (db *DB) Rollback() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Rollback()
	db.tx = nil
	return err
}

// Exec executes a prepared statement with the specified arguments.
// And this method returns a Result summarizing the effect of the statement.
func (db *DB) Exec(query string, args ...interface{}) (ret sql.Result, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Exec(query, args...)
	default:
		return db.tx.Exec(query, args...)
	}
}

// The query executes a prepared query statement with the specified arguments
// and returns the query result as *sql.Rows.
func (db *DB) Query(query string, args ...interface{}) (ret *sql.Rows, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Query(query, args...)
	default:
		return db.tx.Query(query, args...)
	}
}

// QueryRow executes a prepared query statement with the specified arguments.
// Scans the first selected line and returns it as *sql.Row.
// It will be destroyed after that.
func (db *DB) QueryRow(query string, args ...interface{}) (ret *sql.Row) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret
	}

	switch db.tx {
	case nil:
		return db.db.QueryRow(query, args...)
	default:
		return db.tx.QueryRow(query, args...)
	}
}

// The error returns *DB.err.
func (db *DB) Error() error {
	return db.err
}

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
// Expired connections may be closed lazily before reuse.
// If d <= 0, connections are reused forever.
func (db *DB) SetConnMaxLifetime(d time.Duration) {
	db.db.SetConnMaxLifetime(d)
}

// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
// If n <= 0, no idle connections are retained.
func (db *DB) SetMaxIdleConns(n int) {
	db.db.SetMaxIdleConns(n)
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
// MaxIdleConns, then MaxIdleConns will be reduced to match the new
// MaxOpenConns limit
// If n <= 0, then there is no limit on the number of open connections.
// The default is 0 (unlimited).
func (db *DB) SetMaxOpenConns(n int) {
	db.db.SetMaxOpenConns(n)
}

// Prepare creates a prepared statement for later queries or executions.
func (db *DB) Prepare(query string, args ...interface{}) (*sql.Stmt, error) {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return db.db.Prepare(query)
	} else {
		return db.tx.Prepare(query)
	}
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package main

import (
	"html/template"
	"net/http"
	"path"
)

type Site struct {
	templates *template.Template
}

var (
	site Site
)

func setupSite() {
	templatedir := path.Join(C.webroot, "templates")

	pattern := templatedir + "/*.tmpl"
	site.templates = template.Must(template.ParseGlob(pattern))
}

func siteHomeHandler(w http.ResponseWriter, req *http.Request) {
	// homepage

}
<commit_msg>site: render base template<commit_after>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package main

import (
	"html/template"
	"net/http"
	"path"
)

type Site struct {
	templates *template.Template
}

var (
	site Site
)

func setupSite() {
	templatedir := path.Join(C.webroot, "templates")

	pattern := templatedir + "/*.tmpl"
	site.templates = template.Must(template.ParseGlob(pattern))
}

func siteHomeHandler(w http.ResponseWriter, req *http.Request) {
	// homepage

	err := site.templates.ExecuteTemplate(w, "base", nil)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
<|endoftext|>


<commit_before>package violetear

import (
	"fmt"
	"strings"
)

type Trie struct {
	Node    map[string]*Trie
	Handler map[string]string
	Level   int
}

func NewTrie() *Trie {
	t := &Trie{}
	t.Node = make(map[string]*Trie)
	t.Handler = make(map[string]string)
	return t
}

func (t *Trie) Set(path []string, handler string, method string, level ...bool) {
	key := path[0]
	newpath := path[1:]

	val, ok := t.Node[key]

	if !ok {
		val = NewTrie()
		t.Node[key] = val

		// increment level
		if len(level) > 0 {
			val.Level = t.Level + 1
		}
	}

	if len(newpath) == 0 {
		methods := strings.Split(method, ",")
		for _, v := range methods {
			val.Handler[strings.TrimSpace(v)] = handler
		}
		return
	}

	// recursive call with 4 argument set to true so that level can be
	// increased by 1 if newpath > than 1
	val.Set(newpath, handler, method, true)
}

func (t *Trie) Get(path []string) *Trie {

	key := path[0]
	newpath := path[1:]

	fmt.Println(key, newpath, t.Level)

	if val, ok := t.Node[key]; ok {
		if len(newpath) == 0 {
			return val
		}
		return val.Get(newpath)
	}

	return t
}
<commit_msg>	modified:   trie.go<commit_after>package violetear

import (
	"strings"
)

type Trie struct {
	Node     map[string]*Trie
	Handler  map[string]string
	HasRegex bool
}

func NewTrie() *Trie {
	t := &Trie{}
	t.Node = make(map[string]*Trie)
	t.Handler = make(map[string]string)
	return t
}

func (t *Trie) Set(path []string, handler string, method string) {
	key := path[0]
	newpath := path[1:]

	val, ok := t.Node[key]

	if !ok {
		val = NewTrie()
		t.Node[key] = val

		// check for regex ":"
		if strings.HasPrefix(key, ":") {
			t.HasRegex = true
		}
	}

	if len(newpath) == 0 {
		methods := strings.Split(method, ",")
		for _, v := range methods {
			val.Handler[strings.TrimSpace(v)] = handler
		}
		return
	}

	val.Set(newpath, handler, method)
}

func (t *Trie) Get(path []string) (trie *Trie, leaf bool) {
	key := path[0]
	newpath := path[1:]

	if val, ok := t.Node[key]; ok {
		if len(newpath) == 0 {
			return val, true
		}
		return val.Get(newpath)
	}
	return t, false
}
<|endoftext|>


<commit_before>/*
Implementation of an R-Way Trie data structure.

A Trie has a root Node which is the base of the tree.
Each subsequent Node has a letter and children, which are
nodes that have letter values associated with them.
*/

package trie

import (
	"bufio"
	"log"
	"os"
	"sort"
)

type Node struct {
	val      rune
	term     bool
	mask     uint64
	parent   *Node
	children map[rune]*Node
}

type Trie struct {
	root *Node
	size int
}

const nul = 0x0

func newNode(parent *Node, val rune, m uint64, term bool) *Node {
	return &Node{
		val:      val,
		mask:     m,
		term:     term,
		parent:   parent,
		children: make(map[rune]*Node),
	}
}

// Creates and returns a pointer to a new child for the node.
func (n *Node) NewChild(parent *Node, r rune, bitmask uint64, val rune, term bool) *Node {
	node := newNode(parent, val, bitmask, term)
	n.children[r] = node
	return node
}

func (n *Node) RemoveChild(r rune) {
	delete(n.children, r)

	n.recalculateMask()
	for parent := n.Parent(); parent != nil; parent = parent.Parent() {
		parent.recalculateMask()
	}
}

func (n *Node) recalculateMask() {
	n.mask = maskrune(n.Val())
	for k, c := range n.Children() {
		n.mask |= (maskrune(k) | c.Mask())
	}
}

// Returns the parent of this node.
func (n Node) Parent() *Node {
	return n.parent
}

// Returns the children of this node.
func (n Node) Children() map[rune]*Node {
	return n.children
}

func (n Node) Val() rune {
	return n.val
}

// Returns a uint64 representing the current
// mask of this node.
func (n Node) Mask() uint64 {
	return n.mask
}

// Creates a new Trie with an initialized root Node.
func CreateTrie() *Trie {
	node := newNode(nil, 0, 0, false)
	return &Trie{
		root: node,
		size: 0,
	}
}

// Returns the root node for the Trie.
func (t *Trie) Root() *Node {
	return t.root
}

// Adds the key to the Trie.
func (t *Trie) Add(key string) int {
	t.size++
	runes := []rune(key)
	return t.addrune(t.Root(), runes, 0)
}

// Removes a key from the trie, ensuring that
// all bitmasks up to root are appropriately recalculated.
func (t *Trie) Remove(key string) {
	var (
		i    int
		rs   = []rune(key)
		node = t.nodeAtPath(key)
	)

	t.size--
	for n := node.Parent(); n != nil; n = n.Parent() {
		i++
		if len(n.Children()) > 1 {
			r := rs[len(rs)-i]
			n.RemoveChild(r)
			break
		}
	}
}

// Reads words from a file and adds them to the
// trie. Expects words to be seperated by a newline.
func (t *Trie) AddFromFile(path string) {
	file, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}

	reader := bufio.NewScanner(file)

	for reader.Scan() {
		t.Add(reader.Text())
	}

	if reader.Err() != nil {
		log.Fatal(err)
	}
}

// Returns all the keys currently stored in the trie.
func (t *Trie) Keys() []string {
	return t.PrefixSearch("")
}

// Performs a fuzzy search against the keys in the trie.
func (t Trie) FuzzySearch(pre string) []string {
	var (
		keys []string
		pm   []rune
	)

	fuzzycollect(t.Root(), pm, []rune(pre), &keys)
	sort.Strings(keys)
	return keys
}

// Performs a prefix search against the keys in the trie.
func (t Trie) PrefixSearch(pre string) []string {
	var keys []string

	node := t.nodeAtPath(pre)
	if node == nil {
		return keys
	}

	collect(node, []rune(pre), &keys)
	return keys
}

func (t Trie) nodeAtPath(pre string) *Node {
	runes := []rune(pre)
	return findNode(t.Root(), runes, 0)
}

func findNode(node *Node, runes []rune, d int) *Node {
	if node == nil {
		return nil
	}

	if len(runes) == 0 {
		return node
	}

	upper := len(runes)
	if d == upper {
		return node
	}

	n, ok := node.Children()[runes[d]]
	if !ok {
		return nil
	}

	d++
	return findNode(n, runes, d)
}

func (t Trie) addrune(node *Node, runes []rune, i int) int {
	if len(runes) == 0 {
		node.NewChild(node, 0, 0, nul, true)
		return i
	}

	r := runes[0]
	c := node.Children()

	n, ok := c[r]
	bitmask := maskruneslice(runes)
	if !ok {
		n = node.NewChild(node, r, bitmask, r, false)
	}
	n.mask |= bitmask

	i++
	return t.addrune(n, runes[1:], i)
}

func maskruneslice(rs []rune) uint64 {
	var m uint64
	for _, r := range rs {
		m |= maskrune(r)
	}

	return m
}

func maskrune(r rune) uint64 {
	i := uint64(1)
	return i << (uint64(r) - 97)
}

func collect(node *Node, pre []rune, keys *[]string) {
	children := node.Children()
	for r, n := range children {
		if n.term {
			*keys = append(*keys, string(pre))
			continue
		}

		npre := append(pre, r)
		collect(n, npre, keys)
	}
}

func fuzzycollect(node *Node, partialmatch, partial []rune, keys *[]string) {
	partiallen := len(partial)

	if partiallen == 0 {
		collect(node, partialmatch, keys)
		return
	}

	m := maskruneslice(partial)
	children := node.Children()
	for v, n := range children {
		xor := n.Mask() ^ m
		if (xor & m) != 0 {
			continue
		}

		npartial := partial
		if v == partial[0] {
			if partiallen > 1 {
				npartial = partial[1:]
			} else {
				npartial = partial[0:0]
			}
		}

		fuzzycollect(n, append(partialmatch, v), npartial, keys)
	}
}
<commit_msg>Change comment style<commit_after>// Implementation of an R-Way Trie data structure.
//
// A Trie has a root Node which is the base of the tree.
// Each subsequent Node has a letter and children, which are
// nodes that have letter values associated with them.

package trie

import (
	"bufio"
	"log"
	"os"
	"sort"
)

type Node struct {
	val      rune
	term     bool
	mask     uint64
	parent   *Node
	children map[rune]*Node
}

type Trie struct {
	root *Node
	size int
}

const nul = 0x0

func newNode(parent *Node, val rune, m uint64, term bool) *Node {
	return &Node{
		val:      val,
		mask:     m,
		term:     term,
		parent:   parent,
		children: make(map[rune]*Node),
	}
}

// Creates and returns a pointer to a new child for the node.
func (n *Node) NewChild(parent *Node, r rune, bitmask uint64, val rune, term bool) *Node {
	node := newNode(parent, val, bitmask, term)
	n.children[r] = node
	return node
}

func (n *Node) RemoveChild(r rune) {
	delete(n.children, r)

	n.recalculateMask()
	for parent := n.Parent(); parent != nil; parent = parent.Parent() {
		parent.recalculateMask()
	}
}

func (n *Node) recalculateMask() {
	n.mask = maskrune(n.Val())
	for k, c := range n.Children() {
		n.mask |= (maskrune(k) | c.Mask())
	}
}

// Returns the parent of this node.
func (n Node) Parent() *Node {
	return n.parent
}

// Returns the children of this node.
func (n Node) Children() map[rune]*Node {
	return n.children
}

func (n Node) Val() rune {
	return n.val
}

// Returns a uint64 representing the current
// mask of this node.
func (n Node) Mask() uint64 {
	return n.mask
}

// Creates a new Trie with an initialized root Node.
func CreateTrie() *Trie {
	node := newNode(nil, 0, 0, false)
	return &Trie{
		root: node,
		size: 0,
	}
}

// Returns the root node for the Trie.
func (t *Trie) Root() *Node {
	return t.root
}

// Adds the key to the Trie.
func (t *Trie) Add(key string) int {
	t.size++
	runes := []rune(key)
	return t.addrune(t.Root(), runes, 0)
}

// Removes a key from the trie, ensuring that
// all bitmasks up to root are appropriately recalculated.
func (t *Trie) Remove(key string) {
	var (
		i    int
		rs   = []rune(key)
		node = t.nodeAtPath(key)
	)

	t.size--
	for n := node.Parent(); n != nil; n = n.Parent() {
		i++
		if len(n.Children()) > 1 {
			r := rs[len(rs)-i]
			n.RemoveChild(r)
			break
		}
	}
}

// Reads words from a file and adds them to the
// trie. Expects words to be seperated by a newline.
func (t *Trie) AddFromFile(path string) {
	file, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}

	reader := bufio.NewScanner(file)

	for reader.Scan() {
		t.Add(reader.Text())
	}

	if reader.Err() != nil {
		log.Fatal(err)
	}
}

// Returns all the keys currently stored in the trie.
func (t *Trie) Keys() []string {
	return t.PrefixSearch("")
}

// Performs a fuzzy search against the keys in the trie.
func (t Trie) FuzzySearch(pre string) []string {
	var (
		keys []string
		pm   []rune
	)

	fuzzycollect(t.Root(), pm, []rune(pre), &keys)
	sort.Strings(keys)
	return keys
}

// Performs a prefix search against the keys in the trie.
func (t Trie) PrefixSearch(pre string) []string {
	var keys []string

	node := t.nodeAtPath(pre)
	if node == nil {
		return keys
	}

	collect(node, []rune(pre), &keys)
	return keys
}

func (t Trie) nodeAtPath(pre string) *Node {
	runes := []rune(pre)
	return findNode(t.Root(), runes, 0)
}

func findNode(node *Node, runes []rune, d int) *Node {
	if node == nil {
		return nil
	}

	if len(runes) == 0 {
		return node
	}

	upper := len(runes)
	if d == upper {
		return node
	}

	n, ok := node.Children()[runes[d]]
	if !ok {
		return nil
	}

	d++
	return findNode(n, runes, d)
}

func (t Trie) addrune(node *Node, runes []rune, i int) int {
	if len(runes) == 0 {
		node.NewChild(node, 0, 0, nul, true)
		return i
	}

	r := runes[0]
	c := node.Children()

	n, ok := c[r]
	bitmask := maskruneslice(runes)
	if !ok {
		n = node.NewChild(node, r, bitmask, r, false)
	}
	n.mask |= bitmask

	i++
	return t.addrune(n, runes[1:], i)
}

func maskruneslice(rs []rune) uint64 {
	var m uint64
	for _, r := range rs {
		m |= maskrune(r)
	}

	return m
}

func maskrune(r rune) uint64 {
	i := uint64(1)
	return i << (uint64(r) - 97)
}

func collect(node *Node, pre []rune, keys *[]string) {
	children := node.Children()
	for r, n := range children {
		if n.term {
			*keys = append(*keys, string(pre))
			continue
		}

		npre := append(pre, r)
		collect(n, npre, keys)
	}
}

func fuzzycollect(node *Node, partialmatch, partial []rune, keys *[]string) {
	partiallen := len(partial)

	if partiallen == 0 {
		collect(node, partialmatch, keys)
		return
	}

	m := maskruneslice(partial)
	children := node.Children()
	for v, n := range children {
		xor := n.Mask() ^ m
		if (xor & m) != 0 {
			continue
		}

		npartial := partial
		if v == partial[0] {
			if partiallen > 1 {
				npartial = partial[1:]
			} else {
				npartial = partial[0:0]
			}
		}

		fuzzycollect(n, append(partialmatch, v), npartial, keys)
	}
}
<|endoftext|>


<commit_before>package web

import (
	"fmt"
	"strings"
)

// Controller interface
type Controller interface {
	Index(ctx *Context)
	Create(ctx *Context)
	Detail(ctx *Context)
	Update(ctx *Context)
	Destroy(ctx *Context)
}

// Validation interface
type Validation interface {
	Validate() ValidationError
}

// AttributeError struct
type AttributeError struct {
	Name  string `json:"name"`
	Error error  `json:"error"`
}

// ValidationError Error Collection
type ValidationError []AttributeError

// CreateValidationError return new ValidationError
func CreateValidationError() *ValidationError {
	return &ValidationError{}
}

func (validationError ValidationError) Error() string {
	var str strings.Builder

	for _, attributeError := range validationError {
		fmt.Fprintf(&str, "%s: %v", attributeError.Name, attributeError.Error)
	}

	return str.String()
}
<commit_msg>clean code<commit_after>package web

import (
	"fmt"
	"strings"
)

// Controller interface
type Controller interface {
	Index(ctx *Context)
	Create(ctx *Context)
	Detail(ctx *Context)
	Update(ctx *Context)
	Destroy(ctx *Context)
}

// Validation interface
type Validation interface {
	Validate() ValidationError
}

// AttributeError struct
type AttributeError struct {
	Name  string `json:"name"`
	Error string `json:"error"`
}

// ValidationError Error Collection
type ValidationError []AttributeError

func (validationError ValidationError) Error() string {
	var str strings.Builder

	for _, attributeError := range validationError {
		fmt.Fprintf(&str, "%s: %v", attributeError.Name, attributeError.Error)
	}

	return str.String()
}
<|endoftext|>


<commit_before>package gitinfo

import (
	"fmt"
	"os"

	"github.com/denormal/go-gitconfig"
)

// User is the interface representing the git user.
type User interface {
	// Name returns the name of the current git user, or the empty string
	// if no name is configured.
	Name() string

	// Email returns the e-mail addrdd of the current git user, or the empty
	// string if no e-mail address is configured.
	Email() string

	// String() returns a string representation of the git user's name and
	// e-mail address, or the empty string if neither are defined.
	String() string
}

// user is the implementation of the User interface
type user struct {
	name  string
	email string
}

// newUser returns the user instance as detailed in the given git configuration
func newUser(config gitconfig.GitConfig) User {
	// extract the name & email from the git configuration
	_name := ""
	if config != nil {
		_config := config.Get("user.name")
		if _config != nil {
			_name = _config.String()
		}
	}
	_email := ""
	if config != nil {
		_config = config.Get("user.email")
		if _config != nil {
			_email = _config.String()
		}
	}

	return &user{name: _name, email: _email}
} // newUser()

// Name returns the name of the current git user, or the empty string
// if no name is configured.
func (u *user) Name() string {
	// is the git user name defined in the environment?
	_n := os.Getenv("GIT_AUTHOR_NAME")
	if _n == "" {
		_n = os.Getenv("GIT_COMMITTER_NAME")
		if _n == "" {
			_n = u.name
		}
	}

	return _n
} // Name()

// Email returns the e-mail addrdd of the current git user, or the empty
// string if no e-mail address is configured.
func (u *user) Email() string {
	// is the git user e-mail defined in the environment?
	_e := os.Getenv("GIT_AUTHOR_EMAIL")
	if _e == "" {
		_e = os.Getenv("GIT_COMMITTER_EMAIL")
		if _e == "" {
			_e = u.email
			if _e == "" {
				_e = os.Getenv("EMAIL")
			}
		}
	}

	return _e
} // Email()

// String() returns a string representation of the git user's name and
// e-mail address, or the empty string if neither are defined.
func (u *user) String() string {
	_name := u.Name()
	_email := u.Email()

	if _name == "" {
		return _email
	} else if _email == "" {
		return _name
	} else {
		return fmt.Sprintf("%s <%s>", _name, _email)
	}
} // String()
<commit_msg>Corrected compilation failure.<commit_after>package gitinfo

import (
	"fmt"
	"os"

	"github.com/denormal/go-gitconfig"
)

// User is the interface representing the git user.
type User interface {
	// Name returns the name of the current git user, or the empty string
	// if no name is configured.
	Name() string

	// Email returns the e-mail addrdd of the current git user, or the empty
	// string if no e-mail address is configured.
	Email() string

	// String() returns a string representation of the git user's name and
	// e-mail address, or the empty string if neither are defined.
	String() string
}

// user is the implementation of the User interface
type user struct {
	name  string
	email string
}

// newUser returns the user instance as detailed in the given git configuration
func newUser(config gitconfig.GitConfig) User {
	// extract the name & email from the git configuration
	_name := ""
	if config != nil {
		_config := config.Get("user.name")
		if _config != nil {
			_name = _config.String()
		}
	}
	_email := ""
	if config != nil {
		_config := config.Get("user.email")
		if _config != nil {
			_email = _config.String()
		}
	}

	return &user{name: _name, email: _email}
} // newUser()

// Name returns the name of the current git user, or the empty string
// if no name is configured.
func (u *user) Name() string {
	// is the git user name defined in the environment?
	_n := os.Getenv("GIT_AUTHOR_NAME")
	if _n == "" {
		_n = os.Getenv("GIT_COMMITTER_NAME")
		if _n == "" {
			_n = u.name
		}
	}

	return _n
} // Name()

// Email returns the e-mail addrdd of the current git user, or the empty
// string if no e-mail address is configured.
func (u *user) Email() string {
	// is the git user e-mail defined in the environment?
	_e := os.Getenv("GIT_AUTHOR_EMAIL")
	if _e == "" {
		_e = os.Getenv("GIT_COMMITTER_EMAIL")
		if _e == "" {
			_e = u.email
			if _e == "" {
				_e = os.Getenv("EMAIL")
			}
		}
	}

	return _e
} // Email()

// String() returns a string representation of the git user's name and
// e-mail address, or the empty string if neither are defined.
func (u *user) String() string {
	_name := u.Name()
	_email := u.Email()

	if _name == "" {
		return _email
	} else if _email == "" {
		return _name
	} else {
		return fmt.Sprintf("%s <%s>", _name, _email)
	}
} // String()
<|endoftext|>


<commit_before>package gom

import (
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"
	"time"
)

func IsEmpty(v interface{}) bool {
	times := time.Time{}
	if times == v {
		return true
	}
	if v == "" {
		return true
	}
	if v == 0 {
		return true
	}
	if v == 0.0 {
		return true
	}
	if v == nil {
		return true
	}
	return false
}
func getType(v interface{}) (reflect.Type, bool, bool) {
	tt := reflect.TypeOf(v)
	isPtr := false
	islice := false
	if tt.Kind() == reflect.Ptr {
		tt = tt.Elem()
		isPtr = true
	}
	if tt.Kind() == reflect.Slice || tt.Kind() == reflect.Array {
		tt = tt.Elem()
		islice = true
	}
	if debug {
		fmt.Println("Test getType, result:", tt, isPtr, islice)
	}
	return tt, isPtr, islice
}

func GetTableModel(v interface{}, names ...string) (TableModel, error) {
	tms, err := getTableModel(v)
	if err != nil {
		return TableModel{}, nil
	}
	tm := tms[0]
	var cc []Column
	for _, ct := range tm.Columns {
		for _, name := range names {
			if ct.ColumnName == name {
				cc = append(cc, ct)
			}
		}
	}
	tm.Columns = cc
	return tm, nil

}
func CreateSingleValueTableModel(v interface{}, table string, field string) TableModel {
	tt, _, _ := getType(v)
	vals := reflect.New(tt).Elem()
	columns := []Column{{ColumnName: field, ColumnType: tt, IsPrimary: false, Auto: false}}
	return TableModel{Columns: columns, TableName: table, ModelType: tt, ModelValue: vals}
}
func getTableModels(vs ...interface{}) ([]TableModel, error) {
	tablemodels := []TableModel{}
	for _, v := range vs {
		tt, _, _ := getType(v)
		if tt.Kind() == reflect.Interface {
			return tablemodels, errors.New("can't use interface as struct")
		}
		tbs, err := getTableModel(v)
		if err != nil {
			return tablemodels, err
		}
		tablemodels = append(tablemodels, tbs...)
	}
	return tablemodels, nil
}
func getTableModel(v interface{}) ([]TableModel, error) {
	var tableModels []TableModel
	var values []reflect.Value
	tt, isPtr, isSlice := getType(v)
	if tt.NumField() == 0 || tt.NumMethod() == 0 {
		return tableModels, errors.New(tt.Name() + " is not a valid struct")
	}
	value := reflect.ValueOf(v)
	if v != nil && tt.Kind() != reflect.Interface {

		if isPtr {
			value = value.Elem()
		}
		if debug {
			fmt.Println("model info:", tt, isPtr, isSlice, value)
		}
		if isSlice {
			if value.Len() > 0 {
				for i := 0; i < value.Len(); i++ {
					val := value.Index(i)
					values = append(values, val)
				}
			} else {
				values = append(values, reflect.New(tt).Elem())
			}
		} else {
			values = append(values, value)
		}
		if debug {
			fmt.Println(values)
		}
		for _, val := range values {
			nameMethod := val.MethodByName("TableName")
			if debug {
				fmt.Println(nameMethod)
			}
			tableName := nameMethod.Call(nil)[0].String()
			columns, primary := getColumns(val)
			ccs := []Column{primary}
			ccs = append(ccs, columns...)
			tableModels = append(tableModels, TableModel{ModelType: tt, ModelValue: val, Columns: ccs, TableName: tableName, Primary: primary})
		}
		return tableModels, nil

	} else {
		return tableModels, errors.New("can't use interface to build TableModel")
	}
}
func getColumns(v reflect.Value) ([]Column, Column) {
	var columns []Column
	var primary Column
	results := reflect.Indirect(reflect.ValueOf(&columns))
	oo := v.Type()

	for i := 0; i < oo.NumField(); i++ {
		field := oo.Field(i)
		col, tps := getColumnFromField(field)
		if tps != -1 {
			if tps == 1 || tps == 2 {
				primary = col
			} else {
				n := reflect.Indirect(reflect.ValueOf(&col))
				if results.Kind() == reflect.Ptr {
					results.Set(reflect.Append(results, n.Addr()))
				} else {
					results.Set(reflect.Append(results, n))
				}
			}

		}
	}
	if debug {
		fmt.Println("columns is:", columns)
	}
	return columns, primary
}
func getColumnFromField(filed reflect.StructField) (Column, int) {
	tag, tps := getTagFromField(filed)
	if debug {
		fmt.Println("Tag is:", tag, "type is:", tps)
	}
	if tps != -1 {
		return Column{ColumnType: filed.Type, ColumnName: tag, FieldName: filed.Name, Auto: tps == 2, IsPrimary: tps == 1 || tps == 2}, tps
	} else {
		return Column{}, -1
	}

}
func getTagFromField(field reflect.StructField) (string, int) {
	tag, hasTag := field.Tag.Lookup("gom")
	if hasTag {
		if strings.EqualFold(tag, "-") || len(tag) == 0 {
			return "", -1
		} else if len(tag) == 1 {
			tps := 0
			if strings.EqualFold(tag, "@") {
				tps = 2
			}
			if strings.EqualFold(tag, "!") {
				tps = 1
			}
			return strings.ToLower(field.Name), tps
		} else {
			if strings.Contains(tag, ",") {
				tags := strings.Split(tag, ",")
				if len(tags) == 2 {
					if strings.EqualFold(tags[0], "!") || strings.EqualFold(tags[0], "primary") {
						return tags[1], 1
					} else if strings.EqualFold(tags[0], "@") || strings.EqualFold(tags[0], "auto") {
						return tags[1], 2
					} else if strings.EqualFold(tags[0], "#") || strings.EqualFold(tags[0], "column") {
						return tags[1], 0
					} else {
						return "", -1
					}
				} else {
					return "", -1
				}
			} else {
				return tag, 0
			}
		}
	} else {
		return "", -1
	}
}
func getValueOfTableRow(model TableModel, row RowChooser) reflect.Value {
	maps := getBytesMap(model, row)
	ccs := model.Columns
	vv := reflect.New(model.ModelType).Elem()
	isStruct := model.ModelType.Kind() == reflect.Struct && model.ModelType != reflect.TypeOf(time.Time{})
	for _, c := range ccs {
		var dds interface{}
		dbytes := maps[c.ColumnName]
		data := string(dbytes)
		switch v := vv.Interface().(type) {
		case BinaryUnmarshaler:
			dd, er := v.UnmarshalBinary(dbytes)
			if er != nil {
				log.Fatalln("when convert binary data to '", vv.Kind().String(), "', find error:", er.Error())
			}
			dds = dd
		case uint:
			dds, _ = UIntfromString(data)
		case uint16:
			dds, _ = UInt16fromString(data)
		case uint32:
			dds, _ = UInt32fromString(data)
		case uint64:
			dds, _ = UInt64fromString(data)
		case int:
			dds, _ = IntfromString(data)
		case int8:
			dds, _ = Int8fromString(data)
		case int16:
			dds, _ = Int16fromString(data)
		case int32:
			dds, _ = Int32fromString(data)
		case int64:
			dds, _ = Int64fromString(data)
		case float32:
			dds, _ = Float32fromString(data)
		case float64:
			dds, _ = Float64fromString(data)
		case string:
			dds = data
		case []byte:
			dds = dbytes
		case time.Time:
			dds, _ = TimeFromString(data)
		default:
			dds = data
		}
		if isStruct {
			vv.Elem().FieldByName(c.FieldName).Set(reflect.ValueOf(dds))
		} else {
			vv.Elem().Set(reflect.ValueOf(dds))
		}
	}
	return vv
}
func getBytesMap(model TableModel, row RowChooser) map[string][]byte {

	data := make([][]byte, len(model.Columns))
	dest := make([]interface{}, len(model.Columns)) // A temporary interface{} slice
	for i, _ := range data {
		dest[i] = &data[i] // Put pointers to each string in the interface slice
	}
	err := row.Scan(dest...)
	if err != nil {
		return map[string][]byte{}
	}
	result := make(map[string][]byte, len(model.Columns))
	ccs := model.Columns
	for i, dd := range ccs {
		result[dd.ColumnName] = data[i]
	}
	return result

}
<commit_msg>修复无法使用自定义对象的bug<commit_after>package gom

import (
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"
	"time"
)

func IsEmpty(v interface{}) bool {
	times := time.Time{}
	if times == v {
		return true
	}
	if v == "" {
		return true
	}
	if v == 0 {
		return true
	}
	if v == 0.0 {
		return true
	}
	if v == nil {
		return true
	}
	return false
}
func getType(v interface{}) (reflect.Type, bool, bool) {
	tt := reflect.TypeOf(v)
	isPtr := false
	islice := false
	if tt.Kind() == reflect.Ptr {
		tt = tt.Elem()
		isPtr = true
	}
	if tt.Kind() == reflect.Slice || tt.Kind() == reflect.Array {
		tt = tt.Elem()
		islice = true
	}
	if debug {
		fmt.Println("Test getType, result:", tt, isPtr, islice)
	}
	return tt, isPtr, islice
}

func GetTableModel(v interface{}, names ...string) (TableModel, error) {
	tms, err := getTableModel(v)
	if err != nil {
		return TableModel{}, nil
	}
	tm := tms[0]
	var cc []Column
	for _, ct := range tm.Columns {
		for _, name := range names {
			if ct.ColumnName == name {
				cc = append(cc, ct)
			}
		}
	}
	tm.Columns = cc
	return tm, nil

}
func CreateSingleValueTableModel(v interface{}, table string, field string) TableModel {
	tt, _, _ := getType(v)
	vals := reflect.New(tt).Elem()
	columns := []Column{{ColumnName: field, ColumnType: tt, IsPrimary: false, Auto: false}}
	return TableModel{Columns: columns, TableName: table, ModelType: tt, ModelValue: vals}
}
func getTableModels(vs ...interface{}) ([]TableModel, error) {
	tablemodels := []TableModel{}
	for _, v := range vs {
		tt, _, _ := getType(v)
		if tt.Kind() == reflect.Interface {
			return tablemodels, errors.New("can't use interface as struct")
		}
		tbs, err := getTableModel(v)
		if err != nil {
			return tablemodels, err
		}
		tablemodels = append(tablemodels, tbs...)
	}
	return tablemodels, nil
}
func getTableModel(v interface{}) ([]TableModel, error) {
	var tableModels []TableModel
	var values []reflect.Value
	tt, isPtr, isSlice := getType(v)
	if tt.NumField() == 0 || tt.NumMethod() == 0 {
		return tableModels, errors.New(tt.Name() + " is not a valid struct")
	}
	value := reflect.ValueOf(v)
	if v != nil && tt.Kind() != reflect.Interface {

		if isPtr {
			value = value.Elem()
		}
		if debug {
			fmt.Println("model info:", tt, isPtr, isSlice, value)
		}
		if isSlice {
			if value.Len() > 0 {
				for i := 0; i < value.Len(); i++ {
					val := value.Index(i)
					values = append(values, val)
				}
			} else {
				values = append(values, reflect.New(tt).Elem())
			}
		} else {
			values = append(values, value)
		}
		if debug {
			fmt.Println(values)
		}
		for _, val := range values {
			nameMethod := val.MethodByName("TableName")
			if debug {
				fmt.Println(nameMethod)
			}
			tableName := nameMethod.Call(nil)[0].String()
			columns, primary := getColumns(val)
			ccs := []Column{primary}
			ccs = append(ccs, columns...)
			tableModels = append(tableModels, TableModel{ModelType: tt, ModelValue: val, Columns: ccs, TableName: tableName, Primary: primary})
		}
		return tableModels, nil

	} else {
		return tableModels, errors.New("can't use interface to build TableModel")
	}
}
func getColumns(v reflect.Value) ([]Column, Column) {
	var columns []Column
	var primary Column
	results := reflect.Indirect(reflect.ValueOf(&columns))
	oo := v.Type()

	for i := 0; i < oo.NumField(); i++ {
		field := oo.Field(i)
		col, tps := getColumnFromField(field)
		if tps != -1 {
			if tps == 1 || tps == 2 {
				primary = col
			} else {
				n := reflect.Indirect(reflect.ValueOf(&col))
				if results.Kind() == reflect.Ptr {
					results.Set(reflect.Append(results, n.Addr()))
				} else {
					results.Set(reflect.Append(results, n))
				}
			}

		}
	}
	if debug {
		fmt.Println("columns is:", columns)
	}
	return columns, primary
}
func getColumnFromField(filed reflect.StructField) (Column, int) {
	tag, tps := getTagFromField(filed)
	if debug {
		fmt.Println("Tag is:", tag, "type is:", tps)
	}
	if tps != -1 {
		return Column{ColumnType: filed.Type, ColumnName: tag, FieldName: filed.Name, Auto: tps == 2, IsPrimary: tps == 1 || tps == 2}, tps
	} else {
		return Column{}, -1
	}

}
func getTagFromField(field reflect.StructField) (string, int) {
	tag, hasTag := field.Tag.Lookup("gom")
	if hasTag {
		if strings.EqualFold(tag, "-") || len(tag) == 0 {
			return "", -1
		} else if len(tag) == 1 {
			tps := 0
			if strings.EqualFold(tag, "@") {
				tps = 2
			}
			if strings.EqualFold(tag, "!") {
				tps = 1
			}
			return strings.ToLower(field.Name), tps
		} else {
			if strings.Contains(tag, ",") {
				tags := strings.Split(tag, ",")
				if len(tags) == 2 {
					if strings.EqualFold(tags[0], "!") || strings.EqualFold(tags[0], "primary") {
						return tags[1], 1
					} else if strings.EqualFold(tags[0], "@") || strings.EqualFold(tags[0], "auto") {
						return tags[1], 2
					} else if strings.EqualFold(tags[0], "#") || strings.EqualFold(tags[0], "column") {
						return tags[1], 0
					} else {
						return "", -1
					}
				} else {
					return "", -1
				}
			} else {
				return tag, 0
			}
		}
	} else {
		return "", -1
	}
}
func getValueOfTableRow(model TableModel, row RowChooser) reflect.Value {
	maps := getBytesMap(model, row)
	ccs := model.Columns
	vv := reflect.New(model.ModelType).Elem()
	isStruct := model.ModelType.Kind() == reflect.Struct && model.ModelType != reflect.TypeOf(time.Time{})
	for _, c := range ccs {
		var dds interface{}
		dbytes := maps[c.ColumnName]
		data := string(dbytes)
		switch v := vv.Interface().(type) {
		case BinaryUnmarshaler:
			dd, er := v.UnmarshalBinary(dbytes)
			if er != nil {
				log.Fatalln("when convert binary data to '", vv.Kind().String(), "', find error:", er.Error())
			}
			dds = dd
		case uint:
			dds, _ = UIntfromString(data)
		case uint16:
			dds, _ = UInt16fromString(data)
		case uint32:
			dds, _ = UInt32fromString(data)
		case uint64:
			dds, _ = UInt64fromString(data)
		case int:
			dds, _ = IntfromString(data)
		case int8:
			dds, _ = Int8fromString(data)
		case int16:
			dds, _ = Int16fromString(data)
		case int32:
			dds, _ = Int32fromString(data)
		case int64:
			dds, _ = Int64fromString(data)
		case float32:
			dds, _ = Float32fromString(data)
		case float64:
			dds, _ = Float64fromString(data)
		case string:
			dds = data
		case []byte:
			dds = dbytes
		case time.Time:
			dds, _ = TimeFromString(data)
		default:
			dds = data
		}
		if isStruct {
			vv.FieldByName(c.FieldName).Set(reflect.ValueOf(dds))
		} else {
			vv.Set(reflect.ValueOf(dds))
		}
	}
	return vv
}
func getBytesMap(model TableModel, row RowChooser) map[string][]byte {

	data := make([][]byte, len(model.Columns))
	dest := make([]interface{}, len(model.Columns)) // A temporary interface{} slice
	for i, _ := range data {
		dest[i] = &data[i] // Put pointers to each string in the interface slice
	}
	err := row.Scan(dest...)
	if err != nil {
		return map[string][]byte{}
	}
	result := make(map[string][]byte, len(model.Columns))
	ccs := model.Columns
	for i, dd := range ccs {
		result[dd.ColumnName] = data[i]
	}
	return result

}
<|endoftext|>


<commit_before>package water

import (
	"fmt"
	"net/http"
	"net/url"
	"path"
	"reflect"
	"runtime"
	"strings"
	"time"

	jsoniter "github.com/json-iterator/go"
)

var (
	json = jsoniter.ConfigCompatibleWithStandardLibrary
)

// from net/http
func cleanPath(p string) string {
	if p == "" {
		return "/"
	}
	if p[0] != '/' {
		p = "/" + p
	}

	// Restful uri
	// path.Clean会去除末尾的'/'("/"除外)
	return path.Clean(p)
}

func requestProxy(req *http.Request) []string {
	if ips := req.Header.Get(HeaderXForwardedFor); ips != "" {
		return strings.Split(ips, ", ")
	}

	return nil
}

func requestRealIp(req *http.Request) string {
	ip := req.Header.Get(HeaderXRealIP)
	if ip == "" {
		ips := requestProxy(req)
		if len(ips) > 0 && ips[0] != "" {
			return ips[0]
		}

		ip = req.RemoteAddr
		if i := strings.LastIndex(ip, ":"); i > -1 {
			ip = ip[:i]
		}
	}

	return ip
}

func contentDisposition(fileName, dispositionType string) string {
	if dispositionType == "" {
		dispositionType = "attachment"
	}
	if fileName == "" {
		return dispositionType
	}

	return fmt.Sprintf(`%s; filename="%s"; filename*=UTF-8''%s`,
		dispositionType, url.PathEscape(fileName), url.PathEscape(fileName))
}

// check pattern segment
// 检查url片段的合法性
func checkSplitPattern(pattern string) bool {
	n := len(pattern)
	return n > 0 && pattern[0] == '/' && pattern[n-1] != '/'
}

func reverseStrings(s []string) []string {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}

	return s
}

func checkMethod(method string) (string, int) {
	method = strings.ToUpper(method)
	idx := MethodIndex(method)
	if idx < 0 {
		panic("unsupport method: " + method)
	}

	return method, idx
}

func filterFlags(content string) string {
	for i, char := range content {
		if char == ' ' || char == ';' {
			return content[:i]
		}
	}
	return content
}

func nameOfFunction(f interface{}) string {
	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
}

// GenerateETag generates an ETag based on file modification time and size
// from http://lxr.nginx.org/ident?_i=ngx_http_set_etag
func GenerateETag(lastModified time.Time, size int64) string {
	return fmt.Sprintf("%x-%x", lastModified.Unix(), size)
}
<commit_msg>u requestRealIp comment<commit_after>package water

import (
	"fmt"
	"net/http"
	"net/url"
	"path"
	"reflect"
	"runtime"
	"strings"
	"time"

	jsoniter "github.com/json-iterator/go"
)

var (
	json = jsoniter.ConfigCompatibleWithStandardLibrary
)

// from net/http
func cleanPath(p string) string {
	if p == "" {
		return "/"
	}
	if p[0] != '/' {
		p = "/" + p
	}

	// Restful uri
	// path.Clean会去除末尾的'/'("/"除外)
	return path.Clean(p)
}

func requestProxy(req *http.Request) []string {
	if ips := req.Header.Get(HeaderXForwardedFor); ips != "" {
		return strings.Split(ips, ", ")
	}

	return nil
}

// see more detail in github.com/minio/minio/pkg/handlers/proxy.go
func requestRealIp(req *http.Request) string {
	ip := req.Header.Get(HeaderXRealIP)
	if ip == "" {
		ips := requestProxy(req)
		if len(ips) > 0 && ips[0] != "" {
			return ips[0]
		}

		ip = req.RemoteAddr
		if i := strings.LastIndex(ip, ":"); i > -1 {
			ip = ip[:i]
		}
	}

	return ip
}

func contentDisposition(fileName, dispositionType string) string {
	if dispositionType == "" {
		dispositionType = "attachment"
	}
	if fileName == "" {
		return dispositionType
	}

	return fmt.Sprintf(`%s; filename="%s"; filename*=UTF-8''%s`,
		dispositionType, url.PathEscape(fileName), url.PathEscape(fileName))
}

// check pattern segment
// 检查url片段的合法性
func checkSplitPattern(pattern string) bool {
	n := len(pattern)
	return n > 0 && pattern[0] == '/' && pattern[n-1] != '/'
}

func reverseStrings(s []string) []string {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}

	return s
}

func checkMethod(method string) (string, int) {
	method = strings.ToUpper(method)
	idx := MethodIndex(method)
	if idx < 0 {
		panic("unsupport method: " + method)
	}

	return method, idx
}

func filterFlags(content string) string {
	for i, char := range content {
		if char == ' ' || char == ';' {
			return content[:i]
		}
	}
	return content
}

func nameOfFunction(f interface{}) string {
	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
}

// GenerateETag generates an ETag based on file modification time and size
// from http://lxr.nginx.org/ident?_i=ngx_http_set_etag
func GenerateETag(lastModified time.Time, size int64) string {
	return fmt.Sprintf("%x-%x", lastModified.Unix(), size)
}
<|endoftext|>


<commit_before>// Collection of small, useful utility functions
package util

import (
	"bufio"
	"flag"
	"io"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"
)

// TimeoutDialer creates a Dialer that can timeout after a connection timeout
// or a read timeout
func TimeoutDialer(connTimeout, rwTimeout time.Duration) func(netw, addr string) (c net.Conn, err error) {
	return func(netw, addr string) (net.Conn, error) {
		conn, err := net.DialTimeout(netw, addr, connTimeout)

		if err != nil {
			return nil, err
		}

		conn.SetDeadline(time.Now().Add(rwTimeout))

		return conn, nil
	}
}

// ExitWhenOrphaned checks if the current process becomes orphaned and
// immediately kills the script. This prevents multiple instances of the
// script running indefinitely when it's being launched by some external
// process (e.g. Splunk).
func ExitWhenOrphaned() {
	ticker := time.Tick(1 * time.Second)

	go func() {
		for _ := range ticker {
			// The parent pid of an orphaned process is PID 1
			if os.Getppid() == 1 {
				panic("Orphaned process. Exiting!")
			}
		}
	}()
}

// Collect args from files or stdin
func GetArgs() (args []string) {
	var inputs []io.Reader

	// Check for files first and use stdin if no files are specified
	files := flag.Args()

	if len(files) > 0 {
		for _, file := range files {
			input, err := os.Open(file)

			if err != nil {
				//logging.Warn(err.Error())
				continue
			}

			inputs = append(inputs, input)
		}
	} else {
		inputs = append(inputs, os.Stdin)
	}

	// Scan all inputs for arguments
	for _, input := range inputs {
		scanner := bufio.NewScanner(input)

		for scanner.Scan() {
			line := scanner.Text()
			// Skip empty lines and comments
			arg := strings.TrimSpace(line)

			if arg == "" || strings.HasPrefix(arg, "#") {
				continue
			}

			args = append(args, arg)
			//logging.Trace("Adding arg: %s", arg)
		}

		if err := scanner.Err(); err != nil {
			//logging.Error("Unable to add line: %s", err)
		}
	}

	return args
}

// Return a random duration between two (positive) durations
func RandomDuration(min, max time.Duration) time.Duration {
	rand.Seed(time.Now().UnixNano())
	nmin := int(min.Seconds())
	nmax := int(max.Seconds())
	n := rand.Intn(nmax-nmin) + nmax

	return time.Second * time.Duration(n)
}
<commit_msg>Update util.go<commit_after>// Collection of small, useful utility functions
package util

import (
	"bufio"
	"flag"
	"io"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"
)

// TimeoutDialer creates a Dialer that can timeout after a connection timeout
// or a read timeout
func TimeoutDialer(connTimeout, rwTimeout time.Duration) func(netw, addr string) (c net.Conn, err error) {
	return func(netw, addr string) (net.Conn, error) {
		conn, err := net.DialTimeout(netw, addr, connTimeout)

		if err != nil {
			return nil, err
		}

		conn.SetDeadline(time.Now().Add(rwTimeout))

		return conn, nil
	}
}

// ExitWhenOrphaned checks if the current process becomes orphaned and
// immediately kills the script. This prevents multiple instances of the
// script running indefinitely when it's being launched by some external
// process (e.g. Splunk).
func ExitWhenOrphaned() {
	ticker := time.Tick(1 * time.Second)

	go func() {
		for _ = range ticker {
			// The parent pid of an orphaned process is PID 1
			if os.Getppid() == 1 {
				panic("Orphaned process. Exiting!")
			}
		}
	}()
}

// Collect args from files or stdin
func GetArgs() (args []string) {
	var inputs []io.Reader

	// Check for files first and use stdin if no files are specified
	files := flag.Args()

	if len(files) > 0 {
		for _, file := range files {
			input, err := os.Open(file)

			if err != nil {
				//logging.Warn(err.Error())
				continue
			}

			inputs = append(inputs, input)
		}
	} else {
		inputs = append(inputs, os.Stdin)
	}

	// Scan all inputs for arguments
	for _, input := range inputs {
		scanner := bufio.NewScanner(input)

		for scanner.Scan() {
			line := scanner.Text()
			// Skip empty lines and comments
			arg := strings.TrimSpace(line)

			if arg == "" || strings.HasPrefix(arg, "#") {
				continue
			}

			args = append(args, arg)
			//logging.Trace("Adding arg: %s", arg)
		}

		if err := scanner.Err(); err != nil {
			//logging.Error("Unable to add line: %s", err)
		}
	}

	return args
}

// Return a random duration between two (positive) durations
func RandomDuration(min, max time.Duration) time.Duration {
	rand.Seed(time.Now().UnixNano())
	nmin := int(min.Seconds())
	nmax := int(max.Seconds())
	n := rand.Intn(nmax-nmin) + nmax

	return time.Second * time.Duration(n)
}
<|endoftext|>