Skip to content

Commit 7b4ac8e

Browse files
committed
fix cbor path api
1 parent 5dbcdaa commit 7b4ac8e

2 files changed

Lines changed: 19 additions & 14 deletions

File tree

src/mrb_cbor.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,6 @@ decode_negative(mrb_state* mrb, Reader* r, uint8_t info)
306306
// ============================================================================
307307
// Bytes / Text
308308
// ============================================================================
309-
static mrb_value decode_value(mrb_state* mrb, Reader* r, mrb_value src, mrb_value sharedrefs);
310-
311309
static mrb_value
312310
decode_text(mrb_state* mrb, Reader* r, mrb_value src, uint8_t info)
313311
{
@@ -348,6 +346,8 @@ decode_bytes(mrb_state* mrb, Reader* r, mrb_value src, uint8_t info)
348346
return mrb_undef_value();
349347
}
350348

349+
static mrb_value decode_value(mrb_state* mrb, Reader* r, mrb_value src, mrb_value sharedrefs);
350+
351351
static mrb_value
352352
decode_array(mrb_state* mrb, Reader* r, mrb_value src,
353353
uint8_t info, mrb_value sharedrefs, bool reg)
@@ -2479,8 +2479,6 @@ static mrb_value
24792479
lazy_aref_map(mrb_state *mrb, Reader *r, mrb_value key,
24802480
mrb_value self, cbor_lazy_t *p, mrb_value sharedrefs)
24812481
{
2482-
mrb_value kcache = mrb_iv_get(mrb, self, MRB_SYM(kcache));
2483-
mrb_assert(mrb_hash_p(kcache));
24842482
mrb_int pairs = cbor_len_to_mrb_int(mrb, read_cbor_uint(mrb, r, r->info));
24852483
const mrb_bool key_is_str = mrb_string_p(key);
24862484

@@ -2503,6 +2501,8 @@ lazy_aref_map(mrb_state *mrb, Reader *r, mrb_value key,
25032501
if (match) {
25042502
mrb_int value_offset = cbor_pdiff(mrb, r->p, r->base);
25052503
mrb_value lazy_new = cbor_lazy_new(mrb, p->buf, value_offset, sharedrefs);
2504+
mrb_value kcache = mrb_iv_get(mrb, self, MRB_SYM(kcache));
2505+
mrb_assert(mrb_hash_p(kcache));
25062506
mrb_hash_set(mrb, kcache, key, lazy_new);
25072507
return lazy_new;
25082508
}
@@ -2865,7 +2865,6 @@ cbor_doc_end_rb(mrb_state *mrb, mrb_value self)
28652865
offset);
28662866
}
28672867

2868-
#if 0
28692868
/* ============================================================
28702869
* Parser: String → compiled segment list on the Path object
28712870
*
@@ -3025,20 +3024,28 @@ path_walk_wildcards(mrb_state *mrb, mrb_value node,
30253024
mrb_value sharedrefs = mrb_iv_get(mrb, node, MRB_SYM(sharedrefs));
30263025
mrb_assert(mrb_array_p(sharedrefs));
30273026

3027+
mrb_int sharedrefs_before = RARRAY_LEN(sharedrefs);
30283028
major = lazy_resolve_tags(mrb, &r, p->buf, sharedrefs, &resolved);
30293029

30303030
if (major == 4) {
3031-
/* Found the array — pull length, then iterate via cbor_lazy_aref. */
30323031
mrb_int len = cbor_len_to_mrb_int(mrb, read_cbor_uint(mrb, &r, r.info));
30333032
mrb_int nseg = RARRAY_LEN(segments);
30343033
mrb_value next_steps = mrb_ary_ref(mrb, segments, depth + 1);
30353034
mrb_bool is_leaf = (depth == nseg - 2);
30363035

3036+
/* If lazy_resolve_tags consumed a Tag28 and registered the inner Lazy,
3037+
* use that Lazy (which starts at the array header, not the Tag28 byte)
3038+
* for cbor_lazy_aref calls. Without this, each call re-reads the Tag28
3039+
* and pushes a duplicate into sharedrefs, corrupting Tag29 resolution. */
3040+
mrb_value work_node = (RARRAY_LEN(sharedrefs) > sharedrefs_before)
3041+
? mrb_ary_ref(mrb, sharedrefs, RARRAY_LEN(sharedrefs) - 1)
3042+
: node;
3043+
30373044
mrb_value results = mrb_ary_new_capa(mrb, len);
3038-
int arena = mrb_gc_arena_save(mrb);
3045+
mrb_int arena = mrb_gc_arena_save(mrb);
30393046

30403047
for (mrb_int i = 0; i < len; i++) {
3041-
mrb_value elem = cbor_lazy_aref(mrb, node, mrb_convert_mrb_int(mrb, i));
3048+
mrb_value elem = cbor_lazy_aref(mrb, work_node, mrb_convert_mrb_int(mrb, i));
30423049
mrb_value next = path_walk_steps(mrb, elem, next_steps);
30433050
mrb_value val = is_leaf
30443051
? cbor_lazy_value(mrb, next)
@@ -3087,7 +3094,7 @@ mrb_cbor_path_at(mrb_state *mrb, mrb_value self)
30873094
? cbor_lazy_value(mrb, node)
30883095
: path_walk_wildcards(mrb, node, segments, 0);
30893096
}
3090-
#endif
3097+
30913098
MRB_BEGIN_DECL
30923099

30933100
MRB_API mrb_value
@@ -3203,7 +3210,6 @@ mrb_mruby_cbor_gem_init(mrb_state* mrb)
32033210
mrb_define_method_id(mrb, lazy, MRB_SYM(value), cbor_lazy_value, MRB_ARGS_NONE());
32043211
mrb_define_method_id(mrb, lazy, MRB_SYM(dig), cbor_lazy_dig, MRB_ARGS_ANY());
32053212

3206-
#if 0
32073213
struct RClass *path =
32083214
mrb_define_class_under_id(mrb, cbor, MRB_SYM(Path), mrb->object_class);
32093215
mrb_undef_method_id(mrb, path, MRB_SYM(initialize));
@@ -3213,7 +3219,7 @@ mrb_mruby_cbor_gem_init(mrb_state* mrb)
32133219

32143220
mrb_define_method_id(mrb, path, MRB_SYM(at),
32153221
mrb_cbor_path_at, MRB_ARGS_REQ(1));
3216-
#endif
3222+
32173223
}
32183224

32193225
void

test/test.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3230,7 +3230,6 @@ def initialize; @id = 0; @price = nil; end
32303230
assert_raise(TypeError) { CBOR.decode(buf) }
32313231
end
32323232

3233-
=begin
32343233
# ============================================================================
32353234
# CBOR::Path — [*] wildcard
32363235
# ============================================================================
@@ -3800,7 +3799,6 @@ def initialize; @id = 0; @price = nil; end
38003799
p = CBOR::Path.compile("$.xs[*]")
38013800
assert_equal [1, "two", nil, true, [3, 4], {"k" => "v"}], p.at(lazy)
38023801
end
3803-
=end
38043802

38053803
# ============================================================================
38063804
# 9. Shared references — Tag 28/29 (deduplication + cyclic structures)
@@ -4397,4 +4395,5 @@ class MutualB
43974395
"\xD8\x1D\x00"
43984396
lazy = CBOR.decode_lazy(buf)
43994397
assert_equal [1, 2], lazy["ref"].value
4400-
end
4398+
end
4399+

0 commit comments

Comments
 (0)