parsav  Artifact [f642fd73ba]

Artifact f642fd73baa77a6f01ac6349a176528fcc8ce7f70433ad715cdbc9a52b3b3941:


-- 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

terra m.hexdigit(hb: uint8): int8
	var a = hb and 0x0F
	if a < 10 then return 0x30 + a
	else return 0x61 + (a-10) end
end

terra m.hexbyte(b: uint8): int8[2]
	return array(m.hexdigit((b and 0xF0) >> 4), m.hexdigit(b and 0x0F))
end

terra m.hexstr(src: &uint8, str: rawstring, sz: intptr)
	for i = 0, sz do
		var d = m.hexbyte(src[i])
		str[i*2] = d[0]
		str[i*2 + 1] = d[1]
	end
end

terra m.b32char(v: uint8): int8
	if v <= 25 then return 0x61 + v
	elseif v < 31 then return 0x32 + (v-26)
	else return 0 end
end

terra m.b32(v: uint64, buf: rawstring) -- 5 bytes -> 8 chars
	while v > 0 do
		var val = v % 32
		v = v / 32
		@buf = m.b32char(val)
		buf = buf + 1
	end
end

terra m.b32str(a: lib.mem.ptr(uint64))
	
end

return m