github.com/goplus/gossa@v0.3.25/print.go (about)

     1  package gossa
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"unsafe"
     8  )
     9  
    10  //  writevalue for write argument pass to print
    11  func writevalue(buf *bytes.Buffer, v interface{}, enableAny bool) {
    12  	switch v := v.(type) {
    13  	case float64:
    14  		writefloat(buf, v)
    15  	case float32:
    16  		writefloat(buf, float64(v))
    17  	case complex128:
    18  		writecomplex(buf, v)
    19  	case complex64:
    20  		writecomplex(buf, complex128(v))
    21  	case nil, bool, int, int8, int16, int32, int64,
    22  		uint, uint8, uint16, uint32, uint64, uintptr,
    23  		string:
    24  		fmt.Fprintf(buf, "%v", v)
    25  	default:
    26  		i := reflect.ValueOf(v)
    27  		switch i.Kind() {
    28  		case reflect.Float32, reflect.Float64:
    29  			writefloat(buf, i.Float())
    30  		case reflect.Complex64, reflect.Complex128:
    31  			writecomplex(buf, i.Complex())
    32  		case reflect.Map, reflect.Ptr, reflect.Func, reflect.Chan, reflect.UnsafePointer:
    33  			fmt.Fprintf(buf, "%p", v)
    34  		case reflect.Slice:
    35  			fmt.Fprintf(buf, "[%v/%v]%p", i.Len(), i.Cap(), v)
    36  		case reflect.String:
    37  			fmt.Fprintf(buf, "%v", v)
    38  		case reflect.Interface:
    39  			eface := *(*emptyInterface)(unsafe.Pointer(&i))
    40  			fmt.Fprintf(buf, "(%p,%p)", eface.typ, eface.word)
    41  		case reflect.Struct, reflect.Array:
    42  			if enableAny {
    43  				fmt.Fprintf(buf, "%v", v)
    44  			} else {
    45  				panic(fmt.Sprintf("illegal types for operand: print\n\t%T", v))
    46  			}
    47  		default:
    48  			fmt.Fprintf(buf, "%v", v)
    49  		}
    50  	}
    51  }
    52  
    53  // emptyInterface is the header for an interface{} value.
    54  type emptyInterface struct {
    55  	typ  unsafe.Pointer
    56  	word unsafe.Pointer
    57  }
    58  
    59  func writeinterface(out *bytes.Buffer, i interface{}) {
    60  	eface := *(*emptyInterface)(unsafe.Pointer(&i))
    61  	fmt.Fprintf(out, "(%p,%p)", eface.typ, eface.word)
    62  }
    63  
    64  func writecomplex(out *bytes.Buffer, c complex128) {
    65  	out.WriteByte('(')
    66  	writefloat(out, real(c))
    67  	writefloat(out, imag(c))
    68  	out.WriteString("i)")
    69  }
    70  
    71  func writefloat(out *bytes.Buffer, v float64) {
    72  	switch {
    73  	case v != v:
    74  		out.WriteString("NaN")
    75  		return
    76  	case v+v == v && v > 0:
    77  		out.WriteString("+Inf")
    78  		return
    79  	case v+v == v && v < 0:
    80  		out.WriteString("-Inf")
    81  		return
    82  	}
    83  
    84  	const n = 7 // digits printed
    85  	var buf [n + 7]byte
    86  	buf[0] = '+'
    87  	e := 0 // exp
    88  	if v == 0 {
    89  		if 1/v < 0 {
    90  			buf[0] = '-'
    91  		}
    92  	} else {
    93  		if v < 0 {
    94  			v = -v
    95  			buf[0] = '-'
    96  		}
    97  
    98  		// normalize
    99  		for v >= 10 {
   100  			e++
   101  			v /= 10
   102  		}
   103  		for v < 1 {
   104  			e--
   105  			v *= 10
   106  		}
   107  
   108  		// round
   109  		h := 5.0
   110  		for i := 0; i < n; i++ {
   111  			h /= 10
   112  		}
   113  		v += h
   114  		if v >= 10 {
   115  			e++
   116  			v /= 10
   117  		}
   118  	}
   119  
   120  	// format +d.dddd+edd
   121  	for i := 0; i < n; i++ {
   122  		s := int(v)
   123  		buf[i+2] = byte(s + '0')
   124  		v -= float64(s)
   125  		v *= 10
   126  	}
   127  	buf[1] = buf[2]
   128  	buf[2] = '.'
   129  
   130  	buf[n+2] = 'e'
   131  	buf[n+3] = '+'
   132  	if e < 0 {
   133  		e = -e
   134  		buf[n+3] = '-'
   135  	}
   136  
   137  	buf[n+4] = byte(e/100) + '0'
   138  	buf[n+5] = byte(e/10)%10 + '0'
   139  	buf[n+6] = byte(e%10) + '0'
   140  	out.Write(buf[:])
   141  }
   142  
   143  // writeany for write argument pass to panic
   144  func writeany(buf *bytes.Buffer, v interface{}) {
   145  	switch v := v.(type) {
   146  	case nil, bool, int, int8, int16, int32, int64,
   147  		float32, float64, complex64, complex128,
   148  		uint, uint8, uint16, uint32, uint64, uintptr,
   149  		string:
   150  		writevalue(buf, v, true)
   151  	case error:
   152  		fmt.Fprintf(buf, "%v", v)
   153  	default:
   154  		i := reflect.ValueOf(v)
   155  		typ := i.Type()
   156  		switch i.Kind() {
   157  		case reflect.String:
   158  			fmt.Fprintf(buf, "%v(%q)", typ, i)
   159  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   160  			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   161  			fmt.Fprintf(buf, "%v(%v)", typ, i)
   162  		case reflect.Float32, reflect.Float64:
   163  			buf.WriteString(typ.String())
   164  			buf.WriteByte('(')
   165  			writefloat(buf, i.Float())
   166  			buf.WriteByte(')')
   167  		case reflect.Complex64, reflect.Complex128:
   168  			buf.WriteString(typ.String())
   169  			buf.WriteByte('(')
   170  			writecomplex(buf, i.Complex())
   171  			buf.WriteByte(')')
   172  		default:
   173  			eface := *(*emptyInterface)(unsafe.Pointer(&i))
   174  			fmt.Fprintf(buf, "(%v) %p", typ, eface.word)
   175  		}
   176  	}
   177  }