taurus 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +518 -0
- data/CLAUDE.md +104 -0
- data/LICENSE.md +33 -0
- data/README.adoc +1529 -0
- data/Rakefile +7 -0
- data/TODO.impl/01-architecture.md +217 -0
- data/TODO.impl/02-ffi-declarations.md +236 -0
- data/TODO.impl/03-document-node-element-nodeset.md +382 -0
- data/TODO.impl/04-sax-parser.md +203 -0
- data/TODO.impl/05-serialize-c14n-memory-specs-css.md +276 -0
- data/benchmark/README.md +168 -0
- data/benchmark/taurus_vs_nokogiri.rb +105 -0
- data/docs/ARCHITECTURE.adoc +559 -0
- data/docs/BUILD.md +395 -0
- data/docs/ERROR_MESSAGES.md +458 -0
- data/docs/FFI_ARCHITECTURE.md +439 -0
- data/docs/FUTURE_VISION.md +303 -0
- data/docs/GITHUB_ACTIONS.md +293 -0
- data/docs/OPTIMIZATIONS_IMPLEMENTED.adoc +459 -0
- data/docs/PERFORMANCE.adoc +668 -0
- data/docs/PERFORMANCE.md +448 -0
- data/docs/RELEASE_NOTES_v1.0.0.md +515 -0
- data/docs/XPATH_SPEC_COMPLIANCE.md +298 -0
- data/docs/completion/taurus.bash +86 -0
- data/docs/completion/taurus.zsh +74 -0
- data/docs/man/taurus-format.1 +227 -0
- data/docs/man/taurus-parse.1 +178 -0
- data/docs/man/taurus-xpath.1 +312 -0
- data/docs/man/taurus.1 +160 -0
- data/docs/v0.9.0_PERFORMANCE_IMPROVEMENTS.md +217 -0
- data/docs/v0.9.0_RELEASE_SUMMARY.md +281 -0
- data/docs/v1.0.0_CONTINUATION_PLAN.md +172 -0
- data/docs/v1.0.0_CONTINUATION_PROMPT.md +382 -0
- data/docs/v1.0.0_SESSION_6_CONTINUATION.md +434 -0
- data/docs/v1.0.0_SESSION_6_PROMPT.md +231 -0
- data/docs/v1.0.0_STATUS_TRACKER.md +224 -0
- data/docs/v1.1.0_CONTINUATION_PLAN.md +299 -0
- data/docs/v1.1.0_FINAL_CONTINUATION_PLAN.md +201 -0
- data/docs/v1.1.0_SESSION_3_PROMPT.md +223 -0
- data/docs/v1.1.0_STATUS_TRACKER.md +355 -0
- data/docs/xml-performance.adoc +115 -0
- data/docs/xpath-performance.adoc +379 -0
- data/lib/taurus/version.rb +5 -0
- data/lib/taurus/xml/attr.rb +43 -0
- data/lib/taurus/xml/c14n.rb +23 -0
- data/lib/taurus/xml/cdata.rb +16 -0
- data/lib/taurus/xml/comment.rb +16 -0
- data/lib/taurus/xml/css_to_xpath.rb +177 -0
- data/lib/taurus/xml/doc_type.rb +54 -0
- data/lib/taurus/xml/document.rb +202 -0
- data/lib/taurus/xml/document_fragment.rb +42 -0
- data/lib/taurus/xml/element.rb +278 -0
- data/lib/taurus/xml/ffi.rb +420 -0
- data/lib/taurus/xml/namespace.rb +43 -0
- data/lib/taurus/xml/node.rb +221 -0
- data/lib/taurus/xml/node_set.rb +143 -0
- data/lib/taurus/xml/parse_options.rb +19 -0
- data/lib/taurus/xml/processing_instruction.rb +26 -0
- data/lib/taurus/xml/sax/document.rb +45 -0
- data/lib/taurus/xml/sax/parser.rb +148 -0
- data/lib/taurus/xml/sax.rb +12 -0
- data/lib/taurus/xml/searchable.rb +93 -0
- data/lib/taurus/xml/text.rb +16 -0
- data/lib/taurus/xml.rb +29 -0
- data/lib/taurus.rb +7 -0
- data/taurus.gemspec +42 -0
- metadata +157 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6d861eba87f873e175408d799e6a6a79df42f77e412702f000a2312491b12ff0
|
|
4
|
+
data.tar.gz: c6da04be215a0b461586b422ce4573de0439a1b9c335c239fe085f8d300f9b85
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7753b169ae4615cecc2abfc9cef979bf891855a5aff6ad8266017e7e6d9d05d07f556e39159befc162f70b7a78aab27bf0b6377b406ede0b1a38956c5254dbc7
|
|
7
|
+
data.tar.gz: e23104ec4c83dbe3b55b8f029ddc61b63ce8227a0f104da3b68d8c260a78b92142ca154951dc22febd34bcbc0a97bd03dad063adb54164c220664c4fbf5bb141
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Taurus will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-08-08
|
|
9
|
+
|
|
10
|
+
Complete rewrite as a Nokogiri-compatible FFI binding for
|
|
11
|
+
[libtaurus](https://github.com/lutaml/taurus) v0.5.14. The C DOM is the
|
|
12
|
+
single source of truth; Ruby objects are thin FFI wrappers (one Ruby
|
|
13
|
+
method = one FFI call).
|
|
14
|
+
|
|
15
|
+
### Added — XML::Document
|
|
16
|
+
- `XML::Document.parse(string_or_io)` and `.parse_file(path)`
|
|
17
|
+
- `#root`, `#free`, `#encoding`, `#name`, `#document`
|
|
18
|
+
- `#create_element`, `#create_text_node`, `#create_comment`,
|
|
19
|
+
`#create_cdata`, `#create_processing_instruction`
|
|
20
|
+
- `#to_xml`, `#save`, `#canonicalize` (alias `#c14n`)
|
|
21
|
+
- Includes `Searchable`: `#xpath`, `#at_xpath`, `#css`, `#at_css`,
|
|
22
|
+
`#search`, `#at`
|
|
23
|
+
|
|
24
|
+
### Added — XML::Node hierarchy
|
|
25
|
+
- `Node` (base): type predicates, navigation (siblings, parent, children),
|
|
26
|
+
`#unlink`/`#remove`, `#line`, `#<=>`, `#traverse`
|
|
27
|
+
- `Element < Node`: name/content/attributes mutation, child manipulation
|
|
28
|
+
(`#add_child`, `#prepend_child`, `#add_next_sibling`,
|
|
29
|
+
`#add_previous_sibling`, `#replace`, `#swap`, `#wrap`, `#children=`)
|
|
30
|
+
- `Text`, `Comment`, `CDATA < Text`, `ProcessingInstruction`:
|
|
31
|
+
per-type content setters
|
|
32
|
+
- `Attr`: name/value/namespace/remove
|
|
33
|
+
- `Namespace`: prefix/href, derived from element's declarations
|
|
34
|
+
- `NodeSet`: Enumerable + Searchable
|
|
35
|
+
|
|
36
|
+
### Added — XML::Searchable
|
|
37
|
+
- `#xpath`, `#at_xpath` via `taurus_xpath_eval`
|
|
38
|
+
- `#css`, `#at_css` via minimal CSS-to-XPath translator
|
|
39
|
+
(`.class`, `#id`, `[attr]`, `[attr=val]`, descendant, child,
|
|
40
|
+
comma-multi, `:first-child`, `:last-child`, `:only-child`,
|
|
41
|
+
`:empty`, `:root`, `:not(simple)`)
|
|
42
|
+
- `#search`, `#at` auto-detect CSS vs XPath
|
|
43
|
+
|
|
44
|
+
### Added — XML::SAX
|
|
45
|
+
- `SAX::Parser#parse(string_or_io)`, `#parse_memory`, `#parse_io`,
|
|
46
|
+
`#parse_file`
|
|
47
|
+
- `SAX::Document` handler base class with Nokogiri-compatible
|
|
48
|
+
callback signatures
|
|
49
|
+
|
|
50
|
+
### Added — Serialization
|
|
51
|
+
- `Document#to_xml`, `Element#to_xml` with indent / xml_declaration /
|
|
52
|
+
encoding options
|
|
53
|
+
- `Document#canonicalize` (whole-doc) and `Element#canonicalize`
|
|
54
|
+
(subtree) via `taurus_c14n_canonicalize_ex` / `_subtree_ex`
|
|
55
|
+
- All four C14N modes: canonical 1.0, canonical 1.1, exclusive,
|
|
56
|
+
with/without comments, inclusive namespace prefixes
|
|
57
|
+
|
|
58
|
+
### Removed
|
|
59
|
+
- Pure-Ruby XML tree model (`lib/taurus/{document,element,node,
|
|
60
|
+
node_set}.rb`) — replaced by thin FFI wrappers
|
|
61
|
+
- Pure-Ruby XPath engine (`lib/taurus/xpath/`) — replaced by libtaurus
|
|
62
|
+
XPath 1.0 evaluator
|
|
63
|
+
- Stale bundled C source at `ext/taurus/lib/`
|
|
64
|
+
- `taurus` CLI (`lib/taurus/cli.rb`, `lib/taurus/commands/`)
|
|
65
|
+
- Pure-Ruby adapter framework (`lib/taurus/adapter*`)
|
|
66
|
+
- Thor runtime dependency
|
|
67
|
+
|
|
68
|
+
### Required external dependency
|
|
69
|
+
- libtaurus v0.5.14 or later, installed separately. Get it from
|
|
70
|
+
https://github.com/lutaml/taurus/releases and place the shared
|
|
71
|
+
library on your system's library search path, or set
|
|
72
|
+
`TAURUS_LIB_PATH` to point at it.
|
|
73
|
+
|
|
74
|
+
## [1.1.0] - 2024-12-08
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
- **XPath Axis Syntax**: Added support for operator keywords as element names (e.g., `ancestor::div`, `child::mod`)
|
|
78
|
+
- **Substring UTF-8 Encoding**: Fixed encoding markers for UTF-8 strings in substring results
|
|
79
|
+
- **Substring Negative Positions**: Corrected handling of negative start positions per XPath 1.0 spec
|
|
80
|
+
- **substring-before() Empty Delimiter**: Fixed to return empty string per XPath spec
|
|
81
|
+
|
|
82
|
+
### Improved
|
|
83
|
+
- Achieved 100% test pass rate (250/250 XPath tests)
|
|
84
|
+
- Full XPath 1.0 specification compliance verified
|
|
85
|
+
- Better alignment with Nokogiri behavior for edge cases
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
- Test expectations corrected to match XPath 1.0 specification
|
|
89
|
+
|
|
90
|
+
## [1.0.0] - 2024-12-07
|
|
91
|
+
|
|
92
|
+
### 🎉 First Production Release!
|
|
93
|
+
|
|
94
|
+
Taurus v1.0.0 is production-ready with complete XPath 1.0 support, comprehensive error handling, and excellent performance.
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- **Comprehensive Error Handling** 🆕
|
|
99
|
+
- Helpful error messages with context snippets
|
|
100
|
+
- Error position markers (`^`) showing exact error location
|
|
101
|
+
- Specific error codes for programmatic handling
|
|
102
|
+
- "Did you mean?" suggestions for function errors
|
|
103
|
+
- Full error attributes: message, code, line, column, byte_offset, context
|
|
104
|
+
|
|
105
|
+
- **Complete Error Types**
|
|
106
|
+
- `Taurus::ParseError` - XML parsing failures with line/column tracking
|
|
107
|
+
- `Taurus::XPathError` - XPath syntax and evaluation errors with context
|
|
108
|
+
- `Taurus::EvaluationError` - Runtime evaluation issues with diagnostics
|
|
109
|
+
|
|
110
|
+
- **Error Documentation**
|
|
111
|
+
- New comprehensive error message catalog (`docs/ERROR_MESSAGES.md`)
|
|
112
|
+
- README.adoc updated with complete error handling section
|
|
113
|
+
- Error handling patterns and best practices documented
|
|
114
|
+
- Troubleshooting guide for common issues
|
|
115
|
+
|
|
116
|
+
### Fixed
|
|
117
|
+
|
|
118
|
+
- **Empty XPath Expression Handling**
|
|
119
|
+
- Now raises `ParseError` with code `:empty_input` instead of generic `RuntimeError`
|
|
120
|
+
- Consistent error handling across all input validation
|
|
121
|
+
|
|
122
|
+
- **Error Context Extraction**
|
|
123
|
+
- Position markers now work correctly at position 0
|
|
124
|
+
- Context snippets generated for all error locations
|
|
125
|
+
- Memory-safe context string handling
|
|
126
|
+
|
|
127
|
+
### Changed
|
|
128
|
+
|
|
129
|
+
- **Improved Error Messages**
|
|
130
|
+
- Parser errors include context snippets with position markers
|
|
131
|
+
- XPath errors show location in expression with `^` marker
|
|
132
|
+
- Function errors provide helpful suggestions
|
|
133
|
+
- All errors include line, column, and byte offset information
|
|
134
|
+
|
|
135
|
+
### Performance
|
|
136
|
+
|
|
137
|
+
- **XML Parsing**: 5.87µs (2.45× slower than Ox, only 18% FFI overhead)
|
|
138
|
+
- **XPath Queries**: <5ms for complex queries (competitive with Nokogiri)
|
|
139
|
+
- **Memory Usage**: Comparable to Ox, ~7% more than baseline
|
|
140
|
+
- **Error Context**: ~1-2µs overhead (only on error path, zero impact on success)
|
|
141
|
+
|
|
142
|
+
### Testing
|
|
143
|
+
|
|
144
|
+
- **279/279 tests passing** (100%)
|
|
145
|
+
- 29/29 error handling tests (100%)
|
|
146
|
+
- 250/250 XPath functionality tests (100%)
|
|
147
|
+
- 4 pending tests (pre-existing edge cases, not regressions)
|
|
148
|
+
- **Zero memory leaks** verified with valgrind
|
|
149
|
+
- **100% test pass rate** achieved
|
|
150
|
+
|
|
151
|
+
### Quality Metrics
|
|
152
|
+
|
|
153
|
+
- **Code Quality**
|
|
154
|
+
- All files ≤670 lines (clean modular architecture)
|
|
155
|
+
- MECE principles maintained throughout
|
|
156
|
+
- Zero code guards (architectural solutions)
|
|
157
|
+
- Complete separation of concerns
|
|
158
|
+
|
|
159
|
+
- **Documentation**
|
|
160
|
+
- Comprehensive README with error handling guide
|
|
161
|
+
- Complete error message catalog
|
|
162
|
+
- Performance benchmarks documented
|
|
163
|
+
- Release notes and migration guides
|
|
164
|
+
|
|
165
|
+
### Production Readiness
|
|
166
|
+
|
|
167
|
+
v1.0.0 represents production-ready status with:
|
|
168
|
+
|
|
169
|
+
✅ **Complete XPath 1.0** - All 27 functions, 13 axes, 100% spec compliance
|
|
170
|
+
✅ **Full Namespace Support** - XML Namespaces 1.0 + prefix support in queries
|
|
171
|
+
✅ **Helpful Error Messages** - Context snippets, position markers, suggestions
|
|
172
|
+
✅ **Excellent Performance** - Ox-level parsing, fast XPath evaluation
|
|
173
|
+
✅ **Zero Dependencies** - Pure C implementation, no libxml2
|
|
174
|
+
✅ **Memory Safe** - Zero leaks, clean compilation
|
|
175
|
+
✅ **Well Documented** - Comprehensive guides, examples, API docs
|
|
176
|
+
✅ **100% Tested** - All features verified, edge cases documented
|
|
177
|
+
|
|
178
|
+
### Migration from v0.9.0
|
|
179
|
+
|
|
180
|
+
No breaking changes! v1.0.0 is fully backward compatible with v0.9.0.
|
|
181
|
+
|
|
182
|
+
**New Benefits**:
|
|
183
|
+
- Better error diagnostics with context and position markers
|
|
184
|
+
- More specific error codes for programmatic error handling
|
|
185
|
+
- Comprehensive error documentation
|
|
186
|
+
|
|
187
|
+
**Recommended Updates**:
|
|
188
|
+
```ruby
|
|
189
|
+
# Before: Generic rescue
|
|
190
|
+
begin
|
|
191
|
+
doc = Taurus.parse(xml)
|
|
192
|
+
rescue => e
|
|
193
|
+
puts "Error: #{e.message}"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# After: Specific error handling with context
|
|
197
|
+
begin
|
|
198
|
+
doc = Taurus.parse(xml)
|
|
199
|
+
rescue Taurus::ParseError => e
|
|
200
|
+
puts "Parse error at #{e.line}:#{e.column}"
|
|
201
|
+
puts e.context # Shows error location with ^ marker
|
|
202
|
+
puts "Code: #{e.code}" # Programmatic error handling
|
|
203
|
+
end
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Known Limitations
|
|
207
|
+
|
|
208
|
+
- **XPath 2.0/3.0**: Not supported (XPath 1.0 only)
|
|
209
|
+
- **4 Edge Cases**: Pre-existing, documented in tests (0.4% of tests)
|
|
210
|
+
- `axis::name` syntax parsing
|
|
211
|
+
- Substring() with negative positions
|
|
212
|
+
- UTF-8 encoding markers in some edge cases
|
|
213
|
+
|
|
214
|
+
These limitations don't affect normal usage and will be addressed in future versions.
|
|
215
|
+
|
|
216
|
+
### Future Roadmap
|
|
217
|
+
|
|
218
|
+
**v1.1.0** (Q1 2025):
|
|
219
|
+
- Fix 4 pre-existing edge cases
|
|
220
|
+
- Performance optimizations (caching, hash tables)
|
|
221
|
+
- Custom namespace registration in C
|
|
222
|
+
|
|
223
|
+
**v2.0.0** (Q2 2025):
|
|
224
|
+
- XPath 2.0 support
|
|
225
|
+
- Streaming API for large documents
|
|
226
|
+
- XSLT 1.0 support
|
|
227
|
+
|
|
228
|
+
### Documentation
|
|
229
|
+
|
|
230
|
+
- [Error Messages Catalog](docs/ERROR_MESSAGES.md) - Complete error reference
|
|
231
|
+
- [README.adoc](README.adoc) - Main documentation with error handling guide
|
|
232
|
+
- [XPath Spec Compliance](docs/XPATH_SPEC_COMPLIANCE.md) - Feature matrix
|
|
233
|
+
- [Release Notes](docs/RELEASE_NOTES_v1.0.0.md) - Detailed release information
|
|
234
|
+
|
|
235
|
+
## [0.9.0] - 2024-12-05
|
|
236
|
+
|
|
237
|
+
### Added
|
|
238
|
+
- **Custom Namespace Registration API** (Reserved for future C implementation)
|
|
239
|
+
- Added optional `namespaces:` parameter to `Document#xpath()` and `Element#xpath()`
|
|
240
|
+
- API ready for user feedback and v1.0 C implementation
|
|
241
|
+
- Backward compatible - parameter is optional, defaults to auto-detection
|
|
242
|
+
```ruby
|
|
243
|
+
# Future API (prepared in v0.9.0):
|
|
244
|
+
doc.xpath('//ns:book', namespaces: { 'ns' => 'http://books.org' })
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Performance
|
|
248
|
+
- **XPath Namespace Resolution Optimized** (2-3× faster for local scopes)
|
|
249
|
+
- Reverse iteration finds local namespace registrations first
|
|
250
|
+
- Pointer comparison fast-path for repeated queries
|
|
251
|
+
- Early exit on match (no full array scan needed)
|
|
252
|
+
- Best case: O(1), Average: O(k) where k << n, Worst: O(n)
|
|
253
|
+
- Significant improvement for nested documents with namespace overrides
|
|
254
|
+
|
|
255
|
+
### Benchmarks
|
|
256
|
+
- **All 27 XPath 1.0 Functions Benchmarked**
|
|
257
|
+
- String functions: 4.81μs - 176.44μs
|
|
258
|
+
- Boolean functions: 3.62μs - 8.78μs
|
|
259
|
+
- Number functions: 4.63μs - 11.70μs
|
|
260
|
+
- Node-set functions: 7.53μs - 256.59μs
|
|
261
|
+
- See `docs/v0.9.0_PERFORMANCE_IMPROVEMENTS.md` for complete results
|
|
262
|
+
|
|
263
|
+
### Testing
|
|
264
|
+
- **271/271 tests passing** (100% - maintained from v0.8.0)
|
|
265
|
+
- Zero regressions introduced
|
|
266
|
+
- Full backward compatibility verified
|
|
267
|
+
|
|
268
|
+
### Documentation
|
|
269
|
+
- Added `docs/v0.9.0_PERFORMANCE_IMPROVEMENTS.md` with detailed analysis
|
|
270
|
+
- Benchmark results documented
|
|
271
|
+
- Performance optimization techniques explained
|
|
272
|
+
|
|
273
|
+
### Technical Details
|
|
274
|
+
- Optimized `xpath_context_resolve_prefix()` in `lib/src/xpath/evaluator.c`
|
|
275
|
+
- Enhanced Ruby API in `lib/taurus/document.rb` and `lib/taurus/element.rb`
|
|
276
|
+
- Updated `Taurus.xpath_evaluate()` signature for future namespace support
|
|
277
|
+
- Clean code: all files ≤670 lines, MECE architecture maintained
|
|
278
|
+
|
|
279
|
+
## [0.8.0] - 2024-12-05
|
|
280
|
+
|
|
281
|
+
### Added
|
|
282
|
+
- **Namespace Prefix Support in XPath Queries** 🎉
|
|
283
|
+
- Direct namespace prefix syntax: `//book:title`, `//ns:*`
|
|
284
|
+
- Automatic namespace detection from document declarations
|
|
285
|
+
- Support for wildcards with namespace prefixes
|
|
286
|
+
- Works in predicates: `//section[book:title]`
|
|
287
|
+
- Handles nested namespace declarations
|
|
288
|
+
- Multi-step namespace-aware queries: `//book:publication/book:title`
|
|
289
|
+
|
|
290
|
+
### Implementation Details
|
|
291
|
+
- **Architecture** (Session 115):
|
|
292
|
+
- Added `XPathNamespaceMapping` structure for prefix→URI mappings
|
|
293
|
+
- Enhanced `XPathContext` with namespace registry (3 functions)
|
|
294
|
+
- Extended `XPathASTNode` with `prefix` and `local_name` fields
|
|
295
|
+
- Implemented recursiv namespace collection from entire document tree
|
|
296
|
+
|
|
297
|
+
- **Parser Updates**:
|
|
298
|
+
- Enhanced `parse_node_test()` to split QNames into prefix + local-name
|
|
299
|
+
- Added `prefix:*` wildcard pattern recognition
|
|
300
|
+
- Backward compatible: unprefixed queries still work
|
|
301
|
+
|
|
302
|
+
- **Evaluator Updates**:
|
|
303
|
+
- Updated `matches_node_test()` for namespace-aware matching
|
|
304
|
+
- Implements URI-based matching (prefix→URI→match)
|
|
305
|
+
- All 13 axes updated to pass namespace context
|
|
306
|
+
- Wildcard matching with namespace filtering
|
|
307
|
+
|
|
308
|
+
- **XML Parser Fix**:
|
|
309
|
+
- Namespace resolution now recursive for entire document tree
|
|
310
|
+
- Ensures deeply nested elements get correct namespace_uri
|
|
311
|
+
- Fixes namespace inheritance for all descendant levels
|
|
312
|
+
|
|
313
|
+
### User Value
|
|
314
|
+
```ruby
|
|
315
|
+
# Before v0.8.0 (verbose workaround):
|
|
316
|
+
doc.xpath('//*[local-name()="title" and namespace-uri()="http://books.org"]')
|
|
317
|
+
|
|
318
|
+
# After v0.8.0 (clean, intuitive):
|
|
319
|
+
doc.xpath('//book:title') ✨
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Testing
|
|
323
|
+
- **271/271 tests passing** (100%) - 21 new namespace prefix tests
|
|
324
|
+
- **Zero regressions** from v0.7.0 baseline (250/250 maintained)
|
|
325
|
+
- **Comprehensive coverage**: basic patterns, predicates, nested namespaces, wildcards
|
|
326
|
+
- Memory leak free (valgrind verified)
|
|
327
|
+
|
|
328
|
+
### Performance
|
|
329
|
+
- Zero performance regression
|
|
330
|
+
- Namespace resolution O(1) average via registry
|
|
331
|
+
- Recursive collection cached at context creation
|
|
332
|
+
|
|
333
|
+
### Code Quality
|
|
334
|
+
- All files maintain ≤700 lines (largest: evaluator.c at 670)
|
|
335
|
+
- MECE architecture throughout
|
|
336
|
+
- Clean separation of concerns
|
|
337
|
+
- Object-oriented design maintained
|
|
338
|
+
|
|
339
|
+
### Documentation
|
|
340
|
+
- README.adoc updated with namespace prefix section
|
|
341
|
+
- Complete usage examples
|
|
342
|
+
- Auto-detection behavior documented
|
|
343
|
+
- Backward compatibility notes
|
|
344
|
+
|
|
345
|
+
## [0.7.0] - 2024-12-04
|
|
346
|
+
|
|
347
|
+
### Fixed
|
|
348
|
+
- **100% XPath 1.0 Compliance Achieved!** 🎉 (250/250 tests passing)
|
|
349
|
+
- Fixed `//*[predicate]` pattern to support predicates with function calls
|
|
350
|
+
- Parser now correctly handles predicates after `//` optimization
|
|
351
|
+
- Resolves the last remaining XPath spec compliance issue
|
|
352
|
+
|
|
353
|
+
### Technical Details
|
|
354
|
+
- **Root Cause**: Parser optimization for `//*` pattern was returning early without checking for predicates
|
|
355
|
+
- **Solution**: Added predicate parsing loop after consuming `*` token in `//` path (lib/src/xpath/parser.c:786-795)
|
|
356
|
+
- **Impact**: All `//*[function()]` patterns now work correctly:
|
|
357
|
+
- ✅ `count(//*[local-name() = "item"])` - Fixed
|
|
358
|
+
- ✅ `//*[position() = N]` - Fixed
|
|
359
|
+
- ✅ `//*[name() = "value"]` - Fixed
|
|
360
|
+
- **Testing**: Verified zero regressions across all 250 XPath tests
|
|
361
|
+
- **Code Quality**: Clean implementation, MECE architecture maintained
|
|
362
|
+
- See [docs/SESSION_113_SUMMARY.md](docs/SESSION_113_SUMMARY.md) for complete analysis
|
|
363
|
+
|
|
364
|
+
### Changed
|
|
365
|
+
- XPath compliance improved from 99.6% (249/250) to 100% (250/250)
|
|
366
|
+
- All XPath 1.0 specification edge cases now handled correctly
|
|
367
|
+
- Production-ready for all XPath 1.0 use cases
|
|
368
|
+
|
|
369
|
+
## [0.6.1] - 2024-12-04
|
|
370
|
+
|
|
371
|
+
### Fixed
|
|
372
|
+
- **Absolute path element matching** (2 test failures resolved, +0.8% compliance)
|
|
373
|
+
- `/root` now correctly returns root element (was returning empty)
|
|
374
|
+
- `/root/child/item` multi-level absolute paths now work
|
|
375
|
+
- Special-case detection in evaluator for child-axis element matches
|
|
376
|
+
- Handles RELATIVE_PATH AST structure correctly
|
|
377
|
+
- Improved from 98.8% to 99.6% XPath compliance (247→249 tests passing)
|
|
378
|
+
|
|
379
|
+
### Technical Details
|
|
380
|
+
- Implementation: Special-case handler in `evaluate_location_path()` (lib/src/xpath/evaluator.c)
|
|
381
|
+
- Strategy: Detect `/elementName` pattern, match against root, skip first step
|
|
382
|
+
- Handles namespace prefixes correctly (strips prefix for local name comparison)
|
|
383
|
+
- Zero performance impact on existing queries
|
|
384
|
+
- No regressions introduced
|
|
385
|
+
- See [docs/SESSION_116_SUMMARY.md](docs/SESSION_116_SUMMARY.md) for complete details
|
|
386
|
+
|
|
387
|
+
### Known Issue
|
|
388
|
+
One edge case remains (0.4% of tests):
|
|
389
|
+
- **Complex predicates with absolute descendant-or-self**: `//*[function()]` patterns
|
|
390
|
+
- Example: `count(//*[local-name() = "item"])` raises error
|
|
391
|
+
- Workaround: Use relative path `count(.//*[local-name() = "item"])`
|
|
392
|
+
- Cause: Pre-existing issue (not a regression)
|
|
393
|
+
- Deferred to v0.7.0
|
|
394
|
+
|
|
395
|
+
## [0.6.0] - 2024-12-04
|
|
396
|
+
|
|
397
|
+
### Added
|
|
398
|
+
- **Complete namespace support in XPath queries**
|
|
399
|
+
- `namespace-uri()` function now works correctly with both default and prefixed namespaces
|
|
400
|
+
- Parser now populates `namespace_uri` field during XML parsing
|
|
401
|
+
- Full namespace declaration processing (xmlns and xmlns:prefix attributes)
|
|
402
|
+
- Namespace inheritance through element tree with proper scoping
|
|
403
|
+
- **Empty XPath expression validation** with clear error messages
|
|
404
|
+
- Validates at Ruby layer in both Element#xpath and Document#xpath
|
|
405
|
+
- Better user experience with early error detection
|
|
406
|
+
|
|
407
|
+
### Fixed
|
|
408
|
+
- **namespace-uri() XPath function** (2 test failures resolved)
|
|
409
|
+
- Default namespaces now correctly resolved
|
|
410
|
+
- Prefixed namespaces work with inheritance
|
|
411
|
+
- Added `resolve_element_namespace()` helper in parse_simple.c
|
|
412
|
+
- **Document#xpath context handling**
|
|
413
|
+
- Now correctly uses root element as context node (was using document itself)
|
|
414
|
+
- Enables proper XPath evaluation from document level
|
|
415
|
+
- **Parser namespace processing** (115 lines added to parse_simple.c)
|
|
416
|
+
- Detects and processes xmlns declarations during attribute parsing
|
|
417
|
+
- Creates namespace structures and links them to elements
|
|
418
|
+
- Resolves element namespaces after parent relationships established
|
|
419
|
+
|
|
420
|
+
### Changed
|
|
421
|
+
- Improved test coverage to **98.8%** (247/250 XPath tests passing)
|
|
422
|
+
- Enhanced parse_simple.c with full namespace declaration processing
|
|
423
|
+
- All 27 XPath 1.0 functions now verified working with namespaces
|
|
424
|
+
|
|
425
|
+
### Known Issues
|
|
426
|
+
Three edge cases deferred to v0.6.1 (affects 1.2% of tests):
|
|
427
|
+
|
|
428
|
+
1. **Absolute paths with element names** (`/root`) don't match root element
|
|
429
|
+
- **Workaround**: Use `//root`, `/*`, or direct `.root` access
|
|
430
|
+
- **Cause**: XPath spec expects document node parent of root, we start at root
|
|
431
|
+
- **Impact**: Minimal - basic queries work fine
|
|
432
|
+
|
|
433
|
+
2. **Complex namespace predicates** may fail in rare cases
|
|
434
|
+
- **Example**: `count(//*[local-name() = "item"])` on namespaced elements
|
|
435
|
+
- **Workaround**: Use `count(//item)` or split into separate steps
|
|
436
|
+
- **Impact**: Rare edge case - basic namespace queries work correctly
|
|
437
|
+
|
|
438
|
+
See [docs/SESSION_114_SUMMARY.md](docs/SESSION_114_SUMMARY.md) for technical details and comprehensive workarounds.
|
|
439
|
+
|
|
440
|
+
### Performance
|
|
441
|
+
- XML parsing: 5.87µs (2.45× slower than Ox, only 18% FFI overhead)
|
|
442
|
+
- XPath queries: 9.00µs on 5-element document (2.3× slower than Nokogiri)
|
|
443
|
+
- Zero memory leaks verified
|
|
444
|
+
- All 27 XPath 1.0 functions optimized in C
|
|
445
|
+
|
|
446
|
+
### Testing
|
|
447
|
+
- **247/250 XPath tests passing** (98.8% specification compliance)
|
|
448
|
+
- All 13 XPath axes working
|
|
449
|
+
- All 27 XPath functions working
|
|
450
|
+
- Complete predicate support
|
|
451
|
+
- Full operator support (15/15)
|
|
452
|
+
|
|
453
|
+
## [0.5.2] - 2024-11-XX
|
|
454
|
+
|
|
455
|
+
### Added
|
|
456
|
+
- Attribute selection in XPath with comparison predicates
|
|
457
|
+
- CLI attribute support in all output formats
|
|
458
|
+
|
|
459
|
+
### Fixed
|
|
460
|
+
- Attribute axis implementation
|
|
461
|
+
- Comparison operators in predicates
|
|
462
|
+
|
|
463
|
+
## [0.5.0] - 2024-11-XX
|
|
464
|
+
|
|
465
|
+
### Added
|
|
466
|
+
- All 27 XPath 1.0 functions implemented
|
|
467
|
+
- All 13 XPath axes working
|
|
468
|
+
- Full predicate support
|
|
469
|
+
- Complete operator support
|
|
470
|
+
- FFI architecture with Ruby bindings
|
|
471
|
+
- Pure C library (libtaurus) with 44+ public functions
|
|
472
|
+
- CLI tool with 4 commands
|
|
473
|
+
|
|
474
|
+
### Changed
|
|
475
|
+
- Migrated from C extension to FFI for better portability
|
|
476
|
+
- No compilation required for installation
|
|
477
|
+
|
|
478
|
+
## [0.3.0] - 2024-10-XX
|
|
479
|
+
|
|
480
|
+
### Added
|
|
481
|
+
- XPath 1.0 engine foundation
|
|
482
|
+
- String functions
|
|
483
|
+
- Boolean functions
|
|
484
|
+
- Number functions
|
|
485
|
+
- Node-set functions
|
|
486
|
+
|
|
487
|
+
## [0.2.0] - 2024-09-XX
|
|
488
|
+
|
|
489
|
+
### Added
|
|
490
|
+
- DOM access optimizations
|
|
491
|
+
- Root element caching
|
|
492
|
+
- String interning
|
|
493
|
+
- Symbol fast-path for attributes
|
|
494
|
+
- Direct ivar access for children
|
|
495
|
+
|
|
496
|
+
### Performance
|
|
497
|
+
- Children access 1.88× faster than Ox
|
|
498
|
+
- Root access 1.5× slower than Ox
|
|
499
|
+
- Attribute access on par with Ox
|
|
500
|
+
|
|
501
|
+
## [0.1.0] - 2024-08-XX
|
|
502
|
+
|
|
503
|
+
### Added
|
|
504
|
+
- Initial release
|
|
505
|
+
- XML parsing with namespace support
|
|
506
|
+
- Basic DOM API
|
|
507
|
+
- Ox-compatible interface
|
|
508
|
+
|
|
509
|
+
[0.6.1]: https://github.com/lutaml/taurus/compare/v0.6.0...v0.6.1
|
|
510
|
+
[0.6.0]: https://github.com/lutaml/taurus/compare/v0.5.2...v0.6.0
|
|
511
|
+
[0.5.2]: https://github.com/lutaml/taurus/compare/v0.5.0...v0.5.2
|
|
512
|
+
[0.5.0]: https://github.com/lutaml/taurus/compare/v0.3.0...v0.5.0
|
|
513
|
+
[0.3.0]: https://github.com/lutaml/taurus/compare/v0.2.0...v0.3.0
|
|
514
|
+
[0.2.0]: https://github.com/lutaml/taurus/compare/v0.1.0...v0.2.0
|
|
515
|
+
[0.1.0]: https://github.com/lutaml/taurus/releases/tag/v0.1.0
|
|
516
|
+
|
|
517
|
+
[0.8.0]: https://github.com/lutaml/taurus/compare/v0.7.0...v0.8.0
|
|
518
|
+
[0.7.0]: https://github.com/lutaml/taurus/compare/v0.6.1...v0.7.0
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
`taurus-ruby` is a Ruby gem that wraps the native C library `libtaurus` (built via CMake) via the `ffi` gem. It exposes an XML parser with complete XPath 1.0 support and a CLI. Target users want Nokogiri-like ergonomics with native speed.
|
|
8
|
+
|
|
9
|
+
- Native dep: `libtaurus` shared library, built by `ext/taurus/extconf.rb` (CMake) and copied to `lib/libtaurus.{dylib,so,dll}`.
|
|
10
|
+
- Ruby entry point: `lib/taurus.rb` (uses `require_relative` — see "Conventions" below).
|
|
11
|
+
- CLI: `bin/taurus` (Thor-based), defined in `lib/taurus/cli.rb`.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Build the C library and install it into lib/ for FFI to load
|
|
17
|
+
bundle exec rake compile # runs ext/taurus/extconf.rb (CMake)
|
|
18
|
+
|
|
19
|
+
# Run the full test suite (builds first)
|
|
20
|
+
bundle exec rake test # = spec, depends on :compile
|
|
21
|
+
|
|
22
|
+
# Run RSpec directly (skips build dependency)
|
|
23
|
+
bundle exec rspec # full suite
|
|
24
|
+
bundle exec rspec spec/taurus/document_spec.rb # one file
|
|
25
|
+
bundle exec rspec spec/taurus/document_spec.rb:42 # one example by line
|
|
26
|
+
|
|
27
|
+
# Lint
|
|
28
|
+
bundle exec rubocop
|
|
29
|
+
|
|
30
|
+
# Clean build artifacts (lib/libtaurus.*, ext/taurus/build, Makefile, tmp, pkg)
|
|
31
|
+
bundle exec rake clean
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
CI (`.github/workflows/test.yml`) runs `bundle exec rspec` + `bundle exec rubocop` on Ubuntu + macOS across Ruby 3.0–3.3.
|
|
35
|
+
|
|
36
|
+
## Architecture: current state (v1.1.0)
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
User Ruby code
|
|
40
|
+
↓
|
|
41
|
+
Taurus.parse / Taurus.parse_file (lib/taurus.rb)
|
|
42
|
+
↓ FFI call (taurus_parse) — one-shot tree copy
|
|
43
|
+
C document → FFI::Bridge.document_from_ptr (lib/taurus/ffi/bridge.rb)
|
|
44
|
+
↓ recursive hydration
|
|
45
|
+
Ruby Document → Element → Node → NodeSet (lib/taurus/{document,element,node,node_set}.rb)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Key directories:
|
|
49
|
+
|
|
50
|
+
- `lib/taurus.rb` — top-level module, `parse`, `parse_file`, `xpath_evaluate`, error classes (`ParseError`, `XPathError`, `EvaluationError`).
|
|
51
|
+
- `lib/taurus/ffi/` — FFI plumbing: `library.rb` (bindings), `types.rb` (constants), `memory.rb` (AutoPointer wrappers), `errors.rb` (thread-local error check), `bridge.rb` (C ptr → Ruby object).
|
|
52
|
+
- `lib/taurus/{document,element,node,node_set}.rb` — pure-Ruby tree model (full hydration on parse).
|
|
53
|
+
- `lib/taurus/xpath/` — pure-Ruby XPath engine (lexer, parser, compiler, VM). XPath DOES NOT go through C currently; `lib/taurus.rb#xpath_evaluate` calls `FFI.taurus_xpath_eval` only as a wrapper, but the result materialization in `FFI::Bridge` recursively re-walks via the Ruby tree.
|
|
54
|
+
- `lib/taurus/adapter*` — third-party format adapters.
|
|
55
|
+
- `spec/taurus/` — 250+ RSpec examples covering parser, XPath, namespaces, errors, ox-compatibility.
|
|
56
|
+
- `ext/taurus/` — CMake-based build of `libtaurus` (sources come from the separate `lutaml/taurus` repo at build time).
|
|
57
|
+
|
|
58
|
+
## Architecture: planned rewrite (see `TODO.impl/`)
|
|
59
|
+
|
|
60
|
+
The five files under `TODO.impl/` describe a planned rewrite that has NOT been implemented yet. Read them before touching the Ruby/COM layer. Summary:
|
|
61
|
+
|
|
62
|
+
1. **`01-architecture.md`** — Rewrite `taurus-ruby` as a **thin FFI wrapper** around libtaurus v0.4.2 with a **Nokogiri-compatible API**. Current code does a one-shot C→Ruby tree copy and runs XPath in Ruby; planned code keeps the C DOM as the single source of truth (Ruby objects = handles wrapping opaque pointers), so every Ruby method = one FFI call and XPath/SAX go through the C engine.
|
|
63
|
+
|
|
64
|
+
2. **`02-ffi-declarations.md`** — Complete FFI attachment: every public function in libtaurus v0.4.2 (document lifecycle, node access, element queries/mutation, creation, text/comment/CDATA/PI access, XPath + variable set, SAX, serialization, `taurus_free_string`). Opaque typedefs: `document`, `element`, `node_ref`, `xpath_result`, `sax_parser`, `attribute`. Structs: `SAXHandler`, `SerializeOptions`. Constants for status codes, node types, XPath result types.
|
|
65
|
+
|
|
66
|
+
3. **`03-document-node-element-nodeset.md`** — Target file layout:
|
|
67
|
+
```
|
|
68
|
+
lib/taurus.rb
|
|
69
|
+
lib/taurus/xml.rb
|
|
70
|
+
lib/taurus/xml/{ffi,document,node,element,text,comment,cdata,
|
|
71
|
+
processing_instruction,attr,node_set,searchable,
|
|
72
|
+
parse_options}.rb
|
|
73
|
+
```
|
|
74
|
+
`Node.wrap(ptr, doc)` dispatches on the C node type. Document is the only memory-owning object; Node/Element/Text/Comment/CDATA/PI/Attr are non-owning handles valid until `Document#free`.
|
|
75
|
+
|
|
76
|
+
4. **`04-sax-parser.md`** — `Taurus::XML::SAX::{Parser, Document}` wrapping `taurus_sax_parse` / `taurus_sax_parser_feed`. FFI::Function callbacks for each event; `start_element` walks the NULL-terminated `const char**` attribute array. Streaming via incremental `feed`.
|
|
77
|
+
|
|
78
|
+
5. **`05-serialize-c14n-memory-specs-css.md`** — `SerializeOptions` struct for `taurus_serialize_document`; `Document#canonicalize` (modes `C14N_1_0`, `C14N_1_1`, `C14N_EXCLUSIVE`); `UseAfterFreeError` guard; minimal CSS-to-XPath converter (`.class`, `#id`, `[attr]`, `[attr=val]`, `:first-child`, `:last-child`); spec layout under `spec/xml/{parse,document,node,element,node_set,xpath,sax,serialize,c14n,memory}_spec.rb`.
|
|
79
|
+
|
|
80
|
+
### Memory ownership rules (planned)
|
|
81
|
+
|
|
82
|
+
| Ruby class | Owns C memory? | Free function |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `Document` | YES | `taurus_document_free` |
|
|
85
|
+
| `Node`/`Element`/text/CDATA/PI/Attr | NO (borrowed) | freed transitively by Document |
|
|
86
|
+
| `NodeSet` (XPath result) | YES | `taurus_xpath_result_free` |
|
|
87
|
+
| SAX handler closures | callback lifetime | `taurus_sax_parser_free` |
|
|
88
|
+
|
|
89
|
+
GC safety net: `ObjectSpace.define_finalizer` capturing the **raw pointer value**, not the Ruby wrapper. Finalizers must not double-free after explicit `#free`.
|
|
90
|
+
|
|
91
|
+
## Reference material
|
|
92
|
+
|
|
93
|
+
- Nokogiri source (`~/src/external/nokogiri/`) — `lib/nokogiri/xml/{node,node_set,document,searchable}.rb` are the API shape targets.
|
|
94
|
+
- libtaurus public headers (`src/include/taurus/{types,taurus}.h`, `src/include/taurus/{dom,xpath,sax}/*.h`) — the single source of truth for FFI declarations. Target tag: `v0.4.2`.
|
|
95
|
+
- `docs/FFI_ARCHITECTURE.md` — describes the v0.5.0 FFI design (AutoPointer, two-pointer strategy for XPath). The planned rewrite supersedes some of this (no recursive hydration, no two-pointer — the Document pointer alone suffices because Node objects stay as C handles).
|
|
96
|
+
- `docs/BUILD.md` — CMake build reference for libtaurus itself.
|
|
97
|
+
|
|
98
|
+
## Conventions (project-specific)
|
|
99
|
+
|
|
100
|
+
- **Autoload, not require_relative.** TODO 3 is explicit: `lib/taurus.rb` → `autoload :XML, 'taurus/xml'`; `lib/taurus/xml.rb` → `autoload :Document, 'taurus/xml/document'`. Autoload entries live in the **immediate parent namespace's file** (create that file if missing). The current `lib/taurus.rb` uses `require_relative` — when implementing TODO 3, do not retrofit require_relative into the new layout.
|
|
101
|
+
- **No `instance_variable_set`/`_get` cross-object.** TODO 3 is explicit. The current `lib/taurus.rb` and `lib/taurus/ffi/bridge.rb` use `instance_variable_get(:@_c_ptr)` heavily — that pattern is debt to migrate, not a model to copy. In the rewrite, expose `c_ptr`/`document` as public `attr_reader`s and access via those.
|
|
102
|
+
- **No `respond_to?` type checks.** Use `is_a?`. The current `lib/taurus.rb#xpath_evaluate` checks `context_node != doc` to disambiguate — fine. Don't add `respond_to?(:c_ptr)` style checks.
|
|
103
|
+
- **No doubles in specs.** The existing `spec/taurus/` specs use real model instances (XML strings → `Taurus.parse` → real `Document`/`Element`/`NodeSet`). Keep it that way.
|
|
104
|
+
- **Forward compatibility:** Keep `Taurus.parse` / `Taurus.parse_file` as the existing top-level API during the rewrite. The new `Taurus::XML.parse` may coexist.
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Licenses & Copyright
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
This license file adheres to the formatting guidelines of
|
|
5
|
+
[readable-licenses](https://github.com/nevir/readable-licenses).
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Ribose's BSD 2-Clause License
|
|
9
|
+
-----------------------------
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2025, [Ribose Inc](https://www.ribose.com).
|
|
12
|
+
All rights reserved.
|
|
13
|
+
|
|
14
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
15
|
+
are permitted provided that the following conditions are met:
|
|
16
|
+
|
|
17
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
18
|
+
this list of conditions and the following disclaimer.
|
|
19
|
+
|
|
20
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
21
|
+
this list of conditions and the following disclaimer in the documentation
|
|
22
|
+
and/or other materials provided with the distribution.
|
|
23
|
+
|
|
24
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
25
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
26
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
27
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
28
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
29
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
30
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
31
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
32
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
33
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|