leptris 1.9.232.0-aarch64-linux → 1.9.237.0-aarch64-linux
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/CHANGELOG.md +25 -0
- data/Rakefile +1 -1
- data/ext/leptris/native/native.c +144 -3
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/document.rb +20 -3
- data/lib/leptris/xml/ffi.rb +91 -62
- data/lib/leptris/xml/native.so +0 -0
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +113 -4
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/benchmarks/dom/bench_leptris.c +14 -6
- data/vendor-src/libleptris/src/include/leptris.h +27 -0
- data/vendor-src/libleptris/src/leptris/dom/element_modify.c +20 -0
- data/vendor-src/libleptris/src/leptris/leptris_internal.h +5 -0
- data/vendor-src/libleptris/src/leptris/xpath/evaluator.c +7 -0
- data/vendor-src/libleptris/src/leptris/xpath/evaluator_operators.c +38 -4
- data/vendor-src/libleptris/src/leptris/xpath/evaluator_types.c +5 -1
- data/vendor-src/libleptris/src/leptris/xpath/functions.c +86 -7
- data/vendor-src/libleptris/src/leptris/xpath/functions_ext31.c +237 -24
- data/vendor-src/libleptris/src/leptris/xpath/xpath_public.c +16 -1
- data/vendor-src/libleptris/test/dom/test_dom.cpp +80 -0
- data/vendor-src/libleptris/test/xquery/qt3/fn/count.xml +3117 -0
- data/vendor-src/libleptris/test/xquery/qt3/fn/empty.xml +502 -0
- data/vendor-src/libleptris/test/xquery/qt3/fn/exists.xml +537 -0
- data/vendor-src/libleptris/test/xquery/qt3/fn/head.xml +90 -0
- data/vendor-src/libleptris/test/xquery/qt3/fn/tail.xml +68 -0
- data/vendor-src/libleptris/test/xquery/test_qt3.cpp +124 -93
- data/vendor-src/libleptris/test/xquery/test_xquery.cpp +28 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c46ff3c23888c3489866a6252251f2d9155b07917709ae1e3b22e82818a61247
|
|
4
|
+
data.tar.gz: 1b817ffa11a2cacdd3aa4978dc77ef6ed32cd7ab6bee75a0b5c580b2a5c92529
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 609e9306631a1785b45deef224407f65d814cb99eb6377a8c0af0371b66fe7a17f208fe56465aa330c992b4b3ca19ac0835dd5c54261ba1e41a6c1c30855a772
|
|
7
|
+
data.tar.gz: d501fd465c04ce249ae962aebf2a4886a82021b33470349cbca7ada83d84029485c45ad35355d2114ba09c2f7031c5e96fa04957d80a0f4279b4dc9278ab6f0e
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ All notable changes to Leptris will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.9.237.0] - 2026-09-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `Document#create_element` accepts an attributes hash:
|
|
13
|
+
`doc.create_element("book", "id" => "1", "lang" => "en")` creates
|
|
14
|
+
the element with every attribute in ONE engine crossing
|
|
15
|
+
(leptris_element_new_with_attributes, #1344) — builder paths
|
|
16
|
+
collapse from 1 + N crossings to one. Duplicate names replace,
|
|
17
|
+
last wins; `nil` values store the empty string (engine
|
|
18
|
+
semantics). The native face falls back to create + per-pair sets
|
|
19
|
+
on pins predating #1344.
|
|
20
|
+
|
|
21
|
+
### Performance — engine sync (1.9.237)
|
|
22
|
+
|
|
23
|
+
- Vendored libleptris 1.9.237: typed atoms for QT3 equality
|
|
24
|
+
(typed constructors, float32, the xs: constructor surface),
|
|
25
|
+
per-function equality semantics (index-of/distinct-values/
|
|
26
|
+
deep-equal), the F&O fn:subsequence window with NaN safety and
|
|
27
|
+
member-type preservation, the xpath per-eval registry init fix,
|
|
28
|
+
QT3 slice 3 (405 gated cases), the matched-shape traversal
|
|
29
|
+
benchmark correction (#1341: the structural gap vs libxml2 is
|
|
30
|
+
1.5-1.7x, not 1.8-4.2x), and the single-crossing element
|
|
31
|
+
constructor (#1344).
|
|
32
|
+
|
|
8
33
|
## [1.9.232.0] - 2026-09-24
|
|
9
34
|
|
|
10
35
|
### Added
|
data/Rakefile
CHANGED
|
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
|
8
8
|
# Pin for `rake compile` and the platform-gem builds. Keep in lockstep
|
|
9
9
|
# with .github/workflows/build.yml (which calls `rake compile`) and the
|
|
10
10
|
# CHANGELOG when libleptris releases.
|
|
11
|
-
LIBLEPTRIS_VERSION = "1.9.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.237"
|
|
12
12
|
# Vendored alongside libleptris for fn:normalize-unicode (TODO
|
|
13
13
|
# .restructure/20): built per platform with a RELOCATABLE @rpath
|
|
14
14
|
# install name, loaded by ffi.rb before libleptris so the
|
data/ext/leptris/native/native.c
CHANGED
|
@@ -42,6 +42,8 @@ typedef size_t (*node_offset_fn)(void *);
|
|
|
42
42
|
typedef const char *(*element_text_fn)(void *);
|
|
43
43
|
typedef void *(*doc_create_fn)(void);
|
|
44
44
|
typedef void *(*elem_create_fn)(void *, const char *);
|
|
45
|
+
typedef void *(*elem_new_attrs_fn)(void *, const char *, const char **,
|
|
46
|
+
const char **, size_t);
|
|
45
47
|
typedef void *(*text_create_fn)(void *, const char *);
|
|
46
48
|
typedef void *(*create_child_fn)(void *, const char *);
|
|
47
49
|
typedef int (*append_child_fn)(void *, void *);
|
|
@@ -75,10 +77,14 @@ static node_offset_fn f_node_offset;
|
|
|
75
77
|
static element_text_fn f_element_text;
|
|
76
78
|
static doc_create_fn f_doc_create;
|
|
77
79
|
static elem_create_fn f_elem_create;
|
|
80
|
+
static elem_new_attrs_fn f_elem_new_with_attrs;
|
|
78
81
|
static text_create_fn f_text_create;
|
|
79
82
|
static create_child_fn f_create_child;
|
|
80
83
|
static append_child_fn f_append_child;
|
|
81
84
|
static append_child_fn f_prepend_child, f_insert_after, f_insert_before;
|
|
85
|
+
typedef void *(*elem_new_attrs_fn)(void *, const char *, const char **,
|
|
86
|
+
const char **, size_t);
|
|
87
|
+
static elem_new_attrs_fn f_elem_new_with_attrs;
|
|
82
88
|
static set_attr_fn f_set_attr;
|
|
83
89
|
typedef int (*xp_type_fn)(void *);
|
|
84
90
|
typedef void (*xp_free_fn)(void *);
|
|
@@ -218,6 +224,11 @@ static void resolve_symbols(const char *lib_path)
|
|
|
218
224
|
f_element_text = (element_text_fn)lib_sym(h, "leptris_element_text");
|
|
219
225
|
f_doc_create = (doc_create_fn)lib_sym(h, "leptris_document_create");
|
|
220
226
|
f_elem_create = (elem_create_fn)lib_sym(h, "leptris_element_create");
|
|
227
|
+
/* Single-crossing element construction (libleptris 1.9.237,
|
|
228
|
+
* #1344): NULL in older engine pins; the create path falls
|
|
229
|
+
* back to create + per-pair sets. */
|
|
230
|
+
f_elem_new_with_attrs =
|
|
231
|
+
(elem_new_attrs_fn)lib_sym(h, "leptris_element_new_with_attributes");
|
|
221
232
|
f_text_create = (text_create_fn)lib_sym(h, "leptris_text_node_create");
|
|
222
233
|
f_create_child = (create_child_fn)lib_sym(h, "leptris_element_create_child");
|
|
223
234
|
f_append_child = (append_child_fn)lib_sym(h, "leptris_element_append_child");
|
|
@@ -225,6 +236,11 @@ static void resolve_symbols(const char *lib_path)
|
|
|
225
236
|
f_insert_after = (append_child_fn)lib_sym(h, "leptris_element_insert_after");
|
|
226
237
|
f_insert_before = (append_child_fn)lib_sym(h, "leptris_element_insert_before");
|
|
227
238
|
f_set_attr = (set_attr_fn)lib_sym(h, "leptris_element_set_attribute");
|
|
239
|
+
/* Engine single-crossing construction (leptris#1344, 1.9.236+):
|
|
240
|
+
* optional; absent engines use the create_child + set_attr
|
|
241
|
+
* loop, which is still one Ruby->C crossing. */
|
|
242
|
+
f_elem_new_with_attrs =
|
|
243
|
+
(elem_new_attrs_fn)lib_sym(h, "leptris_element_new_with_attributes");
|
|
228
244
|
f_xp_type = (xp_type_fn)lib_sym(h, "leptris_xpath_result_type");
|
|
229
245
|
f_xp_free = (xp_free_fn)lib_sym(h, "leptris_xpath_result_free");
|
|
230
246
|
f_first_child = (first_child_fn)lib_sym(h, "leptris_node_first_child");
|
|
@@ -1638,15 +1654,88 @@ static VALUE nf_bulk_attributes(VALUE self, VALUE addr)
|
|
|
1638
1654
|
/* ---- Binding create via C (TODO.perf/09): one call creates the
|
|
1639
1655
|
* node AND constructs the binding wrapper (class dispatch, ivars,
|
|
1640
1656
|
* identity-cache store) — no FFI marshaling, no wrap_fresh path. */
|
|
1657
|
+
static int set_attr_pair(VALUE key, VALUE value, VALUE data)
|
|
1658
|
+
{
|
|
1659
|
+
void *elem =
|
|
1660
|
+
(void *)(uintptr_t)NUM2ULL(rb_ary_entry(data, 0));
|
|
1661
|
+
VALUE k = RB_TYPE_P(key, T_STRING) ? key : rb_obj_as_string(key);
|
|
1662
|
+
VALUE v = NIL_P(value) ? rb_usascii_str_new(0, 0)
|
|
1663
|
+
: (RB_TYPE_P(value, T_STRING) ? value
|
|
1664
|
+
: rb_obj_as_string(value));
|
|
1665
|
+
|
|
1666
|
+
rb_ary_push(rb_ary_entry(data, 1), k);
|
|
1667
|
+
rb_ary_push(rb_ary_entry(data, 2), v);
|
|
1668
|
+
f_set_attr(elem, RSTRING_PTR(k), RSTRING_PTR(v));
|
|
1669
|
+
return ST_CONTINUE;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1641
1672
|
static VALUE nf_create_binding_element(VALUE self, VALUE document,
|
|
1642
|
-
VALUE name)
|
|
1673
|
+
VALUE name, VALUE attrs)
|
|
1643
1674
|
{
|
|
1644
1675
|
void *doc = doc_ptr_of(document);
|
|
1645
|
-
void *ptr
|
|
1676
|
+
void *ptr;
|
|
1677
|
+
VALUE name_str = StringValue(name);
|
|
1646
1678
|
VALUE node, cache, key;
|
|
1647
1679
|
|
|
1648
1680
|
(void)self;
|
|
1649
1681
|
resolve_binding_classes();
|
|
1682
|
+
if (attrs == Qnil ||
|
|
1683
|
+
(RB_TYPE_P(attrs, T_HASH) && RHASH_SIZE(attrs) == 0)) {
|
|
1684
|
+
ptr = f_elem_create(doc, RSTRING_PTR(name_str));
|
|
1685
|
+
} else if (f_elem_new_with_attrs != NULL) {
|
|
1686
|
+
/* #1344: element + every attribute in ONE crossing.
|
|
1687
|
+
* Duplicate names replace, last wins; NULL values store
|
|
1688
|
+
* the empty string — engine semantics, identical to
|
|
1689
|
+
* per-pair set_attribute.
|
|
1690
|
+
*
|
|
1691
|
+
* Iteration goes through keys + aref (no rb_hash_foreach
|
|
1692
|
+
* state pointer): every converted key/value is pushed into
|
|
1693
|
+
* Ruby arrays BEFORE its pointer enters the C arrays, so
|
|
1694
|
+
* temporaries (non-String keys, nil -> "") survive until
|
|
1695
|
+
* the engine call returns — no C pointer rides through a
|
|
1696
|
+
* boxed VALUE (long is 32-bit on Windows/LLP64; the
|
|
1697
|
+
* foreach+boxed-struct shape truncated it and segfaulted
|
|
1698
|
+
* the windows CI leg). */
|
|
1699
|
+
VALUE keys, names, values;
|
|
1700
|
+
const char **np, **vp;
|
|
1701
|
+
long cap, i;
|
|
1702
|
+
Check_Type(attrs, T_HASH);
|
|
1703
|
+
cap = (long)RHASH_SIZE(attrs);
|
|
1704
|
+
keys = rb_funcall(attrs, rb_intern("keys"), 0);
|
|
1705
|
+
names = rb_ary_new_capa(cap);
|
|
1706
|
+
values = rb_ary_new_capa(cap);
|
|
1707
|
+
np = ruby_xmalloc(sizeof(char *) * (cap + 1));
|
|
1708
|
+
vp = ruby_xmalloc(sizeof(char *) * (cap + 1));
|
|
1709
|
+
for (i = 0; i < cap; i++) {
|
|
1710
|
+
VALUE k = rb_ary_entry(keys, i);
|
|
1711
|
+
VALUE v = rb_hash_aref(attrs, k);
|
|
1712
|
+
k = RB_TYPE_P(k, T_STRING) ? k : rb_obj_as_string(k);
|
|
1713
|
+
v = NIL_P(v) ? rb_usascii_str_new(0, 0)
|
|
1714
|
+
: (RB_TYPE_P(v, T_STRING) ? v
|
|
1715
|
+
: rb_obj_as_string(v));
|
|
1716
|
+
rb_ary_push(names, k);
|
|
1717
|
+
rb_ary_push(values, v);
|
|
1718
|
+
np[i] = RSTRING_PTR(k);
|
|
1719
|
+
vp[i] = RSTRING_PTR(v);
|
|
1720
|
+
}
|
|
1721
|
+
ptr = f_elem_new_with_attrs(doc, RSTRING_PTR(name_str),
|
|
1722
|
+
np, vp, (size_t)cap);
|
|
1723
|
+
ruby_xfree(np);
|
|
1724
|
+
ruby_xfree(vp);
|
|
1725
|
+
} else {
|
|
1726
|
+
/* Older pin: create + per-pair sets (N+1 crossings). */
|
|
1727
|
+
VALUE addr = Qnil;
|
|
1728
|
+
VALUE anchor;
|
|
1729
|
+
Check_Type(attrs, T_HASH);
|
|
1730
|
+
anchor = rb_ary_new_capa((long)RHASH_SIZE(attrs));
|
|
1731
|
+
ptr = f_elem_create(doc, RSTRING_PTR(name_str));
|
|
1732
|
+
if (!ptr)
|
|
1733
|
+
return Qnil;
|
|
1734
|
+
addr = ULL2NUM((uint64_t)(uintptr_t)ptr);
|
|
1735
|
+
rb_hash_foreach(attrs, set_attr_pair,
|
|
1736
|
+
rb_ary_new3(3, addr, anchor,
|
|
1737
|
+
rb_ary_new_capa(0)));
|
|
1738
|
+
}
|
|
1650
1739
|
if (!ptr)
|
|
1651
1740
|
return Qnil; /* caller raises with the error channel */
|
|
1652
1741
|
node = rb_obj_alloc(c_b_element);
|
|
@@ -2194,6 +2283,56 @@ static VALUE nf_plan_structs_typed_p(VALUE self)
|
|
|
2194
2283
|
* to the per-attribute FFI chain (first/next/get_name/get_value,
|
|
2195
2284
|
* 4 crossings each) — the win amplifies with attribute density
|
|
2196
2285
|
* (40-attr elements: ~7x on the listing). */
|
|
2286
|
+
/* ---- Single-crossing element construction (leptris#1344) --------
|
|
2287
|
+
* Creates an element attached under parent (parent_addr 0 = free
|
|
2288
|
+
*floating, owner document only) with all attributes set — ONE
|
|
2289
|
+
* Ruby->C crossing for the whole construction. Internal calls are
|
|
2290
|
+
* C->C dlsym dispatches (create_child = create+attach in one
|
|
2291
|
+
* engine call; set_attr per attribute). Returns the new node's
|
|
2292
|
+
* address for wrapper minting. */
|
|
2293
|
+
static VALUE nf_create_element_with_attrs(VALUE self, VALUE document,
|
|
2294
|
+
VALUE parent_addr, VALUE name,
|
|
2295
|
+
VALUE attrs)
|
|
2296
|
+
{
|
|
2297
|
+
(void)self;
|
|
2298
|
+
(void)document;
|
|
2299
|
+
void *parent = NIL_P(parent_addr)
|
|
2300
|
+
? NULL
|
|
2301
|
+
: (void *)(uintptr_t)NUM2ULL(parent_addr);
|
|
2302
|
+
const char *cname = StringValueCStr(name);
|
|
2303
|
+
|
|
2304
|
+
if (f_elem_new_with_attrs && parent && RARRAY_LEN(attrs) > 0 &&
|
|
2305
|
+
RARRAY_LEN(attrs) % 2 == 0) {
|
|
2306
|
+
/* Engine single-crossing construction (1.9.236+): arena
|
|
2307
|
+
* create + all attributes with no per-attr calls at all. */
|
|
2308
|
+
long n = RARRAY_LEN(attrs) / 2;
|
|
2309
|
+
const char **names = ALLOCA_N(const char *, n);
|
|
2310
|
+
const char **values = ALLOCA_N(const char *, n);
|
|
2311
|
+
for (long i = 0; i < n; i++) {
|
|
2312
|
+
/* Hoist to lvalues: truffleruby's StringValueCStr takes
|
|
2313
|
+
* the address of its argument (RARRAY_AREF is not one). */
|
|
2314
|
+
VALUE an = RARRAY_AREF(attrs, 2 * i);
|
|
2315
|
+
VALUE av = RARRAY_AREF(attrs, 2 * i + 1);
|
|
2316
|
+
names[i] = StringValueCStr(an);
|
|
2317
|
+
values[i] = StringValueCStr(av);
|
|
2318
|
+
}
|
|
2319
|
+
void *elem = f_elem_new_with_attrs(parent, cname, names, values,
|
|
2320
|
+
n);
|
|
2321
|
+
return elem ? ULL2NUM((uintptr_t)elem) : Qnil;
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
void *elem = parent ? f_create_child(parent, cname) : NULL;
|
|
2325
|
+
if (!elem) return Qnil;
|
|
2326
|
+
|
|
2327
|
+
long i, n = RARRAY_LEN(attrs);
|
|
2328
|
+
for (i = 0; i + 1 < n; i += 2) {
|
|
2329
|
+
VALUE an = RARRAY_AREF(attrs, i);
|
|
2330
|
+
VALUE av = RARRAY_AREF(attrs, i + 1);
|
|
2331
|
+
f_set_attr(elem, StringValueCStr(an), StringValueCStr(av));
|
|
2332
|
+
}
|
|
2333
|
+
return ULL2NUM((uintptr_t)elem);
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2197
2336
|
static VALUE nf_attribute_rows(VALUE self, VALUE document, VALUE addr)
|
|
2198
2337
|
{
|
|
2199
2338
|
(void)self;
|
|
@@ -2808,6 +2947,8 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
2808
2947
|
nf_plan_structs, 3);
|
|
2809
2948
|
rb_define_module_function(m_native, "attribute_rows",
|
|
2810
2949
|
nf_attribute_rows, 2);
|
|
2950
|
+
rb_define_module_function(m_native, "create_element_with_attrs",
|
|
2951
|
+
nf_create_element_with_attrs, 4);
|
|
2811
2952
|
rb_define_module_function(m_native, "plan_structs_typed?",
|
|
2812
2953
|
nf_plan_structs_typed_p, 0);
|
|
2813
2954
|
rb_define_module_function(m_native, "doc_handle_attach",
|
|
@@ -2822,7 +2963,7 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
2822
2963
|
rb_define_module_function(m_native, "bulk_attr_faces",
|
|
2823
2964
|
nf_bulk_attr_faces, 2);
|
|
2824
2965
|
rb_define_module_function(m_native, "create_binding_element",
|
|
2825
|
-
nf_create_binding_element,
|
|
2966
|
+
nf_create_binding_element, 3);
|
|
2826
2967
|
rb_define_module_function(m_native, "create_binding_text",
|
|
2827
2968
|
nf_create_binding_text, 2);
|
|
2828
2969
|
rb_define_module_function(m_native, "bulk_children", nf_bulk_children, 2);
|
data/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/document.rb
CHANGED
|
@@ -389,15 +389,32 @@ class Leptris::XML::Document
|
|
|
389
389
|
element
|
|
390
390
|
end
|
|
391
391
|
|
|
392
|
-
|
|
392
|
+
# attributes: optional Hash of {name => value} applied in the
|
|
393
|
+
# SAME engine crossing as construction
|
|
394
|
+
# (leptris_element_new_with_attributes, #1344) — builder paths
|
|
395
|
+
# collapse from 1 + N crossings to one. nil values store the
|
|
396
|
+
# empty string; duplicate names replace, last wins (engine
|
|
397
|
+
# semantics, identical to per-pair set_attribute).
|
|
398
|
+
def create_element(name, attributes = nil)
|
|
393
399
|
# TODO.perf/09: one C call creates + wraps when the ext is
|
|
394
400
|
# loaded — no FFI marshaling, no wrap_fresh frames.
|
|
395
401
|
if defined?(Leptris::XML::NATIVE_FAST)
|
|
396
|
-
node = Leptris::XML::Native.create_binding_element(
|
|
402
|
+
node = Leptris::XML::Native.create_binding_element(
|
|
403
|
+
self, name.to_s, attributes)
|
|
397
404
|
raise Leptris::XML::Error, "leptris_element_create failed" if node.nil?
|
|
398
405
|
return node
|
|
399
406
|
end
|
|
400
|
-
ptr =
|
|
407
|
+
ptr =
|
|
408
|
+
if attributes && !attributes.empty?
|
|
409
|
+
names = attributes.map { |k, _| k.to_s }
|
|
410
|
+
values = attributes.map { |_, v| v.nil? ? "" : v.to_s }
|
|
411
|
+
nb, na = Leptris::XML::CStringArray.to_c(names)
|
|
412
|
+
vb, va = Leptris::XML::CStringArray.to_c(values)
|
|
413
|
+
Leptris::XML::FFI.leptris_element_new_with_attributes(
|
|
414
|
+
c_ptr, name.to_s, nb, vb, names.size)
|
|
415
|
+
else
|
|
416
|
+
Leptris::XML::FFI.leptris_element_create(c_ptr, name)
|
|
417
|
+
end
|
|
401
418
|
raise Leptris::XML::Error, "leptris_element_create failed" if ptr.null?
|
|
402
419
|
Leptris::XML::Node.wrap_fresh(ptr, self, Leptris::XML::FFI::NODE_ELEMENT)
|
|
403
420
|
end
|