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