// Copy matching Lua table entries to a struct, given the struct type // and the index on the Lua stack. func CopyTableToStruct(L *lua.State, t reflect.Type, idx int) interface{} { was_ptr := t.Kind() == reflect.Ptr if was_ptr { t = t.Elem() } s := reflect.New(t) // T -> *T ref := s.Elem() L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { key := L.ToString(-2) f := ref.FieldByName(strings.Title(key)) if f.IsValid() { val := luaToGoValue(L, f.Type(), -1) f.Set(val) } L.Pop(1) } if was_ptr { return s.Interface() } return s.Elem().Interface() }
func copyTableToMap(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} { if t == nil { t = tmap } te, tk := t.Elem(), t.Key() m := reflect.MakeMap(t) // See copyTableToSlice. ptr := L.ToPointer(idx) if !luaIsEmpty(L, idx) { visited[ptr] = m.Interface() } L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { // key at -2, value at -1 key := reflect.ValueOf(luaToGo(L, tk, -2, visited)) val := reflect.ValueOf(luaToGo(L, te, -1, visited)) if val.Interface() == nullv.Interface() { val = reflect.Zero(te) } m.SetMapIndex(key, val) L.Pop(1) } return m.Interface() }
func popMap(L *lua.State) map[string]interface{} { m := make(map[string]interface{}) L.PushNil() for L.Next(-2) != 0 { if L.IsString(-2) { var v interface{} if L.IsBoolean(-1) { v = L.ToBoolean(-1) } else if L.IsNumber(-1) { var t float64 t = L.ToNumber(-1) if t == float64(int64(t)) { v = int(t) } else { v = t } } else if L.IsString(-1) { v = L.ToString(-1) } else if L.IsNil(-1) { v = nil } else if L.IsTable(-1) { v = popMap(L) } m[L.ToString(-2)] = v } L.Pop(1) } return m }
func outputNumbersToStrings(L *lua.State) { L.GetGlobal("output") if !L.IsTable(-1) { L.NewTable() L.SetGlobal("output") } L.GetField(-1, "tags") if L.IsTable(-1) { // First key. L.PushNil() for L.Next(-2) != 0 { // Use 'key' at index -2 and 'value' at index -1. if L.IsString(-2) && L.IsString(-1) { // Convert numbers to strings. L.ToString(-1) L.SetField(-3, L.ToString(-2)) } else { // Remove 'value' and keep 'key' for next iteration. L.Pop(1) } } } L.Pop(1) L.Pop(1) }
func pairsAux(L *lua.State) int { L.CheckType(1, lua.LUA_TTABLE) L.SetTop(2) // Create a 2nd argument if there isn't one. if L.Next(1) != 0 { return 2 } L.PushNil() return 1 }
func luaIsEmpty(L *lua.State, idx int) bool { L.PushNil() if idx < 0 { idx-- } if L.Next(idx) != 0 { L.Pop(2) return false } return true }
func copyTableToStruct(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} { if t == nil { RaiseError(L, "type argument must be non-nill") } wasPtr := t.Kind() == reflect.Ptr if wasPtr { t = t.Elem() } s := reflect.New(t) // T -> *T ref := s.Elem() // See copyTableToSlice. ptr := L.ToPointer(idx) if !luaIsEmpty(L, idx) { if wasPtr { visited[ptr] = s.Interface() } else { visited[ptr] = s.Elem().Interface() } } // Associate Lua keys with Go fields: tags have priority over matching field // name. fields := map[string]string{} st := ref.Type() for i := 0; i < ref.NumField(); i++ { field := st.Field(i) tag := field.Tag.Get("lua") if tag != "" { fields[tag] = field.Name continue } fields[field.Name] = field.Name } L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { key := L.ToString(-2) f := ref.FieldByName(fields[key]) if f.CanSet() && f.IsValid() { val := reflect.ValueOf(luaToGo(L, f.Type(), -1, visited)) f.Set(val) } L.Pop(1) } if wasPtr { return s.Interface() } return s.Elem().Interface() }
// return the Lua table at 'idx' as a copied Go map. If 't' is nil then the map // type is map[string]interface{} func CopyTableToMap(L *lua.State, t reflect.Type, idx int) interface{} { if t == nil { t = reflect.TypeOf(tmap) } te, tk := t.Elem(), t.Key() m := reflect.MakeMap(t) L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { // key at -2, value at -1 key := valueOf(LuaToGo(L, tk, -2)) val := valueOf(LuaToGo(L, te, -1)) m.SetMapIndex(key, val) L.Pop(1) } return m.Interface() }
// Copy matching Lua table entries to a struct, given the struct type // and the index on the Lua stack. func CopyTableToStruct(L *lua.State, t reflect.Type, idx int) interface{} { was_ptr := t.Kind() == reflect.Ptr if was_ptr { t = t.Elem() } s := reflect.New(t) // T -> *T ref := s.Elem() // Associate Lua keys with Go fields: tags have priority over matching field // name. fields := map[string]string{} st := ref.Type() for i := 0; i < ref.NumField(); i++ { field := st.Field(i) tag := field.Tag.Get("lua") if tag != "" { fields[tag] = field.Name continue } fields[field.Name] = field.Name } L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { key := L.ToString(-2) f := ref.FieldByName(fields[key]) if f.CanSet() && f.IsValid() { val := luaToGoValue(L, f.Type(), -1) f.Set(val) } L.Pop(1) } if was_ptr { return s.Interface() } return s.Elem().Interface() }
// Return the Lua table at 'idx' as a copied Go map. If 't' is nil then the map // type is map[string]interface{} func CopyTableToMap(L *lua.State, t reflect.Type, idx int) interface{} { if t == nil { t = tmap } te, tk := t.Elem(), t.Key() m := reflect.MakeMap(t) L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { // key at -2, value at -1 key := luaToGoValue(L, tk, -2) val := luaToGoValue(L, te, -1) if val == nullv { val = reflect.Zero(te) } m.SetMapIndex(key, val) L.Pop(1) } return m.Interface() }