archive_r_ruby 0.1.21 → 0.1.22

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -21
  3. data/NOTICE +116 -116
  4. data/README.md +106 -106
  5. data/VERSION +1 -1
  6. data/ext/archive_r/archive_r_ext.cc +1098 -1098
  7. data/ext/archive_r/extconf.rb +125 -125
  8. data/ext/archive_r/vendor/archive_r/LICENSE +21 -21
  9. data/ext/archive_r/vendor/archive_r/NOTICE +116 -116
  10. data/ext/archive_r/vendor/archive_r/include/archive_r/data_stream.h +42 -42
  11. data/ext/archive_r/vendor/archive_r/include/archive_r/entry.h +180 -180
  12. data/ext/archive_r/vendor/archive_r/include/archive_r/entry_fault.h +34 -34
  13. data/ext/archive_r/vendor/archive_r/include/archive_r/entry_metadata.h +56 -56
  14. data/ext/archive_r/vendor/archive_r/include/archive_r/multi_volume_stream_base.h +46 -46
  15. data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy.h +92 -92
  16. data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy_utils.h +36 -36
  17. data/ext/archive_r/vendor/archive_r/include/archive_r/platform_compat.h +34 -34
  18. data/ext/archive_r/vendor/archive_r/include/archive_r/traverser.h +156 -156
  19. data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.cc +300 -300
  20. data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.h +110 -110
  21. data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.cc +161 -161
  22. data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.h +53 -53
  23. data/ext/archive_r/vendor/archive_r/src/archive_type.cc +545 -545
  24. data/ext/archive_r/vendor/archive_r/src/archive_type.h +77 -77
  25. data/ext/archive_r/vendor/archive_r/src/data_stream.cc +35 -35
  26. data/ext/archive_r/vendor/archive_r/src/entry.cc +238 -238
  27. data/ext/archive_r/vendor/archive_r/src/entry_fault.cc +26 -26
  28. data/ext/archive_r/vendor/archive_r/src/entry_fault_error.cc +54 -54
  29. data/ext/archive_r/vendor/archive_r/src/entry_fault_error.h +32 -32
  30. data/ext/archive_r/vendor/archive_r/src/entry_impl.h +56 -56
  31. data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.cc +76 -76
  32. data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.h +39 -39
  33. data/ext/archive_r/vendor/archive_r/src/multi_volume_stream_base.cc +208 -208
  34. data/ext/archive_r/vendor/archive_r/src/path_hierarchy.cc +127 -127
  35. data/ext/archive_r/vendor/archive_r/src/path_hierarchy_utils.cc +251 -251
  36. data/ext/archive_r/vendor/archive_r/src/simple_profiler.h +109 -109
  37. data/ext/archive_r/vendor/archive_r/src/system_file_stream.cc +294 -294
  38. data/ext/archive_r/vendor/archive_r/src/system_file_stream.h +46 -46
  39. data/ext/archive_r/vendor/archive_r/src/traverser.cc +295 -295
  40. data/lib/archive_r.rb +120 -120
  41. metadata +3 -6
@@ -1,295 +1,295 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #include "archive_r/traverser.h"
5
- #include "archive_r/entry.h"
6
- #include "archive_r/entry_fault.h"
7
- #include "archive_r/path_hierarchy.h"
8
- #include "archive_r/path_hierarchy_utils.h"
9
- #include "archive_stack_orchestrator.h"
10
- #include "archive_type.h"
11
- #include "entry_fault_error.h"
12
- #include "system_file_stream.h"
13
- #include <filesystem>
14
- #include <memory>
15
- #include <stdexcept>
16
- #include <sys/stat.h>
17
- #include <system_error>
18
- #include <unordered_set>
19
- #include <utility>
20
- #include <vector>
21
-
22
- namespace archive_r {
23
-
24
- // ============================================================================
25
- // Traverser Implementation
26
- // ============================================================================
27
-
28
- namespace {
29
-
30
- archive_r::ArchiveOption to_archive_option(const TraverserOptions &options) {
31
- archive_r::ArchiveOption converted;
32
- converted.passphrases = options.passphrases;
33
- converted.formats = options.formats;
34
- converted.metadata_keys.insert(options.metadata_keys.begin(), options.metadata_keys.end());
35
- return converted;
36
- }
37
-
38
- } // namespace
39
-
40
- Traverser::Traverser(std::vector<PathHierarchy> paths, TraverserOptions options)
41
- : _initial_paths(std::move(paths))
42
- , _options(std::move(options)) {
43
- if (_initial_paths.empty()) {
44
- throw std::invalid_argument("paths cannot be empty");
45
- }
46
- for (const auto &hierarchy : _initial_paths) {
47
- if (hierarchy.empty()) {
48
- throw std::invalid_argument("path hierarchy cannot be empty");
49
- }
50
- }
51
- }
52
-
53
- Traverser::Traverser(PathHierarchy path, TraverserOptions options)
54
- : Traverser(std::vector<PathHierarchy>{ std::move(path) }, std::move(options)) {}
55
-
56
- Traverser::Traverser(const std::string &path, TraverserOptions options)
57
- : Traverser(std::vector<PathHierarchy>{ make_single_path(path) }, std::move(options)) {}
58
-
59
- Traverser::~Traverser() = default;
60
-
61
- // ============================================================================
62
- // Iterator Implementation
63
- // ============================================================================
64
-
65
- class Traverser::Iterator::Impl {
66
- public:
67
- Impl(std::vector<PathHierarchy> paths, bool at_end, const TraverserOptions &traverser_options)
68
- : _paths(std::move(paths))
69
- , _at_end(at_end)
70
- , _archive_options(to_archive_option(traverser_options))
71
- , _default_descent(traverser_options.descend_archives) {
72
- if (_at_end) {
73
- return;
74
- }
75
- ensure_shared_orchestrator();
76
-
77
- _at_end = !advance_to_next_root();
78
- }
79
-
80
- Entry &get_entry() {
81
- if (!_current_entry) {
82
- throw std::logic_error("Cannot dereference end iterator");
83
- }
84
- return *_current_entry;
85
- }
86
-
87
- void advance() {
88
- if (_at_end) {
89
- return;
90
- }
91
-
92
- bool request_descend_into_archive = _current_entry && _current_entry->descent_enabled() && !_current_entry->is_directory();
93
-
94
- if (_current_entry->depth() == 0 && request_descend_into_archive && !_current_entry->is_directory()) {
95
- request_descend_into_archive = false;
96
- attempt_descend_into_root(_current_entry->path_hierarchy());
97
- }
98
- _current_entry.reset();
99
-
100
- if (fetch_from_archive(request_descend_into_archive)) {
101
- return;
102
- }
103
-
104
- if (fetch_from_directory()) {
105
- return;
106
- }
107
-
108
- if (advance_to_next_root()) {
109
- return;
110
- }
111
-
112
- descend_pending_multi_volumes();
113
-
114
- if (fetch_from_archive(false)) {
115
- return;
116
- }
117
-
118
- _at_end = true;
119
- }
120
-
121
- bool equals(const Impl *other) const {
122
- if (this == other) {
123
- return true;
124
- }
125
- return other && _at_end && other->_at_end;
126
- }
127
-
128
- private:
129
- std::shared_ptr<ArchiveStackOrchestrator> ensure_shared_orchestrator() {
130
- if (!_shared_orchestrator) {
131
- _shared_orchestrator = std::make_shared<ArchiveStackOrchestrator>(_archive_options);
132
- }
133
- return _shared_orchestrator;
134
- }
135
-
136
- std::string normalize_path_string(const std::string &value) {
137
- std::filesystem::path path_value(value);
138
- return path_value.lexically_normal().string();
139
- }
140
-
141
- bool fetch_from_directory() {
142
- if (_directory_iterator == _directory_end) {
143
- return false;
144
- }
145
- const std::filesystem::directory_entry entry = *_directory_iterator;
146
- set_current_entry(make_single_path(normalize_path_string(entry.path().string())));
147
- if (_current_entry->is_directory() && !_current_entry->descent_enabled()) {
148
- _directory_iterator.disable_recursion_pending();
149
- }
150
- ++_directory_iterator;
151
- return true;
152
- }
153
-
154
- bool fetch_from_archive(bool request_descend_into_archive) {
155
- if (!archive_active()) {
156
- return false;
157
- }
158
- ArchiveStackOrchestrator &orchestrator = *ensure_shared_orchestrator();
159
-
160
- if (orchestrator.advance(request_descend_into_archive)) {
161
- set_current_entry(orchestrator.current_entry_hierarchy());
162
- return true;
163
- }
164
- return false;
165
- }
166
-
167
- bool advance_to_next_root() {
168
- if (_current_path_index >= _paths.size()) {
169
- return false;
170
- }
171
- const PathHierarchy &hierarchy = _paths[_current_path_index];
172
- reset_source_state();
173
- set_current_entry(hierarchy);
174
- if (hierarchy.size() == 1 && hierarchy.front().is_single()) {
175
- const std::filesystem::path fs_path(hierarchy.front().single_value());
176
- std::error_code ec;
177
- const bool path_is_directory = std::filesystem::is_directory(fs_path, ec) && !ec;
178
- if (path_is_directory) {
179
- _directory_iterator = std::filesystem::recursive_directory_iterator(fs_path, std::filesystem::directory_options::skip_permission_denied);
180
- _directory_end = std::filesystem::recursive_directory_iterator();
181
- }
182
- }
183
- ++_current_path_index;
184
- return true;
185
- }
186
-
187
- bool descend_pending_multi_volumes() {
188
- auto orchestrator = ensure_shared_orchestrator();
189
- try {
190
- if (orchestrator->descend_pending_multi_volumes()) {
191
- return true;
192
- }
193
- } catch (const EntryFaultError &error) {
194
- EntryFault fault = enrich_orchestrator_error(error, *orchestrator);
195
- handle_orchestrator_error(fault);
196
- }
197
- return false;
198
- }
199
-
200
- void attempt_descend_into_root(const PathHierarchy &hierarchy) {
201
- auto shared_orchestrator = ensure_shared_orchestrator();
202
- try {
203
- shared_orchestrator->open_root_hierarchy(hierarchy);
204
- } catch (const EntryFaultError &error) {
205
- EntryFault fault = enrich_orchestrator_error(error, *shared_orchestrator);
206
- handle_orchestrator_error(fault);
207
- }
208
- }
209
-
210
- void set_current_entry(PathHierarchy hierarchy) { _current_entry = Entry::create(std::move(hierarchy), ensure_shared_orchestrator(), _default_descent); }
211
-
212
- void handle_orchestrator_error(const EntryFault &fault) { dispatch_registered_fault(fault); }
213
-
214
- void reset_source_state() {
215
- reset_directory_traversal();
216
- _current_entry.reset();
217
- }
218
-
219
- bool archive_active() const { return _shared_orchestrator && _shared_orchestrator->depth() > 0; }
220
-
221
- bool directory_traversal_active() const { return _directory_iterator != _directory_end; }
222
-
223
- void reset_directory_traversal() {
224
- _directory_iterator = std::filesystem::recursive_directory_iterator();
225
- _directory_end = std::filesystem::recursive_directory_iterator();
226
- }
227
-
228
- EntryFault enrich_orchestrator_error(const EntryFaultError &error, ArchiveStackOrchestrator &orchestrator) {
229
- EntryFault fault = error.fault();
230
- if (fault.hierarchy.empty()) {
231
- fault.hierarchy = orchestrator.current_entry_hierarchy();
232
- }
233
- return fault;
234
- }
235
-
236
- std::vector<PathHierarchy> _paths;
237
- size_t _current_path_index = 0;
238
- std::filesystem::recursive_directory_iterator _directory_iterator;
239
- std::filesystem::recursive_directory_iterator _directory_end;
240
- bool _at_end = false;
241
- std::unique_ptr<Entry> _current_entry;
242
-
243
- ArchiveOption _archive_options;
244
- std::shared_ptr<ArchiveStackOrchestrator> _shared_orchestrator;
245
- bool _default_descent = true;
246
- };
247
- // ============================================================================
248
- // Iterator public interface
249
- // ============================================================================
250
-
251
- Traverser::Iterator::Iterator(std::unique_ptr<Impl> impl)
252
- : _impl(std::move(impl)) {}
253
-
254
- Traverser::Iterator::~Iterator() = default;
255
-
256
- Traverser::Iterator::Iterator(Iterator &&other) noexcept
257
- : _impl(std::move(other._impl)) {}
258
-
259
- Traverser::Iterator &Traverser::Iterator::operator=(Iterator &&other) noexcept {
260
- _impl = std::move(other._impl);
261
- return *this;
262
- }
263
-
264
- Traverser::Iterator::reference Traverser::Iterator::operator*() { return _impl->get_entry(); }
265
-
266
- Traverser::Iterator::pointer Traverser::Iterator::operator->() { return &_impl->get_entry(); }
267
-
268
- Traverser::Iterator &Traverser::Iterator::operator++() {
269
- if (_impl) {
270
- _impl->advance();
271
- }
272
- return *this;
273
- }
274
-
275
- bool Traverser::Iterator::operator==(const Iterator &other) const {
276
- if (!_impl && !other._impl) {
277
- return true;
278
- }
279
- if (!_impl || !other._impl) {
280
- return false;
281
- }
282
- return _impl->equals(other._impl.get());
283
- }
284
-
285
- bool Traverser::Iterator::operator!=(const Iterator &other) const { return !(*this == other); }
286
-
287
- // ============================================================================
288
- // Traverser public interface
289
- // ============================================================================
290
-
291
- Traverser::Iterator Traverser::begin() { return Iterator(std::make_unique<Iterator::Impl>(_initial_paths, false, _options)); }
292
-
293
- Traverser::Iterator Traverser::end() { return Iterator(std::make_unique<Iterator::Impl>(_initial_paths, true, _options)); }
294
-
295
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #include "archive_r/traverser.h"
5
+ #include "archive_r/entry.h"
6
+ #include "archive_r/entry_fault.h"
7
+ #include "archive_r/path_hierarchy.h"
8
+ #include "archive_r/path_hierarchy_utils.h"
9
+ #include "archive_stack_orchestrator.h"
10
+ #include "archive_type.h"
11
+ #include "entry_fault_error.h"
12
+ #include "system_file_stream.h"
13
+ #include <filesystem>
14
+ #include <memory>
15
+ #include <stdexcept>
16
+ #include <sys/stat.h>
17
+ #include <system_error>
18
+ #include <unordered_set>
19
+ #include <utility>
20
+ #include <vector>
21
+
22
+ namespace archive_r {
23
+
24
+ // ============================================================================
25
+ // Traverser Implementation
26
+ // ============================================================================
27
+
28
+ namespace {
29
+
30
+ archive_r::ArchiveOption to_archive_option(const TraverserOptions &options) {
31
+ archive_r::ArchiveOption converted;
32
+ converted.passphrases = options.passphrases;
33
+ converted.formats = options.formats;
34
+ converted.metadata_keys.insert(options.metadata_keys.begin(), options.metadata_keys.end());
35
+ return converted;
36
+ }
37
+
38
+ } // namespace
39
+
40
+ Traverser::Traverser(std::vector<PathHierarchy> paths, TraverserOptions options)
41
+ : _initial_paths(std::move(paths))
42
+ , _options(std::move(options)) {
43
+ if (_initial_paths.empty()) {
44
+ throw std::invalid_argument("paths cannot be empty");
45
+ }
46
+ for (const auto &hierarchy : _initial_paths) {
47
+ if (hierarchy.empty()) {
48
+ throw std::invalid_argument("path hierarchy cannot be empty");
49
+ }
50
+ }
51
+ }
52
+
53
+ Traverser::Traverser(PathHierarchy path, TraverserOptions options)
54
+ : Traverser(std::vector<PathHierarchy>{ std::move(path) }, std::move(options)) {}
55
+
56
+ Traverser::Traverser(const std::string &path, TraverserOptions options)
57
+ : Traverser(std::vector<PathHierarchy>{ make_single_path(path) }, std::move(options)) {}
58
+
59
+ Traverser::~Traverser() = default;
60
+
61
+ // ============================================================================
62
+ // Iterator Implementation
63
+ // ============================================================================
64
+
65
+ class Traverser::Iterator::Impl {
66
+ public:
67
+ Impl(std::vector<PathHierarchy> paths, bool at_end, const TraverserOptions &traverser_options)
68
+ : _paths(std::move(paths))
69
+ , _at_end(at_end)
70
+ , _archive_options(to_archive_option(traverser_options))
71
+ , _default_descent(traverser_options.descend_archives) {
72
+ if (_at_end) {
73
+ return;
74
+ }
75
+ ensure_shared_orchestrator();
76
+
77
+ _at_end = !advance_to_next_root();
78
+ }
79
+
80
+ Entry &get_entry() {
81
+ if (!_current_entry) {
82
+ throw std::logic_error("Cannot dereference end iterator");
83
+ }
84
+ return *_current_entry;
85
+ }
86
+
87
+ void advance() {
88
+ if (_at_end) {
89
+ return;
90
+ }
91
+
92
+ bool request_descend_into_archive = _current_entry && _current_entry->descent_enabled() && !_current_entry->is_directory();
93
+
94
+ if (_current_entry->depth() == 0 && request_descend_into_archive && !_current_entry->is_directory()) {
95
+ request_descend_into_archive = false;
96
+ attempt_descend_into_root(_current_entry->path_hierarchy());
97
+ }
98
+ _current_entry.reset();
99
+
100
+ if (fetch_from_archive(request_descend_into_archive)) {
101
+ return;
102
+ }
103
+
104
+ if (fetch_from_directory()) {
105
+ return;
106
+ }
107
+
108
+ if (advance_to_next_root()) {
109
+ return;
110
+ }
111
+
112
+ descend_pending_multi_volumes();
113
+
114
+ if (fetch_from_archive(false)) {
115
+ return;
116
+ }
117
+
118
+ _at_end = true;
119
+ }
120
+
121
+ bool equals(const Impl *other) const {
122
+ if (this == other) {
123
+ return true;
124
+ }
125
+ return other && _at_end && other->_at_end;
126
+ }
127
+
128
+ private:
129
+ std::shared_ptr<ArchiveStackOrchestrator> ensure_shared_orchestrator() {
130
+ if (!_shared_orchestrator) {
131
+ _shared_orchestrator = std::make_shared<ArchiveStackOrchestrator>(_archive_options);
132
+ }
133
+ return _shared_orchestrator;
134
+ }
135
+
136
+ std::string normalize_path_string(const std::string &value) {
137
+ std::filesystem::path path_value(value);
138
+ return path_value.lexically_normal().string();
139
+ }
140
+
141
+ bool fetch_from_directory() {
142
+ if (_directory_iterator == _directory_end) {
143
+ return false;
144
+ }
145
+ const std::filesystem::directory_entry entry = *_directory_iterator;
146
+ set_current_entry(make_single_path(normalize_path_string(entry.path().string())));
147
+ if (_current_entry->is_directory() && !_current_entry->descent_enabled()) {
148
+ _directory_iterator.disable_recursion_pending();
149
+ }
150
+ ++_directory_iterator;
151
+ return true;
152
+ }
153
+
154
+ bool fetch_from_archive(bool request_descend_into_archive) {
155
+ if (!archive_active()) {
156
+ return false;
157
+ }
158
+ ArchiveStackOrchestrator &orchestrator = *ensure_shared_orchestrator();
159
+
160
+ if (orchestrator.advance(request_descend_into_archive)) {
161
+ set_current_entry(orchestrator.current_entry_hierarchy());
162
+ return true;
163
+ }
164
+ return false;
165
+ }
166
+
167
+ bool advance_to_next_root() {
168
+ if (_current_path_index >= _paths.size()) {
169
+ return false;
170
+ }
171
+ const PathHierarchy &hierarchy = _paths[_current_path_index];
172
+ reset_source_state();
173
+ set_current_entry(hierarchy);
174
+ if (hierarchy.size() == 1 && hierarchy.front().is_single()) {
175
+ const std::filesystem::path fs_path(hierarchy.front().single_value());
176
+ std::error_code ec;
177
+ const bool path_is_directory = std::filesystem::is_directory(fs_path, ec) && !ec;
178
+ if (path_is_directory) {
179
+ _directory_iterator = std::filesystem::recursive_directory_iterator(fs_path, std::filesystem::directory_options::skip_permission_denied);
180
+ _directory_end = std::filesystem::recursive_directory_iterator();
181
+ }
182
+ }
183
+ ++_current_path_index;
184
+ return true;
185
+ }
186
+
187
+ bool descend_pending_multi_volumes() {
188
+ auto orchestrator = ensure_shared_orchestrator();
189
+ try {
190
+ if (orchestrator->descend_pending_multi_volumes()) {
191
+ return true;
192
+ }
193
+ } catch (const EntryFaultError &error) {
194
+ EntryFault fault = enrich_orchestrator_error(error, *orchestrator);
195
+ handle_orchestrator_error(fault);
196
+ }
197
+ return false;
198
+ }
199
+
200
+ void attempt_descend_into_root(const PathHierarchy &hierarchy) {
201
+ auto shared_orchestrator = ensure_shared_orchestrator();
202
+ try {
203
+ shared_orchestrator->open_root_hierarchy(hierarchy);
204
+ } catch (const EntryFaultError &error) {
205
+ EntryFault fault = enrich_orchestrator_error(error, *shared_orchestrator);
206
+ handle_orchestrator_error(fault);
207
+ }
208
+ }
209
+
210
+ void set_current_entry(PathHierarchy hierarchy) { _current_entry = Entry::create(std::move(hierarchy), ensure_shared_orchestrator(), _default_descent); }
211
+
212
+ void handle_orchestrator_error(const EntryFault &fault) { dispatch_registered_fault(fault); }
213
+
214
+ void reset_source_state() {
215
+ reset_directory_traversal();
216
+ _current_entry.reset();
217
+ }
218
+
219
+ bool archive_active() const { return _shared_orchestrator && _shared_orchestrator->depth() > 0; }
220
+
221
+ bool directory_traversal_active() const { return _directory_iterator != _directory_end; }
222
+
223
+ void reset_directory_traversal() {
224
+ _directory_iterator = std::filesystem::recursive_directory_iterator();
225
+ _directory_end = std::filesystem::recursive_directory_iterator();
226
+ }
227
+
228
+ EntryFault enrich_orchestrator_error(const EntryFaultError &error, ArchiveStackOrchestrator &orchestrator) {
229
+ EntryFault fault = error.fault();
230
+ if (fault.hierarchy.empty()) {
231
+ fault.hierarchy = orchestrator.current_entry_hierarchy();
232
+ }
233
+ return fault;
234
+ }
235
+
236
+ std::vector<PathHierarchy> _paths;
237
+ size_t _current_path_index = 0;
238
+ std::filesystem::recursive_directory_iterator _directory_iterator;
239
+ std::filesystem::recursive_directory_iterator _directory_end;
240
+ bool _at_end = false;
241
+ std::unique_ptr<Entry> _current_entry;
242
+
243
+ ArchiveOption _archive_options;
244
+ std::shared_ptr<ArchiveStackOrchestrator> _shared_orchestrator;
245
+ bool _default_descent = true;
246
+ };
247
+ // ============================================================================
248
+ // Iterator public interface
249
+ // ============================================================================
250
+
251
+ Traverser::Iterator::Iterator(std::unique_ptr<Impl> impl)
252
+ : _impl(std::move(impl)) {}
253
+
254
+ Traverser::Iterator::~Iterator() = default;
255
+
256
+ Traverser::Iterator::Iterator(Iterator &&other) noexcept
257
+ : _impl(std::move(other._impl)) {}
258
+
259
+ Traverser::Iterator &Traverser::Iterator::operator=(Iterator &&other) noexcept {
260
+ _impl = std::move(other._impl);
261
+ return *this;
262
+ }
263
+
264
+ Traverser::Iterator::reference Traverser::Iterator::operator*() { return _impl->get_entry(); }
265
+
266
+ Traverser::Iterator::pointer Traverser::Iterator::operator->() { return &_impl->get_entry(); }
267
+
268
+ Traverser::Iterator &Traverser::Iterator::operator++() {
269
+ if (_impl) {
270
+ _impl->advance();
271
+ }
272
+ return *this;
273
+ }
274
+
275
+ bool Traverser::Iterator::operator==(const Iterator &other) const {
276
+ if (!_impl && !other._impl) {
277
+ return true;
278
+ }
279
+ if (!_impl || !other._impl) {
280
+ return false;
281
+ }
282
+ return _impl->equals(other._impl.get());
283
+ }
284
+
285
+ bool Traverser::Iterator::operator!=(const Iterator &other) const { return !(*this == other); }
286
+
287
+ // ============================================================================
288
+ // Traverser public interface
289
+ // ============================================================================
290
+
291
+ Traverser::Iterator Traverser::begin() { return Iterator(std::make_unique<Iterator::Impl>(_initial_paths, false, _options)); }
292
+
293
+ Traverser::Iterator Traverser::end() { return Iterator(std::make_unique<Iterator::Impl>(_initial_paths, true, _options)); }
294
+
295
+ } // namespace archive_r