github.com/goplus/igop@v0.25.0/print.go (about) 1 /* 2 * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package igop 18 19 import ( 20 "bytes" 21 "fmt" 22 "reflect" 23 "unsafe" 24 ) 25 26 // writevalue for write argument pass to print 27 func writevalue(buf *bytes.Buffer, v interface{}, enableAny bool) { 28 switch v := v.(type) { 29 case float64: 30 writefloat(buf, v) 31 case float32: 32 writefloat(buf, float64(v)) 33 case complex128: 34 writecomplex(buf, v) 35 case complex64: 36 writecomplex(buf, complex128(v)) 37 case nil, bool, int, int8, int16, int32, int64, 38 uint, uint8, uint16, uint32, uint64, uintptr, 39 string: 40 fmt.Fprintf(buf, "%v", v) 41 default: 42 i := reflect.ValueOf(v) 43 switch i.Kind() { 44 case reflect.Float32, reflect.Float64: 45 writefloat(buf, i.Float()) 46 case reflect.Complex64, reflect.Complex128: 47 writecomplex(buf, i.Complex()) 48 case reflect.Map, reflect.Ptr, reflect.Func, reflect.Chan, reflect.UnsafePointer: 49 fmt.Fprintf(buf, "%p", v) 50 case reflect.Slice: 51 fmt.Fprintf(buf, "[%v/%v]%p", i.Len(), i.Cap(), v) 52 case reflect.String: 53 fmt.Fprintf(buf, "%v", v) 54 case reflect.Interface: 55 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 56 fmt.Fprintf(buf, "(%p,%p)", eface.typ, eface.word) 57 case reflect.Struct, reflect.Array: 58 if enableAny { 59 fmt.Fprintf(buf, "%v", v) 60 } else { 61 panic(fmt.Sprintf("illegal types for operand: print\n\t%T", v)) 62 } 63 default: 64 fmt.Fprintf(buf, "%v", v) 65 } 66 } 67 } 68 69 // emptyInterface is the header for an interface{} value. 70 type emptyInterface struct { 71 typ unsafe.Pointer 72 word unsafe.Pointer 73 } 74 75 func writeinterface(out *bytes.Buffer, i interface{}) { 76 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 77 fmt.Fprintf(out, "(%p,%p)", eface.typ, eface.word) 78 } 79 80 func writecomplex(out *bytes.Buffer, c complex128) { 81 out.WriteByte('(') 82 writefloat(out, real(c)) 83 writefloat(out, imag(c)) 84 out.WriteString("i)") 85 } 86 87 func writefloat(out *bytes.Buffer, v float64) { 88 switch { 89 case v != v: 90 out.WriteString("NaN") 91 return 92 case v+v == v && v > 0: 93 out.WriteString("+Inf") 94 return 95 case v+v == v && v < 0: 96 out.WriteString("-Inf") 97 return 98 } 99 100 const n = 7 // digits printed 101 var buf [n + 7]byte 102 buf[0] = '+' 103 e := 0 // exp 104 if v == 0 { 105 if 1/v < 0 { 106 buf[0] = '-' 107 } 108 } else { 109 if v < 0 { 110 v = -v 111 buf[0] = '-' 112 } 113 114 // normalize 115 for v >= 10 { 116 e++ 117 v /= 10 118 } 119 for v < 1 { 120 e-- 121 v *= 10 122 } 123 124 // round 125 h := 5.0 126 for i := 0; i < n; i++ { 127 h /= 10 128 } 129 v += h 130 if v >= 10 { 131 e++ 132 v /= 10 133 } 134 } 135 136 // format +d.dddd+edd 137 for i := 0; i < n; i++ { 138 s := int(v) 139 buf[i+2] = byte(s + '0') 140 v -= float64(s) 141 v *= 10 142 } 143 buf[1] = buf[2] 144 buf[2] = '.' 145 146 buf[n+2] = 'e' 147 buf[n+3] = '+' 148 if e < 0 { 149 e = -e 150 buf[n+3] = '-' 151 } 152 153 buf[n+4] = byte(e/100) + '0' 154 buf[n+5] = byte(e/10)%10 + '0' 155 buf[n+6] = byte(e%10) + '0' 156 out.Write(buf[:]) 157 } 158 159 // writeany for write argument pass to panic 160 func writeany(buf *bytes.Buffer, v interface{}) { 161 switch v := v.(type) { 162 case nil, bool, int, int8, int16, int32, int64, 163 float32, float64, complex64, complex128, 164 uint, uint8, uint16, uint32, uint64, uintptr, 165 string: 166 writevalue(buf, v, true) 167 case error: 168 fmt.Fprintf(buf, "%v", v) 169 default: 170 i := reflect.ValueOf(v) 171 typ := i.Type() 172 switch i.Kind() { 173 case reflect.String: 174 fmt.Fprintf(buf, "%v(%q)", typ, i) 175 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 176 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 177 fmt.Fprintf(buf, "%v(%v)", typ, i) 178 case reflect.Float32, reflect.Float64: 179 buf.WriteString(typ.String()) 180 buf.WriteByte('(') 181 writefloat(buf, i.Float()) 182 buf.WriteByte(')') 183 case reflect.Complex64, reflect.Complex128: 184 buf.WriteString(typ.String()) 185 buf.WriteByte('(') 186 writecomplex(buf, i.Complex()) 187 buf.WriteByte(')') 188 default: 189 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 190 fmt.Fprintf(buf, "(%v) %p", typ, eface.word) 191 } 192 } 193 }