LuaTable.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*
  2. * Tencent is pleased to support the open source community by making xLua available.
  3. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  4. * 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
  5. * http://opensource.org/licenses/MIT
  6. * 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.
  7. */
  8. #if USE_UNI_LUA
  9. using LuaAPI = UniLua.Lua;
  10. using RealStatePtr = UniLua.ILuaState;
  11. using LuaCSFunction = UniLua.CSharpFunctionDelegate;
  12. #else
  13. using LuaAPI = XLua.LuaDLL.Lua;
  14. using RealStatePtr = System.IntPtr;
  15. using LuaCSFunction = XLua.LuaDLL.lua_CSFunction;
  16. #endif
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Text;
  20. using System.Collections;
  21. namespace XLua
  22. {
  23. public partial class LuaTable : LuaBase
  24. {
  25. public LuaTable(int reference, LuaEnv luaenv) : base(reference, luaenv)
  26. {
  27. }
  28. // no boxing version get
  29. public void Get<TKey, TValue>(TKey key, out TValue value)
  30. {
  31. #if THREAD_SAFE || HOTFIX_ENABLE
  32. lock (luaEnv.luaEnvLock)
  33. {
  34. #endif
  35. var L = luaEnv.L;
  36. var translator = luaEnv.translator;
  37. int oldTop = LuaAPI.lua_gettop(L);
  38. LuaAPI.lua_getref(L, luaReference);
  39. translator.PushByType(L, key);
  40. if (0 != LuaAPI.xlua_pgettable(L, -2))
  41. {
  42. string err = LuaAPI.lua_tostring(L, -1);
  43. LuaAPI.lua_settop(L, oldTop);
  44. throw new Exception("get field [" + key + "] error:" + err);
  45. }
  46. LuaTypes lua_type = LuaAPI.lua_type(L, -1);
  47. Type type_of_value = typeof(TValue);
  48. if (lua_type == LuaTypes.LUA_TNIL && type_of_value.IsValueType())
  49. {
  50. throw new InvalidCastException("can not assign nil to " + type_of_value.GetFriendlyName());
  51. }
  52. try
  53. {
  54. translator.Get(L, -1, out value);
  55. }
  56. catch (Exception e)
  57. {
  58. throw e;
  59. }
  60. finally
  61. {
  62. LuaAPI.lua_settop(L, oldTop);
  63. }
  64. #if THREAD_SAFE || HOTFIX_ENABLE
  65. }
  66. #endif
  67. }
  68. // no boxing version get
  69. public bool ContainsKey<TKey>(TKey key)
  70. {
  71. #if THREAD_SAFE || HOTFIX_ENABLE
  72. lock (luaEnv.luaEnvLock)
  73. {
  74. #endif
  75. var L = luaEnv.L;
  76. var translator = luaEnv.translator;
  77. int oldTop = LuaAPI.lua_gettop(L);
  78. LuaAPI.lua_getref(L, luaReference);
  79. translator.PushByType(L, key);
  80. if (0 != LuaAPI.xlua_pgettable(L, -2))
  81. {
  82. string err = LuaAPI.lua_tostring(L, -1);
  83. LuaAPI.lua_settop(L, oldTop);
  84. throw new Exception("get field [" + key + "] error:" + err);
  85. }
  86. bool ret = LuaAPI.lua_type(L, -1) != LuaTypes.LUA_TNIL;
  87. LuaAPI.lua_settop(L, oldTop);
  88. return ret;
  89. #if THREAD_SAFE || HOTFIX_ENABLE
  90. }
  91. #endif
  92. }
  93. //no boxing version set
  94. public void Set<TKey, TValue>(TKey key, TValue value)
  95. {
  96. #if THREAD_SAFE || HOTFIX_ENABLE
  97. lock (luaEnv.luaEnvLock)
  98. {
  99. #endif
  100. var L = luaEnv.L;
  101. int oldTop = LuaAPI.lua_gettop(L);
  102. var translator = luaEnv.translator;
  103. LuaAPI.lua_getref(L, luaReference);
  104. translator.PushByType(L, key);
  105. translator.PushByType(L, value);
  106. if (0 != LuaAPI.xlua_psettable(L, -3))
  107. {
  108. luaEnv.ThrowExceptionFromError(oldTop);
  109. }
  110. LuaAPI.lua_settop(L, oldTop);
  111. #if THREAD_SAFE || HOTFIX_ENABLE
  112. }
  113. #endif
  114. }
  115. public T GetInPath<T>(string path)
  116. {
  117. #if THREAD_SAFE || HOTFIX_ENABLE
  118. lock (luaEnv.luaEnvLock)
  119. {
  120. #endif
  121. var L = luaEnv.L;
  122. var translator = luaEnv.translator;
  123. int oldTop = LuaAPI.lua_gettop(L);
  124. LuaAPI.lua_getref(L, luaReference);
  125. if (0 != LuaAPI.xlua_pgettable_bypath(L, -1, path))
  126. {
  127. luaEnv.ThrowExceptionFromError(oldTop);
  128. }
  129. LuaTypes lua_type = LuaAPI.lua_type(L, -1);
  130. if (lua_type == LuaTypes.LUA_TNIL && typeof(T).IsValueType())
  131. {
  132. throw new InvalidCastException("can not assign nil to " + typeof(T).GetFriendlyName());
  133. }
  134. T value;
  135. try
  136. {
  137. translator.Get(L, -1, out value);
  138. }
  139. catch (Exception e)
  140. {
  141. throw e;
  142. }
  143. finally
  144. {
  145. LuaAPI.lua_settop(L, oldTop);
  146. }
  147. return value;
  148. #if THREAD_SAFE || HOTFIX_ENABLE
  149. }
  150. #endif
  151. }
  152. public void SetInPath<T>(string path, T val)
  153. {
  154. #if THREAD_SAFE || HOTFIX_ENABLE
  155. lock (luaEnv.luaEnvLock)
  156. {
  157. #endif
  158. var L = luaEnv.L;
  159. int oldTop = LuaAPI.lua_gettop(L);
  160. LuaAPI.lua_getref(L, luaReference);
  161. luaEnv.translator.PushByType(L, val);
  162. if (0 != LuaAPI.xlua_psettable_bypath(L, -2, path))
  163. {
  164. luaEnv.ThrowExceptionFromError(oldTop);
  165. }
  166. LuaAPI.lua_settop(L, oldTop);
  167. #if THREAD_SAFE || HOTFIX_ENABLE
  168. }
  169. #endif
  170. }
  171. [Obsolete("use no boxing version: GetInPath/SetInPath Get/Set instead!")]
  172. public object this[string field]
  173. {
  174. get
  175. {
  176. return GetInPath<object>(field);
  177. }
  178. set
  179. {
  180. SetInPath(field, value);
  181. }
  182. }
  183. [Obsolete("use no boxing version: GetInPath/SetInPath Get/Set instead!")]
  184. public object this[object field]
  185. {
  186. get
  187. {
  188. return Get<object>(field);
  189. }
  190. set
  191. {
  192. Set(field, value);
  193. }
  194. }
  195. public void ForEach<TKey, TValue>(Action<TKey, TValue> action)
  196. {
  197. #if THREAD_SAFE || HOTFIX_ENABLE
  198. lock (luaEnv.luaEnvLock)
  199. {
  200. #endif
  201. var L = luaEnv.L;
  202. var translator = luaEnv.translator;
  203. int oldTop = LuaAPI.lua_gettop(L);
  204. try
  205. {
  206. LuaAPI.lua_getref(L, luaReference);
  207. LuaAPI.lua_pushnil(L);
  208. while (LuaAPI.lua_next(L, -2) != 0)
  209. {
  210. if (translator.Assignable<TKey>(L, -2))
  211. {
  212. TKey key;
  213. TValue val;
  214. translator.Get(L, -2, out key);
  215. translator.Get(L, -1, out val);
  216. action(key, val);
  217. }
  218. LuaAPI.lua_pop(L, 1);
  219. }
  220. }
  221. finally
  222. {
  223. LuaAPI.lua_settop(L, oldTop);
  224. }
  225. #if THREAD_SAFE || HOTFIX_ENABLE
  226. }
  227. #endif
  228. }
  229. public int Length
  230. {
  231. get
  232. {
  233. #if THREAD_SAFE || HOTFIX_ENABLE
  234. lock (luaEnv.luaEnvLock)
  235. {
  236. #endif
  237. var L = luaEnv.L;
  238. int oldTop = LuaAPI.lua_gettop(L);
  239. LuaAPI.lua_getref(L, luaReference);
  240. var len = (int)LuaAPI.xlua_objlen(L, -1);
  241. LuaAPI.lua_settop(L, oldTop);
  242. return len;
  243. #if THREAD_SAFE || HOTFIX_ENABLE
  244. }
  245. #endif
  246. }
  247. }
  248. #if THREAD_SAFE || HOTFIX_ENABLE
  249. [Obsolete("not thread safe!", true)]
  250. #endif
  251. public IEnumerable GetKeys()
  252. {
  253. var L = luaEnv.L;
  254. var translator = luaEnv.translator;
  255. int oldTop = LuaAPI.lua_gettop(L);
  256. LuaAPI.lua_getref(L, luaReference);
  257. LuaAPI.lua_pushnil(L);
  258. while (LuaAPI.lua_next(L, -2) != 0)
  259. {
  260. yield return translator.GetObject(L, -2);
  261. LuaAPI.lua_pop(L, 1);
  262. }
  263. LuaAPI.lua_settop(L, oldTop);
  264. }
  265. #if THREAD_SAFE || HOTFIX_ENABLE
  266. [Obsolete("not thread safe!", true)]
  267. #endif
  268. public IEnumerable<T> GetKeys<T>()
  269. {
  270. var L = luaEnv.L;
  271. var translator = luaEnv.translator;
  272. int oldTop = LuaAPI.lua_gettop(L);
  273. LuaAPI.lua_getref(L, luaReference);
  274. LuaAPI.lua_pushnil(L);
  275. while (LuaAPI.lua_next(L, -2) != 0)
  276. {
  277. if (translator.Assignable<T>(L, -2))
  278. {
  279. T v;
  280. translator.Get(L, -2, out v);
  281. yield return v;
  282. }
  283. LuaAPI.lua_pop(L, 1);
  284. }
  285. LuaAPI.lua_settop(L, oldTop);
  286. }
  287. [Obsolete("use no boxing version: Get<TKey, TValue> !")]
  288. public T Get<T>(object key)
  289. {
  290. T ret;
  291. Get(key, out ret);
  292. return ret;
  293. }
  294. public TValue Get<TKey, TValue>(TKey key)
  295. {
  296. TValue ret;
  297. Get(key, out ret);
  298. return ret;
  299. }
  300. public TValue Get<TValue>(string key)
  301. {
  302. TValue ret;
  303. Get(key, out ret);
  304. return ret;
  305. }
  306. public void SetMetaTable(LuaTable metaTable)
  307. {
  308. #if THREAD_SAFE || HOTFIX_ENABLE
  309. lock (luaEnv.luaEnvLock)
  310. {
  311. #endif
  312. push(luaEnv.L);
  313. metaTable.push(luaEnv.L);
  314. LuaAPI.lua_setmetatable(luaEnv.L, -2);
  315. LuaAPI.lua_pop(luaEnv.L, 1);
  316. #if THREAD_SAFE || HOTFIX_ENABLE
  317. }
  318. #endif
  319. }
  320. public T Cast<T>()
  321. {
  322. var L = luaEnv.L;
  323. var translator = luaEnv.translator;
  324. #if THREAD_SAFE || HOTFIX_ENABLE
  325. lock (luaEnv.luaEnvLock)
  326. {
  327. #endif
  328. push(L);
  329. T ret = (T)translator.GetObject(L, -1, typeof(T));
  330. LuaAPI.lua_pop(luaEnv.L, 1);
  331. return ret;
  332. #if THREAD_SAFE || HOTFIX_ENABLE
  333. }
  334. #endif
  335. }
  336. internal override void push(RealStatePtr L)
  337. {
  338. LuaAPI.lua_getref(L, luaReference);
  339. }
  340. public override string ToString()
  341. {
  342. return "table :" + luaReference;
  343. }
  344. }
  345. }