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