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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8979aca09e2418ae2f22b32e21af1b9299f3fbe2b396bc73e47fccd999f4a39d
4
- data.tar.gz: 1d42ce1ddbf65fcb1cc57985899f4bc8366e763b12a1cd32fd54f5ab660769de
3
+ metadata.gz: 49ef91f7ec6c9a0642a8a7663226bb98d5a1922adbb026354b9af783ab5f2821
4
+ data.tar.gz: 114f27006c38eb0949f7754b39b4428da84f6c9e5dcc67886d147ac9ac04ebfb
5
5
  SHA512:
6
- metadata.gz: f258ab8d0f990359137b6819432f6cd75c87b72b9ac4c52debd127d399735f8ccdd46f5a55934c38d73e85f6a0475e5331bc716139eb5ccd7b461138cea97f83
7
- data.tar.gz: c40707201086cfbdbd2e36d87d0659f9a1503b429a09fde5d5f7fe7a05ace634ebd267eef2b04c95e739f7b92deee4dd9d9f5ba68800002a3901880371afb012
6
+ metadata.gz: 7ca23bf845f255e976988659785f79292fd131502b4ae04c0baaf95f813c06c22d1d57b76412ec52040e4a855cfffc3e122b82f3165a8244ae9c59e8cd1e527a
7
+ data.tar.gz: 914210f2e059b27479bad365a3f8beef6121109638dced1db909ad49869db27cceb45426630024301d1542841540c6b63db1fe703baaee56c0c7f79d78bdf7f5
@@ -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
- return s ? rb_utf8_str_new_cstr(s) : Qnil;
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(c_native_node);
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(c_native_node);
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, void *ptr)
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(c_native_node);
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);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.193.1"
4
+ VERSION = "1.9.193.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.193.1
4
+ version: 1.9.193.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.