2024-08-23 15:49:34 +08:00
|
|
|
|
/*
|
|
|
|
|
* Tencent is pleased to support the open source community by making xLua available.
|
|
|
|
|
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
|
|
|
|
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
|
|
|
|
* http://opensource.org/licenses/MIT
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if USE_UNI_LUA
|
|
|
|
|
using LuaAPI = UniLua.Lua;
|
|
|
|
|
using RealStatePtr = UniLua.ILuaState;
|
|
|
|
|
using LuaCSFunction = UniLua.CSharpFunctionDelegate;
|
|
|
|
|
#else
|
|
|
|
|
using LuaAPI = XLua.LuaDLL.Lua;
|
|
|
|
|
using RealStatePtr = System.IntPtr;
|
|
|
|
|
using LuaCSFunction = XLua.LuaDLL.lua_CSFunction;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
|
|
|
|
namespace XLua
|
|
|
|
|
{
|
|
|
|
|
public partial class LuaTable : LuaBase
|
|
|
|
|
{
|
|
|
|
|
public LuaTable(int reference, LuaEnv luaenv) : base(reference, luaenv)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no boxing version get
|
|
|
|
|
public void Get<TKey, TValue>(TKey key, out TValue value)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
translator.PushByType(L, key);
|
|
|
|
|
|
|
|
|
|
if (0 != LuaAPI.xlua_pgettable(L, -2))
|
|
|
|
|
{
|
|
|
|
|
string err = LuaAPI.lua_tostring(L, -1);
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
throw new Exception("get field [" + key + "] error:" + err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LuaTypes lua_type = LuaAPI.lua_type(L, -1);
|
|
|
|
|
Type type_of_value = typeof(TValue);
|
|
|
|
|
if (lua_type == LuaTypes.LUA_TNIL && type_of_value.IsValueType())
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidCastException("can not assign nil to " + type_of_value.GetFriendlyName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
translator.Get(L, -1, out value);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
}
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no boxing version get
|
|
|
|
|
public bool ContainsKey<TKey>(TKey key)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
translator.PushByType(L, key);
|
|
|
|
|
|
|
|
|
|
if (0 != LuaAPI.xlua_pgettable(L, -2))
|
|
|
|
|
{
|
|
|
|
|
string err = LuaAPI.lua_tostring(L, -1);
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
throw new Exception("get field [" + key + "] error:" + err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ret = LuaAPI.lua_type(L, -1) != LuaTypes.LUA_TNIL;
|
|
|
|
|
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//no boxing version set
|
|
|
|
|
public void Set<TKey, TValue>(TKey key, TValue value)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
translator.PushByType(L, key);
|
|
|
|
|
translator.PushByType(L, value);
|
|
|
|
|
|
|
|
|
|
if (0 != LuaAPI.xlua_psettable(L, -3))
|
|
|
|
|
{
|
|
|
|
|
luaEnv.ThrowExceptionFromError(oldTop);
|
|
|
|
|
}
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public T GetInPath<T>(string path)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
if (0 != LuaAPI.xlua_pgettable_bypath(L, -1, path))
|
|
|
|
|
{
|
|
|
|
|
luaEnv.ThrowExceptionFromError(oldTop);
|
|
|
|
|
}
|
|
|
|
|
LuaTypes lua_type = LuaAPI.lua_type(L, -1);
|
|
|
|
|
if (lua_type == LuaTypes.LUA_TNIL && typeof(T).IsValueType())
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidCastException("can not assign nil to " + typeof(T).GetFriendlyName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T value;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
translator.Get(L, -1, out value);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetInPath<T>(string path, T val)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
luaEnv.translator.PushByType(L, val);
|
|
|
|
|
if (0 != LuaAPI.xlua_psettable_bypath(L, -2, path))
|
|
|
|
|
{
|
|
|
|
|
luaEnv.ThrowExceptionFromError(oldTop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Obsolete("use no boxing version: GetInPath/SetInPath Get/Set instead!")]
|
|
|
|
|
public object this[string field]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return GetInPath<object>(field);
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
SetInPath(field, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Obsolete("use no boxing version: GetInPath/SetInPath Get/Set instead!")]
|
|
|
|
|
public object this[object field]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return Get<object>(field);
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
Set(field, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ForEach<TKey, TValue>(Action<TKey, TValue> action)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
LuaAPI.lua_pushnil(L);
|
|
|
|
|
while (LuaAPI.lua_next(L, -2) != 0)
|
|
|
|
|
{
|
|
|
|
|
if (translator.Assignable<TKey>(L, -2))
|
|
|
|
|
{
|
|
|
|
|
TKey key;
|
|
|
|
|
TValue val;
|
|
|
|
|
translator.Get(L, -2, out key);
|
|
|
|
|
translator.Get(L, -1, out val);
|
|
|
|
|
action(key, val);
|
|
|
|
|
}
|
|
|
|
|
LuaAPI.lua_pop(L, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
}
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int Length
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
var len = (int)LuaAPI.xlua_objlen(L, -1);
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
return len;
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
[Obsolete("not thread safe!", true)]
|
|
|
|
|
#endif
|
|
|
|
|
public IEnumerable GetKeys()
|
|
|
|
|
{
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
2024-09-04 02:07:48 +08:00
|
|
|
|
try
|
2024-08-23 15:49:34 +08:00
|
|
|
|
{
|
2024-09-04 02:07:48 +08:00
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
LuaAPI.lua_pushnil(L);
|
|
|
|
|
while (LuaAPI.lua_next(L, -2) != 0)
|
|
|
|
|
{
|
|
|
|
|
yield return translator.GetObject(L, -2);
|
|
|
|
|
LuaAPI.lua_pop(L, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
[Obsolete("not thread safe!", true)]
|
|
|
|
|
#endif
|
|
|
|
|
public IEnumerable<T> GetKeys<T>()
|
|
|
|
|
{
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
int oldTop = LuaAPI.lua_gettop(L);
|
2024-09-04 02:07:48 +08:00
|
|
|
|
try
|
2024-08-23 15:49:34 +08:00
|
|
|
|
{
|
2024-09-04 02:07:48 +08:00
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
LuaAPI.lua_pushnil(L);
|
|
|
|
|
while (LuaAPI.lua_next(L, -2) != 0)
|
2024-08-23 15:49:34 +08:00
|
|
|
|
{
|
2024-09-04 02:07:48 +08:00
|
|
|
|
if (translator.Assignable<T>(L, -2))
|
|
|
|
|
{
|
|
|
|
|
T v;
|
|
|
|
|
translator.Get(L, -2, out v);
|
|
|
|
|
yield return v;
|
|
|
|
|
}
|
|
|
|
|
LuaAPI.lua_pop(L, 1);
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-04 02:07:48 +08:00
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_settop(L, oldTop);
|
|
|
|
|
}
|
2024-08-23 15:49:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Obsolete("use no boxing version: Get<TKey, TValue> !")]
|
|
|
|
|
public T Get<T>(object key)
|
|
|
|
|
{
|
|
|
|
|
T ret;
|
|
|
|
|
Get(key, out ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TValue Get<TKey, TValue>(TKey key)
|
|
|
|
|
{
|
|
|
|
|
TValue ret;
|
|
|
|
|
Get(key, out ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TValue Get<TValue>(string key)
|
|
|
|
|
{
|
|
|
|
|
TValue ret;
|
|
|
|
|
Get(key, out ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetMetaTable(LuaTable metaTable)
|
|
|
|
|
{
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
push(luaEnv.L);
|
|
|
|
|
metaTable.push(luaEnv.L);
|
|
|
|
|
LuaAPI.lua_setmetatable(luaEnv.L, -2);
|
|
|
|
|
LuaAPI.lua_pop(luaEnv.L, 1);
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public T Cast<T>()
|
|
|
|
|
{
|
|
|
|
|
var L = luaEnv.L;
|
|
|
|
|
var translator = luaEnv.translator;
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
lock (luaEnv.luaEnvLock)
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
push(L);
|
|
|
|
|
T ret = (T)translator.GetObject(L, -1, typeof(T));
|
|
|
|
|
LuaAPI.lua_pop(luaEnv.L, 1);
|
|
|
|
|
return ret;
|
|
|
|
|
#if THREAD_SAFE || HOTFIX_ENABLE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal override void push(RealStatePtr L)
|
|
|
|
|
{
|
|
|
|
|
LuaAPI.lua_getref(L, luaReference);
|
|
|
|
|
}
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return "table :" + luaReference;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|