JJBB/Assets/XLua/Src/LuaTable.cs

391 lines
11 KiB
C#
Raw Permalink Normal View History

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;
}
}
}