lib: Add decoder functions

Split existing lua_to* functions into two functions:
 - lua_decode_*: unmarshall Lua values into an existing C data structure
 - lua_to*: allocate *and* unmarshall Lua values into C data structure
This allows us to mutate C data structures passed into frrscript_call,
without allocation

Signed-off-by: Donald Lee <dlqs@gmx.com>
This commit is contained in:
Donald Lee 2021-06-20 08:25:22 +08:00
parent c2642aab24
commit 3a3cfe4762
3 changed files with 83 additions and 24 deletions

View File

@ -71,14 +71,17 @@ void lua_pushprefix(lua_State *L, const struct prefix *prefix)
lua_setfield(L, -2, "family");
}
void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix)
{
lua_getfield(L, idx, "network");
(void)str2prefix(lua_tostring(L, -1), prefix);
lua_pop(L, 1);
}
void *lua_toprefix(lua_State *L, int idx)
{
struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
lua_getfield(L, idx, "network");
(void)str2prefix(lua_tostring(L, -1), p);
lua_pop(L, 1);
lua_decode_prefix(L, idx, p);
return p;
}
@ -109,10 +112,8 @@ void lua_pushinterface(lua_State *L, const struct interface *ifp)
lua_setfield(L, -2, "linklayer_type");
}
void *lua_tointerface(lua_State *L, int idx)
void lua_decode_interface(lua_State *L, int idx, struct interface *ifp)
{
struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
lua_getfield(L, idx, "name");
strlcpy(ifp->name, lua_tostring(L, -1), sizeof(ifp->name));
lua_pop(L, 1);
@ -146,13 +147,19 @@ void *lua_tointerface(lua_State *L, int idx)
lua_getfield(L, idx, "linklayer_type");
ifp->ll_type = lua_tointeger(L, -1);
lua_pop(L, 1);
}
void *lua_tointerface(lua_State *L, int idx)
{
struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
lua_decode_interface(L, idx, ifp);
return ifp;
}
void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
{
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, addr, buf, sizeof(buf));
lua_newtable(L);
@ -162,14 +169,17 @@ void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
lua_setfield(L, -2, "string");
}
void *lua_toinaddr(lua_State *L, int idx)
void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *inaddr)
{
struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
lua_getfield(L, idx, "value");
inaddr->s_addr = lua_tointeger(L, -1);
lua_pop(L, 1);
}
void *lua_toinaddr(lua_State *L, int idx)
{
struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
lua_decode_inaddr(L, idx, inaddr);
return inaddr;
}
@ -177,6 +187,7 @@ void *lua_toinaddr(lua_State *L, int idx)
void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
{
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, addr, buf, sizeof(buf));
lua_newtable(L);
@ -186,20 +197,24 @@ void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
lua_setfield(L, -2, "string");
}
void *lua_toin6addr(lua_State *L, int idx)
void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *in6addr)
{
struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr));
lua_getfield(L, idx, "string");
inet_pton(AF_INET6, lua_tostring(L, -1), in6addr);
lua_pop(L, 1);
}
void *lua_toin6addr(lua_State *L, int idx)
{
struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr));
lua_decode_in6addr(L, idx, in6addr);
return in6addr;
}
void lua_pushsockunion(lua_State *L, const union sockunion *su)
{
char buf[SU_ADDRSTRLEN];
sockunion2str(su, buf, sizeof(buf));
lua_newtable(L);
@ -210,13 +225,17 @@ void lua_pushsockunion(lua_State *L, const union sockunion *su)
lua_setfield(L, -2, "string");
}
void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su)
{
lua_getfield(L, idx, "string");
str2sockunion(lua_tostring(L, -1), su);
}
void *lua_tosockunion(lua_State *L, int idx)
{
union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion));
lua_getfield(L, idx, "string");
str2sockunion(lua_tostring(L, -1), su);
lua_decode_sockunion(L, idx, su);
return su;
}
@ -225,12 +244,16 @@ void lua_pushtimet(lua_State *L, const time_t *time)
lua_pushinteger(L, *time);
}
void lua_decode_timet(lua_State *L, int idx, time_t *t)
{
*t = lua_tointeger(L, idx);
}
void *lua_totimet(lua_State *L, int idx)
{
time_t *t = XCALLOC(MTYPE_TMP, sizeof(time_t));
*t = lua_tointeger(L, idx);
lua_decode_timet(L, idx, t);
return t;
}
@ -239,17 +262,27 @@ void lua_pushintegerp(lua_State *L, const long long *num)
lua_pushinteger(L, *num);
}
void *lua_tointegerp(lua_State *L, int idx)
void lua_decode_integerp(lua_State *L, int idx, long long *num)
{
int isnum;
long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
*num = lua_tonumberx(L, idx, &isnum);
assert(isnum);
}
void *lua_tointegerp(lua_State *L, int idx)
{
long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
lua_decode_integerp(L, idx, num);
return num;
}
void lua_decode_stringp(lua_State *L, int idx, char *str)
{
strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
lua_pop(L, 1);
}
void *lua_tostringp(lua_State *L, int idx)
{
char *string = XSTRDUP(MTYPE_TMP, lua_tostring(L, idx));

View File

@ -50,6 +50,8 @@ static inline void lua_pushstring_wrapper(lua_State *L, const char *str)
*/
void lua_pushprefix(lua_State *L, const struct prefix *prefix);
void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix);
/*
* Converts the Lua value at idx to a prefix.
*
@ -63,6 +65,8 @@ void *lua_toprefix(lua_State *L, int idx);
*/
void lua_pushinterface(lua_State *L, const struct interface *ifp);
void lua_decode_interface(lua_State *L, int idx, struct interface *ifp);
/*
* Converts the Lua value at idx to an interface.
*
@ -77,6 +81,8 @@ void *lua_tointerface(lua_State *L, int idx);
*/
void lua_pushinaddr(lua_State *L, const struct in_addr *addr);
void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *addr);
/*
* Converts the Lua value at idx to an in_addr.
*
@ -90,6 +96,8 @@ void *lua_toinaddr(lua_State *L, int idx);
*/
void lua_pushin6addr(lua_State *L, const struct in6_addr *addr);
void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *addr);
/*
* Converts the Lua value at idx to an in6_addr.
*
@ -103,6 +111,8 @@ void *lua_toin6addr(lua_State *L, int idx);
*/
void lua_pushtimet(lua_State *L, const time_t *time);
void lua_decode_timet(lua_State *L, int idx, time_t *time);
/*
* Converts the Lua value at idx to a time_t.
*
@ -116,6 +126,8 @@ void *lua_totimet(lua_State *L, int idx);
*/
void lua_pushsockunion(lua_State *L, const union sockunion *su);
void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su);
/*
* Converts the Lua value at idx to a sockunion.
*
@ -129,6 +141,8 @@ void *lua_tosockunion(lua_State *L, int idx);
*/
void lua_pushintegerp(lua_State *L, const long long *num);
void lua_decode_integerp(lua_State *L, int idx, long long *num);
/*
* Converts the Lua value at idx to an int.
*
@ -137,6 +151,8 @@ void lua_pushintegerp(lua_State *L, const long long *num);
*/
void *lua_tointegerp(lua_State *L, int idx);
void lua_decode_stringp(lua_State *L, int idx, char *str);
/*
* Pop string.
*

View File

@ -105,7 +105,7 @@ void frrscript_init(const char *scriptdir);
#define DECODE_ARGS(name, value) \
do { \
lua_getglobal(L, name); \
DECODE_ARGS_WITH_STATE(L, value) \
DECODE_ARGS_WITH_STATE(L, value); \
} while (0)
#define ENCODE_ARGS_WITH_STATE(L, value) \
@ -120,7 +120,17 @@ time_t * : lua_pushtimet, \
char * : lua_pushstring_wrapper \
)(L, value)
#define DECODE_ARGS_WITH_STATE(L, value) _Generic((value), )(L, value);
#define DECODE_ARGS_WITH_STATE(L, value) \
_Generic((value), \
long long * : lua_decode_integerp, \
struct prefix * : lua_decode_prefix, \
struct interface * : lua_decode_interface, \
struct in_addr * : lua_decode_inaddr, \
struct in6_addr * : lua_decode_in6addr, \
union sockunion * : lua_decode_sockunion, \
time_t * : lua_decode_timet, \
char * : lua_decode_stringp \
)(L, -1, value)
/*
* Call script.