diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-05-13 16:02:55 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-05-13 16:35:43 +0100 |
commit | 2c9a6cfca599bba34075baba133edb156a861c07 (patch) | |
tree | 7c44fa01ca8373e11e26ad3f939efa7462101286 | |
parent | 3dfad0da61cb1bd1b68f9f456d051da3f77996a9 (diff) | |
download | rspamd-2c9a6cfca599bba34075baba133edb156a861c07.tar.gz rspamd-2c9a6cfca599bba34075baba133edb156a861c07.zip |
[Project] Add text:sub method
-rw-r--r-- | src/lua/lua_text.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/lua/lua_text.c b/src/lua/lua_text.c index 046d6ff5c..d1cf14c6f 100644 --- a/src/lua/lua_text.c +++ b/src/lua/lua_text.c @@ -92,6 +92,12 @@ LUA_FUNCTION_DEF (text, save_in_file); */ LUA_FUNCTION_DEF (text, span); /*** + * @method rspamd_text:sub(start[, len]) + * Returns a substrin for lua_text similar to string.sub from Lua + * @return {rspamd_text} new rspamd_text with span (must be careful when using with owned texts...) + */ +LUA_FUNCTION_DEF (text, sub); +/*** * @method rspamd_text:lines([stringify]) * Returns an iter over all lines as rspamd_text objects or as strings if `stringify` is true * @param {boolean} stringify stringify lines @@ -196,6 +202,7 @@ static const struct luaL_reg textlib_m[] = { LUA_INTERFACE_DEF (text, take_ownership), LUA_INTERFACE_DEF (text, save_in_file), LUA_INTERFACE_DEF (text, span), + LUA_INTERFACE_DEF (text, sub), LUA_INTERFACE_DEF (text, lines), LUA_INTERFACE_DEF (text, split), LUA_INTERFACE_DEF (text, at), @@ -556,6 +563,68 @@ lua_text_span (lua_State *L) return 1; } +/* Helpers to behave exactly as Lua does */ +static inline gsize +relative_pos_start (gint pos, gsize len) +{ + if (pos > 0) { + return pos; + } + else if (pos == 0) { + return 1; + } + else if (pos < -((gint) len)) { + return 1; + } + + /* Negative pos inside str */ + return len + ((gsize)pos) + 1; +} + +static inline gsize +relative_pos_end (gint pos, gsize len) +{ + if (pos > (gint)len) { + return len; + } + else if (pos >= 0) { + return (size_t) pos; + } + else if (pos < -((gint)len)) { + return 0; + } + + return len + ((gsize)pos) + 1; +} + +static gint +lua_text_sub (lua_State *L) +{ + LUA_TRACE_POINT; + struct rspamd_lua_text *t = lua_check_text (L, 1); + + if (t) { + size_t start = relative_pos_start (luaL_checkinteger (L, 2), + t->len); + size_t end = relative_pos_end (luaL_optinteger (L, 3, -1), + t->len); + + + if (start <= end) { + lua_new_text (L, t->start + (start - 1), + (end - start) + 1, FALSE); + } + else { + lua_new_text (L, "", 0, TRUE); + } + } + else { + return luaL_error (L, "invalid arguments"); + } + + return 1; +} + static gint64 rspamd_lua_text_push_line (lua_State *L, struct rspamd_lua_text *t, |