MINOR: hlua: Add regex class
This patch simply brings HAProxy internal regex system to the Lua API. Lua doesn't embed regexes, now it inherits from the regexes compiled with haproxy.
This commit is contained in:
parent
46c72551f3
commit
31904278dc
|
@ -1890,6 +1890,70 @@ Socket class
|
|||
:param class_socket socket: Is the manipulated Socket.
|
||||
:param integer value: The timeout value.
|
||||
|
||||
.. _regex_class:
|
||||
|
||||
Regex class
|
||||
===========
|
||||
|
||||
.. js:class:: Regex
|
||||
|
||||
This class allows the usage of HAProxy regexes because classic lua doesn't
|
||||
provides regexes. This class inherits the HAProxy compilation options, so the
|
||||
regexes can be libc regex, pcre regex or pcre JIT regex.
|
||||
|
||||
The expression matching number is limited to 20 per regex. The only available
|
||||
option is case sensitive.
|
||||
|
||||
Because regexes compilation is a heavy process, it is better to define all
|
||||
your regexes in the **body context** and use it during the runtime.
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
-- Create the regex
|
||||
st, regex = Regex.new("needle (..) (...)", true);
|
||||
|
||||
-- Check compilation errors
|
||||
if st == false then
|
||||
print "error: " .. regex
|
||||
end
|
||||
|
||||
-- Match the regexes
|
||||
print(regex:exec("Looking for a needle in the haystack")) -- true
|
||||
print(regex:exec("Lokking for a cat in the haystack")) -- false
|
||||
|
||||
-- Extract words
|
||||
st, list = regex:match("Looking for a needle in the haystack")
|
||||
print(st) -- true
|
||||
print(list[1]) -- needle in the
|
||||
print(list[2]) -- in
|
||||
print(list[3]) -- the
|
||||
|
||||
.. js:function:: Regex.new(regex, case_sensitive)
|
||||
|
||||
Create and compile a regex.
|
||||
|
||||
:param string regex: The regular expression according with the libc or pcre
|
||||
standard
|
||||
:param boolean case_sensitive: Match is case sensitive or not.
|
||||
:returns: boolean status and :ref:`regex_class` or string containing fail reason.
|
||||
|
||||
.. js:function:: Regex.exec(regex, str)
|
||||
|
||||
Execute the regex.
|
||||
|
||||
:param class_regex regex: A :ref:`regex_class` object.
|
||||
:param string str: The input string will be compared with the compiled regex.
|
||||
:returns: a boolean status according with the match result.
|
||||
|
||||
.. js:function:: Regex.match(regex, str)
|
||||
|
||||
Execute the regex and return matched expressions.
|
||||
|
||||
:param class_map map: A :ref:`regex_class` object.
|
||||
:param string str: The input string will be compared with the compiled regex.
|
||||
:returns: a boolean status according with the match result, and
|
||||
a table containing all the string matched in order of declaration.
|
||||
|
||||
.. _map_class:
|
||||
|
||||
Map class
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define CLASS_PROXY "Proxy"
|
||||
#define CLASS_SERVER "Server"
|
||||
#define CLASS_LISTENER "Listener"
|
||||
#define CLASS_REGEX "Regex"
|
||||
|
||||
struct stream;
|
||||
|
||||
|
|
103
src/hlua_fcn.c
103
src/hlua_fcn.c
|
@ -36,6 +36,7 @@ static int class_concat_ref;
|
|||
static int class_proxy_ref;
|
||||
static int class_server_ref;
|
||||
static int class_listener_ref;
|
||||
static int class_regex_ref;
|
||||
|
||||
#define STATS_LEN (MAX((int)ST_F_TOTAL_FIELDS, (int)INF_TOTAL_FIELDS))
|
||||
|
||||
|
@ -1076,6 +1077,90 @@ int hlua_match_addr(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct my_regex *hlua_check_regex(lua_State *L, int ud)
|
||||
{
|
||||
return (hlua_checkudata(L, ud, class_regex_ref));
|
||||
}
|
||||
|
||||
static int hlua_regex_comp(struct lua_State *L)
|
||||
{
|
||||
struct my_regex *regex;
|
||||
const char *str;
|
||||
int cs;
|
||||
char *err;
|
||||
|
||||
str = luaL_checkstring(L, 1);
|
||||
luaL_argcheck(L, lua_isboolean(L, 2), 2, NULL);
|
||||
cs = lua_toboolean(L, 2);
|
||||
|
||||
regex = lua_newuserdata(L, sizeof(*regex));
|
||||
|
||||
err = NULL;
|
||||
if (!regex_comp(str, regex, cs, 1, &err)) {
|
||||
lua_pushboolean(L, 0); /* status error */
|
||||
lua_pushstring(L, err); /* Reason */
|
||||
free(err);
|
||||
return 2;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, 1); /* Status ok */
|
||||
|
||||
/* Create object */
|
||||
lua_newtable(L);
|
||||
lua_pushvalue(L, -3); /* Get the userdata pointer. */
|
||||
lua_rawseti(L, -2, 0);
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, class_regex_ref);
|
||||
lua_setmetatable(L, -2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int hlua_regex_exec(struct lua_State *L)
|
||||
{
|
||||
struct my_regex *regex;
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
regex = hlua_check_regex(L, 1);
|
||||
str = luaL_checklstring(L, 2, &len);
|
||||
|
||||
lua_pushboolean(L, regex_exec2(regex, (char *)str, len));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hlua_regex_match(struct lua_State *L)
|
||||
{
|
||||
struct my_regex *regex;
|
||||
const char *str;
|
||||
size_t len;
|
||||
regmatch_t pmatch[20];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
regex = hlua_check_regex(L, 1);
|
||||
str = luaL_checklstring(L, 2, &len);
|
||||
|
||||
ret = regex_exec_match2(regex, (char *)str, len, 20, pmatch, 0);
|
||||
lua_pushboolean(L, ret);
|
||||
lua_newtable(L);
|
||||
if (ret) {
|
||||
for (i = 0; i < 20 && pmatch[i].rm_so != -1; i++) {
|
||||
lua_pushlstring(L, str + pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int hlua_regex_free(struct lua_State *L)
|
||||
{
|
||||
struct my_regex *regex;
|
||||
|
||||
regex = hlua_check_regex(L, 1);
|
||||
regex_free(regex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hlua_fcn_reg_core_fcn(lua_State *L)
|
||||
{
|
||||
if (!hlua_concat_init(L))
|
||||
|
@ -1092,6 +1177,24 @@ int hlua_fcn_reg_core_fcn(lua_State *L)
|
|||
hlua_class_function(L, "match_addr", hlua_match_addr);
|
||||
hlua_class_function(L, "tokenize", hlua_tokenize);
|
||||
|
||||
/* Create regex object. */
|
||||
lua_newtable(L);
|
||||
hlua_class_function(L, "new", hlua_regex_comp);
|
||||
|
||||
lua_newtable(L); /* The metatable. */
|
||||
lua_pushstring(L, "__index");
|
||||
lua_newtable(L);
|
||||
hlua_class_function(L, "exec", hlua_regex_exec);
|
||||
hlua_class_function(L, "match", hlua_regex_match);
|
||||
lua_rawset(L, -3); /* -> META["__index"] = TABLE */
|
||||
hlua_class_function(L, "__gc", hlua_regex_free);
|
||||
|
||||
lua_pushvalue(L, -1); /* Duplicate the metatable reference. */
|
||||
class_regex_ref = hlua_register_metatable(L, CLASS_REGEX);
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, CLASS_REGEX); /* Create global object called Regex */
|
||||
|
||||
/* Create listener object. */
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "__index");
|
||||
|
|
Loading…
Reference in New Issue