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 }