1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-31 22:05:10 +02:00
vcmi/lua/luabind/ref.cpp
majaczek 3f5b339fc5 ratunku... :/
tak czy siak lua/src jest wykorzystywane w include
:( nie umiem zmusić mojego programu svn do współpracy, zwłaszcz z VC
2008-08-03 15:52:12 +00:00

177 lines
5.5 KiB
C++

// Copyright (c) 2003 Daniel Wallin and Arvid Norberg
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.
#include "stdafx.h"
#include <algorithm>
#include <luabind/config.hpp>
#include <luabind/detail/ref.hpp>
#include <luabind/lua_include.hpp>
#include <luabind/detail/debug.hpp>
namespace luabind { namespace detail
{
// most of the code in this file comes from
// lauxlib.c in lua distribution
/******************************************************************************
* Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
enum
{
// the number of reserved references
RESERVED_REFS = 2,
// free list of references
FREELIST_REF = 1,
// array sizes (not used here)
ARRAYSIZE_REF = 2
};
int checkint (lua_State *L, int topop)
{
int n = (int)lua_tonumber(L, -1);
if (n == 0 && !lua_isnumber(L, -1)) n = -1;
lua_pop(L, topop);
return n;
}
void getsizes (lua_State *L)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);
if (lua_isnil(L, -1)) { /* no `size' table? */
lua_pop(L, 1); /* remove nil */
lua_newtable(L); /* create it */
lua_pushvalue(L, -1); /* `size' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushliteral(L, "__mode");
lua_pushliteral(L, "k");
lua_rawset(L, -3); /* metatable(N).__mode = "k" */
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */
}
}
void luaL_setn (lua_State *L, int t, int n)
{
lua_pushliteral(L, "n");
lua_rawget(L, t);
if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
lua_pushliteral(L, "n"); /* use it */
lua_pushnumber(L, n);
lua_rawset(L, t);
}
else { /* use `sizes' */
getsizes(L);
lua_pushvalue(L, t);
lua_pushnumber(L, n);
lua_rawset(L, -3); /* sizes[t] = n */
lua_pop(L, 1); /* remove `sizes' */
}
}
int luaL_getn (lua_State *L, int t)
{
int n;
lua_pushliteral(L, "n"); /* try t.n */
lua_rawget(L, t);
if ((n = checkint(L, 1)) >= 0) return n;
getsizes(L); /* else try sizes[t] */
lua_pushvalue(L, t);
lua_rawget(L, -2);
if ((n = checkint(L, 2)) >= 0) return n;
for (n = 1; ; n++) { /* else must count elements */
lua_rawgeti(L, t, n);
if (lua_isnil(L, -1)) break;
lua_pop(L, 1);
}
lua_pop(L, 1);
return n - 1;
}
// based on luaL_ref
int LUABIND_API ref(lua_State *L)
{
int t = LUA_REGISTRYINDEX;
int ref;
if (lua_isnil(L, -1))
{
lua_pop(L, 1); /* remove from stack */
return LUA_REFNIL; /* `nil' has a unique fixed reference */
}
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
ref = (int)lua_tonumber(L, -1); /* ref = t[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, t, ref); /* remove it from list */
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
}
else { /* no free elements */
ref = ::luabind::detail::luaL_getn(L, t);
if (ref < RESERVED_REFS)
ref = RESERVED_REFS; /* skip reserved references */
ref++; /* create new reference */
::luabind::detail::luaL_setn(L, t, ref);
}
lua_rawseti(L, t, ref);
return ref;
}
void LUABIND_API unref(lua_State *L, int ref)
{
LUABIND_CHECK_STACK(L);
int t = LUA_REGISTRYINDEX;
if (ref >= 0) {
lua_rawgeti(L, t, FREELIST_REF);
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
lua_pushnumber(L, ref);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
}}