<commit_before>// Copyright 2015 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

const usage = `
factom-cli [options] [subcommand]

        -c [ChainID]        hex encoded chainid for the entry
        -e [extid]          external id for the entry. -e may be used multiple times
        -h                  display help message
        -s                  path to the factomclient. default: localhost:8083

    get
        head                Get current dbhead
        dblock keymr        Get dblock by merkle root
        chain chainid       Get ebhead by chainid
        eblock keymr        Get eblock by merkle root
        entry hash          Get entry by hash

    help [command]          Print help message for a sub-command

    mkchain name            Create a new factom chain. read the data for the
                            first entry from stdin.  Use the entry credits
                            from the specified name.
        -e externalid       Externalid for the first entry

    put name                Read data from stdin and write to factom. Use
                            the entry credits from the specified entry credit
                            address
        -e [externalid]     Specify an exteral id for the factom entry. -e
                            can be used multiple times
        -c [chainid]        Specify the chain that the entry belongs to

    newaddress or
    generateaddress         Generate addresses, giving them names.
        ec name             Generate an Entry Credit address, tied to the name
        fct name            Generate a Factoid address, tied to the name
                            Names must be unique, or you will get a
                            Duplicate Name or Invalid Name error.
                            Names are limited to 32 characters

    deletetransaction key   Delete the specified transaction in flight.

    balance key|address     If this is an ec balance, returns number of
                            entry credits
                            If this is a Factoid balance, returns the
                            factoids at that address

    newtransaction key      Create a new transaction.  The key is used to
                            add inputs, outputs, and ecoutputs (to buy
                            entry credits).  Once the transaction is built,
                            call validate, and if all is good, submit

    addinput                Add an input to a transaction
        key name amount     Use the name supplied to genfactoidaddr
        key address amount  Use an address

    addoutput               Add an output to a transaction
        key name amount     Use the name supplied to genfactoidaddr
        key address amount  Use an address

    addecoutput             Add an ecoutput (purchase of entry credits to
                            a transaction
        key name amount     Use the name supplied to genfactoidaddr
        key address amount  Use an address

    getfee key              Get the current fee required for this
                            transaction.  If a transaction is specified,
                            then getfee returns the fee due for the
                            transaction.  If no transaction is provided,
                            then the cost of an Entry Credit is returned.

    sign key                Sign the transaction specified by the key

    submit key              Submit the transaction specified by the key
                            to Factom

    balances or
    getaddresses            Returns the list of addresses known to the
                            wallet. Returns the name that can be used
                            tied to each address, as well as the base 58
                            address (which is the actual address).  This
                            command also returns the balances at each
                            address.

    transactions            Returns a list of all the transactions being
                            constructed by the user.  It shows the fee
                            required (at this point) as well as the fee
                            the user will pay.  Some additional error
                            checking is done as well, with messages
                            provided to the user.

    setup seed              Creates 10 fountain addresses (from which a
                            test program can simply acquire factoids.
                            After those addresses are defined, the wallet
                            seed is changed randomly according to the
                            seed provided and time.  So every call to setup
                            changes the address sequence of the wallet.
                            You may call setup multiple times, but the
                            fountain addresses are not created if any address
                            already exists.
`

// man returns an usage error string for the specified sub command.
func man(s string) {
	m := map[string]string{
		"setup":          "factom-cli setup seed",
		"testcredit":     "factom-cli testcredit [key]",
		"balance":        "factom-cli balance ec|fct [key]",
		"buy":            "factom-cli buy #amt",
		"get":            "factom-cli get head|dblock|chain|eblock|entry",
		"getHead":        "factom-cli get head",
		"getDBlock":      "factom-cli get dblock [keymr]",
		"getChain":       "factom-cli get chain [chainid]",
		"getEBlock":      "factom-cli get eblock [keymr]",
		"getaddresses":   "factom-cli getaddresses|balances",
		"balances":       "factom-cli getaddresses|balances",
		"transactions":   "factom-cli transactions",
		"getentry":       "factom-cli get entry [hash]",
		"help":           usage,
		"mkchain":        "factom-cli mkchain [-e extid ...] name <stdin>",
		"genfactoidaddr": "factom-cli genfactoidaddr name",
		"newtransaction": "factom-cli newtransaction key",
		"addinput":       "factom-cli addinput key name|address amount",
		"addoutput":      "factom-cli addoutput key name|address amount",
		"addecoutput":    "factom-cli addecoutput key name|address amount",
		"validate":       "factom-cli validate key",
		"submit":         "factom-cli submit key",
		"put":            "factom-cli put [-e extid ...] name <stdin>",
		"default":        "More Help can be found by typing:\n\n  factom-cli help",
	}

	if m[s] != "" {
		errorln(m[s])
		return
	}
	errorln(m["default"])
}
<commit_msg>added directions to help<commit_after>// Copyright 2015 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

const usage = `
factom-cli [options] [subcommand]

        -c [ChainID]        hex encoded chainid for the entry
        -e [extid]          external id for the entry. -e may be used multiple times
        -h                  display help message
        -s                  path to the factomclient. default: localhost:8083

    get
        head                Get current dbhead
        dblock keymr        Get dblock by merkle root
        chain chainid       Get ebhead by chainid
        eblock keymr        Get eblock by merkle root
        entry hash          Get entry by hash

    help [command]          Print help message for a sub-command

    mkchain name            Create a new factom chain. read the data for the
                            first entry from stdin.  Use the entry credits
                            from the specified name.
        -e externalid       Externalid for the first entry

    put name                Read data from stdin and write to factom. Use
                            the entry credits from the specified entry credit
                            address
        -e [externalid]     Specify an exteral id for the factom entry. -e
                            can be used multiple times
        -c [chainid]        Specify the chain that the entry belongs to

    newaddress or
    generateaddress         Generate addresses, giving them names.
        ec name             Generate an Entry Credit address, tied to the name
        fct name            Generate a Factoid address, tied to the name
                            Names must be unique, or you will get a
                            Duplicate Name or Invalid Name error.
                            Names are limited to 32 characters
        ec name Es...       Import a secret EC key to the wallet
        fct name Fs...      Import a secret Factoid key to the wallet
        fct name "12 words" Import the Factoid key from the Token Sale

    deletetransaction key   Delete the specified transaction in flight.

    balance key|address     If this is an ec balance, returns number of
                            entry credits
                            If this is a Factoid balance, returns the
                            factoids at that address

    newtransaction key      Create a new transaction.  The key is used to
                            add inputs, outputs, and ecoutputs (to buy
                            entry credits).  Once the transaction is built,
                            call validate, and if all is good, submit

    addinput                Add an input to a transaction
        key name amount     Use the name supplied to genfactoidaddr
        key address amount  Use an address

    addoutput               Add an output to a transaction
        key name amount     Use the name supplied to genfactoidaddr
        key address amount  Use an address

    addecoutput             Add an ecoutput (purchase of entry credits to
                            a transaction
        key name amount     Use the name supplied to genfactoidaddr
        key address amount  Use an address

    getfee key              Get the current fee required for this
                            transaction.  If a transaction is specified,
                            then getfee returns the fee due for the
                            transaction.  If no transaction is provided,
                            then the cost of an Entry Credit is returned.

    sign key                Sign the transaction specified by the key

    submit key              Submit the transaction specified by the key
                            to Factom

    balances or
    getaddresses            Returns the list of addresses known to the
                            wallet. Returns the name that can be used
                            tied to each address, as well as the base 58
                            address (which is the actual address).  This
                            command also returns the balances at each
                            address.

    transactions            Returns a list of all the transactions being
                            constructed by the user.  It shows the fee
                            required (at this point) as well as the fee
                            the user will pay.  Some additional error
                            checking is done as well, with messages
                            provided to the user.

    setup seed              Creates 10 fountain addresses (from which a
                            test program can simply acquire factoids.
                            After those addresses are defined, the wallet
                            seed is changed randomly according to the
                            seed provided and time.  So every call to setup
                            changes the address sequence of the wallet.
                            You may call setup multiple times, but the
                            fountain addresses are not created if any address
                            already exists.
`

// man returns an usage error string for the specified sub command.
func man(s string) {
	m := map[string]string{
		"setup":          "factom-cli setup seed",
		"testcredit":     "factom-cli testcredit [key]",
		"balance":        "factom-cli balance ec|fct [key]",
		"buy":            "factom-cli buy #amt",
		"get":            "factom-cli get head|dblock|chain|eblock|entry",
		"getHead":        "factom-cli get head",
		"getDBlock":      "factom-cli get dblock [keymr]",
		"getChain":       "factom-cli get chain [chainid]",
		"getEBlock":      "factom-cli get eblock [keymr]",
		"getaddresses":   "factom-cli getaddresses|balances",
		"balances":       "factom-cli getaddresses|balances",
		"transactions":   "factom-cli transactions",
		"getentry":       "factom-cli get entry [hash]",
		"help":           usage,
		"mkchain":        "factom-cli mkchain [-e extid ...] name <stdin>",
		"genfactoidaddr": "factom-cli genfactoidaddr name",
		"newtransaction": "factom-cli newtransaction key",
		"addinput":       "factom-cli addinput key name|address amount",
		"addoutput":      "factom-cli addoutput key name|address amount",
		"addecoutput":    "factom-cli addecoutput key name|address amount",
		"validate":       "factom-cli validate key",
		"submit":         "factom-cli submit key",
		"put":            "factom-cli put [-e extid ...] name <stdin>",
		"default":        "More Help can be found by typing:\n\n  factom-cli help",
	}

	if m[s] != "" {
		errorln(m[s])
		return
	}
	errorln(m["default"])
}
<|endoftext|>


<commit_before>package flags

import (
	"fmt"
	"io"
	"runtime"
	"strings"
	"time"
)

func manQuote(s string) string {
	return strings.Replace(s, "\\", "\\\\", -1)
}

func formatForMan(wr io.Writer, s string) {
	for {
		idx := strings.IndexRune(s, '`')

		if idx < 0 {
			fmt.Fprintf(wr, "%s", manQuote(s))
			break
		}

		fmt.Fprintf(wr, "%s", manQuote(s[:idx]))

		s = s[idx+1:]
		idx = strings.IndexRune(s, '\'')

		if idx < 0 {
			fmt.Fprintf(wr, "%s", manQuote(s))
			break
		}

		fmt.Fprintf(wr, "\\fB%s\\fP", manQuote(s[:idx]))
		s = s[idx+1:]
	}
}

func writeManPageOptions(wr io.Writer, grp *Group) {
	grp.eachGroup(func(group *Group) {
		if !group.showInHelp() {
			return
		}

		// If the parent (grp) has any subgroups, display their descriptions as
		// subsection headers similar to the output of --help.
		if group.ShortDescription != "" && len(grp.groups) > 0 {
			fmt.Fprintf(wr, ".SS %s\n", group.ShortDescription)

			if group.LongDescription != "" {
				formatForMan(wr, group.LongDescription)
				fmt.Fprintln(wr, "")
			}
		}

		for _, opt := range group.options {
			if !opt.showInHelp() {
				continue
			}

			fmt.Fprintln(wr, ".TP")
			fmt.Fprintf(wr, "\\fB")

			if opt.ShortName != 0 {
				fmt.Fprintf(wr, "\\fB\\-%c\\fR", opt.ShortName)
			}

			if len(opt.LongName) != 0 {
				if opt.ShortName != 0 {
					fmt.Fprintf(wr, ", ")
				}

				fmt.Fprintf(wr, "\\fB\\-\\-%s\\fR", manQuote(opt.LongNameWithNamespace()))
			}

			if len(opt.ValueName) != 0 || opt.OptionalArgument {
				if opt.OptionalArgument {
					fmt.Fprintf(wr, " [\\fI%s=%s\\fR]", manQuote(opt.ValueName), manQuote(strings.Join(quoteV(opt.OptionalValue), ", ")))
				} else {
					fmt.Fprintf(wr, " \\fI%s\\fR", manQuote(opt.ValueName))
				}
			}

			if len(opt.Default) != 0 {
				fmt.Fprintf(wr, " <default: \\fI%s\\fR>", manQuote(strings.Join(quoteV(opt.Default), ", ")))
			} else if len(opt.EnvKeyWithNamespace()) != 0 {
				if runtime.GOOS == "windows" {
					fmt.Fprintf(wr, " <default: \\fI%%%s%%\\fR>", manQuote(opt.EnvKeyWithNamespace()))
				} else {
					fmt.Fprintf(wr, " <default: \\fI$%s\\fR>", manQuote(opt.EnvKeyWithNamespace()))
				}
			}

			if opt.Required {
				fmt.Fprintf(wr, " (\\fIrequired\\fR)")
			}

			fmt.Fprintln(wr, "\\fP")

			if len(opt.Description) != 0 {
				formatForMan(wr, opt.Description)
				fmt.Fprintln(wr, "")
			}
		}
	})
}

func writeManPageSubcommands(wr io.Writer, name string, root *Command) {
	commands := root.sortedVisibleCommands()

	for _, c := range commands {
		var nn string

		if c.Hidden {
			continue
		}

		if len(name) != 0 {
			nn = name + " " + c.Name
		} else {
			nn = c.Name
		}

		writeManPageCommand(wr, nn, root, c)
	}
}

func writeManPageCommand(wr io.Writer, name string, root *Command, command *Command) {
	fmt.Fprintf(wr, ".SS %s\n", name)
	fmt.Fprintln(wr, command.ShortDescription)

	if len(command.LongDescription) > 0 {
		fmt.Fprintln(wr, "")

		cmdstart := fmt.Sprintf("The %s command", manQuote(command.Name))

		if strings.HasPrefix(command.LongDescription, cmdstart) {
			fmt.Fprintf(wr, "The \\fI%s\\fP command", manQuote(command.Name))

			formatForMan(wr, command.LongDescription[len(cmdstart):])
			fmt.Fprintln(wr, "")
		} else {
			formatForMan(wr, command.LongDescription)
			fmt.Fprintln(wr, "")
		}
	}

	var usage string
	if us, ok := command.data.(Usage); ok {
		usage = us.Usage()
	} else if command.hasHelpOptions() {
		usage = fmt.Sprintf("[%s-OPTIONS]", command.Name)
	}

	var pre string
	if root.hasHelpOptions() {
		pre = fmt.Sprintf("%s [OPTIONS] %s", root.Name, command.Name)
	} else {
		pre = fmt.Sprintf("%s %s", root.Name, command.Name)
	}

	if len(usage) > 0 {
		fmt.Fprintf(wr, "\n\\fBUsage\\fP: %s %s\n.TP\n", manQuote(pre), manQuote(usage))
	}

	if len(command.Aliases) > 0 {
		fmt.Fprintf(wr, "\n\\fBAliases\\fP: %s\n\n", manQuote(strings.Join(command.Aliases, ", ")))
	}

	writeManPageOptions(wr, command.Group)
	writeManPageSubcommands(wr, name, command)
}

// WriteManPage writes a basic man page in groff format to the specified
// writer.
func (p *Parser) WriteManPage(wr io.Writer) {
	t := time.Now()

	fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", manQuote(p.Name), t.Format("2 January 2006"))
	fmt.Fprintln(wr, ".SH NAME")
	fmt.Fprintf(wr, "%s \\- %s\n", manQuote(p.Name), manQuote(p.ShortDescription))
	fmt.Fprintln(wr, ".SH SYNOPSIS")

	usage := p.Usage

	if len(usage) == 0 {
		usage = "[OPTIONS]"
	}

	fmt.Fprintf(wr, "\\fB%s\\fP %s\n", manQuote(p.Name), manQuote(usage))
	fmt.Fprintln(wr, ".SH DESCRIPTION")

	formatForMan(wr, p.LongDescription)
	fmt.Fprintln(wr, "")

	fmt.Fprintln(wr, ".SH OPTIONS")

	writeManPageOptions(wr, p.Command.Group)

	if len(p.visibleCommands()) > 0 {
		fmt.Fprintln(wr, ".SH COMMANDS")

		writeManPageSubcommands(wr, "", p.Command)
	}
}
<commit_msg>Added SOURCE_DATE_EPOCH support<commit_after>package flags

import (
	"fmt"
	"io"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

func manQuote(s string) string {
	return strings.Replace(s, "\\", "\\\\", -1)
}

func formatForMan(wr io.Writer, s string) {
	for {
		idx := strings.IndexRune(s, '`')

		if idx < 0 {
			fmt.Fprintf(wr, "%s", manQuote(s))
			break
		}

		fmt.Fprintf(wr, "%s", manQuote(s[:idx]))

		s = s[idx+1:]
		idx = strings.IndexRune(s, '\'')

		if idx < 0 {
			fmt.Fprintf(wr, "%s", manQuote(s))
			break
		}

		fmt.Fprintf(wr, "\\fB%s\\fP", manQuote(s[:idx]))
		s = s[idx+1:]
	}
}

func writeManPageOptions(wr io.Writer, grp *Group) {
	grp.eachGroup(func(group *Group) {
		if !group.showInHelp() {
			return
		}

		// If the parent (grp) has any subgroups, display their descriptions as
		// subsection headers similar to the output of --help.
		if group.ShortDescription != "" && len(grp.groups) > 0 {
			fmt.Fprintf(wr, ".SS %s\n", group.ShortDescription)

			if group.LongDescription != "" {
				formatForMan(wr, group.LongDescription)
				fmt.Fprintln(wr, "")
			}
		}

		for _, opt := range group.options {
			if !opt.showInHelp() {
				continue
			}

			fmt.Fprintln(wr, ".TP")
			fmt.Fprintf(wr, "\\fB")

			if opt.ShortName != 0 {
				fmt.Fprintf(wr, "\\fB\\-%c\\fR", opt.ShortName)
			}

			if len(opt.LongName) != 0 {
				if opt.ShortName != 0 {
					fmt.Fprintf(wr, ", ")
				}

				fmt.Fprintf(wr, "\\fB\\-\\-%s\\fR", manQuote(opt.LongNameWithNamespace()))
			}

			if len(opt.ValueName) != 0 || opt.OptionalArgument {
				if opt.OptionalArgument {
					fmt.Fprintf(wr, " [\\fI%s=%s\\fR]", manQuote(opt.ValueName), manQuote(strings.Join(quoteV(opt.OptionalValue), ", ")))
				} else {
					fmt.Fprintf(wr, " \\fI%s\\fR", manQuote(opt.ValueName))
				}
			}

			if len(opt.Default) != 0 {
				fmt.Fprintf(wr, " <default: \\fI%s\\fR>", manQuote(strings.Join(quoteV(opt.Default), ", ")))
			} else if len(opt.EnvKeyWithNamespace()) != 0 {
				if runtime.GOOS == "windows" {
					fmt.Fprintf(wr, " <default: \\fI%%%s%%\\fR>", manQuote(opt.EnvKeyWithNamespace()))
				} else {
					fmt.Fprintf(wr, " <default: \\fI$%s\\fR>", manQuote(opt.EnvKeyWithNamespace()))
				}
			}

			if opt.Required {
				fmt.Fprintf(wr, " (\\fIrequired\\fR)")
			}

			fmt.Fprintln(wr, "\\fP")

			if len(opt.Description) != 0 {
				formatForMan(wr, opt.Description)
				fmt.Fprintln(wr, "")
			}
		}
	})
}

func writeManPageSubcommands(wr io.Writer, name string, root *Command) {
	commands := root.sortedVisibleCommands()

	for _, c := range commands {
		var nn string

		if c.Hidden {
			continue
		}

		if len(name) != 0 {
			nn = name + " " + c.Name
		} else {
			nn = c.Name
		}

		writeManPageCommand(wr, nn, root, c)
	}
}

func writeManPageCommand(wr io.Writer, name string, root *Command, command *Command) {
	fmt.Fprintf(wr, ".SS %s\n", name)
	fmt.Fprintln(wr, command.ShortDescription)

	if len(command.LongDescription) > 0 {
		fmt.Fprintln(wr, "")

		cmdstart := fmt.Sprintf("The %s command", manQuote(command.Name))

		if strings.HasPrefix(command.LongDescription, cmdstart) {
			fmt.Fprintf(wr, "The \\fI%s\\fP command", manQuote(command.Name))

			formatForMan(wr, command.LongDescription[len(cmdstart):])
			fmt.Fprintln(wr, "")
		} else {
			formatForMan(wr, command.LongDescription)
			fmt.Fprintln(wr, "")
		}
	}

	var usage string
	if us, ok := command.data.(Usage); ok {
		usage = us.Usage()
	} else if command.hasHelpOptions() {
		usage = fmt.Sprintf("[%s-OPTIONS]", command.Name)
	}

	var pre string
	if root.hasHelpOptions() {
		pre = fmt.Sprintf("%s [OPTIONS] %s", root.Name, command.Name)
	} else {
		pre = fmt.Sprintf("%s %s", root.Name, command.Name)
	}

	if len(usage) > 0 {
		fmt.Fprintf(wr, "\n\\fBUsage\\fP: %s %s\n.TP\n", manQuote(pre), manQuote(usage))
	}

	if len(command.Aliases) > 0 {
		fmt.Fprintf(wr, "\n\\fBAliases\\fP: %s\n\n", manQuote(strings.Join(command.Aliases, ", ")))
	}

	writeManPageOptions(wr, command.Group)
	writeManPageSubcommands(wr, name, command)
}

// WriteManPage writes a basic man page in groff format to the specified
// writer.
func (p *Parser) WriteManPage(wr io.Writer) {
	t := time.Now()
	source_date_epoch := os.Getenv("SOURCE_DATE_EPOCH")
	if source_date_epoch != "" {
		sde, err := strconv.ParseInt(source_date_epoch, 10, 64)
		if err != nil {
			panic(fmt.Sprintf("Invalid SOURCE_DATE_EPOCH: %s", err))
        }
		t = time.Unix(sde, 0)
	}

	fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", manQuote(p.Name), t.Format("2 January 2006"))
	fmt.Fprintln(wr, ".SH NAME")
	fmt.Fprintf(wr, "%s \\- %s\n", manQuote(p.Name), manQuote(p.ShortDescription))
	fmt.Fprintln(wr, ".SH SYNOPSIS")

	usage := p.Usage

	if len(usage) == 0 {
		usage = "[OPTIONS]"
	}

	fmt.Fprintf(wr, "\\fB%s\\fP %s\n", manQuote(p.Name), manQuote(usage))
	fmt.Fprintln(wr, ".SH DESCRIPTION")

	formatForMan(wr, p.LongDescription)
	fmt.Fprintln(wr, "")

	fmt.Fprintln(wr, ".SH OPTIONS")

	writeManPageOptions(wr, p.Command.Group)

	if len(p.visibleCommands()) > 0 {
		fmt.Fprintln(wr, ".SH COMMANDS")

		writeManPageSubcommands(wr, "", p.Command)
	}
}
<|endoftext|>


<commit_before>package darwini

import (
	"net/http"

	"golang.org/x/net/context"
)

// Map multiplexes requests to children based on a map lookup. For Map
// at /path, /path will be forbidden, /path/seg and /path/seg/anything
// are served by the map entry for seg, or not found if nil.
//
// As a special case, missing /path/ is forbidden instead of not
// found, to avoid a situation where /path/foo exists but it's parent
// does not.
type Map map[string]Handler

var _ Handler = Map(nil)

func (c Map) ServeHTTP(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	if req.URL.Path == "" {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
	seg, rest := segment(req.URL.Path)
	req.URL.Path = rest

	var child Handler
	if c != nil {
		child = c[seg]
	}
	if child == nil {
		if seg == "" {
			// Special case trailing slash; it's too easy to assume
			// that if "/foo/" 404s, "/foo/bar" won't exist.
			http.Error(w, "Forbidden", http.StatusForbidden)
			return
		}
		http.NotFound(w, req)
		return
	}
	child.ServeHTTP(ctx, w, req)
}
<commit_msg>Grammar fix<commit_after>package darwini

import (
	"net/http"

	"golang.org/x/net/context"
)

// Map multiplexes requests to children based on a map lookup. For Map
// at /path, /path will be forbidden, /path/seg and /path/seg/anything
// are served by the map entry for seg, or not found if nil.
//
// As a special case, missing /path/ is forbidden instead of not
// found, to avoid a situation where /path/foo exists but its parent
// does not.
type Map map[string]Handler

var _ Handler = Map(nil)

func (c Map) ServeHTTP(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	if req.URL.Path == "" {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
	seg, rest := segment(req.URL.Path)
	req.URL.Path = rest

	var child Handler
	if c != nil {
		child = c[seg]
	}
	if child == nil {
		if seg == "" {
			// Special case trailing slash; it's too easy to assume
			// that if "/foo/" 404s, "/foo/bar" won't exist.
			http.Error(w, "Forbidden", http.StatusForbidden)
			return
		}
		http.NotFound(w, req)
		return
	}
	child.ServeHTTP(ctx, w, req)
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Dmitry Ponomarev <demdxx@gmail.com>
//
// 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 gocast

import (
  "reflect"
)

func ToMapFrom(src interface{}, tag string) (map[interface{}]interface{}, error) {
  dst := make(map[interface{}]interface{})
  err := ToMap(dst, src, tag)
  return dst, err
}

func ToMap(dst, src interface{}, tag string) (err error) {
  if nil == dst || nil == src {
    err = errInvalidParams
  } else {
    dst = reflectTarget(reflect.ValueOf(dst)).Interface()
    s := reflectTarget(reflect.ValueOf(src))
    t := s.Type()

    switch dst.(type) {
    case map[interface{}]interface{}:
      if reflect.Map == t.Kind() {
        for _, k := range s.MapKeys() {
          dst.(map[interface{}]interface{})[k.Interface()] = s.MapIndex(k).Interface()
        }
      } else {
        for i := 0; i < s.NumField(); i++ {
          dst.(map[interface{}]interface{})[fieldName(t.Field(i), tag)] = s.Field(i).Interface()
        }
      }
      break
    case map[string]interface{}:
      if reflect.Map == t.Kind() {
        for _, k := range s.MapKeys() {
          dst.(map[string]interface{})[ToString(k.Interface())] = s.MapIndex(k).Interface()
        }
      } else {
        for i := 0; i < s.NumField(); i++ {
          dst.(map[string]interface{})[fieldName(t.Field(i), tag)] = s.Field(i).Interface()
        }
      }
      break
    case map[string]string:
      if reflect.Map == t.Kind() {
        for _, k := range s.MapKeys() {
          dst.(map[string]interface{})[ToString(k.Interface())] = ToString(s.MapIndex(k).Interface())
        }
      } else {
        for i := 0; i < s.NumField(); i++ {
          dst.(map[string]string)[fieldName(t.Field(i), tag)] = ToString(s.Field(i).Interface())
        }
      }
      break
    default:
      err = errUnsupportedType
    }
  }
  return
}

func ToSiMap(src interface{}, tag string) (map[string]interface{}, error) {
  dst := make(map[string]interface{})
  err := ToMap(dst, src, tag)
  return dst, err
}

func ToStringMap(src interface{}, tag string) (map[string]string, error) {
  dst := make(map[string]string)
  err := ToMap(dst, src, tag)
  return dst, err
}

///////////////////////////////////////////////////////////////////////////////
/// MARK: Helpers
///////////////////////////////////////////////////////////////////////////////

func mapValueByKeys(src interface{}, keys []interface{}) interface{} {
  if nil == src || nil == keys {
    return nil
  }
  sKeys := make([]string, len(keys))
  for i, v := range keys {
    sKeys[i] = ToString(v)
  }
  return mapValueByStringKeys(src, sKeys)
}

func mapValueByStringKeys(src interface{}, keys []string) interface{} {
  switch src.(type) {
  case map[interface{}]interface{}:
    for k, v := range src.(map[interface{}]interface{}) {
      skey := ToString(k)
      for _, ks := range keys {
        if skey == ks {
          return v
        }
      }
    }
    break
  case map[string]interface{}:
    for k, v := range src.(map[string]interface{}) {
      for _, ks := range keys {
        if k == ks {
          return v
        }
      }
    }
    break
  case map[string]string:
    for k, v := range src.(map[string]string) {
      for _, ks := range keys {
        if k == ks {
          var i interface{} = v
          return i
        }
      }
    }
    break
  }
  return nil
}
<commit_msg>Fix string map cast<commit_after>// Copyright (c) 2014 Dmitry Ponomarev <demdxx@gmail.com>
//
// 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 gocast

import (
  "reflect"
)

func ToMapFrom(src interface{}, tag string) (map[interface{}]interface{}, error) {
  dst := make(map[interface{}]interface{})
  err := ToMap(dst, src, tag)
  return dst, err
}

func ToMap(dst, src interface{}, tag string) (err error) {
  if nil == dst || nil == src {
    err = errInvalidParams
  } else {
    dst = reflectTarget(reflect.ValueOf(dst)).Interface()
    s := reflectTarget(reflect.ValueOf(src))
    t := s.Type()

    switch dst.(type) {
    case map[interface{}]interface{}:
      if reflect.Map == t.Kind() {
        for _, k := range s.MapKeys() {
          dst.(map[interface{}]interface{})[k.Interface()] = s.MapIndex(k).Interface()
        }
      } else {
        for i := 0; i < s.NumField(); i++ {
          dst.(map[interface{}]interface{})[fieldName(t.Field(i), tag)] = s.Field(i).Interface()
        }
      }
      break
    case map[string]interface{}:
      if reflect.Map == t.Kind() {
        for _, k := range s.MapKeys() {
          dst.(map[string]interface{})[ToString(k.Interface())] = s.MapIndex(k).Interface()
        }
      } else {
        for i := 0; i < s.NumField(); i++ {
          dst.(map[string]interface{})[fieldName(t.Field(i), tag)] = s.Field(i).Interface()
        }
      }
      break
    case map[string]string:
      if reflect.Map == t.Kind() {
        for _, k := range s.MapKeys() {
          dst.(map[string]string)[ToString(k.Interface())] = ToString(s.MapIndex(k).Interface())
        }
      } else {
        for i := 0; i < s.NumField(); i++ {
          dst.(map[string]string)[fieldName(t.Field(i), tag)] = ToString(s.Field(i).Interface())
        }
      }
      break
    default:
      err = errUnsupportedType
    }
  }
  return
}

func ToSiMap(src interface{}, tag string) (map[string]interface{}, error) {
  dst := make(map[string]interface{})
  err := ToMap(dst, src, tag)
  return dst, err
}

func ToStringMap(src interface{}, tag string) (map[string]string, error) {
  dst := make(map[string]string)
  err := ToMap(dst, src, tag)
  return dst, err
}

///////////////////////////////////////////////////////////////////////////////
/// MARK: Helpers
///////////////////////////////////////////////////////////////////////////////

func mapValueByKeys(src interface{}, keys []interface{}) interface{} {
  if nil == src || nil == keys {
    return nil
  }
  sKeys := make([]string, len(keys))
  for i, v := range keys {
    sKeys[i] = ToString(v)
  }
  return mapValueByStringKeys(src, sKeys)
}

func mapValueByStringKeys(src interface{}, keys []string) interface{} {
  switch src.(type) {
  case map[interface{}]interface{}:
    for k, v := range src.(map[interface{}]interface{}) {
      skey := ToString(k)
      for _, ks := range keys {
        if skey == ks {
          return v
        }
      }
    }
    break
  case map[string]interface{}:
    for k, v := range src.(map[string]interface{}) {
      for _, ks := range keys {
        if k == ks {
          return v
        }
      }
    }
    break
  case map[string]string:
    for k, v := range src.(map[string]string) {
      for _, ks := range keys {
        if k == ks {
          var i interface{} = v
          return i
        }
      }
    }
    break
  }
  return nil
}
<|endoftext|>


<commit_before>package gostats

import (
  "math"
)

func Max(slice []float64) (float64, error) {
  if len(slice) == 0 {
    return math.NaN(), EmptySlice
  }
  max := slice[0]
  for i := 1; i < len(slice); i++ {
    if slice[i] > max {
      max = slice[i]
    }
  }
  return max, nil
}
<commit_msg>add comment for godoc<commit_after>package gostats

import (
  "math"
)

//return the largest value in a slice
func Max(slice []float64) (float64, error) {
  if len(slice) == 0 {
    return math.NaN(), EmptySlice
  }
  max := slice[0]
  for i := 1; i < len(slice); i++ {
    if slice[i] > max {
      max = slice[i]
    }
  }
  return max, nil
}
<|endoftext|>


<commit_before>package xmpp

import (
	"encoding/xml"
	"fmt"
	"strings"
)

const (
	NsMUC     = "http://jabber.org/protocol/muc"
	NsMUCUser = "http://jabber.org/protocol/muc#user"
)

type Status struct {
	XMLName xml.Name `xml:"status"`
	Code    string   `xml:"code,attr"`
}

type Item struct {
	XMLName xml.Name `xml:"item"`
	// owner, admin, member, outcast, none
	Affiliation string `xml:"affiliation,attr,omitempty"`
	// moderator, participant, visitor, none
	Role string `xml:"role,attr,omitempty"`
	JID  string `xml:"jid,attr,omitempty"`
}

type X struct {
	XMLName  xml.Name `xml:"http://jabber.org/protocol/muc#user x"`
	Items    []Item   `xml:"item,omitempty"`
	Statuses []Status `xml:"status,omitempty"`
}

type Photo struct {
	XMLName xml.Name `xml:"vcard-temp:x:update x"`
	Photo   string   `xml:"photo,omitempty"`
}

// http://xmpp.org/extensions/xep-0045.html
// <presence />
type MUCPresence struct {
	XMLName xml.Name `xml:"presence"`
	Lang    string   `xml:"lang,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	Id      string   `xml:"id.attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`

	X     []X   `xml:"http://jabber.org/protocol/muc#user x,omitempty"`
	Photo Photo `xml:"vcard-temp:x:update x"` // http://xmpp.org/extensions/xep-0153.html

	Show     string       `xml:"show,omitempty"`   // away, chat, dnd, xa
	Status   string       `xml:"status,omitempty"` // sb []clientText
	Priority string       `xml:"priority,omitempty"`
	Caps     *ClientCaps  `xml:"c"`
	Error    *ClientError `xml:"error"`
}

// JoinMUC joins to a given conference with nick and optional password
// http://xmpp.org/extensions/xep-0045.html#bizrules-presence
func (c *Conn) JoinMUC(to, nick, password string) error {
	c.lock.Lock()
	defer c.lock.Unlock()
	// remove resource from jid
	parts := strings.SplitN(to, "/", 2)
	to = parts[0]
	if len(nick) == 0 {
		if len(parts) == 2 {
			nick = parts[1]
		} else { // if nick empty & bare jid, set nick to login
			nick = strings.SplitN(c.jid, "@", 2)[0]
		}
	}
	var pass string
	if len(password) > 0 {
		pass = "<password>" + password + "</password>"
	}
	stanza := fmt.Sprintf("<presence from='%s' to='%s/%s'>"+
		"\n  <x xmlns='%s'>"+
		"\n    <history maxchars='0' />"+
		"\n    "+pass+
		"\n  </x>"+
		"\n</presence>",
		xmlEscape(c.jid), xmlEscape(to), xmlEscape(nick), NsMUC)
	_, err := fmt.Fprintf(c.out, stanza)
	return err
}

// SendMUC sends a message to the given conference with specified type (chat or groupchat).
func (c *Conn) SendMUC(to, typ, msg string) error {
	if typ == "" {
		typ = "groupchat"
	}
	cookie := c.getCookie()
	stanza := fmt.Sprintf("<message from='%s' to='%s' type='%s' id='%x'>%s</message>",
		xmlEscape(c.jid), xmlEscape(to), xmlEscape(typ), cookie, xmlEscape(msg))
	_, err := fmt.Fprintf(c.out, stanza)
	return err
}
<commit_msg>MUCPResence->X: add some structures<commit_after>package xmpp

import (
	"encoding/xml"
	"fmt"
	"strings"
)

const (
	NsMUC     = "http://jabber.org/protocol/muc"
	NsMUCUser = "http://jabber.org/protocol/muc#user"
)

type Status struct {
	XMLName xml.Name `xml:"status"`
	Code    string   `xml:"code,attr"`
}

type Item struct {
	XMLName xml.Name `xml:"item"`
	// owner, admin, member, outcast, none
	Affiliation string `xml:"affiliation,attr,omitempty"`
	// moderator, participant, visitor, none
	Role string `xml:"role,attr,omitempty"`
	JID  string `xml:"jid,attr,omitempty"`
	Nick string `xml:"nick,attr,omitempty"`
}

type X struct {
	XMLName  xml.Name `xml:"http://jabber.org/protocol/muc#user x"`
	Items    []Item   `xml:"item,omitempty"`
	Statuses []Status `xml:"status,omitempty"`
	Decline  Reason   `xml:"decline,omitempty"`
	Invite   Reason   `xml:"invite,omitempty"`
	Destroy  XDestroy `xml:"destroy,omitempty"`
	Password string   `xml:"password,omitempty"`
}

type Photo struct {
	XMLName xml.Name `xml:"vcard-temp:x:update x"`
	Photo   string   `xml:"photo,omitempty"`
}

type Reason struct {
	From   string `xml:"from,attr,omitempty"`
	To     string `xml:"to,attr,omitempty"`
	Reason string `xml:"reason,omitempty"`
}

type XDestroy struct {
	JID    string `xml:"jid,attr,omitempty"`
	Reason string `xml:"reason,omitempty"`
}

// http://xmpp.org/extensions/xep-0045.html
// <presence />
type MUCPresence struct {
	XMLName xml.Name `xml:"presence"`
	Lang    string   `xml:"lang,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	Id      string   `xml:"id.attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`

	X     []X   `xml:"http://jabber.org/protocol/muc#user x,omitempty"`
	Photo Photo `xml:"vcard-temp:x:update x"` // http://xmpp.org/extensions/xep-0153.html

	Show     string       `xml:"show,omitempty"`   // away, chat, dnd, xa
	Status   string       `xml:"status,omitempty"` // sb []clientText
	Priority string       `xml:"priority,omitempty"`
	Caps     *ClientCaps  `xml:"c"`
	Error    *ClientError `xml:"error"`
}

// JoinMUC joins to a given conference with nick and optional password
// http://xmpp.org/extensions/xep-0045.html#bizrules-presence
func (c *Conn) JoinMUC(to, nick, password string) error {
	c.lock.Lock()
	defer c.lock.Unlock()
	// remove resource from jid
	parts := strings.SplitN(to, "/", 2)
	to = parts[0]
	if len(nick) == 0 {
		if len(parts) == 2 {
			nick = parts[1]
		} else { // if nick empty & bare jid, set nick to login
			nick = strings.SplitN(c.jid, "@", 2)[0]
		}
	}
	var pass string
	if len(password) > 0 {
		pass = "<password>" + password + "</password>"
	}
	stanza := fmt.Sprintf("<presence from='%s' to='%s/%s'>"+
		"\n  <x xmlns='%s'>"+
		"\n    <history maxchars='0' />"+
		"\n    "+pass+
		"\n  </x>"+
		"\n</presence>",
		xmlEscape(c.jid), xmlEscape(to), xmlEscape(nick), NsMUC)
	_, err := fmt.Fprintf(c.out, stanza)
	return err
}

// SendMUC sends a message to the given conference with specified type (chat or groupchat).
func (c *Conn) SendMUC(to, typ, msg string) error {
	if typ == "" {
		typ = "groupchat"
	}
	cookie := c.getCookie()
	stanza := fmt.Sprintf("<message from='%s' to='%s' type='%s' id='%x'>%s</message>",
		xmlEscape(c.jid), xmlEscape(to), xmlEscape(typ), cookie, xmlEscape(msg))
	_, err := fmt.Fprintf(c.out, stanza)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package mux

import (
	"container/list"
	"fmt"
	"net/http"
	"strings"

	"github.com/issue9/context"
)

// 支持的所有请求方法
var supportMethods = []string{
	"GET",
	"POST",
	"HEAD",
	"DELETE",
	"PUT",
	"OPTIONS",
	"TRACE",
	"PATCH",
}

// http.ServeMux的升级版，可处理对URL的正则匹配和根据METHOD进行过滤。
//
// 用法如下：
//  m := mux.NewServeMux()
//  m.Get("www.example.com/abc", h1).              // 只匹配www.example.com域名下的路径
//    Post("/abc/"", h2).                          // 不限定域名的路径匹配
//    Add("/api/{version:\\d+}",h3, "GET", "POST") // 只匹配GET和POST
//  http.ListenAndServe(m)
//
//
// 路由参数：
//
// 路由参数可通过context包获取：
//  ctx := context.Get(req)
//  params := ctx.Get("params") // 若不存在路由参数，则返回一个空值
// NOTE:记得在退出整个请求之前清除context中的内容：
//  context.Free(req)
//
//
// 匹配规则：
//
// 可能会出现多条记录与同一请求都匹配的情况，这种情况下，
// 系统会找到一条认为最匹配的路由来处理，判断规则如下：
//  1. 静态路由优先于正则路由判断；
//  2. 完全匹配的路由项优先于部分匹配的路由项；
//  3. 正则只能是完全匹配；
//  4. 只有以/结尾的静态路由才有部分匹配功能。
//
// 正则匹配语法：
//  /post/{id}     // 匹配/post/开头的任意字符串，其后的字符串保存到id中；
//  /post/{id:\d+} // 同上，但id的值只能为\d+；
//  /post/{:\d+}   // 同上，但是没有命名；
type ServeMux struct {
	// 路由列表，键名表示method。list中静态路由在前，正则路由在后。
	list map[string]*list.List
}

// 声明一个新的ServeMux
func NewServeMux() *ServeMux {
	l := make(map[string]*list.List, len(supportMethods))
	for _, method := range supportMethods {
		l[method] = list.New()
	}

	return &ServeMux{
		list: l,
	}
}

// 检测匹配模式是否存在，则不存在则返回error
func (mux *ServeMux) checkExists(pattern, method string) error {
	l, found := mux.list[method]
	if !found {
		return fmt.Errorf("不支持的request.Method:[%v]", method)
	}

	for item := l.Front(); item != nil; item = item.Next() {
		if e := item.Value.(*entry); e.pattern == pattern {
			return fmt.Errorf("该模式[%v]的路由项已经存在:", pattern)
		}
	}

	return nil
}

// 添加一个路由项。
func (mux *ServeMux) add(g *Group, pattern string, h http.Handler, methods ...string) *ServeMux {
	if h == nil {
		panic("参数h不能为空")
	}

	if len(methods) == 0 {
		panic("至少指定一个mehtods参数")
	}

	e := newEntry(pattern, h, g)

	for _, method := range methods {
		method = strings.ToUpper(method)

		if err := mux.checkExists(pattern, method); err != nil {
			panic(err)
		}

		if e.expr == nil { // 静态路由，在前端插入
			mux.list[method].PushFront(e)
		} else { // 正则路由，在后端插入
			mux.list[method].PushBack(e)
		}
	}

	return mux
}

// 添加一条路由数据。
//
// pattern为路由匹配模式，可以是正则匹配也可以是字符串匹配，
// 可以带上域名，当第一个字符为'/'当作是一个路径，否则就将'/'之前的当作域名或IP。
// methods参数应该只能为supportMethods中的字符串，若不指定，默认为所有，
// 当h或是pattern为空时，将触发panic。
func (mux *ServeMux) Add(pattern string, h http.Handler, methods ...string) *ServeMux {
	return mux.add(nil, pattern, h, methods...)
}

// Get 相当于ServeMux.Add(pattern, h, "GET")的简易写法
func (mux *ServeMux) Get(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "GET")
}

// Post 相当于ServeMux.Add(pattern, h, "POST")的简易写法
func (mux *ServeMux) Post(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "POST")
}

// Delete 相当于ServeMux.Add(pattern, h, "DELETE")的简易写法
func (mux *ServeMux) Delete(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "DELETE")
}

// Put 相当于ServeMux.Add(pattern, h, "PUT")的简易写法
func (mux *ServeMux) Put(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "PUT")
}

// Patch 相当于ServeMux.Add(pattern, h, "PATCH")的简易写法
func (mux *ServeMux) Patch(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "PATCH")
}

// Any 相当于ServeMux.Add(pattern, h)的简易写法
func (mux *ServeMux) Any(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, supportMethods...)
}

func (mux *ServeMux) addFunc(g *Group, pattern string, fun func(http.ResponseWriter, *http.Request), methods ...string) *ServeMux {
	return mux.add(g, pattern, http.HandlerFunc(fun), methods...)
}

// AddFunc 功能同ServeMux.Add()，但是将第二个参数从http.Handler换成了func(http.ResponseWriter, *http.Request)
func (mux *ServeMux) AddFunc(pattern string, fun func(http.ResponseWriter, *http.Request), methods ...string) *ServeMux {
	return mux.Add(pattern, http.HandlerFunc(fun), methods...)
}

// GetFunc 相当于ServeMux.AddFunc(pattern, func, "GET")的简易写法
func (mux *ServeMux) GetFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "GET")
}

// PutFunc 相当于ServeMux.AddFunc(pattern, func, "PUT")的简易写法
func (mux *ServeMux) PutFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "PUT")
}

// PostFunc 相当于ServeMux.AddFunc(pattern, func, "POST")的简易写法
func (mux *ServeMux) PostFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "POST")
}

// DeleteFunc 相当于ServeMux.AddFunc(pattern, func, "DELETE")的简易写法
func (mux *ServeMux) DeleteFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "DELETE")
}

// PatchFunc 相当于ServeMux.AddFunc(pattern, func, "PATCH")的简易写法
func (mux *ServeMux) PatchFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "PATCH")
}

// AnyFunc 相当于ServeMux.AddFunc(pattern, func)的简易写法
func (mux *ServeMux) AnyFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, supportMethods...)
}

// implement http.Handler.ServerHTTP()
// 若没有找到匹配路由，返回404
func (mux *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	hostURL := r.Host + r.URL.Path
	size := -1 // 匹配度，0表示完全匹配，负数表示完全不匹配，其它值越小匹配度越高
	var e *entry
	var p string

	for item := mux.list[r.Method].Front(); item != nil; item = item.Next() {
		entry := item.Value.(*entry)

		url := r.URL.Path
		if entry.hosts {
			url = hostURL
		}

		s := entry.match(url)
		if s == -1 || (size > 0 && s > size) { // 完全不匹配，或是匹配度没有当前的高
			continue
		}

		size = s
		e = entry
		p = url

		if s == 0 { // 完全匹配，可以中止匹配过程
			break
		}
	} // end for

	if size < 0 {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	params := e.getParams(p)
	if params != nil {
		ctx := context.Get(r)
		ctx.Set("params", params)
	}
	e.handler.ServeHTTP(w, r)
}
<commit_msg>为servemux添加一个读写锁<commit_after>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package mux

import (
	"container/list"
	"fmt"
	"net/http"
	"strings"
	"sync"

	"github.com/issue9/context"
)

// 支持的所有请求方法
var supportMethods = []string{
	"GET",
	"POST",
	"HEAD",
	"DELETE",
	"PUT",
	"OPTIONS",
	"TRACE",
	"PATCH",
}

// http.ServeMux的升级版，可处理对URL的正则匹配和根据METHOD进行过滤。
//
// 用法如下：
//  m := mux.NewServeMux()
//  m.Get("www.example.com/abc", h1).              // 只匹配www.example.com域名下的路径
//    Post("/abc/"", h2).                          // 不限定域名的路径匹配
//    Add("/api/{version:\\d+}",h3, "GET", "POST") // 只匹配GET和POST
//  http.ListenAndServe(m)
//
//
// 路由参数：
//
// 路由参数可通过context包获取：
//  ctx := context.Get(req)
//  params := ctx.Get("params") // 若不存在路由参数，则返回一个空值
// NOTE:记得在退出整个请求之前清除context中的内容：
//  context.Free(req)
//
//
// 匹配规则：
//
// 可能会出现多条记录与同一请求都匹配的情况，这种情况下，
// 系统会找到一条认为最匹配的路由来处理，判断规则如下：
//  1. 静态路由优先于正则路由判断；
//  2. 完全匹配的路由项优先于部分匹配的路由项；
//  3. 正则只能是完全匹配；
//  4. 只有以/结尾的静态路由才有部分匹配功能。
//
// 正则匹配语法：
//  /post/{id}     // 匹配/post/开头的任意字符串，其后的字符串保存到id中；
//  /post/{id:\d+} // 同上，但id的值只能为\d+；
//  /post/{:\d+}   // 同上，但是没有命名；
type ServeMux struct {
	mu sync.RWMutex

	// 路由列表，键名表示method。list中静态路由在前，正则路由在后。
	list map[string]*list.List
}

// 声明一个新的ServeMux
func NewServeMux() *ServeMux {
	l := make(map[string]*list.List, len(supportMethods))
	for _, method := range supportMethods {
		l[method] = list.New()
	}

	return &ServeMux{
		list: l,
	}
}

// 检测匹配模式是否存在，则不存在则返回error
func (mux *ServeMux) checkExists(pattern, method string) error {
	l, found := mux.list[method]
	if !found {
		return fmt.Errorf("不支持的request.Method:[%v]", method)
	}

	for item := l.Front(); item != nil; item = item.Next() {
		if e := item.Value.(*entry); e.pattern == pattern {
			return fmt.Errorf("该模式[%v]的路由项已经存在:", pattern)
		}
	}

	return nil
}

// 添加一个路由项。
func (mux *ServeMux) add(g *Group, pattern string, h http.Handler, methods ...string) *ServeMux {
	if h == nil {
		panic("参数h不能为空")
	}

	if len(methods) == 0 {
		panic("至少指定一个mehtods参数")
	}

	e := newEntry(pattern, h, g)

	mux.mu.Lock()
	defer mux.mu.Unlock()

	for _, method := range methods {
		method = strings.ToUpper(method)

		if err := mux.checkExists(pattern, method); err != nil {
			panic(err)
		}

		if e.expr == nil { // 静态路由，在前端插入
			mux.list[method].PushFront(e)
		} else { // 正则路由，在后端插入
			mux.list[method].PushBack(e)
		}
	}

	return mux
}

// 添加一条路由数据。
//
// pattern为路由匹配模式，可以是正则匹配也可以是字符串匹配，
// 可以带上域名，当第一个字符为'/'当作是一个路径，否则就将'/'之前的当作域名或IP。
// methods参数应该只能为supportMethods中的字符串，若不指定，默认为所有，
// 当h或是pattern为空时，将触发panic。
func (mux *ServeMux) Add(pattern string, h http.Handler, methods ...string) *ServeMux {
	return mux.add(nil, pattern, h, methods...)
}

// Get 相当于ServeMux.Add(pattern, h, "GET")的简易写法
func (mux *ServeMux) Get(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "GET")
}

// Post 相当于ServeMux.Add(pattern, h, "POST")的简易写法
func (mux *ServeMux) Post(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "POST")
}

// Delete 相当于ServeMux.Add(pattern, h, "DELETE")的简易写法
func (mux *ServeMux) Delete(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "DELETE")
}

// Put 相当于ServeMux.Add(pattern, h, "PUT")的简易写法
func (mux *ServeMux) Put(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "PUT")
}

// Patch 相当于ServeMux.Add(pattern, h, "PATCH")的简易写法
func (mux *ServeMux) Patch(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, "PATCH")
}

// Any 相当于ServeMux.Add(pattern, h)的简易写法
func (mux *ServeMux) Any(pattern string, h http.Handler) *ServeMux {
	return mux.Add(pattern, h, supportMethods...)
}

func (mux *ServeMux) addFunc(g *Group, pattern string, fun func(http.ResponseWriter, *http.Request), methods ...string) *ServeMux {
	return mux.add(g, pattern, http.HandlerFunc(fun), methods...)
}

// AddFunc 功能同ServeMux.Add()，但是将第二个参数从http.Handler换成了func(http.ResponseWriter, *http.Request)
func (mux *ServeMux) AddFunc(pattern string, fun func(http.ResponseWriter, *http.Request), methods ...string) *ServeMux {
	return mux.Add(pattern, http.HandlerFunc(fun), methods...)
}

// GetFunc 相当于ServeMux.AddFunc(pattern, func, "GET")的简易写法
func (mux *ServeMux) GetFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "GET")
}

// PutFunc 相当于ServeMux.AddFunc(pattern, func, "PUT")的简易写法
func (mux *ServeMux) PutFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "PUT")
}

// PostFunc 相当于ServeMux.AddFunc(pattern, func, "POST")的简易写法
func (mux *ServeMux) PostFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "POST")
}

// DeleteFunc 相当于ServeMux.AddFunc(pattern, func, "DELETE")的简易写法
func (mux *ServeMux) DeleteFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "DELETE")
}

// PatchFunc 相当于ServeMux.AddFunc(pattern, func, "PATCH")的简易写法
func (mux *ServeMux) PatchFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, "PATCH")
}

// AnyFunc 相当于ServeMux.AddFunc(pattern, func)的简易写法
func (mux *ServeMux) AnyFunc(pattern string, fun func(http.ResponseWriter, *http.Request)) *ServeMux {
	return mux.AddFunc(pattern, fun, supportMethods...)
}

// implement http.Handler.ServerHTTP()
// 若没有找到匹配路由，返回404
func (mux *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	hostURL := r.Host + r.URL.Path
	size := -1 // 匹配度，0表示完全匹配，负数表示完全不匹配，其它值越小匹配度越高
	var e *entry
	var p string

	mux.mu.RLock()
	defer mux.mu.RUnlock()

	for item := mux.list[r.Method].Front(); item != nil; item = item.Next() {
		entry := item.Value.(*entry)

		url := r.URL.Path
		if entry.hosts {
			url = hostURL
		}

		s := entry.match(url)
		if s == -1 || (size > 0 && s > size) { // 完全不匹配，或是匹配度没有当前的高
			continue
		}

		size = s
		e = entry
		p = url

		if s == 0 { // 完全匹配，可以中止匹配过程
			break
		}
	} // end for

	if size < 0 {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	params := e.getParams(p)
	if params != nil {
		ctx := context.Get(r)
		ctx.Set("params", params)
	}
	e.handler.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>package serviced

import (
	"github.com/zenoss/glog"

	"bufio"
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/textproto"
	"strconv"
	"strings"
)

type TCPMux struct {
	Enabled     bool
	UseTLS      bool
	CertPEMFile string
	KeyPEMFile  string
	Port        int
}

type MuxConfig struct {
	Proxies   []Proxy
	TCPMux    TCPMux
	ServiceId string
	Command   string
}

// sendMuxError logs an error message and attempts to write it to the connected
// endpoint
func sendMuxError(conn net.Conn, source, facility, msg string, err error) {
	glog.Errorf("%s Error (%s): %v\n", source, facility, err)
	if _, e := conn.Write([]byte(msg)); e != nil {
		glog.Errorf("%s", e)
	}
}

// muxConnection takes an inbound connection reads MIME headers from it and
// then attempts to set up a connection to the service specified by the
// Zen-Service header. If the Zen-Service header is missing or the requested
// service is not running (listening) on the local host and error message
// is sent to the requestor and its connection is closed. Otherwise data is
// proxied between the requestor and the local service.
func (mux TCPMux) MuxConnection(conn net.Conn) {
	rdr := textproto.NewReader(bufio.NewReader(conn))
	hdr, err := rdr.ReadMIMEHeader()
	if err != nil {
		sendMuxError(conn, "MuxConnection", "textproto.ReadMIMEHeader", "bad request (no headers)", err)
		conn.Close()
		return
	}

	zs, ok := hdr["Zen-Service"]
	if ok == false {
		sendMuxError(conn, "MuxConnection", "MIMEHeader", "bad request (no Zen-Service header)", err)
		conn.Close()
		return
	}

	port, err := strconv.Atoi(strings.Split(zs[0], "/")[1])
	if err != nil {
		sendMuxError(conn, "MuxConnection", "Zen-Service Header", "bad Zen-Service spec", err)
		conn.Close()
		return
	}

	svc, err := net.Dial("tcp4", fmt.Sprintf("172.17.42.1:%d", port))
	if err != nil {
		sendMuxError(conn, "MuxConnection", "net.Dial", "cannot connect to service", err)
		conn.Close()
		return
	}

	go func() {
		io.Copy(conn, svc)
		conn.Close()
		svc.Close()
	}()
	go func() {
		io.Copy(svc, conn)
		conn.Close()
		svc.Close()
	}()
}

// ListenAndMux listens for incoming connections and attempts to multiplex them
// to the local service that they request via a Zen-Service header in their
// initial message.
func (mux *TCPMux) ListenAndMux() {
	var l net.Listener
	var err error

	if mux.UseTLS == false {
		l, err = net.Listen("tcp4", fmt.Sprintf(":%d", mux.Port))
	} else {
		cert, cerr := tls.X509KeyPair([]byte(proxyCertPEM), []byte(proxyKeyPEM))
		if cerr != nil {
			glog.Error("ListenAndMux Error (tls.X509KeyPair): ", cerr)
			return
		}

		tlsConfig := tls.Config{Certificates: []tls.Certificate{cert}}
		l, err = tls.Listen("tcp4", fmt.Sprintf(":%d", mux.Port), &tlsConfig)
	}
	if err != nil {
		glog.Error("ListenAndMux Error (net.Listen): ", err)
		return
	}
	defer l.Close()

	for {
		conn, err := l.Accept()
		if err != nil {
			glog.Error("ListenAndMux Error (net.Accept): ", err)
			return
		}

		go mux.MuxConnection(conn)
	}
}
<commit_msg>cannot connect changed to warning<commit_after>package serviced

import (
	"github.com/zenoss/glog"

	"bufio"
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/textproto"
	"strconv"
	"strings"
)

type TCPMux struct {
	Enabled     bool
	UseTLS      bool
	CertPEMFile string
	KeyPEMFile  string
	Port        int
}

type MuxConfig struct {
	Proxies   []Proxy
	TCPMux    TCPMux
	ServiceId string
	Command   string
}

// sendMuxError logs an error message and attempts to write it to the connected
// endpoint
func sendMuxError(conn net.Conn, source, facility, msg string, err error) {
	glog.Errorf("%s Error (%s): %v\n", source, facility, err)
	if _, e := conn.Write([]byte(msg)); e != nil {
		glog.Errorf("%s", e)
	}
}

// sendMuxWarning logs an error message and attempts to write it to the connected
// endpoint
func sendMuxWarning(conn net.Conn, source, facility, msg string, err error) {
	glog.Warningf("%s Error (%s): %v\n", source, facility, err)
	if _, e := conn.Write([]byte(msg)); e != nil {
		glog.Warningf("%s", e)
	}
}

// muxConnection takes an inbound connection reads MIME headers from it and
// then attempts to set up a connection to the service specified by the
// Zen-Service header. If the Zen-Service header is missing or the requested
// service is not running (listening) on the local host and error message
// is sent to the requestor and its connection is closed. Otherwise data is
// proxied between the requestor and the local service.
func (mux TCPMux) MuxConnection(conn net.Conn) {
	rdr := textproto.NewReader(bufio.NewReader(conn))
	hdr, err := rdr.ReadMIMEHeader()
	if err != nil {
		sendMuxError(conn, "MuxConnection", "textproto.ReadMIMEHeader", "bad request (no headers)", err)
		conn.Close()
		return
	}

	zs, ok := hdr["Zen-Service"]
	if ok == false {
		sendMuxError(conn, "MuxConnection", "MIMEHeader", "bad request (no Zen-Service header)", err)
		conn.Close()
		return
	}

	port, err := strconv.Atoi(strings.Split(zs[0], "/")[1])
	if err != nil {
		sendMuxError(conn, "MuxConnection", "Zen-Service Header", "bad Zen-Service spec", err)
		conn.Close()
		return
	}

	svc, err := net.Dial("tcp4", fmt.Sprintf("172.17.42.1:%d", port))
	if err != nil {
		sendMuxWarning(conn, "MuxConnection", "net.Dial", "cannot connect to service", err)
		conn.Close()
		return
	}

	go func() {
		io.Copy(conn, svc)
		conn.Close()
		svc.Close()
	}()
	go func() {
		io.Copy(svc, conn)
		conn.Close()
		svc.Close()
	}()
}

// ListenAndMux listens for incoming connections and attempts to multiplex them
// to the local service that they request via a Zen-Service header in their
// initial message.
func (mux *TCPMux) ListenAndMux() {
	var l net.Listener
	var err error

	if mux.UseTLS == false {
		l, err = net.Listen("tcp4", fmt.Sprintf(":%d", mux.Port))
	} else {
		cert, cerr := tls.X509KeyPair([]byte(proxyCertPEM), []byte(proxyKeyPEM))
		if cerr != nil {
			glog.Error("ListenAndMux Error (tls.X509KeyPair): ", cerr)
			return
		}

		tlsConfig := tls.Config{Certificates: []tls.Certificate{cert}}
		l, err = tls.Listen("tcp4", fmt.Sprintf(":%d", mux.Port), &tlsConfig)
	}
	if err != nil {
		glog.Error("ListenAndMux Error (net.Listen): ", err)
		return
	}
	defer l.Close()

	for {
		conn, err := l.Accept()
		if err != nil {
			glog.Error("ListenAndMux Error (net.Accept): ", err)
			return
		}

		go mux.MuxConnection(conn)
	}
}
<|endoftext|>


<commit_before>package gothink

import (
    "encoding/json"
    "io/ioutil"
)

type Net interface {
    Epoch()
}

type Layer struct {
    Activation  string
    Weights     [][]float64
}

/*
A feed forward type neural network
*/
type FFNet struct {
    //Net
    Layers []Layer
}

/*
func NewFFNet (filePath string) *FFNet {
    f := FFNet{}
    //f.Layers = make([]InputLayer, 1) // Change to interface{}
    _, err := ioutil.ReadFile(filePath)

    if err != nil {
        panic("failed to load" + filePath)
    }

    return (&f)
}
*/

func FromJson (filepath string) (*FFNet, error) {
    b, err := ioutil.ReadFile(filepath)

    if err != nil {
        panic(err)
    }

    ff := FFNet{}
    return &ff, json.Unmarshal(b, &ff)
}

/*
func (ff *FFNet) ToJson (jsonStr string) error {
    var data = &ff.Layers
}
*/

/*
func EncFFNet () ([]byte, error) {
    f := FFNet{}

    f.Layers = make(map[string]interface{})

    f.Layers["one"] = []float64{.5, .2}
    f.Layers["two"] = []float64{.0, .1}
    return json.Marshal(f)
}
*/
<commit_msg>Change FromJSON to NewFFNet struct initializer function<commit_after>package gothink

import (
    "encoding/json"
    "io/ioutil"
)

type Net interface {
    Epoch()
}

type Layer struct {
    Activation  string
    Weights     [][]float64
}

/*
A feed forward type neural network
*/
type FFNet struct {
    //Net
    Layers []Layer
}

func NewFFNet (filepath string) (*FFNet, error) {
    b, err := ioutil.ReadFile(filepath)

    if err != nil {
        panic(err)
    }

    ff := FFNet{}
    return &ff, json.Unmarshal(b, &ff)
}

/*
func (ff *FFNet) ToJson (jsonStr string) error {
    var data = &ff.Layers
}
*/

/*
func EncFFNet () ([]byte, error) {
    f := FFNet{}

    f.Layers = make(map[string]interface{})

    f.Layers["one"] = []float64{.5, .2}
    f.Layers["two"] = []float64{.0, .1}
    return json.Marshal(f)
}
*/
<|endoftext|>


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

package main

// Now tells what time it is in other time zones. The first argument
// identifies a time zone either by shorthand (EST, NYC) or by time zone
// file base name, such as Yellowknife or Paris.
//
// % now Paris
// Thu Apr 12 15:55:55 CEST 2012 Paris
// % now Adelaide
// Thu Apr 12 23:26:14 CST 2012 Adelaide
// %

import (
	"fmt"
	"os"
	"path/filepath"
	"time"
)

func main() {
	zone := ""
	t := time.Now()
	if len(os.Args) > 1 {
		zone = os.Args[1]
		if tz, ok := timeZone[zone]; ok {
			zone = tz
		} else if tz, ok = timeZone[toUpper(zone)]; ok {
			zone = tz
		}
		t = t.In(loadZone(zone))
	}
	fmt.Printf("%s %s\n", t.Format(time.UnixDate), zone)
}

func loadZone(zone string) *time.Location {
	loc, err := time.LoadLocation(zone)
	if err == nil {
		return loc
	}
	// Pure ASCII, but OK. Allow us to say "paris" as well as "Paris".
	if len(zone) > 0 && 'a' <= zone[0] && zone[0] <= 'z' {
		zone = string(zone[0]+'A'-'a') + string(zone[1:])
	}
	// See if there's a file with that name in /usr/share/zoneinfo
	files, _ := filepath.Glob("/usr/share/zoneinfo/*/" + zone)
	if len(files) >= 1 {
		if len(files) > 1 {
			fmt.Fprintf(os.Stderr, "now: multiple time zones; using first of %v\n", files)
		}
		loc, err = time.LoadLocation(files[0][len("/usr/share/zoneinfo/"):])
		if err == nil {
			return loc
		}
	}
	fmt.Fprintf(os.Stderr, "now: %s\n", err)
	os.Exit(1)
	return nil

}

// Pure ASCII
func toUpper(s string) string {
	var b = make([]byte, len(s))
	for i := range b {
		c := s[i]
		if 'a' <= c && c <= 'z' {
			c -= ' '
		}
		b[i] = c
	}
	return string(b)
}

// from /usr/share/zoneinfo
var timeZone = map[string]string{
	"GMT":     "Europe/London",
	"BST":     "Europe/London",
	"BSDT":    "Europe/London",
	"CET":     "Europe/Paris",
	"UTC":     "",
	"PST":     "America/Los_Angeles",
	"PDT":     "America/Los_Angeles",
	"LA":      "America/Los_Angeles",
	"LAX":     "America/Los_Angeles",
	"MST":     "America/Denver",
	"MDT":     "America/Denver",
	"CST":     "America/Chicago",
	"CDT":     "America/Chicago",
	"Chicago": "America/Chicago",
	"EST":     "America/New_York",
	"EDT":     "America/New_York",
	"NYC":     "America/New_York",
	"NY":      "America/New_York",
	"AEST":    "Australia/Sydney",
	"AEDT":    "Australia/Sydney",
	"AWST":    "Australia/Perth",
	"AWDT":    "Australia/Perth",
	"ACST":    "Australia/Adelaide",
	"ACDT":    "Australia/Adelaide",
}
<commit_msg>all: add import comments, move to golang.org/x for tools<commit_after>// Copyright 2012 The rspace Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main // import "robpike.io/cmd/now"

// Now tells what time it is in other time zones. The first argument
// identifies a time zone either by shorthand (EST, NYC) or by time zone
// file base name, such as Yellowknife or Paris.
//
// % now Paris
// Thu Apr 12 15:55:55 CEST 2012 Paris
// % now Adelaide
// Thu Apr 12 23:26:14 CST 2012 Adelaide
// %

import (
	"fmt"
	"os"
	"path/filepath"
	"time"
)

func main() {
	zone := ""
	t := time.Now()
	if len(os.Args) > 1 {
		zone = os.Args[1]
		if tz, ok := timeZone[zone]; ok {
			zone = tz
		} else if tz, ok = timeZone[toUpper(zone)]; ok {
			zone = tz
		}
		t = t.In(loadZone(zone))
	}
	fmt.Printf("%s %s\n", t.Format(time.UnixDate), zone)
}

func loadZone(zone string) *time.Location {
	loc, err := time.LoadLocation(zone)
	if err == nil {
		return loc
	}
	// Pure ASCII, but OK. Allow us to say "paris" as well as "Paris".
	if len(zone) > 0 && 'a' <= zone[0] && zone[0] <= 'z' {
		zone = string(zone[0]+'A'-'a') + string(zone[1:])
	}
	// See if there's a file with that name in /usr/share/zoneinfo
	files, _ := filepath.Glob("/usr/share/zoneinfo/*/" + zone)
	if len(files) >= 1 {
		if len(files) > 1 {
			fmt.Fprintf(os.Stderr, "now: multiple time zones; using first of %v\n", files)
		}
		loc, err = time.LoadLocation(files[0][len("/usr/share/zoneinfo/"):])
		if err == nil {
			return loc
		}
	}
	fmt.Fprintf(os.Stderr, "now: %s\n", err)
	os.Exit(1)
	return nil

}

// Pure ASCII
func toUpper(s string) string {
	var b = make([]byte, len(s))
	for i := range b {
		c := s[i]
		if 'a' <= c && c <= 'z' {
			c -= ' '
		}
		b[i] = c
	}
	return string(b)
}

// from /usr/share/zoneinfo
var timeZone = map[string]string{
	"GMT":     "Europe/London",
	"BST":     "Europe/London",
	"BSDT":    "Europe/London",
	"CET":     "Europe/Paris",
	"UTC":     "",
	"PST":     "America/Los_Angeles",
	"PDT":     "America/Los_Angeles",
	"LA":      "America/Los_Angeles",
	"LAX":     "America/Los_Angeles",
	"MST":     "America/Denver",
	"MDT":     "America/Denver",
	"CST":     "America/Chicago",
	"CDT":     "America/Chicago",
	"Chicago": "America/Chicago",
	"EST":     "America/New_York",
	"EDT":     "America/New_York",
	"NYC":     "America/New_York",
	"NY":      "America/New_York",
	"AEST":    "Australia/Sydney",
	"AEDT":    "Australia/Sydney",
	"AWST":    "Australia/Perth",
	"AWDT":    "Australia/Perth",
	"ACST":    "Australia/Adelaide",
	"ACDT":    "Australia/Adelaide",
}
<|endoftext|>


<commit_before>package gocr

import (
	"math"

	"github.com/gonum/matrix/mat64"
)

type Coordinate struct {
	row int
	col int
}

func NewCoordinate(r, c int) *Coordinate {
	return &Coordinate{
		row: r,
		col: c,
	}
}

func (c *Coordinate) N() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col,
	}
}

func (c *Coordinate) E() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col + 1,
	}
}

func (c *Coordinate) S() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col,
	}
}

func (c *Coordinate) W() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col - 1,
	}
}

func (c *Coordinate) NE() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SE() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SW() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) NW() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col - 1,
	}
}

type ImageMatrix [][]uint8

type ImageVector []uint8

func NewImageMatrix(r, c int) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
	}

	return imageArray
}

func NewImageMatrixWithDefaultValue(r, c int, v uint8) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
		for j := 0; j < c; j++ {
			imageArray[i][j] = v
		}
	}

	return imageArray
}

func (i ImageMatrix) Dims() (int, int) {
	return len(i), len(i[0])
}

func (i ImageMatrix) At(r, c int) uint8 {
	return i[r][c]
}

func (i ImageMatrix) Set(r, c int, value uint8) {
	i[r][c] = value
}

func (i ImageMatrix) Slice(sr, er, sc, ec int) ImageMatrix {
	slice := NewImageMatrix(er-sr, ec-sc)

	for r := sr; r < er; r++ {
		for c := sc; c < ec; c++ {
			slice[r-sr][c-sc] = i[r][c]
		}
	}

	return slice
}

func (i ImageMatrix) NNInterpolation(tr, tc int) ImageMatrix {
	r, c := i.Dims()
	rRatio := float64(r) / float64(tr)
	cRatio := float64(c) / float64(tc)
	output := NewImageMatrix(tr, tc)

	for r := 0; r < tr; r++ {
		for c := 0; c < tc; c++ {
			pr := int(math.Floor(float64(r) * rRatio))
			pc := int(math.Floor(float64(c) * cRatio))

			output.Set(r, c, i.At(pr, pc))
		}
	}

	return output
}

func (i ImageMatrix) Pad(top, bottom, left, right int, value uint8) ImageMatrix {
	sr, sc := i.Dims()
	nr := sr + top + bottom
	nc := sc + left + right
	output := NewImageMatrixWithDefaultValue(nr, nc, value)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			output[r+top][c+left] = i[r][c]
		}
	}

	return output
}

func (i ImageMatrix) Row(r int) ImageVector {
	return i[r]
}

func (i ImageMatrix) Col(c int) ImageVector {
	v := NewImageVector(len(i))

	for j := 0; j < len(i); j++ {
		v[j] = i[j][c]
	}

	return v
}

type ImageMatrixs []ImageMatrix

func (is ImageMatrixs) Average() ImageMatrix {
	l := len(is)
	sr, sc := is[0].Dims()
	output := NewImageMatrix(sr, sc)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			sum := 0
			for i := 0; i < l; i++ {
				sum += int(is[i][r][c])
			}

			output[r][c] = uint8(sum / l)
		}
	}

	return output
}

func NewImageVector(l int) ImageVector {
	return make([]uint8, l)
}

func (v ImageVector) Sum() uint64 {
	var sum uint64 = 0

	for i := 0; i < len(v); i++ {
		sum += uint64(v[i])
	}

	return sum
}

// ========================= Convolution =========================

type fn func(int, bool) string

// Calculate size after forward
// ds: Data Size
// ks: Kernel / Filter size
// p: Padding
// s: Stride
func sizeAfter(ds, ks, p, s int) int {
	return ((ds - ks + 2*p) / s) + 1
}

func Sigmoid(x float64, deriv bool) float64 {
	if deriv {
		return x * (1 - x)
	}

	return 1 / (1 + math.Exp(-x))
}

func Relu(x float64, deriv bool) float64 {
	if deriv {
		if x > 0 {
			return 1
		} else {
			return 0
		}
	} else {
		if x > 0 {
			return x
		} else {
			return 0
		}
	}
}

func LeakyRelu(x float64, deriv bool) float64 {
	a := 0.001

	if deriv {
		if x > 0 {
			return 1
		} else {
			return a
		}
	} else {
		if x > 0 {
			return x
		} else {
			return a * x
		}
	}
}

func Reshape2DTo2D(x *mat64.Dense, r, c int) *mat64.Dense {
	_, sc := x.Dims()
	o := mat64.NewDense(r, c, nil)

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			o.Set(i, j, x.At(i/c, (i*c+j)%sc))
		}
	}

	return o
}

func Im2col(x []*mat64.Dense, p, s, kd, kr, kc int) *mat64.Dense {
	dd := len(x)
	_, dc := x[0].Dims()
	dnr := kd * kr * kc
	pl := sizeAfter(dc, kc, p, s)
	dnc := dd * pl

	o := mat64.NewDense(dnr, dnc, nil)

	for i := 0; i < dnr; i++ {
		for j := 0; j < dnc; j++ {
			v := x[i/(dnr/dd)].At(i/kc%dd+(j/pl)*s, i%kc+(j%pl)*s)
			o.Set(i, j, v)
		}
	}

	return o
}

func Col2im(x *mat64.Dense, d, r, c int) []*mat64.Dense {
	_, sc := x.Dims()
	o := make([]*mat64.Dense, d)

	for i := 0; i < d; i++ {
		o[i] = mat64.NewDense(r, c, nil)
		for j := 0; j < r; j++ {
			for k := 0; k < c; k++ {
				o[i].Set(j, k, x.At(i, (j*c+k)%sc))
			}
		}
	}

	return o
}

func ReshapeKernel(x [][]*mat64.Dense) *mat64.Dense {
	n := len(x)
	d := len(x[0])
	r, c := x[0][0].Dims()
	nr := n
	nc := d * r * c

	o := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			v := x[i][j/(r*c)].At(j/c%r, j%c)
			o.Set(i, j, v)
		}
	}

	return o
}

func Convolve(x, k [][]*mat64.Dense, p, s int) [][]*mat64.Dense {
	kn := len(k)
	kd := len(k[0])
	kr, kc := k[0][0].Dims()
	xn := len(x)
	dr, dc := x[0][0].Dims()

	x_new := make([]*mat64.Dense, xn)
	k_new := ReshapeKernel(k)
	result := make([][]*mat64.Dense, xn)

	pr := sizeAfter(dr, kr, p, s)
	pc := sizeAfter(dc, kc, p, s)

	for i := 0; i < xn; i++ {
		x_new[i] = Im2col(x[i], p, s, kd, kr, kc)
	}

	for i := 0; i < xn; i++ {
		r := &mat64.Dense{}
		r.Mul(k_new, x_new[i])
		result[i] = Col2im(r, kn, pr, pc)
	}

	return result
}

func MaxPool(x *mat64.Dense, fr, fc int) (*mat64.Dense, *mat64.Dense) {
	r, c := x.Dims()
	frc := fr * fc
	nr := sizeAfter(r, fr, 0, fr)
	nc := sizeAfter(c, fc, 0, fc)
	o := mat64.NewDense(nr, nc, nil)
	sw := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			m := 0.0
			mi := 0

			for k := 0; k < frc; k++ {
				v := x.At(i*fr+k/fr, j*fc+k%fc)

				if m < v {
					m = v
					mi = k
				}
			}

			o.Set(i, j, m)
			sw.Set(i, j, float64(mi))
		}
	}

	return o, sw
}
<commit_msg>Adding area struct<commit_after>package gocr

import (
	"math"

	"github.com/gonum/matrix/mat64"
)

type Coordinate struct {
	row int
	col int
}

func NewCoordinate(r, c int) *Coordinate {
	return &Coordinate{
		row: r,
		col: c,
	}
}

func (c *Coordinate) N() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col,
	}
}

func (c *Coordinate) E() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col + 1,
	}
}

func (c *Coordinate) S() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col,
	}
}

func (c *Coordinate) W() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col - 1,
	}
}

func (c *Coordinate) NE() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SE() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SW() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) NW() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) IsInside(a *Area) bool {
	return c.row >= a.topLeft.row && c.col >= a.topLeft.col && c.row <= a.bottomRight.row && c.col <= a.bottomRight.col
}

type Area struct {
	topLeft     *Coordinate
	bottomRight *Coordinate
}

func NewArea(coor1, coor2 *Coordinate) *Area {
	a := &Area{}

	if coor1.row > coor2.row {
		a.topLeft.row = coor2.row
		a.bottomRight.row = coor1.row
	} else {
		a.topLeft.row = coor1.row
		a.bottomRight.row = coor2.row
	}

	if coor1.col > coor2.col {
		a.bottomRight.col = coor1.col
		a.topLeft.col = coor2.col
	} else {
		a.bottomRight.col = coor2.col
		a.topLeft.col = coor1.col
	}

	return a
}

func (a *Area) Expand(c *Coordinate) {
	if !c.IsInside(a) {
		if c.row > a.bottomRight.row {
			a.bottomRight.row = c.row
		} else {
			a.topLeft.row = c.row
		}

		if c.col > a.bottomRight.col {
			a.bottomRight.col = c.col
		} else {
			a.topLeft.col = c.col
		}
	}
}

type ImageMatrix [][]uint8

type ImageVector []uint8

func NewImageMatrix(r, c int) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
	}

	return imageArray
}

func NewImageMatrixWithDefaultValue(r, c int, v uint8) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
		for j := 0; j < c; j++ {
			imageArray[i][j] = v
		}
	}

	return imageArray
}

func (i ImageMatrix) Dims() (int, int) {
	return len(i), len(i[0])
}

func (i ImageMatrix) At(r, c int) uint8 {
	return i[r][c]
}

func (i ImageMatrix) Set(r, c int, value uint8) {
	i[r][c] = value
}

func (i ImageMatrix) Slice(sr, er, sc, ec int) ImageMatrix {
	slice := NewImageMatrix(er-sr, ec-sc)

	for r := sr; r < er; r++ {
		for c := sc; c < ec; c++ {
			slice[r-sr][c-sc] = i[r][c]
		}
	}

	return slice
}

func (i ImageMatrix) NNInterpolation(tr, tc int) ImageMatrix {
	r, c := i.Dims()
	rRatio := float64(r) / float64(tr)
	cRatio := float64(c) / float64(tc)
	output := NewImageMatrix(tr, tc)

	for r := 0; r < tr; r++ {
		for c := 0; c < tc; c++ {
			pr := int(math.Floor(float64(r) * rRatio))
			pc := int(math.Floor(float64(c) * cRatio))

			output.Set(r, c, i.At(pr, pc))
		}
	}

	return output
}

func (i ImageMatrix) Pad(top, bottom, left, right int, value uint8) ImageMatrix {
	sr, sc := i.Dims()
	nr := sr + top + bottom
	nc := sc + left + right
	output := NewImageMatrixWithDefaultValue(nr, nc, value)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			output[r+top][c+left] = i[r][c]
		}
	}

	return output
}

func (i ImageMatrix) Row(r int) ImageVector {
	return i[r]
}

func (i ImageMatrix) Col(c int) ImageVector {
	v := NewImageVector(len(i))

	for j := 0; j < len(i); j++ {
		v[j] = i[j][c]
	}

	return v
}

type ImageMatrixs []ImageMatrix

func (is ImageMatrixs) Average() ImageMatrix {
	l := len(is)
	sr, sc := is[0].Dims()
	output := NewImageMatrix(sr, sc)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			sum := 0
			for i := 0; i < l; i++ {
				sum += int(is[i][r][c])
			}

			output[r][c] = uint8(sum / l)
		}
	}

	return output
}

func NewImageVector(l int) ImageVector {
	return make([]uint8, l)
}

func (v ImageVector) Sum() uint64 {
	var sum uint64 = 0

	for i := 0; i < len(v); i++ {
		sum += uint64(v[i])
	}

	return sum
}

// ========================= Convolution =========================

type fn func(int, bool) string

// Calculate size after forward
// ds: Data Size
// ks: Kernel / Filter size
// p: Padding
// s: Stride
func sizeAfter(ds, ks, p, s int) int {
	return ((ds - ks + 2*p) / s) + 1
}

func Sigmoid(x float64, deriv bool) float64 {
	if deriv {
		return x * (1 - x)
	}

	return 1 / (1 + math.Exp(-x))
}

func Relu(x float64, deriv bool) float64 {
	if deriv {
		if x > 0 {
			return 1
		} else {
			return 0
		}
	} else {
		if x > 0 {
			return x
		} else {
			return 0
		}
	}
}

func LeakyRelu(x float64, deriv bool) float64 {
	a := 0.001

	if deriv {
		if x > 0 {
			return 1
		} else {
			return a
		}
	} else {
		if x > 0 {
			return x
		} else {
			return a * x
		}
	}
}

func Reshape2DTo2D(x *mat64.Dense, r, c int) *mat64.Dense {
	_, sc := x.Dims()
	o := mat64.NewDense(r, c, nil)

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			o.Set(i, j, x.At(i/c, (i*c+j)%sc))
		}
	}

	return o
}

func Im2col(x []*mat64.Dense, p, s, kd, kr, kc int) *mat64.Dense {
	dd := len(x)
	_, dc := x[0].Dims()
	dnr := kd * kr * kc
	pl := sizeAfter(dc, kc, p, s)
	dnc := dd * pl

	o := mat64.NewDense(dnr, dnc, nil)

	for i := 0; i < dnr; i++ {
		for j := 0; j < dnc; j++ {
			v := x[i/(dnr/dd)].At(i/kc%dd+(j/pl)*s, i%kc+(j%pl)*s)
			o.Set(i, j, v)
		}
	}

	return o
}

func Col2im(x *mat64.Dense, d, r, c int) []*mat64.Dense {
	_, sc := x.Dims()
	o := make([]*mat64.Dense, d)

	for i := 0; i < d; i++ {
		o[i] = mat64.NewDense(r, c, nil)
		for j := 0; j < r; j++ {
			for k := 0; k < c; k++ {
				o[i].Set(j, k, x.At(i, (j*c+k)%sc))
			}
		}
	}

	return o
}

func ReshapeKernel(x [][]*mat64.Dense) *mat64.Dense {
	n := len(x)
	d := len(x[0])
	r, c := x[0][0].Dims()
	nr := n
	nc := d * r * c

	o := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			v := x[i][j/(r*c)].At(j/c%r, j%c)
			o.Set(i, j, v)
		}
	}

	return o
}

func Convolve(x, k [][]*mat64.Dense, p, s int) [][]*mat64.Dense {
	kn := len(k)
	kd := len(k[0])
	kr, kc := k[0][0].Dims()
	xn := len(x)
	dr, dc := x[0][0].Dims()

	x_new := make([]*mat64.Dense, xn)
	k_new := ReshapeKernel(k)
	result := make([][]*mat64.Dense, xn)

	pr := sizeAfter(dr, kr, p, s)
	pc := sizeAfter(dc, kc, p, s)

	for i := 0; i < xn; i++ {
		x_new[i] = Im2col(x[i], p, s, kd, kr, kc)
	}

	for i := 0; i < xn; i++ {
		r := &mat64.Dense{}
		r.Mul(k_new, x_new[i])
		result[i] = Col2im(r, kn, pr, pc)
	}

	return result
}

func MaxPool(x *mat64.Dense, fr, fc int) (*mat64.Dense, *mat64.Dense) {
	r, c := x.Dims()
	frc := fr * fc
	nr := sizeAfter(r, fr, 0, fr)
	nc := sizeAfter(c, fc, 0, fc)
	o := mat64.NewDense(nr, nc, nil)
	sw := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			m := 0.0
			mi := 0

			for k := 0; k < frc; k++ {
				v := x.At(i*fr+k/fr, j*fc+k%fc)

				if m < v {
					m = v
					mi = k
				}
			}

			o.Set(i, j, m)
			sw.Set(i, j, float64(mi))
		}
	}

	return o, sw
}
<|endoftext|>


<commit_before>package models

import (
	"errors"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// Init creates a connection to the database
func Init(host, db string) error {
	conn = &connection{}
	return conn.connect(host, db)
}

// Modeller is an interface for use with the ORM, describing a model.
type Modeller interface {
	BID() bson.ObjectId
	C() string
}

// Persist creates a copy of the model and persists it in the DB.
func Persist(m Modeller) error {
	c := conn.collection(m.C())
	if err := c.Insert(m); err != nil {
		return err
	}

	return nil
}

// Update updates a Modeller interface with the provided values in persistent storage.
func Update(m Modeller, values bson.M) error {
	if err := updateValues(m, values); err != nil {
		return err
	}

	setValues(m, values)

	return nil
}

// Remove removes a model from the MongoDB.
func Remove(m Modeller) error {
	c := conn.collection(m.C())

	return c.RemoveId(m.BID())
}

// RemoveAll removes all models matching which match the values query
func RemoveAll(collection string, values bson.M) error {
	c := conn.collection(collection)
	_, err := c.RemoveAll(values)
	return err
}

// RestoreByID restores a model using the specified bson ObjectId.
func RestoreByID(m Modeller, id bson.ObjectId) error {
	return Restore(m, bson.M{"_id": id})
}

// Restore restores a model using specified values as a search key
func Restore(m Modeller, values bson.M) error {
	c := conn.collection(m.C())

	err := c.Find(values).One(m)
	if err != nil {
		return err
	}

	if empty(m) {
		return errors.New("Could not find that model")
	}

	return nil
}

// Fetch retrieves all models matching a set of values in a collections
func Fetch(collection string, values bson.M) (*mgo.Iter, error) {
	c := conn.collection(collection)

	iter := c.Find(values).Iter()
	return iter, nil
}
<commit_msg>orm: add sort field to Fetch function<commit_after>package models

import (
	"errors"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// Init creates a connection to the database
func Init(host, db string) error {
	conn = &connection{}
	return conn.connect(host, db)
}

// Modeller is an interface for use with the ORM, describing a model.
type Modeller interface {
	BID() bson.ObjectId
	C() string
}

// Persist creates a copy of the model and persists it in the DB.
func Persist(m Modeller) error {
	c := conn.collection(m.C())
	if err := c.Insert(m); err != nil {
		return err
	}

	return nil
}

// Update updates a Modeller interface with the provided values in persistent storage.
func Update(m Modeller, values bson.M) error {
	if err := updateValues(m, values); err != nil {
		return err
	}

	setValues(m, values)

	return nil
}

// Remove removes a model from the MongoDB.
func Remove(m Modeller) error {
	c := conn.collection(m.C())

	return c.RemoveId(m.BID())
}

// RemoveAll removes all models matching which match the values query
func RemoveAll(collection string, values bson.M) error {
	c := conn.collection(collection)
	_, err := c.RemoveAll(values)
	return err
}

// RestoreByID restores a model using the specified bson ObjectId.
func RestoreByID(m Modeller, id bson.ObjectId) error {
	return Restore(m, bson.M{"_id": id})
}

// Restore restores a model using specified values as a search key
func Restore(m Modeller, values bson.M) error {
	c := conn.collection(m.C())

	err := c.Find(values).One(m)
	if err != nil {
		return err
	}

	if empty(m) {
		return errors.New("Could not find that model")
	}

	return nil
}

// Fetch retrieves all models matching a set of values in a collections
func Fetch(collection string, values bson.M, sort string) (*mgo.Iter, error) {
	c := conn.collection(collection)

	iter := c.Find(values).Sort(sort).Iter()
	return iter, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/Toorop/govh"
	"github.com/toqueteos/webbrowser"
	"github.com/wsxiaoys/terminal"
	//"github.com/wsxiaoys/terminal/color"
	"bufio"
	//"encoding/json"
	"os"
	"runtime"
)

const (
	OVH_APP_KEY    = "SECRET"
	OVH_APP_SECRET = "SECRET"
	NL             = "\r\n"
)

var (
	ck  string // consumer key
	cmd Cmd
)

func init() {
	flag.StringVar(&ck, "ck", "", "Consumer Key")
	//flag.StringVar(&outputFormat, "of", "JSON", "Output format")
	flag.Parse()

	if len(flag.Args()) > 0 {
		cmd = Cmd{
			Domain: flag.Arg(0),
			Action: flag.Arg(1),
			Args:   flag.Args(),
		}
	}

	// WYAUsR31Z3dT9Y5f0arTHeZwpFRdcnz2
	ck = os.Getenv("OVH_CONSUMER_KEY")

	// if No ConsumerKey, request one
	if len(ck) == 0 {
		var r []byte

		if runtime.GOOS == "windows" {
			fmt.Println(NL, "No consumer key found in environnement vars !", NL)
		} else {
			terminal.Stdout.Clear().Move(0, 0).Color("r").
				Print("No consumer key found in environnement vars !").Nl().Nl().Reset()
		}
		for {
			fmt.Print("Have you a valid Consumer Key for that app ? (y/n) : ")

			r, _, _ = bufio.NewReader(os.Stdin).ReadLine()
			if r[0] == 110 || r[0] == 121 {
				break
			}
		}
		// Yes
		if r[0] == 121 {
			fmt.Println("\r\nRun the following command :", NL)
			if runtime.GOOS == "windows" {
				fmt.Println("SET OVH_CONSUMER_KEY=your_consumer_key", NL)
			} else {
				fmt.Println("export OVH_CONSUMER_KEY=your_consumer_key", NL)
			}
			fmt.Println("and restart ovh CLI application.\r\n")
			os.Exit(0)
		}

		ck, link, err := govh.AuthGetConsumerKey(OVH_APP_KEY)
		if err != nil {
			panic(err)
		}
		fmt.Print("\r\nYour consumer key is : ")
		if runtime.GOOS != "windows" {
			terminal.Stdout.Color("g").Print(ck).Nl().Reset().Nl()
		} else {
			fmt.Print(ck)
		}

		fmt.Println("Now you need to validate it :")
		if runtime.GOOS != "windows" {
			fmt.Printf("\t- If you have a browser available on this machine it will open to the validation page.\n\t- If not copy and paste the link below in a browser to validate your key :\r\n\r\n%s\r\n", link)
			webbrowser.Open(link)
		} else {
			fmt.Printf("To do it just copy and paste the link below in a browser and follow instructions on OVH website :\r\n\r\n%s\r\n", link)
		}

		fmt.Println("\r\nWhen it will be done run the following command : \r\n")
		if runtime.GOOS == "windows" {
			fmt.Printf("SET OVH_CONSUMER_KEY=%s\r\n", ck)
		} else {
			fmt.Printf("export OVH_CONSUMER_KEY=%s\r\n", ck)
		}

		fmt.Println("and restart ovh CLI application.\r\n")
		os.Exit(0)
	}
}

// Main
func main() {
	var resp string
	var err error

	switch cmd.Domain {
	case "ip":
		resp, err = ipHandler(&cmd)
		break
	case "help":
		resp = "See : https://github.com/Toorop/govh"
		break
	default:
		dieError("This section '", cmd.Domain, "' is not valid or not implemented yet !")
	}
	if err != nil {
		dieError(err, resp)
	}
	dieOk(resp)

}
<commit_msg>add TAB const<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/Toorop/govh"
	"github.com/toqueteos/webbrowser"
	"github.com/wsxiaoys/terminal"
	//"github.com/wsxiaoys/terminal/color"
	"bufio"
	//"encoding/json"
	"os"
	"runtime"
)

const (
	OVH_APP_KEY    = "SECRET"
	OVH_APP_SECRET = "SECRET"
	NL             = "\r\n"
	TAB            = "\t"
)

var (
	ck  string // consumer key
	cmd Cmd
)

func init() {
	flag.StringVar(&ck, "ck", "", "Consumer Key")
	flag.Parse()

	if len(flag.Args()) > 0 {
		cmd = Cmd{
			Domain: flag.Arg(0),
			Action: flag.Arg(1),
			Args:   flag.Args(),
		}
	}

	// WYAUsR31Z3dT9Y5f0arTHeZwpFRdcnz2
	ck = os.Getenv("OVH_CONSUMER_KEY")

	// if No ConsumerKey, request one
	if len(ck) == 0 {
		var r []byte

		if runtime.GOOS == "windows" {
			fmt.Println(NL, "No consumer key found in environnement vars !", NL)
		} else {
			terminal.Stdout.Clear().Move(0, 0).Color("r").
				Print("No consumer key found in environnement vars !").Nl().Nl().Reset()
		}
		for {
			fmt.Print("Have you a valid Consumer Key for that app ? (y/n) : ")

			r, _, _ = bufio.NewReader(os.Stdin).ReadLine()
			if r[0] == 110 || r[0] == 121 {
				break
			}
		}
		// Yes
		if r[0] == 121 {
			fmt.Println("\r\nRun the following command :", NL)
			if runtime.GOOS == "windows" {
				fmt.Println("SET OVH_CONSUMER_KEY=your_consumer_key", NL)
			} else {
				fmt.Println("export OVH_CONSUMER_KEY=your_consumer_key", NL)
			}
			fmt.Println("and restart ovh CLI application.\r\n")
			os.Exit(0)
		}

		ck, link, err := govh.AuthGetConsumerKey(OVH_APP_KEY)
		if err != nil {
			panic(err)
		}
		fmt.Print("\r\nYour consumer key is : ")
		if runtime.GOOS != "windows" {
			terminal.Stdout.Color("g").Print(ck).Nl().Reset().Nl()
		} else {
			fmt.Print(ck)
		}

		fmt.Println("Now you need to validate it :")
		if runtime.GOOS != "windows" {
			fmt.Printf("\t- If you have a browser available on this machine it will open to the validation page.\n\t- If not copy and paste the link below in a browser to validate your key :\r\n\r\n%s\r\n", link)
			webbrowser.Open(link)
		} else {
			fmt.Printf("To do it just copy and paste the link below in a browser and follow instructions on OVH website :\r\n\r\n%s\r\n", link)
		}

		fmt.Println("\r\nWhen it will be done run the following command : \r\n")
		if runtime.GOOS == "windows" {
			fmt.Printf("SET OVH_CONSUMER_KEY=%s\r\n", ck)
		} else {
			fmt.Printf("export OVH_CONSUMER_KEY=%s\r\n", ck)
		}

		fmt.Println("and restart ovh CLI application.\r\n")
		os.Exit(0)
	}
}

// Main
func main() {
	var resp string
	var err error

	switch cmd.Domain {
	case "ip":
		resp, err = ipHandler(&cmd)
		break
	case "help":
		resp = "See : https://github.com/Toorop/govh"
		break
	default:
		dieError("This section '", cmd.Domain, "' is not valid or not implemented yet !")
	}
	if err != nil {
		dieError(err, resp)
	}
	dieOk(resp)

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/build"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var (
	ctx = build.Default
)

func init() {
	ctx.UseAllFiles = true
}

func collectAllDeps(wd string, downloadFunc func(importPath, dir string) error, initPkgs ...*build.Package) ([]*build.Package, error) {
	pkgCache := make(map[string]*build.Package)
	var deps []*build.Package
	for _, pkg := range initPkgs {
		pkgCache[pkg.ImportPath] = pkg
		deps = append(deps, pkg)
	}
	gopath := os.Getenv("GOPATH")
	rel, err := filepath.Rel(filepath.Join(gopath, "src"), wd)
	if err != nil {
		return nil, err
	}
	vdImportPrefix := filepath.Join(rel, "vendor")
	for {
		var newDeps []*build.Package
		for _, pkg := range deps {
			if pkg.Goroot {
				continue
			}
			for _, imp := range pkg.Imports {
				if imp == "C" {
					continue
				}
				ipkg, err := ctx.Import(imp, wd, build.AllowVendor)
				if ipkg.Goroot {
					continue
				}
				// if package not found or it is package for current GOPATH, we should try to download it
				if err != nil || !strings.HasPrefix(ipkg.ImportPath, rel) {
					if downloadFunc == nil {
						log.Printf("WARN: unsatisfied dep: %s for %s\n", imp, pkg.ImportPath)
						continue
					}
					if err := downloadFunc(imp, filepath.Join(wd, vendorDir)); err != nil {
						return nil, err
					}
					dlPkg, err := ctx.Import(imp, wd, build.AllowVendor)
					if err != nil {
						return nil, err
					}
					if !strings.HasPrefix(dlPkg.ImportPath, vdImportPrefix) {
						return nil, fmt.Errorf("%s was not vendored properly", imp)
					}
				}
				if _, ok := pkgCache[ipkg.ImportPath]; ok {
					continue
				}
				newDeps = append(newDeps, ipkg)
			}
			pkgCache[pkg.ImportPath] = pkg
		}
		if len(newDeps) == 0 {
			break
		}
		deps = newDeps
	}
	var pkgs []*build.Package
	for _, pkg := range pkgCache {
		pkgs = append(pkgs, pkg)
	}
	return pkgs, nil
}

func collectPkgs(dir string) ([]*build.Package, error) {
	var pkgs []*build.Package
	err := filepath.Walk(dir, func(path string, i os.FileInfo, err error) error {
		if i == nil {
			return err
		}
		if !i.IsDir() {
			return nil
		}
		// skip vendoring directory itself
		if path == filepath.Join(dir, vendorDir) {
			return filepath.SkipDir
		}
		pkg, err := ctx.ImportDir(path, build.ImportMode(0))
		if err != nil {
			// not a package
			if _, ok := err.(*build.NoGoError); ok {
				return nil
			}
			return err
		}
		pkgs = append(pkgs, pkg)
		return nil
	})
	return pkgs, err
}
<commit_msg>Remove usage of removed AllowVendor<commit_after>package main

import (
	"fmt"
	"go/build"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var (
	ctx = build.Default
)

func init() {
	ctx.UseAllFiles = true
}

func collectAllDeps(wd string, downloadFunc func(importPath, dir string) error, initPkgs ...*build.Package) ([]*build.Package, error) {
	pkgCache := make(map[string]*build.Package)
	var deps []*build.Package
	for _, pkg := range initPkgs {
		pkgCache[pkg.ImportPath] = pkg
		deps = append(deps, pkg)
	}
	gopath := os.Getenv("GOPATH")
	rel, err := filepath.Rel(filepath.Join(gopath, "src"), wd)
	if err != nil {
		return nil, err
	}
	vdImportPrefix := filepath.Join(rel, "vendor")
	for {
		var newDeps []*build.Package
		for _, pkg := range deps {
			if pkg.Goroot {
				continue
			}
			for _, imp := range pkg.Imports {
				if imp == "C" {
					continue
				}
				ipkg, err := ctx.Import(imp, wd, 0)
				if ipkg.Goroot {
					continue
				}
				// if package not found or it is package for current GOPATH, we should try to download it
				if err != nil || !strings.HasPrefix(ipkg.ImportPath, rel) {
					if downloadFunc == nil {
						log.Printf("WARN: unsatisfied dep: %s for %s\n", imp, pkg.ImportPath)
						continue
					}
					if err := downloadFunc(imp, filepath.Join(wd, vendorDir)); err != nil {
						return nil, err
					}
					dlPkg, err := ctx.Import(imp, wd, 0)
					if err != nil {
						return nil, err
					}
					if !strings.HasPrefix(dlPkg.ImportPath, vdImportPrefix) {
						return nil, fmt.Errorf("%s was not vendored properly", imp)
					}
				}
				if _, ok := pkgCache[ipkg.ImportPath]; ok {
					continue
				}
				newDeps = append(newDeps, ipkg)
			}
			pkgCache[pkg.ImportPath] = pkg
		}
		if len(newDeps) == 0 {
			break
		}
		deps = newDeps
	}
	var pkgs []*build.Package
	for _, pkg := range pkgCache {
		pkgs = append(pkgs, pkg)
	}
	return pkgs, nil
}

func collectPkgs(dir string) ([]*build.Package, error) {
	var pkgs []*build.Package
	err := filepath.Walk(dir, func(path string, i os.FileInfo, err error) error {
		if i == nil {
			return err
		}
		if !i.IsDir() {
			return nil
		}
		// skip vendoring directory itself
		if path == filepath.Join(dir, vendorDir) {
			return filepath.SkipDir
		}
		pkg, err := ctx.ImportDir(path, build.ImportMode(0))
		if err != nil {
			// not a package
			if _, ok := err.(*build.NoGoError); ok {
				return nil
			}
			return err
		}
		pkgs = append(pkgs, pkg)
		return nil
	})
	return pkgs, err
}
<|endoftext|>