OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [fmt/] [format.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package fmt
6
 
7
import (
8
        "bytes"
9
        "strconv"
10
        "unicode"
11
        "unicode/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
// A fmt is the raw formatter used by Printf etc.
39
// It prints into a bytes.Buffer that must be set up externally.
40
type fmt struct {
41
        intbuf [nByte]byte
42
        buf    *bytes.Buffer
43
        // width, precision
44
        wid  int
45
        prec int
46
        // flags
47
        widPresent  bool
48
        precPresent bool
49
        minus       bool
50
        plus        bool
51
        sharp       bool
52
        space       bool
53
        unicode     bool
54
        uniQuote    bool // Use 'x'= prefix for %U if printable.
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
// Compute left and right padding widths (only one will be non-zero).
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
                        // can't be zero padding on the right
94
                        return padSpaceBytes, 0, w
95
                }
96
        }
97
        return
98
}
99
 
100
// Generate n bytes of padding.
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
// Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus)
113
// clear flags afterwards.
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
// append s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
130
// clear flags afterwards.
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
var (
158
        trueBytes  = []byte("true")
159
        falseBytes = []byte("false")
160
)
161
 
162
// fmt_boolean formats a boolean.
163
func (f *fmt) fmt_boolean(v bool) {
164
        if v {
165
                f.pad(trueBytes)
166
        } else {
167
                f.pad(falseBytes)
168
        }
169
}
170
 
171
// integer; interprets prec but not wid.  Once formatted, result is sent to pad()
172
// and then flags are cleared.
173
func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
174
        // precision of 0 and value of 0 means "print nothing"
175
        if f.precPresent && f.prec == 0 && a == 0 {
176
                return
177
        }
178
 
179
        var buf []byte = f.intbuf[0:]
180
        negative := signedness == signed && a < 0
181
        if negative {
182
                a = -a
183
        }
184
 
185
        // two ways to ask for extra leading zero digits: %.3d or %03d.
186
        // apparently the first cancels the second.
187
        prec := 0
188
        if f.precPresent {
189
                prec = f.prec
190
                f.zero = false
191
        } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
192
                prec = f.wid
193
                if negative || f.plus || f.space {
194
                        prec-- // leave room for sign
195
                }
196
        }
197
 
198
        // format a into buf, ending at buf[i].  (printing is easier right-to-left.)
199
        // a is made into unsigned ua.  we could make things
200
        // marginally faster by splitting the 32-bit case out into a separate
201
        // block but it's not worth the duplication, so ua has 64 bits.
202
        i := len(f.intbuf)
203
        ua := uint64(a)
204
        for ua >= base {
205
                i--
206
                buf[i] = digits[ua%base]
207
                ua /= base
208
        }
209
        i--
210
        buf[i] = digits[ua]
211
        for i > 0 && prec > nByte-i {
212
                i--
213
                buf[i] = '0'
214
        }
215
 
216
        // Various prefixes: 0x, -, etc.
217
        if f.sharp {
218
                switch base {
219
                case 8:
220
                        if buf[i] != '0' {
221
                                i--
222
                                buf[i] = '0'
223
                        }
224
                case 16:
225
                        i--
226
                        buf[i] = 'x' + digits[10] - 'a'
227
                        i--
228
                        buf[i] = '0'
229
                }
230
        }
231
        if f.unicode {
232
                i--
233
                buf[i] = '+'
234
                i--
235
                buf[i] = 'U'
236
        }
237
 
238
        if negative {
239
                i--
240
                buf[i] = '-'
241
        } else if f.plus {
242
                i--
243
                buf[i] = '+'
244
        } else if f.space {
245
                i--
246
                buf[i] = ' '
247
        }
248
 
249
        // If we want a quoted char for %#U, move the data up to make room.
250
        if f.unicode && f.uniQuote && a >= 0 && a <= unicode.MaxRune && unicode.IsPrint(rune(a)) {
251
                runeWidth := utf8.RuneLen(rune(a))
252
                width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
253
                copy(buf[i-width:], buf[i:])   // guaranteed to have enough room.
254
                i -= width
255
                // Now put " 'x'" at the end.
256
                j := len(buf) - width
257
                buf[j] = ' '
258
                j++
259
                buf[j] = '\''
260
                j++
261
                utf8.EncodeRune(buf[j:], rune(a))
262
                j += runeWidth
263
                buf[j] = '\''
264
        }
265
 
266
        f.pad(buf[i:])
267
}
268
 
269
// truncate truncates the string to the specified precision, if present.
270
func (f *fmt) truncate(s string) string {
271
        if f.precPresent && f.prec < utf8.RuneCountInString(s) {
272
                n := f.prec
273
                for i := range s {
274
                        if n == 0 {
275
                                s = s[:i]
276
                                break
277
                        }
278
                        n--
279
                }
280
        }
281
        return s
282
}
283
 
284
// fmt_s formats a string.
285
func (f *fmt) fmt_s(s string) {
286
        s = f.truncate(s)
287
        f.padString(s)
288
}
289
 
290
// fmt_sx formats a string as a hexadecimal encoding of its bytes.
291
func (f *fmt) fmt_sx(s, digits string) {
292
        // TODO: Avoid buffer by pre-padding.
293
        var b bytes.Buffer
294
        for i := 0; i < len(s); i++ {
295
                if i > 0 && f.space {
296
                        b.WriteByte(' ')
297
                }
298
                v := s[i]
299
                b.WriteByte(digits[v>>4])
300
                b.WriteByte(digits[v&0xF])
301
        }
302
        f.pad(b.Bytes())
303
}
304
 
305
// fmt_q formats a string as a double-quoted, escaped Go string constant.
306
func (f *fmt) fmt_q(s string) {
307
        s = f.truncate(s)
308
        var quoted string
309
        if f.sharp && strconv.CanBackquote(s) {
310
                quoted = "`" + s + "`"
311
        } else {
312
                if f.plus {
313
                        quoted = strconv.QuoteToASCII(s)
314
                } else {
315
                        quoted = strconv.Quote(s)
316
                }
317
        }
318
        f.padString(quoted)
319
}
320
 
321
// fmt_qc formats the integer as a single-quoted, escaped Go character constant.
322
// If the character is not valid Unicode, it will print '\ufffd'.
323
func (f *fmt) fmt_qc(c int64) {
324
        var quoted []byte
325
        if f.plus {
326
                quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
327
        } else {
328
                quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
329
        }
330
        f.pad(quoted)
331
}
332
 
333
// floating-point
334
 
335
func doPrec(f *fmt, def int) int {
336
        if f.precPresent {
337
                return f.prec
338
        }
339
        return def
340
}
341
 
342
// formatFloat formats a float64; it is an efficient equivalent to  f.pad(strconv.FormatFloat()...).
343
func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
344
        // We leave one byte at the beginning of f.intbuf for a sign if needed,
345
        // and make it a space, which we might be able to use.
346
        f.intbuf[0] = ' '
347
        slice := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
348
        // Add a plus sign or space to the floating-point string representation if missing and required.
349
        // The formatted number starts at slice[1].
350
        switch slice[1] {
351
        case '-', '+':
352
                // We're set; drop the leading space.
353
                slice = slice[1:]
354
        default:
355
                // There's no sign, but we might need one.
356
                if f.plus {
357
                        slice[0] = '+'
358
                } else if f.space {
359
                        // space is already there
360
                } else {
361
                        slice = slice[1:]
362
                }
363
        }
364
        f.pad(slice)
365
}
366
 
367
// fmt_e64 formats a float64 in the form -1.23e+12.
368
func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
369
 
370
// fmt_E64 formats a float64 in the form -1.23E+12.
371
func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
372
 
373
// fmt_f64 formats a float64 in the form -1.23.
374
func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
375
 
376
// fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
377
func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
378
 
379
// fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
380
func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
381
 
382
// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
383
func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
384
 
385
// float32
386
// cannot defer to float64 versions
387
// because it will get rounding wrong in corner cases.
388
 
389
// fmt_e32 formats a float32 in the form -1.23e+12.
390
func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
391
 
392
// fmt_E32 formats a float32 in the form -1.23E+12.
393
func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
394
 
395
// fmt_f32 formats a float32 in the form -1.23.
396
func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
397
 
398
// fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
399
func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
400
 
401
// fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
402
func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
403
 
404
// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
405
func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
406
 
407
// fmt_c64 formats a complex64 according to the verb.
408
func (f *fmt) fmt_c64(v complex64, verb rune) {
409
        f.buf.WriteByte('(')
410
        r := real(v)
411
        for i := 0; ; i++ {
412
                switch verb {
413
                case 'e':
414
                        f.fmt_e32(r)
415
                case 'E':
416
                        f.fmt_E32(r)
417
                case 'f':
418
                        f.fmt_f32(r)
419
                case 'g':
420
                        f.fmt_g32(r)
421
                case 'G':
422
                        f.fmt_G32(r)
423
                }
424
                if i != 0 {
425
                        break
426
                }
427
                f.plus = true
428
                r = imag(v)
429
        }
430
        f.buf.Write(irparenBytes)
431
}
432
 
433
// fmt_c128 formats a complex128 according to the verb.
434
func (f *fmt) fmt_c128(v complex128, verb rune) {
435
        f.buf.WriteByte('(')
436
        r := real(v)
437
        for i := 0; ; i++ {
438
                switch verb {
439
                case 'e':
440
                        f.fmt_e64(r)
441
                case 'E':
442
                        f.fmt_E64(r)
443
                case 'f':
444
                        f.fmt_f64(r)
445
                case 'g':
446
                        f.fmt_g64(r)
447
                case 'G':
448
                        f.fmt_G64(r)
449
                }
450
                if i != 0 {
451
                        break
452
                }
453
                f.plus = true
454
                r = imag(v)
455
        }
456
        f.buf.Write(irparenBytes)
457
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.