void
luaopen_cdb (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{cdb}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cdb}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cdblib_m);
- lua_pop (L, 1); /* remove metatable from stack */
-
+ rspamd_lua_new_class (L, "rspamd{cdb}", cdblib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cdb", lua_load_cdb);
}
return g_quark_from_static_string ("lua-routines");
}
+/* idea from daurnimator */
+#if defined(WITH_LUAJIT) && (defined(_LP64) || defined(_LLP64) || defined(__arch64__) || defined (__arm64__) || defined (__aarch64__) || defined(_WIN64))
+#define RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK 1
+#else
+#define RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK 0
+#endif
+
+#if RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK
+#define RSPAMD_LIGHTUSERDATA_MASK(p) ((void *)((uintptr_t)(p) & ((1UL<<47)-1)))
+#else
+#define RSPAMD_LIGHTUSERDATA_MASK(p) ((void *)(p))
+#endif
+
+/*
+ * Used to map string to a pointer
+ */
+KHASH_INIT (lua_class_set, const gchar *, bool, 0, rspamd_str_hash, rspamd_str_equal);
+khash_t (lua_class_set) *lua_classes = NULL;
+
/* Util functions */
/**
* Create new class and store metatable on top of the stack (must be popped if not needed)
const gchar *classname,
const struct luaL_reg *methods)
{
- luaL_newmetatable (L, classname); /* mt */
+ void *class_ptr;
+ khiter_t k;
+ gint r, nmethods = 0;
+
+ if (lua_classes == NULL) {
+ lua_classes = kh_init (lua_class_set);
+ }
+
+ k = kh_put (lua_class_set, lua_classes, classname, &r);
+ class_ptr = RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k));
+
+ if (methods) {
+ for (;;) {
+ if (methods[nmethods].name != NULL) {
+ nmethods ++;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ lua_createtable (L, 0, 3 + nmethods);
lua_pushstring (L, "__index");
lua_pushvalue (L, -2); /* pushes the metatable */
lua_settable (L, -3); /* metatable.__index = metatable */
- lua_pushstring (L, "class"); /* mt,"class" */
- lua_pushstring (L, classname); /* mt,"class",classname */
- lua_rawset (L, -3); /* mt */
+ lua_pushstring (L, "class");
+ lua_pushstring (L, classname);
+ lua_rawset (L, -3);
+
+ lua_pushstring (L, "class_ptr");
+ lua_pushlightuserdata (L, class_ptr);
+ lua_rawset (L, -3);
if (methods) {
luaL_register (L, NULL, methods); /* pushes all methods as MT fields */
}
- /* MT is left on stack ! */
-}
-/**
- * Create and register new class with static methods and store metatable on top of the stack
- */
-void
-rspamd_lua_new_class_full (lua_State *L,
- const gchar *classname,
- const gchar *static_name,
- const struct luaL_reg *methods,
- const struct luaL_reg *func)
-{
- rspamd_lua_new_class (L, classname, methods);
- luaL_register (L, static_name, func);
+ lua_pushvalue (L, -1); /* Preserves metatable */
+ lua_rawsetp (L, LUA_REGISTRYINDEX, class_ptr);
+ /* MT is left on stack ! */
}
static const gchar *
void
rspamd_lua_setclass (lua_State * L, const gchar *classname, gint objidx)
{
- luaL_getmetatable (L, classname);
+ khiter_t k;
+
+ k = kh_get (lua_class_set, lua_classes, classname);
+
+ g_assert (k != kh_end (lua_classes));
+ lua_rawgetp (L, LUA_REGISTRYINDEX,
+ RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
+
if (objidx < 0) {
objidx--;
}
void
rspamd_lua_table_set (lua_State * L, const gchar *index, const gchar *value)
{
-
lua_pushstring (L, index);
if (value) {
lua_pushstring (L, value);
lua_settop (L, 0);
#endif
- luaL_newmetatable (L, "rspamd{ev_base}");
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{ev_base}");
- lua_rawset (L, -3);
+ rspamd_lua_new_class (L, "rspamd{ev_base}", NULL);
lua_pop (L, 1);
- luaL_newmetatable (L, "rspamd{session}");
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{session}");
- lua_rawset (L, -3);
+ rspamd_lua_new_class (L, "rspamd{session}", NULL);
lua_pop (L, 1);
rspamd_lua_add_preload (L, "lpeg", luaopen_lpeg);
rspamd_lua_check_class (lua_State *L, gint index, const gchar *name)
{
gpointer p;
+ khiter_t k;
if (lua_type (L, index) == LUA_TUSERDATA) {
p = lua_touserdata (L, index);
if (p) {
if (lua_getmetatable (L, index)) {
- lua_getfield (L, LUA_REGISTRYINDEX, name); /* get correct metatable */
+ k = kh_get (lua_class_set, lua_classes, name);
+
+ if (k == kh_end (lua_classes)) {
+ lua_pop (L, 1);
+
+ return NULL;
+ }
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX,
+ RSPAMD_LIGHTUSERDATA_MASK (kh_value (lua_classes, k)));
+
if (lua_rawequal (L, -1, -2)) { /* does it have the correct mt? */
lua_pop (L, 2); /* remove both metatables */
return p;
{
void *p = lua_touserdata (L, pos);
guint i, top = lua_gettop (L);
+ khiter_t k;
if (p == NULL) {
goto err;
else {
/* Match class */
if (lua_getmetatable (L, pos)) {
- luaL_getmetatable (L, classname);
+ k = kh_get (lua_class_set, lua_classes, (gchar *)classname);
+
+ if (k == kh_end (lua_classes)) {
+ goto err;
+ }
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX,
+ RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
if (!lua_rawequal (L, -1, -2)) {
goto err;
const gchar *classname,
const struct luaL_reg *methods);
-/**
- * Create and register new class with static methods
- */
-void rspamd_lua_new_class_full (lua_State *L,
- const gchar *classname,
- const gchar *static_name,
- const struct luaL_reg *methods,
- const struct luaL_reg *func);
-
/**
* Set class name for object at @param objidx position
*/
void
luaopen_cryptobox (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{cryptobox_pubkey}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_pubkey}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxpubkeylib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_pubkey}", cryptoboxpubkeylib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_pubkey", lua_load_pubkey);
- luaL_newmetatable (L, "rspamd{cryptobox_keypair}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_keypair}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxkeypairlib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_keypair}", cryptoboxkeypairlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_keypair", lua_load_keypair);
- luaL_newmetatable (L, "rspamd{cryptobox_signature}");
-
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_signature}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxsignlib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_signature}", cryptoboxsignlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_signature", lua_load_signature);
- luaL_newmetatable (L, "rspamd{cryptobox_hash}");
-
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_hash}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxhashlib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_hash}", cryptoboxhashlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_hash", lua_load_hash);
rspamd_lua_add_preload (L, "rspamd_cryptobox", lua_load_cryptobox);
luaopen_dns_resolver (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{resolver}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{resolver}");
- lua_rawset (L, -3);
-
+ rspamd_lua_new_class (L, "rspamd{resolver}", dns_resolverlib_m);
{
LUA_ENUM (L, DNS_A, RDNS_REQUEST_A);
LUA_ENUM (L, DNS_PTR, RDNS_REQUEST_PTR);
LUA_ENUM (L, DNS_SOA, RDNS_REQUEST_SOA);
}
- luaL_register (L, NULL, dns_resolverlib_m);
- rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
+ lua_pop (L, 1);
- lua_pop (L, 1); /* remove metatable from stack */
+ rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
}
void
luaopen_expression (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{expr}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{expr}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, exprlib_m);
+ rspamd_lua_new_class (L, "rspamd{expr}", exprlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_expression", lua_load_expression);
-
- lua_pop (L, 1); /* remove metatable from stack */
}
void
luaopen_ip (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{ip}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{ip}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, iplib_m);
- rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
-
+ rspamd_lua_new_class (L, "rspamd{ip}", iplib_m);
lua_pop (L, 1);
+ rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
}
void
luaopen_mempool (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{mempool}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{mempool}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, mempoollib_m);
+ rspamd_lua_new_class (L, "rspamd{mempool}", mempoollib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_mempool", lua_load_mempool);
-
- lua_pop (L, 1); /* remove metatable from stack */
}
void
luaopen_redis (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{redis}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{redis}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, redislib_m);
+ rspamd_lua_new_class (L, "rspamd{redis}", redislib_m);
lua_pop (L, 1);
-
rspamd_lua_add_preload (L, "rspamd_redis", lua_load_redis);
}
void
luaopen_regexp (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{regexp}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{regexp}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, regexplib_m);
+ rspamd_lua_new_class (L, "rspamd{regexp}", regexplib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_regexp", lua_load_regexp);
if (regexp_static_pool == NULL) {
regexp_static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
"regexp_lua_pool");
}
-
- lua_settop (L, 0);
}
void
luaopen_rsa (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{rsa_pubkey}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_pubkey}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, rsapubkeylib_m);
+ rspamd_lua_new_class (L, "rspamd{rsa_pubkey}", rsapubkeylib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_rsa_pubkey", lua_load_pubkey);
- luaL_newmetatable (L, "rspamd{rsa_privkey}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_privkey}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, rsaprivkeylib_m);
+ rspamd_lua_new_class (L, "rspamd{rsa_privkey}", rsaprivkeylib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_rsa_privkey", lua_load_privkey);
- luaL_newmetatable (L, "rspamd{rsa_signature}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_signature}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, rsasignlib_m);
+ rspamd_lua_new_class (L, "rspamd{rsa_signature}", rsasignlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_rsa_signature", lua_load_signature);
rspamd_lua_add_preload (L, "rspamd_rsa", lua_load_rsa);
void
luaopen_sqlite3 (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{sqlite3}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{sqlite3}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, sqlitelib_m);
+ rspamd_lua_new_class (L, "rspamd{sqlite3}", sqlitelib_m);
lua_pop (L, 1);
- luaL_newmetatable (L, "rspamd{sqlite3_stmt}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{sqlite3_stmt}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, sqlitestmtlib_m);
+ rspamd_lua_new_class (L, "rspamd{sqlite3_stmt}", sqlitestmtlib_m);
lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_sqlite3", lua_load_sqlite3);
void
luaopen_trie (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{trie}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{trie}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, trielib_m);
+ rspamd_lua_new_class (L, "rspamd{trie}", trielib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_trie", lua_load_trie);
-
- lua_pop (L, 1); /* remove metatable from stack */
}
void
luaopen_upstream (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{upstream_list}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{upstream_list}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, upstream_list_m);
+ rspamd_lua_new_class (L, "rspamd{upstream_list}", upstream_list_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_upstream_list", lua_load_upstream_list);
- lua_pop (L, 1); /* remove metatable from stack */
-
- luaL_newmetatable (L, "rspamd{upstream}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{upstream}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, upstream_m);
-
- lua_pop (L, 1); /* remove metatable from stack */
+ rspamd_lua_new_class (L, "rspamd{upstream}", upstream_m);
+ lua_pop (L, 1);
}