archive_r_ruby 0.1.3 → 0.1.4

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE → LICENSE.txt} +77 -77
  3. data/README.md +103 -103
  4. data/ext/archive_r/Makefile +48 -45
  5. data/ext/archive_r/archive_r-x64-mingw-ucrt.def +2 -0
  6. data/ext/archive_r/archive_r_ext.cc +1106 -1106
  7. data/ext/archive_r/archive_r_ext.o +0 -0
  8. data/ext/archive_r/extconf.rb +120 -120
  9. data/ext/archive_r/mkmf.log +23 -18
  10. data/ext/archive_r/vendor/archive_r/LICENSE.txt +77 -77
  11. data/ext/archive_r/vendor/archive_r/include/archive_r/data_stream.h +52 -52
  12. data/ext/archive_r/vendor/archive_r/include/archive_r/entry.h +166 -166
  13. data/ext/archive_r/vendor/archive_r/include/archive_r/entry_fault.h +34 -34
  14. data/ext/archive_r/vendor/archive_r/include/archive_r/entry_metadata.h +56 -56
  15. data/ext/archive_r/vendor/archive_r/include/archive_r/multi_volume_stream_base.h +46 -46
  16. data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy.h +109 -109
  17. data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy_utils.h +37 -37
  18. data/ext/archive_r/vendor/archive_r/include/archive_r/platform_compat.h +19 -19
  19. data/ext/archive_r/vendor/archive_r/include/archive_r/traverser.h +122 -122
  20. data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.cc +330 -330
  21. data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.h +97 -97
  22. data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.cc +162 -162
  23. data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.h +54 -54
  24. data/ext/archive_r/vendor/archive_r/src/archive_type.cc +552 -552
  25. data/ext/archive_r/vendor/archive_r/src/archive_type.h +77 -77
  26. data/ext/archive_r/vendor/archive_r/src/data_stream.cc +35 -35
  27. data/ext/archive_r/vendor/archive_r/src/entry.cc +253 -253
  28. data/ext/archive_r/vendor/archive_r/src/entry_fault.cc +26 -26
  29. data/ext/archive_r/vendor/archive_r/src/entry_fault_error.cc +54 -54
  30. data/ext/archive_r/vendor/archive_r/src/entry_fault_error.h +32 -32
  31. data/ext/archive_r/vendor/archive_r/src/entry_impl.h +57 -57
  32. data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.cc +81 -81
  33. data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.h +41 -41
  34. data/ext/archive_r/vendor/archive_r/src/multi_volume_stream_base.cc +199 -199
  35. data/ext/archive_r/vendor/archive_r/src/path_hierarchy.cc +151 -151
  36. data/ext/archive_r/vendor/archive_r/src/path_hierarchy_utils.cc +304 -304
  37. data/ext/archive_r/vendor/archive_r/src/simple_profiler.h +120 -120
  38. data/ext/archive_r/vendor/archive_r/src/system_file_stream.cc +295 -295
  39. data/ext/archive_r/vendor/archive_r/src/system_file_stream.h +46 -46
  40. data/ext/archive_r/vendor/archive_r/src/traverser.cc +314 -314
  41. data/lib/archive_r.rb +105 -105
  42. metadata +11 -8
  43. data/ext/archive_r/archive_r.bundle +0 -0
@@ -1,109 +1,109 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #pragma once
5
-
6
- #include <cstddef>
7
- #include <stdexcept>
8
- #include <string>
9
- #include <utility>
10
- #include <variant>
11
- #include <vector>
12
-
13
- namespace archive_r {
14
-
15
- /**
16
- * @brief Represents a single component within a logical path hierarchy.
17
- *
18
- * A component can be one of three shapes:
19
- * - single string value (most common)
20
- * - multi-volume part list (split archives that share a common base name)
21
- * - nested list of child entries (used for synthetic grouping)
22
- */
23
- class PathEntry {
24
- public:
25
- struct Parts {
26
- std::vector<std::string> values;
27
- enum class Ordering { Natural, Given } ordering = Ordering::Natural;
28
- };
29
-
30
- using NodeList = std::vector<PathEntry>;
31
-
32
- PathEntry() = default;
33
-
34
- explicit PathEntry(std::string value)
35
- : _value(std::move(value)) {}
36
-
37
- explicit PathEntry(Parts parts)
38
- : _value(std::move(parts)) {}
39
-
40
- explicit PathEntry(NodeList nodes)
41
- : _value(std::move(nodes)) {}
42
-
43
- static PathEntry single(std::string entry) { return PathEntry(std::move(entry)); }
44
-
45
- static PathEntry multi_volume(std::vector<std::string> entries, Parts::Ordering ordering = Parts::Ordering::Natural) {
46
- Parts parts{ std::move(entries), ordering };
47
- if (parts.values.empty()) {
48
- throw std::invalid_argument("multi-volume parts cannot be empty");
49
- }
50
- return PathEntry(std::move(parts));
51
- }
52
-
53
- static PathEntry nested(NodeList hierarchies) {
54
- if (hierarchies.empty()) {
55
- throw std::invalid_argument("nested hierarchies cannot be empty");
56
- }
57
- return PathEntry(std::move(hierarchies));
58
- }
59
-
60
- bool is_single() const { return std::holds_alternative<std::string>(_value); }
61
- bool is_multi_volume() const { return std::holds_alternative<Parts>(_value); }
62
- bool is_nested() const { return std::holds_alternative<NodeList>(_value); }
63
- const std::string &single_value() const { return std::get<std::string>(_value); }
64
- const Parts &multi_volume_parts() const { return std::get<Parts>(_value); }
65
- Parts &multi_volume_parts_mut() { return std::get<Parts>(_value); }
66
- const NodeList &nested_nodes() const { return std::get<NodeList>(_value); }
67
- NodeList &nested_nodes_mut() { return std::get<NodeList>(_value); }
68
-
69
- private:
70
- std::variant<std::string, Parts, NodeList> _value;
71
- };
72
-
73
- using PathHierarchy = std::vector<PathEntry>;
74
-
75
- /**
76
- * Compare two entries using the ordering enforced throughout archive_r.
77
- *
78
- * Ordering rules:
79
- * 1. Entry categories are ordered single < multi-volume < nested node-list.
80
- * 2. Single entries compare by string value.
81
- * 3. Multi-volume entries first compare their ordering flag (Natural < Given),
82
- * then compare corresponding part names lexicographically, finally by list length.
83
- * 4. Nested node-lists compare child entries pairwise using the same rules.
84
- */
85
- int compare_entries(const PathEntry &lhs, const PathEntry &rhs);
86
-
87
- /** Compare complete hierarchies lexicographically using compare_entries on each level. */
88
- int compare_hierarchies(const PathHierarchy &lhs, const PathHierarchy &rhs);
89
-
90
- /** Shorthand equality helpers for entries and hierarchies. */
91
- bool entries_equal(const PathEntry &lhs, const PathEntry &rhs);
92
- bool hierarchies_equal(const PathHierarchy &lhs, const PathHierarchy &rhs);
93
-
94
- /** Strict-weak-order functor suitable for associative containers. */
95
- struct PathHierarchyLess {
96
- bool operator()(const PathHierarchy &lhs, const PathHierarchy &rhs) const;
97
- };
98
-
99
- /** Build a hierarchy containing a single leaf component. */
100
- PathHierarchy make_single_path(const std::string &root);
101
-
102
- /** Append helpers for single and multi-volume components. */
103
- void append_single(PathHierarchy &hierarchy, std::string value);
104
- void append_multi_volume(PathHierarchy &hierarchy, std::vector<std::string> parts, PathEntry::Parts::Ordering ordering = PathEntry::Parts::Ordering::Natural);
105
-
106
- /** Extract prefix/slice helpers. */
107
- PathHierarchy pathhierarchy_prefix_until(const PathHierarchy &hierarchy, size_t inclusive_index);
108
- PathHierarchy parent_hierarchy(const PathHierarchy &hierarchy);
109
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #pragma once
5
+
6
+ #include <cstddef>
7
+ #include <stdexcept>
8
+ #include <string>
9
+ #include <utility>
10
+ #include <variant>
11
+ #include <vector>
12
+
13
+ namespace archive_r {
14
+
15
+ /**
16
+ * @brief Represents a single component within a logical path hierarchy.
17
+ *
18
+ * A component can be one of three shapes:
19
+ * - single string value (most common)
20
+ * - multi-volume part list (split archives that share a common base name)
21
+ * - nested list of child entries (used for synthetic grouping)
22
+ */
23
+ class PathEntry {
24
+ public:
25
+ struct Parts {
26
+ std::vector<std::string> values;
27
+ enum class Ordering { Natural, Given } ordering = Ordering::Natural;
28
+ };
29
+
30
+ using NodeList = std::vector<PathEntry>;
31
+
32
+ PathEntry() = default;
33
+
34
+ explicit PathEntry(std::string value)
35
+ : _value(std::move(value)) {}
36
+
37
+ explicit PathEntry(Parts parts)
38
+ : _value(std::move(parts)) {}
39
+
40
+ explicit PathEntry(NodeList nodes)
41
+ : _value(std::move(nodes)) {}
42
+
43
+ static PathEntry single(std::string entry) { return PathEntry(std::move(entry)); }
44
+
45
+ static PathEntry multi_volume(std::vector<std::string> entries, Parts::Ordering ordering = Parts::Ordering::Natural) {
46
+ Parts parts{ std::move(entries), ordering };
47
+ if (parts.values.empty()) {
48
+ throw std::invalid_argument("multi-volume parts cannot be empty");
49
+ }
50
+ return PathEntry(std::move(parts));
51
+ }
52
+
53
+ static PathEntry nested(NodeList hierarchies) {
54
+ if (hierarchies.empty()) {
55
+ throw std::invalid_argument("nested hierarchies cannot be empty");
56
+ }
57
+ return PathEntry(std::move(hierarchies));
58
+ }
59
+
60
+ bool is_single() const { return std::holds_alternative<std::string>(_value); }
61
+ bool is_multi_volume() const { return std::holds_alternative<Parts>(_value); }
62
+ bool is_nested() const { return std::holds_alternative<NodeList>(_value); }
63
+ const std::string &single_value() const { return std::get<std::string>(_value); }
64
+ const Parts &multi_volume_parts() const { return std::get<Parts>(_value); }
65
+ Parts &multi_volume_parts_mut() { return std::get<Parts>(_value); }
66
+ const NodeList &nested_nodes() const { return std::get<NodeList>(_value); }
67
+ NodeList &nested_nodes_mut() { return std::get<NodeList>(_value); }
68
+
69
+ private:
70
+ std::variant<std::string, Parts, NodeList> _value;
71
+ };
72
+
73
+ using PathHierarchy = std::vector<PathEntry>;
74
+
75
+ /**
76
+ * Compare two entries using the ordering enforced throughout archive_r.
77
+ *
78
+ * Ordering rules:
79
+ * 1. Entry categories are ordered single < multi-volume < nested node-list.
80
+ * 2. Single entries compare by string value.
81
+ * 3. Multi-volume entries first compare their ordering flag (Natural < Given),
82
+ * then compare corresponding part names lexicographically, finally by list length.
83
+ * 4. Nested node-lists compare child entries pairwise using the same rules.
84
+ */
85
+ int compare_entries(const PathEntry &lhs, const PathEntry &rhs);
86
+
87
+ /** Compare complete hierarchies lexicographically using compare_entries on each level. */
88
+ int compare_hierarchies(const PathHierarchy &lhs, const PathHierarchy &rhs);
89
+
90
+ /** Shorthand equality helpers for entries and hierarchies. */
91
+ bool entries_equal(const PathEntry &lhs, const PathEntry &rhs);
92
+ bool hierarchies_equal(const PathHierarchy &lhs, const PathHierarchy &rhs);
93
+
94
+ /** Strict-weak-order functor suitable for associative containers. */
95
+ struct PathHierarchyLess {
96
+ bool operator()(const PathHierarchy &lhs, const PathHierarchy &rhs) const;
97
+ };
98
+
99
+ /** Build a hierarchy containing a single leaf component. */
100
+ PathHierarchy make_single_path(const std::string &root);
101
+
102
+ /** Append helpers for single and multi-volume components. */
103
+ void append_single(PathHierarchy &hierarchy, std::string value);
104
+ void append_multi_volume(PathHierarchy &hierarchy, std::vector<std::string> parts, PathEntry::Parts::Ordering ordering = PathEntry::Parts::Ordering::Natural);
105
+
106
+ /** Extract prefix/slice helpers. */
107
+ PathHierarchy pathhierarchy_prefix_until(const PathHierarchy &hierarchy, size_t inclusive_index);
108
+ PathHierarchy parent_hierarchy(const PathHierarchy &hierarchy);
109
+ } // namespace archive_r
@@ -1,37 +1,37 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #pragma once
5
-
6
- #include "archive_r/path_hierarchy.h"
7
- #include <cstddef>
8
- #include <string>
9
- #include <vector>
10
-
11
- namespace archive_r {
12
-
13
- /** Return pointer to the Nth single value of an entry (nullptr if absent). */
14
- const std::string *path_entry_component_at(const PathEntry &entry, std::size_t index);
15
-
16
- /** Convenience helpers for multi-volume PathHierarchy nodes. */
17
- std::size_t pathhierarchy_volume_size(const PathHierarchy &logical);
18
- std::string pathhierarchy_volume_entry_name(const PathHierarchy &logical, std::size_t index);
19
- bool pathhierarchy_is_multivolume(const PathHierarchy &hierarchy);
20
- PathHierarchy pathhierarchy_select_single_part(const PathHierarchy &logical, std::size_t index);
21
-
22
- /** Combine sibling hierarchies that differ only by their terminal part list. */
23
- PathHierarchy merge_multi_volume_sources(const std::vector<PathHierarchy> &sources);
24
-
25
- /** Sort hierarchies using PathHierarchyLess semantics. */
26
- void sort_hierarchies(std::vector<PathHierarchy> &hierarchies);
27
-
28
- /** Render helpers converting entries to flattened strings for diagnostics. */
29
- bool flatten_entry_to_string(const PathEntry &entry, std::string &output);
30
- bool entry_name_from_component(const PathEntry &entry, std::string &output);
31
-
32
- /** Human readable pretty-printers used in logging and debug output. */
33
- std::string path_entry_display(const PathEntry &entry);
34
- std::string hierarchy_display(const PathHierarchy &hierarchy);
35
-
36
-
37
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #pragma once
5
+
6
+ #include "archive_r/path_hierarchy.h"
7
+ #include <cstddef>
8
+ #include <string>
9
+ #include <vector>
10
+
11
+ namespace archive_r {
12
+
13
+ /** Return pointer to the Nth single value of an entry (nullptr if absent). */
14
+ const std::string *path_entry_component_at(const PathEntry &entry, std::size_t index);
15
+
16
+ /** Convenience helpers for multi-volume PathHierarchy nodes. */
17
+ std::size_t pathhierarchy_volume_size(const PathHierarchy &logical);
18
+ std::string pathhierarchy_volume_entry_name(const PathHierarchy &logical, std::size_t index);
19
+ bool pathhierarchy_is_multivolume(const PathHierarchy &hierarchy);
20
+ PathHierarchy pathhierarchy_select_single_part(const PathHierarchy &logical, std::size_t index);
21
+
22
+ /** Combine sibling hierarchies that differ only by their terminal part list. */
23
+ PathHierarchy merge_multi_volume_sources(const std::vector<PathHierarchy> &sources);
24
+
25
+ /** Sort hierarchies using PathHierarchyLess semantics. */
26
+ void sort_hierarchies(std::vector<PathHierarchy> &hierarchies);
27
+
28
+ /** Render helpers converting entries to flattened strings for diagnostics. */
29
+ bool flatten_entry_to_string(const PathEntry &entry, std::string &output);
30
+ bool entry_name_from_component(const PathEntry &entry, std::string &output);
31
+
32
+ /** Human readable pretty-printers used in logging and debug output. */
33
+ std::string path_entry_display(const PathEntry &entry);
34
+ std::string hierarchy_display(const PathHierarchy &hierarchy);
35
+
36
+
37
+ } // namespace archive_r
@@ -1,19 +1,19 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #pragma once
5
-
6
- #include <sys/types.h>
7
-
8
- #if defined(_WIN32)
9
- # include <sys/stat.h>
10
- # if !defined(_SSIZE_T_DEFINED)
11
- # include <BaseTsd.h>
12
- using ssize_t = SSIZE_T;
13
- # define _SSIZE_T_DEFINED
14
- # endif
15
- # if !defined(_MODE_T_DEFINED)
16
- using mode_t = unsigned short; // MSVC does not expose POSIX mode_t by default
17
- # define _MODE_T_DEFINED
18
- # endif
19
- #endif
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #pragma once
5
+
6
+ #include <sys/types.h>
7
+
8
+ #if defined(_WIN32)
9
+ # include <sys/stat.h>
10
+ # if !defined(_SSIZE_T_DEFINED)
11
+ # include <BaseTsd.h>
12
+ using ssize_t = SSIZE_T;
13
+ # define _SSIZE_T_DEFINED
14
+ # endif
15
+ # if !defined(_MODE_T_DEFINED)
16
+ using mode_t = unsigned short; // MSVC does not expose POSIX mode_t by default
17
+ # define _MODE_T_DEFINED
18
+ # endif
19
+ #endif
@@ -1,122 +1,122 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #pragma once
5
-
6
- #include "archive_r/entry_fault.h"
7
- #include "archive_r/path_hierarchy.h"
8
- #include "entry.h"
9
- #include <memory>
10
- #include <string>
11
- #include <vector>
12
-
13
- namespace archive_r {
14
-
15
- struct TraverserOptions {
16
- std::vector<std::string> passphrases; ///< Passphrases for encrypted archives
17
- std::vector<std::string> formats; ///< Specific archive formats to enable (empty = all)
18
- std::vector<std::string> metadata_keys; ///< Metadata keys to capture for entries
19
- bool descend_archives = true; ///< Whether to descend into archives by default
20
- };
21
-
22
- /**
23
- * @brief Iterator-based traversal for archives and directories
24
- *
25
- * Traverser provides a unified iterator-based interface for traversing
26
- * entries within archives and directories, including support for nested
27
- * archives and automatic descent.
28
- *
29
- * Supports multiple archive formats via libarchive (tar, zip, gzip, etc.)
30
- * and filesystem directories.
31
- *
32
- * Uses std::filesystem for directory traversal and ArchiveStackOrchestrator for archives.
33
-
34
- * @see Entry, ArchiveStackOrchestrator
35
- *
36
- * Usage:
37
- * Traverser traverser({make_single_path("archive.tar.gz")}); // or directory path
38
- * for (Entry& entry : traverser) {
39
- * // Process entry
40
- * }
41
- *
42
- * @note Thread Safety
43
- * Traverser instances are not thread-safe. To use the traverser in a
44
- * multi-threaded environment, create a separate Traverser instance for each
45
- * thread. Do not share a single instance across multiple threads.
46
- */
47
- class Traverser {
48
- public:
49
- /**
50
- * @brief Construct traverser for archives or directories
51
- * @param paths Paths to archive files or directories
52
- *
53
- * Provide one or more paths to traverse. Single-path traversal can be
54
- * achieved by passing a container with one element:
55
- * Traverser traverser({make_single_path("archive.tar.gz")});
56
- */
57
- explicit Traverser(std::vector<PathHierarchy> paths, TraverserOptions options = {});
58
-
59
- ~Traverser();
60
-
61
- // Non-copyable
62
- Traverser(const Traverser &) = delete;
63
- Traverser &operator=(const Traverser &) = delete;
64
-
65
- // ========================================================================
66
- // Iterator API
67
- // ========================================================================
68
-
69
- /**
70
- * @brief Forward iterator for traversing entries
71
- *
72
- * Satisfies InputIterator requirements:
73
- * - Move-only (non-copyable)
74
- * - Equality comparable
75
- * - Dereferenceable (returns Entry&)
76
- * - Incrementable
77
- */
78
- class Iterator {
79
- public:
80
- using iterator_category = std::input_iterator_tag;
81
- using value_type = Entry;
82
- using difference_type = std::ptrdiff_t;
83
- using pointer = Entry *;
84
- using reference = Entry &;
85
-
86
- reference operator*();
87
- pointer operator->();
88
- Iterator &operator++();
89
- bool operator==(const Iterator &other) const;
90
- bool operator!=(const Iterator &other) const;
91
-
92
- ~Iterator();
93
- Iterator(const Iterator &) = delete;
94
- Iterator &operator=(const Iterator &) = delete;
95
- Iterator(Iterator &&) noexcept;
96
- Iterator &operator=(Iterator &&) noexcept;
97
-
98
- private:
99
- friend class Traverser;
100
- class Impl;
101
- std::unique_ptr<Impl> _impl;
102
- explicit Iterator(std::unique_ptr<Impl> impl);
103
- };
104
-
105
- /**
106
- * @brief Get iterator to first entry
107
- * @return Iterator pointing to first entry
108
- */
109
- Iterator begin();
110
-
111
- /**
112
- * @brief Get end iterator
113
- * @return End iterator (sentinel)
114
- */
115
- Iterator end();
116
-
117
- private:
118
- std::vector<PathHierarchy> _initial_paths; ///< Initial paths provided to constructor
119
- TraverserOptions _options; ///< Options controlling archive handling
120
- };
121
-
122
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #pragma once
5
+
6
+ #include "archive_r/entry_fault.h"
7
+ #include "archive_r/path_hierarchy.h"
8
+ #include "entry.h"
9
+ #include <memory>
10
+ #include <string>
11
+ #include <vector>
12
+
13
+ namespace archive_r {
14
+
15
+ struct TraverserOptions {
16
+ std::vector<std::string> passphrases; ///< Passphrases for encrypted archives
17
+ std::vector<std::string> formats; ///< Specific archive formats to enable (empty = all)
18
+ std::vector<std::string> metadata_keys; ///< Metadata keys to capture for entries
19
+ bool descend_archives = true; ///< Whether to descend into archives by default
20
+ };
21
+
22
+ /**
23
+ * @brief Iterator-based traversal for archives and directories
24
+ *
25
+ * Traverser provides a unified iterator-based interface for traversing
26
+ * entries within archives and directories, including support for nested
27
+ * archives and automatic descent.
28
+ *
29
+ * Supports multiple archive formats via libarchive (tar, zip, gzip, etc.)
30
+ * and filesystem directories.
31
+ *
32
+ * Uses std::filesystem for directory traversal and ArchiveStackOrchestrator for archives.
33
+
34
+ * @see Entry, ArchiveStackOrchestrator
35
+ *
36
+ * Usage:
37
+ * Traverser traverser({make_single_path("archive.tar.gz")}); // or directory path
38
+ * for (Entry& entry : traverser) {
39
+ * // Process entry
40
+ * }
41
+ *
42
+ * @note Thread Safety
43
+ * Traverser instances are not thread-safe. To use the traverser in a
44
+ * multi-threaded environment, create a separate Traverser instance for each
45
+ * thread. Do not share a single instance across multiple threads.
46
+ */
47
+ class Traverser {
48
+ public:
49
+ /**
50
+ * @brief Construct traverser for archives or directories
51
+ * @param paths Paths to archive files or directories
52
+ *
53
+ * Provide one or more paths to traverse. Single-path traversal can be
54
+ * achieved by passing a container with one element:
55
+ * Traverser traverser({make_single_path("archive.tar.gz")});
56
+ */
57
+ explicit Traverser(std::vector<PathHierarchy> paths, TraverserOptions options = {});
58
+
59
+ ~Traverser();
60
+
61
+ // Non-copyable
62
+ Traverser(const Traverser &) = delete;
63
+ Traverser &operator=(const Traverser &) = delete;
64
+
65
+ // ========================================================================
66
+ // Iterator API
67
+ // ========================================================================
68
+
69
+ /**
70
+ * @brief Forward iterator for traversing entries
71
+ *
72
+ * Satisfies InputIterator requirements:
73
+ * - Move-only (non-copyable)
74
+ * - Equality comparable
75
+ * - Dereferenceable (returns Entry&)
76
+ * - Incrementable
77
+ */
78
+ class Iterator {
79
+ public:
80
+ using iterator_category = std::input_iterator_tag;
81
+ using value_type = Entry;
82
+ using difference_type = std::ptrdiff_t;
83
+ using pointer = Entry *;
84
+ using reference = Entry &;
85
+
86
+ reference operator*();
87
+ pointer operator->();
88
+ Iterator &operator++();
89
+ bool operator==(const Iterator &other) const;
90
+ bool operator!=(const Iterator &other) const;
91
+
92
+ ~Iterator();
93
+ Iterator(const Iterator &) = delete;
94
+ Iterator &operator=(const Iterator &) = delete;
95
+ Iterator(Iterator &&) noexcept;
96
+ Iterator &operator=(Iterator &&) noexcept;
97
+
98
+ private:
99
+ friend class Traverser;
100
+ class Impl;
101
+ std::unique_ptr<Impl> _impl;
102
+ explicit Iterator(std::unique_ptr<Impl> impl);
103
+ };
104
+
105
+ /**
106
+ * @brief Get iterator to first entry
107
+ * @return Iterator pointing to first entry
108
+ */
109
+ Iterator begin();
110
+
111
+ /**
112
+ * @brief Get end iterator
113
+ * @return End iterator (sentinel)
114
+ */
115
+ Iterator end();
116
+
117
+ private:
118
+ std::vector<PathHierarchy> _initial_paths; ///< Initial paths provided to constructor
119
+ TraverserOptions _options; ///< Options controlling archive handling
120
+ };
121
+
122
+ } // namespace archive_r