leptris 1.9.242.0 → 1.9.248.0
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 +16 -0
- data/Rakefile +1 -1
- data/lib/leptris/vendor/aarch64-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/aarch64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/arm-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/arm-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/arm64-darwin/libleptris.dylib +0 -0
- data/lib/leptris/vendor/ppc64le-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/s390x-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/x86_64-darwin/libleptris.dylib +0 -0
- data/lib/leptris/vendor/x86_64-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/x86_64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/version.rb +1 -1
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +16 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/leptris/html/html_parse.c +10 -1
- data/vendor-src/libleptris/src/leptris/leptris.c +16 -2
- data/vendor-src/libleptris/src/leptris/xpath/evaluator.c +41 -1
- data/vendor-src/libleptris/test/xquery/test_qt3.cpp +1 -2
- data/vendor-src/libleptris/test/xquery/test_xquery.cpp +45 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- 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: 1445126f3a7bced66c8ccb08c13e6d61f0a8ffc95f154bb091aedd07e54ef706
|
|
4
|
+
data.tar.gz: c0c39cf6600337d568dfae5237f650a5b3aa1ebab16b42a648fff456c9d8f050
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35a1e9c1637cdfb8d2556d6ce9e10b5fce62b369f5824ae4b9a941026dee156bc54aa5d8dc9d30ba2fe25e8403d096c45449234ed29b422ce5d12febeca9d7ec
|
|
7
|
+
data.tar.gz: 36a555006ae5e9bb900eaa2f4955c337e4251dbfdd58be20ba91b4825b79de86a6fd8a8b161608c4f71c3d49422d68f3c97e6720e0baceac47e6de7cd0a8e26d
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,22 @@ 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.248.0] - 2026-09-26
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Vendored libleptris 1.9.248 (riding 1.9.247 + 1.9.248):
|
|
13
|
+
- xpath: filtering a non-nodeset base treats the atom as a
|
|
14
|
+
one-item sequence — `(1)[1]` keeps the atom and `(1)[1] + 1`
|
|
15
|
+
is 2 (was an unconditional empty nodeset).
|
|
16
|
+
- html: the document arena span is sized from the input once
|
|
17
|
+
(#1218) — borrowed pointers stay in the int32 compact range,
|
|
18
|
+
removing ~776k overflow-table inserts on a 2.6 MB parse;
|
|
19
|
+
measured 31.4 -> 50.9 MB/s (+62%) on the table-rows corpus.
|
|
20
|
+
- Restores the naming lockstep: the previous release vendored
|
|
21
|
+
engine 1.9.246 under the version 1.9.242.0; version.rb now
|
|
22
|
+
matches the vendored engine semver again.
|
|
23
|
+
|
|
8
24
|
## [1.9.241.0] - 2026-09-25
|
|
9
25
|
|
|
10
26
|
### Fixed
|
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.248"
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/leptris/version.rb
CHANGED
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.248] - 2026-09-26
|
|
4
|
+
|
|
5
|
+
<!-- Edit this section with the actual release notes. -->
|
|
6
|
+
<!-- See https://keepachangelog.com for format guidance. -->
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- (describe changes here)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [1.9.247] - 2026-09-26
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- filter on a non-nodeset base treats the atom as a one-item sequence (xpath)
|
|
18
|
+
|
|
3
19
|
## [1.9.246] - 2026-09-25
|
|
4
20
|
|
|
5
21
|
### Added
|
|
@@ -5453,8 +5453,17 @@ static LeptrisDocument html_parse_shared(
|
|
|
5453
5453
|
if (status) *status = LEPTRIS_ERROR_NULL_ARG;
|
|
5454
5454
|
return NULL;
|
|
5455
5455
|
}
|
|
5456
|
+
/* #1218: size the arena span from the input up front — the
|
|
5457
|
+
* HTML tree expands ~8x (nodes + attributes + the owned input
|
|
5458
|
+
* copy), and an undersized span spills later allocations into
|
|
5459
|
+
* extension blocks in a different malloc region, pushing every
|
|
5460
|
+
* borrowed pointer out of the int32 compact range (measured
|
|
5461
|
+
* 776k overflow-table inserts on the 2.6 MB table shape). */
|
|
5462
|
+
extern struct leptris_document* leptris_document_create_with_arena_size(
|
|
5463
|
+
size_t arena_size);
|
|
5456
5464
|
struct leptris_document* doc =
|
|
5457
|
-
(struct leptris_document*)
|
|
5465
|
+
(struct leptris_document*)leptris_document_create_with_arena_size(
|
|
5466
|
+
len * 10 + (1u << 18));
|
|
5458
5467
|
if (!doc) {
|
|
5459
5468
|
if (status) *status = LEPTRIS_ERROR_MEMORY;
|
|
5460
5469
|
return NULL;
|
|
@@ -173,7 +173,17 @@ void leptris_parse_options_init(leptris_parse_options* opts) {
|
|
|
173
173
|
* pool-allocated (TODO 154) zeroed struct, strict mode inherited
|
|
174
174
|
* from the thread-local setting, standalone unset (-1).
|
|
175
175
|
*/
|
|
176
|
-
|
|
176
|
+
/* #1218: parse entry points that know their input size reserve the
|
|
177
|
+
* arena span ONCE at content-derived scale — an undersized span
|
|
178
|
+
* overflows into tracked extension blocks, which malloc places in a
|
|
179
|
+
* different region (measured 105 TB away on macOS, ~5.5 GB from the
|
|
180
|
+
* span). Every borrowed pointer (text runs, element names, attribute
|
|
181
|
+
* strings) then exceeds the int32 compact range and pays an
|
|
182
|
+
* overflow-table insert per field plus a hash lookup per decode for
|
|
183
|
+
* the REST of the parse. Sized spans keep the whole parse in one
|
|
184
|
+
* contiguous region. */
|
|
185
|
+
struct leptris_document* leptris_document_create_with_arena_size(
|
|
186
|
+
size_t arena_size) {
|
|
177
187
|
extern LeptrisMemoryPool* leptris_pool_create_arena_backed(
|
|
178
188
|
LeptrisArena*, int);
|
|
179
189
|
extern void* leptris_pool_alloc(LeptrisMemoryPool* pool, size_t size);
|
|
@@ -185,7 +195,7 @@ LEPTRIS_API LeptrisDocument leptris_document_create(void) {
|
|
|
185
195
|
* documents take the same arena-backed pool the parser uses
|
|
186
196
|
* (overflow extends via tracked blocks; the pool's page
|
|
187
197
|
* machinery no longer runs for documents). */
|
|
188
|
-
LeptrisArena* arena = leptris_arena_create(
|
|
198
|
+
LeptrisArena* arena = leptris_arena_create(arena_size);
|
|
189
199
|
if (!arena) return NULL;
|
|
190
200
|
LeptrisMemoryPool* pool = leptris_pool_create_arena_backed(arena, 1);
|
|
191
201
|
if (!pool) {
|
|
@@ -210,6 +220,10 @@ LEPTRIS_API LeptrisDocument leptris_document_create(void) {
|
|
|
210
220
|
return doc;
|
|
211
221
|
}
|
|
212
222
|
|
|
223
|
+
LEPTRIS_API LeptrisDocument leptris_document_create(void) {
|
|
224
|
+
return leptris_document_create_with_arena_size(64 * 1024);
|
|
225
|
+
}
|
|
226
|
+
|
|
213
227
|
LEPTRIS_API LeptrisDocument leptris_document_create_html(void) {
|
|
214
228
|
struct leptris_document* doc = leptris_document_create();
|
|
215
229
|
if (doc) doc->html_mode = 1;
|
|
@@ -985,8 +985,48 @@ struct leptris_xpath_result* evaluate_expr(XPathContext* ctx, XPathASTNode* ast)
|
|
|
985
985
|
if (!base) return NULL;
|
|
986
986
|
if (base->type != XPATH_RESULT_NODESET ||
|
|
987
987
|
!base->value.nodeset_value) {
|
|
988
|
+
/* Non-nodeset base: the atom is a one-item sequence
|
|
989
|
+
* — (1)[1] keeps it, (1)[true()] keeps it, (1)[2]
|
|
990
|
+
* empties (the old code returned empty
|
|
991
|
+
* unconditionally). The predicate sees position 1
|
|
992
|
+
* of 1; the context node stays the outer one. */
|
|
993
|
+
int keep = 1;
|
|
994
|
+
for (size_t p = 1; p < ast->child_count && keep; p++) {
|
|
995
|
+
XPathASTNode* pred = ast->children[p];
|
|
996
|
+
if (pred->type == XPATH_AST_NUMBER) {
|
|
997
|
+
keep = pred->number_value == 1.0;
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
LeptrisElement old_node = ctx->context_node;
|
|
1001
|
+
size_t old_pos = ctx->context_position;
|
|
1002
|
+
size_t old_size = ctx->context_size;
|
|
1003
|
+
void* old_pred = ctx->current_predicate_node;
|
|
1004
|
+
ctx->context_position = 1;
|
|
1005
|
+
ctx->context_size = 1;
|
|
1006
|
+
struct leptris_xpath_result* pr =
|
|
1007
|
+
evaluate_expr(ctx, pred);
|
|
1008
|
+
ctx->context_node = old_node;
|
|
1009
|
+
ctx->context_position = old_pos;
|
|
1010
|
+
ctx->context_size = old_size;
|
|
1011
|
+
ctx->current_predicate_node = old_pred;
|
|
1012
|
+
if (!pr) {
|
|
1013
|
+
keep = 0;
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
if (pr->type == XPATH_RESULT_NUMBER)
|
|
1017
|
+
keep =
|
|
1018
|
+
(size_t)pr->value.number_value == 1;
|
|
1019
|
+
else
|
|
1020
|
+
keep = xpath_to_boolean(pr) ? 1 : 0;
|
|
1021
|
+
xpath_result_free(pr);
|
|
1022
|
+
}
|
|
1023
|
+
if (keep) return base;
|
|
988
1024
|
xpath_result_free(base);
|
|
989
|
-
|
|
1025
|
+
struct leptris_xpath_result* empty =
|
|
1026
|
+
xpath_result_new(XPATH_RESULT_NODESET);
|
|
1027
|
+
if (empty && empty->value.nodeset_value)
|
|
1028
|
+
empty->value.nodeset_value->is_sequence = 1;
|
|
1029
|
+
return empty;
|
|
990
1030
|
}
|
|
991
1031
|
if (ast->child_count > 1) {
|
|
992
1032
|
apply_predicates(ctx, base->value.nodeset_value,
|
|
@@ -941,7 +941,7 @@ TEST(Qt3Subset, FnReverse) {
|
|
|
941
941
|
}
|
|
942
942
|
|
|
943
943
|
TEST(Qt3Subset, FnSubsequence) {
|
|
944
|
-
run_test_set("fn/subsequence.xml", {},
|
|
944
|
+
run_test_set("fn/subsequence.xml", {}, 68, {},
|
|
945
945
|
{
|
|
946
946
|
"cbcl-subsequence-011",
|
|
947
947
|
"cbcl-subsequence-012",
|
|
@@ -949,7 +949,6 @@ TEST(Qt3Subset, FnSubsequence) {
|
|
|
949
949
|
"cbcl-subsequence-014",
|
|
950
950
|
"cbcl-subsequence-025",
|
|
951
951
|
"cbcl-subsequence-019", /* document{} + `!` map chain */
|
|
952
|
-
"K-SeqSubsequenceFunc-34", /* mixed-type seq item eq */
|
|
953
952
|
"fn-subsequence-mix-args-025", /* `!` + @id pair */
|
|
954
953
|
|
|
955
954
|
});
|
|
@@ -893,6 +893,51 @@ TEST(XQueryCtors, SequenceItemEbv) {
|
|
|
893
893
|
/* unordered{E} / ordered{E} order-mode constructors: order is
|
|
894
894
|
* irrelevant to this engine's sequence model, so the splice strips
|
|
895
895
|
* them to (E) (QT3 K2-SeqReverseFunc-2 nests three deep). */
|
|
896
|
+
/* Filter on a non-nodeset base: the atom is a one-item sequence —
|
|
897
|
+
* (1)[1] keeps it, (1)[2] empties, boolean predicates see position
|
|
898
|
+
* 1 of 1 (QT3 K-SeqSubsequenceFunc-34 chains (1)[deep-equal(...)]).
|
|
899
|
+
* The old code returned an empty nodeset unconditionally. */
|
|
900
|
+
TEST(XPathFilter, ScalarBase) {
|
|
901
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
902
|
+
LeptrisDocument doc = leptris_parse_string("<e/>", 4, &st);
|
|
903
|
+
ASSERT_NE(doc, nullptr);
|
|
904
|
+
struct {
|
|
905
|
+
const char* q;
|
|
906
|
+
const char* want;
|
|
907
|
+
} cases[] = {
|
|
908
|
+
{"(1)[1]", "1"},
|
|
909
|
+
{"(1)[true()]", "1"},
|
|
910
|
+
{"(2)[1]", "2"},
|
|
911
|
+
{"(1)[2]", ""},
|
|
912
|
+
{"(1)[false()]", ""},
|
|
913
|
+
{"(1)[deep-equal(1, 1)] eq 1", "true"},
|
|
914
|
+
{"(1)[1] + 1", "2"},
|
|
915
|
+
};
|
|
916
|
+
for (auto& c : cases) {
|
|
917
|
+
LeptrisXQuery xq = leptris_xquery_parse(c.q, strlen(c.q));
|
|
918
|
+
ASSERT_NE(xq, nullptr) << c.q;
|
|
919
|
+
LeptrisXPathResult r = leptris_xquery_eval(xq, doc, NULL);
|
|
920
|
+
ASSERT_NE(r, nullptr) << c.q;
|
|
921
|
+
std::string got;
|
|
922
|
+
if (leptris_xpath_result_type(r) == LEPTRIS_XPATH_NODESET) {
|
|
923
|
+
size_t n = leptris_xpath_result_count(r);
|
|
924
|
+
for (size_t i = 0; i < n; i++) {
|
|
925
|
+
const char* v = leptris_xpath_result_node_value(r, i);
|
|
926
|
+
if (i) got += ' ';
|
|
927
|
+
got += v ? v : "";
|
|
928
|
+
}
|
|
929
|
+
} else {
|
|
930
|
+
char* s2 = leptris_xpath_result_string(r);
|
|
931
|
+
got = s2 ? s2 : "";
|
|
932
|
+
leptris_free_string(s2);
|
|
933
|
+
}
|
|
934
|
+
EXPECT_EQ(got, c.want) << c.q;
|
|
935
|
+
leptris_xpath_result_free(r);
|
|
936
|
+
leptris_xquery_free(xq);
|
|
937
|
+
}
|
|
938
|
+
leptris_document_free(doc);
|
|
939
|
+
}
|
|
940
|
+
|
|
896
941
|
TEST(XQueryCtors, OrderModeStrip) {
|
|
897
942
|
LeptrisStatus st = LEPTRIS_OK;
|
|
898
943
|
LeptrisDocument doc = leptris_parse_string("<e/>", 4, &st);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
|
|
3
3
|
"name": "leptris",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.248",
|
|
5
5
|
"description": "High-performance XML parser and XPath 1.0 engine in C (libleptris)",
|
|
6
6
|
"homepage": "https://github.com/leptris/leptris",
|
|
7
7
|
"license": "MIT",
|
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.
|
|
4
|
+
version: 1.9.248.0
|
|
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-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|