diff options
| author | unwox <me@unwox.com> | 2024-09-14 15:54:27 +0600 |
|---|---|---|
| committer | unwox <me@unwox.com> | 2024-09-14 23:59:38 +0600 |
| commit | cc8d3cf4a7cd296d8c409fef5db9df138c3b238d (patch) | |
| tree | 4eae9d64ce9927e8b505fad359511bab22eccd80 /lua.go | |
| parent | 986522e417406956e83362e08adbd6a18ec904a5 (diff) | |
add luna.db.* module
Diffstat (limited to 'lua.go')
| -rw-r--r-- | lua.go | 138 |
1 files changed, 108 insertions, 30 deletions
@@ -25,6 +25,7 @@ import ( "reflect" "runtime/cgo" "slices" + "time" "unsafe" ) @@ -66,7 +67,7 @@ func (l *Lua) Require(file string) error { return nil } -// PCall calls a function with the stack index (-nargs - 1) expecting nresults +// PCall calls a function with the stack index (-nargs-1) expecting nresults // number of results. func (l *Lua) PCall(nargs int, nresults int) error { res := C.lua_pcallk(l.l, C.int(nargs), C.int(nresults), 0, 0, nil) @@ -122,6 +123,11 @@ func (l *Lua) PushNumber(num int) { C.lua_pushnumber(l.l, C.double(num)) } +// PushNumber pushes the number onto the Lua stack. +func (l *Lua) PushFloatNumber(num float64) { + C.lua_pushnumber(l.l, C.double(num)) +} + // PushString pushes the string onto the Lua stack. func (l *Lua) PushString(str string) { cstr := C.CString(str) @@ -153,36 +159,64 @@ func (l *Lua) SetTableItem(key string) { C.lua_setfield(l.l, -2, C.CString(key)) } -// PushTable pushes string->any table onto the stack. +// PushAny pushes value v onto the stack. +func (l *Lua) PushAny(v any) error { + switch v.(type) { + case string: + v, _ := v.(string) + l.PushString(v) + case func (l *Lua) int: + v, _ := v.(func (l *Lua) int) + l.PushGoFunction(v) + case int: + v, _ := v.(int) + l.PushNumber(v) + case int64: + v, _ := v.(int64) + l.PushNumber(int(v)) + case float64: + v, _ := v.(float64) + l.PushFloatNumber(v) + case map[string]any: + v, _ := v.(map[string]any) + l.PushObject(v) + case []any: + v, _ := v.([]any) + l.PushArray(v) + case time.Time: + v, _ := v.(time.Time) + l.PushString(v.Format(time.DateTime)) + default: + return fmt.Errorf("unsupported value type: %T", v) + } + return nil +} + +// PushObject recursively pushes string->any Go table onto the stack. func (l *Lua) PushObject(table map[string]any) error { - var pushTable func(t map[string]any) error - pushTable = func (t map[string]any) error { - l.CreateTable(len(t)) - for k, v := range t { - switch v.(type) { - case string: - v, _ := v.(string) - l.PushString(v) - case func (l *Lua) int: - v, _ := v.(func (l *Lua) int) - l.PushGoFunction(v) - case int: - v, _ := v.(int) - l.PushNumber(v) - case map[string]any: - v, _ := v.(map[string]any) - pushTable(v) - default: - return fmt.Errorf( - "unsupported value type: %T", - v, - ) - } - l.SetTableItem(k) + l.CreateTable(len(table)) + for k, v := range table { + err := l.PushAny(v) + if err != nil { + return err } - return nil + l.SetTableItem(k) } - return pushTable(table) + return nil +} + +// PushArray recursively pushes an array of Go values onto the stack. +func (l *Lua) PushArray(array []any) error { + l.CreateTable(len(array)) + for k, v := range array { + l.PushNumber(k + 1) + err := l.PushAny(v) + if err != nil { + return err + } + C.lua_settable(l.l, C.int(-3)) + } + return nil } // PushFromRef pushes a value from registry ref onto the stack. @@ -190,6 +224,16 @@ func (l *Lua) PushFromRef(ref LuaRef) { C.lua_rawgeti(l.l, C.LUA_REGISTRYINDEX, C.longlong(ref)); } +// Type returns type of the value sitting at n index on the stack. +func (l *Lua) Type(n int) int { + return int(C.lua_type(l.l, C.int(n))) +} + +// IsNil checks if the stack contains nil under the given index. +func (l *Lua) IsNil(index int) bool { + return C.lua_type(l.l, C.int(index)) == C.LUA_TNIL +} + // IsString checks if the stack contains a string under the given index. func (l *Lua) IsString(index int) bool { return C.lua_isstring(l.l, C.int(index)) == 1 @@ -251,6 +295,15 @@ func (l *Lua) Scan(vars ...any) error { ) } *v.(*LuaRef) = l.PopToRef() + } else if t.String() == "cgo.Handle" { + if l.IsNumber(-1) == false { + return fmt.Errorf( + "passed arg #%d must be Go handler", + len(vars)-i, + ) + } + *v.(*cgo.Handle) = cgo.Handle(uintptr(l.ToInt(-1))) + l.Pop(1) } else if tk == reflect.String { if l.IsString(-1) == false { return fmt.Errorf( @@ -287,13 +340,38 @@ func (l *Lua) Scan(vars ...any) error { len(vars)-i, ) } - iv := l.ToString(-1) + v := l.ToString(-1) l.Pop(1) // We must not pop the item key from the stack // because otherwise C.lua_next won't work // properly. k := l.ToString(-1) - (*vm)[k] = iv + (*vm)[k] = v + } + l.Pop(1) + } else if tk == reflect.Slice && + t.Elem().Kind() == reflect.Interface { + if !l.IsTable(-1) { + return fmt.Errorf( + "passed arg #%d must be a table", + len(vars)-i, + ) + } + va, _ := v.(*[]any) + l.PushNil() + for l.Next() { + var v any = nil + if l.IsString(-1) { + v = l.ToString(-1) + } else if l.IsNumber(-1) { + v = l.ToInt(-1) + } else if l.IsNil(-1) { + v = nil + } else { + return fmt.Errorf("unknown value in array") + } + l.Pop(1) + (*va) = append((*va), v) } l.Pop(1) } else { |
