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

View File

@ -105,7 +105,7 @@ void frrscript_init(const char *scriptdir);
#define DECODE_ARGS(name, value) \ #define DECODE_ARGS(name, value) \
do { \ do { \
lua_getglobal(L, name); \ lua_getglobal(L, name); \
DECODE_ARGS_WITH_STATE(L, value) \ DECODE_ARGS_WITH_STATE(L, value); \
} while (0) } while (0)
#define ENCODE_ARGS_WITH_STATE(L, value) \ #define ENCODE_ARGS_WITH_STATE(L, value) \
@ -120,7 +120,17 @@ time_t * : lua_pushtimet, \
char * : lua_pushstring_wrapper \ char * : lua_pushstring_wrapper \
)(L, value) )(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. * Call script.