lua-users home
lua-l archive

Re: Feature request: userdata slice

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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 ... )

AltStyle によって変換されたページ (->オリジナル) /