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/detail/ref.hpp>
25 #include <luabind/lua_include.hpp>
27 namespace luabind
{ namespace detail
30 // most of the code in this file comes from
31 // lauxlib.c in lua distribution
33 /******************************************************************************
34 * Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved.
36 * Permission is hereby granted, free of charge, to any person obtaining
37 * a copy of this software and associated documentation files (the
38 * "Software"), to deal in the Software without restriction, including
39 * without limitation the rights to use, copy, modify, merge, publish,
40 * distribute, sublicense, and/or sell copies of the Software, and to
41 * permit persons to whom the Software is furnished to do so, subject to
42 * the following conditions:
44 * The above copyright notice and this permission notice shall be
45 * included in all copies or substantial portions of the Software.
47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
50 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
51 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
52 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
53 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
54 ******************************************************************************/
58 // the number of reserved references
61 // free list of references
64 // array sizes (not used here)
68 int checkint (lua_State
*L
, int topop
)
70 int n
= (int)lua_tonumber(L
, -1);
71 if (n
== 0 && !lua_isnumber(L
, -1)) n
= -1;
77 void getsizes (lua_State
*L
)
79 lua_rawgeti(L
, LUA_REGISTRYINDEX
, ARRAYSIZE_REF
);
80 if (lua_isnil(L
, -1)) { /* no `size' table? */
81 lua_pop(L
, 1); /* remove nil */
82 lua_newtable(L
); /* create it */
83 lua_pushvalue(L
, -1); /* `size' will be its own metatable */
84 lua_setmetatable(L
, -2);
85 lua_pushliteral(L
, "__mode");
86 lua_pushliteral(L
, "k");
87 lua_rawset(L
, -3); /* metatable(N).__mode = "k" */
89 lua_rawseti(L
, LUA_REGISTRYINDEX
, ARRAYSIZE_REF
); /* store in register */
93 void luaL_setn (lua_State
*L
, int t
, int n
)
95 lua_pushliteral(L
, "n");
97 if (checkint(L
, 1) >= 0) { /* is there a numeric field `n'? */
98 lua_pushliteral(L
, "n"); /* use it */
102 else { /* use `sizes' */
105 lua_pushnumber(L
, n
);
106 lua_rawset(L
, -3); /* sizes[t] = n */
107 lua_pop(L
, 1); /* remove `sizes' */
111 int luaL_getn (lua_State
*L
, int t
)
114 lua_pushliteral(L
, "n"); /* try t.n */
116 if ((n
= checkint(L
, 1)) >= 0) return n
;
117 getsizes(L
); /* else try sizes[t] */
120 if ((n
= checkint(L
, 2)) >= 0) return n
;
121 for (n
= 1; ; n
++) { /* else must count elements */
122 lua_rawgeti(L
, t
, n
);
123 if (lua_isnil(L
, -1)) break;
132 int ref(lua_State
*L
)
134 int t
= LUA_REGISTRYINDEX
;
137 if (lua_isnil(L
, -1))
139 lua_pop(L
, 1); /* remove from stack */
140 return LUA_REFNIL
; /* `nil' has a unique fixed reference */
143 lua_rawgeti(L
, t
, FREELIST_REF
); /* get first free element */
144 ref
= (int)lua_tonumber(L
, -1); /* ref = t[FREELIST_REF] */
145 lua_pop(L
, 1); /* remove it from stack */
146 if (ref
!= 0) { /* any free element? */
147 lua_rawgeti(L
, t
, ref
); /* remove it from list */
148 lua_rawseti(L
, t
, FREELIST_REF
); /* (t[FREELIST_REF] = t[ref]) */
150 else { /* no free elements */
151 ref
= ::luabind::detail::luaL_getn(L
, t
);
152 if (ref
< RESERVED_REFS
)
153 ref
= RESERVED_REFS
; /* skip reserved references */
154 ref
++; /* create new reference */
155 ::luabind::detail::luaL_setn(L
, t
, ref
);
157 lua_rawseti(L
, t
, ref
);
161 void unref(lua_State
*L
, int ref
)
163 int t
= LUA_REGISTRYINDEX
;
165 lua_rawgeti(L
, t
, FREELIST_REF
);
166 lua_rawseti(L
, t
, ref
); /* t[ref] = t[FREELIST_REF] */
167 lua_pushnumber(L
, ref
);
168 lua_rawseti(L
, t
, FREELIST_REF
); /* t[FREELIST_REF] = ref */