1 | /*=========================================================================*\ |
2 | * Auxiliar routines for class hierarchy manipulation |
3 | * LuaSocket toolkit |
4 | \*=========================================================================*/ |
5 | #include <string.h> |
6 | #include <stdio.h> |
7 | |
8 | #include "auxiliar.h" |
9 | |
10 | /*=========================================================================*\ |
11 | * Exported functions |
12 | \*=========================================================================*/ |
13 | /*-------------------------------------------------------------------------*\ |
14 | * Initializes the module |
15 | \*-------------------------------------------------------------------------*/ |
16 | int auxiliar_open(lua_State *L) { |
17 | (void) L; |
18 | return 0; |
19 | } |
20 | |
21 | /*-------------------------------------------------------------------------*\ |
22 | * Creates a new class with given methods |
23 | * Methods whose names start with __ are passed directly to the metatable. |
24 | \*-------------------------------------------------------------------------*/ |
25 | void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) { |
26 | luaL_newmetatable(L, classname); /* mt */ |
27 | /* create __index table to place methods */ |
28 | lua_pushstring(L, "__index" ); /* mt,"__index" */ |
29 | lua_newtable(L); /* mt,"__index",it */ |
30 | /* put class name into class metatable */ |
31 | lua_pushstring(L, "class" ); /* mt,"__index",it,"class" */ |
32 | lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ |
33 | lua_rawset(L, -3); /* mt,"__index",it */ |
34 | /* pass all methods that start with _ to the metatable, and all others |
35 | * to the index table */ |
36 | for (; func->name; func++) { /* mt,"__index",it */ |
37 | lua_pushstring(L, func->name); |
38 | lua_pushcfunction(L, func->func); |
39 | lua_rawset(L, func->name[0] == '_' ? -5: -3); |
40 | } |
41 | lua_rawset(L, -3); /* mt */ |
42 | lua_pop(L, 1); |
43 | } |
44 | |
45 | /*-------------------------------------------------------------------------*\ |
46 | * Prints the value of a class in a nice way |
47 | \*-------------------------------------------------------------------------*/ |
48 | int auxiliar_tostring(lua_State *L) { |
49 | char buf[32]; |
50 | if (!lua_getmetatable(L, 1)) goto error; |
51 | lua_pushstring(L, "__index" ); |
52 | lua_gettable(L, -2); |
53 | if (!lua_istable(L, -1)) goto error; |
54 | lua_pushstring(L, "class" ); |
55 | lua_gettable(L, -2); |
56 | if (!lua_isstring(L, -1)) goto error; |
57 | sprintf(buf, "%p" , lua_touserdata(L, 1)); |
58 | lua_pushfstring(L, "%s: %s" , lua_tostring(L, -1), buf); |
59 | return 1; |
60 | error: |
61 | lua_pushstring(L, "invalid object passed to 'auxiliar.c:__tostring'" ); |
62 | lua_error(L); |
63 | return 1; |
64 | } |
65 | |
66 | /*-------------------------------------------------------------------------*\ |
67 | * Insert class into group |
68 | \*-------------------------------------------------------------------------*/ |
69 | void auxiliar_add2group(lua_State *L, const char *classname, const char *groupname) { |
70 | luaL_getmetatable(L, classname); |
71 | lua_pushstring(L, groupname); |
72 | lua_pushboolean(L, 1); |
73 | lua_rawset(L, -3); |
74 | lua_pop(L, 1); |
75 | } |
76 | |
77 | /*-------------------------------------------------------------------------*\ |
78 | * Make sure argument is a boolean |
79 | \*-------------------------------------------------------------------------*/ |
80 | int auxiliar_checkboolean(lua_State *L, int objidx) { |
81 | if (!lua_isboolean(L, objidx)) |
82 | auxiliar_typeerror(L, objidx, lua_typename(L, LUA_TBOOLEAN)); |
83 | return lua_toboolean(L, objidx); |
84 | } |
85 | |
86 | /*-------------------------------------------------------------------------*\ |
87 | * Return userdata pointer if object belongs to a given class, abort with |
88 | * error otherwise |
89 | \*-------------------------------------------------------------------------*/ |
90 | void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { |
91 | void *data = auxiliar_getclassudata(L, classname, objidx); |
92 | if (!data) { |
93 | char msg[45]; |
94 | sprintf(msg, "%.35s expected" , classname); |
95 | luaL_argerror(L, objidx, msg); |
96 | } |
97 | return data; |
98 | } |
99 | |
100 | /*-------------------------------------------------------------------------*\ |
101 | * Return userdata pointer if object belongs to a given group, abort with |
102 | * error otherwise |
103 | \*-------------------------------------------------------------------------*/ |
104 | void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) { |
105 | void *data = auxiliar_getgroupudata(L, groupname, objidx); |
106 | if (!data) { |
107 | char msg[45]; |
108 | sprintf(msg, "%.35s expected" , groupname); |
109 | luaL_argerror(L, objidx, msg); |
110 | } |
111 | return data; |
112 | } |
113 | |
114 | /*-------------------------------------------------------------------------*\ |
115 | * Set object class |
116 | \*-------------------------------------------------------------------------*/ |
117 | void auxiliar_setclass(lua_State *L, const char *classname, int objidx) { |
118 | luaL_getmetatable(L, classname); |
119 | if (objidx < 0) objidx--; |
120 | lua_setmetatable(L, objidx); |
121 | } |
122 | |
123 | /*-------------------------------------------------------------------------*\ |
124 | * Get a userdata pointer if object belongs to a given group. Return NULL |
125 | * otherwise |
126 | \*-------------------------------------------------------------------------*/ |
127 | void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { |
128 | if (!lua_getmetatable(L, objidx)) |
129 | return NULL; |
130 | lua_pushstring(L, groupname); |
131 | lua_rawget(L, -2); |
132 | if (lua_isnil(L, -1)) { |
133 | lua_pop(L, 2); |
134 | return NULL; |
135 | } else { |
136 | lua_pop(L, 2); |
137 | return lua_touserdata(L, objidx); |
138 | } |
139 | } |
140 | |
141 | /*-------------------------------------------------------------------------*\ |
142 | * Get a userdata pointer if object belongs to a given class. Return NULL |
143 | * otherwise |
144 | \*-------------------------------------------------------------------------*/ |
145 | void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { |
146 | return luaL_checkudata(L, objidx, classname); |
147 | } |
148 | |
149 | /*-------------------------------------------------------------------------*\ |
150 | * Throws error when argument does not have correct type. |
151 | * Used to be part of lauxlib in Lua 5.1, was dropped from 5.2. |
152 | \*-------------------------------------------------------------------------*/ |
153 | int auxiliar_typeerror (lua_State *L, int narg, const char *tname) { |
154 | const char *msg = lua_pushfstring(L, "%s expected, got %s" , tname, |
155 | luaL_typename(L, narg)); |
156 | return luaL_argerror(L, narg, msg); |
157 | } |
158 | |
159 | |