diff options
Diffstat (limited to 'epan/wslua/lrexlib/common.c')
-rw-r--r-- | epan/wslua/lrexlib/common.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/epan/wslua/lrexlib/common.c b/epan/wslua/lrexlib/common.c new file mode 100644 index 00000000..4d42de9c --- /dev/null +++ b/epan/wslua/lrexlib/common.c @@ -0,0 +1,331 @@ +/* common.c */ +/* + * Copyright (C) Reuben Thomas 2000-2020 + * Copyright (C) Shmuel Zeigerman 2004-2020 + + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the + * Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS + * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <wireshark.h> +DIAG_OFF_CLANG(shorten-64-to-32) +#ifdef _MSC_VER +/* disable: " warning C4244: '=': conversion from 'lua _Integer' to 'int', + * possible loss of data" */ +#pragma warning(disable:4244) +/* warning C4267: '+=': conversion from 'size_t' to 'int', + * possible loss of data */ +#pragma warning(disable:4267) +#endif + +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include "lua.h" +#include "lauxlib.h" +#include "common.h" + +#define N_ALIGN sizeof(int) + +/* the table must be on Lua stack top */ +int get_int_field (lua_State *L, const char* field) +{ + int val; + lua_getfield (L, -1, field); + val = lua_tointeger (L, -1); + lua_pop (L, 1); + return val; +} + +/* the table must be on Lua stack top */ +void set_int_field (lua_State *L, const char* field, int val) +{ + lua_pushinteger (L, val); + lua_setfield (L, -2, field); +} + +void *Lmalloc(lua_State *L, size_t size) { + void *ud; + lua_Alloc lalloc = lua_getallocf(L, &ud); + return lalloc(ud, NULL, 0, size); +} + +void *Lrealloc(lua_State *L, void *p, size_t osize, size_t nsize) { + void *ud; + lua_Alloc lalloc = lua_getallocf(L, &ud); + return lalloc(ud, p, osize, nsize); +} + +void Lfree(lua_State *L, void *p, size_t osize) { + void *ud; + lua_Alloc lalloc = lua_getallocf(L, &ud); + lalloc(ud, p, osize, 0); +} + +/* This function fills a table with string-number pairs. + The table can be passed as the 1-st lua-function parameter, + otherwise it is created. The return value is the filled table. +*/ +int get_flags (lua_State *L, const flag_pair **arrs) { + const flag_pair *p; + const flag_pair **pp; + int nparams = lua_gettop(L); + + if(nparams == 0) + lua_newtable(L); + else { + if(!lua_istable(L, 1)) + luaL_argerror(L, 1, "not a table"); + if(nparams > 1) + lua_pushvalue(L, 1); + } + + for(pp=arrs; *pp; ++pp) { + for(p=*pp; p->key; ++p) { + lua_pushstring(L, p->key); + lua_pushinteger(L, p->val); + lua_rawset(L, -3); + } + } + return 1; +} + +const char *get_flag_key (const flag_pair *fp, int val) { + for (; fp->key; ++fp) { + if (fp->val == val) + return fp->key; + } + return NULL; +} + +/* Classes */ + +/* + * class TFreeList + * *************** + * Simple array of pointers to TBuffer's. + * The array has fixed capacity (not expanded automatically). + */ + +void freelist_init (TFreeList *fl) { + fl->top = 0; +} + +void freelist_add (TFreeList *fl, TBuffer *buf) { + fl->list[fl->top++] = buf; +} + +void freelist_free (TFreeList *fl) { + while (fl->top > 0) + buffer_free (fl->list[--fl->top]); +} + +/* + * class TBuffer + * ************* + * Auto-extensible array of characters for building long strings incrementally. + * * Differs from luaL_Buffer in that: + * * its operations do not change Lua stack top position + * * buffer_addvalue does not extract the value from Lua stack + * * buffer_pushresult does not have to be the last operation + * * Uses TFreeList class: + * * for inserting itself into a TFreeList instance for future clean-up + * * calls freelist_free prior to calling luaL_error. + * * Has specialized "Z-operations" for maintaining mixed string/integer + * array: bufferZ_addlstring, bufferZ_addnum and bufferZ_next. + * * if the array is intended to be "mixed", then the methods + * buffer_addlstring and buffer_addvalue must not be used + * (the application will crash on bufferZ_next). + * * conversely, if the array is not intended to be "mixed", + * then the method bufferZ_next must not be used. + */ + +enum { ID_NUMBER, ID_STRING }; + +void buffer_init (TBuffer *buf, size_t sz, lua_State *L, TFreeList *fl) { + buf->arr = (char*) Lmalloc(L, sz); + if (!buf->arr) { + freelist_free (fl); + luaL_error (L, "malloc failed"); + } + buf->size = sz; + buf->top = 0; + buf->L = L; + buf->freelist = fl; + freelist_add (fl, buf); +} + +void buffer_free (TBuffer *buf) { + Lfree(buf->L, buf->arr, buf->size); +} + +void buffer_clear (TBuffer *buf) { + buf->top = 0; +} + +void buffer_pushresult (TBuffer *buf) { + lua_pushlstring (buf->L, buf->arr, buf->top); +} + +void buffer_addbuffer (TBuffer *trg, TBuffer *src) { + buffer_addlstring (trg, src->arr, src->top); +} + +void buffer_addlstring (TBuffer *buf, const void *src, size_t sz) { + size_t newtop = buf->top + sz; + if (newtop > buf->size) { + char *p = (char*) Lrealloc (buf->L, buf->arr, buf->size, 2 * newtop); /* 2x expansion */ + if (!p) { + freelist_free (buf->freelist); + luaL_error (buf->L, "realloc failed"); + } + buf->arr = p; + buf->size = 2 * newtop; + } + if (src) + memcpy (buf->arr + buf->top, src, sz); + buf->top = newtop; +} + +void buffer_addvalue (TBuffer *buf, int stackpos) { + size_t len; + const char *p = lua_tolstring (buf->L, stackpos, &len); + buffer_addlstring (buf, p, len); +} + +void bufferZ_addlstring (TBuffer *buf, const void *src, size_t len) { + int n; + size_t header[2] = { ID_STRING }; + header[1] = len; + buffer_addlstring (buf, header, sizeof (header)); + buffer_addlstring (buf, src, len); + n = len % N_ALIGN; + if (n) buffer_addlstring (buf, NULL, N_ALIGN - n); +} + +void bufferZ_addnum (TBuffer *buf, size_t num) { + size_t header[2] = { ID_NUMBER }; + header[1] = num; + buffer_addlstring (buf, header, sizeof (header)); +} + +/* 1. When called repeatedly on the same TBuffer, its existing data + is discarded and overwritten by the new data. + 2. The TBuffer's array is never shrunk by this function. +*/ +void bufferZ_putrepstring (TBuffer *BufRep, int reppos, int nsub) { + char dbuf[] = { 0, 0 }; + size_t replen; + const char *p = lua_tolstring (BufRep->L, reppos, &replen); + const char *end = p + replen; + BufRep->top = 0; + while (p < end) { + const char *q; + for (q = p; q < end && *q != '%'; ++q) + {} + if (q != p) + bufferZ_addlstring (BufRep, p, q - p); + if (q < end) { + if (++q < end) { /* skip % */ + if (g_ascii_isdigit (*q)) { + int num; + *dbuf = *q; + num = strtol (dbuf, NULL, 10); + if (num == 1 && nsub == 0) + num = 0; + else if (num > nsub) { + freelist_free (BufRep->freelist); + luaL_error (BufRep->L, "invalid capture index"); + } + bufferZ_addnum (BufRep, num); + } + else bufferZ_addlstring (BufRep, q, 1); + } + p = q + 1; + } + else break; + } +} + +/****************************************************************************** + The intended use of this function is as follows: + size_t iter = 0; + while (bufferZ_next (buf, &iter, &num, &str)) { + if (str) do_something_with_string (str, num); + else do_something_with_number (num); + } +******************************************************************************* +*/ +int bufferZ_next (TBuffer *buf, size_t *iter, size_t *num, const char **str) { + if (*iter < buf->top) { + size_t *ptr_header = (size_t*)(buf->arr + *iter); + *num = ptr_header[1]; + *iter += 2 * sizeof (size_t); + *str = NULL; + if (*ptr_header == ID_STRING) { + int n; + *str = buf->arr + *iter; + *iter += *num; + n = *iter % N_ALIGN; + if (n) *iter += (N_ALIGN - n); + } + return 1; + } + return 0; +} + +#if LUA_VERSION_NUM > 501 +int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} +#endif + +#ifndef REX_NOEMBEDDEDTEST +static int ud_topointer (lua_State *L) { + lua_pushlightuserdata (L, lua_touserdata (L, 1)); + return 1; +} + +static int ud_len (lua_State *L) { + lua_pushinteger (L, lua_objlen (L, 1)); + return 1; +} + +/* for testing purposes only */ +int newmembuffer (lua_State *L) { + size_t len; + const char* s = luaL_checklstring (L, 1, &len); + void *ud = lua_newuserdata (L, len); + memcpy (ud, s, len); + lua_newtable (L); /* metatable */ + lua_pushvalue (L, -1); + lua_setfield (L, -2, "__index"); /* metatable.__index = metatable */ + lua_pushcfunction (L, ud_topointer); + lua_setfield (L, -2, "topointer"); + lua_pushcfunction (L, ud_len); + lua_setfield (L, -2, "__len"); + lua_setmetatable (L, -2); + return 1; +} +#endif /* #ifndef REX_NOEMBEDDEDTEST */ |