shithub: libdraw.myr

ref: d180b70c6c69ffe8168cc8571772ad6e15ac6aba
dir: /pack.myr/

View raw version
use std
use sys

use "types"

pkg draw =
	const pack	: (dpy : display#, fmt : byte[:], vsz : std.size,  args : ... -> void)
	const flush	: (dpy : display# -> bool)
	const flushbuf	: (dpy : display# -> bool)
;;

const pack = {dpy, fmt, vsz, args
	var ap
	var sz, b, o

	ap = std.vastart(&args)
	sz = fixsize(fmt) + vsz
	b = ensure(dpy, sz)
	o = 0
	for c : fmt
		match (c : char)
		| 'b':
			b[o] = std.vanext(&ap)
			o += 1
		| 's':
			var v : int16 = std.vanext(&ap)
			std.putle16(b[o:o+2], v)
			o += 2
		| 'i':
			var v : int32 = std.vanext(&ap)
			std.putle32(b[o:o+4], v)
			o += 4
		| 'p':
			var p : point = std.vanext(&ap)
			std.putle32(b[o + 0:o + 4], p.x)
			std.putle32(b[o + 4:o + 8], p.y)
			o += 2*4
		| 'r':
			var r : rect = std.vanext(&ap)
			std.putle32(b[o+ 0:o+ 4], r.x0)
			std.putle32(b[o+ 4:o+ 8], r.y0)
			std.putle32(b[o+ 8:o+12], r.x1)
			std.putle32(b[o+12:o+16], r.y1)
			o += 4*4
		| 'S':
			var s : byte[:] = std.vanext(&ap)
			b[o++] = (s.len : byte)
			std.slcp(b[o:o+s.len], s)
			o += s.len
		| 'I':
			var s : int16[:] = std.vanext(&ap)
			for var i = 0; i < s.len; i++
				std.putle16(b[o:o+2], s[i])
				o += 2
			;;
		| 'd':
			var d : byte[:] = std.vanext(&ap)
			std.slcp(b[o:o+d.len], d)
			o += d.len
		| ' ':
			/* for readability of format strings */
		| chr:
			std.fatal("unknown specifier {} in pack\n", chr)
		;;
	;;
}

const fixsize = {fmt
	var sz

	sz = 0
	for c : fmt
		match (c : char)
		| 'b':	sz += 1
		| 's':	sz += 2
		| 'i':	sz += 4
		| 'r':	sz += 4*4
		| 'p':	sz += 2*4
		| _:	/* variable sizes */
		;;
	;;
	-> sz
}

const ensure = {dpy, sz
	var ret

	if dpy.bufoff + sz > dpy.buf.len
		flush(dpy)
	;;
	ret = dpy.buf[dpy.bufoff:dpy.bufoff + sz]
	dpy.bufoff += sz
	-> ret
}

const flush = {dpy

	/* five bytes always reserved here */
	dpy.buf[dpy.bufoff++] = ('v' : byte)
	-> flushbuf(dpy)
}
		
const flushbuf = {dpy
	var off, ret
	var errbuf : byte[128]

	off = 0
	ret = true
	while off != dpy.bufoff
		match std.write(dpy.datafd, dpy.buf[off:dpy.bufoff])
		| `std.Ok n:	off += n
		| `std.Err e:
			sys.errstr(errbuf[:])
			std.fatal("**error: {}\n", std.cstrconv(errbuf[:]))
			ret = false
			break
		;;
	;;
	dpy.bufoff = 0
	-> true
}