leptris 1.9.319.0-ppc64le-linux → 1.9.321.0-ppc64le-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 +35 -0
- data/Rakefile +1 -1
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/ffi.rb +15 -0
- data/lib/leptris/xml/xsd.rb +58 -6
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +45 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/CMakeLists.txt +2 -0
- data/vendor-src/libleptris/src/include/leptris.h +22 -0
- data/vendor-src/libleptris/src/leptris/descriptor/plan.c +35 -3
- data/vendor-src/libleptris/src/leptris/xsd/compile.c +309 -1
- data/vendor-src/libleptris/src/leptris/xsd/content_model.c +232 -0
- data/vendor-src/libleptris/src/leptris/xsd/validate.c +287 -0
- data/vendor-src/libleptris/src/leptris/xsd/xsd_internal.h +48 -0
- data/vendor-src/libleptris/test/abi/test_descriptor.cpp +168 -0
- data/vendor-src/libleptris/test/xsd/test_xsd_compile.cpp +253 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1048f2fc1a458e50488f4a53446f240132e308854082ef6111ca9efeb1a9689
|
|
4
|
+
data.tar.gz: 354c7562a80d80c4ab7b61bd0289cae6df4d06153b17ba63386c9a03b135f71a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17327bf2ee904eb779ffdcc430cfd6d2efd44a597e0bde5c223cef1f158372fed36cf61ce3f0d02fd16e14f822b9646d01719cc893e7ec8d9f93d0de39758281
|
|
7
|
+
data.tar.gz: 0b6affc78a6e658809641bedea21c45886558d50f662a35a1c42698512617a7cf5fbdcfc650054dc6d27b4855536a1281ac9651a653c2f55e0f52a34bb67b8e7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
## [1.9.321.0] - 2026-10-08
|
|
2
|
+
|
|
3
|
+
### Added — engine sync (libleptris 1.9.321)
|
|
4
|
+
|
|
5
|
+
- **XSD instance validation, slices 3-4 (#1075)**:
|
|
6
|
+
`Schema#valid?` walks the whole document — element declarations,
|
|
7
|
+
attribute rows (required + typed + lenient qualified spellings),
|
|
8
|
+
text lexical checks, child content models through a Thompson NFA
|
|
9
|
+
(linear in children x states, no backtracking blowup);
|
|
10
|
+
`Schema#validate_errors` enumerates every failure (the engine
|
|
11
|
+
replaces the list per run); `Schema#content_valid?` evaluates a
|
|
12
|
+
child sequence directly against a top-level declaration's model.
|
|
13
|
+
The -1 contract raises (unknown declaration never masquerades as
|
|
14
|
+
invalid input). Pins use the named-ref shape — the inline-
|
|
15
|
+
anonymous complexType capture gap is filed upstream
|
|
16
|
+
(leptris#1592).
|
|
17
|
+
|
|
18
|
+
## [1.9.320.0] - 2026-10-08
|
|
19
|
+
|
|
20
|
+
### Fixed — engine sync (libleptris 1.9.320)
|
|
21
|
+
|
|
22
|
+
- **Exact-URI child rows survive build-anchor GC (#1585)**: the
|
|
23
|
+
engine's plan build let child-row `ns_uri` ride a pointer into
|
|
24
|
+
the caller's build buffers instead of deep-copying — bindings
|
|
25
|
+
GC their anchors after build, so exact-URI child rows
|
|
26
|
+
deterministically stopped matching (uniword's
|
|
27
|
+
dc:title/dc:creator/dc:description hydrated nil). The engine
|
|
28
|
+
retains the URI; pinned with build + GC + walk.
|
|
29
|
+
- **Plain attribute rows match any qualification (#1586)**:
|
|
30
|
+
ns-unset attr rows try the exact wire spelling first, then any
|
|
31
|
+
qualification by local name (#758 parity) — plain rows bind
|
|
32
|
+
`w:name`/`w:val` exactly as the interpretive path does, top
|
|
33
|
+
level and nested; exact-URI rows keep their #1486 precedence.
|
|
34
|
+
Pinned at both depths.
|
|
35
|
+
|
|
1
36
|
## [1.9.319.0] - 2026-10-08
|
|
2
37
|
|
|
3
38
|
### Added — engine sync (libleptris 1.9.319)
|
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.321"
|
|
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/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/ffi.rb
CHANGED
|
@@ -1304,6 +1304,21 @@ attach_function :leptris_parse_string,
|
|
|
1304
1304
|
[:string, :string], :int
|
|
1305
1305
|
attach_function :leptris_xsd_simple_valid,
|
|
1306
1306
|
[:leptris_xsd_schema, :string, :string], :int
|
|
1307
|
+
# Slices 3-4 (libleptris 1.9.321, #1075): content models via
|
|
1308
|
+
# Thompson NFA (linear in children x states) and whole-
|
|
1309
|
+
# instance validation — element declarations, attribute rows
|
|
1310
|
+
# (required + typed + lenient qualified spellings), text
|
|
1311
|
+
# lexical checks, child content models. Failures enumerate
|
|
1312
|
+
# behind error_count/_at (schema-owned; the next validate
|
|
1313
|
+
# run replaces them).
|
|
1314
|
+
attach_function :leptris_xsd_content_valid,
|
|
1315
|
+
[:leptris_xsd_schema, :string, :pointer, :pointer, :size_t], :int
|
|
1316
|
+
attach_function :leptris_xsd_validate,
|
|
1317
|
+
[:leptris_xsd_schema, :leptris_document], :int
|
|
1318
|
+
attach_function :leptris_xsd_error_count,
|
|
1319
|
+
[:leptris_xsd_schema], :size_t
|
|
1320
|
+
attach_function :leptris_xsd_error_at,
|
|
1321
|
+
[:leptris_xsd_schema, :size_t], UTF8_STRING
|
|
1307
1322
|
|
|
1308
1323
|
attach_function :leptris_rng_parse,
|
|
1309
1324
|
[:string, :size_t, :pointer], :leptris_relaxng
|
data/lib/leptris/xml/xsd.rb
CHANGED
|
@@ -79,14 +79,66 @@ module Leptris::XML::XSD
|
|
|
79
79
|
# name) — restriction chains validate every hop's facets,
|
|
80
80
|
# cycle-guarded. Unknown type names raise (the -1 contract).
|
|
81
81
|
def simple_valid?(type_name, lexical)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
tri_state(
|
|
83
|
+
Leptris::XML::FFI.leptris_xsd_simple_valid(
|
|
84
|
+
@handle, type_name.to_s, lexical.to_s),
|
|
85
|
+
"#{type_name.inspect} is not a simpleType in this schema")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Slices 3-4 (libleptris 1.9.321, #1075): whole-instance
|
|
89
|
+
# validation — element declarations, attribute rows (required
|
|
90
|
+
# + typed + lenient qualified spellings), text lexical checks,
|
|
91
|
+
# and child content models through the Thompson NFA. Returns
|
|
92
|
+
# true/false.
|
|
93
|
+
def valid?(document)
|
|
94
|
+
tri_state(
|
|
95
|
+
Leptris::XML::FFI.leptris_xsd_validate(
|
|
96
|
+
@handle, document.c_ptr), "invalid document handle")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# The enumerated failure list of the last #validate run
|
|
100
|
+
# (empty when valid; the NEXT validate replaces the list).
|
|
101
|
+
def validate_errors(document)
|
|
102
|
+
valid?(document)
|
|
103
|
+
Leptris::XML::FFI.leptris_xsd_error_count(@handle).times.map do |i|
|
|
104
|
+
Leptris::XML::FFI.leptris_xsd_error_at(@handle, i)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Slice 3 direct face: a child SEQUENCE against a top-level
|
|
109
|
+
# element declaration's compiled content model (occurrence
|
|
110
|
+
# bounds, xs:any wildcards). +children+ are child Nodes (name
|
|
111
|
+
# + effective namespace extracted per child). Unknown element
|
|
112
|
+
# declarations raise (the -1 contract).
|
|
113
|
+
def content_valid?(element_name, children)
|
|
114
|
+
kids = children.to_a
|
|
115
|
+
nb, na = Leptris::XML::CStringArray.to_c(
|
|
116
|
+
kids.map { |c| c.name.to_s })
|
|
117
|
+
ub, ua = Leptris::XML::CStringArray.to_c(
|
|
118
|
+
kids.map { |c| child_ns_uri(c) })
|
|
119
|
+
tri_state(
|
|
120
|
+
Leptris::XML::FFI.leptris_xsd_content_valid(
|
|
121
|
+
@handle, element_name.to_s, nb, ub, kids.size),
|
|
122
|
+
"#{element_name.inspect} is not a top-level element declaration")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
# A child's effective namespace URI (nil = none) — read
|
|
128
|
+
# through its own c_ptr, so docless wrappers work.
|
|
129
|
+
def child_ns_uri(node)
|
|
130
|
+
uri = Leptris::XML::FFI.leptris_element_namespace(node.c_ptr)
|
|
131
|
+
uri.nil? || uri.empty? ? "" : uri
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# The C faces' 1/0/-1 contract: true/false, with -1 raising —
|
|
135
|
+
# a silent false would mean "no such declaration/type", which
|
|
136
|
+
# callers must never confuse with "invalid input".
|
|
137
|
+
def tri_state(code, unknown_message)
|
|
138
|
+
case code
|
|
85
139
|
when 1 then true
|
|
86
140
|
when 0 then false
|
|
87
|
-
else
|
|
88
|
-
raise ArgumentError,
|
|
89
|
-
"#{type_name.inspect} is not a simpleType in this schema"
|
|
141
|
+
else raise ArgumentError, unknown_message
|
|
90
142
|
end
|
|
91
143
|
end
|
|
92
144
|
end
|
data/lib/libleptris.so
CHANGED
|
Binary file
|
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.321] - 2026-10-08
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **XSD validation, tier 1, slices 3–4 (#1075, PRs #1589/#1590).**
|
|
8
|
+
Slice 3 — content models: the compiler captures top-level
|
|
9
|
+
`xs:element` declarations and named `xs:complexType` models
|
|
10
|
+
(sequence/choice/all, occurrence bounds incl. unbounded, element
|
|
11
|
+
name/ref particles, `xs:any` wildcards with the full
|
|
12
|
+
namespace-filter grammar); `leptris_xsd_content_valid` evaluates
|
|
13
|
+
a child sequence through a Thompson NFA — linear in children x
|
|
14
|
+
states, no backtracking blowup on nested choices. Slice 4 —
|
|
15
|
+
instance validation: `leptris_xsd_validate(schema, document)`
|
|
16
|
+
walks element declarations, complexType attribute rows
|
|
17
|
+
(required + typed + lenient qualified spellings), child content
|
|
18
|
+
models, and lexical text checks for simple-typed elements
|
|
19
|
+
(particles carry type refs); failures enumerate behind
|
|
20
|
+
`leptris_xsd_error_count/_at`. The libxml2 corpus gate holds at
|
|
21
|
+
163/163; full suite 1911/1911.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## [1.9.320] - 2026-10-08
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **Descriptor: child-row exact-URI `ns_uri` retained at build
|
|
30
|
+
(#1585, PR #1587).** The build deep-copied child `ns_prefix` but
|
|
31
|
+
let `ns_uri` ride the struct copy — a pointer into the caller's
|
|
32
|
+
build buffers. Bindings GC their anchors (a warm walk plus one GC
|
|
33
|
+
makes it deterministic), after which exact-URI child rows
|
|
34
|
+
silently stopped matching and hydration answered nil (uniword's
|
|
35
|
+
`dc:title`/`dc:creator`/`dc:description`). The spec trashes the
|
|
36
|
+
caller's buffer after build and asserts the row still binds.
|
|
37
|
+
- **Descriptor: plain attribute rows match any qualification
|
|
38
|
+
(#1586, PR #1587).** `dp_attr_value`'s ns-unset path now mirrors
|
|
39
|
+
#758 — the exact wire spelling first, then any qualification by
|
|
40
|
+
local name — so plain rows bind `w:name`/`w:val` exactly as the
|
|
41
|
+
interpretive path does, top level and nested. Exact-URI rows keep
|
|
42
|
+
their #1486 precedence. A NESTED row's binding also consults the
|
|
43
|
+
TARGET plan's `ns_lenient` now (the #1115-consistent authority)
|
|
44
|
+
instead of the outer plan's.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
3
48
|
## [1.9.319] - 2026-10-08
|
|
4
49
|
|
|
5
50
|
### Added
|
|
@@ -920,6 +920,28 @@ LEPTRIS_API int leptris_xsd_builtin_valid(const char* builtin,
|
|
|
920
920
|
LEPTRIS_API int leptris_xsd_simple_valid(LeptrisXsdSchema schema,
|
|
921
921
|
const char* type_name,
|
|
922
922
|
const char* lexical);
|
|
923
|
+
/* Slice 3 — content models. Validates a child sequence against the
|
|
924
|
+
* compiled content model of a top-level element declaration (its
|
|
925
|
+
* type's sequence/choice/all with occurrence bounds and xs:any
|
|
926
|
+
* wildcards). 1 valid, 0 invalid, -1 unknown element. child_ns may
|
|
927
|
+
* be NULL (all children unqualified). */
|
|
928
|
+
LEPTRIS_API int leptris_xsd_content_valid(
|
|
929
|
+
LeptrisXsdSchema schema, const char* element_name,
|
|
930
|
+
const char* const* child_names, const char* const* child_ns,
|
|
931
|
+
size_t child_count);
|
|
932
|
+
/* Slice 4 — instance validation. Walks the document against the
|
|
933
|
+
* compiled schema: element declarations by name, attribute rows
|
|
934
|
+
* (required use + typed values, lenient qualified spellings),
|
|
935
|
+
* text lexical checks for simple-typed elements, child content
|
|
936
|
+
* models (slice 3). Returns 1 valid, 0 invalid, -1 bad args.
|
|
937
|
+
* Errors accumulate — leptris_xsd_error_count/_at enumerate them
|
|
938
|
+
* (schema-owned; the next validate run replaces them; freed with
|
|
939
|
+
* the schema). */
|
|
940
|
+
LEPTRIS_API int leptris_xsd_validate(LeptrisXsdSchema schema,
|
|
941
|
+
LeptrisDocument doc);
|
|
942
|
+
LEPTRIS_API size_t leptris_xsd_error_count(LeptrisXsdSchema schema);
|
|
943
|
+
LEPTRIS_API const char* leptris_xsd_error_at(LeptrisXsdSchema schema,
|
|
944
|
+
size_t i);
|
|
923
945
|
/* Validate an instance document against the parsed schema
|
|
924
946
|
* (phase-2 core subset: element/attribute/text/data/value/
|
|
925
947
|
* choice/group/interleave/repeats/ref). Returns 1 valid; on 0,
|
|
@@ -285,6 +285,7 @@ static void dp_plan_free(LeptrisPlan p) {
|
|
|
285
285
|
for (uint32_t c = 0; c < d->child_count; c++) {
|
|
286
286
|
free((char *)d->child_plans[c].wire_name);
|
|
287
287
|
free((char *)d->child_plans[c].ns_prefix);
|
|
288
|
+
free((char *)d->child_plans[c].ns_uri);
|
|
288
289
|
for (uint16_t pi = 0;
|
|
289
290
|
pi < d->child_plans[c].predicate_count; pi++) {
|
|
290
291
|
free((char*)d->child_plans[c]
|
|
@@ -481,6 +482,15 @@ LEPTRIS_API LeptrisPlan leptris_plan_build(const leptris_plan_spec* spec,
|
|
|
481
482
|
sc->ns_prefix ? dp_strdup(sc->ns_prefix) : NULL;
|
|
482
483
|
if (sc->ns_prefix && !d->child_plans[c].ns_prefix)
|
|
483
484
|
goto oom;
|
|
485
|
+
/* #1585: ns_uri rides the struct copy otherwise —
|
|
486
|
+
* a dangling pointer into the caller's build
|
|
487
|
+
* buffers once they are reclaimed (bindings GC
|
|
488
|
+
* their anchors; the descriptor must outlive
|
|
489
|
+
* them). Same retention as attr rows (#1486). */
|
|
490
|
+
d->child_plans[c].ns_uri =
|
|
491
|
+
sc->ns_uri ? dp_strdup(sc->ns_uri) : NULL;
|
|
492
|
+
if (sc->ns_uri && !d->child_plans[c].ns_uri)
|
|
493
|
+
goto oom;
|
|
484
494
|
uint16_t pc = sc->predicate_count;
|
|
485
495
|
if (pc) {
|
|
486
496
|
if (!sc->predicates) goto oom;
|
|
@@ -598,8 +608,25 @@ static int dp_walk_children(LeptrisElement elem, const dp_plan* plan,
|
|
|
598
608
|
* namespace (XML namespaces §5.2) — EXACT never binds them. */
|
|
599
609
|
static const char* dp_attr_value(LeptrisElement elem,
|
|
600
610
|
const leptris_attr_plan* ap) {
|
|
601
|
-
if (!ap->ns_form)
|
|
602
|
-
|
|
611
|
+
if (!ap->ns_form) {
|
|
612
|
+
/* #1586, the plan-path mirror of #758: the exact wire
|
|
613
|
+
* spelling first, then any qualification by local name —
|
|
614
|
+
* plain rows are lenient exactly like element rows under
|
|
615
|
+
* ns_lenient. Exact-URI rows keep their #1486 semantics. */
|
|
616
|
+
const char* exact =
|
|
617
|
+
leptris_element_attribute(elem, ap->wire_name);
|
|
618
|
+
if (exact) return exact;
|
|
619
|
+
for (LeptrisAttribute at = leptris_element_first_attribute(elem);
|
|
620
|
+
at; at = leptris_attribute_next(at)) {
|
|
621
|
+
const char* qn = leptris_attribute_get_name(at);
|
|
622
|
+
if (!qn) continue;
|
|
623
|
+
const char* colon = strchr(qn, ':');
|
|
624
|
+
const char* local = colon ? colon + 1 : qn;
|
|
625
|
+
if (strcmp(local, ap->wire_name) == 0)
|
|
626
|
+
return leptris_attribute_get_value(elem, at);
|
|
627
|
+
}
|
|
628
|
+
return NULL;
|
|
629
|
+
}
|
|
603
630
|
for (LeptrisAttribute at = leptris_element_first_attribute(elem);
|
|
604
631
|
at; at = leptris_attribute_next(at)) {
|
|
605
632
|
const char* qn = leptris_attribute_get_name(at);
|
|
@@ -832,8 +859,13 @@ static int dp_walk_children(LeptrisElement elem, const dp_plan* plan,
|
|
|
832
859
|
LeptrisElement child = (LeptrisElement)n;
|
|
833
860
|
if (!dp_wire_name_matches(child, row->wire_name))
|
|
834
861
|
continue;
|
|
862
|
+
/* The TARGET plan's form governs (#1115) — so its
|
|
863
|
+
* lenient flag governs the leniency, not the outer
|
|
864
|
+
* plan's (#1586: a namespaced child under a plan
|
|
865
|
+
* that declares ns_lenient binds by local name). */
|
|
835
866
|
if (!dp_ns_binds(child, target->ns_form, target->ns_uri,
|
|
836
|
-
|
|
867
|
+
(target->flags &
|
|
868
|
+
LEPTRIS_PLAN_FLAG_NS_LENIENT) != 0))
|
|
837
869
|
continue;
|
|
838
870
|
/* Claim the element against later same-wire rows
|
|
839
871
|
* (predicate partitioning). */
|