1
2
3
4
5 package fmt
6
7 import (
8 "bytes"
9 "strconv"
10 "unicode"
11 "utf8"
12 )
13
14 const (
15 nByte = 64
16
17 ldigits = "0123456789abcdef"
18 udigits = "0123456789ABCDEF"
19 )
20
21 const (
22 signed = true
23 unsigned = false
24 )
25
26 var padZeroBytes = make([]byte, nByte)
27 var padSpaceBytes = make([]byte, nByte)
28
29 var newline = []byte{'\n'}
30
31 func init() {
32 for i := 0; i < nByte; i++ {
33 padZeroBytes[i] = '0'
34 padSpaceBytes[i] = ' '
35 }
36 }
37
38
39
40 type fmt struct {
41 intbuf [nByte]byte
42 buf *bytes.Buffer
43
44 wid int
45 prec int
46
47 widPresent bool
48 precPresent bool
49 minus bool
50 plus bool
51 sharp bool
52 space bool
53 unicode bool
54 uniQuote bool
55 zero bool
56 }
57
58 func (f *fmt) clearflags() {
59 f.wid = 0
60 f.widPresent = false
61 f.prec = 0
62 f.precPresent = false
63 f.minus = false
64 f.plus = false
65 f.sharp = false
66 f.space = false
67 f.unicode = false
68 f.uniQuote = false
69 f.zero = false
70 }
71
72 func (f *fmt) init(buf *bytes.Buffer) {
73 f.buf = buf
74 f.clearflags()
75 }
76
77
78 func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
79 left := !f.minus
80 w := f.wid
81 if w < 0 {
82 left = false
83 w = -w
84 }
85 w -= width
86 if w > 0 {
87 if left && f.zero {
88 return padZeroBytes, w, 0
89 }
90 if left {
91 return padSpaceBytes, w, 0
92 } else {
93
94 return padSpaceBytes, 0, w
95 }
96 }
97 return
98 }
99
100
101 func (f *fmt) writePadding(n int, padding []byte) {
102 for n > 0 {
103 m := n
104 if m > nByte {
105 m = nByte
106 }
107 f.buf.Write(padding[0:m])
108 n -= m
109 }
110 }
111
112
113
114 func (f *fmt) pad(b []byte) {
115 var padding []byte
116 var left, right int
117 if f.widPresent && f.wid != 0 {
118 padding, left, right = f.computePadding(len(b))
119 }
120 if left > 0 {
121 f.writePadding(left, padding)
122 }
123 f.buf.Write(b)
124 if right > 0 {
125 f.writePadding(right, padding)
126 }
127 }
128
129
130
131 func (f *fmt) padString(s string) {
132 var padding []byte
133 var left, right int
134 if f.widPresent && f.wid != 0 {
135 padding, left, right = f.computePadding(utf8.RuneCountInString(s))
136 }
137 if left > 0 {
138 f.writePadding(left, padding)
139 }
140 f.buf.WriteString(s)
141 if right > 0 {
142 f.writePadding(right, padding)
143 }
144 }
145
146 func putint(buf []byte, base, val uint64, digits string) int {
147 i := len(buf) - 1
148 for val >= base {
149 buf[i] = digits[val%base]
150 i--
151 val /= base
152 }
153 buf[i] = digits[val]
154 return i - 1
155 }
156
157
158 func (f *fmt) fmt_boolean(v bool) {
159 if v {
160 f.padString("true")
161 } else {
162 f.padString("false")
163 }
164 }
165
166
167
168 func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
169
170 if f.precPresent && f.prec == 0 && a == 0 {
171 return
172 }
173
174 var buf []byte = f.intbuf[0:]
175 negative := signedness == signed && a < 0
176 if negative {
177 a = -a
178 }
179
180
181
182 prec := 0
183 if f.precPresent {
184 prec = f.prec
185 f.zero = false
186 } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
187 prec = f.wid
188 if negative || f.plus || f.space {
189 prec--
190 }
191 }
192
193
194
195
196
197 i := len(f.intbuf)
198 ua := uint64(a)
199 for ua >= base {
200 i--
201 buf[i] = digits[ua%base]
202 ua /= base
203 }
204 i--
205 buf[i] = digits[ua]
206 for i > 0 && prec > nByte-i {
207 i--
208 buf[i] = '0'
209 }
210
211
212 if f.sharp {
213 switch base {
214 case 8:
215 if buf[i] != '0' {
216 i--
217 buf[i] = '0'
218 }
219 case 16:
220 i--
221 buf[i] = 'x' + digits[10] - 'a'
222 i--
223 buf[i] = '0'
224 }
225 }
226 if f.unicode {
227 i--
228 buf[i] = '+'
229 i--
230 buf[i] = 'U'
231 }
232
233 if negative {
234 i--
235 buf[i] = '-'
236 } else if f.plus {
237 i--
238 buf[i] = '+'
239 } else if f.space {
240 i--
241 buf[i] = ' '
242 }
243
244
245 if f.unicode && f.uniQuote && a >= 0 && a <= unicode.MaxRune && unicode.IsPrint(int(a)) {
246 runeWidth := utf8.RuneLen(int(a))
247 width := 1 + 1 + runeWidth + 1
248 copy(buf[i-width:], buf[i:])
249 i -= width
250
251 j := len(buf) - width
252 buf[j] = ' '
253 j++
254 buf[j] = '\''
255 j++
256 utf8.EncodeRune(buf[j:], int(a))
257 j += runeWidth
258 buf[j] = '\''
259 }
260
261 f.pad(buf[i:])
262 }
263
264
265 func (f *fmt) truncate(s string) string {
266 if f.precPresent && f.prec < utf8.RuneCountInString(s) {
267 n := f.prec
268 for i := range s {
269 if n == 0 {
270 s = s[:i]
271 break
272 }
273 n--
274 }
275 }
276 return s
277 }
278
279
280 func (f *fmt) fmt_s(s string) {
281 s = f.truncate(s)
282 f.padString(s)
283 }
284
285
286 func (f *fmt) fmt_sx(s string) {
287 t := ""
288 for i := 0; i < len(s); i++ {
289 if i > 0 && f.space {
290 t += " "
291 }
292 v := s[i]
293 t += string(ldigits[v>>4])
294 t += string(ldigits[v&0xF])
295 }
296 f.padString(t)
297 }
298
299
300 func (f *fmt) fmt_sX(s string) {
301 t := ""
302 for i := 0; i < len(s); i++ {
303 if i > 0 && f.space {
304 t += " "
305 }
306 v := s[i]
307 t += string(udigits[v>>4])
308 t += string(udigits[v&0xF])
309 }
310 f.padString(t)
311 }
312
313
314 func (f *fmt) fmt_q(s string) {
315 s = f.truncate(s)
316 var quoted string
317 if f.sharp && strconv.CanBackquote(s) {
318 quoted = "`" + s + "`"
319 } else {
320 if f.plus {
321 quoted = strconv.QuoteToASCII(s)
322 } else {
323 quoted = strconv.Quote(s)
324 }
325 }
326 f.padString(quoted)
327 }
328
329
330
331 func (f *fmt) fmt_qc(c int64) {
332 var quoted string
333 if f.plus {
334 quoted = strconv.QuoteRuneToASCII(int(c))
335 } else {
336 quoted = strconv.QuoteRune(int(c))
337 }
338 f.padString(quoted)
339 }
340
341
342
343 func doPrec(f *fmt, def int) int {
344 if f.precPresent {
345 return f.prec
346 }
347 return def
348 }
349
350
351 func (f *fmt) plusSpace(s string) {
352 if s[0] != '-' {
353 if f.plus {
354 s = "+" + s
355 } else if f.space {
356 s = " " + s
357 }
358 }
359 f.padString(s)
360 }
361
362
363 func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
364
365
366 func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
367
368
369 func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
370
371
372 func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
373
374
375 func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
376
377
378 func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
379
380
381
382
383
384
385 func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
386
387
388 func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
389
390
391 func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
392
393
394 func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
395
396
397 func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
398
399
400 func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
401
402
403 func (f *fmt) fmt_c64(v complex64, verb int) {
404 f.buf.WriteByte('(')
405 r := real(v)
406 for i := 0; ; i++ {
407 switch verb {
408 case 'e':
409 f.fmt_e32(r)
410 case 'E':
411 f.fmt_E32(r)
412 case 'f':
413 f.fmt_f32(r)
414 case 'g':
415 f.fmt_g32(r)
416 case 'G':
417 f.fmt_G32(r)
418 }
419 if i != 0 {
420 break
421 }
422 f.plus = true
423 r = imag(v)
424 }
425 f.buf.Write(irparenBytes)
426 }
427
428
429 func (f *fmt) fmt_c128(v complex128, verb int) {
430 f.buf.WriteByte('(')
431 r := real(v)
432 for i := 0; ; i++ {
433 switch verb {
434 case 'e':
435 f.fmt_e64(r)
436 case 'E':
437 f.fmt_E64(r)
438 case 'f':
439 f.fmt_f64(r)
440 case 'g':
441 f.fmt_g64(r)
442 case 'G':
443 f.fmt_G64(r)
444 }
445 if i != 0 {
446 break
447 }
448 f.plus = true
449 r = imag(v)
450 }
451 f.buf.Write(irparenBytes)
452 }