<commit_before>package model

import (
	"kmud/database"
	"sync"
	"time"
)

var fightsMutex sync.RWMutex

var fights map[*database.Character]*database.Character // Maps the attacker to the defender

func StartFight(attacker *database.Character, defender *database.Character) {
	fightsMutex.Lock()
	defer fightsMutex.Unlock()

	oldDefender, found := fights[attacker]

	if defender == oldDefender {
		return
	}

	if found {
		fightsMutex.Unlock()
		StopFight(attacker)
		fightsMutex.Lock()
	}

	fights[attacker] = defender

	queueEvent(CombatStartEvent{Attacker: attacker, Defender: defender})
}

func StopFight(attacker *database.Character) {
	fightsMutex.Lock()
	defer fightsMutex.Unlock()

	defender := fights[attacker]

	if defender != nil {
		delete(fights, attacker)
		queueEvent(CombatStopEvent{Attacker: attacker, Defender: defender})
	}
}

func combatLoop() {
	for {
		time.Sleep(3 * time.Second)

		fightsMutex.RLock()
		for a, d := range fights {
			if a.GetRoomId() == d.GetRoomId() {
				queueEvent(CombatEvent{Attacker: a, Defender: d, Damage: 10})
			} else {
				fightsMutex.RUnlock()
				StopFight(a)
				fightsMutex.RLock()
			}
		}
		fightsMutex.RUnlock()
	}
}

// vim: nocindent
<commit_msg>Make combat slightly more interesting<commit_after>package model

import (
	"kmud/database"
	"math/rand"
	"sync"
	"time"
)

var fightsMutex sync.RWMutex

var fights map[*database.Character]*database.Character // Maps the attacker to the defender

func StartFight(attacker *database.Character, defender *database.Character) {
	fightsMutex.Lock()
	defer fightsMutex.Unlock()

	oldDefender, found := fights[attacker]

	if defender == oldDefender {
		return
	}

	if found {
		fightsMutex.Unlock()
		StopFight(attacker)
		fightsMutex.Lock()
	}

	fights[attacker] = defender

	queueEvent(CombatStartEvent{Attacker: attacker, Defender: defender})
}

func StopFight(attacker *database.Character) {
	fightsMutex.Lock()
	defer fightsMutex.Unlock()

	defender := fights[attacker]

	if defender != nil {
		delete(fights, attacker)
		queueEvent(CombatStopEvent{Attacker: attacker, Defender: defender})
	}
}

func combatLoop() {
	for {
		time.Sleep(3 * time.Second)

		fightsMutex.RLock()
		for a, d := range fights {
			if a.GetRoomId() == d.GetRoomId() {
				dmg := rand.Int()%10 + 1
				queueEvent(CombatEvent{Attacker: a, Defender: d, Damage: dmg})
			} else {
				fightsMutex.RUnlock()
				StopFight(a)
				fightsMutex.RLock()
			}
		}
		fightsMutex.RUnlock()
	}
}

// vim: nocindent
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	"code.google.com/p/go.text/encoding/japanese"
	"code.google.com/p/go.text/transform"
)

func Dat(url string) {
	resp, err := http.Get(url)
	if err != nil {
		log.Fatalf("failed to fetch: %v, err: %v\n", url, err)
		return
	}
	defer resp.Body.Close()

	reader := transform.NewReader(resp.Body, japanese.ShiftJIS.NewDecoder())
	bufr := bufio.NewReader(reader)
	for {
		lineb, err := bufr.ReadString('\n')
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Fatalf("failed to read content. err: %v\n", err)
			return
		}
		line := string(lineb)
		fmt.Printf("line: %v\n", string(line))
	}
}

func DatQueue(dat chan string, done chan bool) {
	for {
		url, more := <-dat
		if more && url != "" {
			Dat(url)
		} else {
			done <- true
		}
	}
}

func main() {
	dat := make(chan string)
	done := make(chan bool)

	go DatQueue(dat, done)

	if len(os.Args) > 1 {
		for i := 1; i < len(os.Args); i++ {
			dat <- os.Args[i]
		}
	} else {
		in := bufio.NewReader(os.Stdin)
		for {
			input, err := in.ReadString('\n')
			if err != nil {
				break
			}
			dat <- input
		}
	}
	close(dat)

	<-done
}
<commit_msg>extract img url<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"

	"code.google.com/p/go.text/encoding/japanese"
	"code.google.com/p/go.text/transform"
)

var ImgUrlRegexp *regexp.Regexp = regexp.MustCompile("h?ttp://[0-9a-zA-Z/\\-.%]+?\\.(jpg|jpeg|gif|png)")

func Dat(url string) {
	resp, err := http.Get(url)
	if err != nil {
		log.Fatalf("failed to fetch: %v, err: %v\n", url, err)
		return
	}
	defer resp.Body.Close()

	reader := transform.NewReader(resp.Body, japanese.ShiftJIS.NewDecoder())
	bufr := bufio.NewReader(reader)
	for {
		lineb, err := bufr.ReadString('\n')
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Fatalf("failed to read content. err: %v\n", err)
			return
		}
		line := strings.Split(string(lineb), "<>")
		if len(line) >= 4 {
			body := line[3]
			matched := ImgUrlRegexp.FindAllString(body, -1)
			fmt.Println(matched)
		}
	}
}

func DatQueue(dat chan string, done chan bool) {
	for {
		url, more := <-dat
		if more && url != "" {
			Dat(url)
		} else {
			done <- true
		}
	}
}

func main() {
	dat := make(chan string)
	done := make(chan bool)

	go DatQueue(dat, done)

	if len(os.Args) > 1 {
		for i := 1; i < len(os.Args); i++ {
			dat <- os.Args[i]
		}
	} else {
		in := bufio.NewReader(os.Stdin)
		for {
			input, err := in.ReadString('\n')
			if err != nil {
				break
			}
			dat <- input
		}
	}
	close(dat)

	<-done
}
<|endoftext|>


<commit_before>package readline

import (
	"io"
	"os"
)

type Instance struct {
	Config    *Config
	Terminal  *Terminal
	Operation *Operation
}

type FdReader interface {
	io.Reader
	Fd() uintptr
}

type Config struct {
	// prompt supports ANSI escape sequence, so we can color some characters even in windows
	Prompt string

	// readline will persist historys to file where HistoryFile specified
	HistoryFile string
	// specify the max length of historys, it's 500 by default, set it to -1 to disable history
	HistoryLimit           int
	DisableAutoSaveHistory bool

	// AutoCompleter will called once user press TAB
	AutoComplete AutoCompleter

	// Any key press will pass to Listener
	// NOTE: Listener will be triggered by (nil, 0, 0) immediately
	Listener Listener

	// If VimMode is true, readline will in vim.insert mode by default
	VimMode bool

	InterruptPrompt string
	EOFPrompt       string

	Stdin  FdReader
	Stdout io.Writer
	Stderr io.Writer

	MaskRune rune

	UniqueEditLine bool

	// force use interactive even stdout is not a tty
	StdoutFd            int
	ForceUseInteractive bool

	// private fields
	inited    bool
	opHistory *opHistory
	opSearch  *opSearch
}

func (c *Config) useInteractive() bool {
	return c.ForceUseInteractive || IsTerminal(c.StdoutFd)
}

func (c *Config) Init() error {
	if c.inited {
		return nil
	}
	c.inited = true
	if c.Stdin == nil {
		c.Stdin = os.Stdin
	}
	if c.Stdout == nil {
		c.Stdout = Stdout
	}
	if c.Stderr == nil {
		c.Stderr = Stderr
	}
	if c.StdoutFd == 0 {
		c.StdoutFd = StdoutFd
	}
	if c.HistoryLimit == 0 {
		c.HistoryLimit = 500
	}

	if c.InterruptPrompt == "" {
		c.InterruptPrompt = "^C"
	} else if c.InterruptPrompt == "\n" {
		c.InterruptPrompt = ""
	}
	if c.EOFPrompt == "" {
		c.EOFPrompt = "^D"
	} else if c.EOFPrompt == "\n" {
		c.EOFPrompt = ""
	}

	return nil
}

func (c Config) Clone() *Config {
	c.opHistory = nil
	c.opSearch = nil
	return &c
}

func (c *Config) SetListener(f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)) {
	c.Listener = FuncListener(f)
}

func NewEx(cfg *Config) (*Instance, error) {
	t, err := NewTerminal(cfg)
	if err != nil {
		return nil, err
	}
	rl := t.Readline()
	return &Instance{
		Config:    cfg,
		Terminal:  t,
		Operation: rl,
	}, nil
}

func New(prompt string) (*Instance, error) {
	return NewEx(&Config{Prompt: prompt})
}

func (i *Instance) SetPrompt(s string) {
	i.Operation.SetPrompt(s)
}

func (i *Instance) SetMaskRune(r rune) {
	i.Operation.SetMaskRune(r)
}

// change hisotry persistence in runtime
func (i *Instance) SetHistoryPath(p string) {
	i.Operation.SetHistoryPath(p)
}

// readline will refresh automatic when write through Stdout()
func (i *Instance) Stdout() io.Writer {
	return i.Operation.Stdout()
}

// readline will refresh automatic when write through Stdout()
func (i *Instance) Stderr() io.Writer {
	return i.Operation.Stderr()
}

// switch VimMode in runtime
func (i *Instance) SetVimMode(on bool) {
	i.Operation.SetVimMode(on)
}

func (i *Instance) IsVimMode() bool {
	return i.Operation.IsEnableVimMode()
}

func (i *Instance) GenPasswordConfig() *Config {
	return i.Operation.GenPasswordConfig()
}

// we can generate a config by `i.GenPasswordConfig()`
func (i *Instance) ReadPasswordWithConfig(cfg *Config) ([]byte, error) {
	return i.Operation.PasswordWithConfig(cfg)
}

func (i *Instance) ReadPasswordEx(prompt string, l Listener) ([]byte, error) {
	return i.Operation.PasswordEx(prompt, l)
}

func (i *Instance) ReadPassword(prompt string) ([]byte, error) {
	return i.Operation.Password(prompt)
}

// err is one of (nil, io.EOF, readline.ErrInterrupt)
func (i *Instance) Readline() (string, error) {
	return i.Operation.String()
}

func (i *Instance) SaveHistory(content string) error {
	return i.Operation.SaveHistory(content)
}

// same as readline
func (i *Instance) ReadSlice() ([]byte, error) {
	return i.Operation.Slice()
}

// we must make sure that call Close() before process exit.
func (i *Instance) Close() error {
	if err := i.Terminal.Close(); err != nil {
		return err
	}
	i.Operation.Close()
	return nil
}

func (i *Instance) SetConfig(cfg *Config) *Config {
	if i.Config == cfg {
		return cfg
	}
	old := i.Config
	i.Config = cfg
	i.Operation.SetConfig(cfg)
	i.Terminal.SetConfig(cfg)
	return old
}

func (i *Instance) Refresh() {
	i.Operation.Refresh()
}
<commit_msg>disable interactive when stdin is not a tty<commit_after>package readline

import (
	"io"
	"os"
)

type Instance struct {
	Config    *Config
	Terminal  *Terminal
	Operation *Operation
}

type FdReader interface {
	io.Reader
	Fd() uintptr
}

type Config struct {
	// prompt supports ANSI escape sequence, so we can color some characters even in windows
	Prompt string

	// readline will persist historys to file where HistoryFile specified
	HistoryFile string
	// specify the max length of historys, it's 500 by default, set it to -1 to disable history
	HistoryLimit           int
	DisableAutoSaveHistory bool

	// AutoCompleter will called once user press TAB
	AutoComplete AutoCompleter

	// Any key press will pass to Listener
	// NOTE: Listener will be triggered by (nil, 0, 0) immediately
	Listener Listener

	// If VimMode is true, readline will in vim.insert mode by default
	VimMode bool

	InterruptPrompt string
	EOFPrompt       string

	Stdin  FdReader
	Stdout io.Writer
	Stderr io.Writer

	MaskRune rune

	UniqueEditLine bool

	// force use interactive even stdout is not a tty
	StdinFd             int
	StdoutFd            int
	ForceUseInteractive bool

	// private fields
	inited    bool
	opHistory *opHistory
	opSearch  *opSearch
}

func (c *Config) useInteractive() bool {
	if c.ForceUseInteractive {
		return true
	}
	return IsTerminal(c.StdoutFd) && IsTerminal(c.StdinFd)
}

func (c *Config) Init() error {
	if c.inited {
		return nil
	}
	c.inited = true
	if c.Stdin == nil {
		c.Stdin = os.Stdin
	}
	if c.Stdout == nil {
		c.Stdout = Stdout
	}
	if c.Stderr == nil {
		c.Stderr = Stderr
	}
	if c.StdinFd == 0 {
		c.StdinFd = StdinFd
	}
	if c.StdoutFd == 0 {
		c.StdoutFd = StdoutFd
	}
	if c.HistoryLimit == 0 {
		c.HistoryLimit = 500
	}

	if c.InterruptPrompt == "" {
		c.InterruptPrompt = "^C"
	} else if c.InterruptPrompt == "\n" {
		c.InterruptPrompt = ""
	}
	if c.EOFPrompt == "" {
		c.EOFPrompt = "^D"
	} else if c.EOFPrompt == "\n" {
		c.EOFPrompt = ""
	}

	return nil
}

func (c Config) Clone() *Config {
	c.opHistory = nil
	c.opSearch = nil
	return &c
}

func (c *Config) SetListener(f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)) {
	c.Listener = FuncListener(f)
}

func NewEx(cfg *Config) (*Instance, error) {
	t, err := NewTerminal(cfg)
	if err != nil {
		return nil, err
	}
	rl := t.Readline()
	return &Instance{
		Config:    cfg,
		Terminal:  t,
		Operation: rl,
	}, nil
}

func New(prompt string) (*Instance, error) {
	return NewEx(&Config{Prompt: prompt})
}

func (i *Instance) SetPrompt(s string) {
	i.Operation.SetPrompt(s)
}

func (i *Instance) SetMaskRune(r rune) {
	i.Operation.SetMaskRune(r)
}

// change hisotry persistence in runtime
func (i *Instance) SetHistoryPath(p string) {
	i.Operation.SetHistoryPath(p)
}

// readline will refresh automatic when write through Stdout()
func (i *Instance) Stdout() io.Writer {
	return i.Operation.Stdout()
}

// readline will refresh automatic when write through Stdout()
func (i *Instance) Stderr() io.Writer {
	return i.Operation.Stderr()
}

// switch VimMode in runtime
func (i *Instance) SetVimMode(on bool) {
	i.Operation.SetVimMode(on)
}

func (i *Instance) IsVimMode() bool {
	return i.Operation.IsEnableVimMode()
}

func (i *Instance) GenPasswordConfig() *Config {
	return i.Operation.GenPasswordConfig()
}

// we can generate a config by `i.GenPasswordConfig()`
func (i *Instance) ReadPasswordWithConfig(cfg *Config) ([]byte, error) {
	return i.Operation.PasswordWithConfig(cfg)
}

func (i *Instance) ReadPasswordEx(prompt string, l Listener) ([]byte, error) {
	return i.Operation.PasswordEx(prompt, l)
}

func (i *Instance) ReadPassword(prompt string) ([]byte, error) {
	return i.Operation.Password(prompt)
}

// err is one of (nil, io.EOF, readline.ErrInterrupt)
func (i *Instance) Readline() (string, error) {
	return i.Operation.String()
}

func (i *Instance) SaveHistory(content string) error {
	return i.Operation.SaveHistory(content)
}

// same as readline
func (i *Instance) ReadSlice() ([]byte, error) {
	return i.Operation.Slice()
}

// we must make sure that call Close() before process exit.
func (i *Instance) Close() error {
	if err := i.Terminal.Close(); err != nil {
		return err
	}
	i.Operation.Close()
	return nil
}

func (i *Instance) SetConfig(cfg *Config) *Config {
	if i.Config == cfg {
		return cfg
	}
	old := i.Config
	i.Config = cfg
	i.Operation.SetConfig(cfg)
	i.Terminal.SetConfig(cfg)
	return old
}

func (i *Instance) Refresh() {
	i.Operation.Refresh()
}
<|endoftext|>


<commit_before>package cypress

import (
	"net"
	"runtime"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/vektra/neko"
)

func TestTCPSend(t *testing.T) {
	n := neko.Start(t)

	n.It("sends logs across to a server", func() {
		l, err := net.Listen("tcp", ":0")
		require.NoError(t, err)

		defer l.Close()

		var recvMesg *Message

		var wg sync.WaitGroup

		wg.Add(1)
		go func() {
			defer wg.Done()

			c, err := l.Accept()
			require.NoError(t, err)

			recv, err := NewRecv(c)

			recvMesg, err = recv.Generate()
		}()

		m := Log()
		m.Add("hello", "world")

		tcp, err := NewTCPSend(l.Addr().String(), 0, 0)
		require.NoError(t, err)

		defer tcp.Close()

		err = tcp.Receive(m)
		require.NoError(t, err)

		wg.Wait()

		assert.Equal(t, m, recvMesg)
	})

	n.It("uses a window to increase throughput", func() {
		time.Sleep(1 * time.Second)

		l, err := net.Listen("tcp", ":0")
		require.NoError(t, err)

		defer l.Close()

		var wg sync.WaitGroup

		latch := make(chan bool)

		wg.Add(1)
		go func() {
			defer wg.Done()

			c, err := l.Accept()
			require.NoError(t, err)

			defer c.Close()

			recv, err := NewRecv(c)
			require.NoError(t, err)

			<-latch

			_, err = recv.Generate()
			require.NoError(t, err)

			latch <- true
			<-latch
		}()

		m := Log()
		m.Add("hello", "world")

		tcp, err := NewTCPSend(l.Addr().String(), 0, 0)
		require.NoError(t, err)

		defer tcp.Close()

		err = tcp.Receive(m)
		require.NoError(t, err)

		err = tcp.Receive(m)
		require.NoError(t, err)

		runtime.Gosched()

		assert.Equal(t, 2, tcp.outstanding)

		latch <- true
		<-latch

		time.Sleep(100 * time.Millisecond)

		assert.Equal(t, 1, tcp.outstanding)

		latch <- true
		wg.Wait()

		runtime.Gosched()

		assert.Equal(t, 1, tcp.outstanding)
	})

	n.It("send nack'd messages once reconnected", func() {
		time.Sleep(1 * time.Second)

		l, err := net.Listen("tcp", ":0")
		require.NoError(t, err)

		defer l.Close()

		var recvMesg *Message
		var wg sync.WaitGroup

		latch := make(chan bool)

		wg.Add(1)
		go func() {
			defer wg.Done()

			c, err := l.Accept()
			require.NoError(t, err)

			defer c.Close()

			recv, err := NewRecv(c)
			require.NoError(t, err)

			<-latch

			_, err = recv.Generate()
			require.NoError(t, err)

			c.Close()

			c, err = l.Accept()
			require.NoError(t, err)

			defer c.Close()

			recv, err = NewRecv(c)
			require.NoError(t, err)

			recvMesg, err = recv.Generate()
			require.NoError(t, err)

			latch <- true
		}()

		m := Log()
		m.Add("hello", "world")

		tcp, err := NewTCPSend(l.Addr().String(), 0, 0)
		require.NoError(t, err)

		defer tcp.Close()

		err = tcp.Receive(m)
		require.NoError(t, err)

		m2 := Log()
		m2.Add("hello", "world")

		err = tcp.Receive(m2)
		require.NoError(t, err)

		latch <- true

		select {
		case <-time.Tick(100 * time.Millisecond):
			t.Fatal("didn't generate a new message")
		case <-latch:
			// ok
		}

		wg.Wait()

		assert.Equal(t, m2, recvMesg)
	})

	n.Meow()
}
<commit_msg>Try to fix test timing (I hate these kinds of fixes)<commit_after>package cypress

import (
	"net"
	"runtime"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/vektra/neko"
)

func TestTCPSend(t *testing.T) {
	n := neko.Start(t)

	n.It("sends logs across to a server", func() {
		l, err := net.Listen("tcp", ":0")
		require.NoError(t, err)

		defer l.Close()

		var recvMesg *Message

		var wg sync.WaitGroup

		wg.Add(1)
		go func() {
			defer wg.Done()

			c, err := l.Accept()
			require.NoError(t, err)

			recv, err := NewRecv(c)

			recvMesg, err = recv.Generate()
		}()

		m := Log()
		m.Add("hello", "world")

		tcp, err := NewTCPSend(l.Addr().String(), 0, 0)
		require.NoError(t, err)

		defer tcp.Close()

		err = tcp.Receive(m)
		require.NoError(t, err)

		wg.Wait()

		assert.Equal(t, m, recvMesg)
	})

	n.It("uses a window to increase throughput", func() {
		time.Sleep(1 * time.Second)

		l, err := net.Listen("tcp", ":0")
		require.NoError(t, err)

		defer l.Close()

		var wg sync.WaitGroup

		latch := make(chan bool)

		wg.Add(1)
		go func() {
			defer wg.Done()

			c, err := l.Accept()
			require.NoError(t, err)

			defer c.Close()

			recv, err := NewRecv(c)
			require.NoError(t, err)

			<-latch

			_, err = recv.Generate()
			require.NoError(t, err)

			latch <- true
			<-latch
		}()

		m := Log()
		m.Add("hello", "world")

		tcp, err := NewTCPSend(l.Addr().String(), 0, 0)
		require.NoError(t, err)

		defer tcp.Close()

		err = tcp.Receive(m)
		require.NoError(t, err)

		err = tcp.Receive(m)
		require.NoError(t, err)

		runtime.Gosched()

		assert.Equal(t, 2, tcp.outstanding)

		latch <- true
		<-latch

		time.Sleep(100 * time.Millisecond)

		assert.Equal(t, 1, tcp.outstanding)

		latch <- true
		wg.Wait()

		time.Sleep(100 * time.Millisecond)

		assert.Equal(t, 1, tcp.outstanding)
	})

	n.It("send nack'd messages once reconnected", func() {
		time.Sleep(1 * time.Second)

		l, err := net.Listen("tcp", ":0")
		require.NoError(t, err)

		defer l.Close()

		var recvMesg *Message
		var wg sync.WaitGroup

		latch := make(chan bool)

		wg.Add(1)
		go func() {
			defer wg.Done()

			c, err := l.Accept()
			require.NoError(t, err)

			defer c.Close()

			recv, err := NewRecv(c)
			require.NoError(t, err)

			<-latch

			_, err = recv.Generate()
			require.NoError(t, err)

			c.Close()

			c, err = l.Accept()
			require.NoError(t, err)

			defer c.Close()

			recv, err = NewRecv(c)
			require.NoError(t, err)

			recvMesg, err = recv.Generate()
			require.NoError(t, err)

			latch <- true
		}()

		m := Log()
		m.Add("hello", "world")

		tcp, err := NewTCPSend(l.Addr().String(), 0, 0)
		require.NoError(t, err)

		defer tcp.Close()

		err = tcp.Receive(m)
		require.NoError(t, err)

		m2 := Log()
		m2.Add("hello", "world")

		err = tcp.Receive(m2)
		require.NoError(t, err)

		latch <- true

		select {
		case <-time.Tick(100 * time.Millisecond):
			t.Fatal("didn't generate a new message")
		case <-latch:
			// ok
		}

		wg.Wait()

		assert.Equal(t, m2, recvMesg)
	})

	n.Meow()
}
<|endoftext|>


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

package mvcc

import (
	"errors"
	"sync"

	"github.com/coreos/etcd/mvcc/mvccpb"
)

var (
	ErrWatcherNotExist = errors.New("mvcc: watcher does not exist")
)

type WatchID int64

type WatchStream interface {
	// Watch creates a watcher. The watcher watches the events happening or
	// happened on the given key or range [key, end) from the given startRev.
	//
	// The whole event history can be watched unless compacted.
	// If `startRev` <=0, watch observes events after currentRev.
	//
	// The returned `id` is the ID of this watcher. It appears as WatchID
	// in events that are sent to the created watcher through stream channel.
	//
	Watch(key, end []byte, startRev int64) WatchID

	// Chan returns a chan. All watch response will be sent to the returned chan.
	Chan() <-chan WatchResponse

	// RequestProgress requests the progress of the watcher with given ID. The response
	// will only be sent if the watcher is currently synced.
	// The responses will be sent through the WatchRespone Chan attached
	// with this stream to ensure correct ordering.
	// The responses contains no events. The revision in the response is the progress
	// of the watchers since the watcher is currently synced.
	RequestProgress(id WatchID)

	// Cancel cancels a watcher by giving its ID. If watcher does not exist, an error will be
	// returned.
	Cancel(id WatchID) error

	// Close closes Chan and release all related resources.
	Close()

	// Rev returns the current revision of the KV the stream watches on.
	Rev() int64
}

type WatchResponse struct {
	// WatchID is the WatchID of the watcher this response sent to.
	WatchID WatchID

	// Events contains all the events that needs to send.
	Events []mvccpb.Event

	// Revision is the revision of the KV when the watchResponse is created.
	// For a normal response, the revision should be the same as the last
	// modified revision inside Events. For a delayed response to a unsynced
	// watcher, the revision is greater than the last modified revision
	// inside Events.
	Revision int64

	// CompactRevision is set when the watcher is cancelled due to compaction.
	CompactRevision int64
}

// watchStream contains a collection of watchers that share
// one streaming chan to send out watched events and other control events.
type watchStream struct {
	watchable watchable
	ch        chan WatchResponse

	mu sync.Mutex // guards fields below it
	// nextID is the ID pre-allocated for next new watcher in this stream
	nextID   WatchID
	closed   bool
	cancels  map[WatchID]cancelFunc
	watchers map[WatchID]*watcher
}

// Watch creates a new watcher in the stream and returns its WatchID.
// TODO: return error if ws is closed?
func (ws *watchStream) Watch(key, end []byte, startRev int64) WatchID {
	ws.mu.Lock()
	defer ws.mu.Unlock()
	if ws.closed {
		return -1
	}

	id := ws.nextID
	ws.nextID++

	w, c := ws.watchable.watch(key, end, startRev, id, ws.ch)

	ws.cancels[id] = c
	ws.watchers[id] = w
	return id
}

func (ws *watchStream) Chan() <-chan WatchResponse {
	return ws.ch
}

func (ws *watchStream) Cancel(id WatchID) error {
	cancel, ok := ws.cancels[id]
	if !ok {
		return ErrWatcherNotExist
	}
	cancel()
	delete(ws.cancels, id)
	delete(ws.watchers, id)
	return nil
}

func (ws *watchStream) Close() {
	ws.mu.Lock()
	defer ws.mu.Unlock()

	for _, cancel := range ws.cancels {
		cancel()
	}
	ws.closed = true
	close(ws.ch)
	watchStreamGauge.Dec()
}

func (ws *watchStream) Rev() int64 {
	ws.mu.Lock()
	defer ws.mu.Unlock()
	return ws.watchable.rev()
}

func (ws *watchStream) RequestProgress(id WatchID) {
	ws.mu.Lock()
	w, ok := ws.watchers[id]
	ws.mu.Unlock()
	if !ok {
		return
	}
	ws.watchable.progress(w)
}
<commit_msg>mvcc: don't cancel watcher if stream is already closed<commit_after>// Copyright 2015 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mvcc

import (
	"errors"
	"sync"

	"github.com/coreos/etcd/mvcc/mvccpb"
)

var (
	ErrWatcherNotExist = errors.New("mvcc: watcher does not exist")
)

type WatchID int64

type WatchStream interface {
	// Watch creates a watcher. The watcher watches the events happening or
	// happened on the given key or range [key, end) from the given startRev.
	//
	// The whole event history can be watched unless compacted.
	// If `startRev` <=0, watch observes events after currentRev.
	//
	// The returned `id` is the ID of this watcher. It appears as WatchID
	// in events that are sent to the created watcher through stream channel.
	//
	Watch(key, end []byte, startRev int64) WatchID

	// Chan returns a chan. All watch response will be sent to the returned chan.
	Chan() <-chan WatchResponse

	// RequestProgress requests the progress of the watcher with given ID. The response
	// will only be sent if the watcher is currently synced.
	// The responses will be sent through the WatchRespone Chan attached
	// with this stream to ensure correct ordering.
	// The responses contains no events. The revision in the response is the progress
	// of the watchers since the watcher is currently synced.
	RequestProgress(id WatchID)

	// Cancel cancels a watcher by giving its ID. If watcher does not exist, an error will be
	// returned.
	Cancel(id WatchID) error

	// Close closes Chan and release all related resources.
	Close()

	// Rev returns the current revision of the KV the stream watches on.
	Rev() int64
}

type WatchResponse struct {
	// WatchID is the WatchID of the watcher this response sent to.
	WatchID WatchID

	// Events contains all the events that needs to send.
	Events []mvccpb.Event

	// Revision is the revision of the KV when the watchResponse is created.
	// For a normal response, the revision should be the same as the last
	// modified revision inside Events. For a delayed response to a unsynced
	// watcher, the revision is greater than the last modified revision
	// inside Events.
	Revision int64

	// CompactRevision is set when the watcher is cancelled due to compaction.
	CompactRevision int64
}

// watchStream contains a collection of watchers that share
// one streaming chan to send out watched events and other control events.
type watchStream struct {
	watchable watchable
	ch        chan WatchResponse

	mu sync.Mutex // guards fields below it
	// nextID is the ID pre-allocated for next new watcher in this stream
	nextID   WatchID
	closed   bool
	cancels  map[WatchID]cancelFunc
	watchers map[WatchID]*watcher
}

// Watch creates a new watcher in the stream and returns its WatchID.
// TODO: return error if ws is closed?
func (ws *watchStream) Watch(key, end []byte, startRev int64) WatchID {
	ws.mu.Lock()
	defer ws.mu.Unlock()
	if ws.closed {
		return -1
	}

	id := ws.nextID
	ws.nextID++

	w, c := ws.watchable.watch(key, end, startRev, id, ws.ch)

	ws.cancels[id] = c
	ws.watchers[id] = w
	return id
}

func (ws *watchStream) Chan() <-chan WatchResponse {
	return ws.ch
}

func (ws *watchStream) Cancel(id WatchID) error {
	ws.mu.Lock()
	cancel, ok := ws.cancels[id]
	ok = ok && !ws.closed
	if ok {
		delete(ws.cancels, id)
		delete(ws.watchers, id)
	}
	ws.mu.Unlock()
	if !ok {
		return ErrWatcherNotExist
	}
	cancel()
	return nil
}

func (ws *watchStream) Close() {
	ws.mu.Lock()
	defer ws.mu.Unlock()

	for _, cancel := range ws.cancels {
		cancel()
	}
	ws.closed = true
	close(ws.ch)
	watchStreamGauge.Dec()
}

func (ws *watchStream) Rev() int64 {
	ws.mu.Lock()
	defer ws.mu.Unlock()
	return ws.watchable.rev()
}

func (ws *watchStream) RequestProgress(id WatchID) {
	ws.mu.Lock()
	w, ok := ws.watchers[id]
	ws.mu.Unlock()
	if !ok {
		return
	}
	ws.watchable.progress(w)
}
<|endoftext|>


<commit_before>package spcdb

import (
	"database/sql"
	"fmt"
	_ "github.com/lib/pq"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"time"
	"unicode"
	//"github.com/mitchellh/mapstructure"
)

type DBMediator interface {
	DB() *DB
}

type DB struct {
	*sql.DB
}

func Open(driverName, dataSourceName string) (*DB, error) {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	return &DB{db}, nil
}

type Record interface {
	Get(key string) interface{}
	GetRaw(key string) *reflect.Value
	GetInString(key string) string
	Each(func(key string, value reflect.Value))
	Merge(r Record)
}

type record struct {
	raw map[string]reflect.Value
	m   sync.RWMutex
}

func mapToMap(recMap reflect.Value, recType reflect.Type, dst map[string]reflect.Value) {
	// TODO
}

func mapToStruct(valStruct reflect.Value, typeStruct reflect.Type, dst map[string]reflect.Value) {
	for i := 0; i < typeStruct.NumField(); i++ {
		typeField := typeStruct.Field(i)
		if !unicode.IsUpper(rune(typeField.Name[0])) {
			continue
		}

		recName := typeField.Tag.Get("record")
		if recName == "" {
			if typeField.Anonymous {
				continue
			}
			recName = typeField.Name
		} else if recName == "-" {
			continue
		}

		structField := valStruct.Field(i)
		if !structField.IsValid() || !structField.CanInterface() {
			continue
		}
		dst[recName] = structField
	}
}

func mapTo(recObj reflect.Value, dst map[string]reflect.Value) {
	if recObj.Kind() == reflect.Ptr {
		recObj = recObj.Elem()
	}
	typeObj := recObj.Type()

	switch typeObj.Kind() {
		case reflect.Struct:
			mapToStruct(recObj, typeObj, dst)
		case reflect.Map:
			mapToMap(recObj, typeObj, dst)
	}
}

func NewRecord(mapToObj ...interface{}) Record {
	rec := &record{
		raw: make(map[string]reflect.Value),
	}
	for _, val := range mapToObj {
		if val == nil {
			continue
		}
		obj := normalizeValue(reflect.ValueOf(val))
		mapTo(obj, rec.raw)
	}
	return rec
}

func (r *record) String() string {
	if r == nil {
		return ""
	}
    s := make([]string, len(r.raw))
    s = append(s, "Record[")
	for key, _ := range r.raw {
        s = append(s, fmt.Sprintf("\"%s\":\"%s\"", key, r.GetInString(key)))
	}
	return "Record[" + strings.Join(s, ", ") + "]"
}

func (r *record) Get(key string) interface{} {
	if r == nil {
		return nil
	}
	r.m.RLock()
	defer r.m.RUnlock()
	if el, ok := r.raw[key]; ok && el.IsValid() {
		return el.Interface()
	}
	return nil
}

func (r *record) GetRaw(key string) *reflect.Value {
	if r == nil {
		return nil
	}
	r.m.RLock()
	defer r.m.RUnlock()
	el, ok := r.raw[key]
	if !ok {
		return nil
	}
	return &el
}

func (r *record) GetInString(key string) string {
	if r == nil {
		return ""
	}
	r.m.RLock()
	defer r.m.RUnlock()
	el, ok := r.raw[key]
	if !ok || !el.IsValid() {
		return ""
	}

	var str string
	//mapstructure.WeakDecode(el.Interface(), &str)
	//return str
	switch s := el.Interface().(type) {
	case string:
		str = s
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		str = fmt.Sprintf("%d", s)
	case []byte:
		str = string(s[:])
	case bool:
		str = strconv.FormatBool(s)
	case time.Time:
		str = s.Format("2006-01-02 15:04:05")
	default:
		str = fmt.Sprintf("%v", el.Interface())
	}

	return str
}

func (r *record) Each(fn func(key string, value reflect.Value)) {
	if r == nil {
		return
	}
	r.m.RLock()
	defer r.m.RUnlock()
	for key, value := range r.raw {
		fn(key, value)
	}
}

func (r *record) Merge(r2 Record) {
	if r == nil || r2 == nil {
		return
	}
	r.m.Lock()
	defer r.m.Unlock()
	r2.Each(func(key string, value reflect.Value) {
		r.raw[key] = value
	})
}

func normalizeValue(value reflect.Value) reflect.Value {
	k := value.Kind()
	if k == reflect.Interface || k == reflect.Ptr {
		return normalizeValue(value.Elem())
	}
	return value
}

func (db *DB) ExistsRecord(query string, args ...interface{}) error {
	rows, err := db.Query(query, args...)
	if err != nil {
		return err
	}
	defer rows.Close()
	if !rows.Next() {
		return sql.ErrNoRows
	}
	return nil
}

func newRecord(rows *sql.Rows, cols []string) Record {
	/*
		ptrs := make([]interface{}, len(cols))
		cont := make([]string, len(cols))
		for i, _ := range ptrs {
			ptrs[i] = &cont[i]
		}
		rows.Scan(ptrs...)
	*/
	pointers := make([]interface{}, len(cols))
	container := make(map[string]interface{}, len(cols))
	for i, _ := range pointers {
		var v interface{}
		container[cols[i]] = &v
		pointers[i] = &v
	}
	rows.Scan(pointers...)

	rec := record{raw: make(map[string]reflect.Value, len(cols))}
	for key, value := range container {
		rec.raw[key] = reflect.Indirect(reflect.ValueOf(value)).Elem()
	}
	return &rec
}

func (db *DB) QueryRecord(query string, args ...interface{}) (Record, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	if !rows.Next() {
		return nil, sql.ErrNoRows
	}

	cols, _ := rows.Columns()
	return newRecord(rows, cols), err
}

func (db *DB) QueryRecords(query string, args ...interface{}) ([]Record, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	cols, _ := rows.Columns()
	ret := make([]Record, 0, 10)
	for rows.Next() {
		ret = append(ret, newRecord(rows, cols))
	}
	return ret, err
}
<commit_msg>fix debug mode<commit_after>package spcdb

import (
	"database/sql"
	"fmt"
	_ "github.com/lib/pq"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"time"
	"unicode"
	//"github.com/mitchellh/mapstructure"
)

type DBMediator interface {
	DB() *DB
}

type DB struct {
	*sql.DB
}

func Open(driverName, dataSourceName string) (*DB, error) {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	return &DB{db}, nil
}

type Record interface {
	Get(key string) interface{}
	GetRaw(key string) *reflect.Value
	GetInString(key string) string
	Each(func(key string, value reflect.Value))
	Merge(r Record)
}

type record struct {
	raw map[string]reflect.Value
	m   sync.RWMutex
}

func mapToMap(recMap reflect.Value, recType reflect.Type, dst map[string]reflect.Value) {
	// TODO
}

func mapToStruct(valStruct reflect.Value, typeStruct reflect.Type, dst map[string]reflect.Value) {
	for i := 0; i < typeStruct.NumField(); i++ {
		typeField := typeStruct.Field(i)
		if !unicode.IsUpper(rune(typeField.Name[0])) {
			continue
		}

		recName := typeField.Tag.Get("record")
		if recName == "" {
			if typeField.Anonymous {
				continue
			}
			recName = typeField.Name
		} else if recName == "-" {
			continue
		}

		structField := valStruct.Field(i)
		if !structField.IsValid() || !structField.CanInterface() {
			continue
		}
		dst[recName] = structField
	}
}

func mapTo(recObj reflect.Value, dst map[string]reflect.Value) {
	if recObj.Kind() == reflect.Ptr {
		recObj = recObj.Elem()
	}
	typeObj := recObj.Type()

	switch typeObj.Kind() {
		case reflect.Struct:
			mapToStruct(recObj, typeObj, dst)
		case reflect.Map:
			mapToMap(recObj, typeObj, dst)
	}
}

func NewRecord(mapToObj ...interface{}) Record {
	rec := &record{
		raw: make(map[string]reflect.Value),
	}
	for _, val := range mapToObj {
		if val == nil {
			continue
		}
		obj := normalizeValue(reflect.ValueOf(val))
		mapTo(obj, rec.raw)
	}
	return rec
}

func (r *record) String() string {
	if r == nil {
		return ""
	}
    s := make([]string, 0, len(r.raw))
	for key, _ := range r.raw {
        s = append(s, fmt.Sprintf("\"%s\":\"%s\"", key, r.GetInString(key)))
	}
	return "Record[" + strings.Join(s, ", ") + "]"
}

func (r *record) Get(key string) interface{} {
	if r == nil {
		return nil
	}
	r.m.RLock()
	defer r.m.RUnlock()
	if el, ok := r.raw[key]; ok && el.IsValid() {
		return el.Interface()
	}
	return nil
}

func (r *record) GetRaw(key string) *reflect.Value {
	if r == nil {
		return nil
	}
	r.m.RLock()
	defer r.m.RUnlock()
	el, ok := r.raw[key]
	if !ok {
		return nil
	}
	return &el
}

func (r *record) GetInString(key string) string {
	if r == nil {
		return ""
	}
	r.m.RLock()
	defer r.m.RUnlock()
	el, ok := r.raw[key]
	if !ok || !el.IsValid() {
		return ""
	}

	var str string
	//mapstructure.WeakDecode(el.Interface(), &str)
	//return str
	switch s := el.Interface().(type) {
	case string:
		str = s
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		str = fmt.Sprintf("%d", s)
	case []byte:
		str = string(s[:])
	case bool:
		str = strconv.FormatBool(s)
	case time.Time:
		str = s.Format("2006-01-02 15:04:05")
	default:
		str = fmt.Sprintf("%v", el.Interface())
	}

	return str
}

func (r *record) Each(fn func(key string, value reflect.Value)) {
	if r == nil {
		return
	}
	r.m.RLock()
	defer r.m.RUnlock()
	for key, value := range r.raw {
		fn(key, value)
	}
}

func (r *record) Merge(r2 Record) {
	if r == nil || r2 == nil {
		return
	}
	r.m.Lock()
	defer r.m.Unlock()
	r2.Each(func(key string, value reflect.Value) {
		r.raw[key] = value
	})
}

func normalizeValue(value reflect.Value) reflect.Value {
	k := value.Kind()
	if k == reflect.Interface || k == reflect.Ptr {
		return normalizeValue(value.Elem())
	}
	return value
}

func (db *DB) ExistsRecord(query string, args ...interface{}) error {
	rows, err := db.Query(query, args...)
	if err != nil {
		return err
	}
	defer rows.Close()
	if !rows.Next() {
		return sql.ErrNoRows
	}
	return nil
}

func newRecord(rows *sql.Rows, cols []string) Record {
	/*
		ptrs := make([]interface{}, len(cols))
		cont := make([]string, len(cols))
		for i, _ := range ptrs {
			ptrs[i] = &cont[i]
		}
		rows.Scan(ptrs...)
	*/
	pointers := make([]interface{}, len(cols))
	container := make(map[string]interface{}, len(cols))
	for i, _ := range pointers {
		var v interface{}
		container[cols[i]] = &v
		pointers[i] = &v
	}
	rows.Scan(pointers...)

	rec := record{raw: make(map[string]reflect.Value, len(cols))}
	for key, value := range container {
		rec.raw[key] = reflect.Indirect(reflect.ValueOf(value)).Elem()
	}
	return &rec
}

func (db *DB) QueryRecord(query string, args ...interface{}) (Record, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	if !rows.Next() {
		return nil, sql.ErrNoRows
	}

	cols, _ := rows.Columns()
	return newRecord(rows, cols), err
}

func (db *DB) QueryRecords(query string, args ...interface{}) ([]Record, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	cols, _ := rows.Columns()
	ret := make([]Record, 0, 10)
	for rows.Next() {
		ret = append(ret, newRecord(rows, cols))
	}
	return ret, err
}
<|endoftext|>


<commit_before>package configo

import (
	"github.com/asaskevich/govalidator"
	"github.com/shafreeck/toml"
	"github.com/shafreeck/toml/ast"

	"fmt"
	"net"
	"reflect"
	"strconv"
	"strings"
	"unicode"
)

const (
	fieldTagName = "cfg"
)

func init() {
	toml.SetValue = fieldValidate
	govalidator.TagMap["netaddr"] = func(addr string) bool {
		if h, p, err := net.SplitHostPort(addr); err == nil {
			if h != "" && !(govalidator.IsDNSName(h) || govalidator.IsIP(h)) {
				return false
			}
			if p != "" && !govalidator.IsPort(p) {
				return true
			}
			return true
		}
		return false
	}
}

func fieldValidate(field string, rv reflect.Value, av ast.Value, tag *toml.CfgTag) error {
	if tag == nil {
		return nil
	}
	val, ok := av.(*ast.String)
	if tag.Check != "" && ok {
		rules := strings.Split(tag.Check, " ")
		return validate(field, val.Value, rules)
	}
	return nil
}
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.String, reflect.Array:
		return v.Len() == 0
	case reflect.Map, reflect.Slice:
		return v.Len() == 0 || v.IsNil()
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
}

func extractTag(tag string) *toml.CfgTag {
	tags := strings.SplitN(tag, ",", 4)
	cfg := &toml.CfgTag{}
	switch c := len(tags); c {
	case 1:
		cfg.Name = strings.TrimSpace(tags[0])
	case 2:
		cfg.Name = strings.TrimSpace(tags[0])
		cfg.Value = strings.TrimSpace(tags[1])
	case 3:
		cfg.Name = strings.TrimSpace(tags[0])
		cfg.Value = strings.TrimSpace(tags[1])
		cfg.Check = strings.TrimSpace(tags[2])
	case 4:
		cfg.Name = strings.TrimSpace(tags[0])
		cfg.Value = strings.TrimSpace(tags[1])
		cfg.Check = strings.TrimSpace(tags[2])
		cfg.Description = strings.TrimSpace(tags[3])
	default:
		return nil
	}
	return cfg
}

func validate(key, value string, rules []string) error {
	for _, rule := range rules {
		validate, ok := govalidator.TagMap[rule]
		if !ok {
			return fmt.Errorf("validate rule %q is not supported", rule)
			continue
		}
		if !validate(value) {
			return fmt.Errorf("value of %q validate failed, %q does not match rule %q", key, value, rule)
		}
	}
	return nil
}

//parse a toml array
func unmarshalArray(key, value string, v interface{}) error {
	//construct a valid toml array
	data := key + " = " + value
	if err := toml.Unmarshal([]byte(data), v); err != nil {
		return err
	}
	return nil
}

func applyDefaultValue(fv reflect.Value, ft reflect.StructField, rv reflect.Value) error {
	tag := extractTag(ft.Tag.Get(fieldTagName))

	//Default value is not supported
	if tag.Value == "required" {
		return fmt.Errorf("value of %q is required", ft.Name)
	}

	//No default value supplied
	if tag.Value == "" {
		return nil
	}

	//Validate the default value
	//reflect.Slice will be validated by unmarshalArray
	if tag.Check != "" && fv.Kind() != reflect.Slice {
		rules := strings.Split(tag.Check, " ")
		if err := validate(ft.Name, tag.Value, rules); err != nil {
			return err
		}
	}

	//Set the default value
	switch fv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64:
		if v, err := strconv.ParseInt(tag.Value, 10, 64); err != nil {
			return err
		} else {
			fv.SetInt(v)
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64:
		if v, err := strconv.ParseUint(tag.Value, 10, 64); err != nil {
			return err
		} else {
			fv.SetUint(v)
		}
	case reflect.Float32, reflect.Float64:
		if v, err := strconv.ParseFloat(tag.Value, 64); err != nil {
			return err
		} else {
			fv.SetFloat(v)
		}
	case reflect.Bool:
		if v, err := strconv.ParseBool(tag.Value); err != nil {
			return err
		} else {
			fv.SetBool(v)
		}
	case reflect.String:
		fv.SetString(tag.Value)
	case reflect.Slice:
		v := rv.Addr().Interface()
		if err := unmarshalArray(ft.Name, tag.Value, v); err != nil {
			return err
		}
	default:
		return fmt.Errorf("set default value of type %s is not supported yet", ft.Type)
	}
	return nil
}

//Notice toCamelCase is copied from github.com/naoina/toml
// toCamelCase returns a copy of the string s with all Unicode letters mapped to their camel case.
// It will convert to upper case previous letter of '_' and first letter, and remove letter of '_'.
func toUnderscore(s string) string {
	if s == "" {
		return ""
	}
	result := make([]rune, 0, len(s))

	result = append(result, unicode.ToLower(rune(s[0])))
	for _, r := range s[1:] {
		if unicode.ToUpper(r) == r {
			result = append(result, '_', unicode.ToLower(r))
			continue
		}
		result = append(result, r)
	}
	return string(result)
}

func findField(t *ast.Table, field reflect.StructField) (interface{}, bool) {
	if t == nil {
		return nil, false
	}
	tag := extractTag(field.Tag.Get(fieldTagName))
	if tag != nil && tag.Name != "" {
		if f, found := t.Fields[tag.Name]; found {
			return f, found
		}
		return nil, false
	}

	name := field.Name
	for _, n := range []string{name, strings.ToLower(name), toUnderscore(name)} {
		if f, found := t.Fields[n]; found {
			return f, found
		}
	}
	return nil, false
}

func ApplyDefault(t *ast.Table, rv reflect.Value) error {
	for rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}

	rt := rv.Type()

	if kind := rt.Kind(); kind == reflect.Struct {
		for i := 0; i < rt.NumField(); i++ {
			ft := rt.Field(i)
			fv := rv.Field(i)
			for fv.Kind() == reflect.Ptr {
				fv = fv.Elem()
			}
			if fv.Kind() == reflect.Struct {
				var subt *ast.Table
				var ok bool
				if f, found := findField(t, ft); found {
					subt, ok = f.(*ast.Table)
					//Assgin t back to subt
					//This is becuase the reflect.Struct is emmbed
					// type D struct {
					//    time.Duration
					// }
					// D is a struct , but there is no sub table in conf
					if !ok {
						subt = t
					}
				}

				if err := ApplyDefault(subt, fv); err != nil {
					return err
				}
				continue
			}
			if isEmptyValue(fv) {
				if _, found := findField(t, ft); !found {
					if err := applyDefaultValue(fv, ft, rv); err != nil {
						return err
					}
				}
			}
		}
	}

	return nil
}

func Unmarshal(data []byte, v interface{}) error {
	table, err := toml.Parse(data)
	if err != nil {
		return err
	}

	if err := toml.UnmarshalTable(table, v); err != nil {
		return err
	}

	if err := ApplyDefault(table, reflect.ValueOf(v)); err != nil {
		return err
	}
	return nil
}
func Marshal(v interface{}) ([]byte, error) {
	return toml.Marshal(v)
}
<commit_msg>Unexport ApplyDefault<commit_after>package configo

import (
	"github.com/asaskevich/govalidator"
	"github.com/shafreeck/toml"
	"github.com/shafreeck/toml/ast"

	"fmt"
	"net"
	"reflect"
	"strconv"
	"strings"
	"unicode"
)

const (
	fieldTagName = "cfg"
)

func init() {
	toml.SetValue = fieldValidate
	govalidator.TagMap["netaddr"] = func(addr string) bool {
		if h, p, err := net.SplitHostPort(addr); err == nil {
			if h != "" && !(govalidator.IsDNSName(h) || govalidator.IsIP(h)) {
				return false
			}
			if p != "" && !govalidator.IsPort(p) {
				return true
			}
			return true
		}
		return false
	}
}

func fieldValidate(field string, rv reflect.Value, av ast.Value, tag *toml.CfgTag) error {
	if tag == nil {
		return nil
	}
	val, ok := av.(*ast.String)
	if tag.Check != "" && ok {
		rules := strings.Split(tag.Check, " ")
		return validate(field, val.Value, rules)
	}
	return nil
}
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.String, reflect.Array:
		return v.Len() == 0
	case reflect.Map, reflect.Slice:
		return v.Len() == 0 || v.IsNil()
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
}

func extractTag(tag string) *toml.CfgTag {
	tags := strings.SplitN(tag, ",", 4)
	cfg := &toml.CfgTag{}
	switch c := len(tags); c {
	case 1:
		cfg.Name = strings.TrimSpace(tags[0])
	case 2:
		cfg.Name = strings.TrimSpace(tags[0])
		cfg.Value = strings.TrimSpace(tags[1])
	case 3:
		cfg.Name = strings.TrimSpace(tags[0])
		cfg.Value = strings.TrimSpace(tags[1])
		cfg.Check = strings.TrimSpace(tags[2])
	case 4:
		cfg.Name = strings.TrimSpace(tags[0])
		cfg.Value = strings.TrimSpace(tags[1])
		cfg.Check = strings.TrimSpace(tags[2])
		cfg.Description = strings.TrimSpace(tags[3])
	default:
		return nil
	}
	return cfg
}

func validate(key, value string, rules []string) error {
	for _, rule := range rules {
		validate, ok := govalidator.TagMap[rule]
		if !ok {
			return fmt.Errorf("validate rule %q is not supported", rule)
			continue
		}
		if !validate(value) {
			return fmt.Errorf("value of %q validate failed, %q does not match rule %q", key, value, rule)
		}
	}
	return nil
}

//parse a toml array
func unmarshalArray(key, value string, v interface{}) error {
	//construct a valid toml array
	data := key + " = " + value
	if err := toml.Unmarshal([]byte(data), v); err != nil {
		return err
	}
	return nil
}

func applyDefaultValue(fv reflect.Value, ft reflect.StructField, rv reflect.Value) error {
	tag := extractTag(ft.Tag.Get(fieldTagName))

	//Default value is not supported
	if tag.Value == "required" {
		return fmt.Errorf("value of %q is required", ft.Name)
	}

	//No default value supplied
	if tag.Value == "" {
		return nil
	}

	//Validate the default value
	//reflect.Slice will be validated by unmarshalArray
	if tag.Check != "" && fv.Kind() != reflect.Slice {
		rules := strings.Split(tag.Check, " ")
		if err := validate(ft.Name, tag.Value, rules); err != nil {
			return err
		}
	}

	//Set the default value
	switch fv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64:
		if v, err := strconv.ParseInt(tag.Value, 10, 64); err != nil {
			return err
		} else {
			fv.SetInt(v)
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64:
		if v, err := strconv.ParseUint(tag.Value, 10, 64); err != nil {
			return err
		} else {
			fv.SetUint(v)
		}
	case reflect.Float32, reflect.Float64:
		if v, err := strconv.ParseFloat(tag.Value, 64); err != nil {
			return err
		} else {
			fv.SetFloat(v)
		}
	case reflect.Bool:
		if v, err := strconv.ParseBool(tag.Value); err != nil {
			return err
		} else {
			fv.SetBool(v)
		}
	case reflect.String:
		fv.SetString(tag.Value)
	case reflect.Slice:
		v := rv.Addr().Interface()
		if err := unmarshalArray(ft.Name, tag.Value, v); err != nil {
			return err
		}
	default:
		return fmt.Errorf("set default value of type %s is not supported yet", ft.Type)
	}
	return nil
}

//Notice toCamelCase is copied from github.com/naoina/toml
// toCamelCase returns a copy of the string s with all Unicode letters mapped to their camel case.
// It will convert to upper case previous letter of '_' and first letter, and remove letter of '_'.
func toUnderscore(s string) string {
	if s == "" {
		return ""
	}
	result := make([]rune, 0, len(s))

	result = append(result, unicode.ToLower(rune(s[0])))
	for _, r := range s[1:] {
		if unicode.ToUpper(r) == r {
			result = append(result, '_', unicode.ToLower(r))
			continue
		}
		result = append(result, r)
	}
	return string(result)
}

func findField(t *ast.Table, field reflect.StructField) (interface{}, bool) {
	if t == nil {
		return nil, false
	}
	tag := extractTag(field.Tag.Get(fieldTagName))
	if tag != nil && tag.Name != "" {
		if f, found := t.Fields[tag.Name]; found {
			return f, found
		}
		return nil, false
	}

	name := field.Name
	for _, n := range []string{name, strings.ToLower(name), toUnderscore(name)} {
		if f, found := t.Fields[n]; found {
			return f, found
		}
	}
	return nil, false
}

func applyDefault(t *ast.Table, rv reflect.Value) error {
	for rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}

	rt := rv.Type()

	if kind := rt.Kind(); kind == reflect.Struct {
		for i := 0; i < rt.NumField(); i++ {
			ft := rt.Field(i)
			fv := rv.Field(i)
			for fv.Kind() == reflect.Ptr {
				fv = fv.Elem()
			}
			if fv.Kind() == reflect.Struct {
				var subt *ast.Table
				var ok bool
				if f, found := findField(t, ft); found {
					subt, ok = f.(*ast.Table)
					//Assgin t back to subt
					//This is becuase the reflect.Struct is emmbed
					// type D struct {
					//    time.Duration
					// }
					// D is a struct , but there is no sub table in conf
					if !ok {
						subt = t
					}
				}

				if err := applyDefault(subt, fv); err != nil {
					return err
				}
				continue
			}
			if isEmptyValue(fv) {
				if _, found := findField(t, ft); !found {
					if err := applyDefaultValue(fv, ft, rv); err != nil {
						return err
					}
				}
			}
		}
	}

	return nil
}

func Unmarshal(data []byte, v interface{}) error {
	table, err := toml.Parse(data)
	if err != nil {
		return err
	}

	if err := toml.UnmarshalTable(table, v); err != nil {
		return err
	}

	if err := applyDefault(table, reflect.ValueOf(v)); err != nil {
		return err
	}
	return nil
}
func Marshal(v interface{}) ([]byte, error) {
	return toml.Marshal(v)
}
<|endoftext|>


<commit_before>package survey

import (
	"fmt"
	"os"
	"regexp"

	"github.com/AlecAivazis/survey/core"
	"github.com/AlecAivazis/survey/terminal"
)

// Confirm is a regular text input that accept yes/no answers. Response type is a bool.
type Confirm struct {
	core.Renderer
	Message string
	Default bool
	Help    string
}

// data available to the templates when processing
type ConfirmTemplateData struct {
	Confirm
	Answer   string
	ShowHelp bool
}

// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
var ConfirmQuestionTemplate = `
{{- if .ShowHelp }}{{- color "cyan"}}{{ HelpIcon }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
{{- color "green+hb"}}{{ QuestionIcon }} {{color "reset"}}
{{- color "default+hb"}}{{ .Message }} {{color "reset"}}
{{- if .Answer}}
  {{- color "cyan"}}{{.Answer}}{{color "reset"}}{{"\n"}}
{{- else }}
  {{- if and .Help (not .ShowHelp)}}{{color "cyan"}}[{{ HelpInputRune }} for help]{{color "reset"}} {{end}}
  {{- color "white"}}{{if .Default}}(Y/n) {{else}}(y/N) {{end}}{{color "reset"}}
{{- end}}`

// the regex for answers
var (
	yesRx = regexp.MustCompile("^(?i:y(?:es)?)$")
	noRx  = regexp.MustCompile("^(?i:n(?:o)?)$")
)

func yesNo(t bool) string {
	if t {
		return "Yes"
	}
	return "No"
}

func (c *Confirm) getBool(showHelp bool) (bool, error) {
	rr := terminal.NewRuneReader(os.Stdin)
	rr.SetTermMode()
	defer rr.RestoreTermMode()
	// start waiting for input
	for {
		line, err := rr.ReadLine(0)
		if err != nil {
			return false, err
		}
		// move back up a line to compensate for the \n echoed from terminal
		terminal.CursorPreviousLine(1)
		val := string(line)

		// get the answer that matches the
		var answer bool
		switch {
		case yesRx.Match([]byte(val)):
			answer = true
		case noRx.Match([]byte(val)):
			answer = false
		case val == "":
			answer = c.Default
		case val == string(core.HelpInputRune) && c.Help != "":
			err := c.Render(
				ConfirmQuestionTemplate,
				ConfirmTemplateData{Confirm: *c, ShowHelp: true},
			)
			if err != nil {
				// use the default value and bubble up
				return c.Default, err
			}
			showHelp = true
			continue
		default:
			// we didnt get a valid answer, so print error and prompt again
			if err := c.Error(fmt.Errorf("%q is not a valid answer, please try again.", val)); err != nil {
				return c.Default, err
			}
			err := c.Render(
				ConfirmQuestionTemplate,
				ConfirmTemplateData{Confirm: *c, ShowHelp: showHelp},
			)
			if err != nil {
				// use the default value and bubble up
				return c.Default, err
			}
			continue
		}
		return answer, nil
	}
	// should not get here
	return c.Default, nil
}

/*
Prompt prompts the user with a simple text field and expects a reply followed
by a carriage return.

	likesPie := false
	prompt := &survey.Confirm{ Message: "What is your name?" }
	survey.AskOne(prompt, &name, nil)
*/
func (c *Confirm) Prompt() (interface{}, error) {
	// render the question template
	err := c.Render(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *c},
	)
	if err != nil {
		return "", err
	}

	// get input and return
	return c.getBool(false)
}

// Cleanup overwrite the line with the finalized formatted version
func (c *Confirm) Cleanup(val interface{}) error {
	// if the value was previously true
	ans := yesNo(val.(bool))
	// render the template
	return c.Render(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *c, Answer: ans},
	)
}
<commit_msg>fixed typo in confirm docs<commit_after>package survey

import (
	"fmt"
	"os"
	"regexp"

	"github.com/AlecAivazis/survey/core"
	"github.com/AlecAivazis/survey/terminal"
)

// Confirm is a regular text input that accept yes/no answers. Response type is a bool.
type Confirm struct {
	core.Renderer
	Message string
	Default bool
	Help    string
}

// data available to the templates when processing
type ConfirmTemplateData struct {
	Confirm
	Answer   string
	ShowHelp bool
}

// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
var ConfirmQuestionTemplate = `
{{- if .ShowHelp }}{{- color "cyan"}}{{ HelpIcon }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
{{- color "green+hb"}}{{ QuestionIcon }} {{color "reset"}}
{{- color "default+hb"}}{{ .Message }} {{color "reset"}}
{{- if .Answer}}
  {{- color "cyan"}}{{.Answer}}{{color "reset"}}{{"\n"}}
{{- else }}
  {{- if and .Help (not .ShowHelp)}}{{color "cyan"}}[{{ HelpInputRune }} for help]{{color "reset"}} {{end}}
  {{- color "white"}}{{if .Default}}(Y/n) {{else}}(y/N) {{end}}{{color "reset"}}
{{- end}}`

// the regex for answers
var (
	yesRx = regexp.MustCompile("^(?i:y(?:es)?)$")
	noRx  = regexp.MustCompile("^(?i:n(?:o)?)$")
)

func yesNo(t bool) string {
	if t {
		return "Yes"
	}
	return "No"
}

func (c *Confirm) getBool(showHelp bool) (bool, error) {
	rr := terminal.NewRuneReader(os.Stdin)
	rr.SetTermMode()
	defer rr.RestoreTermMode()
	// start waiting for input
	for {
		line, err := rr.ReadLine(0)
		if err != nil {
			return false, err
		}
		// move back up a line to compensate for the \n echoed from terminal
		terminal.CursorPreviousLine(1)
		val := string(line)

		// get the answer that matches the
		var answer bool
		switch {
		case yesRx.Match([]byte(val)):
			answer = true
		case noRx.Match([]byte(val)):
			answer = false
		case val == "":
			answer = c.Default
		case val == string(core.HelpInputRune) && c.Help != "":
			err := c.Render(
				ConfirmQuestionTemplate,
				ConfirmTemplateData{Confirm: *c, ShowHelp: true},
			)
			if err != nil {
				// use the default value and bubble up
				return c.Default, err
			}
			showHelp = true
			continue
		default:
			// we didnt get a valid answer, so print error and prompt again
			if err := c.Error(fmt.Errorf("%q is not a valid answer, please try again.", val)); err != nil {
				return c.Default, err
			}
			err := c.Render(
				ConfirmQuestionTemplate,
				ConfirmTemplateData{Confirm: *c, ShowHelp: showHelp},
			)
			if err != nil {
				// use the default value and bubble up
				return c.Default, err
			}
			continue
		}
		return answer, nil
	}
	// should not get here
	return c.Default, nil
}

/*
Prompt prompts the user with a simple text field and expects a reply followed
by a carriage return.

	likesPie := false
	prompt := &survey.Confirm{ Message: "What is your name?" }
	survey.AskOne(prompt, &likesPie, nil)
*/
func (c *Confirm) Prompt() (interface{}, error) {
	// render the question template
	err := c.Render(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *c},
	)
	if err != nil {
		return "", err
	}

	// get input and return
	return c.getBool(false)
}

// Cleanup overwrite the line with the finalized formatted version
func (c *Confirm) Cleanup(val interface{}) error {
	// if the value was previously true
	ans := yesNo(val.(bool))
	// render the template
	return c.Render(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *c, Answer: ans},
	)
}
<|endoftext|>


<commit_before>package fakku

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strconv"
	"time"
)

const (
	ErrorContentDoesntExist = "Content doesn't exist"
	ErrorUnknownJsonData    = "Got unknown json data back from content request. API Change?"
	ErrorUnknownJsonLayout  = "Got an unknown layout back from content request. API Change?"
)

type AttributeList []Attribute
type Attribute struct {
	Attribute     string `json:"attribute"`
	AttributeLink string `json:"attribute_link"`
}

func (this *Attribute) populate(c map[string]interface{}) {
	this.Attribute = c["attribute"].(string)
	this.AttributeLink = c["attribute_link"].(string)
}

func (this *Attribute) String() string {
	return this.Attribute
}

func constructAttributeFields(c map[string]interface{}, field string) AttributeList {
	try, ok := c[field]
	if !ok {
		return nil
	}
	tmp := try.([]interface{})
	attrs := make(AttributeList, len(tmp))
	for i := 0; i < len(tmp); i++ {
		attrs[i].populate(tmp[i].(map[string]interface{}))
	}
	return attrs
}

type Content struct {
	Name         string
	RawUrl       string
	Description  string
	Language     string
	Category     string
	RawDate      float64
	FileSize     float64
	Favorites    float64
	CommentCount float64
	Pages        float64
	Poster       string
	RawPosterUrl string
	Tags         AttributeList `json:"content_tags"`
	Translators  AttributeList `json:"content_translators"`
	Series       AttributeList `json:"content_series"`
	Artists      AttributeList `json:"content_artists"`
	Images       struct {
		Cover  string
		Sample string
	}
}
type ContentList []Content

func (this *Content) Url() (*url.URL, error) {
	return url.Parse(this.RawUrl)
}
func (this *Content) PosterUrl() (*url.URL, error) {
	return url.Parse(this.RawPosterUrl)
}
func (this *Content) CoverUrl() (*url.URL, error) {
	return url.Parse(this.Images.Cover)
}
func (this *Content) SampleUrl() (*url.URL, error) {
	return url.Parse(this.Images.Sample)
}
func (this *Content) Date() time.Time {
	return time.Unix(int64(this.RawDate), 0)
}
func (c *Content) UnmarshalJSON(b []byte) error {
	var f interface{}
	json.Unmarshal(b, &f)
	switch f.(type) {
	case map[string]interface{}:
		m := f.(map[string]interface{})
		contents := m["content"]
		switch contents.(type) {
		case map[string]interface{}:
			v := contents.(map[string]interface{})
			c.populate(v)
			return nil
		case []interface{}:
			q := contents.([]interface{})
			if len(q) == 0 {
				// doesn't exist
				return fmt.Errorf(ErrorContentDoesntExist)
			} else {
				return fmt.Errorf(ErrorUnknownJsonData)
			}
		default:
			return fmt.Errorf(ErrorUnknownJsonLayout)
		}
	case []interface{}:
		q := f.([]interface{})
		if len(q) == 0 {
			// doesn't exist
			return fmt.Errorf(ErrorContentDoesntExist)
		} else {
			return fmt.Errorf(ErrorUnknownJsonData)
		}
	default:
		return fmt.Errorf(ErrorUnknownJsonLayout)
	}
}

func (c *Content) populate(v map[string]interface{}) {
	c.Name = v["content_name"].(string)
	c.RawUrl = v["content_url"].(string)
	c.Description = v["content_description"].(string)
	c.Language = v["content_language"].(string)
	c.Category = v["content_category"].(string)
	c.RawDate = v["content_date"].(float64)
	c.FileSize = v["content_filesize"].(float64)
	c.Favorites = v["content_favorites"].(float64)
	c.CommentCount = v["content_comments"].(float64)
	c.Pages = v["content_pages"].(float64)
	c.Poster = v["content_poster"].(string)
	c.RawPosterUrl = v["content_poster_url"].(string)
	c.Tags = constructAttributeFields(v, "content_tags")
	c.Translators = constructAttributeFields(v, "content_translators")
	c.Series = constructAttributeFields(v, "content_series")
	c.Artists = constructAttributeFields(v, "content_artists")

	tmp := v["content_images"]
	z := tmp.(map[string]interface{})
	c.Images.Cover = z["cover"].(string)
	c.Images.Sample = z["sample"].(string)
}

func GetContent(category, name string) (*Content, error) {
	var c Content
	url := contentApiFunction{Category: category, Name: name}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}

type contentApiFunction struct {
	Category string
	Name     string
}

func (a contentApiFunction) Construct() string {
	return fmt.Sprintf("%s/%s/%s", apiHeader, a.Category, a.Name)
}

type contentCommentApiFunction struct {
	contentApiFunction
	TopComments bool
	supportsPagination
}

func (a contentCommentApiFunction) Construct() string {
	base := fmt.Sprintf("%s/comments", a.contentApiFunction.Construct())
	if a.TopComments {
		return fmt.Sprintf("%s/top", base)
	} else {
		return paginateString(base, a.Page)
	}
}

func getContentCommentsGeneric(url apiFunction) (*Comments, error) {
	var c Comments
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}
func ContentComments(category, name string) (*Comments, error) {
	url := contentCommentApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
	}
	return getContentCommentsGeneric(url)
}

func ContentCommentsPage(category, name string, page uint) (*Comments, error) {
	url := contentCommentApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
		supportsPagination: supportsPagination{Page: page},
	}
	return getContentCommentsGeneric(url)
}

func ContentTopComments(category, name string) (*Comments, error) {
	url := contentCommentApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
		TopComments: true,
	}
	return getContentCommentsGeneric(url)
}

func (this *Content) TopComments() (*Comments, error) {
	return ContentTopComments(this.Category, this.Name)
}
func (this *Content) CommentsPage(page uint) (*Comments, error) {
	return ContentCommentsPage(this.Category, this.Name, page)
}
func (this *Content) Comments() (*Comments, error) {
	return ContentComments(this.Category, this.Name)
}

type Comment struct {
	Id           float64 `json:"comment_id"`
	AttachedId   string  `json:"comment_attached_id"`
	Poster       string  `json:"comment_poster"`
	RawPosterUrl string  `json:"comment_poster_url"`
	Reputation   float64 `json:"comment_reputation"`
	Text         string  `json:"comment_text"`
	RawDate      float64 `json:"comment_date"`
}

func (this *Comment) PosterUrl() (*url.URL, error) {
	return url.Parse(this.RawPosterUrl)
}
func (this *Comment) Date() time.Time {
	return time.Unix(int64(this.RawDate), 0)
}

type Comments struct {
	Comments   []Comment `json:"comments"`
	PageNumber float64   `json:"page"`
	Total      float64   `json:"total"`
	Pages      float64   `json:"pages"`
}
type PageList []Page
type ReadOnlineContent struct {
	Content Content  `json:"content"`
	Pages   PageList `json:"pages"`
}

func (r *ReadOnlineContent) UnmarshalJSON(b []byte) error {
	var f interface{}
	if err := json.Unmarshal(b, &r.Content); err != nil {
		return err
	}
	json.Unmarshal(b, &f)
	// need to check and make sure that the content exists
	switch f.(type) {
	case map[string]interface{}:
		m := f.(map[string]interface{})
		pages := m["pages"]
		v := pages.(map[string]interface{})
		r.Pages = make([]Page, len(v))
		for i := 0; i < len(v); i++ {
			ind := strconv.Itoa(i + 1)
			r.Pages[i].populate(v[ind].(map[string]interface{}))
		}
		return nil
	case []interface{}:
		q := f.([]interface{})
		if len(q) == 0 {
			// doesn't exist
			return fmt.Errorf("Content doesn't exist")
		} else {
			return fmt.Errorf("Got unknown json data back from content request. API Change?")
		}
	default:
		return fmt.Errorf("Got an unknown layout back from content request. API Change?")
	}
}

type Page struct {
	Thumb string
	Image string
}

func (this *Page) populate(c map[string]interface{}) {
	this.Thumb = c["thumb"].(string)
	this.Image = c["image"].(string)
}

func (this *Page) ThumbUrl() (*url.URL, error) {
	return url.Parse(this.Thumb)
}
func (this *Page) ImageUrl() (*url.URL, error) {
	return url.Parse(this.Image)
}

type contentReadOnlineApiFunction struct {
	contentApiFunction
}

func (a contentReadOnlineApiFunction) Construct() string {
	return fmt.Sprintf("%s/read", a.contentApiFunction.Construct())
}

func ReadOnline(category, name string) (*ReadOnlineContent, error) {
	var c ReadOnlineContent
	url := contentReadOnlineApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
	}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}

func (this *Content) ReadOnline() (PageList, error) {
	element, err := ReadOnline(this.Category, this.Name)
	if err != nil {
		return nil, err
	} else {
		return element.Pages, nil
	}
}

type contentDownloadsApiFunction struct {
	contentApiFunction
}

func (a contentDownloadsApiFunction) Construct() string {
	return fmt.Sprintf("%s/download", a.contentApiFunction.Construct())
}

type DownloadList []Download

func (this DownloadList) HasDownloads() bool {
	return len(this) > 0
}

type downloadContent struct {
	Downloads DownloadList `json:"downloads"`
	Total     uint         `json:"total"`
}

func ContentDownloads(category, name string) (DownloadList, error) {
	var c downloadContent
	url := contentDownloadsApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
	}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return c.Downloads, nil
	}
}

func (this *Content) Downloads() (DownloadList, error) {
	return ContentDownloads(this.Category, this.Name)
}

type Download struct {
	Type          string  `json:"download_type"`
	RawUrl        string  `json:"download_url"`
	Info          string  `json:"download_info"`
	DownloadCount float64 `json:"download_count"`
	RawTime       float64 `json:"download_time"`
	Poster        string  `json:"download_poster"`
	RawPosterUrl  string  `json:"download_poster_url"`
}

func (this *Download) Url() (*url.URL, error) {
	return url.Parse(this.RawUrl)
}
func (this *Download) PosterUrl() (*url.URL, error) {
	return url.Parse(this.RawPosterUrl)
}
func (this *Download) Time() time.Time {
	return time.Unix(int64(this.RawTime), 0)
}

type contentRelatedApiFunction struct {
	contentApiFunction
	supportsPagination
}

func (a contentRelatedApiFunction) Construct() string {
	base := fmt.Sprintf("%s/related", a.contentApiFunction.Construct())
	return paginateString(base, a.Page)
}

type RelatedContentList struct {
	Related ContentList `json:"related"`
	Total   uint        `json:"total"`
	Pages   uint        `json:"pages"`
}

func RelatedContent(category, name string) (*RelatedContentList, error) {
	return RelatedContentPage(category, name, 0)
}

func RelatedContentPage(category, name string, page uint) (*RelatedContentList, error) {
	var c RelatedContentList
	url := contentRelatedApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
		supportsPagination: supportsPagination{Page: page},
	}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}
func (this *Content) RelatedContent() (*RelatedContentList, error) {
	return RelatedContent(this.Category, this.Name)
}
func (this *Content) RelatedContentPage(page uint) (*RelatedContentList, error) {
	return RelatedContentPage(this.Category, this.Name, page)
}

func (c *RelatedContentList) UnmarshalJSON(b []byte) error {
	// slightly different
	var f interface{}
	json.Unmarshal(b, &f)
	m := f.(map[string]interface{})
	related := m["related"]
	v := related.([]interface{})
	c.Related = make(ContentList, len(v))
	for i := 0; i < len(v); i++ {
		c.Related[i].populate(v[i].(map[string]interface{}))
	}
	c.Total = uint(m["total"].(float64))
	c.Pages = uint(m["pages"].(float64))
	return nil
}
<commit_msg>Added Manga and Doujinshi string constants<commit_after>package fakku

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strconv"
	"time"
)

const (
	ErrorContentDoesntExist = "Content doesn't exist"
	ErrorUnknownJsonData    = "Got unknown json data back from content request. API Change?"
	ErrorUnknownJsonLayout  = "Got an unknown layout back from content request. API Change?"
)

const (
	Manga     = "manga"
	Doujinshi = "doujinshi"
)

type AttributeList []Attribute
type Attribute struct {
	Attribute     string `json:"attribute"`
	AttributeLink string `json:"attribute_link"`
}

func (this *Attribute) populate(c map[string]interface{}) {
	this.Attribute = c["attribute"].(string)
	this.AttributeLink = c["attribute_link"].(string)
}

func (this *Attribute) String() string {
	return this.Attribute
}

func constructAttributeFields(c map[string]interface{}, field string) AttributeList {
	try, ok := c[field]
	if !ok {
		return nil
	}
	tmp := try.([]interface{})
	attrs := make(AttributeList, len(tmp))
	for i := 0; i < len(tmp); i++ {
		attrs[i].populate(tmp[i].(map[string]interface{}))
	}
	return attrs
}

type Content struct {
	Name         string
	RawUrl       string
	Description  string
	Language     string
	Category     string
	RawDate      float64
	FileSize     float64
	Favorites    float64
	CommentCount float64
	Pages        float64
	Poster       string
	RawPosterUrl string
	Tags         AttributeList `json:"content_tags"`
	Translators  AttributeList `json:"content_translators"`
	Series       AttributeList `json:"content_series"`
	Artists      AttributeList `json:"content_artists"`
	Images       struct {
		Cover  string
		Sample string
	}
}
type ContentList []Content

func (this *Content) Url() (*url.URL, error) {
	return url.Parse(this.RawUrl)
}
func (this *Content) PosterUrl() (*url.URL, error) {
	return url.Parse(this.RawPosterUrl)
}
func (this *Content) CoverUrl() (*url.URL, error) {
	return url.Parse(this.Images.Cover)
}
func (this *Content) SampleUrl() (*url.URL, error) {
	return url.Parse(this.Images.Sample)
}
func (this *Content) Date() time.Time {
	return time.Unix(int64(this.RawDate), 0)
}
func (c *Content) UnmarshalJSON(b []byte) error {
	var f interface{}
	json.Unmarshal(b, &f)
	switch f.(type) {
	case map[string]interface{}:
		m := f.(map[string]interface{})
		contents := m["content"]
		switch contents.(type) {
		case map[string]interface{}:
			v := contents.(map[string]interface{})
			c.populate(v)
			return nil
		case []interface{}:
			q := contents.([]interface{})
			if len(q) == 0 {
				// doesn't exist
				return fmt.Errorf(ErrorContentDoesntExist)
			} else {
				return fmt.Errorf(ErrorUnknownJsonData)
			}
		default:
			return fmt.Errorf(ErrorUnknownJsonLayout)
		}
	case []interface{}:
		q := f.([]interface{})
		if len(q) == 0 {
			// doesn't exist
			return fmt.Errorf(ErrorContentDoesntExist)
		} else {
			return fmt.Errorf(ErrorUnknownJsonData)
		}
	default:
		return fmt.Errorf(ErrorUnknownJsonLayout)
	}
}

func (c *Content) populate(v map[string]interface{}) {
	c.Name = v["content_name"].(string)
	c.RawUrl = v["content_url"].(string)
	c.Description = v["content_description"].(string)
	c.Language = v["content_language"].(string)
	c.Category = v["content_category"].(string)
	c.RawDate = v["content_date"].(float64)
	c.FileSize = v["content_filesize"].(float64)
	c.Favorites = v["content_favorites"].(float64)
	c.CommentCount = v["content_comments"].(float64)
	c.Pages = v["content_pages"].(float64)
	c.Poster = v["content_poster"].(string)
	c.RawPosterUrl = v["content_poster_url"].(string)
	c.Tags = constructAttributeFields(v, "content_tags")
	c.Translators = constructAttributeFields(v, "content_translators")
	c.Series = constructAttributeFields(v, "content_series")
	c.Artists = constructAttributeFields(v, "content_artists")

	tmp := v["content_images"]
	z := tmp.(map[string]interface{})
	c.Images.Cover = z["cover"].(string)
	c.Images.Sample = z["sample"].(string)
}

func GetContent(category, name string) (*Content, error) {
	var c Content
	url := contentApiFunction{Category: category, Name: name}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}

type contentApiFunction struct {
	Category string
	Name     string
}

func (a contentApiFunction) Construct() string {
	return fmt.Sprintf("%s/%s/%s", apiHeader, a.Category, a.Name)
}

type contentCommentApiFunction struct {
	contentApiFunction
	TopComments bool
	supportsPagination
}

func (a contentCommentApiFunction) Construct() string {
	base := fmt.Sprintf("%s/comments", a.contentApiFunction.Construct())
	if a.TopComments {
		return fmt.Sprintf("%s/top", base)
	} else {
		return paginateString(base, a.Page)
	}
}

func getContentCommentsGeneric(url apiFunction) (*Comments, error) {
	var c Comments
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}
func ContentComments(category, name string) (*Comments, error) {
	url := contentCommentApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
	}
	return getContentCommentsGeneric(url)
}

func ContentCommentsPage(category, name string, page uint) (*Comments, error) {
	url := contentCommentApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
		supportsPagination: supportsPagination{Page: page},
	}
	return getContentCommentsGeneric(url)
}

func ContentTopComments(category, name string) (*Comments, error) {
	url := contentCommentApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
		TopComments: true,
	}
	return getContentCommentsGeneric(url)
}

func (this *Content) TopComments() (*Comments, error) {
	return ContentTopComments(this.Category, this.Name)
}
func (this *Content) CommentsPage(page uint) (*Comments, error) {
	return ContentCommentsPage(this.Category, this.Name, page)
}
func (this *Content) Comments() (*Comments, error) {
	return ContentComments(this.Category, this.Name)
}

type Comment struct {
	Id           float64 `json:"comment_id"`
	AttachedId   string  `json:"comment_attached_id"`
	Poster       string  `json:"comment_poster"`
	RawPosterUrl string  `json:"comment_poster_url"`
	Reputation   float64 `json:"comment_reputation"`
	Text         string  `json:"comment_text"`
	RawDate      float64 `json:"comment_date"`
}

func (this *Comment) PosterUrl() (*url.URL, error) {
	return url.Parse(this.RawPosterUrl)
}
func (this *Comment) Date() time.Time {
	return time.Unix(int64(this.RawDate), 0)
}

type Comments struct {
	Comments   []Comment `json:"comments"`
	PageNumber float64   `json:"page"`
	Total      float64   `json:"total"`
	Pages      float64   `json:"pages"`
}
type PageList []Page
type ReadOnlineContent struct {
	Content Content  `json:"content"`
	Pages   PageList `json:"pages"`
}

func (r *ReadOnlineContent) UnmarshalJSON(b []byte) error {
	var f interface{}
	if err := json.Unmarshal(b, &r.Content); err != nil {
		return err
	}
	json.Unmarshal(b, &f)
	// need to check and make sure that the content exists
	switch f.(type) {
	case map[string]interface{}:
		m := f.(map[string]interface{})
		pages := m["pages"]
		v := pages.(map[string]interface{})
		r.Pages = make([]Page, len(v))
		for i := 0; i < len(v); i++ {
			ind := strconv.Itoa(i + 1)
			r.Pages[i].populate(v[ind].(map[string]interface{}))
		}
		return nil
	case []interface{}:
		q := f.([]interface{})
		if len(q) == 0 {
			// doesn't exist
			return fmt.Errorf("Content doesn't exist")
		} else {
			return fmt.Errorf("Got unknown json data back from content request. API Change?")
		}
	default:
		return fmt.Errorf("Got an unknown layout back from content request. API Change?")
	}
}

type Page struct {
	Thumb string
	Image string
}

func (this *Page) populate(c map[string]interface{}) {
	this.Thumb = c["thumb"].(string)
	this.Image = c["image"].(string)
}

func (this *Page) ThumbUrl() (*url.URL, error) {
	return url.Parse(this.Thumb)
}
func (this *Page) ImageUrl() (*url.URL, error) {
	return url.Parse(this.Image)
}

type contentReadOnlineApiFunction struct {
	contentApiFunction
}

func (a contentReadOnlineApiFunction) Construct() string {
	return fmt.Sprintf("%s/read", a.contentApiFunction.Construct())
}

func ReadOnline(category, name string) (*ReadOnlineContent, error) {
	var c ReadOnlineContent
	url := contentReadOnlineApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
	}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}

func (this *Content) ReadOnline() (PageList, error) {
	element, err := ReadOnline(this.Category, this.Name)
	if err != nil {
		return nil, err
	} else {
		return element.Pages, nil
	}
}

type contentDownloadsApiFunction struct {
	contentApiFunction
}

func (a contentDownloadsApiFunction) Construct() string {
	return fmt.Sprintf("%s/download", a.contentApiFunction.Construct())
}

type DownloadList []Download

func (this DownloadList) HasDownloads() bool {
	return len(this) > 0
}

type downloadContent struct {
	Downloads DownloadList `json:"downloads"`
	Total     uint         `json:"total"`
}

func ContentDownloads(category, name string) (DownloadList, error) {
	var c downloadContent
	url := contentDownloadsApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
	}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return c.Downloads, nil
	}
}

func (this *Content) Downloads() (DownloadList, error) {
	return ContentDownloads(this.Category, this.Name)
}

type Download struct {
	Type          string  `json:"download_type"`
	RawUrl        string  `json:"download_url"`
	Info          string  `json:"download_info"`
	DownloadCount float64 `json:"download_count"`
	RawTime       float64 `json:"download_time"`
	Poster        string  `json:"download_poster"`
	RawPosterUrl  string  `json:"download_poster_url"`
}

func (this *Download) Url() (*url.URL, error) {
	return url.Parse(this.RawUrl)
}
func (this *Download) PosterUrl() (*url.URL, error) {
	return url.Parse(this.RawPosterUrl)
}
func (this *Download) Time() time.Time {
	return time.Unix(int64(this.RawTime), 0)
}

type contentRelatedApiFunction struct {
	contentApiFunction
	supportsPagination
}

func (a contentRelatedApiFunction) Construct() string {
	base := fmt.Sprintf("%s/related", a.contentApiFunction.Construct())
	return paginateString(base, a.Page)
}

type RelatedContentList struct {
	Related ContentList `json:"related"`
	Total   uint        `json:"total"`
	Pages   uint        `json:"pages"`
}

func RelatedContent(category, name string) (*RelatedContentList, error) {
	return RelatedContentPage(category, name, 0)
}

func RelatedContentPage(category, name string, page uint) (*RelatedContentList, error) {
	var c RelatedContentList
	url := contentRelatedApiFunction{
		contentApiFunction: contentApiFunction{
			Category: category,
			Name:     name,
		},
		supportsPagination: supportsPagination{Page: page},
	}
	if err := apiCall(url, &c); err != nil {
		return nil, err
	} else {
		return &c, nil
	}
}
func (this *Content) RelatedContent() (*RelatedContentList, error) {
	return RelatedContent(this.Category, this.Name)
}
func (this *Content) RelatedContentPage(page uint) (*RelatedContentList, error) {
	return RelatedContentPage(this.Category, this.Name, page)
}

func (c *RelatedContentList) UnmarshalJSON(b []byte) error {
	// slightly different
	var f interface{}
	json.Unmarshal(b, &f)
	m := f.(map[string]interface{})
	related := m["related"]
	v := related.([]interface{})
	c.Related = make(ContentList, len(v))
	for i := 0; i < len(v); i++ {
		c.Related[i].populate(v[i].(map[string]interface{}))
	}
	c.Total = uint(m["total"].(float64))
	c.Pages = uint(m["pages"].(float64))
	return nil
}
<|endoftext|>


<commit_before>package gfx

import "errors"

var (
	ErrInvalidOperation = errors.New("invalid operation")
	ErrInvalidValue     = errors.New("invalid value")
	ErrOutOfMemory      = errors.New("out of memory")
)

// ContextAttributes is a set of properties used to initialize the context for
// the first time.
//
// Each property is a preference, and might not be configurable. To query which
// properties you did receive, check Context.GetAttributes()
type ContextAttributes struct {
	// Alpha is whether the drawing buffer has an alpha channel for alpha
	// compositing operations.
	Alpha bool

	// Antialias is whether the rendering context is antialiased.
	Antialias bool

	// Depth is whether or not the drawing buffer has an depth buffer.
	Depth bool

	// PremultipliedAlpha is whether or not the colors in the drawing buffer
	// are premultiplied alpha. This property is ignored if Alpha is false.
	PremultipliedAlpha bool

	// FailIfMajorPerformanceCaveat is whether a context will be created if
	// system performance is low.
	FailIfMajorPerformanceCaveat bool

	// PreserveDrawingBuffer is whether the drawing buffers are cleared once
	// content has been presented to the user.
	PreserveDrawingBuffer bool
}

// Context is a graphics context. Unlike traditional OpenGL contexts, it is not
// tied to a specific OS thread (but still must be accessed from only one
// goroutine/thread at a time).
type Context interface {
	// NewBuffer returns a new buffer object that contains data such as
	// vertices or colors.
	NewBuffer() Buffer

	// Attributes returns a structure filled with this context's in-use
	// attributes.
	Attributes(a ContextAttributes) ContextAttributes

	// Error returns the last error that occured in the context, or nil.
	Error() error
}
<commit_msg>Remove ContextAttributes (WebGL specific).<commit_after>package gfx

import "errors"

var (
	ErrInvalidOperation = errors.New("invalid operation")
	ErrInvalidValue     = errors.New("invalid value")
	ErrOutOfMemory      = errors.New("out of memory")
)

// Context is a graphics context. Unlike traditional OpenGL contexts, it is not
// tied to a specific OS thread (but still must be accessed from only one
// goroutine/thread at a time).
type Context interface {
	// NewBuffer returns a new buffer object that contains data such as
	// vertices or colors.
	NewBuffer() Buffer

	// Attributes returns a structure filled with this context's in-use
	// attributes.
	Attributes(a ContextAttributes) ContextAttributes

	// Error returns the last error that occured in the context, or nil.
	Error() error
}
<|endoftext|>


<commit_before>package cli

import (
	"errors"
	"flag"
	"strconv"
	"strings"
)

// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
	App       *App
	flagSet   *flag.FlagSet
	globalSet *flag.FlagSet
}

type Args []string

// Creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
	return &Context{app, set, globalSet}
}

// Looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int(name string) int {
	return lookupInt(name, c.flagSet)
}

// Looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool {
	return lookupBool(name, c.flagSet)
}

// Looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string {
	return lookupString(name, c.flagSet)
}

// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string {
	return lookupStringSlice(name, c.flagSet)
}

// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int {
	return lookupIntSlice(name, c.flagSet)
}

// Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
	return lookupInt(name, c.globalSet)
}

// Looks up the value of a global bool flag, returns false if no bool flag exists
func (c *Context) GlobalBool(name string) bool {
	return lookupBool(name, c.globalSet)
}

// Looks up the value of a global string flag, returns "" if no string flag exists
func (c *Context) GlobalString(name string) string {
	return lookupString(name, c.globalSet)
}

// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
	return lookupStringSlice(name, c.globalSet)
}

// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
	return lookupIntSlice(name, c.globalSet)
}

// Returns the command line arguments associated with the context.
func (c *Context) Args() Args {
	args := Args(c.flagSet.Args())
	return args
}

func lookupInt(name string, set *flag.FlagSet) int {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.Atoi(f.Value.String())
		if err != nil {
			return 0
		}
		return val
	}

	return 0
}

func lookupString(name string, set *flag.FlagSet) string {
	f := set.Lookup(name)
	if f != nil {
		return f.Value.String()
	}

	return ""
}

func lookupStringSlice(name string, set *flag.FlagSet) []string {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*StringSlice)).Value()

	}

	return nil
}

func lookupIntSlice(name string, set *flag.FlagSet) []int {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*IntSlice)).Value()

	}

	return nil
}

func lookupBool(name string, set *flag.FlagSet) bool {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseBool(f.Value.String())
		if err != nil {
			return false
		}
		return val
	}

	return false
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
	visited := make(map[string]bool)
	set.Visit(func(f *flag.Flag) {
		visited[f.Name] = true
	})
	for _, f := range flags {
		parts := strings.Split(f.getName(), ",")
		if len(parts) == 1 {
			continue
		}
		var ff *flag.Flag
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if visited[name] {
				if ff != nil {
					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
				}
				ff = set.Lookup(name)
			}
		}
		if ff == nil {
			continue
		}
		for _, name := range parts {
			name = strings.Trim(name, " ")
			set.Set(name, ff.Value.String())
		}
	}
	return nil
}

// Returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
	if len(a) > n {
		return a[n]
	}
	return ""
}

// Returns the first argument, or else a blank string
func (a Args) First() string {
	return a.Get(0)
}

// Return the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
	if len(a) >= 2 {
		return []string(a)[1:]
	}
	return []string{}
}

// Checks if there are any arguments present
func (a Args) Present() bool {
	return len(a) != 0
}
<commit_msg>Moved some code around in context.go<commit_after>package cli

import (
	"errors"
	"flag"
	"strconv"
	"strings"
)

// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
	App       *App
	flagSet   *flag.FlagSet
	globalSet *flag.FlagSet
}

// Creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
	return &Context{app, set, globalSet}
}

// Looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int(name string) int {
	return lookupInt(name, c.flagSet)
}

// Looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool {
	return lookupBool(name, c.flagSet)
}

// Looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string {
	return lookupString(name, c.flagSet)
}

// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string {
	return lookupStringSlice(name, c.flagSet)
}

// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int {
	return lookupIntSlice(name, c.flagSet)
}

// Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
	return lookupInt(name, c.globalSet)
}

// Looks up the value of a global bool flag, returns false if no bool flag exists
func (c *Context) GlobalBool(name string) bool {
	return lookupBool(name, c.globalSet)
}

// Looks up the value of a global string flag, returns "" if no string flag exists
func (c *Context) GlobalString(name string) string {
	return lookupString(name, c.globalSet)
}

// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
	return lookupStringSlice(name, c.globalSet)
}

// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
	return lookupIntSlice(name, c.globalSet)
}

type Args []string

// Returns the command line arguments associated with the context.
func (c *Context) Args() Args {
	args := Args(c.flagSet.Args())
	return args
}

// Returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
	if len(a) > n {
		return a[n]
	}
	return ""
}

// Returns the first argument, or else a blank string
func (a Args) First() string {
	return a.Get(0)
}

// Return the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
	if len(a) >= 2 {
		return []string(a)[1:]
	}
	return []string{}
}

// Checks if there are any arguments present
func (a Args) Present() bool {
	return len(a) != 0
}

func lookupInt(name string, set *flag.FlagSet) int {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.Atoi(f.Value.String())
		if err != nil {
			return 0
		}
		return val
	}

	return 0
}

func lookupString(name string, set *flag.FlagSet) string {
	f := set.Lookup(name)
	if f != nil {
		return f.Value.String()
	}

	return ""
}

func lookupStringSlice(name string, set *flag.FlagSet) []string {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*StringSlice)).Value()

	}

	return nil
}

func lookupIntSlice(name string, set *flag.FlagSet) []int {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*IntSlice)).Value()

	}

	return nil
}

func lookupBool(name string, set *flag.FlagSet) bool {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseBool(f.Value.String())
		if err != nil {
			return false
		}
		return val
	}

	return false
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
	visited := make(map[string]bool)
	set.Visit(func(f *flag.Flag) {
		visited[f.Name] = true
	})
	for _, f := range flags {
		parts := strings.Split(f.getName(), ",")
		if len(parts) == 1 {
			continue
		}
		var ff *flag.Flag
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if visited[name] {
				if ff != nil {
					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
				}
				ff = set.Lookup(name)
			}
		}
		if ff == nil {
			continue
		}
		for _, name := range parts {
			name = strings.Trim(name, " ")
			set.Set(name, ff.Value.String())
		}
	}
	return nil
}
<|endoftext|>