From 6f33ed9d04dfb7536ccca2599e79c4aaff6b1378 Mon Sep 17 00:00:00 2001 From: Reuben Thomas Date: Tue, 5 Aug 2014 16:40:03 +0100 Subject: Allow non-string, non-userdata subjects in Lua 5.1 --- doc/manual.txt | 10 +++++----- src/algo.h | 31 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/manual.txt b/doc/manual.txt index ab68394..f7d063c 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -38,15 +38,15 @@ Notes too. In this case, the cf_ and larg_ arguments are ignored (should be either supplied as nils or omitted). -6. All functions that take a string-type subject accept a table (in Lua >= 5.2) - or userdata that has a ``topointer`` method and ``__len`` metamethod, and - take the subject to be a block of memory starting at the address returned by +6. All functions that take a string-type subject accept a table or userdata that + has a ``topointer`` method and ``__len`` metamethod, and take the subject to + be a block of memory starting at the address returned by ``subject:topointer()`` and of length ``#subject``. This works with buffers objects from the alien library (https://github.com/mascarenhas/alien). Note that special attention is needed with POSIX regex libraries that do not support ``REG_STARTEND``, and hence need NUL-terminated subjects: the NUL is - not included in the string length, so alien buffers must be wrapped to - report a length that excludes the NUL. + not included in the string length, so alien buffers must be wrapped to report + a length that excludes the NUL. .. _cf: diff --git a/src/algo.h b/src/algo.h index 5d25330..3bea806 100644 --- a/src/algo.h +++ b/src/algo.h @@ -119,13 +119,8 @@ static void check_subject (lua_State *L, int pos, TArgExec *argE) int stype; argE->text = lua_tolstring (L, pos, &argE->textlen); stype = lua_type (L, pos); -#if LUA_VERSION_NUM == 501 - if (stype != LUA_TSTRING && stype != LUA_TUSERDATA) { - luaL_typerror (L, pos, "string or userdata"); -#else if (stype != LUA_TSTRING && stype != LUA_TTABLE && stype != LUA_TUSERDATA) { luaL_typerror (L, pos, "string, table or userdata"); -#endif } else if (argE->text == NULL) { int type; lua_getfield (L, pos, "topointer"); @@ -140,19 +135,23 @@ static void check_subject (lua_State *L, int pos, TArgExec *argE) argE->text = lua_touserdata (L, -1); lua_pop (L, 1); #if LUA_VERSION_NUM == 501 - if (!luaL_getmetafield (L, pos, "__len") || lua_type (L, -1) != LUA_TFUNCTION) - luaL_argerror (L, pos, "the userdata has no valid __len metafield"); - lua_pushvalue (L, pos); - lua_call (L, 1, 1); + if (stype == LUA_TSTRING || stype == LUA_TTABLE) + argE->textlen = lua_objlen (L, pos); + else { + if (!luaL_getmetafield (L, pos, "__len") || lua_type (L, -1) != LUA_TFUNCTION) + luaL_argerror (L, pos, "the userdata has no valid __len metafield"); + lua_pushvalue (L, pos); + lua_call (L, 1, 1); + type = lua_type (L, -1); + if (type != LUA_TNUMBER) + luaL_error (L, "subject's length is %s (expected number)", + lua_typename (L, type)); + argE->textlen = lua_tointeger (L, -1); + lua_pop (L, 1); + } #else - lua_len (L, pos); + argE->textlen = luaL_len (L, pos); #endif - type = lua_type (L, -1); - if (type != LUA_TNUMBER) - luaL_error (L, "subject's length is %s (expected number)", - lua_typename (L, type)); - argE->textlen = lua_tointeger (L, -1); - lua_pop (L, 1); } } -- cgit v1.2.1