ref: 4ca93982fdef1ddb426b5595f814f3099adfdc65
dir: /libstd/fmt2.myr/
use "alloc.use"
use "chartype.use"
use "die.use"
use "extremum.use"
use "fltfmt.use"
use "introspect.use"
use "strbuf.use"
use "syswrap-ss.use"
use "syswrap.use"
use "types.use"
use "utf.use"
use "varargs.use"
use "fmt.use" /* FOR DEBUGGING */
pkg std =
/* write to fd */
const f2put : (fmt : byte[:], args : ... -> size)
const f2fput : (fd : fd, fmt : byte[:], args : ... -> size)
const f2putv : (fmt : byte[:], ap : valist -> size)
const f2fputv : (fd : fd, fmt : byte[:], ap : valist -> size)
/* write to buffer */
const f2fmt : (fmt : byte[:], args : ... -> byte[:])
const f2fmtv : (fmt : byte[:], ap : valist -> byte[:])
const f2bfmt : (buf : byte[:], fmt : byte[:], args : ... -> byte[:])
const f2bfmtv : (buf : byte[:], fmt : byte[:], ap : valist -> byte[:])
/* write to strbuf */
const f2sbfmt : (buf : strbuf#, fmt : byte[:], args : ... -> size)
const f2sbfmtv : (buf : strbuf#, fmt : byte[:], ap : valist -> size)
$noret const f2fatal : (fmt : byte[:], args : ... -> void)
$noret const f2fatalv : (fmt : byte[:], ap : valist -> void)
;;
const f2put = {fmt, args
-> f2fputv(1, fmt, vastart(&args))
}
const f2putv = {fmt, ap
-> f2fputv(1, fmt, ap)
}
const f2fput = {fd, fmt, args
-> f2fputv(fd, fmt, vastart(&args))
}
const f2fputv = {fd, fmt, ap
var sb, s
sb = mksb()
f2sbfmtv(sb, fmt, ap)
s = sbfin(sb)
-> writeall(fd, s)
}
const f2fmt = {fmt, args
-> f2fmtv(fmt, vastart(&args))
}
const f2fmtv = {fmt, ap
var sb
sb = mksb()
f2sbfmtv(sb, fmt, ap)
-> sbfin(sb)
}
const f2bfmt = {buf, fmt, args
-> f2bfmtv(buf, fmt, vastart(&args))
}
const f2bfmtv = {buf, fmt, ap
var sb
sb = mkbufsb(buf)
f2sbfmtv(sb, fmt, ap)
-> sbfin(sb)
}
const f2sbfmt = {sb, fmt, args
-> f2sbfmtv(sb, fmt, vastart(&args))
}
const f2sbfmtv = {sb, fmt, ap -> size
var c, params
while fmt.len != 0
(c, fmt) = striter(fmt)
match c
| '%':
if fmt.len > 1 && fmt[0] == '{' castto(byte)
(params, fmt) = f2getparams(fmt[1:])
;;
ap = fallbackfmt(sb, params, vatype(ap), ap)
| chr:
sbputc(sb, chr)
;;
;;
-> sb.len
}
const fallbackfmt = {sb, params, tyenc, ap
/* value types */
var t_val : bool
var b_val : int8, ub_val : uint8
var w_val : int16, uw_val : uint16
var i_val : int32, ui_val : uint32
var l_val : int64, ul_val : uint64
var z_val : size
var p_val : byte#
var c_val : char
var s_val : byte[:]
var f32_val : flt32, f64_val : flt64
var i8 : int8, i16: int16, i32 : int32
var by : byte
var i : int, i64 : int64, l : long
var ui8 : int8, ui16: int16, ui32 : int32
var ui : int, ui64 : int64, ul : long
match typedesc(tyenc)
| `Tynone: /* nothing */
/* atomic types */
| `Tyvoid:
sbputs(sb, "void")
| `Tybool:
(t_val, ap) = vanext(ap)
if t_val
sbputs(sb ,"true")
else
sbputs(sb, "false")
;;
| `Tychar:
(c_val, ap) = vanext(ap)
sbputc(sb, c_val)
| `Tyint8:
(b_val, ap) = vanext(ap)
intfmt(sb, params, true, b_val)
| `Tyint16:
(w_val, ap) = vanext(ap)
intfmt(sb, params, true, w_val)
| `Tyint:
(i_val, ap) = vanext(ap)
intfmt(sb, params, true, i_val)
| `Tyint32:
(i_val, ap) = vanext(ap)
intfmt(sb, params, true, i_val)
| `Tyint64:
(l_val, ap) = vanext(ap)
intfmt(sb, params, true, l_val)
| `Tylong:
(l_val, ap) = vanext(ap)
intfmt(sb, params, true, l_val)
| `Tybyte:
(ub_val, ap) = vanext(ap)
intfmt(sb, params, false, ub_val)
| `Tyuint8:
(ub_val, ap) = vanext(ap)
intfmt(sb, params, false, ub_val)
| `Tyuint16:
(w_val, ap) = vanext(ap)
intfmt(sb, params, false, uw_val)
| `Tyuint:
(i_val, ap) = vanext(ap)
intfmt(sb, params, false, ui_val)
| `Tyuint32:
(i_val, ap) = vanext(ap)
intfmt(sb, params, false, ui_val)
| `Tyuint64:
(l_val, ap) = vanext(ap)
intfmt(sb, params, false, ul_val)
| `Tyulong:
(l_val, ap) = vanext(ap)
intfmt(sb, params, false, ul_val)
| `Tyflt32:
(l_val, ap) = vanext(ap)
sbputs(sb, "flt32")
| `Tyflt64:
sbputs(sb, "flt64")
| `Tyvalist:
sbputs(sb, "...")
/* compound types */
| `Typtr desc:
(p_val, ap) = vanext(ap)
intfmt(sb, params, false, p_val castto(intptr))
| `Tyslice desc:
match typedesc(desc)
| `Tybyte:
(s_val, ap) = vanext(ap)
sbputs(sb, s_val)
| _:
sbputs(sb, "slice[:]")
;;
| `Tyfunc tc:
sbputs(sb, "func")
| `Tyarray (sz, data):
sbputs(sb, "array")
/* aggregate types */
| `Tytuple typecursor:
sbputs(sb, "tuple")
| `Tystruct namecursor:
sbputs(sb, "struct")
| `Tyunion namecursor:
sbputs(sb, "struct")
| `Tyname (name, desc):
ap = fallbackfmt(sb, params, desc, ap)
;;
-> ap
}
const f2getparams = {fmt
var i
for i = 0; i < fmt.len; i++
if fmt[i] == '}' castto(byte)
goto foundparams
;;
;;
die("invalid format string")
:foundparams
-> (fmt[:i], fmt[i+1:])
}
const digitchars = [
'0','1','2','3','4',
'5','6','7','8','9',
'a','b','c','d','e','f'
]
generic intfmt = {sb, opts, signed, bits : @a::(integral,numeric)
var isneg
var val
var b : char[32]
var i, j, npad
var base, padto, padfill
i = 0
base = 10
padto = 0
padfill = '0'
if signed && bits < 0
val = -bits castto(uint64)
isneg = true
else
val = bits castto(uint64)
val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a)))
isneg = false
;;
if val == 0
b[0] = '0'
i++
;;
while val != 0
b[i] = digitchars[val % base]
val /= base
i++
;;
npad = clamp(padto - i, 0, padto)
if isneg
npad--
;;
if padfill == '0' && isneg
sbputc(sb, '-')
;;
for j = 0; j < npad; j++
sbputc(sb, padfill)
;;
if padfill != '0' && isneg
sbputc(sb, '-')
;;
for j = i; j != 0; j--
sbputc(sb, b[j - 1])
;;
}
const writeall = {fd, buf
var n, len
len = 0
while true
n = write(fd, buf)
if n <= 0 || n >= len
break
;;
len += n
;;
-> len
}