[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Sequence of bytes - userdata or string?
- From: Yuri Kaszubowski Lopes <yurikazuba@...>
- Date: Wed, 4 Jan 2012 14:40:16 -0200
I don't understand exactly what you want. But: "Is it possible to write such a metatable?" Yes, maybe you want something like (attached: bytelist.c, test.lua)
I strongly agree with Dirk Laurie "Your main concern should be clarity, not speed"
2012/1/4 Dirk Laurie
<dirk.laurie@gmail.com>
2012/1/4 Asim <asim.r.p@gmail.com>:
>
> I want to write a C function that returns a sequence of bytes. This
> function should be called from Lua. There are two options for the type of
> return value in Lua - userdata and string.
>
Your main concern should be clarity, not speed. Is it conceivable
that you would wish to concatenate two of your bytesequences to form a
third? If yes, by all means return a string. If no, do it as
userdata.
/* gcc bytelist.c -pipe -shared -Wall -ansi `pkg-config --cflags --libs lua` -o bytelist.so */
/* Lua headers */
#include <lua.h>
#include <lauxlib.h>
/* C headers */
#include <stdio.h>
#include <stdlib.h>
typedef struct SByteList {
int len;
char *data;
} TByteList;
int bytelist_new(lua_State* L);
int bytelist_len(lua_State* L);
int bytelist_get(lua_State* L);
int bytelist_set(lua_State* L);
int bytelist_MT_gc(lua_State* L);
int bytelist_MT_index(lua_State* L);
int bytelist_MT_newindex(lua_State* L);
static const struct luaL_reg bytelist [] =
{
{ "new" , bytelist_new },
{ "len" , bytelist_len },
{ "get" , bytelist_get },
{ "set" , bytelist_set },
{ NULL , NULL }
};
static const struct luaL_reg bytelist_MT [] =
{
{ "__gc" , bytelist_MT_gc },
{ "__index" , bytelist_MT_index },
{ "__newindex", bytelist_MT_newindex },
{ NULL , NULL }
};
int luaopen_bytelist(lua_State *L){
luaL_register( L, "bytelist", bytelist );
luaL_newmetatable(L, "bytelistMT");
luaL_register( L, NULL , bytelist_MT );
lua_setmetatable( L, -2 );
return 1;
};
/* CLASS METHODS */
/*
+param: length:number
+return: TByteList:userdata
*/
int bytelist_new(lua_State* L){
luaL_checktype(L, 1, LUA_TNUMBER);
/* create userdata:TByteList */
TByteList *obj = (TByteList*) lua_newuserdata(L, sizeof(TByteList));
obj->len = lua_tointeger(L, 1);
obj->data = (char *) malloc( obj->len * sizeof(char) );
luaL_getmetatable(L, "bytelistMT");
lua_setmetatable(L, -2);
return 1;
}
/*
+param: TByteList:userdata
+return: len:number
*/
int bytelist_len(lua_State* L){
luaL_checktype(L, 1, LUA_TUSERDATA);
TByteList* obj = (TByteList*) lua_touserdata(L, 1);
lua_pushinteger( L, obj->len );
return 1;
}
/*
+param: TByteList:userdata
+param: position:number
+return: value:number (in fact the byte)
*/
int bytelist_get(lua_State* L){
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checktype(L, 2, LUA_TNUMBER);
TByteList* obj = (TByteList*) lua_touserdata(L, 1);
int pos = lua_tointeger(L, 2);
if( pos > 0 && pos <= obj->len ){
lua_pushinteger( L, (int) obj->data[ pos-1 ] );
return 1;
} else {
lua_pushnil( L );
lua_pushliteral( L, "invalid position" );
return 2;
}
}
/*
+param: TByteList:userdata
+param: position:number
+param: value:number (in fact the byte)
+return: sucess:boolean
*/
int bytelist_set(lua_State* L){
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checktype(L, 2, LUA_TNUMBER);
luaL_checktype(L, 3, LUA_TNUMBER);
TByteList* obj = (TByteList*) lua_touserdata(L, 1);
int pos = lua_tointeger(L, 2);
if( pos > 0 && pos <= obj->len ){
obj->data[ pos-1 ] = (char) lua_tointeger(L, 3);
lua_pushboolean(L, 1);
return 1;
} else {
lua_pushboolean(L, 0);
lua_pushliteral( L, "invalid position" );
return 2;
}
}
/* METATABLE METHODS */
int bytelist_MT_gc(lua_State* L)
{
luaL_checktype(L, 1, LUA_TUSERDATA);
TByteList* obj = (TByteList*) lua_touserdata(L, 1);
free( obj->data );
return 0;
}
int bytelist_MT_index(lua_State* L)
{
luaL_checktype(L, 1, LUA_TUSERDATA);
if ( lua_isnumber( L, 2 ) ) {
return bytelist_get( L );
} else {
lua_getglobal( L, "bytelist" );
lua_pushvalue(L, 2);
lua_rawget( L, -2);
return 1;
}
return 0;
}
int bytelist_MT_newindex(lua_State* L)
{
luaL_checktype(L, 1, LUA_TUSERDATA);
if ( lua_isnumber( L, 2 ) ) {
return bytelist_set( L );
}
return 0;
}
require 'bytelist'
bl = bytelist.new(1024)
print( bl:len() )
bl:set(1, 10)
bl:set(2, 20)
bl:set(3, 30)
print( bl:get(1), bl:get(2), bl:get(3) )
bl[4] = 40
bl[5] = 50
print( bl[1], bl[2], bl[3], bl[4], bl[5] )
print( bl:get(1), bl:get(2), bl:get(3), bl:get(4), bl:get(5) )