func (e Encoder) EncodeArray(n int, f func(Encoder) error) (err error) {
	if e.key {
		if e.key, err = false, e.Emitter.EmitMapValue(); err != nil {
			return
		}
	}

	if err = e.Emitter.EmitArrayBegin(n); err != nil {
		return
	}

encodeArray:
	for i := 0; n < 0 || i < n; i++ {
		if i != 0 {
			if e.Emitter.EmitArrayNext(); err != nil {
				return
			}
		}
		switch err = f(e); err {
		case nil:
		case End:
			break encodeArray
		default:
			return
		}
	}

	return e.Emitter.EmitArrayEnd()
}

func ( e Encoder ) EncodeArray ( n int , f func ( Encoder ) error ) ( err error ) { if e . key { if e . key , err = false , e . Emitter . EmitMapValue ( ) ; err != nil { return } } if err = e . Emitter . EmitArrayBegin ( n ) ; err != nil { return } encodeArray : for i := 0 ; n < 0 || i < n ; i ++ { if i != 0 { if e . Emitter . EmitArrayNext ( ) ; err != nil { return } } switch err = f ( e ) ; err { case nil : case End : break encodeArray default : return } } return e . Emitter . EmitArrayEnd ( ) }

// EncodeArray provides the implementation of the array encoding algorithm,
// where n is the number of elements in the array, and f a function called to
// encode each element.
//
// The n argument can be set to a negative value to indicate that the program
// doesn't know how many elements it will output to the array. Be mindful that
// not all emitters support encoding arrays of unknown lengths.
//
// The f function is called to encode each element of the array.

EncodeArray provides the implementation of the array encoding algorithm where n is the number of elements in the array and f a function called to encode each element . The n argument can be set to a negative value to indicate that the program doesn t know how many elements it will output to the array . Be mindful that not all emitters support encoding arrays of unknown lengths . The f function is called to encode each element of the array .


func (e Encoder) EncodeMap(n int, f func(Encoder, Encoder) error) (err error) {
	if e.key {
		if e.key, err = false, e.Emitter.EmitMapValue(); err != nil {
			return
		}
	}

	if err = e.Emitter.EmitMapBegin(n); err != nil {
		return
	}

encodeMap:
	for i := 0; n < 0 || i < n; i++ {
		if i != 0 {
			if err = e.Emitter.EmitMapNext(); err != nil {
				return
			}
		}
		e.key = true
		err = f(
			Encoder{Emitter: e.Emitter, SortMapKeys: e.SortMapKeys},
			Encoder{Emitter: e.Emitter, SortMapKeys: e.SortMapKeys, key: true},
		)
		// Because internal calls don't use the exported methods they may not
		// reset this flag to false when expected, forcing the value here.
		e.key = false

		switch err {
		case nil:
		case End:
			break encodeMap
		default:
			return
		}
	}

	return e.Emitter.EmitMapEnd()
}

// EncodeMap provides the implementation of the map encoding algorithm, where n
// is the number of elements in the map, and f a function called to encode each
// element.
//
// The n argument can be set to a negative value to indicate that the program
// doesn't know how many elements it will output to the map. Be mindful that not
// all emitters support encoding maps of unknown length.
//
// The f function is called to encode each element of the map, it is expected to
// encode two values, the first one being the key, follow by the associated value.
// The first encoder must be used to encode the key, the second for the value.

EncodeMap provides the implementation of the map encoding algorithm where n is the number of elements in the map and f a function called to encode each element . The n argument can be set to a negative value to indicate that the program doesn t know how many elements it will output to the map . Be mindful that not all emitters support encoding maps of unknown length . The f function is called to encode each element of the map it is expected to encode two values the first one being the key follow by the associated value . The first encoder must be used to encode the key the second for the value .


func NewStreamEncoder(e Emitter) *StreamEncoder {
	if e == nil {
		panic("objconv.NewStreamEncoder: the emitter is nil")
	}
	return &StreamEncoder{Emitter: e}
}

func NewStreamEncoder ( e Emitter ) * StreamEncoder { if e == nil { panic ( " " ) } return & StreamEncoder { Emitter : e } }

// NewStreamEncoder returns a new stream encoder that outputs to e.
//
// The function panics if e is nil.

NewStreamEncoder returns a new stream encoder that outputs to e . The function panics if e is nil .


func (e *StreamEncoder) Open(n int) error {
	if err := e.err; err != nil {
		return err
	}

	if e.closed {
		return io.ErrClosedPipe
	}

	if !e.opened {
		e.max = n
		e.opened = true

		if !e.oneshot {
			e.err = e.Emitter.EmitArrayBegin(n)
		}
	}

	return e.err
}

func ( e * StreamEncoder ) Open ( n int ) error { if err := e . err ; err != nil { return err } if e . closed { return io . ErrClosedPipe } if ! e . opened { e . max = n e . opened = true if ! e . oneshot { e . err = e . Emitter . EmitArrayBegin ( n ) } } return e . err }

// Open explicitly tells the encoder to start the stream, setting the number
// of values to n.
//
// Depending on the actual format that the stream is encoding to, n may or
// may not have to be accurate, some formats also support passing a negative
// value to indicate that the number of elements is unknown.

Open explicitly tells the encoder to start the stream setting the number of values to n . Depending on the actual format that the stream is encoding to n may or may not have to be accurate some formats also support passing a negative value to indicate that the number of elements is unknown .


func (e *StreamEncoder) Close() error {
	if !e.closed {
		if err := e.Open(-1); err != nil {
			return err
		}

		e.closed = true

		if !e.oneshot {
			e.err = e.Emitter.EmitArrayEnd()
		}
	}

	return e.err
}

func ( e * StreamEncoder ) Close ( ) error { if ! e . closed { if err := e . Open ( - 1 ) ; err != nil { return err } e . closed = true if ! e . oneshot { e . err = e . Emitter . EmitArrayEnd ( ) } } return e . err }


func (e *StreamEncoder) Encode(v interface{}) error {
	if err := e.Open(-1); err != nil {
		return err
	}

	if e.max >= 0 && e.cnt >= e.max {
		return fmt.Errorf("objconv: too many values sent to a stream encoder exceed the configured limit of %d", e.max)
	}

	if !e.oneshot && e.cnt != 0 {
		e.err = e.Emitter.EmitArrayNext()
	}

	if e.err == nil {
		e.err = (Encoder{
			Emitter:     e.Emitter,
			SortMapKeys: e.SortMapKeys,
		}).Encode(v)

		if e.cnt++; e.max >= 0 && e.cnt >= e.max {
			e.Close()
		}
	}

	return e.err
}

func ( e * StreamEncoder ) Encode ( v interface { } ) error { if err := e . Open ( - 1 ) ; err != nil { return err } if e . max >= 0 && e . cnt >= e . max { return fmt . Errorf ( " " , e . max ) } if ! e . oneshot && e . cnt != 0 { e . err = e . Emitter . EmitArrayNext ( ) } if e . err == nil { e . err = ( Encoder { Emitter : e . Emitter , SortMapKeys : e . SortMapKeys , } ) . Encode ( v ) if e . cnt ++ ; e . max >= 0 && e . cnt >= e . max { e . Close ( ) } } return e . err }

// Encode writes v to the stream, encoding it based on the emitter configured
// on e.

Encode writes v to the stream encoding it based on the emitter configured on e .


func newStructType(t reflect.Type, c map[reflect.Type]*structType) *structType {
	if s := c[t]; s != nil {
		return s
	}

	n := t.NumField()
	s := &structType{
		fields:       make([]structField, 0, n),
		fieldsByName: make(map[string]*structField),
	}
	c[t] = s

	for i := 0; i != n; i++ {
		ft := t.Field(i)

		if ft.Anonymous || len(ft.PkgPath) != 0 { // anonymous or non-exported
			continue
		}

		sf := makeStructField(ft, c)

		if sf.name == "-" { // skip
			continue
		}

		s.fields = append(s.fields, sf)
		s.fieldsByName[sf.name] = &s.fields[len(s.fields)-1]
	}

	return s
}

func
newStructType
(
t
reflect
.
Type
,
c
map
[
reflect
.
Type
]
*
structType
)
*
structType
{
if
s
:=
c
[
t
]
;
s
!=
{
return
s
}
n
:=
t
.
NumField
(
)
s
:=
&
structType
{
fields
:
make
(
[
]
structField
,
0
,
n
)
,
fieldsByName
:
make
(
map
[
string
]
*
structField
)
,
}
c
[
t
]
=
s
for
i
:=
0
;
i
!=
n
;
i
++
{
ft
:=
t
.
Field
(
i
)
if
ft
.
Anonymous
||
len
(
ft
.
PkgPath
)
!=
0
{
// anonymous or non-exported
continue
}
sf
:=
makeStructField
(
ft
,
c
)
if
sf
.
name
==
"
"
{
// skip
continue
}
s
.
fields
=
append
(
s
.
fields
,
sf
)
s
.
fieldsByName
[
sf
.
name
]
=
&
s
.
fields
[
len
(
s
.
fields
)
1
]
}
return
s
}

// newStructType takes a Go type as argument and extract information to make a
// new structType value.
// The type has to be a struct type or a panic will be raised.

newStructType takes a Go type as argument and extract information to make a new structType value . The type has to be a struct type or a panic will be raised .


func (cache *structTypeCache) lookup(t reflect.Type) (s *structType) {
	cache.mutex.RLock()
	s = cache.store[t]
	cache.mutex.RUnlock()

	if s == nil {
		// There's a race confition here where this value may be generated
		// multiple times.
		// The impact in practice is really small as it's unlikely to happen
		// often, we take the approach of keeping the logic simple and avoid
		// a more complex synchronization logic required to solve this edge
		// case.
		s = newStructType(t, map[reflect.Type]*structType{})
		cache.mutex.Lock()
		cache.store[t] = s
		cache.mutex.Unlock()
	}

	return
}

// lookup takes a Go type as argument and returns the matching structType value,
// potentially creating it if it didn't already exist.
// This method is safe to call from multiple goroutines.

lookup takes a Go type as argument and returns the matching structType value potentially creating it if it didn t already exist . This method is safe to call from multiple goroutines .


func (cache *structTypeCache) clear() {
	cache.mutex.Lock()
	for typ := range cache.store {
		delete(cache.store, typ)
	}
	cache.mutex.Unlock()
}

func ( cache * structTypeCache ) clear ( ) { cache . mutex . Lock ( ) for typ := range cache . store { delete ( cache . store , typ ) } cache . mutex . Unlock ( ) }


func CheckUint64Bounds(v uint64, max uint64, t reflect.Type) (err error) {
	if v > max {
		err = fmt.Errorf("objconv: %d overflows the maximum value of %d for %s", v, max, t)
	}
	return
}

func CheckUint64Bounds ( v uint64 , max uint64 , t reflect . Type ) ( err error ) { if v > max { err = fmt . Errorf ( " " , v , max , t ) } return }

// CheckUint64Bounds verifies that v is smaller than max, t represents the
// original type of v.

CheckUint64Bounds verifies that v is smaller than max t represents the original type of v .


func CheckInt64Bounds(v int64, min int64, max uint64, t reflect.Type) (err error) {
	if v < min {
		err = fmt.Errorf("objconv: %d overflows the minimum value of %d for %s", v, min, t)
	}
	if v > 0 && uint64(v) > max {
		err = fmt.Errorf("objconv: %d overflows the maximum value of %d for %s", v, max, t)
	}
	return
}

func CheckInt64Bounds ( v int64 , min int64 , max uint64 , t reflect . Type ) ( err error ) { if v < min { err = fmt . Errorf ( " " , v , min , t ) } if v > 0 && uint64 ( v ) > max { err = fmt . Errorf ( " " , v , max , t ) } return }

// CheckInt64Bounds verifies that v is within min and max, t represents the
// original type of v.

CheckInt64Bounds verifies that v is within min and max t represents the original type of v .


func NewDecoder(p Parser) *Decoder {
	if p == nil {
		panic("objconv: the parser is nil")
	}
	return &Decoder{Parser: p}
}

func NewDecoder ( p Parser ) * Decoder { if p == nil { panic ( " " ) } return & Decoder { Parser : p } }

// NewDecoder returns a decoder object that uses p, will panic if p is nil.

NewDecoder returns a decoder object that uses p will panic if p is nil .


func (d Decoder) Decode(v interface{}) error {
	to := reflect.ValueOf(v)

	if d.off != 0 {
		var err error
		if d.off, err = 0, d.Parser.ParseMapValue(d.off-1); err != nil {
			return err
		}
	}

	if !to.IsValid() {
		// This special case for a nil value is used to make it possible to
		// discard decoded values.
		_, err := d.decodeInterface(to)
		return err
	}

	// Optimization for ValueDecoder, in practice tho it's also handled in the
	// methods that are based on reflection.
	switch x := v.(type) {
	case ValueDecoder:
		return x.DecodeValue(d)
	}

	if to.Kind() == reflect.Ptr {
		// In most cases the method receives a pointer, but we may also have to
		// support types that aren't pointers but implement ValueDecoder, or
		// types that have got adapters set.
		// If we're not in either of those cases the code will likely panic when
		// the value is set because it won't be addressable.
		to = to.Elem()
	}

	_, err := d.decode(to)
	return err
}

// Decode expects v to be a pointer to a value in which the decoder will load
// the next parsed data.
//
// The method panics if v is neither a pointer type nor implements the
// ValueDecoder interface, or if v is a nil pointer.

Decode expects v to be a pointer to a value in which the decoder will load the next parsed data . The method panics if v is neither a pointer type nor implements the ValueDecoder interface or if v is a nil pointer .


func (d Decoder) DecodeArray(f func(Decoder) error) (err error) {
	var typ Type

	if d.off != 0 {
		if d.off, err = 0, d.Parser.ParseMapValue(d.off-1); err != nil {
			return
		}
	}

	if typ, err = d.Parser.ParseType(); err != nil {
		return
	}

	err = d.decodeArrayImpl(typ, f)
	return
}

func ( d Decoder ) DecodeArray ( f func ( Decoder ) error ) ( err error ) { var typ Type if d . off != 0 { if d . off , err = 0 , d . Parser . ParseMapValue ( d . off - 1 ) ; err != nil { return } } if typ , err = d . Parser . ParseType ( ) ; err != nil { return } err = d . decodeArrayImpl ( typ , f ) return }

// DecodeArray provides the implementation of the algorithm for decoding arrays,
// where f is called to decode each element of the array.

DecodeArray provides the implementation of the algorithm for decoding arrays where f is called to decode each element of the array .


func (d Decoder) DecodeMap(f func(Decoder, Decoder) error) (err error) {
	var typ Type

	if d.off != 0 {
		if d.off, err = 0, d.Parser.ParseMapValue(d.off-1); err != nil {
			return
		}
	}

	if typ, err = d.Parser.ParseType(); err != nil {
		return
	}

	err = d.decodeMapImpl(typ, f)
	return
}

func ( d Decoder ) DecodeMap ( f func ( Decoder , Decoder ) error ) ( err error ) { var typ Type if d . off != 0 { if d . off , err = 0 , d . Parser . ParseMapValue ( d . off - 1 ) ; err != nil { return } } if typ , err = d . Parser . ParseType ( ) ; err != nil { return } err = d . decodeMapImpl ( typ , f ) return }

// DecodeMap provides the implementation of the algorithm for decoding maps,
// where f is called to decode each pair of key and value.
//
// The function f is expected to decode two values from the map, the first one
// being the key and the second the associated value. The first decoder must be
// used to decode the key, the second one for the value.

DecodeMap provides the implementation of the algorithm for decoding maps where f is called to decode each pair of key and value . The function f is expected to decode two values from the map the first one being the key and the second the associated value . The first decoder must be used to decode the key the second one for the value .


func NewStreamDecoder(p Parser) *StreamDecoder {
	if p == nil {
		panic("objconv: the parser is nil")
	}
	return &StreamDecoder{Parser: p}
}

func NewStreamDecoder ( p Parser ) * StreamDecoder { if p == nil { panic ( " " ) } return & StreamDecoder { Parser : p } }

// NewStreamDecoder returns a new stream decoder that takes input from p.
//
// The function panics if p is nil.

NewStreamDecoder returns a new stream decoder that takes input from p . The function panics if p is nil .


func (d *StreamDecoder) Len() int {
	if d.err != nil {
		return 0
	}

	if d.typ == Unknown {
		if d.init() != nil {
			return 0
		}
	}

	return d.max - d.cnt
}

func ( d * StreamDecoder ) Len ( ) int { if d . err != nil { return 0 } if d . typ == Unknown { if d . init ( ) != nil { return 0 } } return d . max - d . cnt }

// Len returns the number of values remaining to be read from the stream, which
// may be -1 if the underlying format doesn't provide this information. If an
// error occurred while decoding the stream the method returns zero because no
// more values can be read.

Len returns the number of values remaining to be read from the stream which may be - 1 if the underlying format doesn t provide this information . If an error occurred while decoding the stream the method returns zero because no more values can be read .


func (d *StreamDecoder) Err() error {
	if d.err == End {
		return nil
	}
	return d.err
}

func ( d * StreamDecoder ) Err ( ) error { if d . err == End { return nil } return d . err }

// Err returns the last error returned by the Decode method.
//
// The method returns nil if the stream reached its natural end.

Err returns the last error returned by the Decode method . The method returns nil if the stream reached its natural end .


func (d *StreamDecoder) Decode(v interface{}) error {
	if d.err != nil {
		return d.err
	}

	err := error(nil)
	cnt := d.cnt
	max := d.max
	dec := Decoder{
		Parser:  d.Parser,
		MapType: d.MapType,
	}

	switch d.typ {
	case Unknown:
		err = d.init()
		max = d.max
	case Array:
		if cnt == max {
			err = dec.Parser.ParseArrayEnd(cnt)
		} else if cnt != 0 {
			err = dec.Parser.ParseArrayNext(cnt)
		}
	}

	if err == nil {
		if cnt == max {
			err = End
		} else {
			switch err = dec.Decode(v); err {
			case nil:
				cnt++
			case End:
				cnt++
				max = cnt
			default:
				if max < 0 && dec.Parser.ParseArrayEnd(cnt) == nil {
					err = End
				}
			}
		}
	}

	d.err = err
	d.cnt = cnt
	d.max = max
	return err
}

func ( d * StreamDecoder ) Decode ( v interface { } ) error { if d . err != nil { return d . err } err := error ( nil ) cnt := d . cnt max := d . max dec := Decoder { Parser : d . Parser , MapType : d . MapType , } switch d . typ { case Unknown : err = d . init ( ) max = d . max case Array : if cnt == max { err = dec . Parser . ParseArrayEnd ( cnt ) } else if cnt != 0 { err = dec . Parser . ParseArrayNext ( cnt ) } } if err == nil { if cnt == max { err = End } else { switch err = dec . Decode ( v ) ; err { case nil : cnt ++ case End : cnt ++ max = cnt default : if max < 0 && dec . Parser . ParseArrayEnd ( cnt ) == nil { err = End } } } } d . err = err d . cnt = cnt d . max = max return err }

// Decodes the next value from the stream into v.

Decodes the next value from the stream into v .


func (d *StreamDecoder) Encoder(e Emitter) (enc *StreamEncoder, err error) {
	var typ Type

	if typ, err = d.Parser.ParseType(); err == nil {
		enc = NewStreamEncoder(e)
		enc.oneshot = typ != Array
	}

	return
}

func ( d * StreamDecoder ) Encoder ( e Emitter ) ( enc * StreamEncoder , err error ) { var typ Type if typ , err = d . Parser . ParseType ( ) ; err == nil { enc = NewStreamEncoder ( e ) enc . oneshot = typ != Array } return }

// Encoder returns a new StreamEncoder which can be used to re-encode the stream
// decoded by d into e.
//
// The method panics if e is nil.

Encoder returns a new StreamEncoder which can be used to re - encode the stream decoded by d into e . The method panics if e is nil .


func init() {
	for _, f := range strings.Split(os.Getenv("LOGFLAGS"), ",") {
		switch f {
		case "longfile":
			defaultFlags |= Llongfile
		case "shortfile":
			defaultFlags |= Lshortfile
		}
	}
}

func init ( ) { for _ , f := range strings . Split ( os . Getenv ( " " ) , " " ) { switch f { case " " : defaultFlags |= Llongfile case " " : defaultFlags |= Lshortfile } } }

// Read logger flags from the LOGFLAGS environment variable.  Multiple flags can
// be set at once, separated by commas.

Read logger flags from the LOGFLAGS environment variable . Multiple flags can be set at once separated by commas .


func LevelFromString(s string) (l Level, ok bool) {
	switch strings.ToLower(s) {
	case "trace", "trc":
		return LevelTrace, true
	case "debug", "dbg":
		return LevelDebug, true
	case "info", "inf":
		return LevelInfo, true
	case "warn", "wrn":
		return LevelWarn, true
	case "error", "err":
		return LevelError, true
	case "critical", "crt":
		return LevelCritical, true
	case "off":
		return LevelOff, true
	default:
		return LevelInfo, false
	}
}

func LevelFromString ( s string ) ( l Level , ok bool ) { switch strings . ToLower ( s ) { case " " , " " : return LevelTrace , true case " " , " " : return LevelDebug , true case " " , " " : return LevelInfo , true case " " , " " : return LevelWarn , true case " " , " " : return LevelError , true case " " , " " : return LevelCritical , true case " " : return LevelOff , true default : return LevelInfo , false } }

// LevelFromString returns a level based on the input string s.  If the input
// can't be interpreted as a valid log level, the info level and false is
// returned.

LevelFromString returns a level based on the input string s . If the input can t be interpreted as a valid log level the info level and false is returned .


func NewBackend(w io.Writer, opts ...BackendOption) *Backend {
	b := &Backend{w: w, flag: defaultFlags}
	for _, o := range opts {
		o(b)
	}
	return b
}

func NewBackend ( w io . Writer , opts ... BackendOption ) * Backend { b := & Backend { w : w , flag : defaultFlags } for _ , o := range opts { o ( b ) } return b }

// NewBackend creates a logger backend from a Writer.

NewBackend creates a logger backend from a Writer .


func callsite(flag uint32) (string, int) {
	_, file, line, ok := runtime.Caller(calldepth)
	if !ok {
		return "???", 0
	}
	if flag&Lshortfile != 0 {
		short := file
		for i := len(file) - 1; i > 0; i-- {
			if os.IsPathSeparator(file[i]) {
				short = file[i+1:]
				break
			}
		}
		file = short
	}
	return file, line
}

func callsite ( flag uint32 ) ( string , int ) { _ , file , line , ok := runtime . Caller ( calldepth ) if ! ok { return " " , 0 } if flag & Lshortfile != 0 { short := file for i := len ( file ) - 1 ; i > 0 ; i -- { if os . IsPathSeparator ( file [ i ] ) { short = file [ i + 1 : ] break } } file = short } return file , line }

// callsite returns the file name and line number of the callsite to the
// subsystem logger.

callsite returns the file name and line number of the callsite to the subsystem logger .


func (b *Backend) print(lvl, tag string, args ...interface{}) {
	t := time.Now() // get as early as possible

	bytebuf := buffer()

	var file string
	var line int
	if b.flag&(Lshortfile|Llongfile) != 0 {
		file, line = callsite(b.flag)
	}

	formatHeader(bytebuf, t, lvl, tag, file, line)
	buf := bytes.NewBuffer(*bytebuf)
	fmt.Fprintln(buf, args...)
	*bytebuf = buf.Bytes()

	b.mu.Lock()
	b.w.Write(*bytebuf)
	b.mu.Unlock()

	recycleBuffer(bytebuf)
}

func
(
b
*
Backend
)
print
(
lvl
,
tag
string
,
args
...
interface
{
}
)
{
t
:=
time
.
Now
(
)
// get as early as possible
bytebuf
:=
buffer
(
)
var
file
string
var
line
int
if
b
.
flag
&
(
Lshortfile
|
Llongfile
)
!=
0
{
file
,
line
=
callsite
(
b
.
flag
)
}
formatHeader
(
bytebuf
,
t
,
lvl
,
tag
,
file
,
line
)
buf
:=
bytes
.
NewBuffer
(
*
bytebuf
)
fmt
.
Fprintln
(
buf
,
args
...
)
*
bytebuf
=
buf
.
Bytes
(
)
b
.
mu
.
Lock
(
)
b
.
w
.
Write
(
*
bytebuf
)
b
.
mu
.
Unlock
(
)
recycleBuffer
(
bytebuf
)
}

// print outputs a log message to the writer associated with the backend after
// creating a prefix for the given level and tag according to the formatHeader
// function and formatting the provided arguments using the default formatting
// rules.

print outputs a log message to the writer associated with the backend after creating a prefix for the given level and tag according to the formatHeader function and formatting the provided arguments using the default formatting rules .


func (b *Backend) Logger(subsystemTag string) Logger {
	return &slog{LevelInfo, subsystemTag, b}
}

func ( b * Backend ) Logger ( subsystemTag string ) Logger { return & slog { LevelInfo , subsystemTag , b } }

// Logger returns a new logger for a particular subsystem that writes to the
// Backend b.  A tag describes the subsystem and is included in all log
// messages.  The logger uses the info verbosity level by default.

Logger returns a new logger for a particular subsystem that writes to the Backend b . A tag describes the subsystem and is included in all log messages . The logger uses the info verbosity level by default .


func (l *slog) Trace(args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelTrace {
		l.b.print("TRC", l.tag, args...)
	}
}

func ( l * slog ) Trace ( args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelTrace { l . b . print ( " " , l . tag , args ... ) } }

// Trace formats message using the default formats for its operands, prepends
// the prefix as necessary, and writes to log with LevelTrace.
//
// This is part of the Logger interface implementation.

Trace formats message using the default formats for its operands prepends the prefix as necessary and writes to log with LevelTrace . This is part of the Logger interface implementation .


func (l *slog) Tracef(format string, args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelTrace {
		l.b.printf("TRC", l.tag, format, args...)
	}
}

func ( l * slog ) Tracef ( format string , args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelTrace { l . b . printf ( " " , l . tag , format , args ... ) } }

// Tracef formats message according to format specifier, prepends the prefix as
// necessary, and writes to log with LevelTrace.
//
// This is part of the Logger interface implementation.

Tracef formats message according to format specifier prepends the prefix as necessary and writes to log with LevelTrace . This is part of the Logger interface implementation .


func (l *slog) Debug(args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelDebug {
		l.b.print("DBG", l.tag, args...)
	}
}

func ( l * slog ) Debug ( args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelDebug { l . b . print ( " " , l . tag , args ... ) } }

// Debug formats message using the default formats for its operands, prepends
// the prefix as necessary, and writes to log with LevelDebug.
//
// This is part of the Logger interface implementation.

Debug formats message using the default formats for its operands prepends the prefix as necessary and writes to log with LevelDebug . This is part of the Logger interface implementation .


func (l *slog) Debugf(format string, args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelDebug {
		l.b.printf("DBG", l.tag, format, args...)
	}
}

func ( l * slog ) Debugf ( format string , args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelDebug { l . b . printf ( " " , l . tag , format , args ... ) } }

// Debugf formats message according to format specifier, prepends the prefix as
// necessary, and writes to log with LevelDebug.
//
// This is part of the Logger interface implementation.

Debugf formats message according to format specifier prepends the prefix as necessary and writes to log with LevelDebug . This is part of the Logger interface implementation .


func (l *slog) Info(args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelInfo {
		l.b.print("INF", l.tag, args...)
	}
}

func ( l * slog ) Info ( args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelInfo { l . b . print ( " " , l . tag , args ... ) } }

// Info formats message using the default formats for its operands, prepends
// the prefix as necessary, and writes to log with LevelInfo.
//
// This is part of the Logger interface implementation.

Info formats message using the default formats for its operands prepends the prefix as necessary and writes to log with LevelInfo . This is part of the Logger interface implementation .


func (l *slog) Infof(format string, args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelInfo {
		l.b.printf("INF", l.tag, format, args...)
	}
}

func ( l * slog ) Infof ( format string , args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelInfo { l . b . printf ( " " , l . tag , format , args ... ) } }

// Infof formats message according to format specifier, prepends the prefix as
// necessary, and writes to log with LevelInfo.
//
// This is part of the Logger interface implementation.

Infof formats message according to format specifier prepends the prefix as necessary and writes to log with LevelInfo . This is part of the Logger interface implementation .


func (l *slog) Warn(args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelWarn {
		l.b.print("WRN", l.tag, args...)
	}
}

func ( l * slog ) Warn ( args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelWarn { l . b . print ( " " , l . tag , args ... ) } }

// Warn formats message using the default formats for its operands, prepends
// the prefix as necessary, and writes to log with LevelWarn.
//
// This is part of the Logger interface implementation.

Warn formats message using the default formats for its operands prepends the prefix as necessary and writes to log with LevelWarn . This is part of the Logger interface implementation .


func (l *slog) Warnf(format string, args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelWarn {
		l.b.printf("WRN", l.tag, format, args...)
	}
}

func ( l * slog ) Warnf ( format string , args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelWarn { l . b . printf ( " " , l . tag , format , args ... ) } }

// Warnf formats message according to format specifier, prepends the prefix as
// necessary, and writes to log with LevelWarn.
//
// This is part of the Logger interface implementation.

Warnf formats message according to format specifier prepends the prefix as necessary and writes to log with LevelWarn . This is part of the Logger interface implementation .


func (l *slog) Error(args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelError {
		l.b.print("ERR", l.tag, args...)
	}
}

func ( l * slog ) Error ( args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelError { l . b . print ( " " , l . tag , args ... ) } }

// Error formats message using the default formats for its operands, prepends
// the prefix as necessary, and writes to log with LevelError.
//
// This is part of the Logger interface implementation.

Error formats message using the default formats for its operands prepends the prefix as necessary and writes to log with LevelError . This is part of the Logger interface implementation .


func (l *slog) Errorf(format string, args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelError {
		l.b.printf("ERR", l.tag, format, args...)
	}
}

func ( l * slog ) Errorf ( format string , args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelError { l . b . printf ( " " , l . tag , format , args ... ) } }

// Errorf formats message according to format specifier, prepends the prefix as
// necessary, and writes to log with LevelError.
//
// This is part of the Logger interface implementation.

Errorf formats message according to format specifier prepends the prefix as necessary and writes to log with LevelError . This is part of the Logger interface implementation .


func (l *slog) Critical(args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelCritical {
		l.b.print("CRT", l.tag, args...)
	}
}

func ( l * slog ) Critical ( args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelCritical { l . b . print ( " " , l . tag , args ... ) } }

// Critical formats message using the default formats for its operands, prepends
// the prefix as necessary, and writes to log with LevelCritical.
//
// This is part of the Logger interface implementation.

Critical formats message using the default formats for its operands prepends the prefix as necessary and writes to log with LevelCritical . This is part of the Logger interface implementation .


func (l *slog) Criticalf(format string, args ...interface{}) {
	lvl := l.Level()
	if lvl <= LevelCritical {
		l.b.printf("CRT", l.tag, format, args...)
	}
}

func ( l * slog ) Criticalf ( format string , args ... interface { } ) { lvl := l . Level ( ) if lvl <= LevelCritical { l . b . printf ( " " , l . tag , format , args ... ) } }

// Criticalf formats message according to format specifier, prepends the prefix
// as necessary, and writes to log with LevelCritical.
//
// This is part of the Logger interface implementation.

Criticalf formats message according to format specifier prepends the prefix as necessary and writes to log with LevelCritical . This is part of the Logger interface implementation .


func (l *slog) Level() Level {
	return Level(atomic.LoadUint32((*uint32)(&l.lvl)))
}

func ( l * slog ) Level ( ) Level { return Level ( atomic . LoadUint32 ( ( * uint32 ) ( & l . lvl ) ) ) }

// Level returns the current logging level
//
// This is part of the Logger interface implementation.

Level returns the current logging level This is part of the Logger interface implementation .


func (l *slog) SetLevel(level Level) {
	atomic.StoreUint32((*uint32)(&l.lvl), uint32(level))
}

func ( l * slog ) SetLevel ( level Level ) { atomic . StoreUint32 ( ( * uint32 ) ( & l . lvl ) , uint32 ( level ) ) }

// SetLevel changes the logging level to the passed level.
//
// This is part of the Logger interface implementation.

SetLevel changes the logging level to the passed level . This is part of the Logger interface implementation .


func (permission *Permission) Concat(newPermission *Permission) *Permission {
	var result = Permission{
		Role:         Global,
		AllowedRoles: map[PermissionMode][]string{},
		DeniedRoles:  map[PermissionMode][]string{},
	}

	var appendRoles = func(p *Permission) {
		if p != nil {
			result.Role = p.Role

			for mode, roles := range p.DeniedRoles {
				result.DeniedRoles[mode] = append(result.DeniedRoles[mode], roles...)
			}

			for mode, roles := range p.AllowedRoles {
				result.AllowedRoles[mode] = append(result.AllowedRoles[mode], roles...)
			}
		}
	}

	appendRoles(newPermission)
	appendRoles(permission)
	return &result
}

func ( permission * Permission ) Concat ( newPermission * Permission ) * Permission { var result = Permission { Role : Global , AllowedRoles : map [ PermissionMode ] [ ] string { } , DeniedRoles : map [ PermissionMode ] [ ] string { } , } var appendRoles = func ( p * Permission ) { if p != nil { result . Role = p . Role for mode , roles := range p . DeniedRoles { result . DeniedRoles [ mode ] = append ( result . DeniedRoles [ mode ] , roles ... ) } for mode , roles := range p . AllowedRoles { result . AllowedRoles [ mode ] = append ( result . AllowedRoles [ mode ] , roles ... ) } } } appendRoles ( newPermission ) appendRoles ( permission ) return & result }

// Concat concat two permissions into a new one


func (permission Permission) HasPermission(mode PermissionMode, roles ...interface{}) bool {
	var roleNames []string
	for _, role := range roles {
		if r, ok := role.(string); ok {
			roleNames = append(roleNames, r)
		} else if roler, ok := role.(Roler); ok {
			roleNames = append(roleNames, roler.GetRoles()...)
		} else {
			fmt.Printf("invalid role %#v\n", role)
			return false
		}
	}

	if len(permission.DeniedRoles) != 0 {
		if DeniedRoles := permission.DeniedRoles[mode]; DeniedRoles != nil {
			if includeRoles(DeniedRoles, roleNames) {
				return false
			}
		}
	}

	// return true if haven't define allowed roles
	if len(permission.AllowedRoles) == 0 {
		return true
	}

	if AllowedRoles := permission.AllowedRoles[mode]; AllowedRoles != nil {
		if includeRoles(AllowedRoles, roleNames) {
			return true
		}
	}

	return false
}

// HasPermission check roles has permission for mode or not


func ConcatPermissioner(ps ...Permissioner) Permissioner {
	var newPS []Permissioner
	for _, p := range ps {
		if p != nil {
			newPS = append(newPS, p)
		}
	}
	return permissioners(newPS)
}

func ConcatPermissioner ( ps ... Permissioner ) Permissioner { var newPS [ ] Permissioner for _ , p := range ps { if p != nil { newPS = append ( newPS , p ) } } return permissioners ( newPS ) }

// ConcatPermissioner concat permissioner


func (ps permissioners) HasPermission(mode PermissionMode, roles ...interface{}) bool {
	for _, p := range ps {
		if p != nil && !p.HasPermission(mode, roles) {
			return false
		}
	}

	return true
}

func ( ps permissioners ) HasPermission ( mode PermissionMode , roles ... interface { } ) bool { for _ , p := range ps { if p != nil && ! p . HasPermission ( mode , roles ) { return false } } return true }

// HasPermission check has permission for permissioners or not


func (role *Role) Register(name string, fc Checker) {
	if role.definitions == nil {
		role.definitions = map[string]Checker{}
	}

	definition := role.definitions[name]
	if definition != nil {
		fmt.Printf("Role `%v` already defined, overwrited it!\n", name)
	}
	role.definitions[name] = fc
}

func ( role * Role ) Register ( name string , fc Checker ) { if role . definitions == nil { role . definitions = map [ string ] Checker { } } definition := role . definitions [ name ] if definition != nil { fmt . Printf ( " \n " , name ) } role . definitions [ name ] = fc }

// Register register role with conditions


func (role *Role) NewPermission() *Permission {
	return &Permission{
		Role:         role,
		AllowedRoles: map[PermissionMode][]string{},
		DeniedRoles:  map[PermissionMode][]string{},
	}
}

func ( role * Role ) NewPermission ( ) * Permission { return & Permission { Role : role , AllowedRoles : map [ PermissionMode ] [ ] string { } , DeniedRoles : map [ PermissionMode ] [ ] string { } , } }


func (role *Role) Get(name string) (Checker, bool) {
	fc, ok := role.definitions[name]
	return fc, ok
}

func ( role * Role ) Get ( name string ) ( Checker , bool ) { fc , ok := role . definitions [ name ] return fc , ok }


func (p *Process) isPtrFromHeap(a core.Address) bool {
	return p.findHeapInfo(a).IsPtr(a, p.proc.PtrSize())
}

func ( p * Process ) isPtrFromHeap ( a core . Address ) bool { return p . findHeapInfo ( a ) . IsPtr ( a , p . proc . PtrSize ( ) ) }

// isPtrFromHeap reports whether the inferior at address a contains a pointer.
// a must be somewhere in the heap.

isPtrFromHeap reports whether the inferior at address a contains a pointer . a must be somewhere in the heap .


func (p *Process) IsPtr(a core.Address) bool {
	h := p.findHeapInfo(a)
	if h != nil {
		return h.IsPtr(a, p.proc.PtrSize())
	}
	for _, m := range p.modules {
		for _, s := range [2]string{"data", "bss"} {
			min := core.Address(m.r.Field(s).Uintptr())
			max := core.Address(m.r.Field("e" + s).Uintptr())
			if a < min || a >= max {
				continue
			}
			gc := m.r.Field("gc" + s + "mask").Field("bytedata").Address()
			i := a.Sub(min)
			return p.proc.ReadUint8(gc.Add(i/8))>>uint(i%8) != 0
		}
	}
	// Everywhere else can't be a pointer. At least, not a pointer into the Go heap.
	// TODO: stacks?
	// TODO: finalizers?
	return false
}

// IsPtr reports whether the inferior at address a contains a pointer.

IsPtr reports whether the inferior at address a contains a pointer .


func (p *Process) FindObject(a core.Address) (Object, int64) {
	// Round down to the start of an object.
	h := p.findHeapInfo(a)
	if h == nil {
		// Not in Go heap, or in a span
		// that doesn't hold Go objects (freed, stacks, ...)
		return 0, 0
	}
	x := h.base.Add(a.Sub(h.base) / h.size * h.size)
	// Check if object is marked.
	h = p.findHeapInfo(x)
	if h.mark>>(uint64(x)%heapInfoSize/8)&1 == 0 { // free or garbage
		return 0, 0
	}
	return Object(x), a.Sub(x)
}

// FindObject finds the object containing a.  Returns that object and the offset within
// that object to which a points.
// Returns 0,0 if a doesn't point to a live heap object.

FindObject finds the object containing a . Returns that object and the offset within that object to which a points . Returns 0 0 if a doesn t point to a live heap object .


func (p *Process) ForEachObject(fn func(x Object) bool) {
	for _, k := range p.pages {
		pt := p.pageTable[k]
		for i := range pt {
			h := &pt[i]
			m := h.mark
			for m != 0 {
				j := bits.TrailingZeros64(m)
				m &= m - 1
				x := Object(k)*pageTableSize*heapInfoSize + Object(i)*heapInfoSize + Object(j)*8
				if !fn(x) {
					return
				}
			}
		}
	}
}

func ( p * Process ) ForEachObject ( fn func ( x Object ) bool ) { for _ , k := range p . pages { pt := p . pageTable [ k ] for i := range pt { h := & pt [ i ] m := h . mark for m != 0 { j := bits . TrailingZeros64 ( m ) m &= m - 1 x := Object ( k ) * pageTableSize * heapInfoSize + Object ( i ) * heapInfoSize + Object ( j ) * 8 if ! fn ( x ) { return } } } } }

// ForEachObject calls fn with each object in the Go heap.
// If fn returns false, ForEachObject returns immediately.

ForEachObject calls fn with each object in the Go heap . If fn returns false ForEachObject returns immediately .


func (p *Process) ForEachRoot(fn func(r *Root) bool) {
	for _, r := range p.globals {
		if !fn(r) {
			return
		}
	}
	for _, g := range p.goroutines {
		for _, f := range g.frames {
			for _, r := range f.roots {
				if !fn(r) {
					return
				}
			}
		}
	}
}

func ( p * Process ) ForEachRoot ( fn func ( r * Root ) bool ) { for _ , r := range p . globals { if ! fn ( r ) { return } } for _ , g := range p . goroutines { for _ , f := range g . frames { for _ , r := range f . roots { if ! fn ( r ) { return } } } } }

// ForEachRoot calls fn with each garbage collection root.
// If fn returns false, ForEachRoot returns immediately.

ForEachRoot calls fn with each garbage collection root . If fn returns false ForEachRoot returns immediately .


func (p *Process) Addr(x Object) core.Address {
	return core.Address(x)
}

func ( p * Process ) Addr ( x Object ) core . Address { return core . Address ( x ) }

// Addr returns the starting address of x.

Addr returns the starting address of x .


func (p *Process) Size(x Object) int64 {
	return p.findHeapInfo(core.Address(x)).size
}

func ( p * Process ) Size ( x Object ) int64 { return p . findHeapInfo ( core . Address ( x ) ) . size }


func (p *Process) Type(x Object) (*Type, int64) {
	p.typeHeap()

	i, _ := p.findObjectIndex(core.Address(x))
	return p.types[i].t, p.types[i].r
}

func ( p * Process ) Type ( x Object ) ( * Type , int64 ) { p . typeHeap ( ) i , _ := p . findObjectIndex ( core . Address ( x ) ) return p . types [ i ] . t , p . types [ i ] . r }

// Type returns the type and repeat count for the object x.
// x contains at least repeat copies of the returned type.

Type returns the type and repeat count for the object x . x contains at least repeat copies of the returned type .


func (p *Process) ForEachRootPtr(r *Root, fn func(int64, Object, int64) bool) {
	edges1(p, r, 0, r.Type, fn)
}

func ( p * Process ) ForEachRootPtr ( r * Root , fn func ( int64 , Object , int64 ) bool ) { edges1 ( p , r , 0 , r . Type , fn ) }

// ForEachRootPtr behaves like ForEachPtr but it starts with a Root instead of an Object.

ForEachRootPtr behaves like ForEachPtr but it starts with a Root instead of an Object .


func edges1(p *Process, r *Root, off int64, t *Type, fn func(int64, Object, int64) bool) bool {
	switch t.Kind {
	case KindBool, KindInt, KindUint, KindFloat, KindComplex:
		// no edges here
	case KindIface, KindEface:
		// The first word is a type or itab.
		// Itabs are never in the heap.
		// Types might be, though.
		a := r.Addr.Add(off)
		if r.Frame == nil || r.Frame.Live[a] {
			dst, off2 := p.FindObject(p.proc.ReadPtr(a))
			if dst != 0 {
				if !fn(off, dst, off2) {
					return false
				}
			}
		}
		// Treat second word like a pointer.
		off += p.proc.PtrSize()
		fallthrough
	case KindPtr, KindString, KindSlice, KindFunc:
		a := r.Addr.Add(off)
		if r.Frame == nil || r.Frame.Live[a] {
			dst, off2 := p.FindObject(p.proc.ReadPtr(a))
			if dst != 0 {
				if !fn(off, dst, off2) {
					return false
				}
			}
		}
	case KindArray:
		s := t.Elem.Size
		for i := int64(0); i < t.Count; i++ {
			if !edges1(p, r, off+i*s, t.Elem, fn) {
				return false
			}
		}
	case KindStruct:
		for _, f := range t.Fields {
			if !edges1(p, r, off+f.Off, f.Type, fn) {
				return false
			}
		}
	}
	return true
}

func
edges1
(
p
*
Process
,
r
*
Root
,
off
int64
,
t
*
Type
,
fn
func
(
int64
,
Object
,
int64
)
bool
)
bool
{
switch
t
.
Kind
{
case
KindBool
,
KindInt
,
KindUint
,
KindFloat
,
KindComplex
:
// no edges here
case
KindIface
,
KindEface
:
// The first word is a type or itab.
// Itabs are never in the heap.
// Types might be, though.
a
:=
r
.
Addr
.
Add
(
off
)
if
r
.
Frame
==
||
r
.
Frame
.
Live
[
a
]
{
dst
,
off2
:=
p
.
FindObject
(
p
.
proc
.
ReadPtr
(
a
)
)
if
dst
!=
0
{
if
!
fn
(
off
,
dst
,
off2
)
{
return
false
}
}
}
// Treat second word like a pointer.
off
+=
p
.
proc
.
PtrSize
(
)
fallthrough
case
KindPtr
,
KindString
,
KindSlice
,
KindFunc
:
a
:=
r
.
Addr
.
Add
(
off
)
if
r
.
Frame
==
||
r
.
Frame
.
Live
[
a
]
{
dst
,
off2
:=
p
.
FindObject
(
p
.
proc
.
ReadPtr
(
a
)
)
if
dst
!=
0
{
if
!
fn
(
off
,
dst
,
off2
)
{
return
false
}
}
}
case
KindArray
:
s
:=
t
.
Elem
.
Size
for
i
:=
int64
(
0
)
;
i
<
t
.
Count
;
i
++
{
if
!
edges1
(
p
,
r
,
off
+
i
*
s
,
t
.
Elem
,
fn
)
{
return
false
}
}
case
KindStruct
:
for
_
,
f
:=
range
t
.
Fields
{
if
!
edges1
(
p
,
r
,
off
+
f
.
Off
,
f
.
Type
,
fn
)
{
return
false
}
}
}
return
true
}

// edges1 calls fn for the edges found in an object of type t living at offset off in the root r.
// If fn returns false, return immediately with false.

edges1 calls fn for the edges found in an object of type t living at offset off in the root r . If fn returns false return immediately with false .


func (p *Process) setHeapPtr(a core.Address) {
	h := p.allocHeapInfo(a)
	if p.proc.PtrSize() == 8 {
		i := uint(a%heapInfoSize) / 8
		h.ptr[0] |= uint64(1) << i
		return
	}
	i := a % heapInfoSize / 4
	h.ptr[i/64] |= uint64(1) << (i % 64)
}

func ( p * Process ) setHeapPtr ( a core . Address ) { h := p . allocHeapInfo ( a ) if p . proc . PtrSize ( ) == 8 { i := uint ( a % heapInfoSize ) / 8 h . ptr [ 0 ] |= uint64 ( 1 ) << i return } i := a % heapInfoSize / 4 h . ptr [ i / 64 ] |= uint64 ( 1 ) << ( i % 64 ) }

// setHeapPtr records that the memory at heap address a contains a pointer.

setHeapPtr records that the memory at heap address a contains a pointer .


func (p *Process) findHeapInfo(a core.Address) *heapInfo {
	k := a / heapInfoSize / pageTableSize
	i := a / heapInfoSize % pageTableSize
	t := p.pageTable[k]
	if t == nil {
		return nil
	}
	h := &t[i]
	if h.base == 0 {
		return nil
	}
	return h
}

func ( p * Process ) findHeapInfo ( a core . Address ) * heapInfo { k := a / heapInfoSize / pageTableSize i := a / heapInfoSize % pageTableSize t := p . pageTable [ k ] if t == nil { return nil } h := & t [ i ] if h . base == 0 { return nil } return h }

// findHeapInfo finds the heapInfo structure for a.
// Returns nil if a is not a heap address.

findHeapInfo finds the heapInfo structure for a . Returns nil if a is not a heap address .


func (p *Process) allocHeapInfo(a core.Address) *heapInfo {
	k := a / heapInfoSize / pageTableSize
	i := a / heapInfoSize % pageTableSize
	t := p.pageTable[k]
	if t == nil {
		t = new(pageTableEntry)
		for j := 0; j < pageTableSize; j++ {
			t[j].firstIdx = -1
		}
		p.pageTable[k] = t
		p.pages = append(p.pages, k)
	}
	return &t[i]
}

func ( p * Process ) allocHeapInfo ( a core . Address ) * heapInfo { k := a / heapInfoSize / pageTableSize i := a / heapInfoSize % pageTableSize t := p . pageTable [ k ] if t == nil { t = new ( pageTableEntry ) for j := 0 ; j < pageTableSize ; j ++ { t [ j ] . firstIdx = - 1 } p . pageTable [ k ] = t p . pages = append ( p . pages , k ) } return & t [ i ] }

// Same as findHeapInfo, but allocates the heapInfo if it
// hasn't been allocated yet.

Same as findHeapInfo but allocates the heapInfo if it hasn t been allocated yet .


func runtimeName(dt dwarf.Type) string {
	switch x := dt.(type) {
	case *dwarf.PtrType:
		if _, ok := x.Type.(*dwarf.VoidType); ok {
			return "unsafe.Pointer"
		}
		return "*" + runtimeName(x.Type)
	case *dwarf.ArrayType:
		return fmt.Sprintf("[%d]%s", x.Count, runtimeName(x.Type))
	case *dwarf.StructType:
		if !strings.HasPrefix(x.StructName, "struct {") {
			// This is a named type, return that name.
			return stripPackagePath(x.StructName)
		}
		// Figure out which fields have anonymous names.
		var anon []bool
		for _, f := range strings.Split(x.StructName[8:len(x.StructName)-1], ";") {
			f = strings.TrimSpace(f)
			anon = append(anon, !strings.Contains(f, " "))
			// TODO: this isn't perfect. If the field type has a space in it,
			// then this logic doesn't work. Need to search for keyword for
			// field type, like "interface", "struct", ...
		}
		// Make sure anon is long enough. This probably never triggers.
		for len(anon) < len(x.Field) {
			anon = append(anon, false)
		}

		// Build runtime name from the DWARF fields.
		s := "struct {"
		first := true
		for _, f := range x.Field {
			if !first {
				s += ";"
			}
			name := f.Name
			if i := strings.Index(name, "."); i >= 0 {
				name = name[i+1:]
			}
			if anon[0] {
				s += fmt.Sprintf(" %s", runtimeName(f.Type))
			} else {
				s += fmt.Sprintf(" %s %s", name, runtimeName(f.Type))
			}
			first = false
			anon = anon[1:]
		}
		s += " }"
		return s
	default:
		return stripPackagePath(dt.String())
	}
}

// Generate the name the runtime uses for a dwarf type. The DWARF generator
// and the runtime use slightly different names for the same underlying type.

Generate the name the runtime uses for a dwarf type . The DWARF generator and the runtime use slightly different names for the same underlying type .


func (p *Process) readRuntimeConstants() {
	p.rtConstants = map[string]int64{}

	// Hardcoded values for Go 1.9.
	// (Go did not have constants in DWARF before 1.10.)
	m := p.rtConstants
	m["_MSpanDead"] = 0
	m["_MSpanInUse"] = 1
	m["_MSpanManual"] = 2
	m["_MSpanFree"] = 3
	m["_Gidle"] = 0
	m["_Grunnable"] = 1
	m["_Grunning"] = 2
	m["_Gsyscall"] = 3
	m["_Gwaiting"] = 4
	m["_Gdead"] = 6
	m["_Gscan"] = 0x1000
	m["_PCDATA_StackMapIndex"] = 0
	m["_FUNCDATA_LocalsPointerMaps"] = 1
	m["_FUNCDATA_ArgsPointerMaps"] = 0
	m["tflagExtraStar"] = 1 << 1
	m["kindGCProg"] = 1 << 6
	m["kindDirectIface"] = 1 << 5
	m["_PageSize"] = 1 << 13
	m["_KindSpecialFinalizer"] = 1

	// From 1.10, these constants are recorded in DWARF records.
	d, _ := p.proc.DWARF()
	r := d.Reader()
	for e, err := r.Next(); e != nil && err == nil; e, err = r.Next() {
		if e.Tag != dwarf.TagConstant {
			continue
		}
		f := e.AttrField(dwarf.AttrName)
		if f == nil {
			continue
		}
		name := f.Val.(string)
		if !strings.HasPrefix(name, "runtime.") {
			continue
		}
		name = name[8:]
		c := e.AttrField(dwarf.AttrConstValue)
		if c == nil {
			continue
		}
		p.rtConstants[name] = c.Val.(int64)
	}
}

// readRuntimeConstants populates the p.rtConstants map.

readRuntimeConstants populates the p . rtConstants map .


func (t *funcTab) add(min, max core.Address, f *Func) {
	t.entries = append(t.entries, funcTabEntry{min: min, max: max, f: f})
}

func ( t * funcTab ) add ( min , max core . Address , f * Func ) { t . entries = append ( t . entries , funcTabEntry { min : min , max : max , f : f } ) }

// add records that PCs in the range [min,max) map to function f.

add records that PCs in the range [ min max ) map to function f .


func (t *funcTab) sort() {
	sort.Slice(t.entries, func(i, j int) bool {
		return t.entries[i].min < t.entries[j].min
	})
}

func ( t * funcTab ) sort ( ) { sort . Slice ( t . entries , func ( i , j int ) bool { return t . entries [ i ] . min < t . entries [ j ] . min } ) }

// sort must be called after all the adds, but before any find.

sort must be called after all the adds but before any find .


func (t *funcTab) find(pc core.Address) *Func {
	n := sort.Search(len(t.entries), func(i int) bool {
		return t.entries[i].max > pc
	})
	if n == len(t.entries) || pc < t.entries[n].min || pc >= t.entries[n].max {
		return nil
	}
	return t.entries[n].f
}

func ( t * funcTab ) find ( pc core . Address ) * Func { n := sort . Search ( len ( t . entries ) , func ( i int ) bool { return t . entries [ i ] . max > pc } ) if n == len ( t . entries ) || pc < t . entries [ n ] . min || pc >= t . entries [ n ] . max { return nil } return t . entries [ n ] . f }

// Finds a Func for the given address.  Sort must have been called already.

Finds a Func for the given address . Sort must have been called already .


func (t *pcTab) read(core *core.Process, data core.Address) {
	var pcQuantum int64
	switch core.Arch() {
	case "386", "amd64", "amd64p32":
		pcQuantum = 1
	case "s390x":
		pcQuantum = 2
	case "arm", "arm64", "mips", "mipsle", "mips64", "mips64le", "ppc64", "ppc64le":
		pcQuantum = 4
	default:
		panic("unknown architecture " + core.Arch())
	}
	val := int64(-1)
	first := true
	for {
		// Advance value.
		v, n := readVarint(core, data)
		if v == 0 && !first {
			return
		}
		data = data.Add(n)
		if v&1 != 0 {
			val += ^(v >> 1)
		} else {
			val += v >> 1
		}

		// Advance pc.
		v, n = readVarint(core, data)
		data = data.Add(n)
		t.entries = append(t.entries, pcTabEntry{bytes: v * pcQuantum, val: val})
		first = false
	}
}

func
(
t
*
pcTab
)
read
(
core
*
core
.
Process
,
data
core
.
Address
)
{
var
pcQuantum
int64
switch
core
.
Arch
(
)
{
case
"
"
,
"
"
,
"
"
:
pcQuantum
=
1
case
"
"
:
pcQuantum
=
2
case
"
"
,
"
"
,
"
"
,
"
"
,
"
"
,
"
"
,
"
"
,
"
"
:
pcQuantum
=
4
default
:
panic
(
"
"
+
core
.
Arch
(
)
)
}
val
:=
int64
(
1
)
first
:=
true
for
{
// Advance value.
v
,
n
:=
readVarint
(
core
,
data
)
if
v
==
0
&&
!
first
{
return
}
data
=
data
.
Add
(
n
)
if
v
&
1
!=
0
{
val
+=
^
(
v
>>
1
)
}
else
{
val
+=
v
>>
1
}
// Advance pc.
v
,
n
=
readVarint
(
core
,
data
)
data
=
data
.
Add
(
n
)
t
.
entries
=
append
(
t
.
entries
,
pcTabEntry
{
bytes
:
v
*
pcQuantum
,
val
:
val
}
)
first
=
false
}
}

// read parses a pctab from the core file at address data.

read parses a pctab from the core file at address data .


func readVarint(core *core.Process, a core.Address) (val, n int64) {
	for {
		b := core.ReadUint8(a)
		val |= int64(b&0x7f) << uint(n*7)
		n++
		a++
		if b&0x80 == 0 {
			return
		}
	}
}

func readVarint ( core * core . Process , a core . Address ) ( val , n int64 ) { for { b := core . ReadUint8 ( a ) val |= int64 ( b & 0x7f ) << uint ( n * 7 ) n ++ a ++ if b & 0x80 == 0 { return } } }

// readVarint reads a varint from the core file.
// val is the value, n is the number of bytes consumed.

readVarint reads a varint from the core file . val is the value n is the number of bytes consumed .


func useLine(c *cobra.Command) string {
	var useline string
	if c.HasParent() {
		useline = commandPath(c.Parent()) + " " + c.Use
	} else {
		useline = c.Use
	}
	if c.DisableFlagsInUseLine {
		return useline
	}
	if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") {
		useline += " [flags]"
	}
	return useline
}

func useLine ( c * cobra . Command ) string { var useline string if c . HasParent ( ) { useline = commandPath ( c . Parent ( ) ) + " " + c . Use } else { useline = c . Use } if c . DisableFlagsInUseLine { return useline } if c . HasAvailableFlags ( ) && ! strings . Contains ( useline , " " ) { useline += " " } return useline }

// useLine is like cobra.Command.UseLine but tweaked to use commandPath.

useLine is like cobra . Command . UseLine but tweaked to use commandPath .


func commandPath(c *cobra.Command) string {
	if c.HasParent() {
		return commandPath(c) + " " + c.Name()
	}
	return c.Use
}

func commandPath ( c * cobra . Command ) string { if c . HasParent ( ) { return commandPath ( c ) + " " + c . Name ( ) } return c . Use }

// commandPath is like cobra.Command.CommandPath but tweaked to
// use c.Use instead of c.Name for the root command so it works
// with viewcore's unusual command structure.

commandPath is like cobra . Command . CommandPath but tweaked to use c . Use instead of c . Name for the root command so it works with viewcore s unusual command structure .


func readCore() (*core.Process, *gocore.Process, error) {
	cc := coreCache
	if cc.cfg == cfg {
		return cc.coreP, cc.gocoreP, cc.err
	}
	c, err := core.Core(cfg.corefile, cfg.base, cfg.exePath)
	if err != nil {
		return nil, nil, err
	}
	p, err := gocore.Core(c)
	if os.IsNotExist(err) && cfg.exePath == "" {
		return nil, nil, fmt.Errorf("%v; consider specifying the --exe flag", err)
	}
	if err != nil {
		return nil, nil, err
	}
	for _, w := range c.Warnings() {
		fmt.Fprintf(os.Stderr, "WARNING: %s\n", w)
	}
	cc.cfg = cfg
	cc.coreP = c
	cc.gocoreP = p
	cc.err = nil
	return c, p, nil
}

func readCore ( ) ( * core . Process , * gocore . Process , error ) { cc := coreCache if cc . cfg == cfg { return cc . coreP , cc . gocoreP , cc . err } c , err := core . Core ( cfg . corefile , cfg . base , cfg . exePath ) if err != nil { return nil , nil , err } p , err := gocore . Core ( c ) if os . IsNotExist ( err ) && cfg . exePath == " " { return nil , nil , fmt . Errorf ( " " , err ) } if err != nil { return nil , nil , err } for _ , w := range c . Warnings ( ) { fmt . Fprintf ( os . Stderr , " \n " , w ) } cc . cfg = cfg cc . coreP = c cc . gocoreP = p cc . err = nil return c , p , nil }

// readCore reads corefile and returns core and gocore process states.

readCore reads corefile and returns core and gocore process states .


func typeName(c *gocore.Process, x gocore.Object) string {
	size := c.Size(x)
	typ, repeat := c.Type(x)
	if typ == nil {
		return fmt.Sprintf("unk%d", size)
	}
	name := typ.String()
	n := size / typ.Size
	if n > 1 {
		if repeat < n {
			name = fmt.Sprintf("[%d+%d?]%s", repeat, n-repeat, name)
		} else {
			name = fmt.Sprintf("[%d]%s", repeat, name)
		}
	}
	return name
}

func typeName ( c * gocore . Process , x gocore . Object ) string { size := c . Size ( x ) typ , repeat := c . Type ( x ) if typ == nil { return fmt . Sprintf ( " " , size ) } name := typ . String ( ) n := size / typ . Size if n > 1 { if repeat < n { name = fmt . Sprintf ( " " , repeat , n - repeat , name ) } else { name = fmt . Sprintf ( " " , repeat , name ) } } return name }

// typeName returns a string representing the type of this object.

typeName returns a string representing the type of this object .


func fieldName(c *gocore.Process, x gocore.Object, off int64) string {
	size := c.Size(x)
	typ, repeat := c.Type(x)
	if typ == nil {
		return fmt.Sprintf("f%d", off)
	}
	n := size / typ.Size
	i := off / typ.Size
	if i == 0 && repeat == 1 {
		// Probably a singleton object, no need for array notation.
		return typeFieldName(typ, off)
	}
	if i >= n {
		// Partial space at the end of the object - the type can't be complete.
		return fmt.Sprintf("f%d", off)
	}
	q := ""
	if i >= repeat {
		// Past the known repeat section, add a ? because we're not sure about the type.
		q = "?"
	}
	return fmt.Sprintf("[%d]%s%s", i, typeFieldName(typ, off-i*typ.Size), q)
}

// fieldName returns the name of the field at offset off in x.

fieldName returns the name of the field at offset off in x .


func typeFieldName(t *gocore.Type, off int64) string {
	switch t.Kind {
	case gocore.KindBool, gocore.KindInt, gocore.KindUint, gocore.KindFloat:
		return ""
	case gocore.KindComplex:
		if off == 0 {
			return ".real"
		}
		return ".imag"
	case gocore.KindIface, gocore.KindEface:
		if off == 0 {
			return ".type"
		}
		return ".data"
	case gocore.KindPtr, gocore.KindFunc:
		return ""
	case gocore.KindString:
		if off == 0 {
			return ".ptr"
		}
		return ".len"
	case gocore.KindSlice:
		if off == 0 {
			return ".ptr"
		}
		if off <= t.Size/2 {
			return ".len"
		}
		return ".cap"
	case gocore.KindArray:
		s := t.Elem.Size
		i := off / s
		return fmt.Sprintf("[%d]%s", i, typeFieldName(t.Elem, off-i*s))
	case gocore.KindStruct:
		for _, f := range t.Fields {
			if f.Off <= off && off < f.Off+f.Type.Size {
				return "." + f.Name + typeFieldName(f.Type, off-f.Off)
			}
		}
	}
	return ".???"
}

func typeFieldName ( t * gocore . Type , off int64 ) string { switch t . Kind { case gocore . KindBool , gocore . KindInt , gocore . KindUint , gocore . KindFloat : return " " case gocore . KindComplex : if off == 0 { return " " } return " " case gocore . KindIface , gocore . KindEface : if off == 0 { return " " } return " " case gocore . KindPtr , gocore . KindFunc : return " " case gocore . KindString : if off == 0 { return " " } return " " case gocore . KindSlice : if off == 0 { return " " } if off <= t . Size / 2 { return " " } return " " case gocore . KindArray : s := t . Elem . Size i := off / s return fmt . Sprintf ( " " , i , typeFieldName ( t . Elem , off - i * s ) ) case gocore . KindStruct : for _ , f := range t . Fields { if f . Off <= off && off < f . Off + f . Type . Size { return " " + f . Name + typeFieldName ( f . Type , off - f . Off ) } } } return " " }

// typeFieldName returns the name of the field at offset off in t.

typeFieldName returns the name of the field at offset off in t .


func (p *Process) FindFunc(pc core.Address) *Func {
	return p.funcTab.find(pc)
}

func ( p * Process ) FindFunc ( pc core . Address ) * Func { return p . funcTab . find ( pc ) }

// FindFunc returns the function which contains the code at address pc, if any.

FindFunc returns the function which contains the code at address pc if any .


func Core(proc *core.Process) (p *Process, err error) {
	// Make sure we have DWARF info.
	if _, err := proc.DWARF(); err != nil {
		return nil, err
	}

	// Guard against failures of proc.Read* routines.
	/*
		defer func() {
			e := recover()
			if e == nil {
				return
			}
			p = nil
			if x, ok := e.(error); ok {
				err = x
				return
			}
			panic(e) // Not an error, re-panic it.
		}()
	*/

	p = &Process{
		proc:       proc,
		runtimeMap: map[core.Address]*Type{},
		dwarfMap:   map[dwarf.Type]*Type{},
	}

	// Initialize everything that just depends on DWARF.
	p.readDWARFTypes()
	p.readRuntimeConstants()
	p.readGlobals()

	// Find runtime globals we care about. Initialize regions for them.
	p.rtGlobals = map[string]region{}
	for _, g := range p.globals {
		if strings.HasPrefix(g.Name, "runtime.") {
			p.rtGlobals[g.Name[8:]] = region{p: p, a: g.Addr, typ: g.Type}
		}
	}

	// Read all the data that depend on runtime globals.
	p.buildVersion = p.rtGlobals["buildVersion"].String()
	p.readModules()
	p.readHeap()
	p.readGs()
	p.readStackVars() // needs to be after readGs.
	p.markObjects()   // needs to be after readGlobals, readStackVars.

	return p, nil
}

// Core takes a loaded core file and extracts Go information from it.

Core takes a loaded core file and extracts Go information from it .


func (r region) Address() core.Address {
	if r.typ.Kind != KindPtr {
		panic("can't ask for the Address of a non-pointer " + r.typ.Name)
	}
	return r.p.proc.ReadPtr(r.a)
}

func ( r region ) Address ( ) core . Address { if r . typ . Kind != KindPtr { panic ( " " + r . typ . Name ) } return r . p . proc . ReadPtr ( r . a ) }

// Address returns the address that a region of pointer type points to.

Address returns the address that a region of pointer type points to .


func (r region) Int() int64 {
	if r.typ.Kind != KindInt || r.typ.Size != r.p.proc.PtrSize() {
		panic("not an int: " + r.typ.Name)
	}
	return r.p.proc.ReadInt(r.a)
}

func ( r region ) Int ( ) int64 { if r . typ . Kind != KindInt || r . typ . Size != r . p . proc . PtrSize ( ) { panic ( " " + r . typ . Name ) } return r . p . proc . ReadInt ( r . a ) }

// Int returns the int value stored in r.


func (r region) Uintptr() uint64 {
	if r.typ.Kind != KindUint || r.typ.Size != r.p.proc.PtrSize() {
		panic("not a uintptr: " + r.typ.Name)
	}
	return r.p.proc.ReadUintptr(r.a)
}

func ( r region ) Uintptr ( ) uint64 { if r . typ . Kind != KindUint || r . typ . Size != r . p . proc . PtrSize ( ) { panic ( " " + r . typ . Name ) } return r . p . proc . ReadUintptr ( r . a ) }

// Uintptr returns the uintptr value stored in r.

Uintptr returns the uintptr value stored in r .


func (r region) Cast(typ string) region {
	return region{p: r.p, a: r.a, typ: r.p.findType(typ)}
}

func ( r region ) Cast ( typ string ) region { return region { p : r . p , a : r . a , typ : r . p . findType ( typ ) } }


func (r region) Deref() region {
	if r.typ.Kind != KindPtr {
		panic("can't deref on non-pointer: " + r.typ.Name)
	}
	if r.typ.Elem == nil {
		panic("can't deref unsafe.Pointer")
	}
	p := r.p.proc.ReadPtr(r.a)
	return region{p: r.p, a: p, typ: r.typ.Elem}
}

func ( r region ) Deref ( ) region { if r . typ . Kind != KindPtr { panic ( " " + r . typ . Name ) } if r . typ . Elem == nil { panic ( " " ) } p := r . p . proc . ReadPtr ( r . a ) return region { p : r . p , a : p , typ : r . typ . Elem } }

// Deref loads from a pointer. r must contain a pointer.

Deref loads from a pointer . r must contain a pointer .


func (r region) Uint64() uint64 {
	if r.typ.Kind != KindUint || r.typ.Size != 8 {
		panic("bad uint64 type " + r.typ.Name)
	}
	return r.p.proc.ReadUint64(r.a)
}

func ( r region ) Uint64 ( ) uint64 { if r . typ . Kind != KindUint || r . typ . Size != 8 { panic ( " " + r . typ . Name ) } return r . p . proc . ReadUint64 ( r . a ) }

// Uint64 returns the uint64 value stored in r.
// r must have type uint64.

Uint64 returns the uint64 value stored in r . r must have type uint64 .


func (r region) Uint32() uint32 {
	if r.typ.Kind != KindUint || r.typ.Size != 4 {
		panic("bad uint32 type " + r.typ.Name)
	}
	return r.p.proc.ReadUint32(r.a)
}

func ( r region ) Uint32 ( ) uint32 { if r . typ . Kind != KindUint || r . typ . Size != 4 { panic ( " " + r . typ . Name ) } return r . p . proc . ReadUint32 ( r . a ) }

// Uint32 returns the uint32 value stored in r.
// r must have type uint32.

Uint32 returns the uint32 value stored in r . r must have type uint32 .


func (r region) Int32() int32 {
	if r.typ.Kind != KindInt || r.typ.Size != 4 {
		panic("bad int32 type " + r.typ.Name)
	}
	return r.p.proc.ReadInt32(r.a)
}

func ( r region ) Int32 ( ) int32 { if r . typ . Kind != KindInt || r . typ . Size != 4 { panic ( " " + r . typ . Name ) } return r . p . proc . ReadInt32 ( r . a ) }

// Int32 returns the int32 value stored in r.
// r must have type int32.

Int32 returns the int32 value stored in r . r must have type int32 .


func (r region) Uint16() uint16 {
	if r.typ.Kind != KindUint || r.typ.Size != 2 {
		panic("bad uint16 type " + r.typ.Name)
	}
	return r.p.proc.ReadUint16(r.a)
}

func ( r region ) Uint16 ( ) uint16 { if r . typ . Kind != KindUint || r . typ . Size != 2 { panic ( " " + r . typ . Name ) } return r . p . proc . ReadUint16 ( r . a ) }

// Uint16 returns the uint16 value stored in r.
// r must have type uint16.

Uint16 returns the uint16 value stored in r . r must have type uint16 .


func (r region) Uint8() uint8 {
	if r.typ.Kind != KindUint || r.typ.Size != 1 {
		panic("bad uint8 type " + r.typ.Name)
	}
	return r.p.proc.ReadUint8(r.a)
}

func ( r region ) Uint8 ( ) uint8 { if r . typ . Kind != KindUint || r . typ . Size != 1 { panic ( " " + r . typ . Name ) } return r . p . proc . ReadUint8 ( r . a ) }

// Uint8 returns the uint8 value stored in r.
// r must have type uint8.

Uint8 returns the uint8 value stored in r . r must have type uint8 .


func (r region) String() string {
	if r.typ.Kind != KindString {
		panic("bad string type " + r.typ.Name)
	}
	p := r.p.proc.ReadPtr(r.a)
	n := r.p.proc.ReadUintptr(r.a.Add(r.p.proc.PtrSize()))
	b := make([]byte, n)
	r.p.proc.ReadAt(b, p)
	return string(b)
}

func ( r region ) String ( ) string { if r . typ . Kind != KindString { panic ( " " + r . typ . Name ) } p := r . p . proc . ReadPtr ( r . a ) n := r . p . proc . ReadUintptr ( r . a . Add ( r . p . proc . PtrSize ( ) ) ) b := make ( [ ] byte , n ) r . p . proc . ReadAt ( b , p ) return string ( b ) }

// String returns the value of the string stored in r.

String returns the value of the string stored in r .


func (r region) SlicePtr() region {
	if r.typ.Kind != KindSlice {
		panic("can't Ptr a non-slice")
	}
	return region{p: r.p, a: r.a, typ: &Type{Name: "*" + r.typ.Name[2:], Size: r.p.proc.PtrSize(), Kind: KindPtr, Elem: r.typ.Elem}}
}

func ( r region ) SlicePtr ( ) region { if r . typ . Kind != KindSlice { panic ( " " ) } return region { p : r . p , a : r . a , typ : & Type { Name : " " + r . typ . Name [ 2 : ] , Size : r . p . proc . PtrSize ( ) , Kind : KindPtr , Elem : r . typ . Elem } } }

// SlicePtr returns the pointer inside a slice. r must contain a slice.

SlicePtr returns the pointer inside a slice . r must contain a slice .


func (r region) SliceLen() int64 {
	if r.typ.Kind != KindSlice {
		panic("can't len a non-slice")
	}
	return r.p.proc.ReadInt(r.a.Add(r.p.proc.PtrSize()))
}

func ( r region ) SliceLen ( ) int64 { if r . typ . Kind != KindSlice { panic ( " " ) } return r . p . proc . ReadInt ( r . a . Add ( r . p . proc . PtrSize ( ) ) ) }

// SliceLen returns the length of a slice. r must contain a slice.

SliceLen returns the length of a slice . r must contain a slice .


func (r region) Field(f string) region {
	finfo := r.typ.field(f)
	if finfo == nil {
		panic("can't find field " + r.typ.Name + "." + f)
	}
	return region{p: r.p, a: r.a.Add(finfo.Off), typ: finfo.Type}
}

func ( r region ) Field ( f string ) region { finfo := r . typ . field ( f ) if finfo == nil { panic ( " " + r . typ . Name + " " + f ) } return region { p : r . p , a : r . a . Add ( finfo . Off ) , typ : finfo . Type } }

// Field returns the part of r which contains the field f.
// r must contain a struct, and f must be one of its fields.

Field returns the part of r which contains the field f . r must contain a struct and f must be one of its fields .


func (p *Process) ReadUint8(a Address) uint8 {
	m := p.findMapping(a)
	if m == nil {
		panic(fmt.Errorf("address %x is not mapped in the core file", a))
	}
	return m.contents[a.Sub(m.min)]
}

func ( p * Process ) ReadUint8 ( a Address ) uint8 { m := p . findMapping ( a ) if m == nil { panic ( fmt . Errorf ( " " , a ) ) } return m . contents [ a . Sub ( m . min ) ] }

// ReadUint8 returns a uint8 read from address a of the inferior.

ReadUint8 returns a uint8 read from address a of the inferior .


func (p *Process) ReadUint16(a Address) uint16 {
	m := p.findMapping(a)
	if m == nil {
		panic(fmt.Errorf("address %x is not mapped in the core file", a))
	}
	b := m.contents[a.Sub(m.min):]
	if len(b) < 2 {
		var buf [2]byte
		b = buf[:]
		p.ReadAt(b, a)
	}
	if p.littleEndian {
		return binary.LittleEndian.Uint16(b)
	}
	return binary.BigEndian.Uint16(b)
}

func ( p * Process ) ReadUint16 ( a Address ) uint16 { m := p . findMapping ( a ) if m == nil { panic ( fmt . Errorf ( " " , a ) ) } b := m . contents [ a . Sub ( m . min ) : ] if len ( b ) < 2 { var buf [ 2 ] byte b = buf [ : ] p . ReadAt ( b , a ) } if p . littleEndian { return binary . LittleEndian . Uint16 ( b ) } return binary . BigEndian . Uint16 ( b ) }

// ReadUint16 returns a uint16 read from address a of the inferior.

ReadUint16 returns a uint16 read from address a of the inferior .


func (p *Process) ReadUint32(a Address) uint32 {
	m := p.findMapping(a)
	if m == nil {
		panic(fmt.Errorf("address %x is not mapped in the core file", a))
	}
	b := m.contents[a.Sub(m.min):]
	if len(b) < 4 {
		var buf [4]byte
		b = buf[:]
		p.ReadAt(b, a)
	}
	if p.littleEndian {
		return binary.LittleEndian.Uint32(b)
	}
	return binary.BigEndian.Uint32(b)
}

func ( p * Process ) ReadUint32 ( a Address ) uint32 { m := p . findMapping ( a ) if m == nil { panic ( fmt . Errorf ( " " , a ) ) } b := m . contents [ a . Sub ( m . min ) : ] if len ( b ) < 4 { var buf [ 4 ] byte b = buf [ : ] p . ReadAt ( b , a ) } if p . littleEndian { return binary . LittleEndian . Uint32 ( b ) } return binary . BigEndian . Uint32 ( b ) }

// ReadUint32 returns a uint32 read from address a of the inferior.

ReadUint32 returns a uint32 read from address a of the inferior .


func (p *Process) ReadUint64(a Address) uint64 {
	m := p.findMapping(a)
	if m == nil {
		panic(fmt.Errorf("address %x is not mapped in the core file", a))
	}
	b := m.contents[a.Sub(m.min):]
	if len(b) < 8 {
		var buf [8]byte
		b = buf[:]
		p.ReadAt(b, a)
	}
	if p.littleEndian {
		return binary.LittleEndian.Uint64(b)
	}
	return binary.BigEndian.Uint64(b)
}

func ( p * Process ) ReadUint64 ( a Address ) uint64 { m := p . findMapping ( a ) if m == nil { panic ( fmt . Errorf ( " " , a ) ) } b := m . contents [ a . Sub ( m . min ) : ] if len ( b ) < 8 { var buf [ 8 ] byte b = buf [ : ] p . ReadAt ( b , a ) } if p . littleEndian { return binary . LittleEndian . Uint64 ( b ) } return binary . BigEndian . Uint64 ( b ) }

// ReadUint64 returns a uint64 read from address a of the inferior.

ReadUint64 returns a uint64 read from address a of the inferior .


func (p *Process) ReadInt8(a Address) int8 {
	return int8(p.ReadUint8(a))
}

func ( p * Process ) ReadInt8 ( a Address ) int8 { return int8 ( p . ReadUint8 ( a ) ) }

// ReadInt8 returns an int8 read from address a of the inferior.

ReadInt8 returns an int8 read from address a of the inferior .


func (p *Process) ReadInt16(a Address) int16 {
	return int16(p.ReadUint16(a))
}

func ( p * Process ) ReadInt16 ( a Address ) int16 { return int16 ( p . ReadUint16 ( a ) ) }

// ReadInt16 returns an int16 read from address a of the inferior.

ReadInt16 returns an int16 read from address a of the inferior .


func (p *Process) ReadInt32(a Address) int32 {
	return int32(p.ReadUint32(a))
}

func ( p * Process ) ReadInt32 ( a Address ) int32 { return int32 ( p . ReadUint32 ( a ) ) }

// ReadInt32 returns an int32 read from address a of the inferior.

ReadInt32 returns an int32 read from address a of the inferior .


func (p *Process) ReadInt64(a Address) int64 {
	return int64(p.ReadUint64(a))
}

func ( p * Process ) ReadInt64 ( a Address ) int64 { return int64 ( p . ReadUint64 ( a ) ) }

// ReadInt64 returns an int64 read from address a of the inferior.

ReadInt64 returns an int64 read from address a of the inferior .


func (p *Process) ReadUintptr(a Address) uint64 {
	if p.ptrSize == 4 {
		return uint64(p.ReadUint32(a))
	}
	return p.ReadUint64(a)
}

func ( p * Process ) ReadUintptr ( a Address ) uint64 { if p . ptrSize == 4 { return uint64 ( p . ReadUint32 ( a ) ) } return p . ReadUint64 ( a ) }

// ReadUintptr returns a uint of pointer size read from address a of the inferior.

ReadUintptr returns a uint of pointer size read from address a of the inferior .


func (p *Process) ReadPtr(a Address) Address {
	return Address(p.ReadUintptr(a))
}

func ( p * Process ) ReadPtr ( a Address ) Address { return Address ( p . ReadUintptr ( a ) ) }

// ReadPtr returns a pointer loaded from address a of the inferior.

ReadPtr returns a pointer loaded from address a of the inferior .


func (p *Process) ReadCString(a Address) string {
	for n := int64(0); ; n++ {
		if p.ReadUint8(a.Add(n)) == 0 {
			b := make([]byte, n)
			p.ReadAt(b, a)
			return string(b)
		}
	}
}

func ( p * Process ) ReadCString ( a Address ) string { for n := int64 ( 0 ) ; ; n ++ { if p . ReadUint8 ( a . Add ( n ) ) == 0 { b := make ( [ ] byte , n ) p . ReadAt ( b , a ) return string ( b ) } } }

// ReadCString reads a null-terminated string starting at address a.

ReadCString reads a null - terminated string starting at address a .


func (m *Mapping) Source() (string, int64) {
	if m.f == nil {
		return "", 0
	}
	return m.f.Name(), m.off
}

func ( m * Mapping ) Source ( ) ( string , int64 ) { if m . f == nil { return " " , 0 } return m . f . Name ( ) , m . off }

// Source returns the backing file and offset for the mapping, or "", 0 if none.

Source returns the backing file and offset for the mapping or 0 if none .


func (p *Process) findMapping(a Address) *Mapping {
	t3 := p.pageTable[a>>52]
	if t3 == nil {
		return nil
	}
	t2 := t3[a>>42%(1<<10)]
	if t2 == nil {
		return nil
	}
	t1 := t2[a>>32%(1<<10)]
	if t1 == nil {
		return nil
	}
	t0 := t1[a>>22%(1<<10)]
	if t0 == nil {
		return nil
	}
	return t0[a>>12%(1<<10)]
}

func ( p * Process ) findMapping ( a Address ) * Mapping { t3 := p . pageTable [ a >> 52 ] if t3 == nil { return nil } t2 := t3 [ a >> 42 % ( 1 << 10 ) ] if t2 == nil { return nil } t1 := t2 [ a >> 32 % ( 1 << 10 ) ] if t1 == nil { return nil } t0 := t1 [ a >> 22 % ( 1 << 10 ) ] if t0 == nil { return nil } return t0 [ a >> 12 % ( 1 << 10 ) ] }

// findMapping is simple enough that it inlines.

findMapping is simple enough that it inlines .


func (a Address) Max(b Address) Address {
	if a > b {
		return a
	}
	return b
}

func ( a Address ) Max ( b Address ) Address { if a > b { return a } return b }


func (a Address) Min(b Address) Address {
	if a < b {
		return a
	}
	return b
}

func ( a Address ) Min ( b Address ) Address { if a < b { return a } return b }


func (a Address) Align(x int64) Address {
	return (a + Address(x) - 1) & ^(Address(x) - 1)
}

func ( a Address ) Align ( x int64 ) Address { return ( a + Address ( x ) - 1 ) & ^ ( Address ( x ) - 1 ) }

// Align rounds a up to a multiple of x.
// x must be a power of 2.

Align rounds a up to a multiple of x . x must be a power of 2 .


func (d *ltDom) initialize() {
	type workItem struct {
		name       vName
		parentName vName
	}

	// Initialize objs for mapping from object index back to Object.
	i := 0
	d.p.ForEachObject(func(x Object) bool {
		d.objs[i] = x
		i++
		return true
	})

	// Add roots to the work stack, essentially pretending to visit
	// the pseudo-root, numbering it 0.
	d.semis[pseudoRoot] = 0
	d.parents[pseudoRoot] = -1
	d.vertices[0] = pseudoRoot
	var work []workItem
	for i := 1; i < 1+d.nRoots; i++ {
		work = append(work, workItem{name: vName(i), parentName: 0})
	}

	n := vNumber(1) // 0 was the pseudo-root.

	// Build the spanning tree, assigning vertex numbers to each object
	// and initializing semi and parent.
	for len(work) != 0 {
		item := work[len(work)-1]
		work = work[:len(work)-1]

		if d.semis[item.name] != -1 {
			continue
		}

		d.semis[item.name] = n
		d.parents[item.name] = item.parentName
		d.vertices[n] = item.name
		n++

		visitChild := func(_ int64, child Object, _ int64) bool {
			childIdx, _ := d.p.findObjectIndex(d.p.Addr(child))
			work = append(work, workItem{name: vName(childIdx + d.nRoots + 1), parentName: item.name})
			return true
		}

		root, object := d.findVertexByName(item.name)
		if root != nil {
			d.p.ForEachRootPtr(root, visitChild)
		} else {
			d.p.ForEachPtr(object, visitChild)
		}

	}
}


func (d *ltDom) calculate() {
	// name -> bucket (a name), per Georgiadis.
	buckets := make([]vName, d.nVertices)
	for i := range buckets {
		buckets[i] = vName(i)
	}

	for i := vNumber(len(d.vertices)) - 1; i > 0; i-- {
		w := d.vertices[i]

		// Step 3. Implicitly define the immediate dominator of each node.
		for v := buckets[w]; v != w; v = buckets[v] {
			u := d.eval(v)
			if d.semis[u] < d.semis[v] {
				d.idom[v] = u
			} else {
				d.idom[v] = w
			}
		}

		// Step 2. Compute the semidominators of all nodes.
		root, obj := d.findVertexByName(w)
		// This loop never visits the pseudo-root.
		if root != nil {
			u := d.eval(pseudoRoot)
			if d.semis[u] < d.semis[w] {
				d.semis[w] = d.semis[u]
			}
		} else {
			d.p.ForEachReversePtr(obj, func(x Object, r *Root, _, _ int64) bool {
				var v int
				if r != nil {
					v = d.p.findRootIndex(r) + 1
				} else {
					v, _ = d.p.findObjectIndex(d.p.Addr(x))
					v += d.nRoots + 1
				}
				u := d.eval(vName(v))
				if d.semis[u] < d.semis[w] {
					d.semis[w] = d.semis[u]
				}
				return true
			})
		}

		d.link(d.parents[w], w)

		if d.parents[w] == d.vertices[d.semis[w]] {
			d.idom[w] = d.parents[w]
		} else {
			buckets[w] = buckets[d.vertices[d.semis[w]]]
			buckets[d.vertices[d.semis[w]]] = w
		}
	}

	// The final 'Step 3' is now outside the loop.
	for v := buckets[pseudoRoot]; v != pseudoRoot; v = buckets[v] {
		d.idom[v] = pseudoRoot
	}

	// Step 4. Explicitly define the immediate dominator of each
	// node, in preorder.
	for _, w := range d.vertices[1:] {
		if d.idom[w] != d.vertices[d.semis[w]] {
			d.idom[w] = d.idom[d.idom[w]]
		}
	}
}


func (d *ltDom) eval(v vName) vName {
	if d.ancestor[v] == -1 {
		return v
	}
	d.compress(v)
	return d.labels[v]
}

func ( d * ltDom ) eval ( v vName ) vName { if d . ancestor [ v ] == - 1 { return v } d . compress ( v ) return d . labels [ v ] }


func (d *ltDom) compress(v vName) {
	var stackBuf [20]vName
	stack := stackBuf[:0]
	for d.ancestor[d.ancestor[v]] != -1 {
		stack = append(stack, v)
		v = d.ancestor[v]
	}

	for len(stack) != 0 {
		v := stack[len(stack)-1]
		stack = stack[:len(stack)-1]

		if d.semis[d.labels[d.ancestor[v]]] < d.semis[d.labels[v]] {
			d.labels[v] = d.labels[d.ancestor[v]]
		}
		d.ancestor[v] = d.ancestor[d.ancestor[v]]
	}
}

func ( d * ltDom ) compress ( v vName ) { var stackBuf [ 20 ] vName stack := stackBuf [ : 0 ] for d . ancestor [ d . ancestor [ v ] ] != - 1 { stack = append ( stack , v ) v = d . ancestor [ v ] } for len ( stack ) != 0 { v := stack [ len ( stack ) - 1 ] stack = stack [ : len ( stack ) - 1 ] if d . semis [ d . labels [ d . ancestor [ v ] ] ] < d . semis [ d . labels [ v ] ] { d . labels [ v ] = d . labels [ d . ancestor [ v ] ] } d . ancestor [ v ] = d . ancestor [ d . ancestor [ v ] ] } }

// compress is COMPRESS from the papers.


func (d *ltDom) link(v, w vName) {
	d.ancestor[w] = v
}

func ( d * ltDom ) link ( v , w vName ) { d . ancestor [ w ] = v }


func (d *dominators) reverse() {
	// One inbound edge per vertex. Then we need an extra so that you can
	// always look at ridx[i+1], and another for working storage while
	// populating redge.
	cnt := make([]int, len(d.idom)+2)

	// Fill cnt[2:] with the number of outbound edges for each vertex.
	tmp := cnt[2:]
	for _, idom := range d.idom {
		tmp[idom]++
	}

	// Make tmp cumulative. After this step, cnt[1:] is what we want for
	// ridx, but the next step messes it up.
	var n int
	for idx, c := range tmp {
		n += c
		tmp[idx] = n
	}

	// Store outbound edges in redge, using cnt[1:] as the index to store
	// the next edge for each vertex. After we're done, everything's been
	// shifted over one, and cnt is ridx.
	redge := make([]vName, len(d.idom))
	tmp = cnt[1:]
	for i, idom := range d.idom {
		redge[tmp[idom]] = vName(i)
		tmp[idom]++
	}
	d.redge, d.ridx = redge, cnt[:len(cnt)-1]
}

// reverse computes and stores reverse edges for each vertex.

reverse computes and stores reverse edges for each vertex .


func (d *dominators) calcSize(p *Process) {
	d.size = make([]int64, len(d.idom))
	type workItem struct {
		v    vName
		mode dfsMode
	}
	work := []workItem{{pseudoRoot, down}}

	for len(work) > 0 {
		item := &work[len(work)-1]

		kids := d.redge[d.ridx[item.v]:d.ridx[item.v+1]]
		if item.mode == down && len(kids) != 0 {
			item.mode = up
			for _, w := range kids {
				if w == 0 {
					// bogus self-edge. Ignore.
					continue
				}
				work = append(work, workItem{w, down})
			}
			continue
		}

		work = work[:len(work)-1]

		root, obj := d.findVertexByName(item.v)
		var size int64
		switch {
		case item.v == pseudoRoot:
			break
		case root != nil:
			size += root.Type.Size
		default:
			size += p.Size(obj)
		}
		for _, w := range kids {
			size += d.size[w]
		}
		d.size[item.v] = size
	}
}

func
(
d
*
dominators
)
calcSize
(
p
*
Process
)
{
d
.
size
=
make
(
[
]
int64
,
len
(
d
.
idom
)
)
type
workItem
struct
{
v
vName
mode
dfsMode
}
work
:=
[
]
workItem
{
{
pseudoRoot
,
down
}
}
for
len
(
work
)
>
0
{
item
:=
&
work
[
len
(
work
)
1
]
kids
:=
d
.
redge
[
d
.
ridx
[
item
.
v
]
:
d
.
ridx
[
item
.
v
+
1
]
]
if
item
.
mode
==
down
&&
len
(
kids
)
!=
0
{
item
.
mode
=
up
for
_
,
w
:=
range
kids
{
if
w
==
0
{
// bogus self-edge. Ignore.
continue
}
work
=
append
(
work
,
workItem
{
w
,
down
}
)
}
continue
}
work
=
work
[
:
len
(
work
)
1
]
root
,
obj
:=
d
.
findVertexByName
(
item
.
v
)
var
size
int64
switch
{
case
item
.
v
==
pseudoRoot
:
break
case
root
!=
:
size
+=
root
.
Type
.
Size
default
:
size
+=
p
.
Size
(
obj
)
}
for
_
,
w
:=
range
kids
{
size
+=
d
.
size
[
w
]
}
d
.
size
[
item
.
v
]
=
size
}
}

// calcSize calculates the total retained size for each vertex.

calcSize calculates the total retained size for each vertex .


func objField(c *gocore.Process, x gocore.Object, off int64) string {
	t, r := c.Type(x)
	if t == nil {
		return fmt.Sprintf("f%d", off)
	}
	s := ""
	if r > 1 {
		s = fmt.Sprintf("[%d]", off/t.Size)
		off %= t.Size
	}
	return s + typeFieldName(t, off)
}

func objField ( c * gocore . Process , x gocore . Object , off int64 ) string { t , r := c . Type ( x ) if t == nil { return fmt . Sprintf ( " " , off ) } s := " " if r > 1 { s = fmt . Sprintf ( " " , off / t . Size ) off %= t . Size } return s + typeFieldName ( t , off ) }

// Returns the name of the field at offset off in x.

Returns the name of the field at offset off in x .


func (p *Process) Readable(a Address) bool {
	return p.findMapping(a) != nil
}

func ( p * Process ) Readable ( a Address ) bool { return p . findMapping ( a ) != nil }

// Readable reports whether the address a is readable.

Readable reports whether the address a is readable .


func (p *Process) ReadableN(a Address, n int64) bool {
	for {
		m := p.findMapping(a)
		if m == nil || m.perm&Read == 0 {
			return false
		}
		c := m.max.Sub(a)
		if n <= c {
			return true
		}
		n -= c
		a = a.Add(c)
	}
}

func ( p * Process ) ReadableN ( a Address , n int64 ) bool { for { m := p . findMapping ( a ) if m == nil || m . perm & Read == 0 { return false } c := m . max . Sub ( a ) if n <= c { return true } n -= c a = a . Add ( c ) } }

// ReadableN reports whether the n bytes starting at address a are readable.

ReadableN reports whether the n bytes starting at address a are readable .


func (p *Process) splitMappingsAt(a Address) {
	for _, m := range p.memory.mappings {
		if a < m.min || a > m.max {
			continue
		}
		if a == m.min || a == m.max {
			return
		}
		// Split this mapping at a.
		m2 := new(Mapping)
		*m2 = *m
		m.max = a
		m2.min = a
		if m2.f != nil {
			m2.off += m.Size()
		}
		if m2.origF != nil {
			m2.origOff += m.Size()
		}
		p.memory.mappings = append(p.memory.mappings, m2)
		return
	}
}

func
(
p
*
Process
)
splitMappingsAt
(
a
Address
)
{
for
_
,
m
:=
range
p
.
memory
.
mappings
{
if
a
<
m
.
min
||
a
>
m
.
max
{
continue
}
if
a
==
m
.
min
||
a
==
m
.
max
{
return
}
// Split this mapping at a.
m2
:=
new
(
Mapping
)
*
m2
=
*
m
m
.
max
=
a
m2
.
min
=
a
if
m2
.
f
!=
{
m2
.
off
+=
m
.
Size
(
)
}
if
m2
.
origF
!=
{
m2
.
origOff
+=
m
.
Size
(
)
}
p
.
memory
.
mappings
=
append
(
p
.
memory
.
mappings
,
m2
)
return
}
}

// splitMappingsAt ensures that a is not in the middle of any mapping.
// Splits mappings as necessary.

splitMappingsAt ensures that a is not in the middle of any mapping . Splits mappings as necessary .


func (p *Process) DynamicType(t *Type, a core.Address) *Type {
	switch t.Kind {
	default:
		panic("asking for the dynamic type of a non-interface")
	case KindEface:
		x := p.proc.ReadPtr(a)
		if x == 0 {
			return nil
		}
		return p.runtimeType2Type(x)
	case KindIface:
		x := p.proc.ReadPtr(a)
		if x == 0 {
			return nil
		}
		// Read type out of itab.
		x = p.proc.ReadPtr(x.Add(p.proc.PtrSize()))
		return p.runtimeType2Type(x)
	}
}

func
(
p
*
Process
)
DynamicType
(
t
*
Type
,
a
core
.
Address
)
*
Type
{
switch
t
.
Kind
{
default
:
panic
(
"
"
)
case
KindEface
:
x
:=
p
.
proc
.
ReadPtr
(
a
)
if
x
==
0
{
return
}
return
p
.
runtimeType2Type
(
x
)
case
KindIface
:
x
:=
p
.
proc
.
ReadPtr
(
a
)
if
x
==
0
{
return
}
// Read type out of itab.
x
=
p
.
proc
.
ReadPtr
(
x
.
Add
(
p
.
proc
.
PtrSize
(
)
)
)
return
p
.
runtimeType2Type
(
x
)
}
}

// DynamicType returns the concrete type stored in the interface type t at address a.
// If the interface is nil, returns nil.

DynamicType returns the concrete type stored in the interface type t at address a . If the interface is nil returns nil .


func (fs *BtrfsFilesystem) Create(bytes uint64) error {

	// significantly
	idempotent := exec.Command("bash", "-e", "-x", "-c", `
		if [ ! -e $IMAGE_PATH ] || [ "$(stat --printf="%s" $IMAGE_PATH)" != "$SIZE_IN_BYTES" ]; then
			touch $IMAGE_PATH
			truncate -s ${SIZE_IN_BYTES} $IMAGE_PATH
		fi

		lo="$(losetup -j $IMAGE_PATH | cut -d':' -f1)"
		if [ -z "$lo" ]; then
			lo="$(losetup -f --show $IMAGE_PATH)"
		fi

		if ! file $IMAGE_PATH | grep BTRFS; then
			`+fs.mkfsBin+` --nodiscard $IMAGE_PATH
		fi

		mkdir -p $MOUNT_PATH

		if ! mountpoint -q $MOUNT_PATH; then
			mount -t btrfs $lo $MOUNT_PATH
		fi
	`)

	idempotent.Env = []string{
		"PATH=" + os.Getenv("PATH"),
		"MOUNT_PATH=" + fs.mountPath,
		"IMAGE_PATH=" + fs.imagePath,
		fmt.Sprintf("SIZE_IN_BYTES=%d", bytes),
	}

	_, err := fs.run(idempotent)
	return err
}


func Resolve(u *url.URL) (*net.IPAddr, error) {
	host, _, err := SplitHostPort(u)
	if err != nil {
		return nil, err
	}

	addr, err := net.ResolveIPAddr("ip", host)
	if err != nil {
		return nil, err
	}

	return addr, nil
}

func Resolve ( u * url . URL ) ( * net . IPAddr , error ) { host , _ , err := SplitHostPort ( u ) if err != nil { return nil , err } addr , err := net . ResolveIPAddr ( " " , host ) if err != nil { return nil , err } return addr , nil }

// Resolve resolves the URL host to its IP address.

Resolve resolves the URL host to its IP address .


func (a *Token) Equal(b *Token) bool {
	if a == nil || b == nil {
		return false
	}
	if a.tokenType != b.tokenType {
		return false
	}
	return a.value == b.value
}

func ( a * Token ) Equal ( b * Token ) bool { if a == nil || b == nil { return false } if a . tokenType != b . tokenType { return false } return a . value == b . value }

// Equal reports whether tokens a, and b, are equal.
// Two tokens are equal if both their types and values are equal. A nil token can
// never be equal to another token.

Equal reports whether tokens a and b are equal . Two tokens are equal if both their types and values are equal . A nil token can never be equal to another token .


func newDefaultClassifier() tokenClassifier {
	t := tokenClassifier{}
	t.addRuneClass(spaceRunes, spaceRuneClass)
	t.addRuneClass(escapingQuoteRunes, escapingQuoteRuneClass)
	t.addRuneClass(nonEscapingQuoteRunes, nonEscapingQuoteRuneClass)
	t.addRuneClass(escapeRunes, escapeRuneClass)
	t.addRuneClass(commentRunes, commentRuneClass)
	return t
}

func newDefaultClassifier ( ) tokenClassifier { t := tokenClassifier { } t . addRuneClass ( spaceRunes , spaceRuneClass ) t . addRuneClass ( escapingQuoteRunes , escapingQuoteRuneClass ) t . addRuneClass ( nonEscapingQuoteRunes , nonEscapingQuoteRuneClass ) t . addRuneClass ( escapeRunes , escapeRuneClass ) t . addRuneClass ( commentRunes , commentRuneClass ) return t }

// newDefaultClassifier creates a new classifier for ASCII characters.

newDefaultClassifier creates a new classifier for ASCII characters .


func (l *Lexer) Next() (string, error) {
	for {
		token, err := (*Tokenizer)(l).Next()
		if err != nil {
			return "", err
		}
		switch token.tokenType {
		case WordToken:
			return token.value, nil
		case CommentToken:
			// skip comments
		default:
			return "", fmt.Errorf("Unknown token type: %v", token.tokenType)
		}
	}
}

func
(
l
*
Lexer
)
Next
(
)
(
string
,
error
)
{
for
{
token
,
err
:=
(
*
Tokenizer
)
(
l
)
.
Next
(
)
if
err
!=
{
return
"
"
,
err
}
switch
token
.
tokenType
{
case
WordToken
:
return
token
.
value
,
case
CommentToken
:
// skip comments
default
:
return
"
"
,
fmt
.
Errorf
(
"
"
,
token
.
tokenType
)
}
}
}

// Next returns the next word, or an error. If there are no more words,
// the error will be io.EOF.

Next returns the next word or an error . If there are no more words the error will be io . EOF .


func NewTokenizer(r io.Reader) *Tokenizer {
	input := bufio.NewReader(r)
	classifier := newDefaultClassifier()
	return &Tokenizer{
		input:      *input,
		classifier: classifier}
}

func NewTokenizer ( r io . Reader ) * Tokenizer { input := bufio . NewReader ( r ) classifier := newDefaultClassifier ( ) return & Tokenizer { input : * input , classifier : classifier } }

// NewTokenizer creates a new tokenizer from an input stream.

NewTokenizer creates a new tokenizer from an input stream .


func Split(s string) ([]string, error) {
	l := NewLexer(strings.NewReader(s))
	subStrings := make([]string, 0)
	for {
		word, err := l.Next()
		if err != nil {
			if err == io.EOF {
				return subStrings, nil
			}
			return subStrings, err
		}
		subStrings = append(subStrings, word)
	}
}

func Split ( s string ) ( [ ] string , error ) { l := NewLexer ( strings . NewReader ( s ) ) subStrings := make ( [ ] string , 0 ) for { word , err := l . Next ( ) if err != nil { if err == io . EOF { return subStrings , nil } return subStrings , err } subStrings = append ( subStrings , word ) } }

// Split partitions a string into a slice of strings.

Split partitions a string into a slice of strings .


func Between(s, left, right string) string {
	l := len(left)
	startPos := strings.Index(s, left)
	if startPos < 0 {
		return ""
	}
	endPos := IndexOf(s, right, startPos+l)
	//log.Printf("%s: left %s right %s start %d end %d", s, left, right, startPos+l, endPos)
	if endPos < 0 {
		return ""
	} else if right == "" {
		return s[endPos:]
	} else {
		return s[startPos+l : endPos]
	}
}

// Between extracts a string between left and right strings.

Between extracts a string between left and right strings .


func BetweenF(left, right string) func(string) string {
	return func(s string) string {
		return Between(s, left, right)
	}
}

func BetweenF ( left , right string ) func ( string ) string { return func ( s string ) string { return Between ( s , left , right ) } }

// BetweenF is the filter form for Between.

BetweenF is the filter form for Between .


func Camelize(s string) string {
	return camelizeRe.ReplaceAllStringFunc(s, func(val string) string {
		val = strings.ToUpper(val)
		val = camelizeRe2.ReplaceAllString(val, "")
		return val
	})
}

func Camelize ( s string ) string { return camelizeRe . ReplaceAllStringFunc ( s , func ( val string ) string { val = strings . ToUpper ( val ) val = camelizeRe2 . ReplaceAllString ( val , " " ) return val } ) }

// Camelize return new string which removes any underscores or dashes and convert a string into camel casing.

Camelize return new string which removes any underscores or dashes and convert a string into camel casing .


func Capitalize(s string) string {
	return strings.ToUpper(s[0:1]) + strings.ToLower(s[1:])
}

func Capitalize ( s string ) string { return strings . ToUpper ( s [ 0 : 1 ] ) + strings . ToLower ( s [ 1 : ] ) }

// Capitalize uppercases the first char of s and lowercases the rest.

Capitalize uppercases the first char of s and lowercases the rest .


func CharAt(s string, index int) string {
	l := len(s)
	shortcut := index < 0 || index > l-1 || l == 0
	if shortcut {
		return ""
	}
	return s[index : index+1]
}

func CharAt ( s string , index int ) string { l := len ( s ) shortcut := index < 0 || index > l - 1 || l == 0 if shortcut { return " " } return s [ index : index + 1 ] }

// CharAt returns a string from the character at the specified position.

CharAt returns a string from the character at the specified position .


func CharAtF(index int) func(string) string {
	return func(s string) string {
		return CharAt(s, index)
	}
}

func CharAtF ( index int ) func ( string ) string { return func ( s string ) string { return CharAt ( s , index ) } }

// CharAtF is the filter form of CharAt.


func ChompLeft(s, prefix string) string {
	if strings.HasPrefix(s, prefix) {
		return s[len(prefix):]
	}
	return s
}

func ChompLeft ( s , prefix string ) string { if strings . HasPrefix ( s , prefix ) { return s [ len ( prefix ) : ] } return s }

// ChompLeft removes prefix at the start of a string.

ChompLeft removes prefix at the start of a string .


func ChompLeftF(prefix string) func(string) string {
	return func(s string) string {
		return ChompLeft(s, prefix)
	}
}

func ChompLeftF ( prefix string ) func ( string ) string { return func ( s string ) string { return ChompLeft ( s , prefix ) } }

// ChompLeftF is the filter form of ChompLeft.

ChompLeftF is the filter form of ChompLeft .


func ChompRight(s, suffix string) string {
	if strings.HasSuffix(s, suffix) {
		return s[:len(s)-len(suffix)]
	}
	return s
}

func ChompRight ( s , suffix string ) string { if strings . HasSuffix ( s , suffix ) { return s [ : len ( s ) - len ( suffix ) ] } return s }

// ChompRight removes suffix from end of s.

ChompRight removes suffix from end of s .


func ChompRightF(suffix string) func(string) string {
	return func(s string) string {
		return ChompRight(s, suffix)
	}
}

func ChompRightF ( suffix string ) func ( string ) string { return func ( s string ) string { return ChompRight ( s , suffix ) } }

// ChompRightF is the filter form of ChompRight.

ChompRightF is the filter form of ChompRight .


func ClassifyF(s string) func(string) string {
	return func(s string) string {
		return Classify(s)
	}
}

func ClassifyF ( s string ) func ( string ) string { return func ( s string ) string { return Classify ( s ) } }

// ClassifyF is the filter form of Classify.

ClassifyF is the filter form of Classify .


func Clean(s string) string {
	s = spacesRe.ReplaceAllString(s, " ")
	s = beginEndSpacesRe.ReplaceAllString(s, "")
	return s
}

func Clean ( s string ) string { s = spacesRe . ReplaceAllString ( s , " " ) s = beginEndSpacesRe . ReplaceAllString ( s , " " ) return s }

// Clean compresses all adjacent whitespace to a single space and trims s.

Clean compresses all adjacent whitespace to a single space and trims s .


func Dasherize(s string) string {
	s = strings.TrimSpace(s)
	s = spaceUnderscoreRe.ReplaceAllString(s, "-")
	s = capitalsRe.ReplaceAllString(s, "-$1")
	s = dashesRe.ReplaceAllString(s, "-")
	s = strings.ToLower(s)
	return s
}

func Dasherize ( s string ) string { s = strings . TrimSpace ( s ) s = spaceUnderscoreRe . ReplaceAllString ( s , " " ) s = capitalsRe . ReplaceAllString ( s , " " ) s = dashesRe . ReplaceAllString ( s , " " ) s = strings . ToLower ( s ) return s }

// Dasherize  converts a camel cased string into a string delimited by dashes.

Dasherize converts a camel cased string into a string delimited by dashes .


func EscapeHTML(s string) string {
	if Verbose {
		fmt.Println("Use html.EscapeString instead of EscapeHTML")
	}
	return html.EscapeString(s)
}

func EscapeHTML ( s string ) string { if Verbose { fmt . Println ( " " ) } return html . EscapeString ( s ) }

// EscapeHTML is alias for html.EscapeString.

EscapeHTML is alias for html . EscapeString .


func DecodeHTMLEntities(s string) string {
	if Verbose {
		fmt.Println("Use html.UnescapeString instead of DecodeHTMLEntities")
	}
	return html.UnescapeString(s)
}

func DecodeHTMLEntities ( s string ) string { if Verbose { fmt . Println ( " " ) } return html . UnescapeString ( s ) }

// DecodeHTMLEntities decodes HTML entities into their proper string representation.
// DecodeHTMLEntities is an alias for html.UnescapeString

DecodeHTMLEntities decodes HTML entities into their proper string representation . DecodeHTMLEntities is an alias for html . UnescapeString


func EnsurePrefixF(prefix string) func(string) string {
	return func(s string) string {
		return EnsurePrefix(s, prefix)
	}
}

func EnsurePrefixF ( prefix string ) func ( string ) string { return func ( s string ) string { return EnsurePrefix ( s , prefix ) } }

// EnsurePrefixF is the filter form of EnsurePrefix.

EnsurePrefixF is the filter form of EnsurePrefix .


func EnsureSuffixF(suffix string) func(string) string {
	return func(s string) string {
		return EnsureSuffix(s, suffix)
	}
}

func EnsureSuffixF ( suffix string ) func ( string ) string { return func ( s string ) string { return EnsureSuffix ( s , suffix ) } }

// EnsureSuffixF is the filter form of EnsureSuffix.

EnsureSuffixF is the filter form of EnsureSuffix .