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.
- checksums.yaml +4 -4
- data/{LICENSE → LICENSE.txt} +77 -77
- data/README.md +103 -103
- data/ext/archive_r/Makefile +48 -45
- data/ext/archive_r/archive_r-x64-mingw-ucrt.def +2 -0
- data/ext/archive_r/archive_r_ext.cc +1106 -1106
- data/ext/archive_r/archive_r_ext.o +0 -0
- data/ext/archive_r/extconf.rb +120 -120
- data/ext/archive_r/mkmf.log +23 -18
- data/ext/archive_r/vendor/archive_r/LICENSE.txt +77 -77
- data/ext/archive_r/vendor/archive_r/include/archive_r/data_stream.h +52 -52
- data/ext/archive_r/vendor/archive_r/include/archive_r/entry.h +166 -166
- data/ext/archive_r/vendor/archive_r/include/archive_r/entry_fault.h +34 -34
- data/ext/archive_r/vendor/archive_r/include/archive_r/entry_metadata.h +56 -56
- data/ext/archive_r/vendor/archive_r/include/archive_r/multi_volume_stream_base.h +46 -46
- data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy.h +109 -109
- data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy_utils.h +37 -37
- data/ext/archive_r/vendor/archive_r/include/archive_r/platform_compat.h +19 -19
- data/ext/archive_r/vendor/archive_r/include/archive_r/traverser.h +122 -122
- data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.cc +330 -330
- data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.h +97 -97
- data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.cc +162 -162
- data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.h +54 -54
- data/ext/archive_r/vendor/archive_r/src/archive_type.cc +552 -552
- data/ext/archive_r/vendor/archive_r/src/archive_type.h +77 -77
- data/ext/archive_r/vendor/archive_r/src/data_stream.cc +35 -35
- data/ext/archive_r/vendor/archive_r/src/entry.cc +253 -253
- data/ext/archive_r/vendor/archive_r/src/entry_fault.cc +26 -26
- data/ext/archive_r/vendor/archive_r/src/entry_fault_error.cc +54 -54
- data/ext/archive_r/vendor/archive_r/src/entry_fault_error.h +32 -32
- data/ext/archive_r/vendor/archive_r/src/entry_impl.h +57 -57
- data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.cc +81 -81
- data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.h +41 -41
- data/ext/archive_r/vendor/archive_r/src/multi_volume_stream_base.cc +199 -199
- data/ext/archive_r/vendor/archive_r/src/path_hierarchy.cc +151 -151
- data/ext/archive_r/vendor/archive_r/src/path_hierarchy_utils.cc +304 -304
- data/ext/archive_r/vendor/archive_r/src/simple_profiler.h +120 -120
- data/ext/archive_r/vendor/archive_r/src/system_file_stream.cc +295 -295
- data/ext/archive_r/vendor/archive_r/src/system_file_stream.h +46 -46
- data/ext/archive_r/vendor/archive_r/src/traverser.cc +314 -314
- data/lib/archive_r.rb +105 -105
- metadata +11 -8
- data/ext/archive_r/archive_r.bundle +0 -0
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
// Copyright (c) 2025 archive_r Team
|
|
3
|
-
|
|
4
|
-
#pragma once
|
|
5
|
-
|
|
6
|
-
#include "archive_r/data_stream.h"
|
|
7
|
-
#include "archive_r/path_hierarchy.h"
|
|
8
|
-
#include "archive_type.h"
|
|
9
|
-
#include "entry_fault_error.h"
|
|
10
|
-
#include "archive_r/multi_volume_stream_base.h"
|
|
11
|
-
#include <array>
|
|
12
|
-
#include <cstddef>
|
|
13
|
-
#include <exception>
|
|
14
|
-
#include <memory>
|
|
15
|
-
#include <string>
|
|
16
|
-
#include <vector>
|
|
17
|
-
|
|
18
|
-
namespace archive_r {
|
|
19
|
-
|
|
20
|
-
// ============================================================================
|
|
21
|
-
// StreamArchive Interface
|
|
22
|
-
// ============================================================================
|
|
23
|
-
|
|
24
|
-
class StreamArchive : public Archive {
|
|
25
|
-
public:
|
|
26
|
-
explicit StreamArchive(std::shared_ptr<IDataStream> stream, ArchiveOption options = {});
|
|
27
|
-
|
|
28
|
-
~StreamArchive() override;
|
|
29
|
-
|
|
30
|
-
void open_archive() override;
|
|
31
|
-
void rewind() override;
|
|
32
|
-
|
|
33
|
-
PathHierarchy source_hierarchy() const;
|
|
34
|
-
|
|
35
|
-
private:
|
|
36
|
-
static la_ssize_t read_callback_bridge(struct archive *a, void *client_data, const void **buff);
|
|
37
|
-
static la_int64_t seek_callback_bridge(struct archive *a, void *client_data, la_int64_t request, int whence);
|
|
38
|
-
static la_int64_t skip_callback_bridge(struct archive *a, void *client_data, la_int64_t request);
|
|
39
|
-
|
|
40
|
-
static constexpr size_t BUFFER_SIZE = 65536;
|
|
41
|
-
std::shared_ptr<IDataStream> _stream;
|
|
42
|
-
std::array<char, BUFFER_SIZE> _buffer;
|
|
43
|
-
ArchiveOption _options;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// ============================================================================
|
|
47
|
-
// EntryPayloadStream Interface
|
|
48
|
-
// ============================================================================
|
|
49
|
-
|
|
50
|
-
class EntryPayloadStream : public MultiVolumeStreamBase {
|
|
51
|
-
public:
|
|
52
|
-
EntryPayloadStream(std::shared_ptr<StreamArchive> parent_archive, PathHierarchy logical_path);
|
|
53
|
-
~EntryPayloadStream() override;
|
|
54
|
-
|
|
55
|
-
std::shared_ptr<StreamArchive> parent_archive() const;
|
|
56
|
-
void rewind() override;
|
|
57
|
-
|
|
58
|
-
private:
|
|
59
|
-
std::shared_ptr<StreamArchive> _parent_archive;
|
|
60
|
-
|
|
61
|
-
void open_single_part(const PathHierarchy &single_part) override;
|
|
62
|
-
void close_single_part() override;
|
|
63
|
-
ssize_t read_from_single_part(void *buffer, size_t size) override;
|
|
64
|
-
int64_t seek_within_single_part(int64_t offset, int whence) override;
|
|
65
|
-
int64_t size_of_single_part(const PathHierarchy &single_part) override;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// ============================================================================
|
|
69
|
-
// ArchiveStackCursor Interface
|
|
70
|
-
// ============================================================================
|
|
71
|
-
|
|
72
|
-
struct ArchiveStackCursor {
|
|
73
|
-
|
|
74
|
-
ArchiveStackCursor();
|
|
75
|
-
|
|
76
|
-
void configure(const ArchiveOption &options);
|
|
77
|
-
void reset();
|
|
78
|
-
bool has_stream() const { return !stream_stack.empty(); }
|
|
79
|
-
|
|
80
|
-
bool descend();
|
|
81
|
-
bool ascend();
|
|
82
|
-
bool next();
|
|
83
|
-
bool synchronize_to_hierarchy(const PathHierarchy &hierarchy);
|
|
84
|
-
ssize_t read(void *buffer, size_t len);
|
|
85
|
-
|
|
86
|
-
size_t depth() const { return stream_stack.size(); }
|
|
87
|
-
StreamArchive *current_archive();
|
|
88
|
-
|
|
89
|
-
PathHierarchy current_entry_hierarchy();
|
|
90
|
-
|
|
91
|
-
std::shared_ptr<IDataStream> create_stream(const PathHierarchy &hierarchy);
|
|
92
|
-
|
|
93
|
-
ArchiveOption options_snapshot;
|
|
94
|
-
std::vector<std::shared_ptr<IDataStream>> stream_stack;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
} // namespace archive_r
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2025 archive_r Team
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "archive_r/data_stream.h"
|
|
7
|
+
#include "archive_r/path_hierarchy.h"
|
|
8
|
+
#include "archive_type.h"
|
|
9
|
+
#include "entry_fault_error.h"
|
|
10
|
+
#include "archive_r/multi_volume_stream_base.h"
|
|
11
|
+
#include <array>
|
|
12
|
+
#include <cstddef>
|
|
13
|
+
#include <exception>
|
|
14
|
+
#include <memory>
|
|
15
|
+
#include <string>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
18
|
+
namespace archive_r {
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// StreamArchive Interface
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
class StreamArchive : public Archive {
|
|
25
|
+
public:
|
|
26
|
+
explicit StreamArchive(std::shared_ptr<IDataStream> stream, ArchiveOption options = {});
|
|
27
|
+
|
|
28
|
+
~StreamArchive() override;
|
|
29
|
+
|
|
30
|
+
void open_archive() override;
|
|
31
|
+
void rewind() override;
|
|
32
|
+
|
|
33
|
+
PathHierarchy source_hierarchy() const;
|
|
34
|
+
|
|
35
|
+
private:
|
|
36
|
+
static la_ssize_t read_callback_bridge(struct archive *a, void *client_data, const void **buff);
|
|
37
|
+
static la_int64_t seek_callback_bridge(struct archive *a, void *client_data, la_int64_t request, int whence);
|
|
38
|
+
static la_int64_t skip_callback_bridge(struct archive *a, void *client_data, la_int64_t request);
|
|
39
|
+
|
|
40
|
+
static constexpr size_t BUFFER_SIZE = 65536;
|
|
41
|
+
std::shared_ptr<IDataStream> _stream;
|
|
42
|
+
std::array<char, BUFFER_SIZE> _buffer;
|
|
43
|
+
ArchiveOption _options;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// EntryPayloadStream Interface
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
class EntryPayloadStream : public MultiVolumeStreamBase {
|
|
51
|
+
public:
|
|
52
|
+
EntryPayloadStream(std::shared_ptr<StreamArchive> parent_archive, PathHierarchy logical_path);
|
|
53
|
+
~EntryPayloadStream() override;
|
|
54
|
+
|
|
55
|
+
std::shared_ptr<StreamArchive> parent_archive() const;
|
|
56
|
+
void rewind() override;
|
|
57
|
+
|
|
58
|
+
private:
|
|
59
|
+
std::shared_ptr<StreamArchive> _parent_archive;
|
|
60
|
+
|
|
61
|
+
void open_single_part(const PathHierarchy &single_part) override;
|
|
62
|
+
void close_single_part() override;
|
|
63
|
+
ssize_t read_from_single_part(void *buffer, size_t size) override;
|
|
64
|
+
int64_t seek_within_single_part(int64_t offset, int whence) override;
|
|
65
|
+
int64_t size_of_single_part(const PathHierarchy &single_part) override;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// ArchiveStackCursor Interface
|
|
70
|
+
// ============================================================================
|
|
71
|
+
|
|
72
|
+
struct ArchiveStackCursor {
|
|
73
|
+
|
|
74
|
+
ArchiveStackCursor();
|
|
75
|
+
|
|
76
|
+
void configure(const ArchiveOption &options);
|
|
77
|
+
void reset();
|
|
78
|
+
bool has_stream() const { return !stream_stack.empty(); }
|
|
79
|
+
|
|
80
|
+
bool descend();
|
|
81
|
+
bool ascend();
|
|
82
|
+
bool next();
|
|
83
|
+
bool synchronize_to_hierarchy(const PathHierarchy &hierarchy);
|
|
84
|
+
ssize_t read(void *buffer, size_t len);
|
|
85
|
+
|
|
86
|
+
size_t depth() const { return stream_stack.size(); }
|
|
87
|
+
StreamArchive *current_archive();
|
|
88
|
+
|
|
89
|
+
PathHierarchy current_entry_hierarchy();
|
|
90
|
+
|
|
91
|
+
std::shared_ptr<IDataStream> create_stream(const PathHierarchy &hierarchy);
|
|
92
|
+
|
|
93
|
+
ArchiveOption options_snapshot;
|
|
94
|
+
std::vector<std::shared_ptr<IDataStream>> stream_stack;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
} // namespace archive_r
|
|
@@ -1,162 +1,162 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
// Copyright (c) 2025 archive_r Team
|
|
3
|
-
|
|
4
|
-
#include "archive_stack_orchestrator.h"
|
|
5
|
-
#include "archive_r/path_hierarchy_utils.h"
|
|
6
|
-
#include "archive_r/entry_fault.h"
|
|
7
|
-
#include "system_file_stream.h"
|
|
8
|
-
|
|
9
|
-
#include <algorithm>
|
|
10
|
-
#include <cstddef>
|
|
11
|
-
#include <cstdio>
|
|
12
|
-
#include <exception>
|
|
13
|
-
#include <limits>
|
|
14
|
-
#include <memory>
|
|
15
|
-
#include <stdexcept>
|
|
16
|
-
#include <typeinfo>
|
|
17
|
-
#include <utility>
|
|
18
|
-
|
|
19
|
-
namespace archive_r {
|
|
20
|
-
|
|
21
|
-
ArchiveStackOrchestrator::ArchiveStackOrchestrator(const ArchiveOption &options)
|
|
22
|
-
: _archive_options(options)
|
|
23
|
-
, _metadata_keys(options.metadata_keys.begin(), options.metadata_keys.end()) {
|
|
24
|
-
_head.configure(_archive_options);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
ArchiveStackOrchestrator::~ArchiveStackOrchestrator() = default;
|
|
28
|
-
|
|
29
|
-
size_t ArchiveStackOrchestrator::depth() const { return _head.depth(); }
|
|
30
|
-
|
|
31
|
-
StreamArchive *ArchiveStackOrchestrator::current_archive() { return _head.current_archive(); }
|
|
32
|
-
|
|
33
|
-
// Drives the traversal state machine:
|
|
34
|
-
// 1. Optionally descend into the current entry when requested.
|
|
35
|
-
// 2. Attempt to advance within the active archive; report faults but keep looping.
|
|
36
|
-
// 3. Drain any pending multi-volume groups before bubbling up to the parent so multipart
|
|
37
|
-
// archives are consumed contiguously.
|
|
38
|
-
// 4. When leaving a multi-volume context, rewind the parent archive by skipping to EOF to
|
|
39
|
-
// avoid re-reading already processed entries.
|
|
40
|
-
bool ArchiveStackOrchestrator::advance(bool descend_request) {
|
|
41
|
-
bool request_descend = descend_request;
|
|
42
|
-
|
|
43
|
-
while (true) {
|
|
44
|
-
if (depth() == 0) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
if (request_descend) {
|
|
49
|
-
request_descend = false;
|
|
50
|
-
_head.descend();
|
|
51
|
-
}
|
|
52
|
-
} catch (const EntryFaultError &error) {
|
|
53
|
-
dispatch_fault(error.fault());
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
if (_head.next()) {
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
} catch (const EntryFaultError &error) {
|
|
62
|
-
dispatch_fault(error.fault());
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
// Consume any pending multi-volume siblings so we do not return to the parent mid-series.
|
|
68
|
-
if (descend_pending_multi_volumes()) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
} catch (const EntryFaultError &error) {
|
|
72
|
-
dispatch_fault(error.fault());
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
PathHierarchy prev_ascend_hierarchy = _head.current_entry_hierarchy();
|
|
76
|
-
_head.ascend();
|
|
77
|
-
|
|
78
|
-
if (!pathhierarchy_is_multivolume(prev_ascend_hierarchy)) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
// If same-level multi-volume siblings remain, keep draining them before touching the parent next().
|
|
84
|
-
if (descend_pending_multi_volumes()) {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
} catch (const EntryFaultError &error) {
|
|
88
|
-
dispatch_fault(error.fault());
|
|
89
|
-
}
|
|
90
|
-
try {
|
|
91
|
-
StreamArchive *archive = _head.current_archive();
|
|
92
|
-
if (archive) {
|
|
93
|
-
// After all volumes are processed, push the parent back to EOF to avoid duplicate next().
|
|
94
|
-
archive->skip_to_eof();
|
|
95
|
-
}
|
|
96
|
-
} catch (const EntryFaultError &error) {
|
|
97
|
-
dispatch_fault(error.fault());
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const std::string &ArchiveStackOrchestrator::current_entryname() {
|
|
103
|
-
StreamArchive *archive = current_archive();
|
|
104
|
-
if (!archive) {
|
|
105
|
-
static const std::string empty;
|
|
106
|
-
return empty;
|
|
107
|
-
}
|
|
108
|
-
return archive->current_entryname;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
PathHierarchy ArchiveStackOrchestrator::current_entry_hierarchy() { return _head.current_entry_hierarchy(); }
|
|
112
|
-
|
|
113
|
-
bool ArchiveStackOrchestrator::synchronize_to_hierarchy(const PathHierarchy &path_hierarchy) {
|
|
114
|
-
try {
|
|
115
|
-
_head.synchronize_to_hierarchy(path_hierarchy);
|
|
116
|
-
return true;
|
|
117
|
-
} catch (const EntryFaultError &error) {
|
|
118
|
-
dispatch_fault(error.fault());
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
ssize_t ArchiveStackOrchestrator::read_head(void *buff, size_t len) {
|
|
124
|
-
try {
|
|
125
|
-
return _head.read(buff, len);
|
|
126
|
-
} catch (const EntryFaultError &error) {
|
|
127
|
-
dispatch_fault(error.fault());
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return -1;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
void ArchiveStackOrchestrator::mark_entry_as_multi_volume(const PathHierarchy &entry_path, const std::string &base_name, PathEntry::Parts::Ordering ordering) {
|
|
134
|
-
_multi_volume_manager.mark_entry_as_multi_volume(entry_path, base_name, ordering);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
bool ArchiveStackOrchestrator::descend_pending_multi_volumes() {
|
|
138
|
-
const PathHierarchy current_hierarchy = _head.current_entry_hierarchy();
|
|
139
|
-
PathHierarchy multi_volume_target;
|
|
140
|
-
if (!_multi_volume_manager.pop_multi_volume_group(current_hierarchy, multi_volume_target)) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
_head.synchronize_to_hierarchy(multi_volume_target);
|
|
145
|
-
_head.descend();
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
void ArchiveStackOrchestrator::open_root_hierarchy(const PathHierarchy &root_hierarchy) {
|
|
150
|
-
_head.synchronize_to_hierarchy(root_hierarchy);
|
|
151
|
-
_head.descend();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
void ArchiveStackOrchestrator::dispatch_fault(EntryFault fault) {
|
|
155
|
-
if (fault.hierarchy.empty()) {
|
|
156
|
-
fault.hierarchy = _head.current_entry_hierarchy();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
dispatch_registered_fault(fault);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
} // namespace archive_r
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2025 archive_r Team
|
|
3
|
+
|
|
4
|
+
#include "archive_stack_orchestrator.h"
|
|
5
|
+
#include "archive_r/path_hierarchy_utils.h"
|
|
6
|
+
#include "archive_r/entry_fault.h"
|
|
7
|
+
#include "system_file_stream.h"
|
|
8
|
+
|
|
9
|
+
#include <algorithm>
|
|
10
|
+
#include <cstddef>
|
|
11
|
+
#include <cstdio>
|
|
12
|
+
#include <exception>
|
|
13
|
+
#include <limits>
|
|
14
|
+
#include <memory>
|
|
15
|
+
#include <stdexcept>
|
|
16
|
+
#include <typeinfo>
|
|
17
|
+
#include <utility>
|
|
18
|
+
|
|
19
|
+
namespace archive_r {
|
|
20
|
+
|
|
21
|
+
ArchiveStackOrchestrator::ArchiveStackOrchestrator(const ArchiveOption &options)
|
|
22
|
+
: _archive_options(options)
|
|
23
|
+
, _metadata_keys(options.metadata_keys.begin(), options.metadata_keys.end()) {
|
|
24
|
+
_head.configure(_archive_options);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
ArchiveStackOrchestrator::~ArchiveStackOrchestrator() = default;
|
|
28
|
+
|
|
29
|
+
size_t ArchiveStackOrchestrator::depth() const { return _head.depth(); }
|
|
30
|
+
|
|
31
|
+
StreamArchive *ArchiveStackOrchestrator::current_archive() { return _head.current_archive(); }
|
|
32
|
+
|
|
33
|
+
// Drives the traversal state machine:
|
|
34
|
+
// 1. Optionally descend into the current entry when requested.
|
|
35
|
+
// 2. Attempt to advance within the active archive; report faults but keep looping.
|
|
36
|
+
// 3. Drain any pending multi-volume groups before bubbling up to the parent so multipart
|
|
37
|
+
// archives are consumed contiguously.
|
|
38
|
+
// 4. When leaving a multi-volume context, rewind the parent archive by skipping to EOF to
|
|
39
|
+
// avoid re-reading already processed entries.
|
|
40
|
+
bool ArchiveStackOrchestrator::advance(bool descend_request) {
|
|
41
|
+
bool request_descend = descend_request;
|
|
42
|
+
|
|
43
|
+
while (true) {
|
|
44
|
+
if (depth() == 0) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
if (request_descend) {
|
|
49
|
+
request_descend = false;
|
|
50
|
+
_head.descend();
|
|
51
|
+
}
|
|
52
|
+
} catch (const EntryFaultError &error) {
|
|
53
|
+
dispatch_fault(error.fault());
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
if (_head.next()) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
} catch (const EntryFaultError &error) {
|
|
62
|
+
dispatch_fault(error.fault());
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
// Consume any pending multi-volume siblings so we do not return to the parent mid-series.
|
|
68
|
+
if (descend_pending_multi_volumes()) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
} catch (const EntryFaultError &error) {
|
|
72
|
+
dispatch_fault(error.fault());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
PathHierarchy prev_ascend_hierarchy = _head.current_entry_hierarchy();
|
|
76
|
+
_head.ascend();
|
|
77
|
+
|
|
78
|
+
if (!pathhierarchy_is_multivolume(prev_ascend_hierarchy)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// If same-level multi-volume siblings remain, keep draining them before touching the parent next().
|
|
84
|
+
if (descend_pending_multi_volumes()) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
} catch (const EntryFaultError &error) {
|
|
88
|
+
dispatch_fault(error.fault());
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
StreamArchive *archive = _head.current_archive();
|
|
92
|
+
if (archive) {
|
|
93
|
+
// After all volumes are processed, push the parent back to EOF to avoid duplicate next().
|
|
94
|
+
archive->skip_to_eof();
|
|
95
|
+
}
|
|
96
|
+
} catch (const EntryFaultError &error) {
|
|
97
|
+
dispatch_fault(error.fault());
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const std::string &ArchiveStackOrchestrator::current_entryname() {
|
|
103
|
+
StreamArchive *archive = current_archive();
|
|
104
|
+
if (!archive) {
|
|
105
|
+
static const std::string empty;
|
|
106
|
+
return empty;
|
|
107
|
+
}
|
|
108
|
+
return archive->current_entryname;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
PathHierarchy ArchiveStackOrchestrator::current_entry_hierarchy() { return _head.current_entry_hierarchy(); }
|
|
112
|
+
|
|
113
|
+
bool ArchiveStackOrchestrator::synchronize_to_hierarchy(const PathHierarchy &path_hierarchy) {
|
|
114
|
+
try {
|
|
115
|
+
_head.synchronize_to_hierarchy(path_hierarchy);
|
|
116
|
+
return true;
|
|
117
|
+
} catch (const EntryFaultError &error) {
|
|
118
|
+
dispatch_fault(error.fault());
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
ssize_t ArchiveStackOrchestrator::read_head(void *buff, size_t len) {
|
|
124
|
+
try {
|
|
125
|
+
return _head.read(buff, len);
|
|
126
|
+
} catch (const EntryFaultError &error) {
|
|
127
|
+
dispatch_fault(error.fault());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return -1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
void ArchiveStackOrchestrator::mark_entry_as_multi_volume(const PathHierarchy &entry_path, const std::string &base_name, PathEntry::Parts::Ordering ordering) {
|
|
134
|
+
_multi_volume_manager.mark_entry_as_multi_volume(entry_path, base_name, ordering);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
bool ArchiveStackOrchestrator::descend_pending_multi_volumes() {
|
|
138
|
+
const PathHierarchy current_hierarchy = _head.current_entry_hierarchy();
|
|
139
|
+
PathHierarchy multi_volume_target;
|
|
140
|
+
if (!_multi_volume_manager.pop_multi_volume_group(current_hierarchy, multi_volume_target)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_head.synchronize_to_hierarchy(multi_volume_target);
|
|
145
|
+
_head.descend();
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
void ArchiveStackOrchestrator::open_root_hierarchy(const PathHierarchy &root_hierarchy) {
|
|
150
|
+
_head.synchronize_to_hierarchy(root_hierarchy);
|
|
151
|
+
_head.descend();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
void ArchiveStackOrchestrator::dispatch_fault(EntryFault fault) {
|
|
155
|
+
if (fault.hierarchy.empty()) {
|
|
156
|
+
fault.hierarchy = _head.current_entry_hierarchy();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
dispatch_registered_fault(fault);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
} // namespace archive_r
|
|
@@ -1,54 +1,54 @@
|
|
|
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 "archive_r/platform_compat.h"
|
|
8
|
-
#include "archive_type.h"
|
|
9
|
-
#include "archive_stack_cursor.h"
|
|
10
|
-
#include "entry_fault_error.h"
|
|
11
|
-
#include "multi_volume_manager.h"
|
|
12
|
-
#include <limits>
|
|
13
|
-
#include <memory>
|
|
14
|
-
#include <string>
|
|
15
|
-
#include <unordered_set>
|
|
16
|
-
|
|
17
|
-
namespace archive_r {
|
|
18
|
-
|
|
19
|
-
class ArchiveStackOrchestrator {
|
|
20
|
-
public:
|
|
21
|
-
explicit ArchiveStackOrchestrator(const ArchiveOption &options = {});
|
|
22
|
-
ArchiveStackOrchestrator(const ArchiveStackOrchestrator &) = delete;
|
|
23
|
-
ArchiveStackOrchestrator &operator=(const ArchiveStackOrchestrator &) = delete;
|
|
24
|
-
|
|
25
|
-
~ArchiveStackOrchestrator();
|
|
26
|
-
|
|
27
|
-
void open_root_hierarchy(const PathHierarchy &root_hierarchy);
|
|
28
|
-
|
|
29
|
-
bool advance(bool descend_request = true);
|
|
30
|
-
const std::string ¤t_entryname();
|
|
31
|
-
|
|
32
|
-
size_t depth() const;
|
|
33
|
-
PathHierarchy current_entry_hierarchy();
|
|
34
|
-
bool synchronize_to_hierarchy(const PathHierarchy &path_hierarchy);
|
|
35
|
-
|
|
36
|
-
StreamArchive *current_archive();
|
|
37
|
-
ssize_t read_head(void *buff, size_t len);
|
|
38
|
-
|
|
39
|
-
const std::unordered_set<std::string> &metadata_keys() const { return _metadata_keys; }
|
|
40
|
-
const ArchiveOption &options() const { return _archive_options; }
|
|
41
|
-
|
|
42
|
-
void mark_entry_as_multi_volume(const PathHierarchy &entry_path, const std::string &base_name, PathEntry::Parts::Ordering ordering = PathEntry::Parts::Ordering::Natural);
|
|
43
|
-
bool descend_pending_multi_volumes();
|
|
44
|
-
|
|
45
|
-
private:
|
|
46
|
-
ArchiveOption _archive_options;
|
|
47
|
-
std::unordered_set<std::string> _metadata_keys;
|
|
48
|
-
ArchiveStackCursor _head;
|
|
49
|
-
MultiVolumeManager _multi_volume_manager;
|
|
50
|
-
|
|
51
|
-
void dispatch_fault(EntryFault fault);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
} // 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 "archive_r/platform_compat.h"
|
|
8
|
+
#include "archive_type.h"
|
|
9
|
+
#include "archive_stack_cursor.h"
|
|
10
|
+
#include "entry_fault_error.h"
|
|
11
|
+
#include "multi_volume_manager.h"
|
|
12
|
+
#include <limits>
|
|
13
|
+
#include <memory>
|
|
14
|
+
#include <string>
|
|
15
|
+
#include <unordered_set>
|
|
16
|
+
|
|
17
|
+
namespace archive_r {
|
|
18
|
+
|
|
19
|
+
class ArchiveStackOrchestrator {
|
|
20
|
+
public:
|
|
21
|
+
explicit ArchiveStackOrchestrator(const ArchiveOption &options = {});
|
|
22
|
+
ArchiveStackOrchestrator(const ArchiveStackOrchestrator &) = delete;
|
|
23
|
+
ArchiveStackOrchestrator &operator=(const ArchiveStackOrchestrator &) = delete;
|
|
24
|
+
|
|
25
|
+
~ArchiveStackOrchestrator();
|
|
26
|
+
|
|
27
|
+
void open_root_hierarchy(const PathHierarchy &root_hierarchy);
|
|
28
|
+
|
|
29
|
+
bool advance(bool descend_request = true);
|
|
30
|
+
const std::string ¤t_entryname();
|
|
31
|
+
|
|
32
|
+
size_t depth() const;
|
|
33
|
+
PathHierarchy current_entry_hierarchy();
|
|
34
|
+
bool synchronize_to_hierarchy(const PathHierarchy &path_hierarchy);
|
|
35
|
+
|
|
36
|
+
StreamArchive *current_archive();
|
|
37
|
+
ssize_t read_head(void *buff, size_t len);
|
|
38
|
+
|
|
39
|
+
const std::unordered_set<std::string> &metadata_keys() const { return _metadata_keys; }
|
|
40
|
+
const ArchiveOption &options() const { return _archive_options; }
|
|
41
|
+
|
|
42
|
+
void mark_entry_as_multi_volume(const PathHierarchy &entry_path, const std::string &base_name, PathEntry::Parts::Ordering ordering = PathEntry::Parts::Ordering::Natural);
|
|
43
|
+
bool descend_pending_multi_volumes();
|
|
44
|
+
|
|
45
|
+
private:
|
|
46
|
+
ArchiveOption _archive_options;
|
|
47
|
+
std::unordered_set<std::string> _metadata_keys;
|
|
48
|
+
ArchiveStackCursor _head;
|
|
49
|
+
MultiVolumeManager _multi_volume_manager;
|
|
50
|
+
|
|
51
|
+
void dispatch_fault(EntryFault fault);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
} // namespace archive_r
|