format.go 10.8 KB
Newer Older
1 2 3 4 5 6
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fmt

7
import (
8
	"bytes";
9 10
	"strconv";
)
11

12 13
const (
	nByte	= 64;
14

15 16 17
	ldigits	= "0123456789abcdef";
	udigits	= "0123456789ABCDEF";
)
18

19 20 21 22
var padZeroBytes = make([]byte, nByte)
var padSpaceBytes = make([]byte, nByte)

var newline = []byte{'\n'}
23 24

func init() {
25 26 27
	for i := 0; i < nByte; i++ {
		padZeroBytes[i] = '0';
		padSpaceBytes[i] = ' ';
28 29
	}
}
30

31 32 33
// A fmt is the raw formatter used by Printf etc.
// It prints into a bytes.Buffer that must be set up externally.
type fmt struct {
34 35
	intbuf		[nByte]byte;
	buf		*bytes.Buffer;
36
	wid		int;
37
	widPresent	bool;
38
	prec		int;
39
	precPresent	bool;
40
	// flags
41 42 43 44 45
	minus	bool;
	plus	bool;
	sharp	bool;
	space	bool;
	zero	bool;
46 47
}

48
func (f *fmt) clearflags() {
49
	f.wid = 0;
50
	f.widPresent = false;
51
	f.prec = 0;
52
	f.precPresent = false;
53 54 55 56 57
	f.minus = false;
	f.plus = false;
	f.sharp = false;
	f.space = false;
	f.zero = false;
58 59
}

60
func (f *fmt) init(buf *bytes.Buffer) {
61
	f.buf = buf;
62
	f.clearflags();
63 64
}

65
// Compute left and right padding widths (only one will be non-zero).
66
func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
67 68 69 70 71 72 73 74
	left := !f.minus;
	w := f.wid;
	if w < 0 {
		left = false;
		w = -w;
	}
	w -= width;
	if w > 0 {
75
		if left && f.zero {
76
			return padZeroBytes, w, 0
77
		}
78 79 80 81 82 83 84 85 86 87 88
		if left {
			return padSpaceBytes, w, 0
		} else {
			// can't be zero padding on the right
			return padSpaceBytes, 0, w
		}
	}
	return;
}

// Generate n bytes of padding.
89
func (f *fmt) writePadding(n int, padding []byte) {
90 91 92 93
	for n > 0 {
		m := n;
		if m > nByte {
			m = nByte
94
		}
95 96 97 98 99 100
		f.buf.Write(padding[0:m]);
		n -= m;
	}
}

// Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus)
101
func (f *fmt) padBytes(b []byte) {
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
	var padding []byte;
	var left, right int;
	if f.widPresent && f.wid != 0 {
		padding, left, right = f.computePadding(len(b))
	}
	if left > 0 {
		f.writePadding(left, padding)
	}
	f.buf.Write(b);
	if right > 0 {
		f.writePadding(right, padding)
	}
}

// append s to buf, padded on left (w > 0) or right (w < 0 or f.minus)
117
func (f *fmt) pad(s string) {
118 119 120 121 122 123 124 125 126 127 128
	var padding []byte;
	var left, right int;
	if f.widPresent && f.wid != 0 {
		padding, left, right = f.computePadding(len(s))
	}
	if left > 0 {
		f.writePadding(left, padding)
	}
	f.buf.WriteString(s);
	if right > 0 {
		f.writePadding(right, padding)
129 130 131 132 133 134 135 136
	}
}

// format val into buf, ending at buf[i].  (printing is easier right-to-left;
// that's why the bidi languages are right-to-left except for numbers. wait,
// never mind.)  val is known to be unsigned.  we could make things maybe
// marginally faster by splitting the 32-bit case out into a separate function
// but it's not worth the duplication, so val has 64 bits.
137
func putint(buf []byte, base, val uint64, digits string) int {
138
	i := len(buf) - 1;
139
	for val >= base {
140
		buf[i] = digits[val%base];
141 142 143
		i--;
		val /= base;
	}
144
	buf[i] = digits[val];
145
	return i - 1;
146 147
}

148 149
// fmt_boolean formats a boolean.
func (f *fmt) fmt_boolean(v bool) {
Rob Pike's avatar
Rob Pike committed
150
	if v {
151
		f.pad("true")
Rob Pike's avatar
Rob Pike committed
152
	} else {
153
		f.pad("false")
Rob Pike's avatar
Rob Pike committed
154
	}
155
	f.clearflags();
Rob Pike's avatar
Rob Pike committed
156 157
}

158
// integer; interprets prec but not wid.
159
func (f *fmt) integer(a int64, base uint, is_signed bool, digits string) []byte {
160
	var buf []byte = &f.intbuf;
161 162
	negative := is_signed && a < 0;
	if negative {
163
		a = -a
164
	}
165 166 167 168

	// two ways to ask for extra leading zero digits: %.3d or %03d.
	// apparently the first cancels the second.
	prec := 0;
169
	if f.precPresent {
170 171
		prec = f.prec;
		f.zero = false;
172
	} else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
173 174
		prec = f.wid;
		if negative || f.plus || f.space {
175
			prec--	// leave room for sign
176 177
		}
	}
178

179
	i := putint(buf, uint64(base), uint64(a), digits);
Rob Pike's avatar
Rob Pike committed
180
	for i > 0 && prec > (nByte-1-i) {
181 182 183 184
		buf[i] = '0';
		i--;
	}

Rob Pike's avatar
Rob Pike committed
185 186 187 188 189 190 191 192
	if f.sharp {
		switch base {
		case 8:
			if buf[i+1] != '0' {
				buf[i] = '0';
				i--;
			}
		case 16:
193
			buf[i] = 'x' + digits[10] - 'a';
Rob Pike's avatar
Rob Pike committed
194 195 196 197 198 199
			i--;
			buf[i] = '0';
			i--;
		}
	}

200 201 202
	if negative {
		buf[i] = '-';
		i--;
203 204 205 206 207 208
	} else if f.plus {
		buf[i] = '+';
		i--;
	} else if f.space {
		buf[i] = ' ';
		i--;
209
	}
210
	return buf[i+1 : nByte];
211 212
}

213 214
// fmt_d64 formats an int64 in decimal.
func (f *fmt) fmt_d64(v int64) {
215
	f.padBytes(f.integer(v, 10, true, ldigits));
216
	f.clearflags();
217
}
218

219 220
// fmt_d32 formats an int32 in decimal.
func (f *fmt) fmt_d32(v int32)	{ f.fmt_d64(int64(v)) }
221

222 223
// fmt_d formats an int in decimal.
func (f *fmt) fmt_d(v int)	{ f.fmt_d64(int64(v)) }
224

225 226
// fmt_ud64 formats a uint64 in decimal.
func (f *fmt) fmt_ud64(v uint64) *fmt {
227
	f.padBytes(f.integer(int64(v), 10, false, ldigits));
228
	f.clearflags();
229 230 231
	return f;
}

232 233
// fmt_ud32 formats a uint32 in decimal.
func (f *fmt) fmt_ud32(v uint32)	{ f.fmt_ud64(uint64(v)) }
234

235 236
// fmt_ud formats a uint in decimal.
func (f *fmt) fmt_ud(v uint)	{ f.fmt_ud64(uint64(v)) }
237

238 239
// fmt_x64 formats an int64 in hexadecimal.
func (f *fmt) fmt_x64(v int64) {
240
	f.padBytes(f.integer(v, 16, true, ldigits));
241
	f.clearflags();
242 243
}

244 245
// fmt_x32 formats an int32 in hexadecimal.
func (f *fmt) fmt_x32(v int32)	{ f.fmt_x64(int64(v)) }
246

247 248
// fmt_x formats an int in hexadecimal.
func (f *fmt) fmt_x(v int)	{ f.fmt_x64(int64(v)) }
249

250 251
// fmt_ux64 formats a uint64 in hexadecimal.
func (f *fmt) fmt_ux64(v uint64) {
252
	f.padBytes(f.integer(int64(v), 16, false, ldigits));
253
	f.clearflags();
254 255
}

256 257
// fmt_ux32 formats a uint32 in hexadecimal.
func (f *fmt) fmt_ux32(v uint32)	{ f.fmt_ux64(uint64(v)) }
258

259 260
// fmt_ux formats a uint in hexadecimal.
func (f *fmt) fmt_ux(v uint)	{ f.fmt_ux64(uint64(v)) }
261

262 263
// fmt_X64 formats an int64 in upper case hexadecimal.
func (f *fmt) fmt_X64(v int64) {
264
	f.padBytes(f.integer(v, 16, true, udigits));
265
	f.clearflags();
266 267
}

268 269
// fmt_X32 formats an int32 in upper case hexadecimal.
func (f *fmt) fmt_X32(v int32)	{ f.fmt_X64(int64(v)) }
270

271 272
// fmt_X formats an int in upper case hexadecimal.
func (f *fmt) fmt_X(v int)	{ f.fmt_X64(int64(v)) }
273

274 275
// fmt_uX64 formats a uint64 in upper case hexadecimal.
func (f *fmt) fmt_uX64(v uint64) {
276
	f.padBytes(f.integer(int64(v), 16, false, udigits));
277
	f.clearflags();
278 279
}

280 281
// fmt_uX32 formats a uint32 in upper case hexadecimal.
func (f *fmt) fmt_uX32(v uint32)	{ f.fmt_uX64(uint64(v)) }
282

283 284
// fmt_uX formats a uint in upper case hexadecimal.
func (f *fmt) fmt_uX(v uint)	{ f.fmt_uX64(uint64(v)) }
285

286 287
// fmt_o64 formats an int64 in octal.
func (f *fmt) fmt_o64(v int64) {
288
	f.padBytes(f.integer(v, 8, true, ldigits));
289
	f.clearflags();
290 291
}

292 293
// fmt_o32 formats an int32 in octal.
func (f *fmt) fmt_o32(v int32)	{ f.fmt_o64(int64(v)) }
294

295 296
// fmt_o formats an int in octal.
func (f *fmt) fmt_o(v int)	{ f.fmt_o64(int64(v)) }
297

298 299
// fmt_uo64 formats a uint64 in octal.
func (f *fmt) fmt_uo64(v uint64) {
300
	f.padBytes(f.integer(int64(v), 8, false, ldigits));
301
	f.clearflags();
302 303
}

304 305
// fmt_uo32 formats a uint32 in octal.
func (f *fmt) fmt_uo32(v uint32)	{ f.fmt_uo64(uint64(v)) }
306

307 308
// fmt_uo formats a uint in octal.
func (f *fmt) fmt_uo(v uint)	{ f.fmt_uo64(uint64(v)) }
309

310 311
// fmt_b64 formats a uint64 in binary.
func (f *fmt) fmt_b64(v uint64) {
312
	f.padBytes(f.integer(int64(v), 2, false, ldigits));
313
	f.clearflags();
314 315
}

316 317
// fmt_b32 formats a uint32 in binary.
func (f *fmt) fmt_b32(v uint32)	{ f.fmt_b64(uint64(v)) }
318

319 320
// fmt_b formats a uint in binary.
func (f *fmt) fmt_b(v uint)	{ f.fmt_b64(uint64(v)) }
321

322 323
// fmt_c formats a Unicode character.
func (f *fmt) fmt_c(v int) {
Rob Pike's avatar
Rob Pike committed
324
	f.pad(string(v));
325
	f.clearflags();
326 327
}

328 329
// fmt_s formats a string.
func (f *fmt) fmt_s(s string) {
330
	if f.precPresent {
331
		if f.prec < len(s) {
332
			s = s[0:f.prec]
333 334 335
		}
	}
	f.pad(s);
336
	f.clearflags();
337 338
}

339 340
// fmt_sx formats a string as a hexadecimal encoding of its bytes.
func (f *fmt) fmt_sx(s string) {
341 342
	t := "";
	for i := 0; i < len(s); i++ {
343
		if i > 0 && f.space {
344
			t += " "
345
		}
346 347 348 349 350
		v := s[i];
		t += string(ldigits[v>>4]);
		t += string(ldigits[v&0xF]);
	}
	f.pad(t);
351
	f.clearflags();
352 353
}

354 355
// fmt_sX formats a string as an uppercase hexadecimal encoding of its bytes.
func (f *fmt) fmt_sX(s string) {
356 357 358 359 360 361 362
	t := "";
	for i := 0; i < len(s); i++ {
		v := s[i];
		t += string(udigits[v>>4]);
		t += string(udigits[v&0xF]);
	}
	f.pad(t);
363
	f.clearflags();
364 365
}

366 367
// fmt_q formats a string as a double-quoted, escaped Go string constant.
func (f *fmt) fmt_q(s string) {
368 369
	var quoted string;
	if f.sharp && strconv.CanBackquote(s) {
370
		quoted = "`" + s + "`"
371
	} else {
372
		quoted = strconv.Quote(s)
373 374
	}
	f.pad(quoted);
375
	f.clearflags();
376 377
}

378
// floating-point
379

380
func doPrec(f *fmt, def int) int {
381
	if f.precPresent {
382
		return f.prec
Rob Pike's avatar
Rob Pike committed
383
	}
384
	return def;
Rob Pike's avatar
Rob Pike committed
385 386
}

387
func fmtString(f *fmt, s string) {
388
	f.pad(s);
389
	f.clearflags();
390 391
}

392
// Add a plus sign or space to the string if missing and required.
393
func (f *fmt) plusSpace(s string) {
394 395 396 397 398 399 400
	if s[0] != '-' {
		if f.plus {
			s = "+" + s
		} else if f.space {
			s = " " + s
		}
	}
401
	fmtString(f, s);
402 403
}

404 405
// fmt_e64 formats a float64 in the form -1.23e+12.
func (f *fmt) fmt_e64(v float64)	{ f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
406

407 408
// fmt_E64 formats a float64 in the form -1.23E+12.
func (f *fmt) fmt_E64(v float64)	{ f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
Russ Cox's avatar
Russ Cox committed
409

410 411
// fmt_f64 formats a float64 in the form -1.23.
func (f *fmt) fmt_f64(v float64)	{ f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
412

413 414
// fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
func (f *fmt) fmt_g64(v float64)	{ f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
415

416 417
// fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
func (f *fmt) fmt_G64(v float64)	{ f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
Russ Cox's avatar
Russ Cox committed
418

419 420
// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
func (f *fmt) fmt_fb64(v float64)	{ f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
421

422 423 424
// float32
// cannot defer to float64 versions
// because it will get rounding wrong in corner cases.
Rob Pike's avatar
Rob Pike committed
425

426 427
// fmt_e32 formats a float32 in the form -1.23e+12.
func (f *fmt) fmt_e32(v float32)	{ f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
428

429 430
// fmt_E32 formats a float32 in the form -1.23E+12.
func (f *fmt) fmt_E32(v float32)	{ f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
Russ Cox's avatar
Russ Cox committed
431

432 433
// fmt_f32 formats a float32 in the form -1.23.
func (f *fmt) fmt_f32(v float32)	{ f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
434

435 436
// fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
func (f *fmt) fmt_g32(v float32)	{ f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
437

438 439
// fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
func (f *fmt) fmt_G32(v float32)	{ f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
Russ Cox's avatar
Russ Cox committed
440

441 442
// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
func (f *fmt) fmt_fb32(v float32)	{ fmtString(f, strconv.Ftoa32(v, 'b', 0)) }
443 444

// float
445
func (x *fmt) f(a float) {
446
	if strconv.FloatSize == 32 {
447
		x.fmt_f32(float32(a))
448
	} else {
449
		x.fmt_f64(float64(a))
450
	}
451 452
}

453
func (x *fmt) e(a float) {
454
	if strconv.FloatSize == 32 {
455
		x.fmt_e32(float32(a))
456
	} else {
457
		x.fmt_e64(float64(a))
458
	}
459 460
}

461
func (x *fmt) g(a float) {
462
	if strconv.FloatSize == 32 {
463
		x.fmt_g32(float32(a))
464
	} else {
465
		x.fmt_g64(float64(a))
466
	}
467 468
}

469
func (x *fmt) fb(a float) {
470
	if strconv.FloatSize == 32 {
471
		x.fmt_fb32(float32(a))
472
	} else {
473
		x.fmt_fb64(float64(a))
474
	}
475
}