table.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. package lua
  2. const defaultArrayCap = 32
  3. const defaultHashCap = 32
  4. type lValueArraySorter struct {
  5. L *LState
  6. Fn *LFunction
  7. Values []LValue
  8. }
  9. func (lv lValueArraySorter) Len() int {
  10. return len(lv.Values)
  11. }
  12. func (lv lValueArraySorter) Swap(i, j int) {
  13. lv.Values[i], lv.Values[j] = lv.Values[j], lv.Values[i]
  14. }
  15. func (lv lValueArraySorter) Less(i, j int) bool {
  16. if lv.Fn != nil {
  17. lv.L.Push(lv.Fn)
  18. lv.L.Push(lv.Values[i])
  19. lv.L.Push(lv.Values[j])
  20. lv.L.Call(2, 1)
  21. return LVAsBool(lv.L.reg.Pop())
  22. }
  23. return lessThan(lv.L, lv.Values[i], lv.Values[j])
  24. }
  25. func newLTable(acap int, hcap int) *LTable {
  26. if acap < 0 {
  27. acap = 0
  28. }
  29. if hcap < 0 {
  30. hcap = 0
  31. }
  32. tb := &LTable{}
  33. tb.Metatable = LNil
  34. if acap != 0 {
  35. tb.array = make([]LValue, 0, acap)
  36. }
  37. if hcap != 0 {
  38. tb.strdict = make(map[string]LValue, hcap)
  39. }
  40. return tb
  41. }
  42. // Len returns length of this LTable.
  43. func (tb *LTable) Len() int {
  44. if tb.array == nil {
  45. return 0
  46. }
  47. var prev LValue = LNil
  48. for i := len(tb.array) - 1; i >= 0; i-- {
  49. v := tb.array[i]
  50. if prev == LNil && v != LNil {
  51. return i + 1
  52. }
  53. prev = v
  54. }
  55. return 0
  56. }
  57. // Append appends a given LValue to this LTable.
  58. func (tb *LTable) Append(value LValue) {
  59. if tb.array == nil {
  60. tb.array = make([]LValue, 0, defaultArrayCap)
  61. }
  62. tb.array = append(tb.array, value)
  63. }
  64. // Insert inserts a given LValue at position `i` in this table.
  65. func (tb *LTable) Insert(i int, value LValue) {
  66. if tb.array == nil {
  67. tb.array = make([]LValue, 0, defaultArrayCap)
  68. }
  69. if i > len(tb.array) {
  70. tb.RawSetInt(i, value)
  71. return
  72. }
  73. if i <= 0 {
  74. tb.RawSet(LNumber(i), value)
  75. return
  76. }
  77. i -= 1
  78. tb.array = append(tb.array, LNil)
  79. copy(tb.array[i+1:], tb.array[i:])
  80. tb.array[i] = value
  81. }
  82. // MaxN returns a maximum number key that nil value does not exist before it.
  83. func (tb *LTable) MaxN() int {
  84. if tb.array == nil {
  85. return 0
  86. }
  87. for i := len(tb.array) - 1; i >= 0; i-- {
  88. if tb.array[i] != LNil {
  89. return i + 1
  90. }
  91. }
  92. return 0
  93. }
  94. // Remove removes from this table the element at a given position.
  95. func (tb *LTable) Remove(pos int) LValue {
  96. if tb.array == nil {
  97. return LNil
  98. }
  99. i := pos - 1
  100. larray := len(tb.array)
  101. oldval := LNil
  102. switch {
  103. case i >= larray:
  104. // nothing to do
  105. case i == larray-1 || i < 0:
  106. oldval = tb.array[larray-1]
  107. tb.array = tb.array[:larray-1]
  108. default:
  109. oldval = tb.array[i]
  110. copy(tb.array[i:], tb.array[i+1:])
  111. tb.array[larray-1] = nil
  112. tb.array = tb.array[:larray-1]
  113. }
  114. return oldval
  115. }
  116. // RawSet sets a given LValue to a given index without the __newindex metamethod.
  117. // It is recommended to use `RawSetString` or `RawSetInt` for performance
  118. // if you already know the given LValue is a string or number.
  119. func (tb *LTable) RawSet(key LValue, value LValue) {
  120. switch v := key.(type) {
  121. case LNumber:
  122. if isArrayKey(v) {
  123. if tb.array == nil {
  124. tb.array = make([]LValue, 0, defaultArrayCap)
  125. }
  126. index := int(v) - 1
  127. alen := len(tb.array)
  128. switch {
  129. case index == alen:
  130. tb.array = append(tb.array, value)
  131. case index > alen:
  132. for i := 0; i < (index - alen); i++ {
  133. tb.array = append(tb.array, LNil)
  134. }
  135. tb.array = append(tb.array, value)
  136. case index < alen:
  137. tb.array[index] = value
  138. }
  139. return
  140. }
  141. case LString:
  142. tb.RawSetString(string(v), value)
  143. return
  144. }
  145. tb.RawSetH(key, value)
  146. }
  147. // RawSetInt sets a given LValue at a position `key` without the __newindex metamethod.
  148. func (tb *LTable) RawSetInt(key int, value LValue) {
  149. if key < 1 || key >= MaxArrayIndex {
  150. tb.RawSetH(LNumber(key), value)
  151. return
  152. }
  153. if tb.array == nil {
  154. tb.array = make([]LValue, 0, 32)
  155. }
  156. index := key - 1
  157. alen := len(tb.array)
  158. switch {
  159. case index == alen:
  160. tb.array = append(tb.array, value)
  161. case index > alen:
  162. for i := 0; i < (index - alen); i++ {
  163. tb.array = append(tb.array, LNil)
  164. }
  165. tb.array = append(tb.array, value)
  166. case index < alen:
  167. tb.array[index] = value
  168. }
  169. }
  170. // RawSetString sets a given LValue to a given string index without the __newindex metamethod.
  171. func (tb *LTable) RawSetString(key string, value LValue) {
  172. if tb.strdict == nil {
  173. tb.strdict = make(map[string]LValue, defaultHashCap)
  174. }
  175. if tb.keys == nil {
  176. tb.keys = []LValue{}
  177. tb.k2i = map[LValue]int{}
  178. }
  179. if value == LNil {
  180. // TODO tb.keys and tb.k2i should also be removed
  181. delete(tb.strdict, key)
  182. } else {
  183. tb.strdict[key] = value
  184. lkey := LString(key)
  185. if _, ok := tb.k2i[lkey]; !ok {
  186. tb.k2i[lkey] = len(tb.keys)
  187. tb.keys = append(tb.keys, lkey)
  188. }
  189. }
  190. }
  191. // RawSetH sets a given LValue to a given index without the __newindex metamethod.
  192. func (tb *LTable) RawSetH(key LValue, value LValue) {
  193. if s, ok := key.(LString); ok {
  194. tb.RawSetString(string(s), value)
  195. return
  196. }
  197. if tb.dict == nil {
  198. tb.dict = make(map[LValue]LValue, len(tb.strdict))
  199. }
  200. if tb.keys == nil {
  201. tb.keys = []LValue{}
  202. tb.k2i = map[LValue]int{}
  203. }
  204. if value == LNil {
  205. // TODO tb.keys and tb.k2i should also be removed
  206. delete(tb.dict, key)
  207. } else {
  208. tb.dict[key] = value
  209. if _, ok := tb.k2i[key]; !ok {
  210. tb.k2i[key] = len(tb.keys)
  211. tb.keys = append(tb.keys, key)
  212. }
  213. }
  214. }
  215. // RawGet returns an LValue associated with a given key without __index metamethod.
  216. func (tb *LTable) RawGet(key LValue) LValue {
  217. switch v := key.(type) {
  218. case LNumber:
  219. if isArrayKey(v) {
  220. if tb.array == nil {
  221. return LNil
  222. }
  223. index := int(v) - 1
  224. if index >= len(tb.array) {
  225. return LNil
  226. }
  227. return tb.array[index]
  228. }
  229. case LString:
  230. if tb.strdict == nil {
  231. return LNil
  232. }
  233. if ret, ok := tb.strdict[string(v)]; ok {
  234. return ret
  235. }
  236. return LNil
  237. }
  238. if tb.dict == nil {
  239. return LNil
  240. }
  241. if v, ok := tb.dict[key]; ok {
  242. return v
  243. }
  244. return LNil
  245. }
  246. // RawGetInt returns an LValue at position `key` without __index metamethod.
  247. func (tb *LTable) RawGetInt(key int) LValue {
  248. if tb.array == nil {
  249. return LNil
  250. }
  251. index := int(key) - 1
  252. if index >= len(tb.array) || index < 0 {
  253. return LNil
  254. }
  255. return tb.array[index]
  256. }
  257. // RawGet returns an LValue associated with a given key without __index metamethod.
  258. func (tb *LTable) RawGetH(key LValue) LValue {
  259. if s, sok := key.(LString); sok {
  260. if tb.strdict == nil {
  261. return LNil
  262. }
  263. if v, vok := tb.strdict[string(s)]; vok {
  264. return v
  265. }
  266. return LNil
  267. }
  268. if tb.dict == nil {
  269. return LNil
  270. }
  271. if v, ok := tb.dict[key]; ok {
  272. return v
  273. }
  274. return LNil
  275. }
  276. // RawGetString returns an LValue associated with a given key without __index metamethod.
  277. func (tb *LTable) RawGetString(key string) LValue {
  278. if tb.strdict == nil {
  279. return LNil
  280. }
  281. if v, vok := tb.strdict[string(key)]; vok {
  282. return v
  283. }
  284. return LNil
  285. }
  286. // ForEach iterates over this table of elements, yielding each in turn to a given function.
  287. func (tb *LTable) ForEach(cb func(LValue, LValue)) {
  288. if tb.array != nil {
  289. for i, v := range tb.array {
  290. if v != LNil {
  291. cb(LNumber(i+1), v)
  292. }
  293. }
  294. }
  295. if tb.strdict != nil {
  296. for k, v := range tb.strdict {
  297. if v != LNil {
  298. cb(LString(k), v)
  299. }
  300. }
  301. }
  302. if tb.dict != nil {
  303. for k, v := range tb.dict {
  304. if v != LNil {
  305. cb(k, v)
  306. }
  307. }
  308. }
  309. }
  310. // This function is equivalent to lua_next ( http://www.lua.org/manual/5.1/manual.html#lua_next ).
  311. func (tb *LTable) Next(key LValue) (LValue, LValue) {
  312. init := false
  313. if key == LNil {
  314. key = LNumber(0)
  315. init = true
  316. }
  317. if init || key != LNumber(0) {
  318. if kv, ok := key.(LNumber); ok && isInteger(kv) && int(kv) >= 0 && kv < LNumber(MaxArrayIndex) {
  319. index := int(kv)
  320. if tb.array != nil {
  321. for ; index < len(tb.array); index++ {
  322. if v := tb.array[index]; v != LNil {
  323. return LNumber(index + 1), v
  324. }
  325. }
  326. }
  327. if tb.array == nil || index == len(tb.array) {
  328. if (tb.dict == nil || len(tb.dict) == 0) && (tb.strdict == nil || len(tb.strdict) == 0) {
  329. return LNil, LNil
  330. }
  331. key = tb.keys[0]
  332. if v := tb.RawGetH(key); v != LNil {
  333. return key, v
  334. }
  335. }
  336. }
  337. }
  338. for i := tb.k2i[key] + 1; i < len(tb.keys); i++ {
  339. key := tb.keys[i]
  340. if v := tb.RawGetH(key); v != LNil {
  341. return key, v
  342. }
  343. }
  344. return LNil, LNil
  345. }