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,304 +1,304 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #include "archive_r/path_hierarchy_utils.h"
5
-
6
- #include <algorithm>
7
- #include <filesystem>
8
-
9
- namespace archive_r {
10
-
11
- namespace {
12
-
13
- struct CollapseSegments {
14
- PathHierarchy prefix;
15
- PathHierarchy suffix;
16
- std::size_t multi_volume_depth = 0;
17
- };
18
-
19
- PathHierarchy hierarchy_suffix_from(const PathHierarchy &hierarchy, std::size_t start_index) {
20
- if (hierarchy.empty() || start_index >= hierarchy.size()) {
21
- return {};
22
- }
23
- const auto begin = hierarchy.begin() + static_cast<PathHierarchy::difference_type>(start_index);
24
- return PathHierarchy(begin, hierarchy.end());
25
- }
26
-
27
- bool determine_multi_volume_segments(const std::vector<PathHierarchy> &sources, CollapseSegments &segments) {
28
- if (sources.empty()) {
29
- return false;
30
- }
31
-
32
- const PathHierarchy &reference = sources.front();
33
- if (reference.empty()) {
34
- return false;
35
- }
36
-
37
- std::size_t multi_volume_depth = reference.size() - 1;
38
- bool difference_found = false;
39
-
40
- for (std::size_t depth = 0; depth < reference.size(); ++depth) {
41
- const PathEntry &reference_entry = reference[depth];
42
- for (std::size_t i = 1; i < sources.size(); ++i) {
43
- const PathHierarchy &candidate = sources[i];
44
- if (candidate.size() <= depth) {
45
- return false;
46
- }
47
- if (!archive_r::entries_equal(reference_entry, candidate[depth])) {
48
- multi_volume_depth = depth;
49
- difference_found = true;
50
- break;
51
- }
52
- }
53
- if (difference_found) {
54
- break;
55
- }
56
- }
57
-
58
- if (!difference_found) {
59
- for (std::size_t i = 1; i < sources.size(); ++i) {
60
- if (sources[i].size() != reference.size()) {
61
- return false;
62
- }
63
- }
64
- }
65
-
66
- segments.multi_volume_depth = multi_volume_depth;
67
- segments.prefix.clear();
68
- if (multi_volume_depth > 0) {
69
- segments.prefix = pathhierarchy_prefix_until(reference, multi_volume_depth - 1);
70
- }
71
- segments.suffix = hierarchy_suffix_from(reference, multi_volume_depth + 1);
72
- return true;
73
- }
74
-
75
- bool collect_multi_volume_parts(const std::vector<PathHierarchy> &sources, const CollapseSegments &segments, std::vector<std::string> &parts) {
76
- if (sources.empty()) {
77
- return false;
78
- }
79
-
80
- const std::size_t suffix_size = segments.suffix.size();
81
- const std::size_t required_size = segments.multi_volume_depth + 1 + suffix_size;
82
-
83
- parts.clear();
84
- parts.reserve(sources.size());
85
-
86
- for (const auto &hierarchy : sources) {
87
- if (hierarchy.empty() || hierarchy.size() <= segments.multi_volume_depth) {
88
- return false;
89
- }
90
-
91
- if (hierarchy.size() != required_size) {
92
- return false;
93
- }
94
-
95
- const PathEntry &component = hierarchy[segments.multi_volume_depth];
96
- if (!component.is_single()) {
97
- return false;
98
- }
99
-
100
- for (std::size_t offset = 0; offset < suffix_size; ++offset) {
101
- const PathEntry &reference_entry = segments.suffix[offset];
102
- const PathEntry &candidate_entry = hierarchy[segments.multi_volume_depth + 1 + offset];
103
- if (!archive_r::entries_equal(reference_entry, candidate_entry)) {
104
- return false;
105
- }
106
- }
107
-
108
- parts.push_back(component.single_value());
109
- }
110
-
111
- return true;
112
- }
113
-
114
- bool flatten_single_entry(const PathEntry &entry, std::string &output) {
115
- if (entry.is_single()) {
116
- output = entry.single_value();
117
- return true;
118
- }
119
- return flatten_entry_to_string(entry, output);
120
- }
121
-
122
- } // namespace
123
-
124
- const std::string *path_entry_component_at(const PathEntry &entry, std::size_t index) {
125
- if (entry.is_single()) {
126
- if (index == 0) {
127
- return &entry.single_value();
128
- }
129
- return nullptr;
130
- }
131
-
132
- if (entry.is_multi_volume()) {
133
- const auto &parts = entry.multi_volume_parts().values;
134
- if (index < parts.size()) {
135
- return &parts[index];
136
- }
137
- return nullptr;
138
- }
139
-
140
- return nullptr;
141
- }
142
-
143
- std::size_t pathhierarchy_volume_size(const PathHierarchy &logical) {
144
- if (logical.empty()) {
145
- return 0;
146
- }
147
- const PathEntry &tail = logical.back();
148
- if (!tail.is_multi_volume()) {
149
- return 1;
150
- }
151
- const auto &parts = tail.multi_volume_parts().values;
152
- return parts.size();
153
- }
154
-
155
- std::string pathhierarchy_volume_entry_name(const PathHierarchy &logical, std::size_t index) {
156
- if (logical.empty()) {
157
- return {};
158
- }
159
- const PathEntry &tail = logical.back();
160
- if (!tail.is_multi_volume()) {
161
- if (index != 0) {
162
- return {};
163
- }
164
-
165
- std::string entry_name;
166
- if (!flatten_single_entry(tail, entry_name)) {
167
- return {};
168
- }
169
- return entry_name;
170
- }
171
-
172
- const auto &parts = tail.multi_volume_parts().values;
173
- if (index >= parts.size()) {
174
- return {};
175
- }
176
- return parts[index];
177
- }
178
-
179
- bool pathhierarchy_is_multivolume(const PathHierarchy &hierarchy) {
180
- if (hierarchy.empty()) {
181
- return false;
182
- }
183
- return hierarchy.back().is_multi_volume();
184
- }
185
-
186
- PathHierarchy pathhierarchy_select_single_part(const PathHierarchy &logical, std::size_t index) {
187
- if (logical.empty()) {
188
- return {};
189
- }
190
-
191
- PathHierarchy result = parent_hierarchy(logical);
192
- append_single(result, pathhierarchy_volume_entry_name(logical, index));
193
- return result;
194
- }
195
-
196
- void sort_hierarchies(std::vector<PathHierarchy> &hierarchies) {
197
- std::sort(hierarchies.begin(), hierarchies.end(), [](const PathHierarchy &lhs, const PathHierarchy &rhs) { return archive_r::compare_hierarchies(lhs, rhs) < 0; });
198
- }
199
-
200
- bool flatten_entry_to_string(const PathEntry &entry, std::string &output) {
201
- if (entry.is_single()) {
202
- output = entry.single_value();
203
- return true;
204
- }
205
-
206
- if (entry.is_nested()) {
207
- std::string result;
208
- bool first = true;
209
- for (const auto &child : entry.nested_nodes()) {
210
- std::string component;
211
- if (!flatten_entry_to_string(child, component)) {
212
- return false;
213
- }
214
- if (component.empty()) {
215
- return false;
216
- }
217
- if (!first) {
218
- result.push_back('/');
219
- }
220
- result += component;
221
- first = false;
222
- }
223
- output = result;
224
- return !result.empty();
225
- }
226
-
227
- return false;
228
- }
229
-
230
- bool entry_name_from_component(const PathEntry &entry, std::string &output) {
231
- if (entry.is_multi_volume()) {
232
- const auto &parts = entry.multi_volume_parts().values;
233
- if (parts.empty()) {
234
- return false;
235
- }
236
- output = parts.front();
237
- return true;
238
- }
239
-
240
- return flatten_entry_to_string(entry, output);
241
- }
242
-
243
- PathHierarchy merge_multi_volume_sources(const std::vector<PathHierarchy> &sources) {
244
- CollapseSegments segments;
245
- if (!determine_multi_volume_segments(sources, segments)) {
246
- return {};
247
- }
248
-
249
- std::vector<std::string> parts;
250
- if (!collect_multi_volume_parts(sources, segments, parts)) {
251
- return {};
252
- }
253
-
254
- PathHierarchy result = segments.prefix;
255
- result.reserve(result.size() + 1 + segments.suffix.size());
256
- result.emplace_back(PathEntry::multi_volume(std::move(parts)));
257
- result.insert(result.end(), segments.suffix.begin(), segments.suffix.end());
258
- return result;
259
- }
260
-
261
- std::string path_entry_display(const PathEntry &entry) {
262
- if (entry.is_single()) {
263
- return entry.single_value();
264
- }
265
- if (entry.is_multi_volume()) {
266
- std::string value = "[";
267
- bool first = true;
268
- for (const auto &part : entry.multi_volume_parts().values) {
269
- if (!first) {
270
- value.push_back('|');
271
- }
272
- value += part;
273
- first = false;
274
- }
275
- value.push_back(']');
276
- return value;
277
- }
278
- std::string value = "{";
279
- bool first = true;
280
- for (const auto &child : entry.nested_nodes()) {
281
- if (!first) {
282
- value.push_back('/');
283
- }
284
- value += path_entry_display(child);
285
- first = false;
286
- }
287
- value.push_back('}');
288
- return value;
289
- }
290
-
291
- std::string hierarchy_display(const PathHierarchy &hierarchy) {
292
- std::string result;
293
- bool first = true;
294
- for (const auto &component : hierarchy) {
295
- if (!first) {
296
- result.push_back('/');
297
- }
298
- result += path_entry_display(component);
299
- first = false;
300
- }
301
- return result;
302
- }
303
-
304
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #include "archive_r/path_hierarchy_utils.h"
5
+
6
+ #include <algorithm>
7
+ #include <filesystem>
8
+
9
+ namespace archive_r {
10
+
11
+ namespace {
12
+
13
+ struct CollapseSegments {
14
+ PathHierarchy prefix;
15
+ PathHierarchy suffix;
16
+ std::size_t multi_volume_depth = 0;
17
+ };
18
+
19
+ PathHierarchy hierarchy_suffix_from(const PathHierarchy &hierarchy, std::size_t start_index) {
20
+ if (hierarchy.empty() || start_index >= hierarchy.size()) {
21
+ return {};
22
+ }
23
+ const auto begin = hierarchy.begin() + static_cast<PathHierarchy::difference_type>(start_index);
24
+ return PathHierarchy(begin, hierarchy.end());
25
+ }
26
+
27
+ bool determine_multi_volume_segments(const std::vector<PathHierarchy> &sources, CollapseSegments &segments) {
28
+ if (sources.empty()) {
29
+ return false;
30
+ }
31
+
32
+ const PathHierarchy &reference = sources.front();
33
+ if (reference.empty()) {
34
+ return false;
35
+ }
36
+
37
+ std::size_t multi_volume_depth = reference.size() - 1;
38
+ bool difference_found = false;
39
+
40
+ for (std::size_t depth = 0; depth < reference.size(); ++depth) {
41
+ const PathEntry &reference_entry = reference[depth];
42
+ for (std::size_t i = 1; i < sources.size(); ++i) {
43
+ const PathHierarchy &candidate = sources[i];
44
+ if (candidate.size() <= depth) {
45
+ return false;
46
+ }
47
+ if (!archive_r::entries_equal(reference_entry, candidate[depth])) {
48
+ multi_volume_depth = depth;
49
+ difference_found = true;
50
+ break;
51
+ }
52
+ }
53
+ if (difference_found) {
54
+ break;
55
+ }
56
+ }
57
+
58
+ if (!difference_found) {
59
+ for (std::size_t i = 1; i < sources.size(); ++i) {
60
+ if (sources[i].size() != reference.size()) {
61
+ return false;
62
+ }
63
+ }
64
+ }
65
+
66
+ segments.multi_volume_depth = multi_volume_depth;
67
+ segments.prefix.clear();
68
+ if (multi_volume_depth > 0) {
69
+ segments.prefix = pathhierarchy_prefix_until(reference, multi_volume_depth - 1);
70
+ }
71
+ segments.suffix = hierarchy_suffix_from(reference, multi_volume_depth + 1);
72
+ return true;
73
+ }
74
+
75
+ bool collect_multi_volume_parts(const std::vector<PathHierarchy> &sources, const CollapseSegments &segments, std::vector<std::string> &parts) {
76
+ if (sources.empty()) {
77
+ return false;
78
+ }
79
+
80
+ const std::size_t suffix_size = segments.suffix.size();
81
+ const std::size_t required_size = segments.multi_volume_depth + 1 + suffix_size;
82
+
83
+ parts.clear();
84
+ parts.reserve(sources.size());
85
+
86
+ for (const auto &hierarchy : sources) {
87
+ if (hierarchy.empty() || hierarchy.size() <= segments.multi_volume_depth) {
88
+ return false;
89
+ }
90
+
91
+ if (hierarchy.size() != required_size) {
92
+ return false;
93
+ }
94
+
95
+ const PathEntry &component = hierarchy[segments.multi_volume_depth];
96
+ if (!component.is_single()) {
97
+ return false;
98
+ }
99
+
100
+ for (std::size_t offset = 0; offset < suffix_size; ++offset) {
101
+ const PathEntry &reference_entry = segments.suffix[offset];
102
+ const PathEntry &candidate_entry = hierarchy[segments.multi_volume_depth + 1 + offset];
103
+ if (!archive_r::entries_equal(reference_entry, candidate_entry)) {
104
+ return false;
105
+ }
106
+ }
107
+
108
+ parts.push_back(component.single_value());
109
+ }
110
+
111
+ return true;
112
+ }
113
+
114
+ bool flatten_single_entry(const PathEntry &entry, std::string &output) {
115
+ if (entry.is_single()) {
116
+ output = entry.single_value();
117
+ return true;
118
+ }
119
+ return flatten_entry_to_string(entry, output);
120
+ }
121
+
122
+ } // namespace
123
+
124
+ const std::string *path_entry_component_at(const PathEntry &entry, std::size_t index) {
125
+ if (entry.is_single()) {
126
+ if (index == 0) {
127
+ return &entry.single_value();
128
+ }
129
+ return nullptr;
130
+ }
131
+
132
+ if (entry.is_multi_volume()) {
133
+ const auto &parts = entry.multi_volume_parts().values;
134
+ if (index < parts.size()) {
135
+ return &parts[index];
136
+ }
137
+ return nullptr;
138
+ }
139
+
140
+ return nullptr;
141
+ }
142
+
143
+ std::size_t pathhierarchy_volume_size(const PathHierarchy &logical) {
144
+ if (logical.empty()) {
145
+ return 0;
146
+ }
147
+ const PathEntry &tail = logical.back();
148
+ if (!tail.is_multi_volume()) {
149
+ return 1;
150
+ }
151
+ const auto &parts = tail.multi_volume_parts().values;
152
+ return parts.size();
153
+ }
154
+
155
+ std::string pathhierarchy_volume_entry_name(const PathHierarchy &logical, std::size_t index) {
156
+ if (logical.empty()) {
157
+ return {};
158
+ }
159
+ const PathEntry &tail = logical.back();
160
+ if (!tail.is_multi_volume()) {
161
+ if (index != 0) {
162
+ return {};
163
+ }
164
+
165
+ std::string entry_name;
166
+ if (!flatten_single_entry(tail, entry_name)) {
167
+ return {};
168
+ }
169
+ return entry_name;
170
+ }
171
+
172
+ const auto &parts = tail.multi_volume_parts().values;
173
+ if (index >= parts.size()) {
174
+ return {};
175
+ }
176
+ return parts[index];
177
+ }
178
+
179
+ bool pathhierarchy_is_multivolume(const PathHierarchy &hierarchy) {
180
+ if (hierarchy.empty()) {
181
+ return false;
182
+ }
183
+ return hierarchy.back().is_multi_volume();
184
+ }
185
+
186
+ PathHierarchy pathhierarchy_select_single_part(const PathHierarchy &logical, std::size_t index) {
187
+ if (logical.empty()) {
188
+ return {};
189
+ }
190
+
191
+ PathHierarchy result = parent_hierarchy(logical);
192
+ append_single(result, pathhierarchy_volume_entry_name(logical, index));
193
+ return result;
194
+ }
195
+
196
+ void sort_hierarchies(std::vector<PathHierarchy> &hierarchies) {
197
+ std::sort(hierarchies.begin(), hierarchies.end(), [](const PathHierarchy &lhs, const PathHierarchy &rhs) { return archive_r::compare_hierarchies(lhs, rhs) < 0; });
198
+ }
199
+
200
+ bool flatten_entry_to_string(const PathEntry &entry, std::string &output) {
201
+ if (entry.is_single()) {
202
+ output = entry.single_value();
203
+ return true;
204
+ }
205
+
206
+ if (entry.is_nested()) {
207
+ std::string result;
208
+ bool first = true;
209
+ for (const auto &child : entry.nested_nodes()) {
210
+ std::string component;
211
+ if (!flatten_entry_to_string(child, component)) {
212
+ return false;
213
+ }
214
+ if (component.empty()) {
215
+ return false;
216
+ }
217
+ if (!first) {
218
+ result.push_back('/');
219
+ }
220
+ result += component;
221
+ first = false;
222
+ }
223
+ output = result;
224
+ return !result.empty();
225
+ }
226
+
227
+ return false;
228
+ }
229
+
230
+ bool entry_name_from_component(const PathEntry &entry, std::string &output) {
231
+ if (entry.is_multi_volume()) {
232
+ const auto &parts = entry.multi_volume_parts().values;
233
+ if (parts.empty()) {
234
+ return false;
235
+ }
236
+ output = parts.front();
237
+ return true;
238
+ }
239
+
240
+ return flatten_entry_to_string(entry, output);
241
+ }
242
+
243
+ PathHierarchy merge_multi_volume_sources(const std::vector<PathHierarchy> &sources) {
244
+ CollapseSegments segments;
245
+ if (!determine_multi_volume_segments(sources, segments)) {
246
+ return {};
247
+ }
248
+
249
+ std::vector<std::string> parts;
250
+ if (!collect_multi_volume_parts(sources, segments, parts)) {
251
+ return {};
252
+ }
253
+
254
+ PathHierarchy result = segments.prefix;
255
+ result.reserve(result.size() + 1 + segments.suffix.size());
256
+ result.emplace_back(PathEntry::multi_volume(std::move(parts)));
257
+ result.insert(result.end(), segments.suffix.begin(), segments.suffix.end());
258
+ return result;
259
+ }
260
+
261
+ std::string path_entry_display(const PathEntry &entry) {
262
+ if (entry.is_single()) {
263
+ return entry.single_value();
264
+ }
265
+ if (entry.is_multi_volume()) {
266
+ std::string value = "[";
267
+ bool first = true;
268
+ for (const auto &part : entry.multi_volume_parts().values) {
269
+ if (!first) {
270
+ value.push_back('|');
271
+ }
272
+ value += part;
273
+ first = false;
274
+ }
275
+ value.push_back(']');
276
+ return value;
277
+ }
278
+ std::string value = "{";
279
+ bool first = true;
280
+ for (const auto &child : entry.nested_nodes()) {
281
+ if (!first) {
282
+ value.push_back('/');
283
+ }
284
+ value += path_entry_display(child);
285
+ first = false;
286
+ }
287
+ value.push_back('}');
288
+ return value;
289
+ }
290
+
291
+ std::string hierarchy_display(const PathHierarchy &hierarchy) {
292
+ std::string result;
293
+ bool first = true;
294
+ for (const auto &component : hierarchy) {
295
+ if (!first) {
296
+ result.push_back('/');
297
+ }
298
+ result += path_entry_display(component);
299
+ first = false;
300
+ }
301
+ return result;
302
+ }
303
+
304
+ } // namespace archive_r