leptris 1.9.193.1 → 1.9.193.3
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 +59 -9
- data/lib/leptris/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 49ef91f7ec6c9a0642a8a7663226bb98d5a1922adbb026354b9af783ab5f2821
|
|
4
|
+
data.tar.gz: 114f27006c38eb0949f7754b39b4428da84f6c9e5dcc67886d147ac9ac04ebfb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ca23bf845f255e976988659785f79292fd131502b4ae04c0baaf95f813c06c22d1d57b76412ec52040e4a855cfffc3e122b82f3165a8244ae9c59e8cd1e527a
|
|
7
|
+
data.tar.gz: 914210f2e059b27479bad365a3f8beef6121109638dced1db909ad49869db27cceb45426630024301d1542841540c6b63db1fe703baaee56c0c7f79d78bdf7f5
|
data/ext/leptris/native/native.c
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* bulk — one cache round-trip, zero Ruby frames, zero FFI
|
|
6
6
|
* marshaling per node. */
|
|
7
7
|
#include <ruby.h>
|
|
8
|
+
#include <ruby/encoding.h>
|
|
8
9
|
#include <stdint.h>
|
|
9
10
|
#include <string.h>
|
|
10
11
|
|
|
@@ -120,6 +121,7 @@ static ID id_iv_c_address, id_iv_native_cache, id_iv_binding_cache;
|
|
|
120
121
|
static ID id_iv_version, id_iv_readonly, id_address;
|
|
121
122
|
static ID id_iv_nn_content, id_iv_nn_content_ver;
|
|
122
123
|
static ID id_iv_nn_attrs, id_iv_nn_attrs_ver;
|
|
124
|
+
static ID id_child_klasses;
|
|
123
125
|
static VALUE c_use_after_free_error;
|
|
124
126
|
|
|
125
127
|
static VALUE native_cache_of(VALUE document);
|
|
@@ -265,7 +267,13 @@ static VALUE nn_name(VALUE self)
|
|
|
265
267
|
const char *s;
|
|
266
268
|
TypedData_Get_Struct(self, struct native_node, &nn_type, n);
|
|
267
269
|
s = f_elem_name(n->ptr);
|
|
268
|
-
|
|
270
|
+
/* Interned (shared, frozen) fstring: element names repeat
|
|
271
|
+
* massively across a document — one RString per distinct name
|
|
272
|
+
* per process instead of one per read (lutaml/moxml#249:
|
|
273
|
+
* ~18% of consumer materialize allocations were fresh name
|
|
274
|
+
* strings). Names are identifiers; nothing downstream mutates
|
|
275
|
+
* them in place (renames mint new strings). */
|
|
276
|
+
return s ? rb_enc_interned_str(s, strlen(s), rb_utf8_encoding()) : Qnil;
|
|
269
277
|
}
|
|
270
278
|
|
|
271
279
|
static VALUE nn_content(VALUE self)
|
|
@@ -366,6 +374,42 @@ static VALUE nn_allocate(VALUE klass)
|
|
|
366
374
|
return TypedData_Make_Struct(klass, struct native_node, &nn_type, n);
|
|
367
375
|
}
|
|
368
376
|
|
|
377
|
+
/* Klass-propagating reads (#246): a consumer subclass installed a
|
|
378
|
+
* per-kind child-klass map; reads mint that class so the child
|
|
379
|
+
* arrives already being the consumer's wrapper. Map-less callers
|
|
380
|
+
* (the base class) keep today's base mint. */
|
|
381
|
+
static VALUE klass_for_kind(VALUE owner_klass, int kind)
|
|
382
|
+
{
|
|
383
|
+
VALUE map = rb_attr_get(owner_klass, id_child_klasses);
|
|
384
|
+
VALUE k;
|
|
385
|
+
if (NIL_P(map))
|
|
386
|
+
return c_native_node;
|
|
387
|
+
k = rb_ary_entry(map, (long)kind);
|
|
388
|
+
return RB_TYPE_P(k, T_CLASS) ? k : c_native_node;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
static VALUE nn_install_child_klasses(VALUE self, VALUE map)
|
|
392
|
+
{
|
|
393
|
+
long i, len;
|
|
394
|
+
Check_Type(map, T_ARRAY);
|
|
395
|
+
len = RARRAY_LEN(map);
|
|
396
|
+
if (len > 5)
|
|
397
|
+
rb_raise(rb_eArgError,
|
|
398
|
+
"child klasses: Array of classes/nil indexed by "
|
|
399
|
+
"node kind (element, text, comment, cdata, pi)");
|
|
400
|
+
for (i = 0; i < len; i++) {
|
|
401
|
+
VALUE k = rb_ary_entry(map, i);
|
|
402
|
+
if (!NIL_P(k) &&
|
|
403
|
+
!(RB_TYPE_P(k, T_CLASS) &&
|
|
404
|
+
RTEST(rb_class_inherited_p(k, c_native_node))))
|
|
405
|
+
rb_raise(rb_eTypeError,
|
|
406
|
+
"child klasses entries must be nil or a "
|
|
407
|
+
"Leptris::XML::NativeNode subclass");
|
|
408
|
+
}
|
|
409
|
+
rb_ivar_set(self, id_child_klasses, map);
|
|
410
|
+
return self;
|
|
411
|
+
}
|
|
412
|
+
|
|
369
413
|
/* Bulk children: one native pass; cache check/store inline; the
|
|
370
414
|
* document's wrapper_cache (a Ruby Hash keyed by address) provides
|
|
371
415
|
* identity for nodes seen through other paths. */
|
|
@@ -401,7 +445,7 @@ static VALUE nn_children(VALUE self)
|
|
|
401
445
|
void **buf;
|
|
402
446
|
int *kinds;
|
|
403
447
|
int count, i;
|
|
404
|
-
VALUE cache, out;
|
|
448
|
+
VALUE cache, out, owner_klass;
|
|
405
449
|
|
|
406
450
|
TypedData_Get_Struct(self, struct native_node, &nn_type, n);
|
|
407
451
|
count = fetch_children_two_call(n->ptr, &buf, &kinds);
|
|
@@ -413,13 +457,14 @@ static VALUE nn_children(VALUE self)
|
|
|
413
457
|
|
|
414
458
|
cache = native_cache_of(n->document);
|
|
415
459
|
out = rb_ary_new2(count);
|
|
460
|
+
owner_klass = rb_obj_class(self);
|
|
416
461
|
for (i = 0; i < count; i++) {
|
|
417
462
|
uint64_t addr = (uint64_t)(uintptr_t)buf[i];
|
|
418
463
|
VALUE key = ULL2NUM(addr);
|
|
419
464
|
VALUE child = rb_hash_aref(cache, key);
|
|
420
465
|
if (NIL_P(child)) {
|
|
421
466
|
struct native_node *cn;
|
|
422
|
-
child = nn_allocate(
|
|
467
|
+
child = nn_allocate(klass_for_kind(owner_klass, kinds[i]));
|
|
423
468
|
TypedData_Get_Struct(child, struct native_node, &nn_type, cn);
|
|
424
469
|
cn->ptr = buf[i];
|
|
425
470
|
cn->document = n->document;
|
|
@@ -454,7 +499,7 @@ static VALUE nn_element_children(VALUE self)
|
|
|
454
499
|
void **buf;
|
|
455
500
|
int *kinds;
|
|
456
501
|
int count, i;
|
|
457
|
-
VALUE cache, out;
|
|
502
|
+
VALUE cache, out, child_klass;
|
|
458
503
|
|
|
459
504
|
TypedData_Get_Struct(self, struct native_node, &nn_type, n);
|
|
460
505
|
count = fetch_children_two_call(n->ptr, &buf, &kinds);
|
|
@@ -466,6 +511,7 @@ static VALUE nn_element_children(VALUE self)
|
|
|
466
511
|
|
|
467
512
|
cache = native_cache_of(n->document);
|
|
468
513
|
out = rb_ary_new();
|
|
514
|
+
child_klass = klass_for_kind(rb_obj_class(self), NT_ELEMENT);
|
|
469
515
|
for (i = 0; i < count; i++) {
|
|
470
516
|
if (kinds[i] != NT_ELEMENT)
|
|
471
517
|
continue;
|
|
@@ -473,7 +519,7 @@ static VALUE nn_element_children(VALUE self)
|
|
|
473
519
|
VALUE child = rb_hash_aref(cache, key);
|
|
474
520
|
if (NIL_P(child)) {
|
|
475
521
|
struct native_node *cn;
|
|
476
|
-
child = nn_allocate(
|
|
522
|
+
child = nn_allocate(child_klass);
|
|
477
523
|
TypedData_Get_Struct(child, struct native_node, &nn_type, cn);
|
|
478
524
|
cn->ptr = buf[i];
|
|
479
525
|
cn->document = n->document;
|
|
@@ -486,7 +532,8 @@ static VALUE nn_element_children(VALUE self)
|
|
|
486
532
|
return out;
|
|
487
533
|
}
|
|
488
534
|
|
|
489
|
-
static VALUE wrap_cached(struct native_node *owner,
|
|
535
|
+
static VALUE wrap_cached(VALUE owner_klass, struct native_node *owner,
|
|
536
|
+
void *ptr)
|
|
490
537
|
{
|
|
491
538
|
VALUE cache, key, node;
|
|
492
539
|
struct native_node *n;
|
|
@@ -496,7 +543,7 @@ static VALUE wrap_cached(struct native_node *owner, void *ptr)
|
|
|
496
543
|
node = rb_hash_aref(cache, key);
|
|
497
544
|
if (!NIL_P(node))
|
|
498
545
|
return node;
|
|
499
|
-
node = nn_allocate(
|
|
546
|
+
node = nn_allocate(klass_for_kind(owner_klass, f_node_type(ptr)));
|
|
500
547
|
TypedData_Get_Struct(node, struct native_node, &nn_type, n);
|
|
501
548
|
n->ptr = ptr;
|
|
502
549
|
n->document = owner->document;
|
|
@@ -510,7 +557,7 @@ static VALUE nn_next_sibling(VALUE self)
|
|
|
510
557
|
void *sib;
|
|
511
558
|
TypedData_Get_Struct(self, struct native_node, &nn_type, n);
|
|
512
559
|
sib = f_next_sibling(n->ptr);
|
|
513
|
-
return sib ? wrap_cached(n, sib) : Qnil;
|
|
560
|
+
return sib ? wrap_cached(rb_obj_class(self), n, sib) : Qnil;
|
|
514
561
|
}
|
|
515
562
|
|
|
516
563
|
static VALUE nn_parent(VALUE self)
|
|
@@ -519,7 +566,7 @@ static VALUE nn_parent(VALUE self)
|
|
|
519
566
|
void *par;
|
|
520
567
|
TypedData_Get_Struct(self, struct native_node, &nn_type, n);
|
|
521
568
|
par = f_parent(n->ptr);
|
|
522
|
-
return par ? wrap_cached(n, par) : Qnil;
|
|
569
|
+
return par ? wrap_cached(rb_obj_class(self), n, par) : Qnil;
|
|
523
570
|
}
|
|
524
571
|
|
|
525
572
|
/* Wrap a freshly-created C node as a NativeNode and register it
|
|
@@ -2281,6 +2328,7 @@ void Init_native(void)
|
|
|
2281
2328
|
id_iv_nn_content_ver = rb_intern("@nn_content_ver");
|
|
2282
2329
|
id_iv_nn_attrs = rb_intern("@nn_attrs");
|
|
2283
2330
|
id_iv_nn_attrs_ver = rb_intern("@nn_attrs_ver");
|
|
2331
|
+
id_child_klasses = rb_intern("@nn_child_klasses");
|
|
2284
2332
|
id_iv_doc_handle = rb_intern("@doc_handle");
|
|
2285
2333
|
id_freed_new = rb_intern("new");
|
|
2286
2334
|
id_alive = rb_intern("alive");
|
|
@@ -2291,6 +2339,8 @@ void Init_native(void)
|
|
|
2291
2339
|
rb_gc_register_mark_object(c_use_after_free_error);
|
|
2292
2340
|
|
|
2293
2341
|
rb_define_singleton_method(c_native_node, "from", nn_from, 2);
|
|
2342
|
+
rb_define_singleton_method(c_native_node, "install_child_klasses",
|
|
2343
|
+
nn_install_child_klasses, 1);
|
|
2294
2344
|
rb_define_singleton_method(c_native_node, "create_element", nn_create_element, 2);
|
|
2295
2345
|
rb_define_singleton_method(c_native_node, "create_text", nn_create_text, 2);
|
|
2296
2346
|
rb_define_singleton_method(c_native_node, "set_root", nn_set_root, 2);
|
data/lib/leptris/version.rb
CHANGED