func (kb dbKeybase) CreateOffline(name string, pub crypto.PubKey) (Info, error) {
	return kb.writeOfflineKey(pub, name), nil
}

func ( kb dbKeybase ) CreateOffline ( name string , pub crypto . PubKey ) ( Info , error ) { return kb . writeOfflineKey ( pub , name ) , nil }

// CreateOffline creates a new reference to an offline keypair
// It returns the created key info

CreateOffline creates a new reference to an offline keypair It returns the created key info


func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) {
	words := strings.Split(strings.TrimSpace(seedphrase), " ")
	secret, err := kb.codec.WordsToBytes(words)
	if err != nil {
		return nil, err
	}

	// secret is comprised of the actual secret with the type
	// appended.
	// ie [secret] = [type] + [secret]
	typ, secret := secret[0], secret[1:]
	algo := byteToSignAlgo(typ)
	priv, err := generate(algo, secret)
	if err != nil {
		return nil, err
	}

	// encrypt and persist key.
	public := kb.writeLocalKey(priv, name, passphrase)
	return public, nil
}

// Recover converts a seedphrase to a private key and persists it,
// encrypted with the given passphrase.  Functions like Create, but
// seedphrase is input not output.

Recover converts a seedphrase to a private key and persists it encrypted with the given passphrase . Functions like Create but seedphrase is input not output .


func (kb dbKeybase) List() ([]Info, error) {
	var res []Info
	iter := kb.db.Iterator(nil, nil)
	defer iter.Close()
	for ; iter.Valid(); iter.Next() {
		info, err := readInfo(iter.Value())
		if err != nil {
			return nil, err
		}
		res = append(res, info)
	}
	return res, nil
}

func ( kb dbKeybase ) List ( ) ( [ ] Info , error ) { var res [ ] Info iter := kb . db . Iterator ( nil , nil ) defer iter . Close ( ) for ; iter . Valid ( ) ; iter . Next ( ) { info , err := readInfo ( iter . Value ( ) ) if err != nil { return nil , err } res = append ( res , info ) } return res , nil }

// List returns the keys from storage in alphabetical order.

List returns the keys from storage in alphabetical order .


func (kb dbKeybase) Get(name string) (Info, error) {
	bs := kb.db.Get(infoKey(name))
	return readInfo(bs)
}

func ( kb dbKeybase ) Get ( name string ) ( Info , error ) { bs := kb . db . Get ( infoKey ( name ) ) return readInfo ( bs ) }

// Get returns the public information about one key.

Get returns the public information about one key .


func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pub crypto.PubKey, err error) {
	info, err := kb.Get(name)
	if err != nil {
		return
	}
	var priv crypto.PrivKey
	switch info.(type) {
	case localInfo:
		linfo := info.(localInfo)
		if linfo.PrivKeyArmor == "" {
			err = fmt.Errorf("private key not available")
			return
		}
		priv, err = unarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase)
		if err != nil {
			return nil, nil, err
		}
	case ledgerInfo:
		linfo := info.(ledgerInfo)
		priv, err = crypto.NewPrivKeyLedgerSecp256k1(linfo.Path)
		if err != nil {
			return
		}
	case offlineInfo:
		linfo := info.(offlineInfo)
		fmt.Printf("Bytes to sign:\n%s", msg)
		buf := bufio.NewReader(os.Stdin)
		fmt.Printf("\nEnter Amino-encoded signature:\n")
		// Will block until user inputs the signature
		signed, err := buf.ReadString('\n')
		if err != nil {
			return nil, nil, err
		}
		cdc.MustUnmarshalBinary([]byte(signed), sig)
		return sig, linfo.GetPubKey(), nil
	}
	sig, err = priv.Sign(msg)
	if err != nil {
		return nil, nil, err
	}
	pub = priv.PubKey()
	return sig, pub, nil
}

// Sign signs the msg with the named key.
// It returns an error if the key doesn't exist or the decryption fails.

Sign signs the msg with the named key . It returns an error if the key doesn t exist or the decryption fails .


func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) {
	bz := kb.db.Get(infoKey(name))
	if bz == nil {
		return "", errors.New("No key to export with name " + name)
	}
	info, err := readInfo(bz)
	if err != nil {
		return
	}
	return armorPubKeyBytes(info.GetPubKey().Bytes()), nil
}

func ( kb dbKeybase ) ExportPubKey ( name string ) ( armor string , err error ) { bz := kb . db . Get ( infoKey ( name ) ) if bz == nil { return " " , errors . New ( " " + name ) } info , err := readInfo ( bz ) if err != nil { return } return armorPubKeyBytes ( info . GetPubKey ( ) . Bytes ( ) ) , nil }

// ExportPubKey returns public keys in ASCII armored format.
// Retrieve a Info object by its name and return the public key in
// a portable format.

ExportPubKey returns public keys in ASCII armored format . Retrieve a Info object by its name and return the public key in a portable format .


func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) {
	bz := kb.db.Get(infoKey(name))
	if len(bz) > 0 {
		return errors.New("Cannot overwrite data for name " + name)
	}
	pubBytes, err := unarmorPubKeyBytes(armor)
	if err != nil {
		return
	}
	pubKey, err := crypto.PubKeyFromBytes(pubBytes)
	if err != nil {
		return
	}
	kb.writeOfflineKey(pubKey, name)
	return
}

func ( kb dbKeybase ) ImportPubKey ( name string , armor string ) ( err error ) { bz := kb . db . Get ( infoKey ( name ) ) if len ( bz ) > 0 { return errors . New ( " " + name ) } pubBytes , err := unarmorPubKeyBytes ( armor ) if err != nil { return } pubKey , err := crypto . PubKeyFromBytes ( pubBytes ) if err != nil { return } kb . writeOfflineKey ( pubKey , name ) return }

// ImportPubKey imports ASCII-armored public keys.
// Store a new Info object holding a public key only, i.e. it will
// not be possible to sign with it as it lacks the secret key.

ImportPubKey imports ASCII - armored public keys . Store a new Info object holding a public key only i . e . it will not be possible to sign with it as it lacks the secret key .


func (kb dbKeybase) Update(name, oldpass, newpass string) error {
	info, err := kb.Get(name)
	if err != nil {
		return err
	}
	switch info.(type) {
	case localInfo:
		linfo := info.(localInfo)
		key, err := unarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
		if err != nil {
			return err
		}
		kb.writeLocalKey(key, name, newpass)
		return nil
	default:
		return fmt.Errorf("Locally stored key required")
	}
}

func ( kb dbKeybase ) Update ( name , oldpass , newpass string ) error { info , err := kb . Get ( name ) if err != nil { return err } switch info . ( type ) { case localInfo : linfo := info . ( localInfo ) key , err := unarmorDecryptPrivKey ( linfo . PrivKeyArmor , oldpass ) if err != nil { return err } kb . writeLocalKey ( key , name , newpass ) return nil default : return fmt . Errorf ( " " ) } }

// Update changes the passphrase with which an already stored key is
// encrypted.
//
// oldpass must be the current passphrase used for encryption,
// newpass will be the only valid passphrase from this time forward.

Update changes the passphrase with which an already stored key is encrypted . oldpass must be the current passphrase used for encryption newpass will be the only valid passphrase from this time forward .


func randBytes(numBytes int) []byte {
	b := make([]byte, numBytes)
	_, err := crand.Read(b)
	if err != nil {
		PanicCrisis(err)
	}
	return b
}

func randBytes ( numBytes int ) [ ] byte { b := make ( [ ] byte , numBytes ) _ , err := crand . Read ( b ) if err != nil { PanicCrisis ( err ) } return b }


func GenerateFromPassword(salt []byte, password []byte, cost int) ([]byte, error) {
	if len(salt) != maxSaltSize {
		return nil, fmt.Errorf("Salt len must be %v", maxSaltSize)
	}
	p, err := newFromPassword(salt, password, cost)
	if err != nil {
		return nil, err
	}
	return p.Hash(), nil
}

func GenerateFromPassword ( salt [ ] byte , password [ ] byte , cost int ) ( [ ] byte , error ) { if len ( salt ) != maxSaltSize { return nil , fmt . Errorf ( " " , maxSaltSize ) } p , err := newFromPassword ( salt , password , cost ) if err != nil { return nil , err } return p . Hash ( ) , nil }

// GenerateFromPassword returns the bcrypt hash of the password at the given
// cost. If the cost given is less than MinCost, the cost will be set to
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
// to compare the returned hashed password with its cleartext version.

GenerateFromPassword returns the bcrypt hash of the password at the given cost . If the cost given is less than MinCost the cost will be set to DefaultCost instead . Use CompareHashAndPassword as defined in this package to compare the returned hashed password with its cleartext version .


func CompareHashAndPassword(hashedPassword, password []byte) error {
	p, err := newFromHash(hashedPassword)
	if err != nil {
		return err
	}

	otherHash, err := bcrypt(password, p.cost, p.salt)
	if err != nil {
		return err
	}

	otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
	if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
		return nil
	}

	return ErrMismatchedHashAndPassword
}

func CompareHashAndPassword ( hashedPassword , password [ ] byte ) error { p , err := newFromHash ( hashedPassword ) if err != nil { return err } otherHash , err := bcrypt ( password , p . cost , p . salt ) if err != nil { return err } otherP := & hashed { otherHash , p . salt , p . cost , p . major , p . minor } if subtle . ConstantTimeCompare ( p . Hash ( ) , otherP . Hash ( ) ) == 1 { return nil } return ErrMismatchedHashAndPassword }

// CompareHashAndPassword compares a bcrypt hashed password with its possible
// plaintext equivalent. Returns nil on success, or an error on failure.

CompareHashAndPassword compares a bcrypt hashed password with its possible plaintext equivalent . Returns nil on success or an error on failure .


func Cost(hashedPassword []byte) (int, error) {
	p, err := newFromHash(hashedPassword)
	if err != nil {
		return 0, err
	}
	return p.cost, nil
}

func Cost ( hashedPassword [ ] byte ) ( int , error ) { p , err := newFromHash ( hashedPassword ) if err != nil { return 0 , err } return p . cost , nil }

// Cost returns the hashing cost used to create the given hashed
// password. When, in the future, the hashing cost of a password system needs
// to be increased in order to adjust for greater computational power, this
// function allows one to establish which passwords need to be updated.

Cost returns the hashing cost used to create the given hashed password . When in the future the hashing cost of a password system needs to be increased in order to adjust for greater computational power this function allows one to establish which passwords need to be updated .


func (p *hashed) decodeCost(sbytes []byte) (int, error) {
	cost, err := strconv.Atoi(string(sbytes[0:2]))
	if err != nil {
		return -1, err
	}
	err = checkCost(cost)
	if err != nil {
		return -1, err
	}
	p.cost = cost
	return 3, nil
}

func ( p * hashed ) decodeCost ( sbytes [ ] byte ) ( int , error ) { cost , err := strconv . Atoi ( string ( sbytes [ 0 : 2 ] ) ) if err != nil { return - 1 , err } err = checkCost ( cost ) if err != nil { return - 1 , err } p . cost = cost return 3 , nil }

// sbytes should begin where decodeVersion left off.

sbytes should begin where decodeVersion left off .


func ASTToString(a AST, options ...Option) string {
	tparams := true
	for _, o := range options {
		switch o {
		case NoTemplateParams:
			tparams = false
		}
	}

	ps := printState{tparams: tparams}
	a.print(&ps)
	return ps.buf.String()
}

func ASTToString ( a AST , options ... Option ) string { tparams := true for _ , o := range options { switch o { case NoTemplateParams : tparams = false } } ps := printState { tparams : tparams } a . print ( & ps ) return ps . buf . String ( ) }

// ASTToString returns the demangled name of the AST.

ASTToString returns the demangled name of the AST .


func (ps *printState) writeByte(b byte) {
	ps.last = b
	ps.buf.WriteByte(b)
}

func ( ps * printState ) writeByte ( b byte ) { ps . last = b ps . buf . WriteByte ( b ) }

// writeByte adds a byte to the string being printed.

writeByte adds a byte to the string being printed .


func (ps *printState) writeString(s string) {
	if len(s) > 0 {
		ps.last = s[len(s)-1]
	}
	ps.buf.WriteString(s)
}

func ( ps * printState ) writeString ( s string ) { if len ( s ) > 0 { ps . last = s [ len ( s ) - 1 ] } ps . buf . WriteString ( s ) }

// writeString adds a string to the string being printed.

writeString adds a string to the string being printed .


func (ps *printState) print(a AST) {
	c := 0
	for _, v := range ps.printing {
		if v == a {
			// We permit the type to appear once, and
			// return without printing anything if we see
			// it twice.  This is for a case like
			// _Z6outer2IsEPFilES1_, where the
			// substitution is printed differently the
			// second time because the set of inner types
			// is different.
			c++
			if c > 1 {
				return
			}
		}
	}
	ps.printing = append(ps.printing, a)

	a.print(ps)

	ps.printing = ps.printing[:len(ps.printing)-1]
}


func (twq *TypeWithQualifiers) printInner(ps *printState) {
	ps.writeByte(' ')
	ps.writeString(strings.Join(twq.Qualifiers, " "))
}

func
(
twq
*
TypeWithQualifiers
)
printInner
(
ps
*
printState
)
{
ps
.
writeByte
(
' '
)
ps
.
writeString
(
strings
.
Join
(
twq
.
Qualifiers
,
"
"
)
)
}

// Print qualifiers as an inner type by just printing the qualifiers.

Print qualifiers as an inner type by just printing the qualifiers .


func printBase(ps *printState, qual, base AST) {
	ps.inner = append(ps.inner, qual)
	ps.print(base)
	if len(ps.inner) > 0 {
		qual.(innerPrinter).printInner(ps)
		ps.inner = ps.inner[:len(ps.inner)-1]
	}
}

func printBase ( ps * printState , qual , base AST ) { ps . inner = append ( ps . inner , qual ) ps . print ( base ) if len ( ps . inner ) > 0 { qual . ( innerPrinter ) . printInner ( ps ) ps . inner = ps . inner [ : len ( ps . inner ) - 1 ] } }

// printBase is common print code for types that are printed with a
// simple suffix.

printBase is common print code for types that are printed with a simple suffix .


func (at *ArrayType) printDimension(ps *printState) {
	space := " "
	for len(ps.inner) > 0 {
		// We haven't gotten to the real type yet.  Use
		// parentheses around that type, except that if it is
		// an array type we print it as a multi-dimensional
		// array
		in := ps.inner[len(ps.inner)-1]
		if twq, ok := in.(*TypeWithQualifiers); ok {
			in = twq.Base
		}
		if _, ok := in.(*ArrayType); ok {
			if in == ps.inner[len(ps.inner)-1] {
				space = ""
			}
			ps.printOneInner(nil)
		} else {
			ps.writeString(" (")
			ps.printInner(false)
			ps.writeByte(')')
		}
	}
	ps.writeString(space)
	ps.writeByte('[')
	ps.print(at.Dimension)
	ps.writeByte(']')
}


func (ft *FunctionType) printArgs(ps *printState) {
	paren := false
	space := false
	for i := len(ps.inner) - 1; i >= 0; i-- {
		switch ps.inner[i].(type) {
		case *PointerType, *ReferenceType, *RvalueReferenceType:
			paren = true
		case *TypeWithQualifiers, *ComplexType, *ImaginaryType, *PtrMem:
			space = true
			paren = true
		}
		if paren {
			break
		}
	}

	if paren {
		if !space && (ps.last != '(' && ps.last != '*') {
			space = true
		}
		if space && ps.last != ' ' {
			ps.writeByte(' ')
		}
		ps.writeByte('(')
	}

	save := ps.printInner(true)

	if paren {
		ps.writeByte(')')
	}

	ps.writeByte('(')
	first := true
	for _, a := range ft.Args {
		if ps.isEmpty(a) {
			continue
		}
		if !first {
			ps.writeString(", ")
		}
		ps.print(a)
		first = false
	}
	ps.writeByte(')')

	ps.inner = save
	ps.printInner(false)
}

func
(
ft
*
FunctionType
)
printArgs
(
ps
*
printState
)
{
paren
:=
false
space
:=
false
for
i
:=
len
(
ps
.
inner
)
1
;
i
>=
0
;
i
{
switch
ps
.
inner
[
i
]
.
(
type
)
{
case
*
PointerType
,
*
ReferenceType
,
*
RvalueReferenceType
:
paren
=
true
case
*
TypeWithQualifiers
,
*
ComplexType
,
*
ImaginaryType
,
*
PtrMem
:
space
=
true
paren
=
true
}
if
paren
{
break
}
}
if
paren
{
if
!
space
&&
(
ps
.
last
!=
'('
&&
ps
.
last
!=
'*'
)
{
space
=
true
}
if
space
&&
ps
.
last
!=
' '
{
ps
.
writeByte
(
' '
)
}
ps
.
writeByte
(
'('
)
}
save
:=
ps
.
printInner
(
true
)
if
paren
{
ps
.
writeByte
(
')'
)
}
ps
.
writeByte
(
'('
)
first
:=
true
for
_
,
a
:=
range
ft
.
Args
{
if
ps
.
isEmpty
(
a
)
{
continue
}
if
!
first
{
ps
.
writeString
(
"
"
)
}
ps
.
print
(
a
)
first
=
false
}
ps
.
writeByte
(
')'
)
ps
.
inner
=
save
ps
.
printInner
(
false
)
}

// printArgs prints the arguments of a function type.  It looks at the
// inner types for spacing.

printArgs prints the arguments of a function type . It looks at the inner types for spacing .


func parenthesize(ps *printState, val AST) {
	paren := false
	switch v := val.(type) {
	case *Name, *InitializerList, *FunctionParam:
	case *Qualified:
		if v.LocalName {
			paren = true
		}
	default:
		paren = true
	}
	if paren {
		ps.writeByte('(')
	}
	ps.print(val)
	if paren {
		ps.writeByte(')')
	}
}

func parenthesize ( ps * printState , val AST ) { paren := false switch v := val . ( type ) { case * Name , * InitializerList , * FunctionParam : case * Qualified : if v . LocalName { paren = true } default : paren = true } if paren { ps . writeByte ( '(' ) } ps . print ( val ) if paren { ps . writeByte ( ')' ) } }

// The parenthesize function prints the string for val, wrapped in
// parentheses if necessary.

The parenthesize function prints the string for val wrapped in parentheses if necessary .


func (ps *printState) printInner(prefixOnly bool) []AST {
	var save []AST
	var psave *[]AST
	if prefixOnly {
		psave = &save
	}
	for len(ps.inner) > 0 {
		ps.printOneInner(psave)
	}
	return save
}

func ( ps * printState ) printInner ( prefixOnly bool ) [ ] AST { var save [ ] AST var psave * [ ] AST if prefixOnly { psave = & save } for len ( ps . inner ) > 0 { ps . printOneInner ( psave ) } return save }


func (ps *printState) printOneInner(save *[]AST) {
	if len(ps.inner) == 0 {
		panic("printOneInner called with no inner types")
	}
	ln := len(ps.inner)
	a := ps.inner[ln-1]
	ps.inner = ps.inner[:ln-1]

	if save != nil {
		if _, ok := a.(*MethodWithQualifiers); ok {
			*save = append(*save, a)
			return
		}
	}

	if ip, ok := a.(innerPrinter); ok {
		ip.printInner(ps)
	} else {
		ps.print(a)
	}
}

func ( ps * printState ) printOneInner ( save * [ ] AST ) { if len ( ps . inner ) == 0 { panic ( " " ) } ln := len ( ps . inner ) a := ps . inner [ ln - 1 ] ps . inner = ps . inner [ : ln - 1 ] if save != nil { if _ , ok := a . ( * MethodWithQualifiers ) ; ok { * save = append ( * save , a ) return } } if ip , ok := a . ( innerPrinter ) ; ok { ip . printInner ( ps ) } else { ps . print ( a ) } }

// Print the most recent inner type.  If save is not nil, only print
// prefixes.

Print the most recent inner type . If save is not nil only print prefixes .


func (ps *printState) isEmpty(a AST) bool {
	switch a := a.(type) {
	case *ArgumentPack:
		return len(a.Args) == 0
	case *ExprList:
		return len(a.Exprs) == 0
	case *PackExpansion:
		return a.Pack != nil && ps.isEmpty(a.Base)
	default:
		return false
	}
}

func ( ps * printState ) isEmpty ( a AST ) bool { switch a := a . ( type ) { case * ArgumentPack : return len ( a . Args ) == 0 case * ExprList : return len ( a . Exprs ) == 0 case * PackExpansion : return a . Pack != nil && ps . isEmpty ( a . Base ) default : return false } }

// isEmpty returns whether printing a will not print anything.

isEmpty returns whether printing a will not print anything .


func Filter(name string, options ...Option) string {
	ret, err := ToString(name, options...)
	if err != nil {
		return name
	}
	return ret
}

func Filter ( name string , options ... Option ) string { ret , err := ToString ( name , options ... ) if err != nil { return name } return ret }

// Filter demangles a C++ symbol name, returning the human-readable C++ name.
// If any error occurs during demangling, the input string is returned.

Filter demangles a C ++ symbol name returning the human - readable C ++ name . If any error occurs during demangling the input string is returned .


func ToString(name string, options ...Option) (string, error) {
	a, err := ToAST(name, options...)
	if err != nil {
		return "", err
	}
	return ASTToString(a, options...), nil
}

func ToString ( name string , options ... Option ) ( string , error ) { a , err := ToAST ( name , options ... ) if err != nil { return " " , err } return ASTToString ( a , options ... ) , nil }

// ToString demangles a C++ symbol name, returning human-readable C++
// name or an error.
// If the name does not appear to be a C++ symbol name at all, the
// error will be ErrNotMangledName.

ToString demangles a C ++ symbol name returning human - readable C ++ name or an error . If the name does not appear to be a C ++ symbol name at all the error will be ErrNotMangledName .


func ToAST(name string, options ...Option) (AST, error) {
	if strings.HasPrefix(name, "_Z") {
		a, err := doDemangle(name[2:], options...)
		return a, adjustErr(err, 2)
	}

	const prefix = "_GLOBAL_"
	if strings.HasPrefix(name, prefix) {
		// The standard demangler ignores NoParams for global
		// constructors.  We are compatible.
		i := 0
		for i < len(options) {
			if options[i] == NoParams {
				options = append(options[:i], options[i+1:]...)
			} else {
				i++
			}
		}
		a, err := globalCDtorName(name[len(prefix):], options...)
		return a, adjustErr(err, len(prefix))
	}

	return nil, ErrNotMangledName
}

// ToAST demangles a C++ symbol name into an abstract syntax tree
// representing the symbol.
// If the NoParams option is passed, and the name has a function type,
// the parameter types are not demangled.
// If the name does not appear to be a C++ symbol name at all, the
// error will be ErrNotMangledName.

ToAST demangles a C ++ symbol name into an abstract syntax tree representing the symbol . If the NoParams option is passed and the name has a function type the parameter types are not demangled . If the name does not appear to be a C ++ symbol name at all the error will be ErrNotMangledName .


func doDemangle(name string, options ...Option) (ret AST, err error) {
	// When the demangling routines encounter an error, they panic
	// with a value of type demangleErr.
	defer func() {
		if r := recover(); r != nil {
			if de, ok := r.(demangleErr); ok {
				ret = nil
				err = de
				return
			}
			panic(r)
		}
	}()

	params := true
	clones := true
	verbose := false
	for _, o := range options {
		switch o {
		case NoParams:
			params = false
			clones = false
		case NoTemplateParams:
		// This is a valid option but only affect printing of the AST.
		case NoClones:
			clones = false
		case Verbose:
			verbose = true
		default:
			return nil, fmt.Errorf("unrecognized demangler option %v", o)
		}
	}

	st := &state{str: name, verbose: verbose}
	a := st.encoding(params, notForLocalName)

	// Accept a clone suffix.
	if clones {
		for len(st.str) > 1 && st.str[0] == '.' && (isLower(st.str[1]) || st.str[1] == '_' || isDigit(st.str[1])) {
			a = st.cloneSuffix(a)
		}
	}

	if clones && len(st.str) > 0 {
		st.fail("unparsed characters at end of mangled name")
	}

	return a, nil
}

// The doDemangle function is the entry point into the demangler proper.

The doDemangle function is the entry point into the demangler proper .


func (st *state) copy() *state {
	n := new(state)
	*n = *st
	return n
}

func ( st * state ) copy ( ) * state { n := new ( state ) * n = * st return n }

// copy returns a copy of the current state.

copy returns a copy of the current state .


func (st *state) fail(err string) {
	panic(demangleErr{err: err, off: st.off})
}

func ( st * state ) fail ( err string ) { panic ( demangleErr { err : err , off : st . off } ) }

// fail panics with demangleErr, to be caught in doDemangle.

fail panics with demangleErr to be caught in doDemangle .


func (st *state) failEarlier(err string, dec int) {
	if st.off < dec {
		panic("internal error")
	}
	panic(demangleErr{err: err, off: st.off - dec})
}

func ( st * state ) failEarlier ( err string , dec int ) { if st . off < dec { panic ( " " ) } panic ( demangleErr { err : err , off : st . off - dec } ) }

// failEarlier is like fail, but decrements the offset to indicate
// that the point of failure occurred earlier in the string.

failEarlier is like fail but decrements the offset to indicate that the point of failure occurred earlier in the string .


func (st *state) advance(add int) {
	if len(st.str) < add {
		panic("internal error")
	}
	st.str = st.str[add:]
	st.off += add
}

func ( st * state ) advance ( add int ) { if len ( st . str ) < add { panic ( " " ) } st . str = st . str [ add : ] st . off += add }

// advance advances the current string offset.

advance advances the current string offset .


func (st *state) checkChar(c byte) {
	if len(st.str) == 0 || st.str[0] != c {
		panic("internal error")
	}
	st.advance(1)
}

func ( st * state ) checkChar ( c byte ) { if len ( st . str ) == 0 || st . str [ 0 ] != c { panic ( " " ) } st . advance ( 1 ) }

// checkChar requires that the next character in the string be c, and
// advances past it.

checkChar requires that the next character in the string be c and advances past it .


func (de demangleErr) Error() string {
	return fmt.Sprintf("%s at %d", de.err, de.off)
}

func ( de demangleErr ) Error ( ) string { return fmt . Sprintf ( " " , de . err , de . off ) }

// Error implements the builtin error interface for demangleErr.

Error implements the builtin error interface for demangleErr .


func adjustErr(err error, adj int) error {
	if err == nil {
		return nil
	}
	if de, ok := err.(demangleErr); ok {
		de.off += adj
		return de
	}
	return err
}

func adjustErr ( err error , adj int ) error { if err == nil { return nil } if de , ok := err . ( demangleErr ) ; ok { de . off += adj return de } return err }

// adjustErr adjusts the position of err, if it is a demangleErr,
// and returns err.

adjustErr adjusts the position of err if it is a demangleErr and returns err .


func hasReturnType(a AST) bool {
	switch a := a.(type) {
	case *Template:
		return !isCDtorConversion(a.Name)
	case *TypeWithQualifiers:
		return hasReturnType(a.Base)
	case *MethodWithQualifiers:
		return hasReturnType(a.Method)
	default:
		return false
	}
}

func hasReturnType ( a AST ) bool { switch a := a . ( type ) { case * Template : return ! isCDtorConversion ( a . Name ) case * TypeWithQualifiers : return hasReturnType ( a . Base ) case * MethodWithQualifiers : return hasReturnType ( a . Method ) default : return false } }

// hasReturnType returns whether the mangled form of a will have a
// return type.

hasReturnType returns whether the mangled form of a will have a return type .


func isCDtorConversion(a AST) bool {
	switch a := a.(type) {
	case *Qualified:
		return isCDtorConversion(a.Name)
	case *Constructor, *Destructor, *Cast:
		return true
	default:
		return false
	}
}

func isCDtorConversion ( a AST ) bool { switch a := a . ( type ) { case * Qualified : return isCDtorConversion ( a . Name ) case * Constructor , * Destructor , * Cast : return true default : return false } }

// isCDtorConversion returns when an AST is a constructor, a
// destructor, or a conversion operator.

isCDtorConversion returns when an AST is a constructor a destructor or a conversion operator .


func (st *state) javaResource() AST {
	off := st.off
	ln := st.number()
	if ln <= 1 {
		st.failEarlier("java resource length less than 1", st.off-off)
	}
	if len(st.str) == 0 || st.str[0] != '_' {
		st.fail("expected _ after number")
	}
	st.advance(1)
	ln--
	if len(st.str) < ln {
		st.fail("not enough characters for java resource length")
	}
	str := st.str[:ln]
	final := ""
	st.advance(ln)
	for i := 0; i < len(str); i++ {
		if str[i] != '$' {
			final += string(str[i])
		} else {
			if len(str) <= i+1 {
				st.failEarlier("java resource escape at end of string", 1)
			}
			i++
			r, ok := map[byte]string{
				'S': "/",
				'_': ".",
				'$': "$",
			}[str[i]]
			if !ok {
				st.failEarlier("unrecognized java resource escape", ln-i-1)
			}
			final += r
		}
	}
	return &Special{Prefix: "java resource ", Val: &Name{Name: final}}
}

func ( st * state ) javaResource ( ) AST { off := st . off ln := st . number ( ) if ln <= 1 { st . failEarlier ( " " , st . off - off ) } if len ( st . str ) == 0 || st . str [ 0 ] != '_' { st . fail ( " " ) } st . advance ( 1 ) ln -- if len ( st . str ) < ln { st . fail ( " " ) } str := st . str [ : ln ] final := " " st . advance ( ln ) for i := 0 ; i < len ( str ) ; i ++ { if str [ i ] != '$' { final += string ( str [ i ] ) } else { if len ( str ) <= i + 1 { st . failEarlier ( " " , 1 ) } i ++ r , ok := map [ byte ] string { 'S' : " " , '_' : " " , '$' : " " , } [ str [ i ] ] if ! ok { st . failEarlier ( " " , ln - i - 1 ) } final += r } } return & Special { Prefix : " " , Val : & Name { Name : final } } }


func mergeQualifiers(q1, q2 Qualifiers) Qualifiers {
	m := make(map[string]bool)
	for _, qual := range q1 {
		m[qual] = true
	}
	for _, qual := range q2 {
		if !m[qual] {
			q1 = append(q1, qual)
			m[qual] = true
		}
	}
	return q1
}

func mergeQualifiers ( q1 , q2 Qualifiers ) Qualifiers { m := make ( map [ string ] bool ) for _ , qual := range q1 { m [ qual ] = true } for _ , qual := range q2 { if ! m [ qual ] { q1 = append ( q1 , qual ) m [ qual ] = true } } return q1 }

// mergeQualifiers merges two qualifer lists into one.

mergeQualifiers merges two qualifer lists into one .


func (st *state) setTemplate(a AST, tmpl *Template) {
	var seen []AST
	a.Traverse(func(a AST) bool {
		switch a := a.(type) {
		case *TemplateParam:
			if a.Template != nil {
				if tmpl != nil {
					st.fail("duplicate template parameters")
				}
				return false
			}
			if tmpl == nil {
				st.fail("cast template parameter not in scope of template")
			}
			if a.Index >= len(tmpl.Args) {
				st.fail(fmt.Sprintf("cast template index out of range (%d >= %d)", a.Index, len(tmpl.Args)))
			}
			a.Template = tmpl
			return false
		default:
			for _, v := range seen {
				if v == a {
					return false
				}
			}
			seen = append(seen, a)
			return true
		}
	})
}

func ( st * state ) setTemplate ( a AST , tmpl * Template ) { var seen [ ] AST a . Traverse ( func ( a AST ) bool { switch a := a . ( type ) { case * TemplateParam : if a . Template != nil { if tmpl != nil { st . fail ( " " ) } return false } if tmpl == nil { st . fail ( " " ) } if a . Index >= len ( tmpl . Args ) { st . fail ( fmt . Sprintf ( " " , a . Index , len ( tmpl . Args ) ) ) } a . Template = tmpl return false default : for _ , v := range seen { if v == a { return false } } seen = append ( seen , a ) return true } } ) }

// setTemplate sets the Template field of any TemplateParam's in a.
// This handles the forward referencing template parameters found in
// cast operators.

setTemplate sets the Template field of any TemplateParam s in a . This handles the forward referencing template parameters found in cast operators .


func (st *state) clearTemplateArgs(args []AST) {
	for _, a := range args {
		st.setTemplate(a, nil)
	}
}

func ( st * state ) clearTemplateArgs ( args [ ] AST ) { for _ , a := range args { st . setTemplate ( a , nil ) } }

// clearTemplateArgs gives an error for any unset Template field in
// args.  This handles erroneous cases where a cast operator with a
// forward referenced template is in the scope of another cast
// operator.

clearTemplateArgs gives an error for any unset Template field in args . This handles erroneous cases where a cast operator with a forward referenced template is in the scope of another cast operator .


func (st *state) exprList(stop byte) AST {
	if len(st.str) > 0 && st.str[0] == stop {
		st.advance(1)
		return &ExprList{Exprs: nil}
	}

	var exprs []AST
	for {
		e := st.expression()
		exprs = append(exprs, e)
		if len(st.str) > 0 && st.str[0] == stop {
			st.advance(1)
			break
		}
	}
	return &ExprList{Exprs: exprs}
}

func ( st * state ) exprList ( stop byte ) AST { if len ( st . str ) > 0 && st . str [ 0 ] == stop { st . advance ( 1 ) return & ExprList { Exprs : nil } } var exprs [ ] AST for { e := st . expression ( ) exprs = append ( exprs , e ) if len ( st . str ) > 0 && st . str [ 0 ] == stop { st . advance ( 1 ) break } } return & ExprList { Exprs : exprs } }

// exprList parses a sequence of expressions up to a terminating character.

exprList parses a sequence of expressions up to a terminating character .


func (st *state) cloneSuffix(a AST) AST {
	i := 0
	if len(st.str) > 1 && st.str[0] == '.' && (isLower(st.str[1]) || st.str[1] == '_') {
		i += 2
		for len(st.str) > i && (isLower(st.str[i]) || st.str[i] == '_') {
			i++
		}
	}
	for len(st.str) > i+1 && st.str[i] == '.' && isDigit(st.str[i+1]) {
		i += 2
		for len(st.str) > i && isDigit(st.str[i]) {
			i++
		}
	}
	suffix := st.str[:i]
	st.advance(i)
	return &Clone{Base: a, Suffix: suffix}
}

func ( st * state ) cloneSuffix ( a AST ) AST { i := 0 if len ( st . str ) > 1 && st . str [ 0 ] == '.' && ( isLower ( st . str [ 1 ] ) || st . str [ 1 ] == '_' ) { i += 2 for len ( st . str ) > i && ( isLower ( st . str [ i ] ) || st . str [ i ] == '_' ) { i ++ } } for len ( st . str ) > i + 1 && st . str [ i ] == '.' && isDigit ( st . str [ i + 1 ] ) { i += 2 for len ( st . str ) > i && isDigit ( st . str [ i ] ) { i ++ } } suffix := st . str [ : i ] st . advance ( i ) return & Clone { Base : a , Suffix : suffix } }

// Recognize a clone suffix.  These are not part of the mangling API,
// but are added by GCC when cloning functions.

Recognize a clone suffix . These are not part of the mangling API but are added by GCC when cloning functions .


func simplify(a AST) AST {
	var seen []AST
	skip := func(a AST) bool {
		for _, v := range seen {
			if v == a {
				return true
			}
		}
		seen = append(seen, a)
		return false
	}
	if r := a.Copy(simplifyOne, skip); r != nil {
		return r
	}
	return a
}

func simplify ( a AST ) AST { var seen [ ] AST skip := func ( a AST ) bool { for _ , v := range seen { if v == a { return true } } seen = append ( seen , a ) return false } if r := a . Copy ( simplifyOne , skip ) ; r != nil { return r } return a }

// simplify replaces template parameters with their expansions, and
// merges qualifiers.

simplify replaces template parameters with their expansions and merges qualifiers .


func (st *state) findArgumentPack(a AST) *ArgumentPack {
	var seen []AST
	var ret *ArgumentPack
	a.Traverse(func(a AST) bool {
		if ret != nil {
			return false
		}
		switch a := a.(type) {
		case *TemplateParam:
			if a.Template == nil || a.Index >= len(a.Template.Args) {
				return true
			}
			if pack, ok := a.Template.Args[a.Index].(*ArgumentPack); ok {
				ret = pack
				return false
			}
		case *PackExpansion, *Closure, *Name:
			return false
		case *TaggedName, *Operator, *BuiltinType, *FunctionParam:
			return false
		case *UnnamedType, *FixedType, *DefaultArg:
			return false
		}
		for _, v := range seen {
			if v == a {
				return false
			}
		}
		seen = append(seen, a)
		return true
	})
	return ret
}

func ( st * state ) findArgumentPack ( a AST ) * ArgumentPack { var seen [ ] AST var ret * ArgumentPack a . Traverse ( func ( a AST ) bool { if ret != nil { return false } switch a := a . ( type ) { case * TemplateParam : if a . Template == nil || a . Index >= len ( a . Template . Args ) { return true } if pack , ok := a . Template . Args [ a . Index ] . ( * ArgumentPack ) ; ok { ret = pack return false } case * PackExpansion , * Closure , * Name : return false case * TaggedName , * Operator , * BuiltinType , * FunctionParam : return false case * UnnamedType , * FixedType , * DefaultArg : return false } for _ , v := range seen { if v == a { return false } } seen = append ( seen , a ) return true } ) return ret }

// findArgumentPack walks the AST looking for the argument pack for a
// pack expansion.  We find it via a template parameter.

findArgumentPack walks the AST looking for the argument pack for a pack expansion . We find it via a template parameter .


func doDemangle(out *bufio.Writer, name string) {
	skip := 0
	if name[0] == '.' || name[0] == '$' {
		skip++
	}
	if *stripUnderscore && name[skip] == '_' {
		skip++
	}
	result := demangle.Filter(name[skip:], options()...)
	if result == name[skip:] {
		out.WriteString(name)
	} else {
		if name[0] == '.' {
			out.WriteByte('.')
		}
		out.WriteString(result)
	}
}

func doDemangle ( out * bufio . Writer , name string ) { skip := 0 if name [ 0 ] == '.' || name [ 0 ] == '$' { skip ++ } if * stripUnderscore && name [ skip ] == '_' { skip ++ } result := demangle . Filter ( name [ skip : ] , options ( ) ... ) if result == name [ skip : ] { out . WriteString ( name ) } else { if name [ 0 ] == '.' { out . WriteByte ( '.' ) } out . WriteString ( result ) } }

// Demangle a string just as the GNU c++filt program does.

Demangle a string just as the GNU c ++ filt program does .


func options() []demangle.Option {
	var options []demangle.Option
	if *noParams {
		options = append(options, demangle.NoParams)
	}
	if !*noVerbose {
		options = append(options, demangle.Verbose)
	}
	return options
}

func options ( ) [ ] demangle . Option { var options [ ] demangle . Option if * noParams { options = append ( options , demangle . NoParams ) } if ! * noVerbose { options = append ( options , demangle . Verbose ) } return options }

// options returns the demangling options to use based on the command
// line flags.

options returns the demangling options to use based on the command line flags .


func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) martini.Handler {
	return func(context martini.Context, req *http.Request) {
		var errors Errors

		ensureNotPointer(formStruct)
		formStruct := reflect.New(reflect.TypeOf(formStruct))

		// This if check is necessary due to https://github.com/martini-contrib/csrf/issues/6
		if req.MultipartForm == nil {
			// Workaround for multipart forms returning nil instead of an error
			// when content is not multipart; see https://code.google.com/p/go/issues/detail?id=6334
			if multipartReader, err := req.MultipartReader(); err != nil {
				// TODO: Cover this and the next error check with tests
				errors.Add([]string{}, DeserializationError, err.Error())
			} else {
				form, parseErr := multipartReader.ReadForm(MaxMemory)
				if parseErr != nil {
					errors.Add([]string{}, DeserializationError, parseErr.Error())
				}
				req.MultipartForm = form
			}
		}

		mapForm(formStruct, req.MultipartForm.Value, req.MultipartForm.File, errors)
		validateAndMap(formStruct, context, errors, ifacePtr...)
	}

}

// MultipartForm works much like Form, except it can parse multipart forms
// and handle file uploads. Like the other deserialization middleware handlers,
// you can pass in an interface to make the interface available for injection
// into other handlers later.

MultipartForm works much like Form except it can parse multipart forms and handle file uploads . Like the other deserialization middleware handlers you can pass in an interface to make the interface available for injection into other handlers later .


func Json(jsonStruct interface{}, ifacePtr ...interface{}) martini.Handler {
	return func(context martini.Context, req *http.Request) {
		var errors Errors

		ensureNotPointer(jsonStruct)

		jsonStruct := reflect.New(reflect.TypeOf(jsonStruct))

		if req.Body != nil {
			defer req.Body.Close()
			err := json.NewDecoder(req.Body).Decode(jsonStruct.Interface())
			if err != nil && err != io.EOF {
				errors.Add([]string{}, DeserializationError, err.Error())
			}
		}

		validateAndMap(jsonStruct, context, errors, ifacePtr...)
	}
}

func Json ( jsonStruct interface { } , ifacePtr ... interface { } ) martini . Handler { return func ( context martini . Context , req * http . Request ) { var errors Errors ensureNotPointer ( jsonStruct ) jsonStruct := reflect . New ( reflect . TypeOf ( jsonStruct ) ) if req . Body != nil { defer req . Body . Close ( ) err := json . NewDecoder ( req . Body ) . Decode ( jsonStruct . Interface ( ) ) if err != nil && err != io . EOF { errors . Add ( [ ] string { } , DeserializationError , err . Error ( ) ) } } validateAndMap ( jsonStruct , context , errors , ifacePtr ... ) } }

// Json is middleware to deserialize a JSON payload from the request
// into the struct that is passed in. The resulting struct is then
// validated, but no error handling is actually performed here.
// An interface pointer can be added as a second argument in order
// to map the struct to a specific interface.

Json is middleware to deserialize a JSON payload from the request into the struct that is passed in . The resulting struct is then validated but no error handling is actually performed here . An interface pointer can be added as a second argument in order to map the struct to a specific interface .


func validateStruct(errors Errors, obj interface{}) Errors {
	typ := reflect.TypeOf(obj)
	val := reflect.ValueOf(obj)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		// Skip ignored and unexported fields in the struct
		if field.Tag.Get("form") == "-" || !val.Field(i).CanInterface() {
			continue
		}

		fieldValue := val.Field(i).Interface()
		zero := reflect.Zero(field.Type).Interface()

		// Validate nested and embedded structs (if pointer, only do so if not nil)
		if field.Type.Kind() == reflect.Struct ||
			(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue) &&
				field.Type.Elem().Kind() == reflect.Struct) {
			errors = validateStruct(errors, fieldValue)
		}

		if strings.Index(field.Tag.Get("binding"), "required") > -1 {
			if reflect.DeepEqual(zero, fieldValue) {
				name := field.Name
				if j := field.Tag.Get("json"); j != "" {
					name = j
				} else if f := field.Tag.Get("form"); f != "" {
					name = f
				}
				errors.Add([]string{name}, RequiredError, "Required")
			}
		}
	}
	return errors
}

// Performs required field checking on a struct


func ErrorHandler(errs Errors, resp http.ResponseWriter) {
	if len(errs) > 0 {
		resp.Header().Set("Content-Type", jsonContentType)
		if errs.Has(DeserializationError) {
			resp.WriteHeader(http.StatusBadRequest)
		} else if errs.Has(ContentTypeError) {
			resp.WriteHeader(http.StatusUnsupportedMediaType)
		} else {
			resp.WriteHeader(StatusUnprocessableEntity)
		}
		errOutput, _ := json.Marshal(errs)
		resp.Write(errOutput)
		return
	}
}

func ErrorHandler ( errs Errors , resp http . ResponseWriter ) { if len ( errs ) > 0 { resp . Header ( ) . Set ( " " , jsonContentType ) if errs . Has ( DeserializationError ) { resp . WriteHeader ( http . StatusBadRequest ) } else if errs . Has ( ContentTypeError ) { resp . WriteHeader ( http . StatusUnsupportedMediaType ) } else { resp . WriteHeader ( StatusUnprocessableEntity ) } errOutput , _ := json . Marshal ( errs ) resp . Write ( errOutput ) return } }

// ErrorHandler simply counts the number of errors in the
// context and, if more than 0, writes a response with an
// error code and a JSON payload describing the errors.
// The response will have a JSON content-type.
// Middleware remaining on the stack will not even see the request
// if, by this point, there are any errors.
// This is a "default" handler, of sorts, and you are
// welcome to use your own instead. The Bind middleware
// invokes this automatically for convenience.

ErrorHandler simply counts the number of errors in the context and if more than 0 writes a response with an error code and a JSON payload describing the errors . The response will have a JSON content - type . Middleware remaining on the stack will not even see the request if by this point there are any errors . This is a default handler of sorts and you are welcome to use your own instead . The Bind middleware invokes this automatically for convenience .


func (d *localeStore) Get(lang, section, format string) (string, bool) {
	if locale, ok := d.store[lang]; ok {
		if section == "" {
			section = goconfig.DEFAULT_SECTION
		}

		if value, err := locale.message.GetValue(section, format); err == nil {
			return value, true
		}
	}

	return "", false
}

func ( d * localeStore ) Get ( lang , section , format string ) ( string , bool ) { if locale , ok := d . store [ lang ] ; ok { if section == " " { section = goconfig . DEFAULT_SECTION } if value , err := locale . message . GetValue ( section , format ) ; err == nil { return value , true } } return " " , false }


func SetMessage(lang, filePath string, appendFiles ...string) error {
	return SetMessageWithDesc(lang, lang, filePath, appendFiles...)
}

func SetMessage ( lang , filePath string , appendFiles ... string ) error { return SetMessageWithDesc ( lang , lang , filePath , appendFiles ... ) }

// SetMessage sets the message file for localization.

SetMessage sets the message file for localization .


func (c *Client) Idle(stop <-chan struct{}) error {
	if c.LogoutTimeout == 0 {
		return c.idle(stop)
	}

	t := time.NewTicker(c.LogoutTimeout)
	defer t.Stop()

	for {
		stopOrRestart := make(chan struct{})
		done := make(chan error, 1)
		go func() {
			done <- c.idle(stopOrRestart)
		}()

		select {
		case <-t.C:
			close(stopOrRestart)
			if err := <-done; err != nil {
				return err
			}
		case <-stop:
			close(stopOrRestart)
			return <-done
		case err := <-done:
			if err != nil {
				return err
			}
		}
	}
}

func ( c * Client ) Idle ( stop <- chan struct { } ) error { if c . LogoutTimeout == 0 { return c . idle ( stop ) } t := time . NewTicker ( c . LogoutTimeout ) defer t . Stop ( ) for { stopOrRestart := make ( chan struct { } ) done := make ( chan error , 1 ) go func ( ) { done <- c . idle ( stopOrRestart ) } ( ) select { case <- t . C : close ( stopOrRestart ) if err := <- done ; err != nil { return err } case <- stop : close ( stopOrRestart ) return <- done case err := <- done : if err != nil { return err } } } }

// Idle indicates to the server that the client is ready to receive unsolicited
// mailbox update messages. When the client wants to send commands again, it
// must first close stop.

Idle indicates to the server that the client is ready to receive unsolicited mailbox update messages . When the client wants to send commands again it must first close stop .


func (c *Client) IdleWithFallback(stop <-chan struct{}, pollInterval time.Duration) error {
	if ok, err := c.SupportIdle(); err != nil {
		return err
	} else if ok {
		return c.Idle(stop)
	}

	if pollInterval == 0 {
		pollInterval = defaultPollInterval
	}

	t := time.NewTicker(pollInterval)
	defer t.Stop()

	for {
		select {
		case <-t.C:
			if err := c.c.Noop(); err != nil {
				return err
			}
		case <-stop:
			return nil
		case <-c.c.LoggedOut():
			return errors.New("disconnected while idling")
		}
	}
}

func ( c * Client ) IdleWithFallback ( stop <- chan struct { } , pollInterval time . Duration ) error { if ok , err := c . SupportIdle ( ) ; err != nil { return err } else if ok { return c . Idle ( stop ) } if pollInterval == 0 { pollInterval = defaultPollInterval } t := time . NewTicker ( pollInterval ) defer t . Stop ( ) for { select { case <- t . C : if err := c . c . Noop ( ) ; err != nil { return err } case <- stop : return nil case <- c . c . LoggedOut ( ) : return errors . New ( " " ) } } }

// IdleWithFallback tries to idle if the server supports it. If it doesn't, it
// falls back to polling. If pollInterval is zero, a sensible default will be
// used.

IdleWithFallback tries to idle if the server supports it . If it doesn t it falls back to polling . If pollInterval is zero a sensible default will be used .


func (s *Sentinel) putToBottom(addr string) {
	addrs := s.Addrs
	if addrs[len(addrs)-1] == addr {
		// Already on bottom.
		return
	}
	newAddrs := []string{}
	for _, a := range addrs {
		if a == addr {
			continue
		}
		newAddrs = append(newAddrs, a)
	}
	newAddrs = append(newAddrs, addr)
	s.Addrs = newAddrs
}

func
(
s
*
Sentinel
)
putToBottom
(
addr
string
)
{
addrs
:=
s
.
Addrs
if
addrs
[
len
(
addrs
)
1
]
==
addr
{
// Already on bottom.
return
}
newAddrs
:=
[
]
string
{
}
for
_
,
a
:=
range
addrs
{
if
a
==
addr
{
continue
}
newAddrs
=
append
(
newAddrs
,
a
)
}
newAddrs
=
append
(
newAddrs
,
addr
)
s
.
Addrs
=
newAddrs
}

// putToBottom puts Sentinel address to the bottom of address list.
// We call this method internally when see that some Sentinel failed to answer
// on application request so next time we start with another one.
//
// Lock must be held by caller.

putToBottom puts Sentinel address to the bottom of address list . We call this method internally when see that some Sentinel failed to answer on application request so next time we start with another one . Lock must be held by caller .


func (s *Sentinel) defaultPool(addr string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     3,
		MaxActive:   10,
		Wait:        true,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			return s.Dial(addr)
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func ( s * Sentinel ) defaultPool ( addr string ) * redis . Pool { return & redis . Pool { MaxIdle : 3 , MaxActive : 10 , Wait : true , IdleTimeout : 240 * time . Second , Dial : func ( ) ( redis . Conn , error ) { return s . Dial ( addr ) } , TestOnBorrow : func ( c redis . Conn , t time . Time ) error { _ , err := c . Do ( " " ) return err } , } }

// defaultPool returns a connection pool to one Sentinel. This allows
// us to call concurrent requests to Sentinel using connection Do method.

defaultPool returns a connection pool to one Sentinel . This allows us to call concurrent requests to Sentinel using connection Do method .


func (s *Sentinel) close() {
	if s.pools != nil {
		for _, pool := range s.pools {
			pool.Close()
		}
	}
	s.pools = nil
}

func ( s * Sentinel ) close ( ) { if s . pools != nil { for _ , pool := range s . pools { pool . Close ( ) } } s . pools = nil }

// close connection pool to Sentinel.
// Lock must be hold by caller.

close connection pool to Sentinel . Lock must be hold by caller .


func (s *Sentinel) MasterAddr() (string, error) {
	res, err := s.doUntilSuccess(func(c redis.Conn) (interface{}, error) {
		return queryForMaster(c, s.MasterName)
	})
	if err != nil {
		return "", err
	}
	return res.(string), nil
}

func ( s * Sentinel ) MasterAddr ( ) ( string , error ) { res , err := s . doUntilSuccess ( func ( c redis . Conn ) ( interface { } , error ) { return queryForMaster ( c , s . MasterName ) } ) if err != nil { return " " , err } return res . ( string ) , nil }

// MasterAddr returns an address of current Redis master instance.

MasterAddr returns an address of current Redis master instance .


func (s *Sentinel) SlaveAddrs() ([]string, error) {
	res, err := s.doUntilSuccess(func(c redis.Conn) (interface{}, error) {
		return queryForSlaveAddrs(c, s.MasterName)
	})
	if err != nil {
		return nil, err
	}
	return res.([]string), nil
}

func ( s * Sentinel ) SlaveAddrs ( ) ( [ ] string , error ) { res , err := s . doUntilSuccess ( func ( c redis . Conn ) ( interface { } , error ) { return queryForSlaveAddrs ( c , s . MasterName ) } ) if err != nil { return nil , err } return res . ( [ ] string ) , nil }

// SlaveAddrs returns a slice with known slave addresses of current master instance.

SlaveAddrs returns a slice with known slave addresses of current master instance .


func (s *Slave) Addr() string {
	return net.JoinHostPort(s.ip, s.port)
}

func ( s * Slave ) Addr ( ) string { return net . JoinHostPort ( s . ip , s . port ) }


func (s *Slave) Available() bool {
	return !strings.Contains(s.flags, "disconnected") && !strings.Contains(s.flags, "s_down")
}

func ( s * Slave ) Available ( ) bool { return ! strings . Contains ( s . flags , " " ) && ! strings . Contains ( s . flags , " " ) }

// Available returns if slave is in working state at moment based on information in slave flags.

Available returns if slave is in working state at moment based on information in slave flags .


func (s *Sentinel) Slaves() ([]*Slave, error) {
	res, err := s.doUntilSuccess(func(c redis.Conn) (interface{}, error) {
		return queryForSlaves(c, s.MasterName)
	})
	if err != nil {
		return nil, err
	}
	return res.([]*Slave), nil
}

func ( s * Sentinel ) Slaves ( ) ( [ ] * Slave , error ) { res , err := s . doUntilSuccess ( func ( c redis . Conn ) ( interface { } , error ) { return queryForSlaves ( c , s . MasterName ) } ) if err != nil { return nil , err } return res . ( [ ] * Slave ) , nil }

// Slaves returns a slice with known slaves of master instance.

Slaves returns a slice with known slaves of master instance .


func (s *Sentinel) SentinelAddrs() ([]string, error) {
	res, err := s.doUntilSuccess(func(c redis.Conn) (interface{}, error) {
		return queryForSentinels(c, s.MasterName)
	})
	if err != nil {
		return nil, err
	}
	return res.([]string), nil
}

func ( s * Sentinel ) SentinelAddrs ( ) ( [ ] string , error ) { res , err := s . doUntilSuccess ( func ( c redis . Conn ) ( interface { } , error ) { return queryForSentinels ( c , s . MasterName ) } ) if err != nil { return nil , err } return res . ( [ ] string ) , nil }

// SentinelAddrs returns a slice of known Sentinel addresses Sentinel server aware of.

SentinelAddrs returns a slice of known Sentinel addresses Sentinel server aware of .


func (s *Sentinel) Close() error {
	s.mu.Lock()
	s.close()
	s.mu.Unlock()
	return nil
}

func ( s * Sentinel ) Close ( ) error { s . mu . Lock ( ) s . close ( ) s . mu . Unlock ( ) return nil }

// Close closes current connection to Sentinel.

Close closes current connection to Sentinel .


func NewServerList(servers ...string) (*ServerList, error) {
	addrs := make([]*Addr, len(servers))
	for i, server := range servers {
		if strings.Contains(server, "/") {
			addr, err := net.ResolveUnixAddr("unix", server)
			if err != nil {
				return nil, err
			}
			addrs[i] = NewAddr(addr)
		} else {
			tcpaddr, err := net.ResolveTCPAddr("tcp", server)
			if err != nil {
				return nil, err
			}
			addrs[i] = NewAddr(tcpaddr)
		}
	}
	return &ServerList{addrs: addrs}, nil
}

func NewServerList ( servers ... string ) ( * ServerList , error ) { addrs := make ( [ ] * Addr , len ( servers ) ) for i , server := range servers { if strings . Contains ( server , " " ) { addr , err := net . ResolveUnixAddr ( " " , server ) if err != nil { return nil , err } addrs [ i ] = NewAddr ( addr ) } else { tcpaddr , err := net . ResolveTCPAddr ( " " , server ) if err != nil { return nil , err } addrs [ i ] = NewAddr ( tcpaddr ) } } return & ServerList { addrs : addrs } , nil }

// NewServerList returns a new ServerList with the given servers.
// All servers have the same weight. To give a server more weight,
// list it multiple times.
//
// NewServerList returns an error if any of the received addresses
// is not valid or fails to resolve, but it doesn't try to connect
// to the provided servers.

NewServerList returns a new ServerList with the given servers . All servers have the same weight . To give a server more weight list it multiple times . NewServerList returns an error if any of the received addresses is not valid or fails to resolve but it doesn t try to connect to the provided servers .


func NewFromServers(servers Servers) *Client {
	return &Client{
		timeout:        DefaultTimeout,
		maxIdlePerAddr: maxIdleConnsPerAddr,
		servers:        servers,
		freeconn:       make(map[string]chan *conn),
		bufPool:        make(chan []byte, poolSize()),
	}
}

func NewFromServers ( servers Servers ) * Client { return & Client { timeout : DefaultTimeout , maxIdlePerAddr : maxIdleConnsPerAddr , servers : servers , freeconn : make ( map [ string ] chan * conn ) , bufPool : make ( chan [ ] byte , poolSize ( ) ) , } }

// NewFromServers returns a new Client using the provided Servers.

NewFromServers returns a new Client using the provided Servers .


func (c *Client) Close() error {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.closeIdleConns()
	c.freeconn = nil
	c.maxIdlePerAddr = 0
	return nil
}

func ( c * Client ) Close ( ) error { c . mu . Lock ( ) defer c . mu . Unlock ( ) c . closeIdleConns ( ) c . freeconn = nil c . maxIdlePerAddr = 0 return nil }

// Close closes all currently open connections.

Close closes all currently open connections .


func (c *Client) Get(key string) (*Item, error) {
	cn, err := c.sendCommand(key, cmdGet, nil, 0, nil)
	if err != nil {
		return nil, err
	}
	return c.parseItemResponse(key, cn, true)
}

func ( c * Client ) Get ( key string ) ( * Item , error ) { cn , err := c . sendCommand ( key , cmdGet , nil , 0 , nil ) if err != nil { return nil , err } return c . parseItemResponse ( key , cn , true ) }

// Get gets the item for the given key. ErrCacheMiss is returned for a
// memcache cache miss. The key must be at most 250 bytes in length.

Get gets the item for the given key . ErrCacheMiss is returned for a memcache cache miss . The key must be at most 250 bytes in length .


func (c *Client) GetMulti(keys []string) (map[string]*Item, error) {
	keyMap := make(map[*Addr][]string)
	for _, key := range keys {
		addr, err := c.servers.PickServer(key)
		if err != nil {
			return nil, err
		}
		keyMap[addr] = append(keyMap[addr], key)
	}

	var chs []chan *Item
	for addr, keys := range keyMap {
		ch := make(chan *Item)
		chs = append(chs, ch)
		go func(addr *Addr, keys []string, ch chan *Item) {
			defer close(ch)
			cn, err := c.getConn(addr)
			if err != nil {
				return
			}
			defer c.condRelease(cn, &err)
			for _, k := range keys {
				if err = c.sendConnCommand(cn, k, cmdGetKQ, nil, 0, nil); err != nil {
					return
				}
			}
			if err = c.sendConnCommand(cn, "", cmdNoop, nil, 0, nil); err != nil {
				return
			}
			var item *Item
			for {
				item, err = c.parseItemResponse("", cn, false)
				if item == nil || item.Key == "" {
					// Noop response
					break
				}
				ch <- item
			}
		}(addr, keys, ch)
	}

	m := make(map[string]*Item)
	for _, ch := range chs {
		for item := range ch {
			m[item.Key] = item
		}
	}
	return m, nil
}

func
(
c
*
Client
)
GetMulti
(
keys
[
]
string
)
(
map
[
string
]
*
Item
,
error
)
{
keyMap
:=
make
(
map
[
*
Addr
]
[
]
string
)
for
_
,
key
:=
range
keys
{
addr
,
err
:=
c
.
servers
.
PickServer
(
key
)
if
err
!=
{
return
,
err
}
keyMap
[
addr
]
=
append
(
keyMap
[
addr
]
,
key
)
}
var
chs
[
]
chan
*
Item
for
addr
,
keys
:=
range
keyMap
{
ch
:=
make
(
chan
*
Item
)
chs
=
append
(
chs
,
ch
)
go
func
(
addr
*
Addr
,
keys
[
]
string
,
ch
chan
*
Item
)
{
defer
close
(
ch
)
cn
,
err
:=
c
.
getConn
(
addr
)
if
err
!=
{
return
}
defer
c
.
condRelease
(
cn
,
&
err
)
for
_
,
k
:=
range
keys
{
if
err
=
c
.
sendConnCommand
(
cn
,
k
,
cmdGetKQ
,
,
0
,
)
;
err
!=
{
return
}
}
if
err
=
c
.
sendConnCommand
(
cn
,
"
"
,
cmdNoop
,
,
0
,
)
;
err
!=
{
return
}
var
item
*
Item
for
{
item
,
err
=
c
.
parseItemResponse
(
"
"
,
cn
,
false
)
if
item
==
||
item
.
Key
==
"
"
{
// Noop response
break
}
ch
<-
item
}
}
(
addr
,
keys
,
ch
)
}
m
:=
make
(
map
[
string
]
*
Item
)
for
_
,
ch
:=
range
chs
{
for
item
:=
range
ch
{
m
[
item
.
Key
]
=
item
}
}
return
m
,
}

// GetMulti is a batch version of Get. The returned map from keys to
// items may have fewer elements than the input slice, due to memcache
// cache misses. Each key must be at most 250 bytes in length.
// If no error is returned, the returned map will also be non-nil.

GetMulti is a batch version of Get . The returned map from keys to items may have fewer elements than the input slice due to memcache cache misses . Each key must be at most 250 bytes in length . If no error is returned the returned map will also be non - nil .


func (c *Client) Set(item *Item) error {
	return c.populateOne(cmdSet, item, 0)
}

func ( c * Client ) Set ( item * Item ) error { return c . populateOne ( cmdSet , item , 0 ) }

// Set writes the given item, unconditionally.

Set writes the given item unconditionally .


func (c *Client) Add(item *Item) error {
	return c.populateOne(cmdAdd, item, 0)
}

func ( c * Client ) Add ( item * Item ) error { return c . populateOne ( cmdAdd , item , 0 ) }

// Add writes the given item, if no value already exists for its
// key. ErrNotStored is returned if that condition is not met.

Add writes the given item if no value already exists for its key . ErrNotStored is returned if that condition is not met .


func (c *Client) CompareAndSwap(item *Item) error {
	return c.populateOne(cmdSet, item, item.casid)
}

func ( c * Client ) CompareAndSwap ( item * Item ) error { return c . populateOne ( cmdSet , item , item . casid ) }

// CompareAndSwap writes the given item that was previously returned
// by Get, if the value was neither modified or evicted between the
// Get and the CompareAndSwap calls. The item's Key should not change
// between calls but all other item fields may differ. ErrCASConflict
// is returned if the value was modified in between the
// calls. ErrNotStored is returned if the value was evicted in between
// the calls.

CompareAndSwap writes the given item that was previously returned by Get if the value was neither modified or evicted between the Get and the CompareAndSwap calls . The item s Key should not change between calls but all other item fields may differ . ErrCASConflict is returned if the value was modified in between the calls . ErrNotStored is returned if the value was evicted in between the calls .


func (c *Client) Delete(key string) error {
	cn, err := c.sendCommand(key, cmdDelete, nil, 0, nil)
	if err != nil {
		return err
	}
	_, _, _, _, err = c.parseResponse(key, cn)
	c.condRelease(cn, &err)
	return err
}

func ( c * Client ) Delete ( key string ) error { cn , err := c . sendCommand ( key , cmdDelete , nil , 0 , nil ) if err != nil { return err } _ , _ , _ , _ , err = c . parseResponse ( key , cn ) c . condRelease ( cn , & err ) return err }

// Delete deletes the item with the provided key. The error ErrCacheMiss is
// returned if the item didn't already exist in the cache.

Delete deletes the item with the provided key . The error ErrCacheMiss is returned if the item didn t already exist in the cache .


func (c *Client) Increment(key string, delta uint64) (newValue uint64, err error) {
	return c.incrDecr(cmdIncr, key, delta)
}

func ( c * Client ) Increment ( key string , delta uint64 ) ( newValue uint64 , err error ) { return c . incrDecr ( cmdIncr , key , delta ) }

// Increment atomically increments key by delta. The return value is
// the new value after being incremented or an error. If the value
// didn't exist in memcached the error is ErrCacheMiss. The value in
// memcached must be an decimal number, or an error will be returned.
// On 64-bit overflow, the new value wraps around.

Increment atomically increments key by delta . The return value is the new value after being incremented or an error . If the value didn t exist in memcached the error is ErrCacheMiss . The value in memcached must be an decimal number or an error will be returned . On 64 - bit overflow the new value wraps around .


func (c *Client) Flush(expiration int) error {
	servers, err := c.servers.Servers()
	var failed []*Addr
	var errs []error
	if err != nil {
		return err
	}
	var extras []byte
	if expiration > 0 {
		extras = make([]byte, 4)
		putUint32(extras, uint32(expiration))
	}
	for _, addr := range servers {
		cn, err := c.getConn(addr)
		if err != nil {
			failed = append(failed, addr)
			errs = append(errs, err)
			continue
		}
		if err = c.sendConnCommand(cn, "", cmdFlush, nil, 0, extras); err == nil {
			_, _, _, _, err = c.parseResponse("", cn)
		}
		if err != nil {
			failed = append(failed, addr)
			errs = append(errs, err)
		}
		c.condRelease(cn, &err)
	}
	if len(failed) > 0 {
		var buf bytes.Buffer
		buf.WriteString("failed to flush some servers: ")
		for ii, addr := range failed {
			if ii > 0 {
				buf.WriteString(", ")
			}
			buf.WriteString(addr.String())
			buf.WriteString(": ")
			buf.WriteString(errs[ii].Error())
		}
		return errors.New(buf.String())
	}
	return nil
}

func ( c * Client ) Flush ( expiration int ) error { servers , err := c . servers . Servers ( ) var failed [ ] * Addr var errs [ ] error if err != nil { return err } var extras [ ] byte if expiration > 0 { extras = make ( [ ] byte , 4 ) putUint32 ( extras , uint32 ( expiration ) ) } for _ , addr := range servers { cn , err := c . getConn ( addr ) if err != nil { failed = append ( failed , addr ) errs = append ( errs , err ) continue } if err = c . sendConnCommand ( cn , " " , cmdFlush , nil , 0 , extras ) ; err == nil { _ , _ , _ , _ , err = c . parseResponse ( " " , cn ) } if err != nil { failed = append ( failed , addr ) errs = append ( errs , err ) } c . condRelease ( cn , & err ) } if len ( failed ) > 0 { var buf bytes . Buffer buf . WriteString ( " " ) for ii , addr := range failed { if ii > 0 { buf . WriteString ( " " ) } buf . WriteString ( addr . String ( ) ) buf . WriteString ( " " ) buf . WriteString ( errs [ ii ] . Error ( ) ) } return errors . New ( buf . String ( ) ) } return nil }

// Flush removes all the items in the cache after expiration seconds. If
// expiration is <= 0, it removes all the items right now.

Flush removes all the items in the cache after expiration seconds . If expiration is < = 0 it removes all the items right now .


func (pl *processLink) ChildClosing() <-chan struct{} {
	// grab a hold of it, and unlock, as .Closing may block.
	pl.Lock()
	child := pl.child
	pl.Unlock()

	if child == nil { // already closed? memory optimization.
		return closedCh
	}
	return child.Closing()
}

// Closing returns whether the child is closing


func OnClosingContext(p goprocess.Process) context.Context {
	return &procContext{
		done:  p.Closing(),
		which: closing,
	}
}

func OnClosingContext ( p goprocess . Process ) context . Context { return & procContext { done : p . Closing ( ) , which : closing , } }

// OnClosingContext derives a context from a given goprocess that will
// be 'Done' when the process is closing

OnClosingContext derives a context from a given goprocess that will be Done when the process is closing


func OnClosedContext(p goprocess.Process) context.Context {
	return &procContext{
		done:  p.Closed(),
		which: closed,
	}
}

func OnClosedContext ( p goprocess . Process ) context . Context { return & procContext { done : p . Closed ( ) , which : closed , } }

// OnClosedContext derives a context from a given goprocess that will
// be 'Done' when the process is closed

OnClosedContext derives a context from a given goprocess that will be Done when the process is closed


func LimitChan(limit int) chan struct{} {
	limitch := make(chan struct{}, limit)
	for i := 0; i < limit; i++ {
		limitch <- struct{}{}
	}
	return limitch
}

func LimitChan ( limit int ) chan struct { } { limitch := make ( chan struct { } , limit ) for i := 0 ; i < limit ; i ++ { limitch <- struct { } { } } return limitch }

// LimitChan returns a rate-limiting channel. it is the usual, simple,
// golang-idiomatic rate-limiting semaphore. This function merely
// initializes it with certain buffer size, and sends that many values,
// so it is ready to be used.

LimitChan returns a rate - limiting channel . it is the usual simple golang - idiomatic rate - limiting semaphore . This function merely initializes it with certain buffer size and sends that many values so it is ready to be used .


func WithParent(parent Process) Process {
	if parent == nil {
		panic("nil parent Process")
	}
	q := newProcess(nil)
	parent.AddChild(q)
	return q
}

func WithParent ( parent Process ) Process { if parent == nil { panic ( " " ) } q := newProcess ( nil ) parent . AddChild ( q ) return q }

// WithParent constructs and returns a Process with a given parent.

WithParent constructs and returns a Process with a given parent .


func WithContextAndTeardown(ctx context.Context, tf goprocess.TeardownFunc) goprocess.Process {
	p := goprocess.WithTeardown(tf)
	CloseAfterContext(p, ctx)
	return p
}

func WithContextAndTeardown ( ctx context . Context , tf goprocess . TeardownFunc ) goprocess . Process { p := goprocess . WithTeardown ( tf ) CloseAfterContext ( p , ctx ) return p }

// WithContextAndTeardown is a helper function to set teardown at initiation
// of WithContext

WithContextAndTeardown is a helper function to set teardown at initiation of WithContext


func (p *process) SetTeardown(tf TeardownFunc) {
	if tf == nil {
		panic("cannot set nil TeardownFunc")
	}

	p.Lock()
	if p.teardown != nil {
		panic("cannot SetTeardown twice")
	}

	p.teardown = tf
	select {
	case <-p.Closed():
		p.closeErr = tf()
	default:
	}
	p.Unlock()
}

func ( p * process ) SetTeardown ( tf TeardownFunc ) { if tf == nil { panic ( " " ) } p . Lock ( ) if p . teardown != nil { panic ( " " ) } p . teardown = tf select { case <- p . Closed ( ) : p . closeErr = tf ( ) default : } p . Unlock ( ) }

// SetTeardown to assign a teardown function


func (p *process) doClose() {
	// this function is only be called once (protected by p.Lock()).
	// and it will panic (on closing channels) otherwise.

	close(p.closing) // signal that we're shutting down (Closing)

	for len(p.children) > 0 || len(p.waitfors) > 0 {
		for plc, _ := range p.children {
			child := plc.Child()
			if child != nil { // check because child may already have been removed.
				go child.Close() // force all children to shut down
			}
			plc.ParentClear()
		}
		p.children = nil // clear them. release memory.

		// we must be careful not to iterate over waitfors directly, as it may
		// change under our feet.
		wf := p.waitfors
		p.waitfors = nil // clear them. release memory.
		for w, _ := range wf {
			// Here, we wait UNLOCKED, so that waitfors who are in the middle of
			// adding a child to us can finish. we will immediately close the child.
			p.Unlock()
			<-w.ChildClosed() // wait till all waitfors are fully closed (before teardown)
			p.Lock()
			w.ParentClear()
		}
	}

	if p.teardown != nil {
		p.closeErr = p.teardown() // actually run the close logic (ok safe to teardown)
	}
	close(p.closed) // signal that we're shut down (Closed)

	// go remove all the parents from the process links. optimization.
	go func(waiters []*processLink) {
		for _, pl := range waiters {
			pl.ClearChild()
			pr, ok := pl.Parent().(*process)
			if !ok {
				// parent has already been called to close
				continue
			}
			pr.Lock()
			delete(pr.waitfors, pl)
			delete(pr.children, pl)
			pr.Unlock()
		}
	}(p.waiters) // pass in so
	p.waiters = nil // clear them. release memory.
}


func (p *process) CloseAfterChildren() error {
	p.Lock()
	select {
	case <-p.Closed():
		p.Unlock()
		return p.Close() // get error. safe, after p.Closed()
	case <-p.waiting: // already called it.
		p.Unlock()
		<-p.Closed()
		return p.Close() // get error. safe, after p.Closed()
	default:
	}
	p.Unlock()

	// here only from one goroutine.

	nextToWaitFor := func() Process {
		p.Lock()
		defer p.Unlock()
		for e, _ := range p.waitfors {
			c := e.Child()
			if c == nil {
				continue
			}

			select {
			case <-c.Closed():
			default:
				return c
			}
		}
		return nil
	}

	// wait for all processes we're waiting for are closed.
	// the semantics here are simple: we will _only_ close
	// if there are no processes currently waiting for.
	for next := nextToWaitFor(); next != nil; next = nextToWaitFor() {
		<-next.Closed()
	}

	// YAY! we're done. close
	return p.Close()
}

// We will only wait on the children we have now.
// We will not wait on children added subsequently.
// this may change in the future.

We will only wait on the children we have now . We will not wait on children added subsequently . this may change in the future .


func Ticker(ticker <-chan time.Time, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(callOnTicker(ticker, procfunc))
}

func Ticker ( ticker <- chan time . Time , procfunc gp . ProcessFunc ) gp . Process { return gp . Go ( callOnTicker ( ticker , procfunc ) ) }

// Ticker calls the given ProcessFunc every time the ticker fires.
// This is sequentially rate limited, only one call will be in-flight at a time.

Ticker calls the given ProcessFunc every time the ticker fires . This is sequentially rate limited only one call will be in - flight at a time .


func TickerGo(ticker <-chan time.Time, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(goCallOnTicker(ticker, procfunc))
}

func TickerGo ( ticker <- chan time . Time , procfunc gp . ProcessFunc ) gp . Process { return gp . Go ( goCallOnTicker ( ticker , procfunc ) ) }

// TickerGo calls the given ProcessFunc every time the ticker fires.
// This is not rate limited, multiple calls could be in-flight at the same time.

TickerGo calls the given ProcessFunc every time the ticker fires . This is not rate limited multiple calls could be in - flight at the same time .


func (c *CustomerIO) Identify(customerID string, attributes map[string]interface{}) error {
	j, err := json.Marshal(attributes)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("PUT", c.customerURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.customerURL(customerID), responseBody}
	}

	return nil
}

func ( c * CustomerIO ) Identify ( customerID string , attributes map [ string ] interface { } ) error { j , err := json . Marshal ( attributes ) if err != nil { return err } status , responseBody , err := c . request ( " " , c . customerURL ( customerID ) , j ) if err != nil { return err } else if status != 200 { return & CustomerIOError { status , c . customerURL ( customerID ) , responseBody } } return nil }

// Identify identifies a customer and sets their attributes


func (c *CustomerIO) Track(customerID string, eventName string, data map[string]interface{}) error {

	body := map[string]interface{}{"name": eventName, "data": data}
	j, err := json.Marshal(body)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("POST", c.eventURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.eventURL(customerID), responseBody}
	}

	return nil
}

func ( c * CustomerIO ) Track ( customerID string , eventName string , data map [ string ] interface { } ) error { body := map [ string ] interface { } { " " : eventName , " " : data } j , err := json . Marshal ( body ) if err != nil { return err } status , responseBody , err := c . request ( " " , c . eventURL ( customerID ) , j ) if err != nil { return err } else if status != 200 { return & CustomerIOError { status , c . eventURL ( customerID ) , responseBody } } return nil }

// Track sends a single event to Customer.io for the supplied user

Track sends a single event to Customer . io for the supplied user


func (c *CustomerIO) TrackAnonymous(eventName string, data map[string]interface{}) error {
	body := map[string]interface{}{"name": eventName, "data": data}
	j, err := json.Marshal(body)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("POST", c.anonURL(), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.anonURL(), responseBody}
	}

	return nil
}

func ( c * CustomerIO ) TrackAnonymous ( eventName string , data map [ string ] interface { } ) error { body := map [ string ] interface { } { " " : eventName , " " : data } j , err := json . Marshal ( body ) if err != nil { return err } status , responseBody , err := c . request ( " " , c . anonURL ( ) , j ) if err != nil { return err } else if status != 200 { return & CustomerIOError { status , c . anonURL ( ) , responseBody } } return nil }

// TrackAnonymous sends a single event to Customer.io for the anonymous user

TrackAnonymous sends a single event to Customer . io for the anonymous user


func (c *CustomerIO) Delete(customerID string) error {
	status, responseBody, err := c.request("DELETE", c.customerURL(customerID), []byte{})

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.customerURL(customerID), responseBody}
	}

	return nil
}

func ( c * CustomerIO ) Delete ( customerID string ) error { status , responseBody , err := c . request ( " " , c . customerURL ( customerID ) , [ ] byte { } ) if err != nil { return err } else if status != 200 { return & CustomerIOError { status , c . customerURL ( customerID ) , responseBody } } return nil }


func (c *CustomerIO) AddDevice(customerID string, deviceID string, platform string, data map[string]interface{}) error {
	if customerID == "" {
		return errors.New("customerID is a required field")
	}
	if deviceID == "" {
		return errors.New("deviceID is a required field")
	}
	if platform == "" {
		return errors.New("platform is a required field")
	}

	body := map[string]map[string]interface{}{"device": {"id": deviceID, "platform": platform}}
	for k, v := range data {
		body["device"][k] = v
	}
	j, err := json.Marshal(body)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("PUT", c.deviceURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.deviceURL(customerID), responseBody}
	}

	return nil
}

func ( c * CustomerIO ) AddDevice ( customerID string , deviceID string , platform string , data map [ string ] interface { } ) error { if customerID == " " { return errors . New ( " " ) } if deviceID == " " { return errors . New ( " " ) } if platform == " " { return errors . New ( " " ) } body := map [ string ] map [ string ] interface { } { " " : { " " : deviceID , " " : platform } } for k , v := range data { body [ " " ] [ k ] = v } j , err := json . Marshal ( body ) if err != nil { return err } status , responseBody , err := c . request ( " " , c . deviceURL ( customerID ) , j ) if err != nil { return err } else if status != 200 { return & CustomerIOError { status , c . deviceURL ( customerID ) , responseBody } } return nil }

// AddDevice adds a device for a customer


func (c *CustomerIO) DeleteDevice(customerID string, deviceID string) error {
	status, responseBody, err := c.request("DELETE", c.deleteDeviceURL(customerID, deviceID), []byte{})

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.deleteDeviceURL(customerID, deviceID), responseBody}
	}

	return nil
}

func ( c * CustomerIO ) DeleteDevice ( customerID string , deviceID string ) error { status , responseBody , err := c . request ( " " , c . deleteDeviceURL ( customerID , deviceID ) , [ ] byte { } ) if err != nil { return err } else if status != 200 { return & CustomerIOError { status , c . deleteDeviceURL ( customerID , deviceID ) , responseBody } } return nil }

// DeleteDevice deletes a device for a customer


func initLocales(opt Options) language.Matcher {
	tags := make([]language.Tag, len(opt.Langs))
	for i, lang := range opt.Langs {
		tags[i] = language.Raw.Make(lang)
		fname := fmt.Sprintf(opt.Format, lang)
		// Append custom locale file.
		custom := []interface{}{}
		customPath := path.Join(opt.CustomDirectory, fname)
		if com.IsFile(customPath) {
			custom = append(custom, customPath)
		}

		var locale interface{}
		if data, ok := opt.Files[fname]; ok {
			locale = data
		} else {
			locale = path.Join(opt.Directory, fname)
		}

		err := i18n.SetMessageWithDesc(lang, opt.Names[i], locale, custom...)
		if err != nil && err != i18n.ErrLangAlreadyExist {
			panic(fmt.Errorf("fail to set message file(%s): %v", lang, err))
		}
	}
	return language.NewMatcher(tags)
}

func
initLocales
(
opt
Options
)
language
.
Matcher
{
tags
:=
make
(
[
]
language
.
Tag
,
len
(
opt
.
Langs
)
)
for
i
,
lang
:=
range
opt
.
Langs
{
tags
[
i
]
=
language
.
Raw
.
Make
(
lang
)
fname
:=
fmt
.
Sprintf
(
opt
.
Format
,
lang
)
// Append custom locale file.
custom
:=
[
]
interface
{
}
{
}
customPath
:=
path
.
Join
(
opt
.
CustomDirectory
,
fname
)
if
com
.
IsFile
(
customPath
)
{
custom
=
append
(
custom
,
customPath
)
}
var
locale
interface
{
}
if
data
,
ok
:=
opt
.
Files
[
fname
]
;
ok
{
locale
=
data
}
else
{
locale
=
path
.
Join
(
opt
.
Directory
,
fname
)
}
err
:=
i18n
.
SetMessageWithDesc
(
lang
,
opt
.
Names
[
i
]
,
locale
,
custom
...
)
if
err
!=
&&
err
!=
i18n
.
ErrLangAlreadyExist
{
panic
(
fmt
.
Errorf
(
"
"
,
lang
,
err
)
)
}
}
return
language
.
NewMatcher
(
tags
)
}

// initLocales initializes language type list and Accept-Language header matcher.

initLocales initializes language type list and Accept - Language header matcher .


func I18n(options ...Options) macaron.Handler {
	opt := prepareOptions(options)
	m := initLocales(opt)
	return func(ctx *macaron.Context) {
		isNeedRedir := false
		hasCookie := false

		// 1. Check URL arguments.
		lang := ctx.Query(opt.Parameter)

		// 2. Get language information from cookies.
		if len(lang) == 0 {
			lang = ctx.GetCookie("lang")
			hasCookie = true
		} else {
			isNeedRedir = true
		}

		// Check again in case someone modify by purpose.
		if !i18n.IsExist(lang) {
			lang = ""
			isNeedRedir = false
			hasCookie = false
		}

		// 3. Get language information from 'Accept-Language'.
		// The first element in the list is chosen to be the default language automatically.
		if len(lang) == 0 {
			tags, _, _ := language.ParseAcceptLanguage(ctx.Req.Header.Get("Accept-Language"))
			tag, _, _ := m.Match(tags...)
			lang = tag.String()
			isNeedRedir = false
		}

		curLang := LangType{
			Lang: lang,
		}

		// Save language information in cookies.
		if !hasCookie {
			ctx.SetCookie("lang", curLang.Lang, 1<<31-1, "/"+strings.TrimPrefix(opt.SubURL, "/"), opt.CookieDomain)
		}

		restLangs := make([]LangType, 0, i18n.Count()-1)
		langs := i18n.ListLangs()
		names := i18n.ListLangDescs()
		for i, v := range langs {
			if lang != v {
				restLangs = append(restLangs, LangType{v, names[i]})
			} else {
				curLang.Name = names[i]
			}
		}

		// Set language properties.
		locale := Locale{i18n.Locale{lang}}
		ctx.Map(locale)
		ctx.Locale = locale
		ctx.Data[opt.TmplName] = locale
		ctx.Data["Tr"] = i18n.Tr
		ctx.Data["Lang"] = locale.Lang
		ctx.Data["LangName"] = curLang.Name
		ctx.Data["AllLangs"] = append([]LangType{curLang}, restLangs...)
		ctx.Data["RestLangs"] = restLangs

		if opt.Redirect && isNeedRedir {
			ctx.Redirect(opt.SubURL + ctx.Req.RequestURI[:strings.Index(ctx.Req.RequestURI, "?")])
		}
	}
}

// I18n is a middleware provides localization layer for your application.
// Paramenter langs must be in the form of "en-US", "zh-CN", etc.
// Otherwise it may not recognize browser input.

I18n is a middleware provides localization layer for your application . Paramenter langs must be in the form of en - US zh - CN etc . Otherwise it may not recognize browser input .


func (a *API) FetchCheck(cid CIDType) (*Check, error) {
	if cid == nil || *cid == "" {
		return nil, fmt.Errorf("Invalid check CID [none]")
	}

	checkCID := string(*cid)

	matched, err := regexp.MatchString(config.CheckCIDRegex, checkCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid check CID [%s]", checkCID)
	}

	result, err := a.Get(checkCID)
	if err != nil {
		return nil, err
	}

	if a.Debug {
		a.Log.Printf("[DEBUG] fetch check, received JSON: %s", string(result))
	}

	check := new(Check)
	if err := json.Unmarshal(result, check); err != nil {
		return nil, err
	}

	return check, nil
}

func ( a * API ) FetchCheck ( cid CIDType ) ( * Check , error ) { if cid == nil || * cid == " " { return nil , fmt . Errorf ( " " ) } checkCID := string ( * cid ) matched , err := regexp . MatchString ( config . CheckCIDRegex , checkCID ) if err != nil { return nil , err } if ! matched { return nil , fmt . Errorf ( " " , checkCID ) } result , err := a . Get ( checkCID ) if err != nil { return nil , err } if a . Debug { a . Log . Printf ( " " , string ( result ) ) } check := new ( Check ) if err := json . Unmarshal ( result , check ) ; err != nil { return nil , err } return check , nil }

// FetchCheck retrieves check with passed cid.

FetchCheck retrieves check with passed cid .


func (a *API) FetchChecks() (*[]Check, error) {
	result, err := a.Get(config.CheckPrefix)
	if err != nil {
		return nil, err
	}

	var checks []Check
	if err := json.Unmarshal(result, &checks); err != nil {
		return nil, err
	}

	return &checks, nil
}

func ( a * API ) FetchChecks ( ) ( * [ ] Check , error ) { result , err := a . Get ( config . CheckPrefix ) if err != nil { return nil , err } var checks [ ] Check if err := json . Unmarshal ( result , & checks ) ; err != nil { return nil , err } return & checks , nil }

// FetchChecks retrieves all checks available to the API Token.

FetchChecks retrieves all checks available to the API Token .


func New(ac *Config) (*API, error) {

	if ac == nil {
		return nil, errors.New("Invalid API configuration (nil)")
	}

	key := TokenKeyType(ac.TokenKey)
	if key == "" {
		return nil, errors.New("API Token is required")
	}

	app := TokenAppType(ac.TokenApp)
	if app == "" {
		app = defaultAPIApp
	}

	acctID := TokenAccountIDType(ac.TokenAccountID)

	au := string(ac.URL)
	if au == "" {
		au = defaultAPIURL
	}
	if !strings.Contains(au, "/") {
		// if just a hostname is passed, ASSume "https" and a path prefix of "/v2"
		au = fmt.Sprintf("https://%s/v2", ac.URL)
	}
	if last := len(au) - 1; last >= 0 && au[last] == '/' {
		// strip off trailing '/'
		au = au[:last]
	}
	apiURL, err := url.Parse(au)
	if err != nil {
		return nil, err
	}

	a := &API{
		apiURL:    apiURL,
		key:       key,
		app:       app,
		accountID: acctID,
		caCert:    ac.CACert,
		tlsConfig: ac.TLSConfig,
		Debug:     ac.Debug,
		Log:       ac.Log,
		useExponentialBackoff: false,
	}

	a.Debug = ac.Debug
	a.Log = ac.Log
	if a.Debug && a.Log == nil {
		a.Log = log.New(os.Stderr, "", log.LstdFlags)
	}
	if a.Log == nil {
		a.Log = log.New(ioutil.Discard, "", log.LstdFlags)
	}

	return a, nil
}


func (a *API) Get(reqPath string) ([]byte, error) {
	return a.apiRequest("GET", reqPath, nil)
}

func ( a * API ) Get ( reqPath string ) ( [ ] byte , error ) { return a . apiRequest ( " " , reqPath , nil ) }


func (a *API) Post(reqPath string, data []byte) ([]byte, error) {
	return a.apiRequest("POST", reqPath, data)
}

func ( a * API ) Post ( reqPath string , data [ ] byte ) ( [ ] byte , error ) { return a . apiRequest ( " " , reqPath , data ) }


func (a *API) apiRequest(reqMethod string, reqPath string, data []byte) ([]byte, error) {
	backoffs := []uint{2, 4, 8, 16, 32}
	attempts := 0
	success := false

	var result []byte
	var err error

	for !success {
		result, err = a.apiCall(reqMethod, reqPath, data)
		if err == nil {
			success = true
		}

		// break and return error if not using exponential backoff
		if err != nil {
			if !a.useExponentialBackoff {
				break
			}
			if strings.Contains(err.Error(), "code 403") {
				break
			}
		}

		if !success {
			var wait float64
			if attempts >= len(backoffs) {
				wait = backoff(backoffs[len(backoffs)-1])
			} else {
				wait = backoff(backoffs[attempts])
			}
			attempts++
			a.Log.Printf("[WARN] API call failed %s, retrying in %d seconds.\n", err.Error(), uint(wait))
			time.Sleep(time.Duration(wait) * time.Second)
		}
	}

	return result, err
}

// apiRequest manages retry strategy for exponential backoffs


func (a *API) FetchGraph(cid CIDType) (*Graph, error) {
	if cid == nil || *cid == "" {
		return nil, fmt.Errorf("Invalid graph CID [none]")
	}

	graphCID := string(*cid)

	matched, err := regexp.MatchString(config.GraphCIDRegex, graphCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid graph CID [%s]", graphCID)
	}

	result, err := a.Get(graphCID)
	if err != nil {
		return nil, err
	}
	if a.Debug {
		a.Log.Printf("[DEBUG] fetch graph, received JSON: %s", string(result))
	}

	graph := new(Graph)
	if err := json.Unmarshal(result, graph); err != nil {
		return nil, err
	}

	return graph, nil
}

func ( a * API ) FetchGraph ( cid CIDType ) ( * Graph , error ) { if cid == nil || * cid == " " { return nil , fmt . Errorf ( " " ) } graphCID := string ( * cid ) matched , err := regexp . MatchString ( config . GraphCIDRegex , graphCID ) if err != nil { return nil , err } if ! matched { return nil , fmt . Errorf ( " " , graphCID ) } result , err := a . Get ( graphCID ) if err != nil { return nil , err } if a . Debug { a . Log . Printf ( " " , string ( result ) ) } graph := new ( Graph ) if err := json . Unmarshal ( result , graph ) ; err != nil { return nil , err } return graph , nil }

// FetchGraph retrieves graph with passed cid.

FetchGraph retrieves graph with passed cid .


func (a *API) FetchGraphs() (*[]Graph, error) {
	result, err := a.Get(config.GraphPrefix)
	if err != nil {
		return nil, err
	}

	var graphs []Graph
	if err := json.Unmarshal(result, &graphs); err != nil {
		return nil, err
	}

	return &graphs, nil
}

func ( a * API ) FetchGraphs ( ) ( * [ ] Graph , error ) { result , err := a . Get ( config . GraphPrefix ) if err != nil { return nil , err } var graphs [ ] Graph if err := json . Unmarshal ( result , & graphs ) ; err != nil { return nil , err } return & graphs , nil }

// FetchGraphs retrieves all graphs available to the API Token.

FetchGraphs retrieves all graphs available to the API Token .


func (a *API) UpdateGraph(cfg *Graph) (*Graph, error) {
	if cfg == nil {
		return nil, fmt.Errorf("Invalid graph config [nil]")
	}

	graphCID := string(cfg.CID)

	matched, err := regexp.MatchString(config.GraphCIDRegex, graphCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid graph CID [%s]", graphCID)
	}

	jsonCfg, err := json.Marshal(cfg)
	if err != nil {
		return nil, err
	}

	if a.Debug {
		a.Log.Printf("[DEBUG] update graph, sending JSON: %s", string(jsonCfg))
	}

	result, err := a.Put(graphCID, jsonCfg)
	if err != nil {
		return nil, err
	}

	graph := &Graph{}
	if err := json.Unmarshal(result, graph); err != nil {
		return nil, err
	}

	return graph, nil
}

func ( a * API ) UpdateGraph ( cfg * Graph ) ( * Graph , error ) { if cfg == nil { return nil , fmt . Errorf ( " " ) } graphCID := string ( cfg . CID ) matched , err := regexp . MatchString ( config . GraphCIDRegex , graphCID ) if err != nil { return nil , err } if ! matched { return nil , fmt . Errorf ( " " , graphCID ) } jsonCfg , err := json . Marshal ( cfg ) if err != nil { return nil , err } if a . Debug { a . Log . Printf ( " " , string ( jsonCfg ) ) } result , err := a . Put ( graphCID , jsonCfg ) if err != nil { return nil , err } graph := & Graph { } if err := json . Unmarshal ( result , graph ) ; err != nil { return nil , err } return graph , nil }


func (a *API) CreateGraph(cfg *Graph) (*Graph, error) {
	if cfg == nil {
		return nil, fmt.Errorf("Invalid graph config [nil]")
	}

	jsonCfg, err := json.Marshal(cfg)
	if err != nil {
		return nil, err
	}

	if a.Debug {
		a.Log.Printf("[DEBUG] update graph, sending JSON: %s", string(jsonCfg))
	}

	result, err := a.Post(config.GraphPrefix, jsonCfg)
	if err != nil {
		return nil, err
	}

	graph := &Graph{}
	if err := json.Unmarshal(result, graph); err != nil {
		return nil, err
	}

	return graph, nil
}

func ( a * API ) CreateGraph ( cfg * Graph ) ( * Graph , error ) { if cfg == nil { return nil , fmt . Errorf ( " " ) } jsonCfg , err := json . Marshal ( cfg ) if err != nil { return nil , err } if a . Debug { a . Log . Printf ( " " , string ( jsonCfg ) ) } result , err := a . Post ( config . GraphPrefix , jsonCfg ) if err != nil { return nil , err } graph := & Graph { } if err := json . Unmarshal ( result , graph ) ; err != nil { return nil , err } return graph , nil }


func (a *API) DeleteGraph(cfg *Graph) (bool, error) {
	if cfg == nil {
		return false, fmt.Errorf("Invalid graph config [nil]")
	}
	return a.DeleteGraphByCID(CIDType(&cfg.CID))
}

func ( a * API ) DeleteGraph ( cfg * Graph ) ( bool , error ) { if cfg == nil { return false , fmt . Errorf ( " " ) } return a . DeleteGraphByCID ( CIDType ( & cfg . CID ) ) }


func (a *API) DeleteGraphByCID(cid CIDType) (bool, error) {
	if cid == nil || *cid == "" {
		return false, fmt.Errorf("Invalid graph CID [none]")
	}

	graphCID := string(*cid)

	matched, err := regexp.MatchString(config.GraphCIDRegex, graphCID)
	if err != nil {
		return false, err
	}
	if !matched {
		return false, fmt.Errorf("Invalid graph CID [%s]", graphCID)
	}

	_, err = a.Delete(graphCID)
	if err != nil {
		return false, err
	}

	return true, nil
}

func ( a * API ) DeleteGraphByCID ( cid CIDType ) ( bool , error ) { if cid == nil || * cid == " " { return false , fmt . Errorf ( " " ) } graphCID := string ( * cid ) matched , err := regexp . MatchString ( config . GraphCIDRegex , graphCID ) if err != nil { return false , err } if ! matched { return false , fmt . Errorf ( " " , graphCID ) } _ , err = a . Delete ( graphCID ) if err != nil { return false , err } return true , nil }

// DeleteGraphByCID deletes graph with passed cid.

DeleteGraphByCID deletes graph with passed cid .


func (a *API) FetchCheckBundle(cid CIDType) (*CheckBundle, error) {
	if cid == nil || *cid == "" {
		return nil, fmt.Errorf("Invalid check bundle CID [none]")
	}

	bundleCID := string(*cid)

	matched, err := regexp.MatchString(config.CheckBundleCIDRegex, bundleCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid check bundle CID [%v]", bundleCID)
	}

	result, err := a.Get(bundleCID)
	if err != nil {
		return nil, err
	}

	if a.Debug {
		a.Log.Printf("[DEBUG] fetch check bundle, received JSON: %s", string(result))
	}

	checkBundle := &CheckBundle{}
	if err := json.Unmarshal(result, checkBundle); err != nil {
		return nil, err
	}

	return checkBundle, nil
}

func ( a * API ) FetchCheckBundle ( cid CIDType ) ( * CheckBundle , error ) { if cid == nil || * cid == " " { return nil , fmt . Errorf ( " " ) } bundleCID := string ( * cid ) matched , err := regexp . MatchString ( config . CheckBundleCIDRegex , bundleCID ) if err != nil { return nil , err } if ! matched { return nil , fmt . Errorf ( " " , bundleCID ) } result , err := a . Get ( bundleCID ) if err != nil { return nil , err } if a . Debug { a . Log . Printf ( " " , string ( result ) ) } checkBundle := & CheckBundle { } if err := json . Unmarshal ( result , checkBundle ) ; err != nil { return nil , err } return checkBundle , nil }

// FetchCheckBundle retrieves check bundle with passed cid.

FetchCheckBundle retrieves check bundle with passed cid .


func (a *API) FetchCheckBundles() (*[]CheckBundle, error) {
	result, err := a.Get(config.CheckBundlePrefix)
	if err != nil {
		return nil, err
	}

	var checkBundles []CheckBundle
	if err := json.Unmarshal(result, &checkBundles); err != nil {
		return nil, err
	}

	return &checkBundles, nil
}

func ( a * API ) FetchCheckBundles ( ) ( * [ ] CheckBundle , error ) { result , err := a . Get ( config . CheckBundlePrefix ) if err != nil { return nil , err } var checkBundles [ ] CheckBundle if err := json . Unmarshal ( result , & checkBundles ) ; err != nil { return nil , err } return & checkBundles , nil }

// FetchCheckBundles retrieves all check bundles available to the API Token.

FetchCheckBundles retrieves all check bundles available to the API Token .


func (a *API) UpdateCheckBundle(cfg *CheckBundle) (*CheckBundle, error) {
	if cfg == nil {
		return nil, fmt.Errorf("Invalid check bundle config [nil]")
	}

	bundleCID := string(cfg.CID)

	matched, err := regexp.MatchString(config.CheckBundleCIDRegex, bundleCID)
	if err != nil {
		return nil, err
	}
	if !matched {
		return nil, fmt.Errorf("Invalid check bundle CID [%s]", bundleCID)
	}

	jsonCfg, err := json.Marshal(cfg)
	if err != nil {
		return nil, err
	}

	if a.Debug {
		a.Log.Printf("[DEBUG] update check bundle, sending JSON: %s", string(jsonCfg))
	}

	result, err := a.Put(bundleCID, jsonCfg)
	if err != nil {
		return nil, err
	}

	checkBundle := &CheckBundle{}
	if err := json.Unmarshal(result, checkBundle); err != nil {
		return nil, err
	}

	return checkBundle, nil
}

func ( a * API ) UpdateCheckBundle ( cfg * CheckBundle ) ( * CheckBundle , error ) { if cfg == nil { return nil , fmt . Errorf ( " " ) } bundleCID := string ( cfg . CID ) matched , err := regexp . MatchString ( config . CheckBundleCIDRegex , bundleCID ) if err != nil { return nil , err } if ! matched { return nil , fmt . Errorf ( " " , bundleCID ) } jsonCfg , err := json . Marshal ( cfg ) if err != nil { return nil , err } if a . Debug { a . Log . Printf ( " " , string ( jsonCfg ) ) } result , err := a . Put ( bundleCID , jsonCfg ) if err != nil { return nil , err } checkBundle := & CheckBundle { } if err := json . Unmarshal ( result , checkBundle ) ; err != nil { return nil , err } return checkBundle , nil }

// UpdateCheckBundle updates passed check bundle.

UpdateCheckBundle updates passed check bundle .


func (a *API) DeleteCheckBundle(cfg *CheckBundle) (bool, error) {
	if cfg == nil {
		return false, fmt.Errorf("Invalid check bundle config [nil]")
	}
	return a.DeleteCheckBundleByCID(CIDType(&cfg.CID))
}

func ( a * API ) DeleteCheckBundle ( cfg * CheckBundle ) ( bool , error ) { if cfg == nil { return false , fmt . Errorf ( " " ) } return a . DeleteCheckBundleByCID ( CIDType ( & cfg . CID ) ) }

// DeleteCheckBundle deletes passed check bundle.

DeleteCheckBundle deletes passed check bundle .


func (a *API) DeleteCheckBundleByCID(cid CIDType) (bool, error) {

	if cid == nil || *cid == "" {
		return false, fmt.Errorf("Invalid check bundle CID [none]")
	}

	bundleCID := string(*cid)

	matched, err := regexp.MatchString(config.CheckBundleCIDRegex, bundleCID)
	if err != nil {
		return false, err
	}
	if !matched {
		return false, fmt.Errorf("Invalid check bundle CID [%v]", bundleCID)
	}

	_, err = a.Delete(bundleCID)
	if err != nil {
		return false, err
	}

	return true, nil
}

func ( a * API ) DeleteCheckBundleByCID ( cid CIDType ) ( bool , error ) { if cid == nil || * cid == " " { return false , fmt . Errorf ( " " ) } bundleCID := string ( * cid ) matched , err := regexp . MatchString ( config . CheckBundleCIDRegex , bundleCID ) if err != nil { return false , err } if ! matched { return false , fmt . Errorf ( " " , bundleCID ) } _ , err = a . Delete ( bundleCID ) if err != nil { return false , err } return true , nil }

// DeleteCheckBundleByCID deletes check bundle with passed cid.

DeleteCheckBundleByCID deletes check bundle with passed cid .


func (m *CirconusMetrics) Gauge(metric string, val interface{}) {
	m.SetGauge(metric, val)
}

func ( m * CirconusMetrics ) Gauge ( metric string , val interface { } ) { m . SetGauge ( metric , val ) }


func (m *CirconusMetrics) SetGauge(metric string, val interface{}) {
	m.gm.Lock()
	defer m.gm.Unlock()
	m.gauges[metric] = val
}

func ( m * CirconusMetrics ) SetGauge ( metric string , val interface { } ) { m . gm . Lock ( ) defer m . gm . Unlock ( ) m . gauges [ metric ] = val }