feat(json): hb_jsonDecode 2-arg byref form (Harbour-spec compatible)
Previously hb_jsonDecode took only (cJSON) and returned the value.
That covers most uses but not the Harbour-spec second form
nBytesParsed := hb_jsonDecode( cJSON, @xOut )
which mod_harbour / fivenode PRG (e.g. bridge_context.prg's
ctx_get / ctx_set) and any other code that wants the parse-length
relies on. The byref output was silently dropped, so a hash lookup
went through the @hOut path that was always NIL and fell back to
the default value — looking like a hash key was missing even
though the JSON parsed fine.
Now PCount() == 1 keeps the legacy return-value form; PCount() >= 2
writes the decoded value into local-2 via SetLocal (which is
already byref-aware) and returns the byte count (0 on parse error).
Verified: hb_jsonDecode('{"x":1,"y":2}', @h) writes the hash and
returns 13; the 1-arg form still returns the value as before;
Compat 56/56 + go test ./compiler/... ./hbrt/... ./hbrtl/... all pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,7 +58,17 @@ func HbJsonEncode(t *hbrt.Thread) {
|
||||
t.RetString(string(data))
|
||||
}
|
||||
|
||||
// HB_JSONDECODE(cJSON) → xValue
|
||||
// HB_JSONDECODE(cJSON [, @xOut]) → xValue | nBytesParsed
|
||||
//
|
||||
// Two Harbour-spec calling forms:
|
||||
//
|
||||
// - 1 arg : returns the decoded value (or NIL on parse error).
|
||||
// - 2 args: writes the decoded value into the byref @xOut and
|
||||
// returns the number of bytes parsed (0 on error). This is the
|
||||
// form mod_harbour / fivenode PRG code uses for ctx_get and the
|
||||
// like. Five previously implemented only the 1-arg form, so any
|
||||
// PRG that relied on the byref output saw NIL and silently fell
|
||||
// through to a default.
|
||||
func HbJsonDecode(t *hbrt.Thread) {
|
||||
nParams := t.ParamCount()
|
||||
t.Frame(nParams, 0)
|
||||
@@ -66,10 +76,21 @@ func HbJsonDecode(t *hbrt.Thread) {
|
||||
s := t.Local(1).AsString()
|
||||
var raw interface{}
|
||||
if err := json.Unmarshal([]byte(s), &raw); err != nil {
|
||||
if nParams >= 2 {
|
||||
t.SetLocal(2, hbrt.MakeNil())
|
||||
t.RetInt(0)
|
||||
} else {
|
||||
t.RetNil()
|
||||
}
|
||||
return
|
||||
}
|
||||
t.RetVal(goToValue(raw))
|
||||
v := goToValue(raw)
|
||||
if nParams >= 2 {
|
||||
t.SetLocal(2, v)
|
||||
t.RetInt(int64(len(s)))
|
||||
return
|
||||
}
|
||||
t.RetVal(v)
|
||||
}
|
||||
|
||||
// === Five Extensions ===
|
||||
|
||||
Reference in New Issue
Block a user