/*
 * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package spew

import (
	
	
	
	
	
	
)

// Some constants in the form of bytes to avoid string overhead.  This mirrors
// the technique used in the fmt package.
var (
	panicBytes            = []byte("(PANIC=")
	plusBytes             = []byte("+")
	iBytes                = []byte("i")
	trueBytes             = []byte("true")
	falseBytes            = []byte("false")
	interfaceBytes        = []byte("(interface {})")
	commaNewlineBytes     = []byte(",\n")
	newlineBytes          = []byte("\n")
	openBraceBytes        = []byte("{")
	openBraceNewlineBytes = []byte("{\n")
	closeBraceBytes       = []byte("}")
	asteriskBytes         = []byte("*")
	colonBytes            = []byte(":")
	colonSpaceBytes       = []byte(": ")
	openParenBytes        = []byte("(")
	closeParenBytes       = []byte(")")
	spaceBytes            = []byte(" ")
	pointerChainBytes     = []byte("->")
	nilAngleBytes         = []byte("<nil>")
	maxNewlineBytes       = []byte("<max depth reached>\n")
	maxShortBytes         = []byte("<max>")
	circularBytes         = []byte("<already shown>")
	circularShortBytes    = []byte("<shown>")
	invalidAngleBytes     = []byte("<invalid>")
	openBracketBytes      = []byte("[")
	closeBracketBytes     = []byte("]")
	percentBytes          = []byte("%")
	precisionBytes        = []byte(".")
	openAngleBytes        = []byte("<")
	closeAngleBytes       = []byte(">")
	openMapBytes          = []byte("map[")
	closeMapBytes         = []byte("]")
	lenEqualsBytes        = []byte("len=")
	capEqualsBytes        = []byte("cap=")
)

// hexDigits is used to map a decimal value to a hex digit.
var hexDigits = "0123456789abcdef"

// catchPanic handles any panics that might occur during the handleMethods
// calls.
func catchPanic( io.Writer,  reflect.Value) {
	if  := recover();  != nil {
		.Write(panicBytes)
		fmt.Fprintf(, "%v", )
		.Write(closeParenBytes)
	}
}

// handleMethods attempts to call the Error and String methods on the underlying
// type the passed reflect.Value represents and outputes the result to Writer w.
//
// It handles panics in any called methods by catching and displaying the error
// as the formatted value.
func handleMethods( *ConfigState,  io.Writer,  reflect.Value) ( bool) {
	// We need an interface to check if the type implements the error or
	// Stringer interface.  However, the reflect package won't give us an
	// interface on certain things like unexported struct fields in order
	// to enforce visibility rules.  We use unsafe, when it's available,
	// to bypass these restrictions since this package does not mutate the
	// values.
	if !.CanInterface() {
		if UnsafeDisabled {
			return false
		}

		 = unsafeReflectValue()
	}

	// Choose whether or not to do error and Stringer interface lookups against
	// the base type or a pointer to the base type depending on settings.
	// Technically calling one of these methods with a pointer receiver can
	// mutate the value, however, types which choose to satisify an error or
	// Stringer interface with a pointer receiver should not be mutating their
	// state inside these interface methods.
	if !.DisablePointerMethods && !UnsafeDisabled && !.CanAddr() {
		 = unsafeReflectValue()
	}
	if .CanAddr() {
		 = .Addr()
	}

	// Is it an error or Stringer?
	switch iface := .Interface().(type) {
	case error:
		defer catchPanic(, )
		if .ContinueOnMethod {
			.Write(openParenBytes)
			.Write([]byte(.Error()))
			.Write(closeParenBytes)
			.Write(spaceBytes)
			return false
		}

		.Write([]byte(.Error()))
		return true

	case fmt.Stringer:
		defer catchPanic(, )
		if .ContinueOnMethod {
			.Write(openParenBytes)
			.Write([]byte(.String()))
			.Write(closeParenBytes)
			.Write(spaceBytes)
			return false
		}
		.Write([]byte(.String()))
		return true
	}
	return false
}

// printBool outputs a boolean value as true or false to Writer w.
func printBool( io.Writer,  bool) {
	if  {
		.Write(trueBytes)
	} else {
		.Write(falseBytes)
	}
}

// printInt outputs a signed integer value to Writer w.
func printInt( io.Writer,  int64,  int) {
	.Write([]byte(strconv.FormatInt(, )))
}

// printUint outputs an unsigned integer value to Writer w.
func printUint( io.Writer,  uint64,  int) {
	.Write([]byte(strconv.FormatUint(, )))
}

// printFloat outputs a floating point value using the specified precision,
// which is expected to be 32 or 64bit, to Writer w.
func printFloat( io.Writer,  float64,  int) {
	.Write([]byte(strconv.FormatFloat(, 'g', -1, )))
}

// printComplex outputs a complex value using the specified float precision
// for the real and imaginary parts to Writer w.
func printComplex( io.Writer,  complex128,  int) {
	 := real()
	.Write(openParenBytes)
	.Write([]byte(strconv.FormatFloat(, 'g', -1, )))
	 := imag()
	if  >= 0 {
		.Write(plusBytes)
	}
	.Write([]byte(strconv.FormatFloat(, 'g', -1, )))
	.Write(iBytes)
	.Write(closeParenBytes)
}

// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
// prefix to Writer w.
func printHexPtr( io.Writer,  uintptr) {
	// Null pointer.
	 := uint64()
	if  == 0 {
		.Write(nilAngleBytes)
		return
	}

	// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
	 := make([]byte, 18)

	// It's simpler to construct the hex string right to left.
	 := uint64(16)
	 := len() - 1
	for  >=  {
		[] = hexDigits[%]
		 /= 
		--
	}
	[] = hexDigits[]

	// Add '0x' prefix.
	--
	[] = 'x'
	--
	[] = '0'

	// Strip unused leading bytes.
	 = [:]
	.Write()
}

// valuesSorter implements sort.Interface to allow a slice of reflect.Value
// elements to be sorted.
type valuesSorter struct {
	values  []reflect.Value
	strings []string // either nil or same len and values
	cs      *ConfigState
}

// newValuesSorter initializes a valuesSorter instance, which holds a set of
// surrogate keys on which the data should be sorted.  It uses flags in
// ConfigState to decide if and how to populate those surrogate keys.
func newValuesSorter( []reflect.Value,  *ConfigState) sort.Interface {
	 := &valuesSorter{values: , cs: }
	if canSortSimply(.values[0].Kind()) {
		return 
	}
	if !.DisableMethods {
		.strings = make([]string, len())
		for  := range .values {
			 := bytes.Buffer{}
			if !handleMethods(, &, .values[]) {
				.strings = nil
				break
			}
			.strings[] = .String()
		}
	}
	if .strings == nil && .SpewKeys {
		.strings = make([]string, len())
		for  := range .values {
			.strings[] = Sprintf("%#v", .values[].Interface())
		}
	}
	return 
}

// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
// directly, or whether it should be considered for sorting by surrogate keys
// (if the ConfigState allows it).
func canSortSimply( reflect.Kind) bool {
	// This switch parallels valueSortLess, except for the default case.
	switch  {
	case reflect.Bool:
		return true
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
		return true
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
		return true
	case reflect.Float32, reflect.Float64:
		return true
	case reflect.String:
		return true
	case reflect.Uintptr:
		return true
	case reflect.Array:
		return true
	}
	return false
}

// Len returns the number of values in the slice.  It is part of the
// sort.Interface implementation.
func ( *valuesSorter) () int {
	return len(.values)
}

// Swap swaps the values at the passed indices.  It is part of the
// sort.Interface implementation.
func ( *valuesSorter) (,  int) {
	.values[], .values[] = .values[], .values[]
	if .strings != nil {
		.strings[], .strings[] = .strings[], .strings[]
	}
}

// valueSortLess returns whether the first value should sort before the second
// value.  It is used by valueSorter.Less as part of the sort.Interface
// implementation.
func valueSortLess(,  reflect.Value) bool {
	switch .Kind() {
	case reflect.Bool:
		return !.Bool() && .Bool()
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
		return .Int() < .Int()
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
		return .Uint() < .Uint()
	case reflect.Float32, reflect.Float64:
		return .Float() < .Float()
	case reflect.String:
		return .String() < .String()
	case reflect.Uintptr:
		return .Uint() < .Uint()
	case reflect.Array:
		// Compare the contents of both arrays.
		 := .Len()
		for  := 0;  < ; ++ {
			 := .Index()
			 := .Index()
			if .Interface() == .Interface() {
				continue
			}
			return (, )
		}
	}
	return .String() < .String()
}

// Less returns whether the value at index i should sort before the
// value at index j.  It is part of the sort.Interface implementation.
func ( *valuesSorter) (,  int) bool {
	if .strings == nil {
		return valueSortLess(.values[], .values[])
	}
	return .strings[] < .strings[]
}

// sortValues is a sort function that handles both native types and any type that
// can be converted to error or Stringer.  Other inputs are sorted according to
// their Value.String() value to ensure display stability.
func sortValues( []reflect.Value,  *ConfigState) {
	if len() == 0 {
		return
	}
	sort.Sort(newValuesSorter(, ))
}