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