summaryrefslogtreecommitdiff
path: root/lib/std/intfmt.myr
blob: 7b9cfdfde11df6bddfec4576c11865c34fd7aa26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use "die"
use "extremum"
use "intparse"
use "option"
use "strbuf"
use "striter"
use "types"

pkg std =
	pkglocal type intparams = struct
		base	: size
		padto	: size
		padfill	: char
	;;

	pkglocal const intfmt	: (sb : strbuf#, opts : intparams, signed : bool, bits : uint64, nbits : uint64 -> void)
;;

const digitchars = "0123456789abcdef"
const intfmt = {sb : strbuf#, opts : intparams, signed : bool, bits : uint64, nbits : uint64
	var isneg
	var sval, val
	var b : byte[64]
	var i, j, npad
	var base

	base = (opts.base : uint64)
	if signed && bits >= 1 << (nbits - 1)
		sval = -(bits : int64)
		val = (sval : uint64)
		isneg = true

		/* if its negative after inverting, we have int64 min */
		if sval < 0
			std.sbputs(sb, "-9223372036854775808")
			-> void
		;;
	else
		val = (bits : uint64)
		val &= ~0 >> nbits
		isneg = false
	;;

	i = 0
	if val == 0
		b[0] = ('0' : byte)
		i++
	;;
	while val != 0
		b[i] = digitchars[val % base]
		val /= base
		i++
	;;

	npad = clamp(opts.padto - i, 0, opts.padto)
	if isneg
		npad--
	;;
	if opts.padfill == '0' && isneg
		sbputb(sb, ('-' : byte))
	;;
	for j = 0; j < npad; j++
		sbputc(sb, opts.padfill)
	;;
	if opts.padfill != '0' && isneg
		sbputb(sb, ('-' : byte))
	;;
	for j = i; j != 0; j--
		sbputb(sb, b[j - 1])
	;;
}

/* would use std.get(), but that's a dependency loop */
const getint = {s, msg
	match std.intparse(s)
	| `Some w:	-> w;
	| `None:	die(msg)
	;;
}