shithub: lu9-p9

Download patch

ref: 9d97d20f6fa95b1f6ca455ac6a277b3bced5eb1c
parent: 9ddcbf1be2343ebb4d7853fecf8528e862def846
author: kvik <kvik@a-b.xyz>
date: Sat Aug 7 20:21:52 EDT 2021

misc: implement p9.{enc,dec}{16,32,64} bindings

--- a/base/base.c
+++ b/base/base.c
@@ -53,6 +53,13 @@
 	{"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}
 };
 
--- a/base/misc.c
+++ b/base/misc.c
@@ -58,3 +58,75 @@
 	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); }
--- a/test/test.lua
+++ b/test/test.lua
@@ -308,6 +308,23 @@
 	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