res = rspamd_regexp_new (pattern, flags, err);
if (res) {
+ REF_RETAIN (res);
g_hash_table_insert (cache->tbl, res->id, res);
}
return res;
}
+gboolean
+rspamd_regexp_cache_remove (struct rspamd_regexp_cache *cache,
+ rspamd_regexp_t *re)
+{
+ if (cache == NULL) {
+ cache = global_re_cache;
+ }
+
+ g_assert (cache != NULL);
+ g_assert (re != NULL);
+
+ return g_hash_table_remove (cache->tbl, re->id);
+}
+
void
rspamd_regexp_cache_destroy (struct rspamd_regexp_cache *cache)
{
const gchar *pattern,
const gchar *flags, GError **err);
+/**
+ * Remove regexp from the cache
+ * @param cache regexp cache. if NULL, the superglobal cache is used (*not* thread-safe)
+ * @param re re to remove
+ * @return TRUE if a regexp has been removed
+ */
+gboolean rspamd_regexp_cache_remove (struct rspamd_regexp_cache *cache,
+ rspamd_regexp_t *re);
+
/**
* Destroy regexp cache and unref all elements inside it
* @param cache
{
struct rspamd_lua_regexp *re = lua_check_regexp (L);
const gchar *data;
- gchar **parts;
+ gboolean matched = FALSE;
+ gsize len;
+ const gchar *start = NULL, *end = NULL, *old_start;
gint i;
if (re) {
- data = luaL_checkstring (L, 2);
+ data = luaL_checklstring (L, 2, &len);
if (data) {
- if ((re->re_flags & G_REGEX_RAW) == 0) {
- /* Validate input */
- if (!g_utf8_validate (data, -1, NULL)) {
- lua_pushnil (L);
- return 1;
+ lua_newtable (L);
+ i = 0;
+ old_start = data;
+ while (rspamd_regexp_search (re->re, data, len, &start, &end, FALSE)) {
+ if (start - old_start > 0) {
+ lua_pushlstring (L, old_start, start - old_start);
+ lua_rawseti (L, -2, ++i);
+ matched = TRUE;
}
+ old_start = end;
}
- parts = g_regex_split (re->re, data, 0);
- lua_newtable (L);
- for (i = 1; parts[i - 1] != NULL; i++) {
- lua_pushstring (L, parts[i - 1]);
- lua_rawseti (L, -2, i);
+ if (!matched) {
+ lua_pop (L, 1);
+ lua_pushnil (L);
}
- g_strfreev (parts);
return 1;
}
}
struct rspamd_lua_regexp *to_del = lua_check_regexp (L);
if (to_del) {
- re_cache_del (to_del->re_pattern, regexp_static_pool);
+ rspamd_regexp_cache_remove (NULL, to_del->re);
rspamd_regexp_unref (to_del->re);
g_slice_free1 (sizeof (struct rspamd_lua_regexp), to_del);
}
for _,c in ipairs(cases) do
local r = re.create_cached(c[1])
- assert_not_nil(r)
+ assert_not_nil(r, "cannot parse " .. c[1])
local res = r:match(c[2])
assert_equal(res, c[3], string.format("'%s' doesn't match with '%s'",
c[2], c[1]))
end
end)
+
+ test("Regexp split", function()
+ local cases = {
+ {'\\s', 'one two', {'one', 'two'}}, -- trivial
+ {'\\s', 'one two', {'one', 'two'}}, -- multiple delimiters
+ {'\\s', ' one two ', {'one', 'two'}}, -- multiple delimiters
+ {'\\s', ' one ', {'one', 'two'}}, -- multiple delimiters
+ {'[:,]', ',,,:::one,two,,', {'one', 'two'}}, -- multiple delimiters
+ }
+
+ for _,c in ipairs(cases) do
+ local r = re.create_cached(c[1])
+ assert_not_nil(r, "cannot parse " .. c[1])
+
+ local res = r:split(c[2])
+ assert_not_nil(res, "cannot split " .. c[2])
+
+ for i,r in ipairs(res) do
+ assert_equal(r, c[3][i])
+ end
+ end
+ end)
+
end
)
\ No newline at end of file