parsav  math.t at [df4ae251ef]

File math.t artifact fe958b6645 part of check-in df4ae251ef


-- vim: ft=terra
local m = {
	shorthand = {maxlen = 14}
}

-- swap in place -- faster on little endian
m.netswap_ip = macro(function(ty, src, dest)
	if ty:astype().type ~= 'integer' then error('bad type') end
	local bytes = ty:astype().bytes
	src = `[&uint8](src)
	dest = `[&uint8](dest)
	if config.endian == 'little' then
		return quote for i = 0, bytes do dest[i] = src[bytes - (i+1)] end end
	elseif config.endian == 'big' then
		return quote for i = 0, bytes do dest[i] = src[i] end end
	else error('unknown endianness '..config.endian) end
end)

-- swap out of place -- safer, more flexible, and optimized to an intrinsic call; trivial on big endian
m.netswap = macro(function(tyq, src)
	if config.endian == 'little' then
		local ty = tyq:astype()
		local a,b = symbol(ty), symbol(ty)
		local bytes = ty.bytes
		local steps = {}
		for i=0,bytes-1 do
			steps[#steps + 1] = quote
				b = b << 8
				b = b or (a and 0xff)
				a = a >> 8
			end
		end
		return quote
			var [a] = src
			var [b] = 0
			[steps]
		in b end
	elseif config.endian == 'big' then return `src
	else error('unknown endianness '..config.endian) end
end)

terra m.shorthand.cval(character: int8): {uint8, bool}
	var ch = [uint8](character)

	if ch >= 0x30 and ch <= 0x39 then
		ch = 00 + (ch - 0x30)
	elseif ch == 0x2d then ch = 10
	elseif ch >= 0x41 and ch <= 0x5a then
		ch = 11 + (ch - 0x41)
	elseif ch == 0x3a then ch = 37
	elseif ch >= 0x61 and ch <= 0x7a then
		ch = 38 + (ch - 0x61)
	else return 0, false end

	return ch, true 
end

terra m.shorthand.gen(val: uint64, dest: rawstring): ptrdiff
	var lst = "0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ:abcdefghijklmnopqrstuvwxyz"
	var buf: int8[m.shorthand.maxlen]
	var ptr = [&int8](buf)
	while val ~= 0 do
		var v = val % 64
		@ptr = lst[v]
		ptr = ptr + 1
		val = val / 64
	end
	var len = ptr - buf
	for i = 0, len do
		dest[i] = buf[len - (i+1)]
	end
	dest[len] = 0
	return len
end

terra m.shorthand.parse(s: rawstring, len: intptr): {uint64, bool}
	var val: uint64 = 0
	for i = 0, len do
		var v, ok = m.shorthand.cval(s[i])
		if ok == false then return 0, false end
		val = (val * 64) + v
	end
	return val, true
end

return m