OSDN Git Service

86057bf693cda2d49cd8ce44fd41407ac357045a
[pf3gnuchains/gcc-fork.git] / libgo / go / fmt / format.go
1 // 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         "utf8"
11 )
12
13 const (
14         nByte = 64
15
16         ldigits = "0123456789abcdef"
17         udigits = "0123456789ABCDEF"
18 )
19
20 const (
21         signed   = true
22         unsigned = false
23 )
24
25 var padZeroBytes = make([]byte, nByte)
26 var padSpaceBytes = make([]byte, nByte)
27
28 var newline = []byte{'\n'}
29
30 func init() {
31         for i := 0; i < nByte; i++ {
32                 padZeroBytes[i] = '0'
33                 padSpaceBytes[i] = ' '
34         }
35 }
36
37 // A fmt is the raw formatter used by Printf etc.
38 // It prints into a bytes.Buffer that must be set up externally.
39 type fmt struct {
40         intbuf [nByte]byte
41         buf    *bytes.Buffer
42         // width, precision
43         wid  int
44         prec int
45         // flags
46         widPresent  bool
47         precPresent bool
48         minus       bool
49         plus        bool
50         sharp       bool
51         space       bool
52         unicode     bool
53         zero        bool
54 }
55
56 func (f *fmt) clearflags() {
57         f.wid = 0
58         f.widPresent = false
59         f.prec = 0
60         f.precPresent = false
61         f.minus = false
62         f.plus = false
63         f.sharp = false
64         f.space = false
65         f.unicode = false
66         f.zero = false
67 }
68
69 func (f *fmt) init(buf *bytes.Buffer) {
70         f.buf = buf
71         f.clearflags()
72 }
73
74 // Compute left and right padding widths (only one will be non-zero).
75 func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
76         left := !f.minus
77         w := f.wid
78         if w < 0 {
79                 left = false
80                 w = -w
81         }
82         w -= width
83         if w > 0 {
84                 if left && f.zero {
85                         return padZeroBytes, w, 0
86                 }
87                 if left {
88                         return padSpaceBytes, w, 0
89                 } else {
90                         // can't be zero padding on the right
91                         return padSpaceBytes, 0, w
92                 }
93         }
94         return
95 }
96
97 // Generate n bytes of padding.
98 func (f *fmt) writePadding(n int, padding []byte) {
99         for n > 0 {
100                 m := n
101                 if m > nByte {
102                         m = nByte
103                 }
104                 f.buf.Write(padding[0:m])
105                 n -= m
106         }
107 }
108
109 // Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus)
110 // clear flags aftewards.
111 func (f *fmt) pad(b []byte) {
112         var padding []byte
113         var left, right int
114         if f.widPresent && f.wid != 0 {
115                 padding, left, right = f.computePadding(len(b))
116         }
117         if left > 0 {
118                 f.writePadding(left, padding)
119         }
120         f.buf.Write(b)
121         if right > 0 {
122                 f.writePadding(right, padding)
123         }
124 }
125
126 // append s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
127 // clear flags aftewards.
128 func (f *fmt) padString(s string) {
129         var padding []byte
130         var left, right int
131         if f.widPresent && f.wid != 0 {
132                 padding, left, right = f.computePadding(utf8.RuneCountInString(s))
133         }
134         if left > 0 {
135                 f.writePadding(left, padding)
136         }
137         f.buf.WriteString(s)
138         if right > 0 {
139                 f.writePadding(right, padding)
140         }
141 }
142
143 func putint(buf []byte, base, val uint64, digits string) int {
144         i := len(buf) - 1
145         for val >= base {
146                 buf[i] = digits[val%base]
147                 i--
148                 val /= base
149         }
150         buf[i] = digits[val]
151         return i - 1
152 }
153
154 // fmt_boolean formats a boolean.
155 func (f *fmt) fmt_boolean(v bool) {
156         if v {
157                 f.padString("true")
158         } else {
159                 f.padString("false")
160         }
161 }
162
163 // integer; interprets prec but not wid.  Once formatted, result is sent to pad()
164 // and then flags are cleared.
165 func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
166         var buf []byte = f.intbuf[0:]
167         negative := signedness == signed && a < 0
168         if negative {
169                 a = -a
170         }
171
172         // two ways to ask for extra leading zero digits: %.3d or %03d.
173         // apparently the first cancels the second.
174         prec := 0
175         if f.precPresent {
176                 prec = f.prec
177                 f.zero = false
178         } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
179                 prec = f.wid
180                 if negative || f.plus || f.space {
181                         prec-- // leave room for sign
182                 }
183         }
184
185         // format a into buf, ending at buf[i].  (printing is easier right-to-left.)
186         // a is made into unsigned ua.  we could make things
187         // marginally faster by splitting the 32-bit case out into a separate
188         // block but it's not worth the duplication, so ua has 64 bits.
189         i := len(f.intbuf)
190         ua := uint64(a)
191         for ua >= base {
192                 i--
193                 buf[i] = digits[ua%base]
194                 ua /= base
195         }
196         i--
197         buf[i] = digits[ua]
198         for i > 0 && prec > nByte-i {
199                 i--
200                 buf[i] = '0'
201         }
202
203         // Various prefixes: 0x, -, etc.
204         if f.sharp {
205                 switch base {
206                 case 8:
207                         if buf[i] != '0' {
208                                 i--
209                                 buf[i] = '0'
210                         }
211                 case 16:
212                         i--
213                         buf[i] = 'x' + digits[10] - 'a'
214                         i--
215                         buf[i] = '0'
216                 }
217         }
218         if f.unicode {
219                 i--
220                 buf[i] = '+'
221                 i--
222                 buf[i] = 'U'
223         }
224
225         if negative {
226                 i--
227                 buf[i] = '-'
228         } else if f.plus {
229                 i--
230                 buf[i] = '+'
231         } else if f.space {
232                 i--
233                 buf[i] = ' '
234         }
235         f.pad(buf[i:])
236 }
237
238 // fmt_s formats a string.
239 func (f *fmt) fmt_s(s string) {
240         if f.precPresent {
241                 if f.prec < len(s) {
242                         s = s[0:f.prec]
243                 }
244         }
245         f.padString(s)
246 }
247
248 // fmt_sx formats a string as a hexadecimal encoding of its bytes.
249 func (f *fmt) fmt_sx(s string) {
250         t := ""
251         for i := 0; i < len(s); i++ {
252                 if i > 0 && f.space {
253                         t += " "
254                 }
255                 v := s[i]
256                 t += string(ldigits[v>>4])
257                 t += string(ldigits[v&0xF])
258         }
259         f.padString(t)
260 }
261
262 // fmt_sX formats a string as an uppercase hexadecimal encoding of its bytes.
263 func (f *fmt) fmt_sX(s string) {
264         t := ""
265         for i := 0; i < len(s); i++ {
266                 if i > 0 && f.space {
267                         t += " "
268                 }
269                 v := s[i]
270                 t += string(udigits[v>>4])
271                 t += string(udigits[v&0xF])
272         }
273         f.padString(t)
274 }
275
276 // fmt_q formats a string as a double-quoted, escaped Go string constant.
277 func (f *fmt) fmt_q(s string) {
278         var quoted string
279         if f.sharp && strconv.CanBackquote(s) {
280                 quoted = "`" + s + "`"
281         } else {
282                 quoted = strconv.Quote(s)
283         }
284         f.padString(quoted)
285 }
286
287 // floating-point
288
289 func doPrec(f *fmt, def int) int {
290         if f.precPresent {
291                 return f.prec
292         }
293         return def
294 }
295
296 // Add a plus sign or space to the floating-point string representation if missing and required.
297 func (f *fmt) plusSpace(s string) {
298         if s[0] != '-' {
299                 if f.plus {
300                         s = "+" + s
301                 } else if f.space {
302                         s = " " + s
303                 }
304         }
305         f.padString(s)
306 }
307
308 // fmt_e64 formats a float64 in the form -1.23e+12.
309 func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
310
311 // fmt_E64 formats a float64 in the form -1.23E+12.
312 func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
313
314 // fmt_f64 formats a float64 in the form -1.23.
315 func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
316
317 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
318 func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
319
320 // fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
321 func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
322
323 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
324 func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
325
326 // float32
327 // cannot defer to float64 versions
328 // because it will get rounding wrong in corner cases.
329
330 // fmt_e32 formats a float32 in the form -1.23e+12.
331 func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
332
333 // fmt_E32 formats a float32 in the form -1.23E+12.
334 func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
335
336 // fmt_f32 formats a float32 in the form -1.23.
337 func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
338
339 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
340 func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
341
342 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
343 func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
344
345 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
346 func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
347
348 // fmt_c64 formats a complex64 according to the verb.
349 func (f *fmt) fmt_c64(v complex64, verb int) {
350         f.buf.WriteByte('(')
351         r := real(v)
352         for i := 0; ; i++ {
353                 switch verb {
354                 case 'e':
355                         f.fmt_e32(r)
356                 case 'E':
357                         f.fmt_E32(r)
358                 case 'f':
359                         f.fmt_f32(r)
360                 case 'g':
361                         f.fmt_g32(r)
362                 case 'G':
363                         f.fmt_G32(r)
364                 }
365                 if i != 0 {
366                         break
367                 }
368                 f.plus = true
369                 r = imag(v)
370         }
371         f.buf.Write(irparenBytes)
372 }
373
374 // fmt_c128 formats a complex128 according to the verb.
375 func (f *fmt) fmt_c128(v complex128, verb int) {
376         f.buf.WriteByte('(')
377         r := real(v)
378         for i := 0; ; i++ {
379                 switch verb {
380                 case 'e':
381                         f.fmt_e64(r)
382                 case 'E':
383                         f.fmt_E64(r)
384                 case 'f':
385                         f.fmt_f64(r)
386                 case 'g':
387                         f.fmt_g64(r)
388                 case 'G':
389                         f.fmt_G64(r)
390                 }
391                 if i != 0 {
392                         break
393                 }
394                 f.plus = true
395                 r = imag(v)
396         }
397         f.buf.Write(irparenBytes)
398 }