[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Feature request: userdata slice
- From: Sean Conner <sean@...>
- Date: Wed, 19 Aug 2015 12:33:03 -0400
It was thus said that the Great 云风 Cloud Wu once stated:
> > Also, I don't think I'm following your API there. I have this structure:
> >
> > typedef union sockaddr_all
> > {
> > struct sockaddr sa;
> > struct sockaddr_in sin;
> > struct sockaddr_in6 sin6;
> > struct sockaddr_un ssun;
> > } sockaddr_all__t;
> >
> > which I'm using for a userdata. I have a custom __index method associated
> > with this that gives me the following "fields":
> >
> > addr - text representation of IPv4/IPv6 address
> > daddr - other text representation of IPv4/IPv6 address
> > addrbits - The raw binary bits that make up an IPv4/IPv6 address
> > port - port number
> > family - string, either 'ip', 'ip6' or 'unix'.
> > display - textual representation of address and port.
> >
> > How would your system with with that?
>
> You can use 1 for sa, 2 for sin, 3 for sin6 , and 4 for ssun. 0 means the
> sockaddr_all.
Well, that was a bad exaple, as sockaddr_all__t is a union, not a
structure. And its use goes something like:
> net = require "org.conman.net"
> a = net.address("192.168.1.10",'tcp',80)
> b = net.address("fc00::1",'tcp',25)
> print(a.family)
ip
> print(a.addr)
192.168.1.10
> print(a.daddr)
192.168.1.10
> print(a:display())
192.168.1.10:80
> print(b.addr)
fc00::1
> print(b.daddr)
[fc00::1]
> print(b:display())
[fc00::1]:25
> print(b.family)
ip6
> print(b.port)
25
But, if I'm reading you correctly, let's try another example, and this one
is from work. I wrapped a rather large structure (44K in size) in Lua.
Here's a cut down example of that structure:
#define MAX ...
typedef struct
{
time_t update;
char *name;
bool capable;
bool licensed;
} entry__s;
typedef struct
{
uint32_t serial;
size_t lru[MAX];
entry__s entries[MAX];
} cache_data__s;
typedef struct
{
time_t update;
cache_data__s cache;
bool dirty;
} record__s;
Nowhere near 44K in size, but it does go to the same depth as the original.
In Lua, this would be referenced something as:
first = record.cache.lru[1]
if record.cache.entries[first].licensed then
display(record.cache.entries[first].name)
end
As it currently stands, when this structure (which is normally stored on
disk) is shoved into Lua, I convert the entire thing to Lua primitive values
(tables, numbers, strings, etc) with nary a userdata in sight. But there's
quite a bit of code to do that (around 700 lines of C code). So let me try
your approach to this.
I begin with registering an __index method for my userdata:
static int recordlua___index(lua_State *L)
{
record__s *rec = luaL_checkudata(L,1,TYPE_RECORD);
... um ...
}
I think I lost you. Hold on ... let me think. Oh wait, I think I see it
now:
static int record_lua___index(lua_State *L)
{
record__s *rec = luaL_checkudata(L,1,TYPE_RECORD);
int slice = lua_getuserslice(L,1);
switch(slice)
{
case REC_CACHE:
case REC_UPDATE:
case REC_UPDATE_2:
...
}
return 1;
}
and then lua_getuserslice() somehow knows what function to call back to to
... well ... your example just doesn't make sense here.
> How to implement these by new api lua_getuserslice and lua_setuserslice ?
>
> #define SOCKADDR 0
> #define SOCKADDR_SIN 1
> #define SOCKADDR_SIN6 2
> #define SOCKADDR_UN 3
Okay, that I followed.
> int sa_root_index(lua_State *L) {
> const char * f = luaL_checkstring(L, 2);
> int slice = 0;
> if (strcmp(f, "sin")== 0)
> slice = 1;
> else if (strcmp(f, "sin6") == 0)
> slice = 2;
> else if (strcmp(f, "un") == 0)
> slice = 3;
> else
> return luaL_error(L, "never here");
> lua_settop(L,1);
> lua_setuserslice(L,1,slice);
> return 1;
> }
Okay, just a mapping of strings to integers. No problem there.
luaL_checkoption() could be used for this:
int sa_root_index(lua_State *L)
{
static const char *const options[] =
{
"sin",
"sin6",
"un",
NULL
};
lua_setuserslice(L,1,luaL_checkoption(L,2,NULL,options));
return 1;
}
> int sa_sin_index(lua_State *L) {
> const char * f = luaL_checkstring(L, 2);
> sockaddr_all_t *obj = lua_touserdata(L,1);
> if (strcmp(f, "port") == 0)
> lua_pushinteger(L, obj->sin.sin_port);
> else {
> // todo: supoort sin.sin_family ... etc
> }
> return 1;
> }
Okay, that's pretty straight forward to follow ...
> int sockaddr_index(lua_State *L) {
> // todo: do more type check
> sockaddr_all_t *obj = lua_touserdata(L,1);
> int slice = lua_getuserslice(L,1);
Umm ... wait ...
> switch (slice) {
> case SOCKADDR :
> return sa_root_index(L);
doesn't sa_root_index() *set* the userslice? You can call
lua_getuserslice() *before* you set it? This is where I'm lost. I'm not
following this code at all.
-spc (but I think I see where you are trying to go to ... )