* @example
* local rspamd_regexp = require "rspamd_regexp"
*
- * local re = rspamd_regexp.create_cached('/^\\s*some_string\\s*^/i')
+ * local re = rspamd_regexp.create_cached('/^\\s*some_string\\s*$/i')
* re:match('some_string')
- * -- Required since regexp are optimized to be stored in the cache
- * re:destroy()
- *
- * -- Or it is possible to use metatable if re is an element of some table
- * local tbl = {}
- * tbl['key'] = rspamd_regexp.create_cached('.*')
- * setmetatable(tbl, {
- * __gc = function(t) t:destroy() end
- * })
+ * local re = rspamd_regexp.create_cached('/\\s+/i')
+ * re:split('word word word') -- returns ['word', 'word', 'word']
*/
LUA_FUNCTION_DEF (regexp, create);
LUA_FUNCTION_DEF (regexp, match);
LUA_FUNCTION_DEF (regexp, split);
LUA_FUNCTION_DEF (regexp, destroy);
+LUA_FUNCTION_DEF (regexp, gc);
static const struct luaL_reg regexplib_m[] = {
LUA_INTERFACE_DEF (regexp, get_pattern),
LUA_INTERFACE_DEF (regexp, split),
LUA_INTERFACE_DEF (regexp, destroy),
{"__tostring", lua_regexp_get_pattern},
+ {"__gc", lua_regexp_gc},
{NULL, NULL}
};
static const struct luaL_reg regexplib_f[] = {
{NULL, NULL}
};
+#define LUA_REGEXP_FLAG_DESTROYED (1 << 0)
+#define IS_DESTROYED(re) ((re)->re_flags & LUA_REGEXP_FLAG_DESTROYED)
+
rspamd_mempool_t *regexp_static_pool = NULL;
struct rspamd_lua_regexp {
g_error_free (err);
}
else {
- new = g_slice_alloc (sizeof (struct rspamd_lua_regexp));
+ new = g_slice_alloc0 (sizeof (struct rspamd_lua_regexp));
new->re = re;
pnew = lua_newuserdata (L, sizeof (struct rspamd_lua_regexp *));
rspamd_lua_setclass (L, "rspamd{regexp}", -1);
line = luaL_checkstring (L, 1);
re = rspamd_regexp_cache_query (NULL, line, NULL);
if (re) {
- new = g_slice_alloc (sizeof (struct rspamd_lua_regexp));
+ new = g_slice_alloc0 (sizeof (struct rspamd_lua_regexp));
new->re = re;
pnew = lua_newuserdata (L, sizeof (struct rspamd_lua_regexp *));
rspamd_lua_setclass (L, "rspamd{regexp}", -1);
line = luaL_checkstring (L, 1);
re = rspamd_regexp_cache_query (NULL, line, NULL);
if (re) {
- new = g_slice_alloc (sizeof (struct rspamd_lua_regexp));
+ new = g_slice_alloc0 (sizeof (struct rspamd_lua_regexp));
new->re = re;
pnew = lua_newuserdata (L, sizeof (struct rspamd_lua_regexp *));
{
struct rspamd_lua_regexp *re = lua_check_regexp (L);
- if (re && re->re) {
+ if (re && re->re && !IS_DESTROYED (re)) {
lua_pushstring (L, rspamd_regexp_get_pattern (re->re));
}
else {
gsize len;
gboolean matched = FALSE;
- if (re) {
+ if (re && !IS_DESTROYED (re)) {
data = luaL_checklstring (L, 2, &len);
if (data) {
lua_newtable (L);
gsize len = 0;
gboolean raw = FALSE;
- if (re) {
+ if (re && !IS_DESTROYED (re)) {
if (lua_type (L, 2) == LUA_TSTRING) {
data = luaL_checklstring (L, 2, &len);
}
const gchar *start = NULL, *end = NULL, *old_start;
gint i;
- if (re) {
+ if (re && !IS_DESTROYED (re)) {
data = luaL_checklstring (L, 2, &len);
if (data) {
lua_newtable (L);
/***
* @method re:destroy()
- * We are not using `__gc` meta-method as it is usually good idea to have
- * compiled regexps to be stored permanently, so this method can be used
- * for avoiding memory leaks for temporary regexps
+ * Destroy regexp from caches if needed (the pointer is removed by garbadge collector)
*/
static gint
lua_regexp_destroy (lua_State *L)
if (to_del) {
rspamd_regexp_cache_remove (NULL, to_del->re);
rspamd_regexp_unref (to_del->re);
- g_slice_free1 (sizeof (struct rspamd_lua_regexp), to_del);
+ to_del->re = NULL;
+ to_del->re_flags |= LUA_REGEXP_FLAG_DESTROYED;
+ }
+
+ return 0;
+}
+
+static gint
+lua_regexp_gc (lua_State *L)
+{
+ struct rspamd_lua_regexp *to_del = lua_check_regexp (L);
+
+ if (to_del) {
+ if (!IS_DESTROYED (to_del)) {
+ rspamd_regexp_unref (to_del->re);
+ }
+
+ g_slice_free1 (sizeof (*to_del), to_del);
}
return 0;
}
void
-luaopen_glib_regexp (lua_State * L)
+luaopen_regexp (lua_State * L)
{
luaL_newmetatable (L, "rspamd{regexp}");
lua_pushstring (L, "__index");