#include "lua.h"
#include "lauxlib.h"
#include "lpcap.h"
#include "lptypes.h"
#include <string.h>
#include <time.h>
#include "lptree.h"
#include "rpeg.h"
#include "ktable.h"
#include "ktable-macros.h"
#define check_bounds(s,e,n) do { \
if (*(s)+n > (e)) \
luaL_error(L, "corrupt match data (buffer overrun) by %d at %s:%d", \
(e) - *(s), \
__FILE__, __LINE__); \
} while (0);
static void pushmatch (lua_State *L, const char **s, const char *e, int depth) {
int top;
short shortlen;
int pos;
int n = 0;
check_bounds(s, e, 4);
pos = r_readint(s);
if ((pos) > 0) luaL_error(L, "corrupt match data (expected start marker)");
lua_checkstack(L, 4);
lua_createtable(L, 0, 5);
lua_pushliteral(L, "s");
lua_pushinteger(L, -(pos));
lua_rawset(L, -3);
check_bounds(s, e, 2);
shortlen = r_readshort(s);
if (shortlen <= 0) {
lua_pushliteral(L, "type");
lua_pushlstring(L, *s, (size_t) -shortlen);
lua_rawset(L, -3);
(*s) += -shortlen;
check_bounds(s, e, 2);
shortlen = r_readshort(s);
if (shortlen < 0) luaL_error(L, "corrupt match data (expected length of const cap data)");
lua_pushliteral(L, "data");
lua_pushlstring(L, *s, (size_t) shortlen);
lua_rawset(L, -3);
(*s) += shortlen;
check_bounds(s, e, 0);
} else {
lua_pushliteral(L, "type");
lua_pushlstring(L, *s, (size_t) shortlen);
lua_rawset(L, -3);
(*s) += shortlen;
check_bounds(s, e, 0);
}
top = lua_gettop(L);
while (r_peekint(*s) < 0) {
pushmatch(L, s, e, depth++);
n++;
}
if (n) {
lua_createtable(L, n, 0);
lua_insert(L, top+1);
for (int i=n; i>=1; i--) lua_rawseti(L, top+1, (lua_Integer) i);
lua_pushliteral(L, "subs");
lua_insert(L, -2);
lua_rawset(L, -3);
}
check_bounds(s, e, 4);
pos = r_readint(s);
lua_pushliteral(L, "e");
lua_pushinteger(L, pos);
lua_rawset(L, -3);
}
int r_lua_decode (lua_State *L) {
RBuffer *rbuf = (RBuffer *)luaL_checkudata(L, 1, ROSIE_BUFFER);
Buffer *buf = *rbuf;
const char *s = buf->data;
const char *e = buf->data + buf->n;
lua_Integer t0 = (lua_Integer) clock();
lua_Integer duration = luaL_optinteger(L, 2, 0);
if (buf->n == 0) {
lua_pushnil(L);
}
else {
pushmatch(L, &s, e, 0);
}
lua_pushinteger(L, ((lua_Integer) clock()-t0)+duration);
return 2;
}