leptris 1.9.255.0 → 1.9.255.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/leptris/native/native.c +146 -20
- data/lib/leptris/vendor/x86_64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/native_layer.rb +12 -0
- data/lib/leptris/xml/plan_value.rb +12 -15
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b6e6554da43271e1b86c948f2ecd2a0f35c1db9a8ec62cdcb8c8d422a467da4
|
|
4
|
+
data.tar.gz: f37099846579bda7f01d85fb8b5aeb16da3003c862ad3364ed9e485c72d1e40f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c063a07c01d9c968d506bbefb02ef6f82840b44ea7e13e6af58dffef55ccaf44813fd64b438f2e523739585d78286f196f56f53b293b8c75bdc0388708d2a939
|
|
7
|
+
data.tar.gz: 524629c877881d34319b581f3e9b0908ff74484c8325854ab9cf4d203a066b8dd909c2365ee77a08abd80e771d90c160fadad03bfe6cc3b95e0db15e1a5036de
|
data/ext/leptris/native/native.c
CHANGED
|
@@ -627,6 +627,60 @@ static void *doc_ptr_of(VALUE document)
|
|
|
627
627
|
/* Per-document identity caches. Both are lazily allocated on the
|
|
628
628
|
* Ruby side (@x ||= {}), so replicate that here: ivar read, create
|
|
629
629
|
* and store when unset. */
|
|
630
|
+
/* #340: per-document wrapper-klass registration. The ivar holds an
|
|
631
|
+
* Array of classes/nil indexed by node kind (the same shape
|
|
632
|
+
* install_child_klasses uses at the klass level). When an entry is
|
|
633
|
+
* set, the walk cache AND the create faces mint that klass
|
|
634
|
+
* (NativeNode subclass, TypedData path) instead of the binding
|
|
635
|
+
* wrapper classes — consumers receive their own contract-carrying
|
|
636
|
+
* nodes straight from C, and their re-wrap drops out. */
|
|
637
|
+
static ID id_iv_doc_klass_map;
|
|
638
|
+
|
|
639
|
+
static VALUE doc_klass_for_kind(VALUE document, int kind)
|
|
640
|
+
{
|
|
641
|
+
VALUE map = rb_ivar_get(document, id_iv_doc_klass_map);
|
|
642
|
+
VALUE k;
|
|
643
|
+
if (NIL_P(map)) return Qnil;
|
|
644
|
+
k = rb_ary_entry(map, (long)kind);
|
|
645
|
+
return RB_TYPE_P(k, T_CLASS) ? k : Qnil;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
static VALUE mint_consumer_node(VALUE klass, VALUE document, void *ptr)
|
|
649
|
+
{
|
|
650
|
+
struct native_node *n;
|
|
651
|
+
VALUE node =
|
|
652
|
+
TypedData_Make_Struct(klass, struct native_node, &nn_type, n);
|
|
653
|
+
n->ptr = ptr;
|
|
654
|
+
n->document = document;
|
|
655
|
+
rb_hash_aset(native_cache_of(document),
|
|
656
|
+
ULL2NUM((uint64_t)(uintptr_t)ptr), node);
|
|
657
|
+
return node;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
static VALUE nf_register_doc_klasses(VALUE self, VALUE document, VALUE map)
|
|
661
|
+
{
|
|
662
|
+
long i, len;
|
|
663
|
+
(void)self;
|
|
664
|
+
resolve_binding_classes();
|
|
665
|
+
Check_Type(map, T_ARRAY);
|
|
666
|
+
len = RARRAY_LEN(map);
|
|
667
|
+
if (len > 5)
|
|
668
|
+
rb_raise(rb_eArgError,
|
|
669
|
+
"wrapper klasses: Array of classes/nil indexed by "
|
|
670
|
+
"node kind (element, text, comment, cdata, pi)");
|
|
671
|
+
for (i = 0; i < len; i++) {
|
|
672
|
+
VALUE k = rb_ary_entry(map, i);
|
|
673
|
+
if (!NIL_P(k) &&
|
|
674
|
+
!(RB_TYPE_P(k, T_CLASS) &&
|
|
675
|
+
RTEST(rb_class_inherited_p(k, c_native_node))))
|
|
676
|
+
rb_raise(rb_eTypeError,
|
|
677
|
+
"wrapper klasses entries must be nil or a "
|
|
678
|
+
"Leptris::XML::NativeNode subclass");
|
|
679
|
+
}
|
|
680
|
+
rb_ivar_set(document, id_iv_doc_klass_map, map);
|
|
681
|
+
return document;
|
|
682
|
+
}
|
|
683
|
+
|
|
630
684
|
static VALUE native_cache_of(VALUE document)
|
|
631
685
|
{
|
|
632
686
|
VALUE cache = rb_ivar_get(document, id_iv_native_cache);
|
|
@@ -877,7 +931,20 @@ static VALUE trav_wrapper_for(struct trav_state *st, void *node_ptr,
|
|
|
877
931
|
int kind)
|
|
878
932
|
{
|
|
879
933
|
VALUE key = ULL2NUM((uint64_t)(uintptr_t)node_ptr);
|
|
880
|
-
VALUE node
|
|
934
|
+
VALUE node;
|
|
935
|
+
VALUE ck = doc_klass_for_kind(st->document, kind);
|
|
936
|
+
|
|
937
|
+
/* #340 klass-parameterized walk cache: registered consumer
|
|
938
|
+
* klasses mint (and identity-cache) through the TypedData
|
|
939
|
+
* path — nodes arrive already being the consumer's wrapper. */
|
|
940
|
+
if (!NIL_P(ck)) {
|
|
941
|
+
VALUE ncache = native_cache_of(st->document);
|
|
942
|
+
node = rb_hash_aref(ncache, key);
|
|
943
|
+
if (!NIL_P(node)) return node;
|
|
944
|
+
return mint_consumer_node(ck, st->document, node_ptr);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
node = rb_hash_aref(st->cache, key);
|
|
881
948
|
if (!NIL_P(node)) return node;
|
|
882
949
|
|
|
883
950
|
node = rb_obj_alloc(binding_klass_for(kind));
|
|
@@ -2290,20 +2357,15 @@ static VALUE nf_plan_structs_typed_p(VALUE self)
|
|
|
2290
2357
|
* C->C dlsym dispatches (create_child = create+attach in one
|
|
2291
2358
|
* engine call; set_attr per attribute). Returns the new node's
|
|
2292
2359
|
* address for wrapper minting. */
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
: (void *)(uintptr_t)NUM2ULL(parent_addr);
|
|
2303
|
-
const char *cname = StringValueCStr(name);
|
|
2304
|
-
|
|
2305
|
-
if (f_elem_new_with_attrs && doc_ptr && parent && RARRAY_LEN(attrs) > 0 &&
|
|
2306
|
-
RARRAY_LEN(attrs) % 2 == 0) {
|
|
2360
|
+
/* Creation core shared by the raw-address face and the #340
|
|
2361
|
+
* wrapper-returning variant: single-crossing arena create +
|
|
2362
|
+
* attributes when the engine has #1344, else create + per-pair
|
|
2363
|
+
* sets. Returns the raw element pointer (NULL on failure). */
|
|
2364
|
+
static void *create_elem_core(void *doc_ptr, void *parent,
|
|
2365
|
+
const char *cname, VALUE attrs)
|
|
2366
|
+
{
|
|
2367
|
+
if (f_elem_new_with_attrs && doc_ptr && parent &&
|
|
2368
|
+
RARRAY_LEN(attrs) > 0 && RARRAY_LEN(attrs) % 2 == 0) {
|
|
2307
2369
|
/* Engine single-crossing construction (1.9.236+): arena
|
|
2308
2370
|
* create + all attributes with no per-attr calls at all. */
|
|
2309
2371
|
long n = RARRAY_LEN(attrs) / 2;
|
|
@@ -2319,15 +2381,15 @@ static VALUE nf_create_element_with_attrs(VALUE self, VALUE document,
|
|
|
2319
2381
|
}
|
|
2320
2382
|
void *elem = f_elem_new_with_attrs(doc_ptr, cname, names,
|
|
2321
2383
|
values, n);
|
|
2322
|
-
if (!elem) return
|
|
2384
|
+
if (!elem) return NULL;
|
|
2323
2385
|
/* The face creates a floating element owned by the
|
|
2324
2386
|
* document — append under the parent afterwards. */
|
|
2325
|
-
|
|
2326
|
-
return
|
|
2387
|
+
f_append_child(parent, elem);
|
|
2388
|
+
return elem;
|
|
2327
2389
|
}
|
|
2328
2390
|
|
|
2329
2391
|
void *elem = parent ? f_create_child(parent, cname) : NULL;
|
|
2330
|
-
if (!elem) return
|
|
2392
|
+
if (!elem) return NULL;
|
|
2331
2393
|
|
|
2332
2394
|
long i, n = RARRAY_LEN(attrs);
|
|
2333
2395
|
for (i = 0; i + 1 < n; i += 2) {
|
|
@@ -2335,7 +2397,65 @@ static VALUE nf_create_element_with_attrs(VALUE self, VALUE document,
|
|
|
2335
2397
|
VALUE av = RARRAY_AREF(attrs, i + 1);
|
|
2336
2398
|
f_set_attr(elem, StringValueCStr(an), StringValueCStr(av));
|
|
2337
2399
|
}
|
|
2338
|
-
return
|
|
2400
|
+
return elem;
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
static VALUE nf_create_element_with_attrs(VALUE self, VALUE document,
|
|
2404
|
+
VALUE parent_addr, VALUE name,
|
|
2405
|
+
VALUE attrs)
|
|
2406
|
+
{
|
|
2407
|
+
void *doc_ptr = NIL_P(document)
|
|
2408
|
+
? NULL
|
|
2409
|
+
: (void *)(uintptr_t)NUM2ULL(document);
|
|
2410
|
+
void *parent = NIL_P(parent_addr)
|
|
2411
|
+
? NULL
|
|
2412
|
+
: (void *)(uintptr_t)NUM2ULL(parent_addr);
|
|
2413
|
+
void *elem = create_elem_core(doc_ptr, parent,
|
|
2414
|
+
StringValueCStr(name), attrs);
|
|
2415
|
+
return elem ? ULL2NUM((uintptr_t)elem) : Qnil;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
/* #340 construction registration: create + attach + attributes in
|
|
2419
|
+
* one crossing AND mint the wrapper C-side — the registered
|
|
2420
|
+
* consumer klass when one is installed for elements (TypedData
|
|
2421
|
+
* path + native-cache identity), else the binding Element minted
|
|
2422
|
+
* exactly like nf_create_binding_element. The caller receives a
|
|
2423
|
+
* contract-carrying node straight from the crossing; no separate
|
|
2424
|
+
* Node.wrap, no consumer re-wrap. */
|
|
2425
|
+
static VALUE nf_create_element_with_attrs_wrapped(
|
|
2426
|
+
VALUE self, VALUE document, VALUE parent_addr, VALUE name,
|
|
2427
|
+
VALUE attrs)
|
|
2428
|
+
{
|
|
2429
|
+
void *doc_ptr = doc_ptr_of(document);
|
|
2430
|
+
void *parent = NIL_P(parent_addr)
|
|
2431
|
+
? NULL
|
|
2432
|
+
: (void *)(uintptr_t)NUM2ULL(parent_addr);
|
|
2433
|
+
void *elem = create_elem_core(doc_ptr, parent,
|
|
2434
|
+
StringValueCStr(name), attrs);
|
|
2435
|
+
VALUE ck, key, node, cache;
|
|
2436
|
+
|
|
2437
|
+
(void)self;
|
|
2438
|
+
if (!elem) return Qnil;
|
|
2439
|
+
resolve_binding_classes();
|
|
2440
|
+
ck = doc_klass_for_kind(document, 0 /* element */);
|
|
2441
|
+
if (!NIL_P(ck))
|
|
2442
|
+
return mint_consumer_node(ck, document, elem);
|
|
2443
|
+
|
|
2444
|
+
key = ULL2NUM((uint64_t)(uintptr_t)elem);
|
|
2445
|
+
cache = binding_cache_of(document);
|
|
2446
|
+
node = rb_hash_aref(cache, key);
|
|
2447
|
+
if (!NIL_P(node)) return node;
|
|
2448
|
+
node = rb_obj_alloc(c_b_element);
|
|
2449
|
+
rb_iv_set(node, "@c_address", key);
|
|
2450
|
+
rb_iv_set(node, "@document", document);
|
|
2451
|
+
rb_iv_set(node, "@parent", Qnil);
|
|
2452
|
+
rb_iv_set(node, "@structure_memoizable", Qtrue);
|
|
2453
|
+
rb_iv_set(node, "@native_fast", Qtrue);
|
|
2454
|
+
rb_iv_set(node, "@pub_document", document);
|
|
2455
|
+
rb_iv_set(node, "@addr_reads_fast", Qtrue);
|
|
2456
|
+
rb_iv_set(node, "@node_type", INT2FIX(0));
|
|
2457
|
+
rb_hash_aset(cache, key, node);
|
|
2458
|
+
return node;
|
|
2339
2459
|
}
|
|
2340
2460
|
|
|
2341
2461
|
static VALUE nf_attribute_rows(VALUE self, VALUE document, VALUE addr)
|
|
@@ -2844,6 +2964,7 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
2844
2964
|
id_iv_nn_attrs = rb_intern("@nn_attrs");
|
|
2845
2965
|
id_iv_nn_attrs_ver = rb_intern("@nn_attrs_ver");
|
|
2846
2966
|
id_child_klasses = rb_intern("@nn_child_klasses");
|
|
2967
|
+
id_iv_doc_klass_map = rb_intern("@doc_klass_map");
|
|
2847
2968
|
id_iv_doc_handle = rb_intern("@doc_handle");
|
|
2848
2969
|
id_freed_new = rb_intern("new");
|
|
2849
2970
|
id_alive = rb_intern("alive");
|
|
@@ -2954,6 +3075,11 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
2954
3075
|
nf_attribute_rows, 2);
|
|
2955
3076
|
rb_define_module_function(m_native, "create_element_with_attrs",
|
|
2956
3077
|
nf_create_element_with_attrs, 4);
|
|
3078
|
+
rb_define_module_function(m_native, "register_doc_klasses",
|
|
3079
|
+
nf_register_doc_klasses, 2);
|
|
3080
|
+
rb_define_module_function(m_native,
|
|
3081
|
+
"create_element_with_attrs_wrapped",
|
|
3082
|
+
nf_create_element_with_attrs_wrapped, 4);
|
|
2957
3083
|
rb_define_module_function(m_native, "plan_structs_typed?",
|
|
2958
3084
|
nf_plan_structs_typed_p, 0);
|
|
2959
3085
|
rb_define_module_function(m_native, "doc_handle_attach",
|
|
Binary file
|
data/lib/leptris/version.rb
CHANGED
|
@@ -75,6 +75,18 @@ class Leptris::XML::Document
|
|
|
75
75
|
Leptris::XML::NativeNode.from(self, r.c_ptr)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
+
# #340: per-kind wrapper-klass registration for THIS document.
|
|
79
|
+
# map is an Array of classes/nil indexed by node kind (element,
|
|
80
|
+
# text, comment, cdata, pi) — the same shape
|
|
81
|
+
# NativeNode.install_child_klasses uses. Once registered, the C
|
|
82
|
+
# walk cache (trav/visit) and the create faces mint those
|
|
83
|
+
# klasses directly (TypedData path, native-cache identity), so
|
|
84
|
+
# consumers receive their own contract-carrying nodes straight
|
|
85
|
+
# from the crossing with no re-wrap.
|
|
86
|
+
def register_wrapper_klasses(map)
|
|
87
|
+
Leptris::XML::Native.register_doc_klasses(self, map)
|
|
88
|
+
end
|
|
89
|
+
|
|
78
90
|
# Builder factories that return NativeNodes (#149): one C call
|
|
79
91
|
# and a TypedData wrap — no FFI::Pointer, no wrap_fresh path.
|
|
80
92
|
def native_create_element(name)
|
|
@@ -31,33 +31,33 @@ class Leptris::XML::PlanValue
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def kind
|
|
34
|
-
|
|
34
|
+
@counter[0] += 1
|
|
35
35
|
VALUE_KINDS.fetch(Leptris::XML::FFI.leptris_plan_value_kind(@ptr))
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# wire_name of the plan row that produced this value.
|
|
39
39
|
def name
|
|
40
|
-
|
|
40
|
+
@counter[0] += 1
|
|
41
41
|
Leptris::XML::FFI.leptris_plan_value_name(@ptr)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Host type_tag echoed verbatim (0 when the row had none).
|
|
45
45
|
def type_tag
|
|
46
|
-
|
|
46
|
+
@counter[0] += 1
|
|
47
47
|
Leptris::XML::FFI.leptris_plan_value_type_tag(@ptr)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# #1273: LEPTRIS_NODE_TYPE_* of this value's source node (0 for
|
|
51
51
|
# ELEMENT/COLLECTION wrappers and synthesized text).
|
|
52
52
|
def node_kind
|
|
53
|
-
|
|
53
|
+
@counter[0] += 1
|
|
54
54
|
Leptris::XML::FFI.leptris_plan_value_node_kind(@ptr)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
# #1273: dense sibling rank inside the producing element (0 if
|
|
58
58
|
# unranked) — document-order identity without byte offsets.
|
|
59
59
|
def order_index
|
|
60
|
-
|
|
60
|
+
@counter[0] += 1
|
|
61
61
|
Leptris::XML::FFI.leptris_plan_value_order_index(@ptr)
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -85,26 +85,26 @@ class Leptris::XML::PlanValue
|
|
|
85
85
|
|
|
86
86
|
# SCALAR / RAW / CALLBACK string value.
|
|
87
87
|
def string_value
|
|
88
|
-
|
|
88
|
+
@counter[0] += 1
|
|
89
89
|
Leptris::XML::FFI.leptris_plan_value_string(@ptr)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
# CALLBACK: document byte offset of the source node (0 unknown).
|
|
93
93
|
def position
|
|
94
|
-
|
|
94
|
+
@counter[0] += 1
|
|
95
95
|
Leptris::XML::FFI.leptris_plan_value_position(@ptr)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
# ELEMENT: child-value count. COLLECTION: item count.
|
|
99
99
|
def count
|
|
100
|
-
|
|
100
|
+
@counter[0] += 1
|
|
101
101
|
Leptris::XML::FFI.leptris_plan_value_count(@ptr)
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
# ELEMENT child value / COLLECTION item at +i+ (nil out of
|
|
105
105
|
# range). Borrowed: the owning root must stay alive.
|
|
106
106
|
def at(i)
|
|
107
|
-
|
|
107
|
+
@counter[0] += 1
|
|
108
108
|
ptr = Leptris::XML::FFI.leptris_plan_value_at(@ptr, i)
|
|
109
109
|
return nil if ptr.null?
|
|
110
110
|
child_plan = child_plan_for_position(ptr)
|
|
@@ -114,7 +114,7 @@ class Leptris::XML::PlanValue
|
|
|
114
114
|
|
|
115
115
|
# ELEMENT: attribute value by wire_name (nil when absent).
|
|
116
116
|
def attribute(wire_name)
|
|
117
|
-
|
|
117
|
+
@counter[0] += 1
|
|
118
118
|
Leptris::XML::FFI.leptris_plan_value_attribute(@ptr, wire_name.to_s)
|
|
119
119
|
end
|
|
120
120
|
|
|
@@ -149,7 +149,7 @@ class Leptris::XML::PlanValue
|
|
|
149
149
|
# (0 when absent). Collection rows appear as Arrays; callbacks
|
|
150
150
|
# are emitted as +{value:, position:, type_tag:}+ like #to_ruby.
|
|
151
151
|
def as_kwarg_hash
|
|
152
|
-
|
|
152
|
+
@counter[0] += 1 # the kind probe + name + type_tag are one logical fetch
|
|
153
153
|
case kind
|
|
154
154
|
when :element
|
|
155
155
|
{
|
|
@@ -194,9 +194,6 @@ class Leptris::XML::PlanValue
|
|
|
194
194
|
|
|
195
195
|
private
|
|
196
196
|
|
|
197
|
-
def inc_crossing
|
|
198
|
-
@counter[0] += 1
|
|
199
|
-
end
|
|
200
197
|
|
|
201
198
|
def kwarg_attributes
|
|
202
199
|
((@plan && @plan[:attributes]) || []).each_with_object({}) do |row, result|
|
|
@@ -290,7 +287,7 @@ class Leptris::XML::PlanValue
|
|
|
290
287
|
rows = @plan[:children] || []
|
|
291
288
|
row = rows.size == 1 ? rows.first : nil
|
|
292
289
|
unless row
|
|
293
|
-
|
|
290
|
+
@counter[0] += 1
|
|
294
291
|
child_name = Leptris::XML::FFI.leptris_plan_value_name(ptr)
|
|
295
292
|
row = rows.find { |r| r[:name] == child_name }
|
|
296
293
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: leptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.255.
|
|
4
|
+
version: 1.9.255.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|