summaryrefslogtreecommitdiffstats
path: root/epan/wslua/lrexlib/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/wslua/lrexlib/common.c')
-rw-r--r--epan/wslua/lrexlib/common.c331
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 0000000..4d42de9
--- /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 */