OSDN Git Service

libgo: Update to current Go library.
[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 afterwards.
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 afterwards.
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 // truncate truncates the string to the specified precision, if present.
239 func (f *fmt) truncate(s string) string {
240         if f.precPresent && f.prec < utf8.RuneCountInString(s) {
241                 n := f.prec
242                 for i := range s {
243                         if n == 0 {
244                                 s = s[:i]
245                                 break
246                         }
247                         n--
248                 }
249         }
250         return s
251 }
252
253 // fmt_s formats a string.
254 func (f *fmt) fmt_s(s string) {
255         s = f.truncate(s)
256         f.padString(s)
257 }
258
259 // fmt_sx formats a string as a hexadecimal encoding of its bytes.
260 func (f *fmt) fmt_sx(s string) {
261         t := ""
262         for i := 0; i < len(s); i++ {
263                 if i > 0 && f.space {
264                         t += " "
265                 }
266                 v := s[i]
267                 t += string(ldigits[v>>4])
268                 t += string(ldigits[v&0xF])
269         }
270         f.padString(t)
271 }
272
273 // fmt_sX formats a string as an uppercase hexadecimal encoding of its bytes.
274 func (f *fmt) fmt_sX(s string) {
275         t := ""
276         for i := 0; i < len(s); i++ {
277                 if i > 0 && f.space {
278                         t += " "
279                 }
280                 v := s[i]
281                 t += string(udigits[v>>4])
282                 t += string(udigits[v&0xF])
283         }
284         f.padString(t)
285 }
286
287 // fmt_q formats a string as a double-quoted, escaped Go string constant.
288 func (f *fmt) fmt_q(s string) {
289         s = f.truncate(s)
290         var quoted string
291         if f.sharp && strconv.CanBackquote(s) {
292                 quoted = "`" + s + "`"
293         } else {
294                 quoted = strconv.Quote(s)
295         }
296         f.padString(quoted)
297 }
298
299 // floating-point
300
301 func doPrec(f *fmt, def int) int {
302         if f.precPresent {
303                 return f.prec
304         }
305         return def
306 }
307
308 // Add a plus sign or space to the floating-point string representation if missing and required.
309 func (f *fmt) plusSpace(s string) {
310         if s[0] != '-' {
311                 if f.plus {
312                         s = "+" + s
313                 } else if f.space {
314                         s = " " + s
315                 }
316         }
317         f.padString(s)
318 }
319
320 // fmt_e64 formats a float64 in the form -1.23e+12.
321 func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
322
323 // fmt_E64 formats a float64 in the form -1.23E+12.
324 func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
325
326 // fmt_f64 formats a float64 in the form -1.23.
327 func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
328
329 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
330 func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
331
332 // fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
333 func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
334
335 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
336 func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
337
338 // float32
339 // cannot defer to float64 versions
340 // because it will get rounding wrong in corner cases.
341
342 // fmt_e32 formats a float32 in the form -1.23e+12.
343 func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
344
345 // fmt_E32 formats a float32 in the form -1.23E+12.
346 func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
347
348 // fmt_f32 formats a float32 in the form -1.23.
349 func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
350
351 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
352 func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
353
354 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
355 func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
356
357 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
358 func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
359
360 // fmt_c64 formats a complex64 according to the verb.
361 func (f *fmt) fmt_c64(v complex64, verb int) {
362         f.buf.WriteByte('(')
363         r := real(v)
364         for i := 0; ; i++ {
365                 switch verb {
366                 case 'e':
367                         f.fmt_e32(r)
368                 case 'E':
369                         f.fmt_E32(r)
370                 case 'f':
371                         f.fmt_f32(r)
372                 case 'g':
373                         f.fmt_g32(r)
374                 case 'G':
375                         f.fmt_G32(r)
376                 }
377                 if i != 0 {
378                         break
379                 }
380                 f.plus = true
381                 r = imag(v)
382         }
383         f.buf.Write(irparenBytes)
384 }
385
386 // fmt_c128 formats a complex128 according to the verb.
387 func (f *fmt) fmt_c128(v complex128, verb int) {
388         f.buf.WriteByte('(')
389         r := real(v)
390         for i := 0; ; i++ {
391                 switch verb {
392                 case 'e':
393                         f.fmt_e64(r)
394                 case 'E':
395                         f.fmt_E64(r)
396                 case 'f':
397                         f.fmt_f64(r)
398                 case 'g':
399                         f.fmt_g64(r)
400                 case 'G':
401                         f.fmt_G64(r)
402                 }
403                 if i != 0 {
404                         break
405                 }
406                 f.plus = true
407                 r = imag(v)
408         }
409         f.buf.Write(irparenBytes)
410 }