/Assets/LUA/KopiLua/ltable.cs
C# | 517 lines | 476 code | 41 blank | 0 comment | 113 complexity | 6325003ce713f4b2ae5a93c2fa635742 MD5 | raw file
- using System;
- namespace KopiLua
- {
- using lua_Number = System.Double;
- using StkId = Lua.LuaTypeValue;
- using TValue = Lua.LuaTypeValue;
- public partial class Lua
- {
- public const int MAXBITS = 26;
- public const int MAXASIZE = (1 << MAXBITS);
- internal static Node GNode(Table _t, int _i) { return _t.node[_i]; }
- internal static TKeyNK GKey(Node _n) { return _n.i_key.nk; }
- internal static TValue GVal(Node _n) { return _n.i_val; }
- internal static Node GNext(Node _n) { return _n.i_key.nk.next; }
- internal static void GNextSet(Node _n, Node _v) { _n.i_key.nk.next = _v; }
- internal static TValue Key2TVal(Node _n) { return _n.i_key.tvk; }
- internal static Node HashPow2(Table _t, lua_Number _n) { return GNode(_t, (int)LMod(_n, SizeNode(_t))); }
- public static Node HashStr(Table _t, TString _str) { return HashPow2(_t, _str.tsv.hash); }
- public static Node HashBoolean(Table _t, int _p) { return HashPow2(_t, _p); }
- public static Node HashMod(Table _t, int _n) { return GNode(_t, (int)((uint)_n % ((SizeNode(_t) - 1) | 1))); }
- public static Node HashPointer(Table _t, object _p) { return HashMod(_t, _p.GetHashCode()); }
- public const int NumInts = sizeof(lua_Number) / sizeof(int);
- public static Node DummyNode_ = new Node(new LuaTypeValue(new Value(), LUA_TNIL), new TKey(new Value(), LUA_TNIL, null));
- public static Node dummynode = DummyNode_;
- private static Node HashNum(Table _t, lua_Number _n)
- {
- byte[] _a = BitConverter.GetBytes(_n);
- for (int i = 1; i < _a.Length; i++) _a[0] += _a[i];
- return HashMod(_t, (int)_a[0]);
- }
- private static Node MainPosition(Table _t, TValue _key)
- {
- switch (TType(_key))
- {
- case LUA_TNUMBER:
- return HashNum(_t, NValue(_key));
- case LUA_TSTRING:
- return HashStr(_t, RawTSValue(_key));
- case LUA_TBOOLEAN:
- return HashBoolean(_t, BValue(_key));
- case LUA_TLIGHTUSERDATA:
- return HashPointer(_t, PValue(_key));
- default:
- return HashPointer(_t, GCValue(_key));
- }
- }
- private static int ArrayIndex(TValue _key)
- {
- if (TTIsNumber(_key))
- {
- lua_Number _n = NValue(_key);
- int _k;
- LuaNumber2Int(out _k, _n);
- if (LuaINumEq(CastNum(_k), _n))
- return _k;
- }
- return -1;
- }
- private static int FindIndex(LuaState _l, Table _t, StkId _key)
- {
- int _i;
- if (TTIsNil(_key)) return -1;
- _i = ArrayIndex(_key);
- if (0 < _i && _i <= _t.sizeArray)
- return _i - 1;
- else
- {
- Node _n = MainPosition(_t, _key);
- do
- {
- if ((LuaORawEqualObj(Key2TVal(_n), _key) != 0) ||
- (TType(GKey(_n)) == LUATDEADKEY && IsCollectable(_key) &&
- GCValue(GKey(_n)) == GCValue(_key)))
- {
- _i = CastInt(_n - GNode(_t, 0));
- return _i + _t.sizeArray;
- }
- else _n = GNext(_n);
- } while (_n != null);
- LuaGRunError(_l, "invalid key to " + LUA_QL("next"));
- return 0;
- }
- }
- public static int LuaHNext(LuaState _l, Table _t, StkId _key)
- {
- int _i = FindIndex(_l, _t, _key);
- for (_i++; _i < _t.sizeArray; _i++)
- {
- if (!TTIsNil(_t.array[_i]))
- {
- SetNValue(_key, CastNum(_i + 1));
- SetObj2S(_l, _key + 1, _t.array[_i]);
- return 1;
- }
- }
- for (_i -= _t.sizeArray; _i < SizeNode(_t); _i++)
- {
- if (!TTIsNil(GVal(GNode(_t, _i))))
- {
- SetObj2S(_l, _key, Key2TVal(GNode(_t, _i)));
- SetObj2S(_l, _key + 1, GVal(GNode(_t, _i)));
- return 1;
- }
- }
- return 0;
- }
- private static int ComputeSizes(int[] _nums, ref int _n_array)
- {
- int _i;
- int _two_to_i;
- int _a = 0;
- int _na = 0;
- int _n = 0;
- for (_i = 0, _two_to_i = 1; _two_to_i / 2 < _n_array; _i++, _two_to_i *= 2)
- {
- if (_nums[_i] > 0)
- {
- _a += _nums[_i];
- if (_a > _two_to_i / 2)
- {
- _n = _two_to_i;
- _na = _a;
- }
- }
- if (_a == _n_array) break;
- }
- _n_array = _n;
- LuaAssert(_n_array / 2 <= _na && _na <= _n_array);
- return _na;
- }
- private static int CountInt(TValue _key, int[] _nums)
- {
- int _k = ArrayIndex(_key);
- if (0 < _k && _k <= MAXASIZE)
- {
- _nums[CeilLog2(_k)]++;
- return 1;
- }
- else
- return 0;
- }
- private static int NumUseArray(Table _t, int[] _nums)
- {
- int _lg;
- int _ttlg;
- int _ause = 0;
- int _i = 1;
- for (_lg = 0, _ttlg = 1; _lg <= MAXBITS; _lg++, _ttlg *= 2)
- {
- int _lc = 0;
- int _lim = _ttlg;
- if (_lim > _t.sizeArray)
- {
- _lim = _t.sizeArray;
- if (_i > _lim)
- break;
- }
- for (; _i <= _lim; _i++)
- {
- if (!TTIsNil(_t.array[_i - 1]))
- _lc++;
- }
- _nums[_lg] += _lc;
- _ause += _lc;
- }
- return _ause;
- }
- private static int NumUsehash(Table _t, int[] _nums, ref int _pna_size)
- {
- int _total_use = 0;
- int _ause = 0;
- int _i = SizeNode(_t);
- while ((_i--) != 0)
- {
- Node n = _t.node[_i];
- if (!TTIsNil(GVal(n)))
- {
- _ause += CountInt(Key2TVal(n), _nums);
- _total_use++;
- }
- }
- _pna_size += _ause;
- return _total_use;
- }
- private static void SetArrayVector(LuaState _l, Table _t, int _size)
- {
- int _i;
- LuaMReallocVector<TValue>(_l, ref _t.array, _t.sizeArray, _size);
- for (_i = _t.sizeArray; _i < _size; _i++)
- SetNilValue(_t.array[_i]);
- _t.sizeArray = _size;
- }
- private static void SetNodeVector(LuaState _l, Table _t, int _size)
- {
- int _l_size;
- if (_size == 0)
- {
- _t.node = new Node[] { dummynode };
- _l_size = 0;
- }
- else
- {
- int _i;
- _l_size = CeilLog2(_size);
- if (_l_size > MAXBITS)
- LuaGRunError(_l, "table overflow");
- _size = TwoTo(_l_size);
- Node[] nodes = LuaMNewVector<Node>(_l, _size);
- _t.node = nodes;
- for (_i = 0; _i < _size; _i++)
- {
- Node n = GNode(_t, _i);
- GNextSet(n, null);
- SetNilValue(GKey(n));
- SetNilValue(GVal(n));
- }
- }
- _t.lSizeNode = CastByte(_l_size);
- _t.lastFree = _size;
- }
- private static void Resize(LuaState _l, Table _t, int _na_size, int _nh_size)
- {
- int _i;
- int _old_a_size = _t.sizeArray;
- int _old_h_size = _t.lSizeNode;
- Node[] _n_old = _t.node;
- if (_na_size > _old_a_size)
- SetArrayVector(_l, _t, _na_size);
- SetNodeVector(_l, _t, _nh_size);
- if (_na_size < _old_a_size)
- {
- _t.sizeArray = _na_size;
- for (_i = _na_size; _i < _old_a_size; _i++)
- if (!TTIsNil(_t.array[_i]))
- SetObjT2T(_l, LuaHSetNum(_l, _t, _i + 1), _t.array[_i]);
- LuaMReallocVector<TValue>(_l, ref _t.array, _old_a_size, _na_size);
- }
- for (_i = TwoTo(_old_h_size) - 1; _i >= 0; _i--)
- {
- Node _old = _n_old[_i];
- if (!TTIsNil(GVal(_old)))
- SetObjT2T(_l, LuaHSet(_l, _t, Key2TVal(_old)), GVal(_old));
- }
- if (_n_old[0] != dummynode)
- LuaMFreeArray(_l, _n_old);
- }
- public static void LuaHResizeArray(LuaState _l, Table _t, int _na_size)
- {
- int _n_size = (_t.node[0] == dummynode) ? 0 : SizeNode(_t);
- Resize(_l, _t, _na_size, _n_size);
- }
- private static void Rehash(LuaState _l, Table _t, TValue _ek)
- {
- int _na_size, na;
- int[] _nums = new int[MAXBITS + 1];
- int _i;
- int _total_use;
- for (_i = 0; _i <= MAXBITS; _i++) _nums[_i] = 0;
- _na_size = NumUseArray(_t, _nums);
- _total_use = _na_size;
- _total_use += NumUsehash(_t, _nums, ref _na_size);
- _na_size += CountInt(_ek, _nums);
- _total_use++;
- na = ComputeSizes(_nums, ref _na_size);
- Resize(_l, _t, _na_size, _total_use - na);
- }
- public static Table LuaHNew(LuaState _l, int _n_array, int _n_hash)
- {
- Table _t = LuaMNew<Table>(_l);
- LuaCLink(_l, obj2gco(_t), LUA_TTABLE);
- _t.metatable = null;
- _t.flags = CastByte(~0);
- _t.array = null;
- _t.sizeArray = 0;
- _t.lSizeNode = 0;
- _t.node = new Node[] { dummynode };
- SetArrayVector(_l, _t, _n_array);
- SetNodeVector(_l, _t, _n_hash);
- return _t;
- }
- public static void LuaHFree(LuaState _l, Table _t)
- {
- if (_t.node[0] != dummynode)
- LuaMFreeArray(_l, _t.node);
- LuaMFreeArray(_l, _t.array);
- LuaMFree(_l, _t);
- }
- private static Node GetFreePos(Table _t)
- {
- while (_t.lastFree-- > 0)
- if (TTIsNil(GKey(_t.node[_t.lastFree])))
- return _t.node[_t.lastFree];
- return null;
- }
- private static TValue newkey(LuaState _l, Table _t, TValue _key)
- {
- Node _mp = MainPosition(_t, _key);
- if (!TTIsNil(GVal(_mp)) || _mp == dummynode)
- {
- Node _other_n;
- Node _n = GetFreePos(_t);
- if (_n == null)
- {
- Rehash(_l, _t, _key);
- return LuaHSet(_l, _t, _key);
- }
- LuaAssert(_n != dummynode);
- _other_n = MainPosition(_t, Key2TVal(_mp));
- if (_other_n != _mp)
- {
- while (GNext(_other_n) != _mp) _other_n = GNext(_other_n);
- GNextSet(_other_n, _n);
- _n.i_val = new LuaTypeValue(_mp.i_val);
- _n.i_key = new TKey(_mp.i_key);
- GNextSet(_mp, null);
- SetNilValue(GVal(_mp));
- }
- else
- {
- GNextSet(_n, GNext(_mp));
- GNextSet(_mp, _n);
- _mp = _n;
- }
- }
- GKey(_mp).value.Copy(_key.value); GKey(_mp).tt = _key.tt;
- LuaCBarrierT(_l, _t, _key);
- LuaAssert(TTIsNil(GVal(_mp)));
- return GVal(_mp);
- }
- public static TValue LuaHGetnum(Table _t, int _key)
- {
- if ((uint)(_key - 1) < (uint)_t.sizeArray)
- return _t.array[_key - 1];
- else
- {
- lua_Number _nk = CastNum(_key);
- Node _n = HashNum(_t, _nk);
- do
- {
- if (TTIsNumber(GKey(_n)) && LuaINumEq(NValue(GKey(_n)), _nk))
- return GVal(_n); /* that's it */
- else _n = GNext(_n);
- } while (_n != null);
- return LuaONilObject;
- }
- }
- public static TValue LuaHGetStr(Table _t, TString _key)
- {
- Node _n = HashStr(_t, _key);
- do
- {
- if (TTIsString(GKey(_n)) && RawTSValue(GKey(_n)) == _key)
- return GVal(_n);
- else _n = GNext(_n);
- } while (_n != null);
- return LuaONilObject;
- }
- public static TValue LuaHGet(Table _t, TValue _key)
- {
- switch (TType(_key))
- {
- case LUA_TNIL: return LuaONilObject;
- case LUA_TSTRING: return LuaHGetStr(_t, RawTSValue(_key));
- case LUA_TNUMBER:
- {
- int _k;
- lua_Number _n = NValue(_key);
- LuaNumber2Int(out _k, _n);
- if (LuaINumEq(CastNum(_k), NValue(_key)))
- return LuaHGetnum(_t, _k);
- Node node = MainPosition(_t, _key);
- do
- {
- if (LuaORawEqualObj(Key2TVal(node), _key) != 0)
- return GVal(node);
- else node = GNext(node);
- } while (node != null);
- return LuaONilObject;
- }
- default:
- {
- Node _node = MainPosition(_t, _key);
- do
- {
- if (LuaORawEqualObj(Key2TVal(_node), _key) != 0)
- return GVal(_node);
- else _node = GNext(_node);
- } while (_node != null);
- return LuaONilObject;
- }
- }
- }
- public static TValue LuaHSet(LuaState _l, Table _t, TValue _key)
- {
- TValue _p = LuaHGet(_t, _key);
- _t.flags = 0;
- if (_p != LuaONilObject)
- return (TValue)_p;
- else
- {
- if (TTIsNil(_key)) LuaGRunError(_l, "table index is nil");
- else if (TTIsNumber(_key) && LuaINumIsNaN(NValue(_key)))
- LuaGRunError(_l, "table index is NaN");
- return newkey(_l, _t, _key);
- }
- }
- public static TValue LuaHSetNum(LuaState _l, Table _t, int _key)
- {
- TValue _p = LuaHGetnum(_t, _key);
- if (_p != LuaONilObject)
- return (TValue)_p;
- else
- {
- TValue k = new LuaTypeValue();
- SetNValue(k, CastNum(_key));
- return newkey(_l, _t, k);
- }
- }
- public static TValue LuaHSetStr(LuaState _l, Table _t, TString _key)
- {
- TValue _p = LuaHGetStr(_t, _key);
- if (_p != LuaONilObject)
- return (TValue)_p;
- else
- {
- TValue k = new LuaTypeValue();
- SetSValue(_l, k, _key);
- return newkey(_l, _t, k);
- }
- }
- #if !UNITY_3D
- [CLSCompliantAttribute(false)]
- #endif
- public static int UnboundSearch(Table _t, uint _j)
- {
- uint _i = _j;
- _j++;
- while (!TTIsNil(LuaHGetnum(_t, (int)_j)))
- {
- _i = _j;
- _j *= 2;
- if (_j > (uint)MAXINT)
- {
- _i = 1;
- while (!TTIsNil(LuaHGetnum(_t, (int)_i))) _i++;
- return (int)(_i - 1);
- }
- }
- while (_j - _i > 1)
- {
- uint _m = (_i + _j) / 2;
- if (TTIsNil(LuaHGetnum(_t, (int)_m))) _j = _m;
- else _i = _m;
- }
- return (int)_i;
- }
- public static int LuaHGetN(Table _t)
- {
- uint _j = (uint)_t.sizeArray;
- if (_j > 0 && TTIsNil(_t.array[_j - 1]))
- {
- uint _i = 0;
- while (_j - _i > 1)
- {
- uint _m = (_i + _j) / 2;
- if (TTIsNil(_t.array[_m - 1])) _j = _m;
- else _i = _m;
- }
- return (int)_i;
- }
- else if (_t.node[0] == dummynode)
- return (int)_j;
- else return UnboundSearch(_t, _j);
- }
- }
- }