Fix up some miscellaneous shit around the project regarding lua conversions

This commit is contained in:
2025-03-25 17:46:21 +01:00
parent 1bcc6735ab
commit 15ae116447
4 changed files with 101 additions and 85 deletions

9
.vscode/launch.json vendored
View File

@@ -9,8 +9,13 @@
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${fileDirname}", "program": "${workspaceFolder}",
"args": [] "args": [
"-mode=json",
"$..name",
"v='pero'",
"test.json"
]
} }
] ]
} }

22
main.go
View File

@@ -32,7 +32,6 @@ var logger *log.Logger
var ( var (
fileModeFlag = flag.String("mode", "regex", "Processing mode: regex, xml, json") fileModeFlag = flag.String("mode", "regex", "Processing mode: regex, xml, json")
verboseFlag = flag.Bool("verbose", false, "Enable verbose output")
) )
func init() { func init() {
@@ -48,12 +47,6 @@ func main() {
fmt.Fprintf(os.Stderr, "\nOptions:\n") fmt.Fprintf(os.Stderr, "\nOptions:\n")
fmt.Fprintf(os.Stderr, " -mode string\n") fmt.Fprintf(os.Stderr, " -mode string\n")
fmt.Fprintf(os.Stderr, " Processing mode: regex, xml, json (default \"regex\")\n") fmt.Fprintf(os.Stderr, " Processing mode: regex, xml, json (default \"regex\")\n")
fmt.Fprintf(os.Stderr, " -xpath string\n")
fmt.Fprintf(os.Stderr, " XPath expression (for XML mode)\n")
fmt.Fprintf(os.Stderr, " -jsonpath string\n")
fmt.Fprintf(os.Stderr, " JSONPath expression (for JSON mode)\n")
fmt.Fprintf(os.Stderr, " -verbose\n")
fmt.Fprintf(os.Stderr, " Enable verbose output\n")
fmt.Fprintf(os.Stderr, "\nExamples:\n") fmt.Fprintf(os.Stderr, "\nExamples:\n")
fmt.Fprintf(os.Stderr, " Regex mode (default):\n") fmt.Fprintf(os.Stderr, " Regex mode (default):\n")
fmt.Fprintf(os.Stderr, " %s \"<value>(\\d+)</value>\" \"*1.5\" data.xml\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s \"<value>(\\d+)</value>\" \"*1.5\" data.xml\n", os.Args[0])
@@ -83,15 +76,9 @@ func main() {
var pattern, luaExpr string var pattern, luaExpr string
var filePatterns []string var filePatterns []string
if *fileModeFlag == "regex" {
pattern = args[0] pattern = args[0]
luaExpr = args[1] luaExpr = args[1]
filePatterns = args[2:] filePatterns = args[2:]
} else {
// For XML/JSON modes, pattern comes from flags
luaExpr = args[0]
filePatterns = args[1:]
}
// Prepare the Lua expression // Prepare the Lua expression
originalLuaExpr := luaExpr originalLuaExpr := luaExpr
@@ -124,11 +111,10 @@ func main() {
// pattern = *xpathFlag // pattern = *xpathFlag
// logger.Printf("Starting XML modifier with XPath %q, expression %q on %d files", // logger.Printf("Starting XML modifier with XPath %q, expression %q on %d files",
// pattern, luaExpr, len(files)) // pattern, luaExpr, len(files))
// case "json": case "json":
// proc = &processor.JSONProcessor{} proc = &processor.JSONProcessor{}
// pattern = *jsonpathFlag logger.Printf("Starting JSON modifier with JSONPath %q, expression %q on %d files",
// logger.Printf("Starting JSON modifier with JSONPath %q, expression %q on %d files", pattern, luaExpr, len(files))
// pattern, luaExpr, len(files))
} }
var wg sync.WaitGroup var wg sync.WaitGroup

View File

@@ -3,6 +3,7 @@ package processor
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"modify/processor/jsonpath" "modify/processor/jsonpath"
"os" "os"
"path/filepath" "path/filepath"
@@ -67,34 +68,44 @@ func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr s
return content, 0, 0, nil return content, 0, 0, nil
} }
for _, node := range nodes {
log.Printf("Processing node at path: %s with value: %v", node.Path, node.Value)
// Initialize Lua // Initialize Lua
L, err := NewLuaState() L, err := NewLuaState()
if err != nil { if err != nil {
return content, len(nodes), 0, fmt.Errorf("error creating Lua state: %v", err) return content, len(nodes), 0, fmt.Errorf("error creating Lua state: %v", err)
} }
defer L.Close() defer L.Close()
log.Println("Lua state initialized successfully.")
err = p.ToLua(L, nodes) err = p.ToLua(L, node.Value)
if err != nil { if err != nil {
return content, len(nodes), 0, fmt.Errorf("error converting to Lua: %v", err) return content, len(nodes), 0, fmt.Errorf("error converting to Lua: %v", err)
} }
log.Printf("Converted node value to Lua: %v", node.Value)
// Execute Lua script // Execute Lua script
log.Printf("Executing Lua script: %s", luaExpr)
if err := L.DoString(luaExpr); err != nil { if err := L.DoString(luaExpr); err != nil {
return content, len(nodes), 0, fmt.Errorf("error executing Lua %s: %v", luaExpr, err) return content, len(nodes), 0, fmt.Errorf("error executing Lua %s: %v", luaExpr, err)
} }
log.Println("Lua script executed successfully.")
// Get modified value // Get modified value
result, err := p.FromLua(L) result, err := p.FromLua(L)
if err != nil { if err != nil {
return content, len(nodes), 0, fmt.Errorf("error getting result from Lua: %v", err) return content, len(nodes), 0, fmt.Errorf("error getting result from Lua: %v", err)
} }
log.Printf("Retrieved modified value from Lua: %v", result)
// Apply the modification to the JSON data // Apply the modification to the JSON data
err = p.updateJSONValue(jsonData, pattern, result) err = p.updateJSONValue(jsonData, node.Path, result)
if err != nil { if err != nil {
return content, len(nodes), 0, fmt.Errorf("error updating JSON: %v", err) return content, len(nodes), 0, fmt.Errorf("error updating JSON: %v", err)
} }
log.Printf("Updated JSON at path: %s with new value: %v", node.Path, result)
}
// Convert the modified JSON back to a string with same formatting // Convert the modified JSON back to a string with same formatting
var jsonBytes []byte var jsonBytes []byte
@@ -154,12 +165,16 @@ func detectJsonIndentation(content string) (string, error) {
// updateJSONValue updates a value in the JSON structure based on its JSONPath // updateJSONValue updates a value in the JSON structure based on its JSONPath
func (p *JSONProcessor) updateJSONValue(jsonData interface{}, path string, newValue interface{}) error { func (p *JSONProcessor) updateJSONValue(jsonData interface{}, path string, newValue interface{}) error {
err := jsonpath.Set(jsonData, path, newValue)
if err != nil {
return fmt.Errorf("failed to update JSON value at path '%s': %w", path, err)
}
return nil return nil
} }
// ToLua converts JSON values to Lua variables // ToLua converts JSON values to Lua variables
func (p *JSONProcessor) ToLua(L *lua.LState, data interface{}) error { func (p *JSONProcessor) ToLua(L *lua.LState, data interface{}) error {
table, err := ToLuaTable(L, data) table, err := ToLua(L, data)
if err != nil { if err != nil {
return err return err
} }
@@ -170,5 +185,5 @@ func (p *JSONProcessor) ToLua(L *lua.LState, data interface{}) error {
// FromLua retrieves values from Lua // FromLua retrieves values from Lua
func (p *JSONProcessor) FromLua(L *lua.LState) (interface{}, error) { func (p *JSONProcessor) FromLua(L *lua.LState) (interface{}, error) {
luaValue := L.GetGlobal("v") luaValue := L.GetGlobal("v")
return FromLuaTable(L, luaValue.(*lua.LTable)) return FromLua(L, luaValue)
} }

View File

@@ -2,7 +2,7 @@ package processor
import ( import (
"fmt" "fmt"
"reflect" "strconv"
"strings" "strings"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
@@ -52,65 +52,75 @@ func NewLuaState() (*lua.LState, error) {
return L, nil return L, nil
} }
// ToLuaTable converts a struct or map to a Lua table recursively // ToLua converts a struct or map to a Lua table recursively
func ToLuaTable(L *lua.LState, data interface{}) (*lua.LTable, error) { func ToLua(L *lua.LState, data interface{}) (lua.LValue, error) {
luaTable := L.NewTable()
switch v := data.(type) { switch v := data.(type) {
case map[string]interface{}: case map[string]interface{}:
luaTable := L.NewTable()
for key, value := range v { for key, value := range v {
luaValue, err := ToLuaTable(L, value) luaValue, err := ToLua(L, value)
if err != nil { if err != nil {
return nil, err return nil, err
} }
luaTable.RawSetString(key, luaValue) luaTable.RawSetString(key, luaValue)
} }
case struct{}: return luaTable, nil
val := reflect.ValueOf(v) case []interface{}:
for i := 0; i < val.NumField(); i++ { luaTable := L.NewTable()
field := val.Type().Field(i) for i, value := range v {
luaValue, err := ToLuaTable(L, val.Field(i).Interface()) luaValue, err := ToLua(L, value)
if err != nil { if err != nil {
return nil, err return nil, err
} }
luaTable.RawSetString(field.Name, luaValue) luaTable.RawSetInt(i+1, luaValue) // Lua arrays are 1-indexed
} }
return luaTable, nil
case string: case string:
luaTable.RawSetString("v", lua.LString(v)) return lua.LString(v), nil
case bool: case bool:
luaTable.RawSetString("v", lua.LBool(v)) return lua.LBool(v), nil
case float64: case float64:
luaTable.RawSetString("v", lua.LNumber(v)) return lua.LNumber(v), nil
default: default:
return nil, fmt.Errorf("unsupported data type: %T", data) return nil, fmt.Errorf("unsupported data type: %T", data)
} }
return luaTable, nil
} }
// FromLuaTable converts a Lua table to a struct or map recursively // FromLua converts a Lua table to a struct or map recursively
func FromLuaTable(L *lua.LState, luaTable *lua.LTable) (map[string]interface{}, error) { func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
result := make(map[string]interface{}) switch v := luaValue.(type) {
luaTable.ForEach(func(key lua.LValue, value lua.LValue) {
switch v := value.(type) {
case *lua.LTable: case *lua.LTable:
nestedMap, err := FromLuaTable(L, v) result := make(map[string]interface{})
if err != nil { v.ForEach(func(key lua.LValue, value lua.LValue) {
return result[key.String()], _ = FromLua(L, value)
}
result[key.String()] = nestedMap
case lua.LString:
result[key.String()] = string(v)
case lua.LBool:
result[key.String()] = bool(v)
case lua.LNumber:
result[key.String()] = float64(v)
default:
result[key.String()] = nil
}
}) })
// This may be a bit wasteful...
// Hopefully it won't run often enough to matter
isArray := true
for key := range result {
_, err := strconv.Atoi(key)
if err != nil {
isArray = false
break
}
}
if isArray {
list := make([]interface{}, 0, len(result))
for _, value := range result {
list = append(list, value)
}
return list, nil
}
return result, nil return result, nil
case lua.LString:
return string(v), nil
case lua.LBool:
return bool(v), nil
case lua.LNumber:
return float64(v), nil
default:
return nil, nil
}
} }
// InitLuaHelpers initializes common Lua helper functions // InitLuaHelpers initializes common Lua helper functions