summaryrefslogtreecommitdiff
path: root/lua.go
diff options
context:
space:
mode:
authorunwox <me@unwox.com>2025-09-09 16:37:32 +0600
committerunwox <me@unwox.com>2025-09-09 16:41:39 +0600
commitc26739ce130bc40ded6ff9dfea1be1eba1a2e4eb (patch)
tree83a150bbea75a174418dae25628c09f8b5b42106 /lua.go
parent40abca541e331c213a5cc94c676d58b3ca84b7ad (diff)
support ntables in Lua.Scan
Diffstat (limited to 'lua.go')
-rw-r--r--lua.go113
1 files changed, 5 insertions, 108 deletions
diff --git a/lua.go b/lua.go
index f90ba38..fb0b72a 100644
--- a/lua.go
+++ b/lua.go
@@ -25,9 +25,7 @@ import "C"
import (
"errors"
"fmt"
- "reflect"
"runtime/cgo"
- "slices"
"time"
"unsafe"
)
@@ -205,6 +203,11 @@ func (l *Lua) GetTableItem(key string) {
C.lua_getfield(l.l, -1, C.CString(key))
}
+// RawGetI pushes onto the stack value from table from tableOffset at index i.
+func (l *Lua) RawGetI(tableOffset, i int) {
+ C.lua_rawgeti(l.l, C.int(tableOffset), C.longlong(i))
+}
+
// PushAny pushes value v onto the stack.
func (l *Lua) PushAny(v any) error {
switch v.(type) {
@@ -348,112 +351,6 @@ func (l *Lua) LoadAndCall(code string) error {
return nil
}
-// Scan scans values from the Lua stack into vars according to their types.
-func (l *Lua) Scan(vars ...any) error {
- slices.Reverse(vars)
- for i, v := range vars {
- t := reflect.TypeOf(v)
- // unwrap pointers
- for t.Kind() == reflect.Ptr {
- t = t.Elem()
- }
- tk := t.Kind()
- if t.Name() == "LuaRef" {
- if l.IsFunction(-1) == false {
- return fmt.Errorf(
- "passed arg #%d must be function",
- len(vars)-i,
- )
- }
- *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(
- "passed arg #%d must be string",
- len(vars)-i,
- )
- }
- *v.(*string) = l.ToString(-1)
- l.Pop(1)
- } else if tk == reflect.Int {
- if l.IsNumber(-1) == false {
- return fmt.Errorf(
- "passed arg #%d must be number",
- len(vars)-i,
- )
- }
- *v.(*int) = l.ToInt(-1)
- l.Pop(1)
- } else if tk == reflect.Map && t.Key().Kind() == reflect.String {
- // TODO: should be possible to use maps with any types
- // of value, not only strings.
- vm, _ := v.(*map[string]string)
- l.PushNil()
- for l.Next() {
- if !l.IsString(-1) {
- return fmt.Errorf(
- "map arg #%d must only have string values",
- len(vars)-i,
- )
- }
- if !l.IsString(-2) {
- return fmt.Errorf(
- "map arg #%d must only have string keys",
- len(vars)-i,
- )
- }
- 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] = 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.IsBoolean(-1) {
- v = l.ToBoolean(-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 {
- return fmt.Errorf("unknown var type: %s", t)
- }
- }
- return nil
-}
-
// RestoreStackFunc remembers the Lua stack size and then restores it when a
// returned function is called. It's a helper function to avoid stack leakage.
func (l *Lua) RestoreStackFunc() func () {