package gjson import ( "fmt" glua "github.com/yuin/gopher-lua" ) // cfgEncodeSparseArray configures sparse array handling. // Lua: gjson.encode_sparse_array([convert[, ratio[, safe]]]) // Returns current values when called without arguments. func (g *GJSON) cfgEncodeSparseArray(L *glua.LState) int { n := L.GetTop() if n == 0 { // Return current values L.Push(glua.LBool(g.config.encodeSparseArray.convert)) L.Push(glua.LNumber(g.config.encodeSparseArray.ratio)) L.Push(glua.LNumber(g.config.encodeSparseArray.safe)) return 3 } // Set new values if n >= 1 { g.config.encodeSparseArray.convert = L.CheckBool(1) } if n >= 2 { g.config.encodeSparseArray.ratio = L.CheckInt(2) if g.config.encodeSparseArray.ratio < 0 { L.ArgError(2, "ratio must be >= 0") } } if n >= 3 { g.config.encodeSparseArray.safe = L.CheckInt(3) if g.config.encodeSparseArray.safe < 0 { L.ArgError(3, "safe must be >= 0") } } L.Push(glua.LBool(g.config.encodeSparseArray.convert)) L.Push(glua.LNumber(g.config.encodeSparseArray.ratio)) L.Push(glua.LNumber(g.config.encodeSparseArray.safe)) return 3 } // cfgEncodeMaxDepth configures the maximum nesting depth for encoding. // Lua: gjson.encode_max_depth([depth]) func (g *GJSON) cfgEncodeMaxDepth(L *glua.LState) int { if L.GetTop() == 0 { L.Push(glua.LNumber(g.config.encodeMaxDepth)) return 1 } depth := L.CheckInt(1) if depth < 1 { L.ArgError(1, "max depth must be >= 1") } g.config.encodeMaxDepth = depth L.Push(glua.LNumber(g.config.encodeMaxDepth)) return 1 } // cfgDecodeMaxDepth configures the maximum nesting depth for decoding. // Lua: gjson.decode_max_depth([depth]) func (g *GJSON) cfgDecodeMaxDepth(L *glua.LState) int { if L.GetTop() == 0 { L.Push(glua.LNumber(g.config.decodeMaxDepth)) return 1 } depth := L.CheckInt(1) if depth < 1 { L.ArgError(1, "max depth must be >= 1") } g.config.decodeMaxDepth = depth L.Push(glua.LNumber(g.config.decodeMaxDepth)) return 1 } // cfgEncodeNumberPrecision configures the number precision for encoding. // Lua: gjson.encode_number_precision([precision]) func (g *GJSON) cfgEncodeNumberPrecision(L *glua.LState) int { if L.GetTop() == 0 { L.Push(glua.LNumber(g.config.encodeNumberPrecision)) return 1 } precision := L.CheckInt(1) if precision < 1 || precision > 14 { L.ArgError(1, "precision must be between 1 and 14") } g.config.encodeNumberPrecision = precision L.Push(glua.LNumber(g.config.encodeNumberPrecision)) return 1 } // cfgEncodeKeepBuffer configures whether to reuse the encoding buffer. // Lua: gjson.encode_keep_buffer([keep]) func (g *GJSON) cfgEncodeKeepBuffer(L *glua.LState) int { if L.GetTop() == 0 { L.Push(glua.LBool(g.config.encodeKeepBuffer)) return 1 } g.config.encodeKeepBuffer = L.CheckBool(1) L.Push(glua.LBool(g.config.encodeKeepBuffer)) return 1 } // cfgEncodeSortKeys configures whether to sort object keys for stable output. // Lua: gjson.encode_sort_keys([sort]) // Returns current value when called without arguments. // When enabled, object keys are sorted alphabetically for deterministic output. // When disabled (default), keys are output in arbitrary order for better performance. func (g *GJSON) cfgEncodeSortKeys(L *glua.LState) int { if L.GetTop() == 0 { L.Push(glua.LBool(g.config.encodeSortKeys)) return 1 } g.config.encodeSortKeys = L.CheckBool(1) L.Push(glua.LBool(g.config.encodeSortKeys)) return 1 } // encode is the Lua function for gjson.encode(value). // Returns (json_string, nil) on success or (nil, error_message) on failure. func (g *GJSON) encode(L *glua.LState) int { if L.GetTop() != 1 { L.ArgError(1, "expected 1 argument") return 0 } value := L.Get(1) result, err := g.encodeValue(L, value, 0) if err != nil { L.Push(glua.LNil) L.Push(glua.LString(err.Error())) return 2 } L.Push(glua.LString(result)) return 1 } // decode is the Lua function for gjson.decode(string). // Returns (value, nil) on success or (nil, error_message) on failure. func (g *GJSON) decode(L *glua.LState) int { if L.GetTop() != 1 { L.ArgError(1, "expected 1 argument") return 0 } str := L.CheckString(1) if str == "" { L.Push(glua.LNil) L.Push(glua.LString("empty JSON string")) return 2 } result, err := g.decodeValue(L, []byte(str), 0) if err != nil { L.Push(glua.LNil) L.Push(glua.LString(err.Error())) return 2 } L.Push(result) return 1 } // encodeValue encodes a Lua value to JSON with depth tracking. func (g *GJSON) encodeValue(L *glua.LState, value glua.LValue, depth int) (string, error) { if depth > g.config.encodeMaxDepth { return "", fmt.Errorf("maximum nesting depth %d exceeded", g.config.encodeMaxDepth) } return encodeLuaValue(L, value, g.config, depth) } // decodeValue decodes JSON to a Lua value with depth tracking. func (g *GJSON) decodeValue(L *glua.LState, data []byte, depth int) (glua.LValue, error) { if depth > g.config.decodeMaxDepth { return glua.LNil, fmt.Errorf("maximum nesting depth %d exceeded", g.config.decodeMaxDepth) } return decodeJSONValue(L, data, g.config, g.null, depth) }