~kvik/lu9-p9

9d97d20f6fa95b1f6ca455ac6a277b3bced5eb1c — kvik 1 year, 2 days ago 9ddcbf1
misc: implement p9.{enc,dec}{16,32,64} bindings
3 files changed, 96 insertions(+), 0 deletions(-)

M base/base.c
M base/misc.c
M test/test.lua
M base/base.c => base/base.c +7 -0
@@ 53,6 53,13 @@ static luaL_Reg p9_module[] = {
	{"nsec", p9_nsec},
	{"cleanname", p9_cleanname},
	
	{"enc64", p9_enc64},
	{"dec64", p9_dec64},
	{"enc32", p9_enc32},
	{"dec32", p9_dec32},
	{"enc16", p9_enc16},
	{"dec16", p9_dec16},
	
	{nil, nil}
};


M base/misc.c => base/misc.c +72 -0
@@ 58,3 58,75 @@ p9_nsec(lua_State *L)
	lua_pushinteger(L, nsec());
	return 1;
}

static int
decode(lua_State *L, int base)
{
	const char *in;
	char *buf;
	usize insz, bufsz, sz;
	luaL_Buffer b;
	int (*dec)(uchar*, int, char*, int);
	
	in = luaL_checklstring(L, 1, &insz);
	buf = luaL_buffinitsize(L, &b, insz+1);
	switch(base){
	case 64:
		dec = dec64;
		bufsz = 6 * (insz + 3) / 8;
		break;
	case 32:
		dec = dec32;
		bufsz = 5 * (insz + 7) / 8;
		break;
	case 16:
		dec = dec16;
		bufsz = 4 * (insz + 1) / 8;
		break;
	default:
		return error(L, "unsupported base");
	}
	if((sz = dec((uchar*)buf, bufsz, in, insz)) == -1)
		return error(L, "dec: failed");
	luaL_pushresultsize(&b, sz);
	return 1;
}
static int p9_dec64(lua_State *L) { return decode(L, 64); }
static int p9_dec32(lua_State *L) { return decode(L, 32); }
static int p9_dec16(lua_State *L) { return decode(L, 16); }

static int
encode(lua_State *L, int base)
{
	const char *in;
	char *buf;
	usize insz, bufsz, sz;
	luaL_Buffer b;
	int (*enc)(char*, int, uchar*, int);
	
	in = luaL_checklstring(L, 1, &insz);
	switch(base){
	case 64:
		enc = enc64;
 		bufsz = (insz + 3) * 8 / 6;
		break;
	case 32:
		enc = enc32;
 		bufsz = (insz + 7) * 8 / 5;
		break;
	case 16:
		enc = enc16;
 		bufsz = (insz + 1) * 8 / 4;
		break;
	default:
		return error(L, "unsupported base");
	}
	buf = luaL_buffinitsize(L, &b, bufsz);
	if((sz = enc(buf, bufsz, (uchar*)in, insz)) == -1)
		return error(L, "enc: failed");
	luaL_pushresultsize(&b, sz);
	return 1;
}
static int p9_enc64(lua_State *L) { return encode(L, 64); }
static int p9_enc32(lua_State *L) { return encode(L, 32); }
static int p9_enc16(lua_State *L) { return encode(L, 16); }

M test/test.lua => test/test.lua +17 -0
@@ 308,6 308,23 @@ do
	assert(p9.cleanname("/usr///./glenda/.") == "/usr/glenda")
end

-- baseN encode / decode
do
	t = {"", "h", "he", "hel", "hell", "hello", "hello ", "hello w", "hello wo", "hello wor", "hello worl", "hello world"}
	for _, s in ipairs(t) do
		local enc, dec
		s = string.rep(s, 100)
		enc = assert(p9.enc64(s))
		dec = assert(p9.dec64(enc))
		assert(dec == s)
		enc = assert(p9.enc32(s))
		dec = assert(p9.dec32(enc))
		assert(dec == s)
		enc = assert(p9.enc16(s))
		dec = assert(p9.dec16(enc))
		assert(dec == s)
	end
end