<commit_before>package docker

import (
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker/utils"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

const DEFAULTTAG = "latest"

type TagStore struct {
	path         string
	graph        *Graph
	Repositories map[string]Repository
}

type Repository map[string]string

func NewTagStore(path string, graph *Graph) (*TagStore, error) {
	abspath, err := filepath.Abs(path)
	if err != nil {
		return nil, err
	}
	store := &TagStore{
		path:         abspath,
		graph:        graph,
		Repositories: make(map[string]Repository),
	}
	// Load the json file if it exists, otherwise create it.
	if err := store.Reload(); os.IsNotExist(err) {
		if err := store.Save(); err != nil {
			return nil, err
		}
	} else if err != nil {
		return nil, err
	}
	return store, nil
}

func (store *TagStore) Save() error {
	// Store the json ball
	jsonData, err := json.Marshal(store)
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(store.path, jsonData, 0600); err != nil {
		return err
	}
	return nil
}

func (store *TagStore) Reload() error {
	jsonData, err := ioutil.ReadFile(store.path)
	if err != nil {
		return err
	}
	if err := json.Unmarshal(jsonData, store); err != nil {
		return err
	}
	return nil
}

func (store *TagStore) LookupImage(name string) (*Image, error) {
	img, err := store.graph.Get(name)
	if err != nil {
		// FIXME: standardize on returning nil when the image doesn't exist, and err for everything else
		// (so we can pass all errors here)
		repos, tag := utils.ParseRepositoryTag(name)
		if tag == "" {
			tag = DEFAULTTAG
		}
		if i, err := store.GetImage(repos, tag); err != nil {
			return nil, err
		} else if i == nil {
			return nil, fmt.Errorf("Image does not exist: %s", name)
		} else {
			img = i
		}
	}
	return img, nil
}

// Return a reverse-lookup table of all the names which refer to each image
// Eg. {"43b5f19b10584": {"base:latest", "base:v1"}}
func (store *TagStore) ByID() map[string][]string {
	byID := make(map[string][]string)
	for repoName, repository := range store.Repositories {
		for tag, id := range repository {
			name := repoName + ":" + tag
			if _, exists := byID[id]; !exists {
				byID[id] = []string{name}
			} else {
				byID[id] = append(byID[id], name)
				sort.Strings(byID[id])
			}
		}
	}
	return byID
}

func (store *TagStore) ImageName(id string) string {
	if names, exists := store.ByID()[id]; exists && len(names) > 0 {
		return names[0]
	}
	return utils.TruncateID(id)
}

func (store *TagStore) DeleteAll(id string) error {
	names, exists := store.ByID()[id]
	if !exists || len(names) == 0 {
		return nil
	}
	for _, name := range names {
		if strings.Contains(name, ":") {
			nameParts := strings.Split(name, ":")
			if _, err := store.Delete(nameParts[0], nameParts[1]); err != nil {
				return err
			}
		} else {
			if _, err := store.Delete(name, ""); err != nil {
				return err
			}
		}
	}
	return nil
}

func (store *TagStore) Delete(repoName, tag string) (bool, error) {
	deleted := false
	if err := store.Reload(); err != nil {
		return false, err
	}
	if r, exists := store.Repositories[repoName]; exists {
		if tag != "" {
			if _, exists2 := r[tag]; exists2 {
				delete(r, tag)
				if len(r) == 0 {
					delete(store.Repositories, repoName)
				}
				deleted = true
			} else {
				return false, fmt.Errorf("No such tag: %s:%s", repoName, tag)
			}
		} else {
			delete(store.Repositories, repoName)
			deleted = true
		}
	} else {
		fmt.Errorf("No such repository: %s", repoName)
	}
	return deleted, store.Save()
}

func (store *TagStore) Set(repoName, tag, imageName string, force bool) error {
	img, err := store.LookupImage(imageName)
	if err != nil {
		return err
	}
	if tag == "" {
		tag = DEFAULTTAG
	}
	if err := validateRepoName(repoName); err != nil {
		return err
	}
	if err := validateTagName(tag); err != nil {
		return err
	}
	if err := store.Reload(); err != nil {
		return err
	}
	var repo Repository
	if r, exists := store.Repositories[repoName]; exists {
		repo = r
	} else {
		repo = make(map[string]string)
		if old, exists := store.Repositories[repoName]; exists && !force {
			return fmt.Errorf("Conflict: Tag %s:%s is already set to %s", repoName, tag, old)
		}
		store.Repositories[repoName] = repo
	}
	repo[tag] = img.ID
	return store.Save()
}

func (store *TagStore) Get(repoName string) (Repository, error) {
	if err := store.Reload(); err != nil {
		return nil, err
	}
	if r, exists := store.Repositories[repoName]; exists {
		return r, nil
	}
	return nil, nil
}

func (store *TagStore) GetImage(repoName, tagOrID string) (*Image, error) {
	repo, err := store.Get(repoName)
	if err != nil {
		return nil, err
	} else if repo == nil {
		return nil, nil
	}
	if revision, exists := repo[tagOrID]; exists {
		return store.graph.Get(revision)
	}
	// If no matching tag is found, search through images for a matching image id
	for _, revision := range repo {
		if strings.HasPrefix(revision, tagOrID) {
			return store.graph.Get(revision)
		}
	}
	return nil, nil
}

// Validate the name of a repository
func validateRepoName(name string) error {
	if name == "" {
		return fmt.Errorf("Repository name can't be empty")
	}
	return nil
}

// Validate the name of a tag
func validateTagName(name string) error {
	if name == "" {
		return fmt.Errorf("Tag name can't be empty")
	}
	if strings.Contains(name, "/") || strings.Contains(name, ":") {
		return fmt.Errorf("Illegal tag name: %s", name)
	}
	return nil
}
<commit_msg>Search for repo first before image id<commit_after>package docker

import (
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker/utils"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

const DEFAULTTAG = "latest"

type TagStore struct {
	path         string
	graph        *Graph
	Repositories map[string]Repository
}

type Repository map[string]string

func NewTagStore(path string, graph *Graph) (*TagStore, error) {
	abspath, err := filepath.Abs(path)
	if err != nil {
		return nil, err
	}
	store := &TagStore{
		path:         abspath,
		graph:        graph,
		Repositories: make(map[string]Repository),
	}
	// Load the json file if it exists, otherwise create it.
	if err := store.Reload(); os.IsNotExist(err) {
		if err := store.Save(); err != nil {
			return nil, err
		}
	} else if err != nil {
		return nil, err
	}
	return store, nil
}

func (store *TagStore) Save() error {
	// Store the json ball
	jsonData, err := json.Marshal(store)
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(store.path, jsonData, 0600); err != nil {
		return err
	}
	return nil
}

func (store *TagStore) Reload() error {
	jsonData, err := ioutil.ReadFile(store.path)
	if err != nil {
		return err
	}
	if err := json.Unmarshal(jsonData, store); err != nil {
		return err
	}
	return nil
}

func (store *TagStore) LookupImage(name string) (*Image, error) {
	// FIXME: standardize on returning nil when the image doesn't exist, and err for everything else
	// (so we can pass all errors here)
	repos, tag := utils.ParseRepositoryTag(name)
	if tag == "" {
		tag = DEFAULTTAG
	}
	img, err := store.GetImage(repos, tag)
	if err != nil {
		return nil, err
	} else if img == nil {
		if img, err = store.graph.Get(name); err != nil {
			return nil, err
		}
	}
	return img, nil
}

// Return a reverse-lookup table of all the names which refer to each image
// Eg. {"43b5f19b10584": {"base:latest", "base:v1"}}
func (store *TagStore) ByID() map[string][]string {
	byID := make(map[string][]string)
	for repoName, repository := range store.Repositories {
		for tag, id := range repository {
			name := repoName + ":" + tag
			if _, exists := byID[id]; !exists {
				byID[id] = []string{name}
			} else {
				byID[id] = append(byID[id], name)
				sort.Strings(byID[id])
			}
		}
	}
	return byID
}

func (store *TagStore) ImageName(id string) string {
	if names, exists := store.ByID()[id]; exists && len(names) > 0 {
		return names[0]
	}
	return utils.TruncateID(id)
}

func (store *TagStore) DeleteAll(id string) error {
	names, exists := store.ByID()[id]
	if !exists || len(names) == 0 {
		return nil
	}
	for _, name := range names {
		if strings.Contains(name, ":") {
			nameParts := strings.Split(name, ":")
			if _, err := store.Delete(nameParts[0], nameParts[1]); err != nil {
				return err
			}
		} else {
			if _, err := store.Delete(name, ""); err != nil {
				return err
			}
		}
	}
	return nil
}

func (store *TagStore) Delete(repoName, tag string) (bool, error) {
	deleted := false
	if err := store.Reload(); err != nil {
		return false, err
	}
	if r, exists := store.Repositories[repoName]; exists {
		if tag != "" {
			if _, exists2 := r[tag]; exists2 {
				delete(r, tag)
				if len(r) == 0 {
					delete(store.Repositories, repoName)
				}
				deleted = true
			} else {
				return false, fmt.Errorf("No such tag: %s:%s", repoName, tag)
			}
		} else {
			delete(store.Repositories, repoName)
			deleted = true
		}
	} else {
		fmt.Errorf("No such repository: %s", repoName)
	}
	return deleted, store.Save()
}

func (store *TagStore) Set(repoName, tag, imageName string, force bool) error {
	img, err := store.LookupImage(imageName)
	if err != nil {
		return err
	}
	if tag == "" {
		tag = DEFAULTTAG
	}
	if err := validateRepoName(repoName); err != nil {
		return err
	}
	if err := validateTagName(tag); err != nil {
		return err
	}
	if err := store.Reload(); err != nil {
		return err
	}
	var repo Repository
	if r, exists := store.Repositories[repoName]; exists {
		repo = r
	} else {
		repo = make(map[string]string)
		if old, exists := store.Repositories[repoName]; exists && !force {
			return fmt.Errorf("Conflict: Tag %s:%s is already set to %s", repoName, tag, old)
		}
		store.Repositories[repoName] = repo
	}
	repo[tag] = img.ID
	return store.Save()
}

func (store *TagStore) Get(repoName string) (Repository, error) {
	if err := store.Reload(); err != nil {
		return nil, err
	}
	if r, exists := store.Repositories[repoName]; exists {
		return r, nil
	}
	return nil, nil
}

func (store *TagStore) GetImage(repoName, tagOrID string) (*Image, error) {
	repo, err := store.Get(repoName)
	if err != nil {
		return nil, err
	} else if repo == nil {
		return nil, nil
	}
	if revision, exists := repo[tagOrID]; exists {
		return store.graph.Get(revision)
	}
	// If no matching tag is found, search through images for a matching image id
	for _, revision := range repo {
		if strings.HasPrefix(revision, tagOrID) {
			return store.graph.Get(revision)
		}
	}
	return nil, nil
}

// Validate the name of a repository
func validateRepoName(name string) error {
	if name == "" {
		return fmt.Errorf("Repository name can't be empty")
	}
	return nil
}

// Validate the name of a tag
func validateTagName(name string) error {
	if name == "" {
		return fmt.Errorf("Tag name can't be empty")
	}
	if strings.Contains(name, "/") || strings.Contains(name, ":") {
		return fmt.Errorf("Illegal tag name: %s", name)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
)

var (
	follow  bool
	lines   int
	source  string
	process string
)

var cmdTail = &Command{
	Run:   runTail,
	Usage: "tail [-a app] [-f] [-n lines] [-s source] [-p process]",
	Short: "show the last part of the app log",
	Long:  `Tail tails log files.`,
}

func init() {
	cmdTail.Flag.StringVar(&flagApp, "a", "", "app")
	cmdTail.Flag.BoolVar(&follow, "f", false, "do not stop when end of file is reached")
	cmdTail.Flag.IntVar(&lines, "n", -1, "number of log lines to request")
	cmdTail.Flag.StringVar(&source, "s", "", "only display logs from the given source")
	cmdTail.Flag.StringVar(&process, "p", "", "only display logs from the given process")
}

func runTail(cmd *Command, args []string) {
	data := make(url.Values)
	data.Add("logplex", "true")

	if follow {
		data.Add("tail", "1")
	}

	if lines > 0 {
		data.Add("num", strconv.Itoa(lines))
	}

	if source != "" {
		data.Add("source", source)
	}

	if process != "" {
		data.Add("ps", process)
	}

	surl := new(logURL)
	err := APIReq(surl, "GET", "/apps/"+mustApp()+"/logs", data)
	if err != nil {
		log.Fatal(err)
	}
	resp, err := http.Get(surl.String())
	if err != nil {
		log.Fatal(err)
	}
	must(checkResp(resp))
	if _, err = io.Copy(os.Stdout, resp.Body); err != nil {
		log.Fatal(err)
	}
	resp.Body.Close()
}

type logURL struct {
	bytes.Buffer
}

func (logURL) Accept() string {
	return "application/json"
}
<commit_msg>fixup help text<commit_after>package main

import (
	"bytes"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
)

var (
	follow  bool
	lines   int
	source  string
	process string
)

var cmdTail = &Command{
	Run:   runTail,
	Usage: "tail [-a app] [-f] [-n lines] [-s source] [-p process]",
	Short: "show the last part of the app log",
	Long:  `Tail prints recent application logs.`,
}

func init() {
	cmdTail.Flag.StringVar(&flagApp, "a", "", "app")
	cmdTail.Flag.BoolVar(&follow, "f", false, "do not stop when end of file is reached")
	cmdTail.Flag.IntVar(&lines, "n", -1, "number of log lines to request")
	cmdTail.Flag.StringVar(&source, "s", "", "only display logs from the given source")
	cmdTail.Flag.StringVar(&process, "p", "", "only display logs from the given process")
}

func runTail(cmd *Command, args []string) {
	data := make(url.Values)
	data.Add("logplex", "true")

	if follow {
		data.Add("tail", "1")
	}

	if lines > 0 {
		data.Add("num", strconv.Itoa(lines))
	}

	if source != "" {
		data.Add("source", source)
	}

	if process != "" {
		data.Add("ps", process)
	}

	surl := new(logURL)
	err := APIReq(surl, "GET", "/apps/"+mustApp()+"/logs", data)
	if err != nil {
		log.Fatal(err)
	}
	resp, err := http.Get(surl.String())
	if err != nil {
		log.Fatal(err)
	}
	must(checkResp(resp))
	if _, err = io.Copy(os.Stdout, resp.Body); err != nil {
		log.Fatal(err)
	}
	resp.Body.Close()
}

type logURL struct {
	bytes.Buffer
}

func (logURL) Accept() string {
	return "application/json"
}
<|endoftext|>


<commit_before>package chirp

import (
	"bytes"
	. "fmt"
	"go/ast"
	"log"
	R "reflect"
	"strings"
	"sync"
)

type Shower interface {
	Show() string
}

type Hash map[string]T // TODO: Mutex

type Command func(fr *Frame, argv []T) T

type Scope map[string]Loc

type CmdScope map[string]*CmdNode

// CmdNode makes a singly-linked-list of commands
// at different mixin levels, highest level first.
// A non-mixin command has level 0 and only one CmdNode.
type CmdNode struct {
	Fn         Command
	MixinLevel int
	MixinName  string
	Next       *CmdNode
}

// Frame is a local variable frame.
// There is one for the global variables in the Global struct,
// and a new one is created for each proc or yproc invocation
// (but not for every Command; non-proc commands do not make Frames).
type Frame struct {
	Vars Scope // local variables
	Cred Hash  // credentials

	Prev *Frame
	G    *Global

	WriterChan chan<- Either // for yproc & yield
	MixinLevel int
	MixinName  string

	Self  *Obj
	Super *Obj
}

// Global holds the global state of an interpreter,
// mainly the Commands and global variables.
// It also knows if a Mixin is being defined.
// Mixins should be defined by main thread,
// after all overridable procs are defined,
// but before other goroutines start.
type Global struct {
	Cmds CmdScope
	Fr   Frame // global scope

	MixinSerial         int    // Increment before defining Mixin.
	MixinNumberDefining int    // Set nonzero while defining Mixin.
	MixinNameDefining   string // Set nonempty while defining Mixin.
	isSafe              bool   // Set true for safe subinterpreter.
	Logger              *log.Logger
	Verbosity           int    // Log if message level <= verbosity.
	LogName             string // for logging

	Mu sync.Mutex
}

// Clone produces a copy of the receiving interpreter.
func (g *Global) Clone() *Global {
	z := &Global{
		Cmds: make(CmdScope),
		Fr: Frame{
			Vars: make(Scope),
		},
	}

	z.Fr.G = z

	for k, v := range g.Cmds {
		z.Cmds[k] = v
	}

	for k, loc := range g.Fr.Vars {
		z.Fr.SetVar(k, loc.Get())
	}

	return z
}

// StatusCode are the same integers as Tcl/C uses for return, break, and continue.
type StatusCode int

const (
	RETURN = StatusCode(iota + 2)
	BREAK
	CONTINUE
)

// Jump structs are panicked for return, break, and continue.
type Jump struct {
	Status StatusCode
	Result T
}

// Either Bad or Good value.
type Either struct {
	Bad  interface{}
	Good T
}

// Loc is protocol for a variable location.
type Loc interface {
	Has() bool
	Get() T
	Set(T)
}

// Slot stores a variable value.
type Slot struct {
	Elem T
}

// UpSlot forwards a variable to another variable.
type UpSlot struct {
	Fr         *Frame
	RemoteName string
}

var Empty = MkString("")
var InvalidValue = *new(R.Value)

// Create a new interpreter, and return the global frame pointer.
func New1(isSafe bool) *Frame {
	g := &Global{
		Cmds: make(CmdScope),
		Fr: Frame{
			Vars: make(Scope),
		},
		isSafe: isSafe,
	}

	g.Fr.G = g

	// Copy Safes to commands.
	for k, v := range Safes {
		node := CmdNode{Fn: v}
		g.Cmds[k] = &node
	}

	if !isSafe {
		// In unsafe terp, copy Unsafes to commands.
		for k, v := range Unsafes {
			node := CmdNode{Fn: v}
			g.Cmds[k] = &node
		}
	}

	return &g.Fr
}

// New() makes a new full interpreter.
func New() *Frame {
	return New1(false)
}

// NewSafe() makes a new safe interpreter.
func NewSafe() *Frame {
	return New1(true)
}

// NewFrame makes a frame for calling another proc.
func (fr *Frame) NewFrame() *Frame {
	return &Frame{
		Vars: make(Scope), // new local var scope
		Cred: fr.Cred,     // same credentials as caller
		Prev: fr,          // link back to prev frame
		G:    fr.G,        // the Global struct
	}
}

// Initial capital letter for a variable means Global.
func IsGlobal(name string) bool {
	if len(name) == 0 {
		panic("Empty variable name")
	}
	return ast.IsExported(name) // Same criteria, First is Uppercase.
}

// Initial capital letter for a variable means local.
func IsLocal(name string) bool {
	if len(name) == 0 {
		panic("Empty variable name")
	}
	return !ast.IsExported(name)
}

func (p *Slot) Has() bool { return p.Elem != nil }
func (p *Slot) Get() T    { return p.Elem }
func (p *Slot) Set(t T)   { p.Elem = t }

func (fr *Frame) GetVarScope(name string) Scope {
	if len(name) == 0 {
		panic("Empty variable name")
	}

	if name[0] == '_' && fr.Self != nil {
		return fr.Self.Slots
	}

	if IsGlobal(name) {
		return fr.G.Fr.Vars
	}
	return fr.Vars
}

func (fr *Frame) HasVar(name string) bool {
	sc := fr.GetVarScope(name)
	var loc Loc
	var ok bool
	if loc, ok = sc[name]; !ok {
		return false
	}
	return loc.Has()
}

func (fr *Frame) GetVar(name string) T {
	sc := fr.GetVarScope(name)
	var loc Loc
	var ok bool
	if loc, ok = sc[name]; !ok {
		panic(Sprintf("Variable %q does not exist; scope contains %v", name, sc))
	}
	return loc.Get()
}

func (fr *Frame) SetVar(name string, x T) {
	if strings.Contains(name, ",") {
		// Support destructuring list assignment syntax.
		xs := x.List()
		names := strings.Split(name, ",")
		for i, n := range names {
			if len(n) > 0 {
				if i < len(xs) {
					fr.SetVar(n, xs[i])
				} else {
					fr.SetVar(n, Empty) // Missing values become empty.
				}
			}
		}
		return
	}
	sc := fr.GetVarScope(name)
	if sc[name] == nil {
		sc[name] = new(Slot)
	}
	sc[name].Set(x)
}

func (p *UpSlot) Has() bool { return p.Fr.HasVar(p.RemoteName) }
func (p *UpSlot) Get() T    { return p.Fr.GetVar(p.RemoteName) }
func (p *UpSlot) Set(t T)   { p.Fr.SetVar(p.RemoteName, t) }

func (fr *Frame) DefineUpVar(name string, remFr *Frame, remName string) {
	sc := fr.GetVarScope(name)
	sc[name] = &UpSlot{Fr: remFr, RemoteName: remName}
}

func (fr *Frame) FindCommand(name T, callSuper bool) Command {
	// Some day we will not require terpString; for now, it helps debug.
	cmdName, ok := name.(terpString)
	if !ok {
		panic(Sprintf("Restriction: Command must be a string: %#v", name))
	}

	var fn Command
	cmdNode, ok := fr.G.Cmds[cmdName.s]
	if ok {
		if callSuper {
			maxMixinLevel := fr.MixinLevel - 1
			if maxMixinLevel < 0 {
				panic("cannot callSuper from non-mixin")
			}
			for cmdNode != nil && cmdNode.MixinLevel > maxMixinLevel {
				cmdNode = cmdNode.Next
			}
		}
		if cmdNode == nil {
			ok = false
		} else {
			fn = cmdNode.Fn
		}
	}

	// Mixin Local Commands:
	if !ok && fr.MixinLevel > 0 && !IsGlobal(cmdName.s) {
		// Use long name for mixin local fn.
		localCmdName := fr.MixinName + "~" + cmdName.s
		var localNode *CmdNode
		localNode, ok = fr.G.Cmds[localCmdName]
		if ok {
			fn = localNode.Fn // Should be singleton.
		}
	}

	if !ok {
		panic(Sprintf("FindCommand: command not found: %q", cmdName.s))
	}
	return fn
}

// Apply a command with its arguments.
func (fr *Frame) Apply(argv []T) T {
	defer func() {
		if r := recover(); r != nil {
			if re, ok := r.(error); ok {
				r = re.Error() // Convert error to string.
			}
			if rs, ok := r.(string); ok {
				rs = rs + Sprintf("\n\tin Apply\n\t\t%q", argv[0])

				// TODO: Require debug level for the args.
				for _, ae := range argv[1:] {
					as := ae.String()
					if len(as) > 40 {
						as = as[:40] + "..."
					}
					rs = rs + Sprintf(" %q", as)
				}

				if fr.MixinLevel > 0 {
					rs = rs + Sprintf("\n\t\t(frame's MixinLevel=%d)", fr.MixinLevel)
				}
				if len(fr.MixinName) > 0 {
					rs = rs + Sprintf("\n\t\t(frame's MixinName=%q)", fr.MixinName)
				}
				r = rs
			}
			panic(r)
		}
	}()

	head := argv[0]
	fn := fr.FindCommand(head, false) // false: Don't call super.
	z := fn(fr, argv)
	return z
}

func Repr(a interface{}) string { return Sprintf("REPR<<%#v>>", a) }

// Must takes 2 T values, and compares their Show()s.
func Must(a, b T) {
	if a.String() != b.String() {
		panic(Show(a) + " .vs. " + Show(b))
	}
}

// MustST takes a string and a T
func MustST(a string, b T) {
	Must(MkString(a), b)
}

// MustA takes Any 2 values, and compares their Repr()s.
func MustA(a, b interface{}) {
	if Repr(a) != Repr(b) {
		panic(Repr(a) + " .vs. " + Repr(b))
	}
}

// MustSp takes Any 2 values, and compares their Repr()s, without spaces.
func MustNoSp(a, b interface{}) {
	if DropSpaces(Repr(a)) != DropSpaces(Repr(b)) {
		panic(Repr(a) + " .vs. " + Repr(b))
	}
}
func DropSpaces(s string) string {
	z := ""
	for _, c := range s {
		if (c != ' ') {
			z += string(c)
		}
	}
	return z
}

func Show(a T) string {
	if a == nil {
		return "{(T)nil}"
	}
	return Sprintf("{(%T) ## %#v ## %q}", a, a, a.String())
}

func Showv(a []T) string {
	buf := bytes.NewBufferString(Sprintf("Slice of T with %d elements:", len(a)))
	for i, e := range a {
		buf.WriteString(Sprintf("\n    ... [%d] = %s", i, Show(e)))
	}
	return buf.String()
}

// Quick internal logging function that needs no Frame.
func Say(args ...interface{}) {
	prefix := "Say "
	for _, a := range args {
		switch t := a.(type) {
		case Shower:
			log.Println(Sprintf("%s%s", prefix, t.Show()))
		default:
			log.Println(Sprintf("%s%#v", prefix, a))
		}
		prefix += "::: "
	}
}
func Sayf(format string, args ...interface{}) {
	log.Println(Sprintf(format, args...))
}
<commit_msg>gofmt: Parse2Curly, not rest of parse2<commit_after>package chirp

import (
	"bytes"
	. "fmt"
	"go/ast"
	"log"
	R "reflect"
	"strings"
	"sync"
)

type Shower interface {
	Show() string
}

type Hash map[string]T // TODO: Mutex

type Command func(fr *Frame, argv []T) T

type Scope map[string]Loc

type CmdScope map[string]*CmdNode

// CmdNode makes a singly-linked-list of commands
// at different mixin levels, highest level first.
// A non-mixin command has level 0 and only one CmdNode.
type CmdNode struct {
	Fn         Command
	MixinLevel int
	MixinName  string
	Next       *CmdNode
}

// Frame is a local variable frame.
// There is one for the global variables in the Global struct,
// and a new one is created for each proc or yproc invocation
// (but not for every Command; non-proc commands do not make Frames).
type Frame struct {
	Vars Scope // local variables
	Cred Hash  // credentials

	Prev *Frame
	G    *Global

	WriterChan chan<- Either // for yproc & yield
	MixinLevel int
	MixinName  string

	Self  *Obj
	Super *Obj
}

// Global holds the global state of an interpreter,
// mainly the Commands and global variables.
// It also knows if a Mixin is being defined.
// Mixins should be defined by main thread,
// after all overridable procs are defined,
// but before other goroutines start.
type Global struct {
	Cmds CmdScope
	Fr   Frame // global scope

	MixinSerial         int    // Increment before defining Mixin.
	MixinNumberDefining int    // Set nonzero while defining Mixin.
	MixinNameDefining   string // Set nonempty while defining Mixin.
	isSafe              bool   // Set true for safe subinterpreter.
	Logger              *log.Logger
	Verbosity           int    // Log if message level <= verbosity.
	LogName             string // for logging

	Mu sync.Mutex
}

// Clone produces a copy of the receiving interpreter.
func (g *Global) Clone() *Global {
	z := &Global{
		Cmds: make(CmdScope),
		Fr: Frame{
			Vars: make(Scope),
		},
	}

	z.Fr.G = z

	for k, v := range g.Cmds {
		z.Cmds[k] = v
	}

	for k, loc := range g.Fr.Vars {
		z.Fr.SetVar(k, loc.Get())
	}

	return z
}

// StatusCode are the same integers as Tcl/C uses for return, break, and continue.
type StatusCode int

const (
	RETURN = StatusCode(iota + 2)
	BREAK
	CONTINUE
)

// Jump structs are panicked for return, break, and continue.
type Jump struct {
	Status StatusCode
	Result T
}

// Either Bad or Good value.
type Either struct {
	Bad  interface{}
	Good T
}

// Loc is protocol for a variable location.
type Loc interface {
	Has() bool
	Get() T
	Set(T)
}

// Slot stores a variable value.
type Slot struct {
	Elem T
}

// UpSlot forwards a variable to another variable.
type UpSlot struct {
	Fr         *Frame
	RemoteName string
}

var Empty = MkString("")
var InvalidValue = *new(R.Value)

// Create a new interpreter, and return the global frame pointer.
func New1(isSafe bool) *Frame {
	g := &Global{
		Cmds: make(CmdScope),
		Fr: Frame{
			Vars: make(Scope),
		},
		isSafe: isSafe,
	}

	g.Fr.G = g

	// Copy Safes to commands.
	for k, v := range Safes {
		node := CmdNode{Fn: v}
		g.Cmds[k] = &node
	}

	if !isSafe {
		// In unsafe terp, copy Unsafes to commands.
		for k, v := range Unsafes {
			node := CmdNode{Fn: v}
			g.Cmds[k] = &node
		}
	}

	return &g.Fr
}

// New() makes a new full interpreter.
func New() *Frame {
	return New1(false)
}

// NewSafe() makes a new safe interpreter.
func NewSafe() *Frame {
	return New1(true)
}

// NewFrame makes a frame for calling another proc.
func (fr *Frame) NewFrame() *Frame {
	return &Frame{
		Vars: make(Scope), // new local var scope
		Cred: fr.Cred,     // same credentials as caller
		Prev: fr,          // link back to prev frame
		G:    fr.G,        // the Global struct
	}
}

// Initial capital letter for a variable means Global.
func IsGlobal(name string) bool {
	if len(name) == 0 {
		panic("Empty variable name")
	}
	return ast.IsExported(name) // Same criteria, First is Uppercase.
}

// Initial capital letter for a variable means local.
func IsLocal(name string) bool {
	if len(name) == 0 {
		panic("Empty variable name")
	}
	return !ast.IsExported(name)
}

func (p *Slot) Has() bool { return p.Elem != nil }
func (p *Slot) Get() T    { return p.Elem }
func (p *Slot) Set(t T)   { p.Elem = t }

func (fr *Frame) GetVarScope(name string) Scope {
	if len(name) == 0 {
		panic("Empty variable name")
	}

	if name[0] == '_' && fr.Self != nil {
		return fr.Self.Slots
	}

	if IsGlobal(name) {
		return fr.G.Fr.Vars
	}
	return fr.Vars
}

func (fr *Frame) HasVar(name string) bool {
	sc := fr.GetVarScope(name)
	var loc Loc
	var ok bool
	if loc, ok = sc[name]; !ok {
		return false
	}
	return loc.Has()
}

func (fr *Frame) GetVar(name string) T {
	sc := fr.GetVarScope(name)
	var loc Loc
	var ok bool
	if loc, ok = sc[name]; !ok {
		panic(Sprintf("Variable %q does not exist; scope contains %v", name, sc))
	}
	return loc.Get()
}

func (fr *Frame) SetVar(name string, x T) {
	if strings.Contains(name, ",") {
		// Support destructuring list assignment syntax.
		xs := x.List()
		names := strings.Split(name, ",")
		for i, n := range names {
			if len(n) > 0 {
				if i < len(xs) {
					fr.SetVar(n, xs[i])
				} else {
					fr.SetVar(n, Empty) // Missing values become empty.
				}
			}
		}
		return
	}
	sc := fr.GetVarScope(name)
	if sc[name] == nil {
		sc[name] = new(Slot)
	}
	sc[name].Set(x)
}

func (p *UpSlot) Has() bool { return p.Fr.HasVar(p.RemoteName) }
func (p *UpSlot) Get() T    { return p.Fr.GetVar(p.RemoteName) }
func (p *UpSlot) Set(t T)   { p.Fr.SetVar(p.RemoteName, t) }

func (fr *Frame) DefineUpVar(name string, remFr *Frame, remName string) {
	sc := fr.GetVarScope(name)
	sc[name] = &UpSlot{Fr: remFr, RemoteName: remName}
}

func (fr *Frame) FindCommand(name T, callSuper bool) Command {
	// Some day we will not require terpString; for now, it helps debug.
	cmdName, ok := name.(terpString)
	if !ok {
		panic(Sprintf("Restriction: Command must be a string: %#v", name))
	}

	var fn Command
	cmdNode, ok := fr.G.Cmds[cmdName.s]
	if ok {
		if callSuper {
			maxMixinLevel := fr.MixinLevel - 1
			if maxMixinLevel < 0 {
				panic("cannot callSuper from non-mixin")
			}
			for cmdNode != nil && cmdNode.MixinLevel > maxMixinLevel {
				cmdNode = cmdNode.Next
			}
		}
		if cmdNode == nil {
			ok = false
		} else {
			fn = cmdNode.Fn
		}
	}

	// Mixin Local Commands:
	if !ok && fr.MixinLevel > 0 && !IsGlobal(cmdName.s) {
		// Use long name for mixin local fn.
		localCmdName := fr.MixinName + "~" + cmdName.s
		var localNode *CmdNode
		localNode, ok = fr.G.Cmds[localCmdName]
		if ok {
			fn = localNode.Fn // Should be singleton.
		}
	}

	if !ok {
		panic(Sprintf("FindCommand: command not found: %q", cmdName.s))
	}
	return fn
}

// Apply a command with its arguments.
func (fr *Frame) Apply(argv []T) T {
	defer func() {
		if r := recover(); r != nil {
			if re, ok := r.(error); ok {
				r = re.Error() // Convert error to string.
			}
			if rs, ok := r.(string); ok {
				rs = rs + Sprintf("\n\tin Apply\n\t\t%q", argv[0])

				// TODO: Require debug level for the args.
				for _, ae := range argv[1:] {
					as := ae.String()
					if len(as) > 40 {
						as = as[:40] + "..."
					}
					rs = rs + Sprintf(" %q", as)
				}

				if fr.MixinLevel > 0 {
					rs = rs + Sprintf("\n\t\t(frame's MixinLevel=%d)", fr.MixinLevel)
				}
				if len(fr.MixinName) > 0 {
					rs = rs + Sprintf("\n\t\t(frame's MixinName=%q)", fr.MixinName)
				}
				r = rs
			}
			panic(r)
		}
	}()

	head := argv[0]
	fn := fr.FindCommand(head, false) // false: Don't call super.
	z := fn(fr, argv)
	return z
}

func Repr(a interface{}) string { return Sprintf("REPR<<%#v>>", a) }

// Must takes 2 T values, and compares their Show()s.
func Must(a, b T) {
	if a.String() != b.String() {
		panic(Show(a) + " .vs. " + Show(b))
	}
}

// MustST takes a string and a T
func MustST(a string, b T) {
	Must(MkString(a), b)
}

// MustA takes Any 2 values, and compares their Repr()s.
func MustA(a, b interface{}) {
	if Repr(a) != Repr(b) {
		panic(Repr(a) + " .vs. " + Repr(b))
	}
}

// MustSp takes Any 2 values, and compares their Repr()s, without spaces.
func MustNoSp(a, b interface{}) {
	if DropSpaces(Repr(a)) != DropSpaces(Repr(b)) {
		panic(Repr(a) + " .vs. " + Repr(b))
	}
}
func DropSpaces(s string) string {
	z := ""
	for _, c := range s {
		if c != ' ' {
			z += string(c)
		}
	}
	return z
}

func Show(a T) string {
	if a == nil {
		return "{(T)nil}"
	}
	return Sprintf("{(%T) ## %#v ## %q}", a, a, a.String())
}

func Showv(a []T) string {
	buf := bytes.NewBufferString(Sprintf("Slice of T with %d elements:", len(a)))
	for i, e := range a {
		buf.WriteString(Sprintf("\n    ... [%d] = %s", i, Show(e)))
	}
	return buf.String()
}

// Quick internal logging function that needs no Frame.
func Say(args ...interface{}) {
	prefix := "Say "
	for _, a := range args {
		switch t := a.(type) {
		case Shower:
			log.Println(Sprintf("%s%s", prefix, t.Show()))
		default:
			log.Println(Sprintf("%s%#v", prefix, a))
		}
		prefix += "::: "
	}
}
func Sayf(format string, args ...interface{}) {
	log.Println(Sprintf(format, args...))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"./ssdb"
)

func main() {
	ip := "127.0.0.1"
	port := 8888
	db, err := ssdb.Connect(ip, port)
	if err != nil {
		os.Exit(1)
	}

	defer db.Close()
	var val interface{}

	keys := []string{}
	keys = append(keys, "c");
	keys = append(keys, "d");
	val, err = db.Do("multi_get", "a", "b", keys);
	fmt.Printf("%s\n", val);

	db.Set("a", "xxx")
	val, err = db.Get("a")
	fmt.Printf("%s\n", val)
	db.Del("a")
	val, err = db.Get("a")
	fmt.Printf("%s\n", val)

	db.Do("zset", "z", "a", 3)
	db.Do("multi_zset", "z", "b", -2, "c", 5, "d", 3)
	resp, err := db.Do("zrange", "z", 0, 10)
	if err != nil {
		os.Exit(1)
	}
	if len(resp)%2 != 1 {
		fmt.Printf("bad response")
		os.Exit(1)
	}

	fmt.Printf("Status: %s\n", resp[0])
	for i := 1; i < len(resp); i += 2 {
		fmt.Printf("  %s : %3s\n", resp[i], resp[i+1])
	}
	return
}
<commit_msg>update test.go<commit_after>package main

import (
	"fmt"
	"os"

	"./ssdb"
)

func main() {
	ip := "127.0.0.1"
	port := 8888
	db, err := ssdb.Connect(ip, port)
	if err != nil {
		os.Exit(1)
	}

	defer db.Close()
	var val interface{}

	keys := []string{}
	keys = append(keys, "c");
	keys = append(keys, "d");
	val, err = db.Do("multi_get", "a", "b", keys);
	fmt.Printf("%s\n", val);

	db.Set("a", "xxx")
	val, err = db.Get("a")
	fmt.Printf("%s\n", val)
	db.Del("a")
	val, err = db.Get("a")
	fmt.Printf("%s\n", val)

	fmt.Printf("----\n");

	db.Do("zset", "z", "a", 3)
	db.Do("multi_zset", "z", "b", -2, "c", 5, "d", 3)
	resp, err := db.Do("zrscan", "z", "", "", "", 10)
	if err != nil {
		os.Exit(1)
	}
	if len(resp)%2 != 1 {
		fmt.Printf("bad response")
		os.Exit(1)
	}

	fmt.Printf("Status: %s\n", resp[0])
	for i := 1; i < len(resp); i += 2 {
		fmt.Printf("  %s : %3s\n", resp[i], resp[i+1])
	}
	return
}
<|endoftext|>


<commit_before>// Copyright (c) Christoph Berger. All rights reserved.
// Use of this source code is governed by the BSD (3-Clause)
// License that can be found in the LICENSE.txt file.
//
// This source code may import third-party source code whose
// licenses are provided in the respective license files.

package start

import (
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/laurent22/toml-go"
)

// NewconfigFile creates a new configFile struct filled with the contents
// of the file identified by filename.
// Parameter filename can be an empty string, a file name, or a fully qualified path.
func newConfigFile(filename string) (*configFile, error) { // TODO: Do not return an error. See start.go > parse()
	cfg := &configFile{}
	err := cfg.findAndReadTomlFile(filename)
	return cfg, err
}

// String returns the value of key "name" as a string.
// Keys must be defined outside any section in the TOML file.
func (c *configFile) String(name string) string {
	value, exists := c.doc.GetValue(name)
	// Note: c.doc.GetString() does not work here as this
	// returns "" for all non-string values.
	// GetValue().String(), on the other hand, does work for
	// all non-string values that implement the String() method.
	if exists {
		return value.String()
	}
	return ""
}

// Path returns the path to the config file, if one was found.
// Otherwise it returns an empty path.
func (c *configFile) Path() string {
	if c == nil {
		return ""
	}
	return c.path
}

// Toml returns the toml document created from the config file,
// or an empty toml document if no config file was found.
func (c *configFile) Toml() toml.Document {
	if c == nil {
		return toml.Document{}
	}
	return c.doc
}

func (c *configFile) findAndReadTomlFile(name string) error {
	var err error

	// is name an absolute path? If so, go ahead and read the file.
	if filepath.IsAbs(name) {
		fileInfo, _ := os.Stat(name)
		if fileInfo.IsDir() {
			c.doc, err = c.readTomlFile(filepath.Join(name, appName()+".toml"))
		} else {
			c.doc, err = c.readTomlFile(name)
		}
		return err
	}

	// is the environment variable <APPNAME>_CFGPATH set
	// (either to a dir path or to a file path)?
	cfgPath := os.Getenv(strings.ToUpper(appName() + "_CFGPATH"))
	if len(cfgPath) > 0 {
		if len(name) > 0 {
			cfgPath = filepath.Join(cfgPath, name)
		}
		c.doc, err = c.readTomlFile(cfgPath)
		if err == nil {
			return nil
		}
	}

	// environment variable is not set, or the config file was not found there,
	// so place the config file into ~/.config/<application>/.
	cfgPath = GetHomeDir()
	if len(cfgPath) > 0 {
		if len(name) == 0 {
			// no name supplied; use config.toml
			name = "config.toml"
		}
		path := filepath.Join(cfgPath, ".config", appName(), name)
		c.doc, err = c.readTomlFile(path)
		if err == nil {
			return nil
		}
	}

	// did not find a config file in the home dir,
	// or did not find a home dir at all,
	// so try the working dir instead
	cfgPath, err = os.Getwd()
	if err == nil {
		if len(name) == 0 {
			name = appName() + ".toml"
		}
		c.doc, err = c.readTomlFile(filepath.Join(cfgPath, name))
		// At this point, it is clear that no config file exists at the
		// given locations.
		// The code cannot determine if the config file is missing intentionally
		// or rather by fault, so it assumes the former and returns no error.
		// The user of this library can verify if a config file was read by
		// calling start.ConfigFilePath() after having called start.Up()
		// or start.Parse().
		return nil
	}
	return err
}

func (c *configFile) readTomlFile(path string) (toml.Document, error) {
	var parser toml.Parser
	var err error
	emptyDoc := parser.Parse("") // empty default TOML document required to fix a runtime panic
	if _, err = os.Stat(path); err == nil {
		c.path = path
		return parser.ParseFile(path), nil
	}
	return emptyDoc, err
}

// GetHomeDir finds the user's home directory in an OS-independent way.
// "OS-independent" means compatible with most Unix-like operating systems as well as with Microsoft Windows(TM).
func GetHomeDir() string {
	// credits for this OS-independent solution go to http://stackoverflow.com/a/7922977
	// (os.User is not an option here. It relies on CGO and thus prevents cross compiling.)
	home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
	if home == "" {
		home = os.Getenv("USERPROFILE")
	}
	if home == "" {
		home = os.Getenv("HOME")
	}
	return home
}

// appName returns the name of the application, with path and extension stripped off,
// and all characters other than ASCII letters, numbers, or underscores, replaced by
// underscores.
// Replacing special characters by underscores makes the returned name suitable for
// being used in the name of an environment variable.
func appName() string {
	fileName := filepath.Base(os.Args[0])
	fileExt := filepath.Ext(fileName)
	if len(fileExt) > 0 {
		fileName = strings.Split(fileName, ".")[0]
	}
	return regexp.MustCompile("[^a-zA-Z0-9_]").ReplaceAllString(fileName, "_")
}
<commit_msg>Fix: err not used<commit_after>// Copyright (c) Christoph Berger. All rights reserved.
// Use of this source code is governed by the BSD (3-Clause)
// License that can be found in the LICENSE.txt file.
//
// This source code may import third-party source code whose
// licenses are provided in the respective license files.

package start

import (
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/laurent22/toml-go"
)

// NewconfigFile creates a new configFile struct filled with the contents
// of the file identified by filename.
// Parameter filename can be an empty string, a file name, or a fully qualified path.
func newConfigFile(filename string) (*configFile, error) { // TODO: Do not return an error. See start.go > parse()
	cfg := &configFile{}
	err := cfg.findAndReadTomlFile(filename)
	return cfg, err
}

// String returns the value of key "name" as a string.
// Keys must be defined outside any section in the TOML file.
func (c *configFile) String(name string) string {
	value, exists := c.doc.GetValue(name)
	// Note: c.doc.GetString() does not work here as this
	// returns "" for all non-string values.
	// GetValue().String(), on the other hand, does work for
	// all non-string values that implement the String() method.
	if exists {
		return value.String()
	}
	return ""
}

// Path returns the path to the config file, if one was found.
// Otherwise it returns an empty path.
func (c *configFile) Path() string {
	if c == nil {
		return ""
	}
	return c.path
}

// Toml returns the toml document created from the config file,
// or an empty toml document if no config file was found.
func (c *configFile) Toml() toml.Document {
	if c == nil {
		return toml.Document{}
	}
	return c.doc
}

func (c *configFile) findAndReadTomlFile(name string) error {
	var err error

	// is name an absolute path? If so, go ahead and read the file.
	if filepath.IsAbs(name) {
		fileInfo, _ := os.Stat(name)
		if fileInfo.IsDir() {
			c.doc, err = c.readTomlFile(filepath.Join(name, appName()+".toml"))
		} else {
			c.doc, err = c.readTomlFile(name)
		}
		return err
	}

	// is the environment variable <APPNAME>_CFGPATH set
	// (either to a dir path or to a file path)?
	cfgPath := os.Getenv(strings.ToUpper(appName() + "_CFGPATH"))
	if len(cfgPath) > 0 {
		if len(name) > 0 {
			cfgPath = filepath.Join(cfgPath, name)
		}
		c.doc, err = c.readTomlFile(cfgPath)
		if err == nil {
			return nil
		}
	}

	// environment variable is not set, or the config file was not found there,
	// so place the config file into ~/.config/<application>/.
	cfgPath = GetHomeDir()
	if len(cfgPath) > 0 {
		if len(name) == 0 {
			// no name supplied; use config.toml
			name = "config.toml"
		}
		path := filepath.Join(cfgPath, ".config", appName(), name)
		c.doc, err = c.readTomlFile(path)
		if err == nil {
			return nil
		}
	}

	// did not find a config file in the home dir,
	// or did not find a home dir at all,
	// so try the working dir instead
	cfgPath, err = os.Getwd()
	if err == nil {
		if len(name) == 0 {
			name = appName() + ".toml"
		}
		c.doc, _ = c.readTomlFile(filepath.Join(cfgPath, name))
		// At this point, it is clear that no config file exists at the
		// given locations.
		// The code cannot determine if the config file is missing intentionally
		// or rather by fault, so it assumes the former and returns no error.
		// The user of this library can verify if a config file was read by
		// calling start.ConfigFilePath() after having called start.Up()
		// or start.Parse().
		return nil
	}
	return err
}

func (c *configFile) readTomlFile(path string) (toml.Document, error) {
	var parser toml.Parser
	var err error
	emptyDoc := parser.Parse("") // empty default TOML document required to fix a runtime panic
	if _, err = os.Stat(path); err == nil {
		c.path = path
		return parser.ParseFile(path), nil
	}
	return emptyDoc, err
}

// GetHomeDir finds the user's home directory in an OS-independent way.
// "OS-independent" means compatible with most Unix-like operating systems as well as with Microsoft Windows(TM).
func GetHomeDir() string {
	// credits for this OS-independent solution go to http://stackoverflow.com/a/7922977
	// (os.User is not an option here. It relies on CGO and thus prevents cross compiling.)
	home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
	if home == "" {
		home = os.Getenv("USERPROFILE")
	}
	if home == "" {
		home = os.Getenv("HOME")
	}
	return home
}

// appName returns the name of the application, with path and extension stripped off,
// and all characters other than ASCII letters, numbers, or underscores, replaced by
// underscores.
// Replacing special characters by underscores makes the returned name suitable for
// being used in the name of an environment variable.
func appName() string {
	fileName := filepath.Base(os.Args[0])
	fileExt := filepath.Ext(fileName)
	if len(fileExt) > 0 {
		fileName = strings.Split(fileName, ".")[0]
	}
	return regexp.MustCompile("[^a-zA-Z0-9_]").ReplaceAllString(fileName, "_")
}
<|endoftext|>


<commit_before>package sms

import (
	"bytes"
	"fmt"
	"io"
	"time"
)

var (
	msgRef = byte(0)
)

func init() {
	msgRef = byte(time.Now().Nanosecond())
}

// TPDU represents a SMS PDU
type TPDU interface {
	WriteTo(w io.Writer) (n int64, e error)
	ReadFrom(h byte, r io.Reader) (n int64, e error)
}

// ParseAsSM parse byte data to TPDU as SM side
func ParseAsSM(r io.Reader) (t TPDU, n int64, e error) {
	h := make([]byte, 1)
	i := 0
	if i, e = r.Read(h); e != nil {
		return
	} else if i != 1 {
		e = fmt.Errorf("no data")
		return
	}

	switch h[0] & 0x03 {
	case 0x00:
		t = &Deliver{}
	case 0x01:
		//		t = &SubmitReport{}
	case 0x02:
		//		t = &StatusReport{}
	case 0x03:
		e = fmt.Errorf("invalid data: reserved TPDU type")
		return
	}

	if n, e = t.ReadFrom(h[0], r); e != nil {
		return
	}
	n++

	return
}

// ParseAsSC parse byte data to TPDU as SC side
func ParseAsSC(r io.Reader) (t TPDU, n int64, e error) {
	h := make([]byte, 1)
	i := 0
	if i, e = r.Read(h); e != nil {
		return
	} else if i != 1 {
		e = fmt.Errorf("no data")
		return
	}

	switch h[0] & 0x03 {
	case 0x00:
		//		t = &DeliverReport{}
	case 0x01:
		t = &Submit{}
	case 0x02:
		//		t = &Command{}
	case 0x03:
		e = fmt.Errorf("invalid data: reserved TPDU type")
		return
	}

	if n, e = t.ReadFrom(h[0], r); e != nil {
		return
	}
	n++

	return
}

/*
	Req bool

	MTI  byte    // Message Type Indicator
	MMS  bool    // More Messages to Send
	RD   bool    // Reject Duplicates
	LP   bool    // Loop Prevention
	VPF  byte    // Validity Period Format
	SRI  bool    // Status Report Indication
	SRR  bool    // Status Report Request
	SRQ  bool    // Status Report Qualifier
	UDHI bool    // User Data Header Indicator
	RP   bool    // Reply Path
	FCS  byte    // Failure Cause
	MR   byte    // Message Reference
	DA   TPAddr  // Destination Address
	OA   TPAddr  // Originating Address
	RA   TPAddr  // Recipient Address
	SCTS [7]byte // Service Centre Time Stamp
	DT   [7]byte // Discharge Time
	ST   byte    // Status
	PI   byte    // Parameter Indicator
	PID  byte    // Protocol Identifier
	DCS  byte    // Data Coding Scheme
	VP   []byte  // Validity Period
	CDL  byte    // User Data Length
	UD   string  // User Data
	CT   byte    // Command Type
	MN   byte    // Message Number
	CD   []byte  // Command Data

	// User Data
	UDh []byte
}

func (p TPDU) encodeUD() []byte {
	s := p.UD
	if len(s)*2 > 140-len(p.UDh) {
		s = s[0 : (140-len(p.UDh))/2]
	} else if len(s) == 0 {
		return make([]byte, 0)
	}

	u := utf16.Encode([]rune(s))
	b := make([]byte, len(u)*2)
	for i, c := range u {
		b[i*2] = byte((c >> 8) & 0xff)
		b[i*2+1] = byte(c & 0xff)
	}
	return b
}
*/

// Address is SMS originator/destination address
type Address struct {
	TON  byte
	NPI  byte
	Addr addrValue
}

type addrValue interface {
	Length() int
	ByteLength() int
	String() string
	WriteTo(w io.Writer) (n int64, e error)
}

// WriteTo wite binary data to io.Writer
func (a Address) WriteTo(w io.Writer) (n int64, e error) {
	i := 0
	switch a.Addr.(type) {
	case TBCD:
		i = a.Addr.Length()
		if a.TON == 0x05 {
			e = fmt.Errorf("invalid TON for digit address")
			return
		}
	case GSM7bitString:
		i = a.Addr.ByteLength() * 2
		if a.TON != 0x05 || a.NPI != 0x00 {
			e = fmt.Errorf("invalid TON/NPI for alphanumeric address")
			return
		}
	}

	b := []byte{byte(i), 0x80}
	b[1] = b[1] | (a.TON&0x07)<<4
	b[1] = b[1] | (a.NPI & 0x0f)
	if i, e = w.Write(b); e != nil {
		n = int64(i)
		return
	}

	n, e = a.Addr.WriteTo(w)
	n += int64(i)

	if e == nil && n > 12 {
		e = fmt.Errorf("too much long address data %d", n)
	}
	return
}

// ReadFrom read byte data and set parameter of the Address
func (a *Address) ReadFrom(r io.Reader) (n int64, e error) {
	i := 0
	b := make([]byte, 2)
	if i, e = r.Read(b); e != nil {
		return
	} else if i != 2 {
		e = fmt.Errorf("more data required")
		return
	}

	l := int(b[0])
	a.TON = (b[1] >> 4) & 0x07
	a.NPI = b[1] & 0x0f

	if a.TON == 0x05 {
		l /= 2
		b := make([]byte, l)
		i, e = r.Read(b)
		a.Addr = GSM7bitString(b)
	} else {
		if l%2 == 1 {
			l++
		}
		l /= 2
		b := make([]byte, l)
		i, e = r.Read(b)
		a.Addr = TBCD(b)
	}

	n = int64(i + 2)
	if i != l {
		e = fmt.Errorf("more data required")
	}
	return
}

// TimeStamp is time data for TP-SCTS, TP-DT and in Absolute format of TP-VP
type TimeStamp [7]byte

// EncodeTime create DateTime
func EncodeTime(t time.Time) TimeStamp {
	var r [7]byte

	r[0] = byte(t.Year() % 10)
	r[0] = (r[0] << 4) | byte((t.Year()/10)%10)
	r[1] = byte(t.Month() % 10)
	r[1] = (r[1] << 4) | byte((t.Month()/10)%10)
	r[2] = byte(t.Day() % 10)
	r[2] = (r[2] << 4) | byte((t.Day()/10)%10)
	r[3] = byte(t.Hour() % 10)
	r[3] = (r[3] << 4) | byte((t.Hour()/10)%10)
	r[4] = byte(t.Minute() % 10)
	r[4] = (r[4] << 4) | byte((t.Minute()/10)%10)
	r[5] = byte(t.Second() % 10)
	r[5] = (r[5] << 4) | byte((t.Second()/10)%10)

	_, z := t.Zone()
	z /= 900
	r[6] = byte((z % 10) & 0x0f)
	r[6] = (r[6] << 4) | byte(((z/10)%10)&0x0f)
	if z < 0 {
		r[6] = r[6] | 0x08
	}
	return r
}
<<<<<<< HEAD

func encodeUDH(m map[byte][]byte) []byte {
	if len(m) == 0 {
		return []byte{}
	}

	var b bytes.Buffer
	b.WriteByte(0x00)
	for k, v := range m {
		b.WriteByte(k)
		b.WriteByte(byte(len(v)))
		b.Write(v)
	}
	r := b.Bytes()
	r[0] = byte(len(r) - 1)
	return r
}
=======
>>>>>>> e31f85d3701d03cc283c013fa0a86ad85b741831
<commit_msg>modify<commit_after>package sms

import (
	"bytes"
	"fmt"
	"io"
	"time"
)

var (
	msgRef = byte(0)
)

func init() {
	msgRef = byte(time.Now().Nanosecond())
}

// TPDU represents a SMS PDU
type TPDU interface {
	WriteTo(w io.Writer) (n int64, e error)
	ReadFrom(h byte, r io.Reader) (n int64, e error)
}

// ParseAsSM parse byte data to TPDU as SM side
func ParseAsSM(r io.Reader) (t TPDU, n int64, e error) {
	h := make([]byte, 1)
	i := 0
	if i, e = r.Read(h); e != nil {
		return
	} else if i != 1 {
		e = fmt.Errorf("no data")
		return
	}

	switch h[0] & 0x03 {
	case 0x00:
		t = &Deliver{}
	case 0x01:
		//		t = &SubmitReport{}
	case 0x02:
		//		t = &StatusReport{}
	case 0x03:
		e = fmt.Errorf("invalid data: reserved TPDU type")
		return
	}

	if n, e = t.ReadFrom(h[0], r); e != nil {
		return
	}
	n++

	return
}

// ParseAsSC parse byte data to TPDU as SC side
func ParseAsSC(r io.Reader) (t TPDU, n int64, e error) {
	h := make([]byte, 1)
	i := 0
	if i, e = r.Read(h); e != nil {
		return
	} else if i != 1 {
		e = fmt.Errorf("no data")
		return
	}

	switch h[0] & 0x03 {
	case 0x00:
		//		t = &DeliverReport{}
	case 0x01:
		t = &Submit{}
	case 0x02:
		//		t = &Command{}
	case 0x03:
		e = fmt.Errorf("invalid data: reserved TPDU type")
		return
	}

	if n, e = t.ReadFrom(h[0], r); e != nil {
		return
	}
	n++

	return
}

/*
	Req bool

	MTI  byte    // Message Type Indicator
	MMS  bool    // More Messages to Send
	RD   bool    // Reject Duplicates
	LP   bool    // Loop Prevention
	VPF  byte    // Validity Period Format
	SRI  bool    // Status Report Indication
	SRR  bool    // Status Report Request
	SRQ  bool    // Status Report Qualifier
	UDHI bool    // User Data Header Indicator
	RP   bool    // Reply Path
	FCS  byte    // Failure Cause
	MR   byte    // Message Reference
	DA   TPAddr  // Destination Address
	OA   TPAddr  // Originating Address
	RA   TPAddr  // Recipient Address
	SCTS [7]byte // Service Centre Time Stamp
	DT   [7]byte // Discharge Time
	ST   byte    // Status
	PI   byte    // Parameter Indicator
	PID  byte    // Protocol Identifier
	DCS  byte    // Data Coding Scheme
	VP   []byte  // Validity Period
	CDL  byte    // User Data Length
	UD   string  // User Data
	CT   byte    // Command Type
	MN   byte    // Message Number
	CD   []byte  // Command Data

	// User Data
	UDh []byte
}

func (p TPDU) encodeUD() []byte {
	s := p.UD
	if len(s)*2 > 140-len(p.UDh) {
		s = s[0 : (140-len(p.UDh))/2]
	} else if len(s) == 0 {
		return make([]byte, 0)
	}

	u := utf16.Encode([]rune(s))
	b := make([]byte, len(u)*2)
	for i, c := range u {
		b[i*2] = byte((c >> 8) & 0xff)
		b[i*2+1] = byte(c & 0xff)
	}
	return b
}
*/

// Address is SMS originator/destination address
type Address struct {
	TON  byte
	NPI  byte
	Addr addrValue
}

type addrValue interface {
	Length() int
	ByteLength() int
	String() string
	WriteTo(w io.Writer) (n int64, e error)
}

// WriteTo wite binary data to io.Writer
func (a Address) WriteTo(w io.Writer) (n int64, e error) {
	i := 0
	switch a.Addr.(type) {
	case TBCD:
		i = a.Addr.Length()
		if a.TON == 0x05 {
			e = fmt.Errorf("invalid TON for digit address")
			return
		}
	case GSM7bitString:
		i = a.Addr.ByteLength() * 2
		if a.TON != 0x05 || a.NPI != 0x00 {
			e = fmt.Errorf("invalid TON/NPI for alphanumeric address")
			return
		}
	}

	b := []byte{byte(i), 0x80}
	b[1] = b[1] | (a.TON&0x07)<<4
	b[1] = b[1] | (a.NPI & 0x0f)
	if i, e = w.Write(b); e != nil {
		n = int64(i)
		return
	}

	n, e = a.Addr.WriteTo(w)
	n += int64(i)

	if e == nil && n > 12 {
		e = fmt.Errorf("too much long address data %d", n)
	}
	return
}

// ReadFrom read byte data and set parameter of the Address
func (a *Address) ReadFrom(r io.Reader) (n int64, e error) {
	i := 0
	b := make([]byte, 2)
	if i, e = r.Read(b); e != nil {
		return
	} else if i != 2 {
		e = fmt.Errorf("more data required")
		return
	}

	l := int(b[0])
	a.TON = (b[1] >> 4) & 0x07
	a.NPI = b[1] & 0x0f

	if a.TON == 0x05 {
		l /= 2
		b := make([]byte, l)
		i, e = r.Read(b)
		a.Addr = GSM7bitString(b)
	} else {
		if l%2 == 1 {
			l++
		}
		l /= 2
		b := make([]byte, l)
		i, e = r.Read(b)
		a.Addr = TBCD(b)
	}

	n = int64(i + 2)
	if i != l {
		e = fmt.Errorf("more data required")
	}
	return
}

// TimeStamp is time data for TP-SCTS, TP-DT and in Absolute format of TP-VP
type TimeStamp [7]byte

// EncodeTime create DateTime
func EncodeTime(t time.Time) TimeStamp {
	var r [7]byte

	r[0] = byte(t.Year() % 10)
	r[0] = (r[0] << 4) | byte((t.Year()/10)%10)
	r[1] = byte(t.Month() % 10)
	r[1] = (r[1] << 4) | byte((t.Month()/10)%10)
	r[2] = byte(t.Day() % 10)
	r[2] = (r[2] << 4) | byte((t.Day()/10)%10)
	r[3] = byte(t.Hour() % 10)
	r[3] = (r[3] << 4) | byte((t.Hour()/10)%10)
	r[4] = byte(t.Minute() % 10)
	r[4] = (r[4] << 4) | byte((t.Minute()/10)%10)
	r[5] = byte(t.Second() % 10)
	r[5] = (r[5] << 4) | byte((t.Second()/10)%10)

	_, z := t.Zone()
	z /= 900
	r[6] = byte((z % 10) & 0x0f)
	r[6] = (r[6] << 4) | byte(((z/10)%10)&0x0f)
	if z < 0 {
		r[6] = r[6] | 0x08
	}
	return r
}

func encodeUDH(m map[byte][]byte) []byte {
	if len(m) == 0 {
		return []byte{}
	}

	var b bytes.Buffer
	b.WriteByte(0x00)
	for k, v := range m {
		b.WriteByte(k)
		b.WriteByte(byte(len(v)))
		b.Write(v)
	}
	r := b.Bytes()
	r[0] = byte(len(r) - 1)
	return r
}
<|endoftext|>


<commit_before>package lars

import "net/url"

type nodes map[string]*node

type chainMethods map[string]HandlersChain

// node
type node struct {

	// Static Children
	static nodes

	// Params Children
	params *node

	// Wildcard Children
	wild *node

	chains chainMethods

	// set only on params node
	param string
}

type router struct {
	lars *LARS
	tree *node
}

func (n *node) addChain(method string, chain HandlersChain) {

	if n.chains == nil {
		n.chains = map[string]HandlersChain{}
	}

	n.chains[method] = chain
}

func (r *router) addPath(method string, path string, rg *RouteGroup, h HandlersChain) {

	var err error

	if path, err = url.QueryUnescape(path); err != nil {
		panic("Query Unescape Error:" + err.Error())
	}

	if path == blank {
		path = basePath
	}

	pCount := new(uint8)
	*pCount++

	n := add(path[1:], pCount, r.tree)
	if n == nil {
		panic("node not added!")
	}

	if *pCount > r.lars.mostParams {
		r.lars.mostParams = *pCount
	}

	n.addChain(method, append(rg.middleware, h...))
}

// TODO: Add Warning when a wild is add to the same node as a param or vise-versa
func add(path string, pCount *uint8, n *node) *node {

	// if blank we're done move on
	if path == blank {
		return n
	}

	var end int
	var c int32

	for end, c = range path {

		// found chunk ending in slash?
		if c == slash {

			chunk := path[0 : end+1]

			// check for existing node
			if charNode, ok := n.static[chunk]; ok {
				return add(path[end+1:], pCount, charNode)
			}

			// no existing node, adding new one
			if n.static == nil {
				n.static = nodes{}
			}

			nn := &node{}
			n.static[chunk] = nn

			return add(path[end+1:], pCount, nn)
		}

		// found url parameter?
		if c == colon {

			start := end + 1

			// extract param name
			for end, c = range path[start:] {
				if c != slash {
					continue
				}

				param := path[start : end+1]

				// existing param node?
				if n.params != nil {

					// can't have same prefix paths with different param names example:
					// /users/:id/profile
					// /users/:user_id/profile/settings
					// both params above must be either :id or :user_id, no mix & match
					if n.params.param != param {
						panic("Different Param names defined")
					}

					*pCount++

					return add(path[end+2:], pCount, n.params)
				}

				nn := &node{
					param: param,
				}

				n.params = nn

				*pCount++

				return add(path[end+2:], pCount, nn)
			}

			// param name did not end in slash, extract as last element of path

			*pCount++
			param := path[start:]

			if n.params != nil {
				if n.params.param != param {
					panic("Different Param names defined")
				}

				return n.params
			}

			nn := &node{
				param: param,
			}

			n.params = nn

			return nn
		}

		// Check for Wildcard
		if c == star {

			if path[end+1:] != blank {
				panic("Character after the * symbol is not acceptable")
			}

			//Check the node for existing star then throw a panic information
			//if any
			if n.wild != nil {
				panic("Wildcard character already exists")
			}

			nn := &node{}

			n.wild = nn

			return nn

		}
	}

	// no slash encountered, url musn't end in one so use remaining path

	if charNode, ok := n.static[path]; ok {
		return charNode
	}

	if n.static == nil {
		n.static = nodes{}
	}

	nn := &node{}
	n.static[path] = nn

	return nn
}

func (r *router) find(context *ctx, method string, path string) {

	// homepage, no slash equal to r.tree node
	// if path == basePath {

	// 	chain := r.tree.chains[method]

	// 	if chain == nil {
	// 		context.handlers = append(r.lars.RouteGroup.middleware, r.lars.http404...)
	// 		return
	// 	}

	// 	context.handlers = chain
	// 	return
	// }

	findRoute(context, r.tree, method, path[1:])

	if context.handlers == nil {
		context.params = context.params[0:0]
		context.handlers = append(r.lars.RouteGroup.middleware, r.lars.http404...)
	}
}

func findRoute(context *ctx, n *node, method string, path string) {

	var end int
	var c byte
	var node *node
	var ok bool
	var chunk string

START:

	// start parsing URL
	for end = 0; end < len(path); end++ {

		c = path[end]

		if c != slashByte {
			continue
		}

		// found chunk ending in slash

		chunk = path[0 : end+1]

		if node, ok = n.static[chunk]; ok {

			path = path[end+1:]
			n = node

			goto START
		}

		// no matching static chunk look at params if available
		if n.params != nil {

			// extract param, then continue recursing over nodes.

			i := len(context.params)
			context.params = context.params[:i+1]
			context.params[i].Key = n.params.param
			context.params[i].Value = path[0:end]

			path = path[end+1:]
			n = n.params

			goto START
		}

		// no matching static or param chunk look at wild if available
		if n.wild != nil {
			context.handlers = n.chains[method]
			return
		}
	}

	// no slash encountered, end of path...
	if node, ok = n.static[path]; ok {
		context.handlers = node.chains[method]
		return
	}

	if n.params != nil {
		context.handlers = n.params.chains[method]
		i := len(context.params)
		context.params = context.params[:i+1]
		context.params[i].Key = n.params.param
		context.params[i].Value = path
		return
	}

	// no matching chunk nor param check if wild
	if n.wild != nil {
		context.handlers = n.wild.chains[method]
		return
	}

	if path == blank {
		context.handlers = n.chains[method]
		return
	}
}
<commit_msg>minor improvement<commit_after>package lars

import "net/url"

type nodes map[string]*node

type chainMethods map[string]HandlersChain

// node
type node struct {

	// Static Children
	static nodes

	// Params Children
	params *node

	// Wildcard Children
	wild *node

	chains chainMethods

	// set only on params node
	param string
}

type router struct {
	lars *LARS
	tree *node
}

func (n *node) addChain(method string, chain HandlersChain) {

	if n.chains == nil {
		n.chains = map[string]HandlersChain{}
	}

	n.chains[method] = chain
}

func (r *router) addPath(method string, path string, rg *RouteGroup, h HandlersChain) {

	var err error

	if path, err = url.QueryUnescape(path); err != nil {
		panic("Query Unescape Error:" + err.Error())
	}

	if path == blank {
		path = basePath
	}

	pCount := new(uint8)
	*pCount++

	n := add(path[1:], pCount, r.tree)
	if n == nil {
		panic("node not added!")
	}

	if *pCount > r.lars.mostParams {
		r.lars.mostParams = *pCount
	}

	n.addChain(method, append(rg.middleware, h...))
}

// TODO: Add Warning when a wild is add to the same node as a param or vise-versa
func add(path string, pCount *uint8, n *node) *node {

	// if blank we're done move on
	if path == blank {
		return n
	}

	var end int
	var c int32

	for end, c = range path {

		// found chunk ending in slash?
		if c == slash {

			chunk := path[0 : end+1]

			// check for existing node
			if charNode, ok := n.static[chunk]; ok {
				return add(path[end+1:], pCount, charNode)
			}

			// no existing node, adding new one
			if n.static == nil {
				n.static = nodes{}
			}

			nn := &node{}
			n.static[chunk] = nn

			return add(path[end+1:], pCount, nn)
		}

		// found url parameter?
		if c == colon {

			start := end + 1

			// extract param name
			for end, c = range path[start:] {
				if c != slash {
					continue
				}

				param := path[start : end+1]

				// existing param node?
				if n.params != nil {

					// can't have same prefix paths with different param names example:
					// /users/:id/profile
					// /users/:user_id/profile/settings
					// both params above must be either :id or :user_id, no mix & match
					if n.params.param != param {
						panic("Different Param names defined")
					}

					*pCount++

					return add(path[end+2:], pCount, n.params)
				}

				nn := &node{
					param: param,
				}

				n.params = nn

				*pCount++

				return add(path[end+2:], pCount, nn)
			}

			// param name did not end in slash, extract as last element of path

			*pCount++
			param := path[start:]

			if n.params != nil {
				if n.params.param != param {
					panic("Different Param names defined")
				}

				return n.params
			}

			nn := &node{
				param: param,
			}

			n.params = nn

			return nn
		}

		// Check for Wildcard
		if c == star {

			if path[end+1:] != blank {
				panic("Character after the * symbol is not acceptable")
			}

			//Check the node for existing star then throw a panic information
			//if any
			if n.wild != nil {
				panic("Wildcard character already exists")
			}

			nn := &node{}

			n.wild = nn

			return nn

		}
	}

	// no slash encountered, url musn't end in one so use remaining path

	if charNode, ok := n.static[path]; ok {
		return charNode
	}

	if n.static == nil {
		n.static = nodes{}
	}

	nn := &node{}
	n.static[path] = nn

	return nn
}

func (r *router) find(context *ctx, method string, path string) {

	// homepage, no slash equal to r.tree node
	// if path == basePath {

	// 	chain := r.tree.chains[method]

	// 	if chain == nil {
	// 		context.handlers = append(r.lars.RouteGroup.middleware, r.lars.http404...)
	// 		return
	// 	}

	// 	context.handlers = chain
	// 	return
	// }

	findRoute(context, r.tree, method, path[1:])

	if context.handlers == nil {
		context.params = context.params[0:0]
		context.handlers = append(r.lars.RouteGroup.middleware, r.lars.http404...)
	}
}

func findRoute(context *ctx, n *node, method string, path string) {

	var end int
	var c byte
	var node *node
	var ok bool
	var chunk string
	var i int

START:

	// start parsing URL
	for end = 0; end < len(path); end++ {

		c = path[end]

		if c != slashByte {
			continue
		}

		// found chunk ending in slash

		chunk = path[0 : end+1]

		if node, ok = n.static[chunk]; ok {

			path = path[end+1:]
			n = node

			goto START
		}

		// no matching static chunk look at params if available
		if n.params != nil {

			// extract param, then continue recursing over nodes.

			i = len(context.params)
			context.params = context.params[:i+1]
			context.params[i].Key = n.params.param
			context.params[i].Value = path[0:end]

			path = path[end+1:]
			n = n.params

			goto START
		}

		// no matching static or param chunk look at wild if available
		if n.wild != nil {
			context.handlers = n.chains[method]
			return
		}
	}

	// no slash encountered, end of path...
	if node, ok = n.static[path]; ok {
		context.handlers = node.chains[method]
		return
	}

	if n.params != nil {
		context.handlers = n.params.chains[method]
		i = len(context.params)
		context.params = context.params[:i+1]
		context.params[i].Key = n.params.param
		context.params[i].Value = path
		return
	}

	// no matching chunk nor param check if wild
	if n.wild != nil {
		context.handlers = n.wild.chains[method]
		return
	}

	if path == blank {
		context.handlers = n.chains[method]
		return
	}
}
<|endoftext|>


<commit_before>// tree provides balanced tree structure which acts as index
// to sort.Interface and could be used for searching like sort.Search
package tree

import "sort"
import "fmt"

var _ = fmt.Println

// Tree provides balanced tree structure
// which keeps order of is external sort.Interface
type Tree struct {
	root, min, max int
	nodes          []node
}

// Len returns number of indexed elements
func (t *Tree) Len() int {
	return len(t.nodes)
}

// Min returns index of minimum element
// panics if called on empty tree
func (t *Tree) Min() int {
	if len(t.nodes) == 0 {
		panic("Tree.Min should not be called on empty tree")
	}
	return t.min
}

// Max returns index of maximum element
// panics if called on empty tree
func (t *Tree) Max() int {
	if len(t.nodes) == 0 {
		panic("Tree.Max should not be called on empty tree")
	}
	return t.max
}

// Search returns first index for which predicate is true
// returns Len() if no element satisfies predicate
func (t *Tree) Search(pred func(i int) bool) int {
	if len(t.nodes) == 0 {
		return 0
	}
	now := t.root
	last_true := len(t.nodes)
	for {
		node := &t.nodes[now]
		if pred(now) {
			last_true = now
			if node.left() == null {
				return now
			}
			now = node.left()
		} else if node.right() == null {
			return last_true
		} else {
			now = node.right()
		}
	}
}

// SearchLast returns last index for which predicate is true
// returns -1 if no element satisfies predicate
func (t *Tree) SearchLast(pred func(i int) bool) int {
	if len(t.nodes) == 0 {
		return 0
	}
	now := t.root
	last_true := -1
	for {
		node := &t.nodes[now]
		if pred(now) {
			last_true = now
			if node.right() == null {
				return now
			}
			now = node.right()
		} else if node.left() == null {
			return last_true
		} else {
			now = node.left()
		}
	}
}

// Next returns index of next in-order element.
// if argument is -1, then return index of minimal element.
// returns t.Len() on finish.
func (t *Tree) Next(i int) int {
	if i > len(t.nodes) {
		panic("Tree index overflow")
	}
	if i == len(t.nodes) || i == t.max {
		return len(t.nodes)
	}
	if i == -1 {
		return t.min
	}
	node := &t.nodes[i]
	if node.right() != null {
		i = node.right()
		for t.nodes[i].left() != null {
			i = t.nodes[i].left()
		}
		return i
	}
	for node.parent() != null {
		dir := t.dir(i, node.parent())
		if dir == left {
			return node.parent()
		}
		i, node = node.parent(), &t.nodes[node.parent()]
	}
	panic("tree broken")
}

// Insert adds in-order element of sort.Interface at index Tree.Len()
// You should not put element with key equal to existed key.
func (t *Tree) Insert(data sort.Interface) {
	ix := len(t.nodes)
	t.nodes = append(t.nodes, node{null, null, null, 1})
	if ix == 0 {
		t.root, t.min, t.max = 0, 0, 0
		return
	}
	var dir direction
	cur := t.root
	curnode := &t.nodes[cur]
	for {
		dir = direction(data.Less(int(cur), ix))

		if curnode.link(dir) == null {
			break
		}
		cur = curnode.link(dir)
		curnode = &t.nodes[cur]
	}
	node := &t.nodes[ix]
	node.set_parent(cur)
	curnode.set_link(dir, ix)
	if dir == right {
		if cur == t.max {
			t.max = ix
		}
	} else if cur == t.min {
		t.min = ix
	}
	t.balance(cur)
}

// InsertBefore adds new element at specified position.
// It trust you and doesn't check insertion position
func (t *Tree) InsertBefore(data sort.Interface, cur int) {
	ix := len(t.nodes)
	dir := left
	if cur == len(t.nodes) {
		dir, cur = right, t.max
	}
	t.nodes = append(t.nodes, node{null, null, null, 1})
	if ix == 0 {
		if cur != 0 {
			panic("InsertBefore on empty tree accepts only 0")
		}
		t.root, t.min, t.max = 0, 0, 0
		return
	}
	curnode := &t.nodes[cur]
	node := &t.nodes[ix]
	node.set_parent(cur)
	curnode.set_link(dir, ix)
	if dir == right {
		if cur == t.max {
			t.max = ix
		}
	} else if cur == t.min {
		t.min = ix
	}
	t.balance(cur)
}

// Delete removes element from a tree and return index of next in-order element
func (t *Tree) Delete(data sort.Interface, ix int) int {
	if ix < 0 || ix >= len(t.nodes) {
		panic("Tree.Delete out of range")
	}
	if len(t.nodes) == 0 {
		t.nodes = t.nodes[:0]
		return 0
	}
	node := &t.nodes[ix]
	next := t.Next(ix)
	if node.left() != null && node.right() != null {
		data.Swap(ix, next)
		next, ix, node = ix, next, &t.nodes[next]
		/* at this moment order is temporary broken,
		   but it will be restored after complete */
	}
	return t.del(data, node, ix, next)
}

func (t *Tree) del(data sort.Interface, node *node, ix, next int) int {
	pix := node.parent()
	if pix == null {
		if node.left() == null {
			rix := node.right()
			t.root = rix
			if rix != null {
				t.nodes[rix].set_parent(null)
			}
			if t.min == ix {
				t.min = rix
			}
		} else {
			lix := node.left()
			t.root = lix
			if lix != null {
				t.nodes[lix].set_parent(null)
			}
			if t.max == ix {
				t.max = lix
			}
		}
		pix = t.root
	} else {
		pdir := t.dir(ix, pix)
		parent := &t.nodes[pix]
		if node.left() == null {
			rix := node.right()
			parent.set_link(pdir, rix)
			if rix != null {
				t.nodes[rix].set_parent(pix)
				if t.min == ix {
					t.min = rix
				}
			} else {
				if t.max == ix {
					t.max = pix
				}
				if t.min == ix {
					t.min = pix
				}
			}
		} else {
			lix := node.left()
			parent.set_link(pdir, lix)
			if lix != null {
				t.nodes[lix].set_parent(pix)
				if t.max == ix {
					t.max = lix
				}
			} else if t.max == ix {
				t.max = pix
			}
		}
	}
	if ix != len(t.nodes)-1 {
		jx := len(t.nodes) - 1
		data.Swap(ix, jx)
		inode, jnode := &t.nodes[ix], &t.nodes[jx]
		*inode, *jnode = *jnode, *inode
		t.fixlinks(inode, jx, ix)
		if next == jx {
			next = ix
		}
		if pix == jx {
			pix = ix
		}
	}
	t.nodes = t.nodes[:len(t.nodes)-1]
	t.balance(pix)
	return next
}

func (t *Tree) fixlinks(inode *node, i, j int) {
	if inode.parent() != null {
		parent := &t.nodes[inode.parent()]
		dir := direction(parent.right() == i)
		parent.set_link(dir, j)
	} else if t.root == i {
		t.root = j
	} else {
		panic("tree broken")
	}
	if inode.left() != null {
		lnode := &t.nodes[inode.left()]
		if lnode.parent() != i {
			panic("tree broken")
		}
		lnode.set_parent(j)
	} else if t.min == i {
		t.min = j
	}
	if inode.right() != null {
		rnode := &t.nodes[inode.right()]
		if rnode.parent() != i {
			panic("tree broken")
		}
		rnode.set_parent(j)
	} else if t.max == i {
		t.max = j
	}
}

func (t *Tree) balance(cur int) {
	for cur != null {
		node := &t.nodes[cur]
		lh, rh := t.height(node.left()), t.height(node.right())
		var dir direction
		if lh < rh-1 {
			dir = right
		} else if lh-1 > rh {
			dir = left
		} else {
			node.height = max_i8(lh, rh) + 1
			cur = node.parent()
			continue
		}
		chld := node.link(dir)
		chnode := &t.nodes[chld]
		hs := [2]int8{
			t.height(chnode.link(!dir)),
			t.height(chnode.link(dir))}
		if hs[1]-hs[0] < 0 {
			/* rotate child */
			t.rotate(chld, !dir)
		}
		t.rotate(cur, dir)
		cur = node.parent()
	}
}

// rotate tree node to direction
func (t *Tree) rotate(ix int, dir direction) {
	node := &t.nodes[ix]
	p := node.parent()
	ch := node.link(dir)
	if ch == null {
		panic("wrong rotation direction")
	}
	chnode := &t.nodes[ch]
	node.set_link(dir, chnode.link(!dir))
	if node.link(dir) != null {
		t.nodes[node.link(dir)].set_parent(ix)
	}
	chnode.set_link(!dir, ix)
	node.set_parent(ch)
	chnode.set_parent(p)
	t.fixheight(node)
	t.fixheight(chnode)
	if p != null {
		pnode := &t.nodes[p]
		pdir := direction(pnode.right() == ix)
		pnode.set_link(pdir, ch)
		t.fixheight(pnode)
	} else {
		t.root = ch
	}
}

func (t *Tree) fixheight(n *node) {
	lh, rh := t.height(n.left()), t.height(n.right())
	n.height = max_i8(lh, rh) + 1
}

func (t *Tree) height(ix int) int8 {
	if ix == null {
		return 0
	}
	return t.nodes[ix].height
}

func (t *Tree) dir(i, ipar int) direction {
	parent := &t.nodes[ipar]
	if parent.left() == i {
		return left
	} else if parent.right() == i {
		return right
	} else {
		panic("tree broken")
	}
}

func (t *Tree) bal(ix int) int8 {
	node := &t.nodes[ix]
	lh := t.height(node.left())
	rh := t.height(node.right())
	return lh - rh
}

func max_i8(i, j int8) int8 {
	if i < j {
		return j
	}
	return i
}
<commit_msg>DeleteAndPrev<commit_after>// tree provides balanced tree structure which acts as index
// to sort.Interface and could be used for searching like sort.Search
package tree

import "sort"
import "fmt"

var _ = fmt.Println

// Tree provides balanced tree structure
// which keeps order of is external sort.Interface
type Tree struct {
	root, min, max int
	nodes          []node
}

// Len returns number of indexed elements
func (t *Tree) Len() int {
	return len(t.nodes)
}

// Min returns index of minimum element
// panics if called on empty tree
func (t *Tree) Min() int {
	if len(t.nodes) == 0 {
		panic("Tree.Min should not be called on empty tree")
	}
	return t.min
}

// Max returns index of maximum element
// panics if called on empty tree
func (t *Tree) Max() int {
	if len(t.nodes) == 0 {
		panic("Tree.Max should not be called on empty tree")
	}
	return t.max
}

// Search returns first index for which predicate is true
// returns Len() if no element satisfies predicate
func (t *Tree) Search(pred func(i int) bool) int {
	if len(t.nodes) == 0 {
		return 0
	}
	now := t.root
	last_true := len(t.nodes)
	for {
		node := &t.nodes[now]
		if pred(now) {
			last_true = now
			if node.left() == null {
				return now
			}
			now = node.left()
		} else if node.right() == null {
			return last_true
		} else {
			now = node.right()
		}
	}
}

// SearchLast returns last index for which predicate is true
// returns -1 if no element satisfies predicate
func (t *Tree) SearchLast(pred func(i int) bool) int {
	if len(t.nodes) == 0 {
		return 0
	}
	now := t.root
	last_true := -1
	for {
		node := &t.nodes[now]
		if pred(now) {
			last_true = now
			if node.right() == null {
				return now
			}
			now = node.right()
		} else if node.left() == null {
			return last_true
		} else {
			now = node.left()
		}
	}
}

// Next returns index of next in-order element.
// if argument is -1, then return index of minimal element.
// returns t.Len() on finish.
func (t *Tree) Next(i int) int {
	if i > len(t.nodes) {
		panic("Tree index overflow")
	}
	if i == len(t.nodes) || i == t.max {
		return len(t.nodes)
	}
	if i == -1 {
		return t.min
	}
	node := &t.nodes[i]
	if node.right() != null {
		i = node.right()
		for t.nodes[i].left() != null {
			i = t.nodes[i].left()
		}
		return i
	}
	for node.parent() != null {
		pix := node.parent()
		dir := t.dir(i, pix)
		if dir == left {
			return pix
		}
		i, node = pix, &t.nodes[pix]
	}
	panic("tree broken")
}

// Prev returns index of previos in-order element.
// if argument is Tree.Len(), then return index of maximal element.
// returns -1 on finish.
func (t *Tree) Prev(i int) int {
	if i > len(t.nodes) {
		panic("Tree index overflow")
	}
	if i == -1 || i == t.min {
		return -1
	}
	if i == len(t.nodes) {
		return t.max
	}
	node := &t.nodes[i]
	if node.left() != null {
		i = node.left()
		for t.nodes[i].right() != null {
			i = t.nodes[i].right()
		}
		return i
	}
	for node.parent() != null {
		pix := node.parent()
		dir := t.dir(i, pix)
		if dir == right {
			return pix
		}
		i, node = pix, &t.nodes[pix]
	}
	panic("tree broken")
}

// Insert adds in-order element of sort.Interface at index Tree.Len()
// You should not put element with key equal to existed key.
func (t *Tree) Insert(data sort.Interface) {
	ix := len(t.nodes)
	t.nodes = append(t.nodes, node{null, null, null, 1})
	if ix == 0 {
		t.root, t.min, t.max = 0, 0, 0
		return
	}
	var dir direction
	cur := t.root
	curnode := &t.nodes[cur]
	for {
		dir = direction(data.Less(int(cur), ix))

		if curnode.link(dir) == null {
			break
		}
		cur = curnode.link(dir)
		curnode = &t.nodes[cur]
	}
	node := &t.nodes[ix]
	node.set_parent(cur)
	curnode.set_link(dir, ix)
	if dir == right {
		if cur == t.max {
			t.max = ix
		}
	} else if cur == t.min {
		t.min = ix
	}
	t.balance(cur)
}

// InsertBefore adds new element at specified position.
// It trust you and doesn't check insertion position
func (t *Tree) InsertBefore(data sort.Interface, cur int) {
	ix := len(t.nodes)
	dir := left
	if cur == len(t.nodes) {
		dir, cur = right, t.max
	}
	t.nodes = append(t.nodes, node{null, null, null, 1})
	if ix == 0 {
		if cur != 0 {
			panic("InsertBefore on empty tree accepts only 0")
		}
		t.root, t.min, t.max = 0, 0, 0
		return
	}
	curnode := &t.nodes[cur]
	node := &t.nodes[ix]
	node.set_parent(cur)
	curnode.set_link(dir, ix)
	if dir == right {
		if cur == t.max {
			t.max = ix
		}
	} else if cur == t.min {
		t.min = ix
	}
	t.balance(cur)
}

// Delete removes element from a tree and return index of next in-order element
func (t *Tree) Delete(data sort.Interface, ix int) int {
	if ix < 0 || ix >= len(t.nodes) {
		panic("Tree.Delete out of range")
	}
	if len(t.nodes) == 0 {
		t.nodes = t.nodes[:0]
		return 0
	}
	node := &t.nodes[ix]
	next := t.Next(ix)
	if node.left() != null && node.right() != null {
		data.Swap(ix, next)
		next, ix, node = ix, next, &t.nodes[next]
		/* at this moment order is temporary broken,
		   but it will be restored after complete */
	}
	return t.del(data, node, ix, next)
}

// DeleteAndPrev removes element from a tree and return index of next in-order element
func (t *Tree) DeleteAndPrev(data sort.Interface, ix int) int {
	if ix < 0 || ix >= len(t.nodes) {
		panic("Tree.Delete out of range")
	}
	if len(t.nodes) == 0 {
		t.nodes = t.nodes[:0]
		return 0
	}
	node := &t.nodes[ix]
	prev := t.Prev(ix)
	if node.left() != null && node.right() != null {
		data.Swap(ix, prev)
		prev, ix, node = ix, prev, &t.nodes[prev]
		/* at this moment order is temporary broken,
		   but it will be restored after complete */
	}
	return t.del(data, node, ix, prev)
}

func (t *Tree) del(data sort.Interface, node *node, ix, next int) int {
	pix := node.parent()
	if pix == null {
		if node.left() == null {
			rix := node.right()
			t.root = rix
			if rix != null {
				t.nodes[rix].set_parent(null)
			}
			if t.min == ix {
				t.min = rix
			}
		} else {
			lix := node.left()
			t.root = lix
			if lix != null {
				t.nodes[lix].set_parent(null)
			}
			if t.max == ix {
				t.max = lix
			}
		}
		pix = t.root
	} else {
		pdir := t.dir(ix, pix)
		parent := &t.nodes[pix]
		if node.left() == null {
			rix := node.right()
			parent.set_link(pdir, rix)
			if rix != null {
				t.nodes[rix].set_parent(pix)
				if t.min == ix {
					t.min = rix
				}
			} else {
				if t.max == ix {
					t.max = pix
				}
				if t.min == ix {
					t.min = pix
				}
			}
		} else {
			lix := node.left()
			parent.set_link(pdir, lix)
			if lix != null {
				t.nodes[lix].set_parent(pix)
				if t.max == ix {
					t.max = lix
				}
			} else if t.max == ix {
				t.max = pix
			}
		}
	}
	if ix != len(t.nodes)-1 {
		jx := len(t.nodes) - 1
		data.Swap(ix, jx)
		inode, jnode := &t.nodes[ix], &t.nodes[jx]
		*inode, *jnode = *jnode, *inode
		t.fixlinks(inode, jx, ix)
		if next == jx {
			next = ix
		}
		if pix == jx {
			pix = ix
		}
	}
	t.nodes = t.nodes[:len(t.nodes)-1]
	t.balance(pix)
	return next
}

func (t *Tree) fixlinks(inode *node, i, j int) {
	if inode.parent() != null {
		parent := &t.nodes[inode.parent()]
		dir := direction(parent.right() == i)
		parent.set_link(dir, j)
	} else if t.root == i {
		t.root = j
	} else {
		panic("tree broken")
	}
	if inode.left() != null {
		lnode := &t.nodes[inode.left()]
		if lnode.parent() != i {
			panic("tree broken")
		}
		lnode.set_parent(j)
	} else if t.min == i {
		t.min = j
	}
	if inode.right() != null {
		rnode := &t.nodes[inode.right()]
		if rnode.parent() != i {
			panic("tree broken")
		}
		rnode.set_parent(j)
	} else if t.max == i {
		t.max = j
	}
}

func (t *Tree) balance(cur int) {
	for cur != null {
		node := &t.nodes[cur]
		lh, rh := t.height(node.left()), t.height(node.right())
		var dir direction
		if lh < rh-1 {
			dir = right
		} else if lh-1 > rh {
			dir = left
		} else {
			node.height = max_i8(lh, rh) + 1
			cur = node.parent()
			continue
		}
		chld := node.link(dir)
		chnode := &t.nodes[chld]
		hs := [2]int8{
			t.height(chnode.link(!dir)),
			t.height(chnode.link(dir))}
		if hs[1]-hs[0] < 0 {
			/* rotate child */
			t.rotate(chld, !dir)
		}
		t.rotate(cur, dir)
		cur = node.parent()
	}
}

// rotate tree node to direction
func (t *Tree) rotate(ix int, dir direction) {
	node := &t.nodes[ix]
	p := node.parent()
	ch := node.link(dir)
	if ch == null {
		panic("wrong rotation direction")
	}
	chnode := &t.nodes[ch]
	node.set_link(dir, chnode.link(!dir))
	if node.link(dir) != null {
		t.nodes[node.link(dir)].set_parent(ix)
	}
	chnode.set_link(!dir, ix)
	node.set_parent(ch)
	chnode.set_parent(p)
	t.fixheight(node)
	t.fixheight(chnode)
	if p != null {
		pnode := &t.nodes[p]
		pdir := direction(pnode.right() == ix)
		pnode.set_link(pdir, ch)
		t.fixheight(pnode)
	} else {
		t.root = ch
	}
}

func (t *Tree) fixheight(n *node) {
	lh, rh := t.height(n.left()), t.height(n.right())
	n.height = max_i8(lh, rh) + 1
}

func (t *Tree) height(ix int) int8 {
	if ix == null {
		return 0
	}
	return t.nodes[ix].height
}

func (t *Tree) dir(i, ipar int) direction {
	parent := &t.nodes[ipar]
	if parent.left() == i {
		return left
	} else if parent.right() == i {
		return right
	} else {
		panic("tree broken")
	}
}

func (t *Tree) bal(ix int) int8 {
	node := &t.nodes[ix]
	lh := t.height(node.left())
	rh := t.height(node.right())
	return lh - rh
}

func max_i8(i, j int8) int8 {
	if i < j {
		return j
	}
	return i
}
<|endoftext|>


<commit_before>package openstack

import (
	"fmt"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/rackspace/gophercloud"
)

// CheckDeleted checks the error to see if it's a 404 (Not Found) and, if so,
// sets the resource ID to the empty string instead of throwing an error.
func CheckDeleted(d *schema.ResourceData, err error, msg string) error {
	errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
	if !ok {
		return fmt.Errorf("%s: %s", msg, err)
	}
	if errCode.Actual == 404 {
		d.SetId("")
		return nil
	}
	return fmt.Errorf("%s: %s", msg, err)
}
<commit_msg>provider/openstack: gophercloud migration: util<commit_after>package openstack

import (
	"fmt"

	"github.com/gophercloud/gophercloud"
	"github.com/hashicorp/terraform/helper/schema"
)

// CheckDeleted checks the error to see if it's a 404 (Not Found) and, if so,
// sets the resource ID to the empty string instead of throwing an error.
func CheckDeleted(d *schema.ResourceData, err error, msg string) error {
	errCode, ok := err.(*gophercloud.ErrUnexpectedResponseCode)
	if !ok {
		return fmt.Errorf("%s: %s", msg, err)
	}
	if errCode.Actual == 404 {
		d.SetId("")
		return nil
	}
	return fmt.Errorf("%s: %s", msg, err)
}
<|endoftext|>


<commit_before>package luar

import (
	"fmt"
	"unicode"
	"unicode/utf8"

	"github.com/yuin/gopher-lua"
)

func allTostring(L *lua.LState) int {
	ud := L.CheckUserData(1)
	value := ud.Value
	if stringer, ok := value.(fmt.Stringer); ok {
		L.Push(lua.LString(stringer.String()))
	} else {
		L.Push(lua.LString(fmt.Sprintf("userdata (luar): %p", ud)))
	}
	return 1
}

func getUnexportedName(name string) string {
	buf := []byte(name)
	first, n := utf8.DecodeRune(buf)
	if n == 0 {
		return name
	}
	return string(unicode.ToLower(first)) + string(buf[n:])
}

func getMethod(key string, mt *lua.LTable) lua.LValue {
	methods := mt.RawGetString("methods").(*lua.LTable)
	if fn := methods.RawGetString(key); fn != lua.LNil {
		return fn
	}
	return nil
}

func getPtrMethod(key string, mt *lua.LTable) lua.LValue {
	methods := mt.RawGetString("ptr_methods").(*lua.LTable)
	if fn := methods.RawGetString(key); fn != lua.LNil {
		return fn
	}
	return nil
}

func getFieldIndex(key string, mt *lua.LTable) []int {
	fields := mt.RawGetString("fields").(*lua.LTable)
	if index := fields.RawGetString(key); index != lua.LNil {
		return index.(*lua.LUserData).Value.([]int)
	}
	return nil
}
<commit_msg>simplify getUnexportedName<commit_after>package luar

import (
	"fmt"
	"unicode"
	"unicode/utf8"

	"github.com/yuin/gopher-lua"
)

func allTostring(L *lua.LState) int {
	ud := L.CheckUserData(1)
	value := ud.Value
	if stringer, ok := value.(fmt.Stringer); ok {
		L.Push(lua.LString(stringer.String()))
	} else {
		L.Push(lua.LString(fmt.Sprintf("userdata (luar): %p", ud)))
	}
	return 1
}

func getUnexportedName(name string) string {
	first, n := utf8.DecodeRuneInString(name)
	if n == 0 {
		return name
	}
	return string(unicode.ToLower(first)) + name[n:]
}

func getMethod(key string, mt *lua.LTable) lua.LValue {
	methods := mt.RawGetString("methods").(*lua.LTable)
	if fn := methods.RawGetString(key); fn != lua.LNil {
		return fn
	}
	return nil
}

func getPtrMethod(key string, mt *lua.LTable) lua.LValue {
	methods := mt.RawGetString("ptr_methods").(*lua.LTable)
	if fn := methods.RawGetString(key); fn != lua.LNil {
		return fn
	}
	return nil
}

func getFieldIndex(key string, mt *lua.LTable) []int {
	fields := mt.RawGetString("fields").(*lua.LTable)
	if index := fields.RawGetString(key); index != lua.LNil {
		return index.(*lua.LUserData).Value.([]int)
	}
	return nil
}
<|endoftext|>


<commit_before>package ow_stats

import (
	"regexp"
	"strings"
	"strconv"
	"log"
	"golang.org/x/text/transform"
	"golang.org/x/text/unicode/norm"
	"golang.org/x/text/runes"
	"unicode"
)

var spaceRegex = regexp.MustCompile(`[-\s]`)
var nonAlphaRegex = regexp.MustCompile(`\W`)
var normalizeRegex = regexp.MustCompile(`_{2,}`)
var hourRegex = regexp.MustCompile(`(?P<Val>[0-9]+) hours?`)
var minuteRegex = regexp.MustCompile(`(?P<Val>[0-9]+) minutes?`)
var secondRegex = regexp.MustCompile(`(?P<Val>[0-9]+(?:\.[0-9]+)?) seconds?`)
var percentRegex = regexp.MustCompile(`(?P<Val>[0-9]{1,3})\s?%`)
var pluralizerRegex = regexp.MustCompile(`(?P<Start>_|[^a-z]|^)(?P<Term>blow|boost|kill|assist|barrier|hit|multikill|elimination)(?P<End>$|[^a-z])`)

var t = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)

func SanitizeKey(text string) string {
	text = strings.ToLower(text)
	text, _, _ = transform.String(t, text)
	text = spaceRegex.ReplaceAllString(text, "_")
	text = nonAlphaRegex.ReplaceAllString(text, "")
	text = normalizeRegex.ReplaceAllString(text, "_")

	text = strings.Replace(text, "soldier_76", "soldier76", 1)

	return text
}

func SanitizeValue(text string) float32 {
	text = strings.ToLower(text)

	fnParseFloat := func(text string) (float32, error) {
		longNum := strings.Replace(text, ",", "", -1)
		v, err := strconv.ParseFloat(longNum, 32)
		if err != nil {
			return 0., err
		}

		return float32(v), nil
	}

	fnParseSimpleFloat32 := func(t string) float32 {
		if v, err := strconv.Atoi(t); err == nil {
			return float32(v)
		}

		return 0
	}

	if text == "--" {
		return .0
	}

	if v, err := fnParseFloat(text); err == nil {
		return float32(v)
	}

	// value is a percentage
	if m := percentRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v / 100.
		}

		log.Printf("Value is a percentage but failed to decode: %s\n", text)

		return 0
	}

	if strings.ContainsRune(text, ':') {
		parts := strings.Split(text, ":")

		var h, m, s float32
		switch len(parts) {
		case 3:
			h, m, s = fnParseSimpleFloat32(parts[0]), fnParseSimpleFloat32(parts[1]), fnParseSimpleFloat32(parts[2])
		case 2:
			m, s = fnParseSimpleFloat32(parts[0]), fnParseSimpleFloat32(parts[1])
		case 1:
			s = fnParseSimpleFloat32(parts[0])
		}

		return h + ((m + (s / 60.0)) / 60.0)
	}

	if m := hourRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v
		}

		log.Printf("Value is an hour but failed to decode: %s\n", text)

		return 0
	}

	if m := minuteRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v / 60.0
		}

		log.Printf("Value is a minute but failed to decode: %s\n", text)

		return 0
	}

	if m := secondRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v / 3600.0
		}

		log.Printf("Value is a second but failed to decode: %s\n", text)

		return 0

	}

	log.Printf("Unable to find anything to parse: %s\n", text)

	return 0
}

func Pluralizer(text string) string {
	text = strings.ToLower(text)
	text = pluralizerRegex.ReplaceAllString(text, `${1}${2}s${3}`)

	text = strings.Replace(text, "kills_streak_", "kill_streak_", 1)

	return text
}
<commit_msg>Fixed race exception on SanitizeKey<commit_after>package ow_stats

import (
	"regexp"
	"strings"
	"strconv"
	"log"
	"golang.org/x/text/transform"
	"golang.org/x/text/unicode/norm"
	"golang.org/x/text/runes"
	"unicode"
)

var spaceRegex = regexp.MustCompile(`[-\s]`)
var nonAlphaRegex = regexp.MustCompile(`\W`)
var normalizeRegex = regexp.MustCompile(`_{2,}`)
var hourRegex = regexp.MustCompile(`(?P<Val>[0-9]+) hours?`)
var minuteRegex = regexp.MustCompile(`(?P<Val>[0-9]+) minutes?`)
var secondRegex = regexp.MustCompile(`(?P<Val>[0-9]+(?:\.[0-9]+)?) seconds?`)
var percentRegex = regexp.MustCompile(`(?P<Val>[0-9]{1,3})\s?%`)
var pluralizerRegex = regexp.MustCompile(`(?P<Start>_|[^a-z]|^)(?P<Term>blow|boost|kill|assist|barrier|hit|multikill|elimination)(?P<End>$|[^a-z])`)

func SanitizeKey(text string) string {
	var t = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)

	text = strings.ToLower(text)
	text, _, _ = transform.String(t, text)
	text = spaceRegex.ReplaceAllString(text, "_")
	text = nonAlphaRegex.ReplaceAllString(text, "")
	text = normalizeRegex.ReplaceAllString(text, "_")

	text = strings.Replace(text, "soldier_76", "soldier76", 1)

	return text
}

func SanitizeValue(text string) float32 {
	text = strings.ToLower(text)

	fnParseFloat := func(text string) (float32, error) {
		longNum := strings.Replace(text, ",", "", -1)
		v, err := strconv.ParseFloat(longNum, 32)
		if err != nil {
			return 0., err
		}

		return float32(v), nil
	}

	fnParseSimpleFloat32 := func(t string) float32 {
		if v, err := strconv.Atoi(t); err == nil {
			return float32(v)
		}

		return 0
	}

	if text == "--" {
		return .0
	}

	if v, err := fnParseFloat(text); err == nil {
		return float32(v)
	}

	// value is a percentage
	if m := percentRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v / 100.
		}

		log.Printf("Value is a percentage but failed to decode: %s\n", text)

		return 0
	}

	if strings.ContainsRune(text, ':') {
		parts := strings.Split(text, ":")

		var h, m, s float32
		switch len(parts) {
		case 3:
			h, m, s = fnParseSimpleFloat32(parts[0]), fnParseSimpleFloat32(parts[1]), fnParseSimpleFloat32(parts[2])
		case 2:
			m, s = fnParseSimpleFloat32(parts[0]), fnParseSimpleFloat32(parts[1])
		case 1:
			s = fnParseSimpleFloat32(parts[0])
		}

		return h + ((m + (s / 60.0)) / 60.0)
	}

	if m := hourRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v
		}

		log.Printf("Value is an hour but failed to decode: %s\n", text)

		return 0
	}

	if m := minuteRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v / 60.0
		}

		log.Printf("Value is a minute but failed to decode: %s\n", text)

		return 0
	}

	if m := secondRegex.FindStringSubmatch(text); m != nil {
		if v, err := fnParseFloat(m[1]); err == nil {
			return v / 3600.0
		}

		log.Printf("Value is a second but failed to decode: %s\n", text)

		return 0

	}

	log.Printf("Unable to find anything to parse: %s\n", text)

	return 0
}

func Pluralizer(text string) string {
	text = strings.ToLower(text)
	text = pluralizerRegex.ReplaceAllString(text, `${1}${2}s${3}`)

	text = strings.Replace(text, "kills_streak_", "kill_streak_", 1)

	return text
}
<|endoftext|>