func pushMap(L *lua.State, m map[string]interface{}, lower bool) { L.CreateTable(0, len(m)) for k, v := range m { if lower { L.PushString(strings.ToLower(k)) } else { L.PushString(k) } switch t := v.(type) { case string: L.PushString(t) case int64: L.PushInteger(t) case int: L.PushInteger(int64(t)) case float64: L.PushNumber(t) case bool: L.PushBoolean(t) case map[string]interface{}: pushMap(L, t, false) default: L.PushNil() } L.SetTable(-3) } }
// Also for arrays. func copySliceToTable(L *lua.State, vslice reflect.Value, visited visitor) int { ref := vslice for vslice.Kind() == reflect.Ptr { // For arrays. vslice = vslice.Elem() } if vslice.IsValid() && (vslice.Kind() == reflect.Slice || vslice.Kind() == reflect.Array) { n := vslice.Len() L.CreateTable(n, 0) if vslice.Kind() == reflect.Slice { visited.mark(vslice) } else if ref.Kind() == reflect.Ptr { visited.mark(ref) } for i := 0; i < n; i++ { L.PushInteger(int64(i + 1)) v := vslice.Index(i) if isNil(v) { v = nullv } goToLua(L, nil, v, true, visited) L.SetTable(-3) } return 1 } L.PushNil() L.PushString("not a slice/array") return 2 }
func (p *Plugin) apiAudioBitrate(l *lua.State) int { if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { l.PushInteger(int64(enc.Bitrate())) } else { l.PushInteger(-1) } return 1 }
func ipairsAux(L *lua.State) int { i := L.CheckInteger(2) + 1 L.PushInteger(int64(i)) L.PushInteger(int64(i)) L.GetTable(1) if L.Type(-1) == lua.LUA_TNIL { return 1 } return 2 }
func MessThingContents(state *lua.State, thing *Thing) int { // make a new table state.CreateTable(len(thing.Contents), 0) // ( -- tbl ) // for each content add a new lua-space Thing for i, contentId := range thing.Contents { state.PushInteger(int64(i)) pushValue(state, contentId) state.SetTable(-3) // ( tbl key val -- tbl ) } // ( tbl -- tbl ) return 1 }
// ProxyIpairs implements Lua 5.2 'ipairs' functions. // It respects the __ipairs metamethod. // // It is only useful for compatibility with Lua 5.1. func ProxyIpairs(L *lua.State) int { // See Lua >=5.2 source code. if L.GetMetaField(1, "__ipairs") { L.PushValue(1) L.Call(1, 3) return 3 } L.CheckType(1, lua.LUA_TTABLE) L.PushGoFunction(ipairsAux) L.PushValue(1) L.PushInteger(0) return 3 }
func LuaIntTimestamp(L *lua.State) int { luaAssertArgnum(L, 1, "timestamp()") if !L.IsTable(-1) { panic(errors.New("Argoment of timestamp is not a table")) return 0 } L.CheckStack(1) t := time.Date(GetTableInt(L, "year"), time.Month(GetTableInt(L, "month")), GetTableInt(L, "day"), GetTableInt(L, "hour"), GetTableInt(L, "minute"), GetTableInt(L, "second"), 0, time.Local) L.PushInteger(int64(t.Unix())) return 1 }
// copy a Go slice to a Lua table func CopySliceToTable(L *lua.State, vslice reflect.Value) int { if vslice.IsValid() && vslice.Type().Kind() == reflect.Slice { n := vslice.Len() L.CreateTable(n, 0) for i := 0; i < n; i++ { L.PushInteger(int64(i + 1)) GoToLua(L, nil, vslice.Index(i)) L.SetTable(-3) } return 1 } else { L.PushNil() L.PushString("not a slice!") } return 2 }
func LuaIntParseDateTime(L *lua.State) int { luaAssertArgnum(L, 1, "parsedatetime()") L.CheckStack(1) input := L.ToString(-1) tl := GetTasklistFromLua(L) out, _ := ParseDateTime(input, tl.GetTimezone()) if out != nil { L.PushInteger(int64(out.Unix())) } else { L.PushInteger(0) } return 1 }
func LuaIntGetterSetterFunctionInt(fname string, L *lua.State, getter func(tl *Tasklist, entry *Entry) int64, setter func(tl *Tasklist, entry *Entry, value int)) int { argNum := L.GetTop() if argNum == 0 { entry := GetEntryFromLua(L, CURSOR, fname) tl := GetTasklistFromLua(L) L.PushInteger(getter(tl, entry)) return 1 } else if argNum == 1 { value := L.ToInteger(1) entry := GetEntryFromLua(L, CURSOR, fname) tl := GetTasklistFromLua(L) setter(tl, entry, value) if !tl.luaFlags.cursorCloned { tl.luaFlags.cursorEdited = true } return 0 } panic(errors.New(fmt.Sprintf("Incorrect number of argoments to %s (only 0 or 1 accepted)", fname))) return 0 }
func slicemap__len(L *lua.State) int { val, _ := valueOfProxy(L, 1) L.PushInteger(int64(val.Len())) return 1 }
func pushValue(state *lua.State, value interface{}) error { switch v := value.(type) { default: return fmt.Errorf("An item of unknown type was included in the environment or arguments of a Lua call (skipping it): %v", value) case nil: log.Println("Pushing nil onto lua stack") state.PushNil() case string: log.Println("Pushing string onto lua stack") state.PushString(v) case int: log.Println("Pushing int onto lua stack") state.PushInteger(int64(v)) case int64: log.Println("Pushing int64 onto lua stack") state.PushInteger(v) case float64: log.Println("Pushing float64 onto lua stack") state.PushNumber(v) case bool: log.Println("Pushing bool onto lua stack") state.PushBoolean(v) case map[string]interface{}: log.Println("Pushing map[string]interface{} onto lua stack") state.CreateTable(0, len(v)) for name, value := range v { err := pushValue(state, value) if err != nil { // error means nothing was added to stack. So pop our new table so *we* leave nothing added to the stack. state.Pop(1) return err } state.SetField(-2, name) } // then leave the table on the stack case ThingType: // These are singleton sentinel values, so load them from Lua-land. state.GetGlobal("world") state.GetField(-1, strings.Title(v.String())) state.Remove(-2) case *Thing: log.Println("Pushing *Thing onto lua stack") return pushValue(state, v.Id) case ThingId: log.Println("Pushing ThingId onto lua stack") // We're pushing a ThingId, so make a new userdata for it, with the Thing metatable. userdata := state.NewUserdata(uintptr(unsafe.Sizeof(int64(0)))) thingPtr := (*int64)(userdata) *thingPtr = int64(v) if !state.IsUserdata(-1) { log.Println("!!! HOGAD JUST PUSHED NEW USERDATA BUT IT ISN'T OMG !!!") } log.Println("Pushed ThingId", *thingPtr, "onto lua stack") // Now make it act like a Thing. state.LGetMetaTable(ThingMetaTableName) // ( udata -- udata mtbl ) state.SetMetaTable(-2) // ( udata mtbl -- udata ) // Let's just check that it's that, for sures. if !state.IsUserdata(-1) { log.Println("!!! WOOP WOOP DID NOT SET METATABLE RIGHT :( !!!") } } return nil }
func SetTableIntString(L *lua.State, idx int64, value string) { L.PushInteger(idx) L.PushString(value) L.SetTable(-3) }
func SetTableInt(L *lua.State, name string, value int64) { // Remember to check stack for 2 extra locations L.PushString(name) L.PushInteger(value) L.SetTable(-3) }