1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <luabind/config.hpp>
25 #include <luabind/detail/ref.hpp>
26 #include <luabind/lua_include.hpp>
27 #include <luabind/detail/debug.hpp>
29 namespace luabind
{ namespace detail
32 // most of the code in this file comes from
33 // lauxlib.c in lua distribution
35 /******************************************************************************
36 * Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved.
38 * Permission is hereby granted, free of charge, to any person obtaining
39 * a copy of this software and associated documentation files (the
40 * "Software"), to deal in the Software without restriction, including
41 * without limitation the rights to use, copy, modify, merge, publish,
42 * distribute, sublicense, and/or sell copies of the Software, and to
43 * permit persons to whom the Software is furnished to do so, subject to
44 * the following conditions:
46 * The above copyright notice and this permission notice shall be
47 * included in all copies or substantial portions of the Software.
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
53 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
54 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
55 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56 ******************************************************************************/
60 // the number of reserved references
63 // free list of references
66 // array sizes (not used here)
70 int checkint (lua_State
*L
, int topop
)
72 int n
= (int)lua_tonumber(L
, -1);
73 if (n
== 0 && !lua_isnumber(L
, -1)) n
= -1;
79 void getsizes (lua_State
*L
)
81 lua_rawgeti(L
, LUA_REGISTRYINDEX
, ARRAYSIZE_REF
);
82 if (lua_isnil(L
, -1)) { /* no `size' table? */
83 lua_pop(L
, 1); /* remove nil */
84 lua_newtable(L
); /* create it */
85 lua_pushvalue(L
, -1); /* `size' will be its own metatable */
86 lua_setmetatable(L
, -2);
87 lua_pushliteral(L
, "__mode");
88 lua_pushliteral(L
, "k");
89 lua_rawset(L
, -3); /* metatable(N).__mode = "k" */
91 lua_rawseti(L
, LUA_REGISTRYINDEX
, ARRAYSIZE_REF
); /* store in register */
95 void luaL_setn (lua_State
*L
, int t
, int n
)
97 lua_pushliteral(L
, "n");
99 if (checkint(L
, 1) >= 0) { /* is there a numeric field `n'? */
100 lua_pushliteral(L
, "n"); /* use it */
101 lua_pushnumber(L
, n
);
104 else { /* use `sizes' */
107 lua_pushnumber(L
, n
);
108 lua_rawset(L
, -3); /* sizes[t] = n */
109 lua_pop(L
, 1); /* remove `sizes' */
113 int luaL_getn (lua_State
*L
, int t
)
116 lua_pushliteral(L
, "n"); /* try t.n */
118 if ((n
= checkint(L
, 1)) >= 0) return n
;
119 getsizes(L
); /* else try sizes[t] */
122 if ((n
= checkint(L
, 2)) >= 0) return n
;
123 for (n
= 1; ; n
++) { /* else must count elements */
124 lua_rawgeti(L
, t
, n
);
125 if (lua_isnil(L
, -1)) break;
134 int LUABIND_API
ref(lua_State
*L
)
136 int t
= LUA_REGISTRYINDEX
;
139 if (lua_isnil(L
, -1))
141 lua_pop(L
, 1); /* remove from stack */
142 return LUA_REFNIL
; /* `nil' has a unique fixed reference */
145 lua_rawgeti(L
, t
, FREELIST_REF
); /* get first free element */
146 ref
= (int)lua_tonumber(L
, -1); /* ref = t[FREELIST_REF] */
147 lua_pop(L
, 1); /* remove it from stack */
148 if (ref
!= 0) { /* any free element? */
149 lua_rawgeti(L
, t
, ref
); /* remove it from list */
150 lua_rawseti(L
, t
, FREELIST_REF
); /* (t[FREELIST_REF] = t[ref]) */
152 else { /* no free elements */
153 ref
= ::luabind::detail::luaL_getn(L
, t
);
154 if (ref
< RESERVED_REFS
)
155 ref
= RESERVED_REFS
; /* skip reserved references */
156 ref
++; /* create new reference */
157 ::luabind::detail::luaL_setn(L
, t
, ref
);
159 lua_rawseti(L
, t
, ref
);
163 void LUABIND_API
unref(lua_State
*L
, int ref
)
165 LUABIND_CHECK_STACK(L
);
167 int t
= LUA_REGISTRYINDEX
;
169 lua_rawgeti(L
, t
, FREELIST_REF
);
170 lua_rawseti(L
, t
, ref
); /* t[ref] = t[FREELIST_REF] */
171 lua_pushnumber(L
, ref
);
172 lua_rawseti(L
, t
, FREELIST_REF
); /* t[FREELIST_REF] = ref */