github.com/nikandfor/hacked@v0.0.0-20231207014854-3b383967fdf4/hfmt/low.go (about) 1 package hfmt 2 3 import ( 4 "fmt" 5 "io" 6 "reflect" 7 "strconv" 8 "unsafe" 9 ) 10 11 //nolint 12 type ( 13 iface struct { 14 typ, word unsafe.Pointer 15 } 16 17 // pp is used to store a printer's state and is reused with sync.Pool to avoid allocations. 18 pp struct { 19 buf []byte 20 21 // arg holds the current item, as an interface{}. 22 arg interface{} 23 24 // value is used instead of arg for reflect values. 25 value reflect.Value 26 27 // fmt is used to format basic items such as integers or strings. 28 fmt fmtt 29 30 // reordered records whether the format string used argument reordering. 31 reordered bool 32 // goodArgNum records whether the most recent reordering directive was valid. 33 goodArgNum bool 34 // panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion. 35 panicking bool 36 // erroring is set when printing an error string to guard against calling handleMethods. 37 erroring bool 38 // wrapErrs is set when the format string may contain a %w verb. 39 wrapErrs bool 40 // wrappedErr records the target of the %w verb. 41 wrappedErr error 42 } 43 44 // A fmt is the raw formatter used by Printf etc. 45 // It prints into a buffer that must be set up separately. 46 fmtt struct { 47 buf *[]byte 48 49 fmtFlags 50 51 wid int // width 52 prec int // precision 53 54 // intbuf is large enough to store %b of an int64 with a sign and 55 // avoids padding at the end of the struct on 32 bit architectures. 56 intbuf [68]byte 57 } 58 59 // flags placed in a separate struct for easy clearing. 60 fmtFlags struct { 61 widPresent bool 62 precPresent bool 63 minus bool 64 plus bool 65 sharp bool 66 space bool 67 zero bool 68 69 // For the formats %+v %#v, we set the plusV/sharpV flags 70 // and clear the plus/sharp flags since %+v and %#v are in effect 71 // different, flagless formats set at the top level. 72 plusV bool 73 sharpV bool 74 } 75 76 formatter struct{} 77 ) 78 79 var ppType unsafe.Pointer 80 81 func init() { 82 fmt.Fprintf(io.Discard, "%v", formatter{}) 83 } 84 85 // Appendf is similar to fmt.Fprintf but a little bit hacked. 86 // 87 // There is no sync.Pool.Get and Put. There is no copying buffer to io.Writer or conversion to string. There is no io.Writer interface dereference. 88 // All that gives advantage about 30-50 ns per call. Yes, I know :). 89 func Appendf(b []byte, format string, a ...interface{}) []byte { 90 var p pp 91 p.buf = b 92 p.fmt.buf = &p.buf 93 doPrintf(&p, format, a) 94 b = *(*[]byte)(noescape(unsafe.Pointer(&p.buf))) 95 return b 96 } 97 98 // Appendln is similar to fmt.Sprintln but faster. See doc for Appendf for more details. 99 func Appendln(b []byte, a ...interface{}) []byte { 100 var p pp 101 p.buf = b 102 p.fmt.buf = &p.buf 103 doPrintln(&p, a) 104 b = *(*[]byte)(noescape(unsafe.Pointer(&p.buf))) 105 return b 106 } 107 108 // Append is similar to fmt.Sprint but faster. See doc for Appendf for more details. 109 func Append(b []byte, a ...interface{}) []byte { 110 var p pp 111 p.buf = b 112 p.fmt.buf = &p.buf 113 doPrint(&p, a) 114 b = *(*[]byte)(noescape(unsafe.Pointer(&p.buf))) 115 return b 116 } 117 118 func PrintArg(s fmt.State, arg interface{}, verb rune) { 119 i := *(*iface)(unsafe.Pointer(&s)) 120 if i.typ != ppType { 121 var buf [64]byte 122 123 i := 0 124 125 buf[i] = '%' 126 i++ 127 128 for _, f := range "-+# 0" { 129 if s.Flag(int(f)) { 130 buf[i] = byte(f) 131 i++ 132 } 133 } 134 135 if w, ok := s.Width(); ok { 136 q := strconv.AppendInt(buf[:i], int64(w), 10) 137 i = len(q) 138 } 139 140 if p, ok := s.Precision(); ok { 141 buf[i] = '.' 142 i++ 143 144 q := strconv.AppendInt(buf[:i], int64(p), 10) 145 i = len(q) 146 } 147 148 buf[i] = byte(verb) 149 i++ 150 151 fmt.Fprintf(s, bytesToString(buf[:i]), arg) 152 153 return 154 } 155 156 printArg(i.word, arg, verb) 157 } 158 159 //go:linkname doPrintf fmt.(*pp).doPrintf 160 //go:noescape 161 func doPrintf(p *pp, format string, a []interface{}) 162 163 //go:linkname doPrintln fmt.(*pp).doPrintln 164 //go:noescape 165 func doPrintln(p *pp, a []interface{}) 166 167 //go:linkname doPrint fmt.(*pp).doPrint 168 //go:noescape 169 func doPrint(p *pp, a []interface{}) 170 171 //go:linkname newPrinter fmt.newPrinter 172 //go:noescape 173 func newPrinter() unsafe.Pointer 174 175 //go:linkname ppFree fmt.(*pp).free 176 //go:noescape 177 func ppFree(unsafe.Pointer) 178 179 //go:linkname printArg fmt.(*pp).printArg 180 //go:noescape 181 func printArg(p unsafe.Pointer, arg interface{}, verb rune) 182 183 func (formatter) Format(s fmt.State, c rune) { 184 i := *(*iface)(unsafe.Pointer(&s)) 185 186 ppType = i.typ 187 } 188 189 // noescape hides a pointer from escape analysis. noescape is 190 // the identity function but escape analysis doesn't think the 191 // output depends on the input. noescape is inlined and currently 192 // compiles down to zero instructions. 193 // USE CAREFULLY! 194 //go:nosplit 195 func noescape(p unsafe.Pointer) unsafe.Pointer { 196 x := uintptr(p) 197 return unsafe.Pointer(x ^ 0) //nolint:staticcheck 198 } 199 200 func bytesToString(b []byte) string { 201 return *(*string)(unsafe.Pointer(&b)) 202 }