Compare commits
1 Commits
cbfc8c184e
...
14009697f0
Author | SHA1 | Date | |
---|---|---|---|
14009697f0 |
447
batch.go
447
batch.go
@ -1,447 +0,0 @@
|
|||||||
package luajit
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// Batch table field setting - single C call for multiple fields
|
|
||||||
int batch_set_string_fields(lua_State *L, int table_idx,
|
|
||||||
char **keys, char **values, int count) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushstring(L, values[i]);
|
|
||||||
lua_setfield(L, table_idx, keys[i]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_set_number_fields(lua_State *L, int table_idx,
|
|
||||||
char **keys, double *values, int count) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushnumber(L, values[i]);
|
|
||||||
lua_setfield(L, table_idx, keys[i]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_set_bool_fields(lua_State *L, int table_idx,
|
|
||||||
char **keys, int *values, int count) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushboolean(L, values[i]);
|
|
||||||
lua_setfield(L, table_idx, keys[i]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch array creation - build entire array in C
|
|
||||||
int batch_push_int_array(lua_State *L, int *values, int count) {
|
|
||||||
lua_createtable(L, count, 0);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushnumber(L, i + 1);
|
|
||||||
lua_pushnumber(L, values[i]);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_push_float_array(lua_State *L, double *values, int count) {
|
|
||||||
lua_createtable(L, count, 0);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushnumber(L, i + 1);
|
|
||||||
lua_pushnumber(L, values[i]);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_push_string_array(lua_State *L, char **values, int count) {
|
|
||||||
lua_createtable(L, count, 0);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushnumber(L, i + 1);
|
|
||||||
lua_pushstring(L, values[i]);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_push_bool_array(lua_State *L, int *values, int count) {
|
|
||||||
lua_createtable(L, count, 0);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
lua_pushnumber(L, i + 1);
|
|
||||||
lua_pushboolean(L, values[i]);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch array extraction - extract entire array in C
|
|
||||||
int batch_extract_int_array(lua_State *L, int table_idx, int *buffer, int length) {
|
|
||||||
for (int i = 1; i <= length; i++) {
|
|
||||||
lua_pushnumber(L, i);
|
|
||||||
lua_gettable(L, table_idx);
|
|
||||||
buffer[i-1] = (int)lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_extract_float_array(lua_State *L, int table_idx, double *buffer, int length) {
|
|
||||||
for (int i = 1; i <= length; i++) {
|
|
||||||
lua_pushnumber(L, i);
|
|
||||||
lua_gettable(L, table_idx);
|
|
||||||
buffer[i-1] = lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_extract_string_array(lua_State *L, int table_idx, char **buffer, int length) {
|
|
||||||
for (int i = 1; i <= length; i++) {
|
|
||||||
lua_pushnumber(L, i);
|
|
||||||
lua_gettable(L, table_idx);
|
|
||||||
size_t len;
|
|
||||||
const char *str = lua_tolstring(L, -1, &len);
|
|
||||||
if (str) {
|
|
||||||
buffer[i-1] = malloc(len + 1);
|
|
||||||
memcpy(buffer[i-1], str, len);
|
|
||||||
buffer[i-1][len] = '\0';
|
|
||||||
} else {
|
|
||||||
buffer[i-1] = malloc(1);
|
|
||||||
buffer[i-1][0] = '\0';
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int batch_extract_bool_array(lua_State *L, int table_idx, int *buffer, int length) {
|
|
||||||
for (int i = 1; i <= length; i++) {
|
|
||||||
lua_pushnumber(L, i);
|
|
||||||
lua_gettable(L, table_idx);
|
|
||||||
buffer[i-1] = lua_toboolean(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BatchSetStringFields sets multiple string fields on a table in one C call
|
|
||||||
func (s *State) BatchSetStringFields(tableIndex int, fields map[string]string) error {
|
|
||||||
if len(fields) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := make([]*C.char, len(fields))
|
|
||||||
values := make([]*C.char, len(fields))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for k, v := range fields {
|
|
||||||
keys[i] = C.CString(k)
|
|
||||||
values[i] = C.CString(v)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_set_string_fields(s.L, C.int(tableIndex), &keys[0], &values[0], C.int(len(fields)))
|
|
||||||
|
|
||||||
for j := range len(fields) {
|
|
||||||
C.free(unsafe.Pointer(keys[j]))
|
|
||||||
C.free(unsafe.Pointer(values[j]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchSetNumberFields sets multiple number fields on a table in one C call
|
|
||||||
func (s *State) BatchSetNumberFields(tableIndex int, fields map[string]float64) error {
|
|
||||||
if len(fields) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := make([]*C.char, len(fields))
|
|
||||||
values := make([]C.double, len(fields))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for k, v := range fields {
|
|
||||||
keys[i] = C.CString(k)
|
|
||||||
values[i] = C.double(v)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_set_number_fields(s.L, C.int(tableIndex), &keys[0], &values[0], C.int(len(fields)))
|
|
||||||
|
|
||||||
for j := range len(fields) {
|
|
||||||
C.free(unsafe.Pointer(keys[j]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchSetBoolFields sets multiple boolean fields on a table in one C call
|
|
||||||
func (s *State) BatchSetBoolFields(tableIndex int, fields map[string]bool) error {
|
|
||||||
if len(fields) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := make([]*C.char, len(fields))
|
|
||||||
values := make([]C.int, len(fields))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for k, v := range fields {
|
|
||||||
keys[i] = C.CString(k)
|
|
||||||
if v {
|
|
||||||
values[i] = 1
|
|
||||||
} else {
|
|
||||||
values[i] = 0
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_set_bool_fields(s.L, C.int(tableIndex), &keys[0], &values[0], C.int(len(fields)))
|
|
||||||
|
|
||||||
for j := range len(fields) {
|
|
||||||
C.free(unsafe.Pointer(keys[j]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchPushIntArray creates and pushes an int array in a single C call
|
|
||||||
func (s *State) BatchPushIntArray(values []int) error {
|
|
||||||
if len(values) == 0 {
|
|
||||||
s.CreateTable(0, 0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cValues := make([]C.int, len(values))
|
|
||||||
for i, v := range values {
|
|
||||||
cValues[i] = C.int(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_push_int_array(s.L, &cValues[0], C.int(len(values)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchPushFloatArray creates and pushes a float array in a single C call
|
|
||||||
func (s *State) BatchPushFloatArray(values []float64) error {
|
|
||||||
if len(values) == 0 {
|
|
||||||
s.CreateTable(0, 0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cValues := make([]C.double, len(values))
|
|
||||||
for i, v := range values {
|
|
||||||
cValues[i] = C.double(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_push_float_array(s.L, &cValues[0], C.int(len(values)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchPushStringArray creates and pushes a string array in a single C call
|
|
||||||
func (s *State) BatchPushStringArray(values []string) error {
|
|
||||||
if len(values) == 0 {
|
|
||||||
s.CreateTable(0, 0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cValues := make([]*C.char, len(values))
|
|
||||||
for i, v := range values {
|
|
||||||
cValues[i] = C.CString(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_push_string_array(s.L, &cValues[0], C.int(len(values)))
|
|
||||||
|
|
||||||
for i := range values {
|
|
||||||
C.free(unsafe.Pointer(cValues[i]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchPushBoolArray creates and pushes a bool array in a single C call
|
|
||||||
func (s *State) BatchPushBoolArray(values []bool) error {
|
|
||||||
if len(values) == 0 {
|
|
||||||
s.CreateTable(0, 0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cValues := make([]C.int, len(values))
|
|
||||||
for i, v := range values {
|
|
||||||
if v {
|
|
||||||
cValues[i] = 1
|
|
||||||
} else {
|
|
||||||
cValues[i] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
C.batch_push_bool_array(s.L, &cValues[0], C.int(len(values)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchExtractIntArray extracts an entire int array in a single C call
|
|
||||||
func (s *State) BatchExtractIntArray(index, length int) ([]int, error) {
|
|
||||||
if length <= 0 {
|
|
||||||
return []int{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]C.int, length)
|
|
||||||
C.batch_extract_int_array(s.L, C.int(index), &buffer[0], C.int(length))
|
|
||||||
|
|
||||||
result := make([]int, length)
|
|
||||||
for i := range length {
|
|
||||||
result[i] = int(buffer[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchExtractFloatArray extracts an entire float array in a single C call
|
|
||||||
func (s *State) BatchExtractFloatArray(index, length int) ([]float64, error) {
|
|
||||||
if length <= 0 {
|
|
||||||
return []float64{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]C.double, length)
|
|
||||||
C.batch_extract_float_array(s.L, C.int(index), &buffer[0], C.int(length))
|
|
||||||
|
|
||||||
result := make([]float64, length)
|
|
||||||
for i := range length {
|
|
||||||
result[i] = float64(buffer[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchExtractStringArray extracts an entire string array in a single C call
|
|
||||||
func (s *State) BatchExtractStringArray(index, length int) ([]string, error) {
|
|
||||||
if length <= 0 {
|
|
||||||
return []string{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]*C.char, length)
|
|
||||||
C.batch_extract_string_array(s.L, C.int(index), &buffer[0], C.int(length))
|
|
||||||
|
|
||||||
result := make([]string, length)
|
|
||||||
for i := range length {
|
|
||||||
result[i] = C.GoString(buffer[i])
|
|
||||||
C.free(unsafe.Pointer(buffer[i]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchExtractBoolArray extracts an entire bool array in a single C call
|
|
||||||
func (s *State) BatchExtractBoolArray(index, length int) ([]bool, error) {
|
|
||||||
if length <= 0 {
|
|
||||||
return []bool{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]C.int, length)
|
|
||||||
C.batch_extract_bool_array(s.L, C.int(index), &buffer[0], C.int(length))
|
|
||||||
|
|
||||||
result := make([]bool, length)
|
|
||||||
for i := range length {
|
|
||||||
result[i] = buffer[i] != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchTableBuilder provides batched table building operations
|
|
||||||
type BatchTableBuilder struct {
|
|
||||||
state *State
|
|
||||||
index int
|
|
||||||
stringFields map[string]string
|
|
||||||
numberFields map[string]float64
|
|
||||||
boolFields map[string]bool
|
|
||||||
otherFields map[string]any
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBatchTableBuilder creates a table builder that batches operations
|
|
||||||
func (s *State) NewBatchTableBuilder() *BatchTableBuilder {
|
|
||||||
s.NewTable()
|
|
||||||
return &BatchTableBuilder{
|
|
||||||
state: s,
|
|
||||||
index: s.GetTop(),
|
|
||||||
stringFields: make(map[string]string),
|
|
||||||
numberFields: make(map[string]float64),
|
|
||||||
boolFields: make(map[string]bool),
|
|
||||||
otherFields: make(map[string]any),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetString queues a string field for batch setting
|
|
||||||
func (tb *BatchTableBuilder) SetString(key, value string) *BatchTableBuilder {
|
|
||||||
tb.stringFields[key] = value
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNumber queues a number field for batch setting
|
|
||||||
func (tb *BatchTableBuilder) SetNumber(key string, value float64) *BatchTableBuilder {
|
|
||||||
tb.numberFields[key] = value
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBool queues a boolean field for batch setting
|
|
||||||
func (tb *BatchTableBuilder) SetBool(key string, value bool) *BatchTableBuilder {
|
|
||||||
tb.boolFields[key] = value
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNil sets a nil field immediately
|
|
||||||
func (tb *BatchTableBuilder) SetNil(key string) *BatchTableBuilder {
|
|
||||||
tb.state.PushNil()
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTable sets a table field immediately
|
|
||||||
func (tb *BatchTableBuilder) SetTable(key string, value any) *BatchTableBuilder {
|
|
||||||
tb.otherFields[key] = value
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetArray sets an array field immediately
|
|
||||||
func (tb *BatchTableBuilder) SetArray(key string, values []any) *BatchTableBuilder {
|
|
||||||
tb.otherFields[key] = values
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build executes all batched operations and finalizes the table
|
|
||||||
func (tb *BatchTableBuilder) Build() error {
|
|
||||||
// Batch string fields
|
|
||||||
if len(tb.stringFields) > 0 {
|
|
||||||
if err := tb.state.BatchSetStringFields(tb.index, tb.stringFields); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch number fields
|
|
||||||
if len(tb.numberFields) > 0 {
|
|
||||||
if err := tb.state.BatchSetNumberFields(tb.index, tb.numberFields); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch boolean fields
|
|
||||||
if len(tb.boolFields) > 0 {
|
|
||||||
if err := tb.state.BatchSetBoolFields(tb.index, tb.boolFields); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Individual operations for complex types
|
|
||||||
for key, value := range tb.otherFields {
|
|
||||||
if err := tb.state.PushValue(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
69
builder.go
69
builder.go
@ -66,75 +66,6 @@ func (tb *TableBuilder) SetArray(key string, values []any) *TableBuilder {
|
|||||||
return tb
|
return tb
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchBuild builds a table from a map using batched operations
|
|
||||||
func (tb *TableBuilder) BatchBuild(data map[string]any) *TableBuilder {
|
|
||||||
stringFields := make(map[string]string)
|
|
||||||
numberFields := make(map[string]float64)
|
|
||||||
boolFields := make(map[string]bool)
|
|
||||||
|
|
||||||
// Separate fields by type for batching
|
|
||||||
for key, value := range data {
|
|
||||||
switch v := value.(type) {
|
|
||||||
case string:
|
|
||||||
stringFields[key] = v
|
|
||||||
case int:
|
|
||||||
numberFields[key] = float64(v)
|
|
||||||
case int64:
|
|
||||||
numberFields[key] = float64(v)
|
|
||||||
case float64:
|
|
||||||
numberFields[key] = v
|
|
||||||
case float32:
|
|
||||||
numberFields[key] = float64(v)
|
|
||||||
case bool:
|
|
||||||
boolFields[key] = v
|
|
||||||
case []int:
|
|
||||||
if len(v) > 5 {
|
|
||||||
tb.state.BatchPushIntArray(v)
|
|
||||||
} else {
|
|
||||||
tb.state.PushValue(value)
|
|
||||||
}
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
case []string:
|
|
||||||
if len(v) > 3 {
|
|
||||||
tb.state.BatchPushStringArray(v)
|
|
||||||
} else {
|
|
||||||
tb.state.PushValue(value)
|
|
||||||
}
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
case []float64:
|
|
||||||
if len(v) > 5 {
|
|
||||||
tb.state.BatchPushFloatArray(v)
|
|
||||||
} else {
|
|
||||||
tb.state.PushValue(value)
|
|
||||||
}
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
case []bool:
|
|
||||||
if len(v) > 5 {
|
|
||||||
tb.state.BatchPushBoolArray(v)
|
|
||||||
} else {
|
|
||||||
tb.state.PushValue(value)
|
|
||||||
}
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
default:
|
|
||||||
tb.state.PushValue(value)
|
|
||||||
tb.state.SetField(tb.index, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute batched operations
|
|
||||||
if len(stringFields) > 0 {
|
|
||||||
tb.state.BatchSetStringFields(tb.index, stringFields)
|
|
||||||
}
|
|
||||||
if len(numberFields) > 0 {
|
|
||||||
tb.state.BatchSetNumberFields(tb.index, numberFields)
|
|
||||||
}
|
|
||||||
if len(boolFields) > 0 {
|
|
||||||
tb.state.BatchSetBoolFields(tb.index, boolFields)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tb
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build finalizes the table (no-op, table is already on stack)
|
// Build finalizes the table (no-op, table is already on stack)
|
||||||
func (tb *TableBuilder) Build() {
|
func (tb *TableBuilder) Build() {
|
||||||
// Table is already on the stack at tb.index
|
// Table is already on the stack at tb.index
|
||||||
|
149
wrapper.go
149
wrapper.go
@ -71,38 +71,6 @@ static int sample_array_type(lua_State *L, int index, int count) {
|
|||||||
if (all_bools) return 4;
|
if (all_bools) return 4;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sample_map_type(lua_State *L, int index, int max_samples) {
|
|
||||||
int all_numbers = 1;
|
|
||||||
int all_integers = 1;
|
|
||||||
int all_strings = 1;
|
|
||||||
int all_bools = 1;
|
|
||||||
int samples = 0;
|
|
||||||
|
|
||||||
lua_pushnil(L);
|
|
||||||
while (lua_next(L, index) != 0 && samples < max_samples) {
|
|
||||||
if (lua_type(L, -2) == LUA_TSTRING) {
|
|
||||||
int type = lua_type(L, -1);
|
|
||||||
if (type != LUA_TNUMBER) all_numbers = all_integers = 0;
|
|
||||||
if (type != LUA_TSTRING) all_strings = 0;
|
|
||||||
if (type != LUA_TBOOLEAN) all_bools = 0;
|
|
||||||
|
|
||||||
if (all_numbers && !is_integer(L, -1)) all_integers = 0;
|
|
||||||
|
|
||||||
samples++;
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
if (!all_numbers && !all_strings && !all_bools) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samples == 0) return 0;
|
|
||||||
if (all_integers) return 1;
|
|
||||||
if (all_numbers) return 2;
|
|
||||||
if (all_strings) return 3;
|
|
||||||
if (all_bools) return 4;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
@ -238,6 +206,8 @@ func (s *State) PushValue(v any) error {
|
|||||||
s.PushNumber(val)
|
s.PushNumber(val)
|
||||||
case string:
|
case string:
|
||||||
s.PushString(val)
|
s.PushString(val)
|
||||||
|
case []byte:
|
||||||
|
s.PushString(string(val))
|
||||||
case []int:
|
case []int:
|
||||||
return s.pushIntSlice(val)
|
return s.pushIntSlice(val)
|
||||||
case []string:
|
case []string:
|
||||||
@ -265,9 +235,6 @@ func (s *State) PushValue(v any) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) pushIntSlice(arr []int) error {
|
func (s *State) pushIntSlice(arr []int) error {
|
||||||
if len(arr) > 5 {
|
|
||||||
return s.BatchPushIntArray(arr)
|
|
||||||
}
|
|
||||||
s.CreateTable(len(arr), 0)
|
s.CreateTable(len(arr), 0)
|
||||||
for i, v := range arr {
|
for i, v := range arr {
|
||||||
s.PushNumber(float64(i + 1))
|
s.PushNumber(float64(i + 1))
|
||||||
@ -278,9 +245,6 @@ func (s *State) pushIntSlice(arr []int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) pushStringSlice(arr []string) error {
|
func (s *State) pushStringSlice(arr []string) error {
|
||||||
if len(arr) > 3 {
|
|
||||||
return s.BatchPushStringArray(arr)
|
|
||||||
}
|
|
||||||
s.CreateTable(len(arr), 0)
|
s.CreateTable(len(arr), 0)
|
||||||
for i, v := range arr {
|
for i, v := range arr {
|
||||||
s.PushNumber(float64(i + 1))
|
s.PushNumber(float64(i + 1))
|
||||||
@ -291,9 +255,6 @@ func (s *State) pushStringSlice(arr []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) pushBoolSlice(arr []bool) error {
|
func (s *State) pushBoolSlice(arr []bool) error {
|
||||||
if len(arr) > 5 {
|
|
||||||
return s.BatchPushBoolArray(arr)
|
|
||||||
}
|
|
||||||
s.CreateTable(len(arr), 0)
|
s.CreateTable(len(arr), 0)
|
||||||
for i, v := range arr {
|
for i, v := range arr {
|
||||||
s.PushNumber(float64(i + 1))
|
s.PushNumber(float64(i + 1))
|
||||||
@ -304,9 +265,6 @@ func (s *State) pushBoolSlice(arr []bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) pushFloatSlice(arr []float64) error {
|
func (s *State) pushFloatSlice(arr []float64) error {
|
||||||
if len(arr) > 5 {
|
|
||||||
return s.BatchPushFloatArray(arr)
|
|
||||||
}
|
|
||||||
s.CreateTable(len(arr), 0)
|
s.CreateTable(len(arr), 0)
|
||||||
for i, v := range arr {
|
for i, v := range arr {
|
||||||
s.PushNumber(float64(i + 1))
|
s.PushNumber(float64(i + 1))
|
||||||
@ -330,9 +288,6 @@ func (s *State) pushAnySlice(arr []any) error {
|
|||||||
|
|
||||||
func (s *State) pushStringMap(m map[string]string) error {
|
func (s *State) pushStringMap(m map[string]string) error {
|
||||||
s.CreateTable(0, len(m))
|
s.CreateTable(0, len(m))
|
||||||
if len(m) > 3 {
|
|
||||||
return s.BatchSetStringFields(-1, m)
|
|
||||||
}
|
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
s.PushString(k)
|
s.PushString(k)
|
||||||
s.PushString(v)
|
s.PushString(v)
|
||||||
@ -343,13 +298,6 @@ func (s *State) pushStringMap(m map[string]string) error {
|
|||||||
|
|
||||||
func (s *State) pushIntMap(m map[string]int) error {
|
func (s *State) pushIntMap(m map[string]int) error {
|
||||||
s.CreateTable(0, len(m))
|
s.CreateTable(0, len(m))
|
||||||
if len(m) > 3 {
|
|
||||||
numberFields := make(map[string]float64, len(m))
|
|
||||||
for k, v := range m {
|
|
||||||
numberFields[k] = float64(v)
|
|
||||||
}
|
|
||||||
return s.BatchSetNumberFields(-1, numberFields)
|
|
||||||
}
|
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
s.PushString(k)
|
s.PushString(k)
|
||||||
s.PushNumber(float64(v))
|
s.PushNumber(float64(v))
|
||||||
@ -404,54 +352,6 @@ func (s *State) ToValue(index int) (any, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) extractStringMap(index int) map[string]string {
|
|
||||||
result := make(map[string]string)
|
|
||||||
s.PushNil()
|
|
||||||
for s.Next(index) {
|
|
||||||
if s.IsString(-2) && s.IsString(-1) {
|
|
||||||
result[s.ToString(-2)] = s.ToString(-1)
|
|
||||||
}
|
|
||||||
s.Pop(1)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) extractIntMap(index int) map[string]int {
|
|
||||||
result := make(map[string]int)
|
|
||||||
s.PushNil()
|
|
||||||
for s.Next(index) {
|
|
||||||
if s.IsString(-2) && s.IsNumber(-1) {
|
|
||||||
result[s.ToString(-2)] = int(s.ToNumber(-1))
|
|
||||||
}
|
|
||||||
s.Pop(1)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) extractFloatMap(index int) map[string]float64 {
|
|
||||||
result := make(map[string]float64)
|
|
||||||
s.PushNil()
|
|
||||||
for s.Next(index) {
|
|
||||||
if s.IsString(-2) && s.IsNumber(-1) {
|
|
||||||
result[s.ToString(-2)] = s.ToNumber(-1)
|
|
||||||
}
|
|
||||||
s.Pop(1)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) extractBoolMap(index int) map[string]bool {
|
|
||||||
result := make(map[string]bool)
|
|
||||||
s.PushNil()
|
|
||||||
for s.Next(index) {
|
|
||||||
if s.IsString(-2) && s.IsBoolean(-1) {
|
|
||||||
result[s.ToString(-2)] = s.ToBoolean(-1)
|
|
||||||
}
|
|
||||||
s.Pop(1)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToTable converts a Lua table to optimal Go type
|
// ToTable converts a Lua table to optimal Go type
|
||||||
func (s *State) ToTable(index int) (any, error) {
|
func (s *State) ToTable(index int) (any, error) {
|
||||||
absIdx := s.absIndex(index)
|
absIdx := s.absIndex(index)
|
||||||
@ -464,41 +364,23 @@ func (s *State) ToTable(index int) (any, error) {
|
|||||||
if length > 0 {
|
if length > 0 {
|
||||||
arrayType := int(C.sample_array_type(s.L, C.int(absIdx), C.int(length)))
|
arrayType := int(C.sample_array_type(s.L, C.int(absIdx), C.int(length)))
|
||||||
switch arrayType {
|
switch arrayType {
|
||||||
case 1:
|
case 1: // int array
|
||||||
return s.extractIntArray(absIdx, length), nil
|
return s.extractIntArray(absIdx, length), nil
|
||||||
case 2:
|
case 2: // float array
|
||||||
return s.extractFloatArray(absIdx, length), nil
|
return s.extractFloatArray(absIdx, length), nil
|
||||||
case 3:
|
case 3: // string array
|
||||||
return s.extractStringArray(absIdx, length), nil
|
return s.extractStringArray(absIdx, length), nil
|
||||||
case 4:
|
case 4: // bool array
|
||||||
return s.extractBoolArray(absIdx, length), nil
|
return s.extractBoolArray(absIdx, length), nil
|
||||||
default:
|
default: // mixed array
|
||||||
return s.extractAnyArray(absIdx, length), nil
|
return s.extractAnyArray(absIdx, length), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapType := int(C.sample_map_type(s.L, C.int(absIdx), C.int(5)))
|
return s.extractAnyMap(absIdx)
|
||||||
switch mapType {
|
|
||||||
case 1:
|
|
||||||
return s.extractIntMap(absIdx), nil
|
|
||||||
case 2:
|
|
||||||
return s.extractFloatMap(absIdx), nil
|
|
||||||
case 3:
|
|
||||||
return s.extractStringMap(absIdx), nil
|
|
||||||
case 4:
|
|
||||||
return s.extractBoolMap(absIdx), nil
|
|
||||||
default:
|
|
||||||
result, err := s.extractAnyMap(absIdx)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) extractIntArray(index, length int) []int {
|
func (s *State) extractIntArray(index, length int) []int {
|
||||||
if length > 10 {
|
|
||||||
if result, err := s.BatchExtractIntArray(index, length); err == nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := make([]int, length)
|
result := make([]int, length)
|
||||||
for i := 1; i <= length; i++ {
|
for i := 1; i <= length; i++ {
|
||||||
s.PushNumber(float64(i))
|
s.PushNumber(float64(i))
|
||||||
@ -510,11 +392,6 @@ func (s *State) extractIntArray(index, length int) []int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) extractFloatArray(index, length int) []float64 {
|
func (s *State) extractFloatArray(index, length int) []float64 {
|
||||||
if length > 10 {
|
|
||||||
if result, err := s.BatchExtractFloatArray(index, length); err == nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := make([]float64, length)
|
result := make([]float64, length)
|
||||||
for i := 1; i <= length; i++ {
|
for i := 1; i <= length; i++ {
|
||||||
s.PushNumber(float64(i))
|
s.PushNumber(float64(i))
|
||||||
@ -526,11 +403,6 @@ func (s *State) extractFloatArray(index, length int) []float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) extractStringArray(index, length int) []string {
|
func (s *State) extractStringArray(index, length int) []string {
|
||||||
if length > 5 {
|
|
||||||
if result, err := s.BatchExtractStringArray(index, length); err == nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := make([]string, length)
|
result := make([]string, length)
|
||||||
for i := 1; i <= length; i++ {
|
for i := 1; i <= length; i++ {
|
||||||
s.PushNumber(float64(i))
|
s.PushNumber(float64(i))
|
||||||
@ -542,11 +414,6 @@ func (s *State) extractStringArray(index, length int) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) extractBoolArray(index, length int) []bool {
|
func (s *State) extractBoolArray(index, length int) []bool {
|
||||||
if length > 10 {
|
|
||||||
if result, err := s.BatchExtractBoolArray(index, length); err == nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := make([]bool, length)
|
result := make([]bool, length)
|
||||||
for i := 1; i <= length; i++ {
|
for i := 1; i <= length; i++ {
|
||||||
s.PushNumber(float64(i))
|
s.PushNumber(float64(i))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user