omnizip 0.3.1

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 (511) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +754 -0
  5. data/COPYING +502 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +12 -0
  8. data/README.adoc +1045 -0
  9. data/Rakefile +12 -0
  10. data/benchmark/README.md +260 -0
  11. data/benchmark/benchmark_suite.rb +125 -0
  12. data/benchmark/compression_bench.rb +181 -0
  13. data/benchmark/filter_bench.rb +180 -0
  14. data/benchmark/models/benchmark_result.rb +59 -0
  15. data/benchmark/models/comparison_result.rb +69 -0
  16. data/benchmark/profile_suite.rb +167 -0
  17. data/benchmark/reporter.rb +150 -0
  18. data/benchmark/run_benchmarks.rb +66 -0
  19. data/benchmark/test_data.rb +137 -0
  20. data/config/formats/rar3_spec.yml +91 -0
  21. data/config/formats/rar5_spec.yml +102 -0
  22. data/docs/.github/workflows/docs.yml +142 -0
  23. data/docs/.gitignore +21 -0
  24. data/docs/.lychee.toml +67 -0
  25. data/docs/Gemfile +13 -0
  26. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  27. data/docs/README.md +101 -0
  28. data/docs/_config.yml +112 -0
  29. data/docs/assets/logo.svg +1 -0
  30. data/docs/assets/omnizip-logo.pdf +1540 -11
  31. data/docs/comparison/feature-matrix.adoc +694 -0
  32. data/docs/comparison/index.adoc +113 -0
  33. data/docs/comparison/vs-7zip.adoc +309 -0
  34. data/docs/comparison/vs-peazip.adoc +77 -0
  35. data/docs/comparison/vs-rubyzip.adoc +342 -0
  36. data/docs/comparison/vs-winrar.adoc +100 -0
  37. data/docs/compatibility.adoc +579 -0
  38. data/docs/concepts/index.adoc +129 -0
  39. data/docs/developer/architecture.adoc +256 -0
  40. data/docs/developer/contributing.adoc +158 -0
  41. data/docs/developer/index.adoc +25 -0
  42. data/docs/developer/testing.adoc +212 -0
  43. data/docs/getting-started/basic-usage.adoc +271 -0
  44. data/docs/getting-started/index.adoc +42 -0
  45. data/docs/getting-started/installation.adoc +138 -0
  46. data/docs/getting-started/quick-start.adoc +185 -0
  47. data/docs/getting-started/your-first-archive.adoc +218 -0
  48. data/docs/guides/advanced-features/encryption.adoc +300 -0
  49. data/docs/guides/advanced-features/index.adoc +49 -0
  50. data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
  51. data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
  52. data/docs/guides/advanced-features/streaming.adoc +212 -0
  53. data/docs/guides/archive-formats/gzip-format.adoc +107 -0
  54. data/docs/guides/archive-formats/index.adoc +130 -0
  55. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  56. data/docs/guides/archive-formats/rar5.adoc +521 -0
  57. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  58. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  59. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  60. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  61. data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
  62. data/docs/guides/compression-algorithms/deflate.adoc +319 -0
  63. data/docs/guides/compression-algorithms/index.adoc +190 -0
  64. data/docs/guides/compression-algorithms/lzma.adoc +398 -0
  65. data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
  66. data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
  67. data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
  68. data/docs/guides/creating-archives.adoc +354 -0
  69. data/docs/guides/extracting-archives.adoc +53 -0
  70. data/docs/guides/format-conversion.adoc +64 -0
  71. data/docs/guides/index.adoc +49 -0
  72. data/docs/guides/migration-rubyzip.adoc +217 -0
  73. data/docs/guides/parity-archives.adoc +605 -0
  74. data/docs/guides/performance-tuning.adoc +88 -0
  75. data/docs/index.adoc +218 -0
  76. data/docs/lychee.toml +67 -0
  77. data/docs/reference/api/overview.adoc +188 -0
  78. data/docs/reference/cli/compress-command.adoc +114 -0
  79. data/docs/reference/cli/overview.adoc +140 -0
  80. data/docs/reference/index.adoc +26 -0
  81. data/docs/resources/faq.adoc +185 -0
  82. data/docs/resources/quick-reference.adoc +222 -0
  83. data/docs/troubleshooting/index.adoc +208 -0
  84. data/examples/api_comparison.rb +205 -0
  85. data/examples/deflate64_example.rb +96 -0
  86. data/examples/par2_demo.rb +121 -0
  87. data/examples/quick_start_native.rb +150 -0
  88. data/examples/quick_start_rubyzip.rb +115 -0
  89. data/examples/rubyzip_compatibility_demo.rb +194 -0
  90. data/exe/omnizip +27 -0
  91. data/lib/omnizip/algorithm.rb +130 -0
  92. data/lib/omnizip/algorithm_registry.rb +86 -0
  93. data/lib/omnizip/algorithms/.keep +0 -0
  94. data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
  95. data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
  96. data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
  97. data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
  98. data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
  99. data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
  100. data/lib/omnizip/algorithms/bzip2.rb +130 -0
  101. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  102. data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
  103. data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
  104. data/lib/omnizip/algorithms/deflate.rb +128 -0
  105. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  106. data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
  107. data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
  108. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
  109. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
  110. data/lib/omnizip/algorithms/deflate64.rb +109 -0
  111. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  112. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  113. data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
  114. data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
  115. data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
  116. data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
  117. data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
  118. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
  119. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
  120. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
  121. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
  122. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  123. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  124. data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
  125. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  126. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
  127. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
  128. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  129. data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
  130. data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
  131. data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
  132. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  133. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
  134. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
  135. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
  136. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
  137. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
  138. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
  139. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  140. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
  141. data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
  142. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
  143. data/lib/omnizip/algorithms/lzma.rb +238 -0
  144. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
  145. data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
  146. data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
  147. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
  148. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  149. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
  150. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  151. data/lib/omnizip/algorithms/lzma2.rb +141 -0
  152. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  153. data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
  154. data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
  155. data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
  156. data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
  157. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  158. data/lib/omnizip/algorithms/ppmd7.rb +116 -0
  159. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  160. data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
  161. data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
  162. data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
  163. data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
  164. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  165. data/lib/omnizip/algorithms/ppmd8.rb +82 -0
  166. data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
  167. data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
  168. data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
  169. data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
  170. data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
  171. data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
  172. data/lib/omnizip/algorithms/zstandard.rb +138 -0
  173. data/lib/omnizip/buffer/memory_archive.rb +251 -0
  174. data/lib/omnizip/buffer/memory_extractor.rb +224 -0
  175. data/lib/omnizip/buffer.rb +176 -0
  176. data/lib/omnizip/checksum_registry.rb +114 -0
  177. data/lib/omnizip/checksums/crc32.rb +100 -0
  178. data/lib/omnizip/checksums/crc64.rb +101 -0
  179. data/lib/omnizip/checksums/crc_base.rb +158 -0
  180. data/lib/omnizip/checksums/verifier.rb +131 -0
  181. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  182. data/lib/omnizip/chunked/reader.rb +78 -0
  183. data/lib/omnizip/chunked/writer.rb +120 -0
  184. data/lib/omnizip/chunked.rb +129 -0
  185. data/lib/omnizip/cli/output_formatter.rb +104 -0
  186. data/lib/omnizip/cli.rb +572 -0
  187. data/lib/omnizip/commands/.keep +0 -0
  188. data/lib/omnizip/commands/archive_create_command.rb +427 -0
  189. data/lib/omnizip/commands/archive_extract_command.rb +272 -0
  190. data/lib/omnizip/commands/archive_list_command.rb +218 -0
  191. data/lib/omnizip/commands/archive_repair_command.rb +131 -0
  192. data/lib/omnizip/commands/archive_verify_command.rb +117 -0
  193. data/lib/omnizip/commands/compress_command.rb +117 -0
  194. data/lib/omnizip/commands/decompress_command.rb +120 -0
  195. data/lib/omnizip/commands/list_command.rb +53 -0
  196. data/lib/omnizip/commands/metadata_command.rb +153 -0
  197. data/lib/omnizip/commands/parity_create_command.rb +122 -0
  198. data/lib/omnizip/commands/parity_repair_command.rb +122 -0
  199. data/lib/omnizip/commands/parity_verify_command.rb +124 -0
  200. data/lib/omnizip/commands/profile_list_command.rb +56 -0
  201. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  202. data/lib/omnizip/convenience.rb +359 -0
  203. data/lib/omnizip/converter/conversion_registry.rb +49 -0
  204. data/lib/omnizip/converter/conversion_strategy.rb +121 -0
  205. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
  206. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
  207. data/lib/omnizip/converter.rb +105 -0
  208. data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
  209. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  210. data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
  211. data/lib/omnizip/crypto/aes256.rb +102 -0
  212. data/lib/omnizip/error.rb +106 -0
  213. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
  214. data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
  215. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  216. data/lib/omnizip/eta/sample_history.rb +143 -0
  217. data/lib/omnizip/eta/time_estimator.rb +106 -0
  218. data/lib/omnizip/eta.rb +63 -0
  219. data/lib/omnizip/extraction/filter_chain.rb +177 -0
  220. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  221. data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
  222. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  223. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  224. data/lib/omnizip/extraction/selective_extractor.rb +240 -0
  225. data/lib/omnizip/extraction.rb +111 -0
  226. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  227. data/lib/omnizip/file_type.rb +113 -0
  228. data/lib/omnizip/filter.rb +139 -0
  229. data/lib/omnizip/filter_pipeline.rb +108 -0
  230. data/lib/omnizip/filter_registry.rb +166 -0
  231. data/lib/omnizip/filters/bcj.rb +279 -0
  232. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  233. data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
  234. data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
  235. data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
  236. data/lib/omnizip/filters/bcj2.rb +99 -0
  237. data/lib/omnizip/filters/bcj_arm.rb +176 -0
  238. data/lib/omnizip/filters/bcj_arm64.rb +244 -0
  239. data/lib/omnizip/filters/bcj_ia64.rb +196 -0
  240. data/lib/omnizip/filters/bcj_ppc.rb +190 -0
  241. data/lib/omnizip/filters/bcj_sparc.rb +176 -0
  242. data/lib/omnizip/filters/bcj_x86.rb +193 -0
  243. data/lib/omnizip/filters/delta.rb +196 -0
  244. data/lib/omnizip/filters/filter_base.rb +72 -0
  245. data/lib/omnizip/filters/registry.rb +123 -0
  246. data/lib/omnizip/filters/xz_delta.rb +258 -0
  247. data/lib/omnizip/format_detector.rb +162 -0
  248. data/lib/omnizip/format_registry.rb +59 -0
  249. data/lib/omnizip/formats/.keep +0 -0
  250. data/lib/omnizip/formats/bzip2_file.rb +172 -0
  251. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  252. data/lib/omnizip/formats/cpio/entry.rb +385 -0
  253. data/lib/omnizip/formats/cpio/reader.rb +196 -0
  254. data/lib/omnizip/formats/cpio/writer.rb +234 -0
  255. data/lib/omnizip/formats/cpio.rb +140 -0
  256. data/lib/omnizip/formats/format_spec_loader.rb +230 -0
  257. data/lib/omnizip/formats/gzip.rb +238 -0
  258. data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
  259. data/lib/omnizip/formats/iso/directory_record.rb +152 -0
  260. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  261. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  262. data/lib/omnizip/formats/iso/reader.rb +197 -0
  263. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  264. data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
  265. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  266. data/lib/omnizip/formats/iso/writer.rb +530 -0
  267. data/lib/omnizip/formats/iso.rb +140 -0
  268. data/lib/omnizip/formats/lzip.rb +175 -0
  269. data/lib/omnizip/formats/lzma_alone.rb +171 -0
  270. data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
  271. data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
  272. data/lib/omnizip/formats/rar/block_parser.rb +243 -0
  273. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  274. data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
  275. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
  276. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
  277. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  278. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  279. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  280. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  281. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
  282. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
  283. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
  284. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  285. data/lib/omnizip/formats/rar/constants.rb +82 -0
  286. data/lib/omnizip/formats/rar/decompressor.rb +238 -0
  287. data/lib/omnizip/formats/rar/external_writer.rb +312 -0
  288. data/lib/omnizip/formats/rar/header.rb +192 -0
  289. data/lib/omnizip/formats/rar/license_validator.rb +109 -0
  290. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  291. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  292. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  293. data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
  294. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
  295. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
  296. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  297. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  298. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
  299. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  300. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
  301. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  302. data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
  303. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  304. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  305. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  306. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  307. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  308. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
  309. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  310. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
  311. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
  312. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
  313. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  314. data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
  315. data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
  316. data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
  317. data/lib/omnizip/formats/rar/reader.rb +366 -0
  318. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  319. data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
  320. data/lib/omnizip/formats/rar/writer.rb +431 -0
  321. data/lib/omnizip/formats/rar.rb +205 -0
  322. data/lib/omnizip/formats/rar3/compressor.rb +73 -0
  323. data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
  324. data/lib/omnizip/formats/rar3/reader.rb +386 -0
  325. data/lib/omnizip/formats/rar3/writer.rb +219 -0
  326. data/lib/omnizip/formats/rar5/compressor.rb +73 -0
  327. data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
  328. data/lib/omnizip/formats/rar5/reader.rb +342 -0
  329. data/lib/omnizip/formats/rar5/writer.rb +214 -0
  330. data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
  331. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  332. data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
  333. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
  334. data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
  335. data/lib/omnizip/formats/seven_zip/header.rb +106 -0
  336. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
  337. data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
  338. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  339. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
  340. data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
  341. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  342. data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
  343. data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
  344. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
  345. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
  346. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  347. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
  348. data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
  349. data/lib/omnizip/formats/seven_zip.rb +93 -0
  350. data/lib/omnizip/formats/tar/constants.rb +73 -0
  351. data/lib/omnizip/formats/tar/entry.rb +94 -0
  352. data/lib/omnizip/formats/tar/header.rb +168 -0
  353. data/lib/omnizip/formats/tar/reader.rb +121 -0
  354. data/lib/omnizip/formats/tar/writer.rb +216 -0
  355. data/lib/omnizip/formats/tar.rb +84 -0
  356. data/lib/omnizip/formats/xz/reader.rb +116 -0
  357. data/lib/omnizip/formats/xz.rb +237 -0
  358. data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
  359. data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
  360. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  361. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
  362. data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
  363. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  364. data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
  365. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
  366. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
  367. data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
  368. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
  369. data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
  370. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
  371. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  372. data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
  373. data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
  374. data/lib/omnizip/formats/zip/constants.rb +69 -0
  375. data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
  376. data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
  377. data/lib/omnizip/formats/zip/reader.rb +250 -0
  378. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  379. data/lib/omnizip/formats/zip/writer.rb +375 -0
  380. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
  381. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
  382. data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
  383. data/lib/omnizip/formats/zip.rb +50 -0
  384. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  385. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  386. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  387. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  388. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  389. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
  390. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
  391. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
  392. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
  393. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
  394. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
  395. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
  396. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
  397. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
  398. data/lib/omnizip/io/buffered_input.rb +146 -0
  399. data/lib/omnizip/io/buffered_output.rb +105 -0
  400. data/lib/omnizip/io/stream_manager.rb +115 -0
  401. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  402. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  403. data/lib/omnizip/link_handler.rb +124 -0
  404. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  405. data/lib/omnizip/metadata/entry_metadata.rb +146 -0
  406. data/lib/omnizip/metadata/metadata_editor.rb +171 -0
  407. data/lib/omnizip/metadata/metadata_registry.rb +64 -0
  408. data/lib/omnizip/metadata/metadata_validator.rb +99 -0
  409. data/lib/omnizip/metadata.rb +57 -0
  410. data/lib/omnizip/models/.keep +0 -0
  411. data/lib/omnizip/models/algorithm_metadata.rb +73 -0
  412. data/lib/omnizip/models/compression_options.rb +71 -0
  413. data/lib/omnizip/models/conversion_options.rb +87 -0
  414. data/lib/omnizip/models/conversion_result.rb +135 -0
  415. data/lib/omnizip/models/eta_result.rb +46 -0
  416. data/lib/omnizip/models/extraction_rule.rb +115 -0
  417. data/lib/omnizip/models/filter_chain.rb +144 -0
  418. data/lib/omnizip/models/filter_config.rb +183 -0
  419. data/lib/omnizip/models/match_result.rb +124 -0
  420. data/lib/omnizip/models/optimization_suggestion.rb +91 -0
  421. data/lib/omnizip/models/parallel_options.rb +104 -0
  422. data/lib/omnizip/models/performance_result.rb +79 -0
  423. data/lib/omnizip/models/profile_report.rb +82 -0
  424. data/lib/omnizip/models/progress_options.rb +38 -0
  425. data/lib/omnizip/models/split_options.rb +116 -0
  426. data/lib/omnizip/optimization_registry.rb +81 -0
  427. data/lib/omnizip/parallel/job_queue.rb +209 -0
  428. data/lib/omnizip/parallel/job_scheduler.rb +203 -0
  429. data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
  430. data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
  431. data/lib/omnizip/parallel/worker_pool.rb +223 -0
  432. data/lib/omnizip/parallel.rb +149 -0
  433. data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
  434. data/lib/omnizip/parity/galois16.rb +145 -0
  435. data/lib/omnizip/parity/models/creator_packet.rb +73 -0
  436. data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
  437. data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
  438. data/lib/omnizip/parity/models/main_packet.rb +128 -0
  439. data/lib/omnizip/parity/models/packet.rb +156 -0
  440. data/lib/omnizip/parity/models/packet_registry.rb +109 -0
  441. data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
  442. data/lib/omnizip/parity/par2_creator.rb +531 -0
  443. data/lib/omnizip/parity/par2_repairer.rb +407 -0
  444. data/lib/omnizip/parity/par2_verifier.rb +364 -0
  445. data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
  446. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  447. data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
  448. data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
  449. data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
  450. data/lib/omnizip/parity.rb +186 -0
  451. data/lib/omnizip/password/encryption_registry.rb +65 -0
  452. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  453. data/lib/omnizip/password/password_validator.rb +129 -0
  454. data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
  455. data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
  456. data/lib/omnizip/password.rb +87 -0
  457. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  458. data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
  459. data/lib/omnizip/pipe.rb +121 -0
  460. data/lib/omnizip/platform/ntfs_streams.rb +201 -0
  461. data/lib/omnizip/platform.rb +189 -0
  462. data/lib/omnizip/profile/archive_profile.rb +39 -0
  463. data/lib/omnizip/profile/balanced_profile.rb +33 -0
  464. data/lib/omnizip/profile/binary_profile.rb +36 -0
  465. data/lib/omnizip/profile/compression_profile.rb +158 -0
  466. data/lib/omnizip/profile/custom_profile.rb +157 -0
  467. data/lib/omnizip/profile/fast_profile.rb +33 -0
  468. data/lib/omnizip/profile/maximum_profile.rb +33 -0
  469. data/lib/omnizip/profile/profile_detector.rb +110 -0
  470. data/lib/omnizip/profile/profile_registry.rb +161 -0
  471. data/lib/omnizip/profile/text_profile.rb +36 -0
  472. data/lib/omnizip/profile.rb +190 -0
  473. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  474. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  475. data/lib/omnizip/profiler/report_generator.rb +169 -0
  476. data/lib/omnizip/profiler.rb +204 -0
  477. data/lib/omnizip/progress/callback_reporter.rb +36 -0
  478. data/lib/omnizip/progress/console_reporter.rb +62 -0
  479. data/lib/omnizip/progress/log_reporter.rb +91 -0
  480. data/lib/omnizip/progress/operation_progress.rb +118 -0
  481. data/lib/omnizip/progress/progress_bar.rb +156 -0
  482. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  483. data/lib/omnizip/progress/progress_tracker.rb +190 -0
  484. data/lib/omnizip/progress/silent_reporter.rb +24 -0
  485. data/lib/omnizip/progress.rb +127 -0
  486. data/lib/omnizip/rubyzip_compat.rb +63 -0
  487. data/lib/omnizip/temp/safe_extract.rb +168 -0
  488. data/lib/omnizip/temp/temp_file.rb +124 -0
  489. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  490. data/lib/omnizip/temp.rb +181 -0
  491. data/lib/omnizip/version.rb +5 -0
  492. data/lib/omnizip/zip/entry.rb +156 -0
  493. data/lib/omnizip/zip/file.rb +485 -0
  494. data/lib/omnizip/zip/input_stream.rb +273 -0
  495. data/lib/omnizip/zip/output_stream.rb +324 -0
  496. data/lib/omnizip.rb +156 -0
  497. data/readme-docs/advanced-features.adoc +515 -0
  498. data/readme-docs/api-usage.adoc +444 -0
  499. data/readme-docs/architecture.adoc +449 -0
  500. data/readme-docs/archive-formats.adoc +479 -0
  501. data/readme-docs/cli-usage.adoc +222 -0
  502. data/readme-docs/compression-algorithms.adoc +442 -0
  503. data/readme-docs/compression-profiles.adoc +247 -0
  504. data/readme-docs/encryption-checksums.adoc +328 -0
  505. data/readme-docs/format-converter.adoc +325 -0
  506. data/readme-docs/installation.adoc +228 -0
  507. data/readme-docs/par2-archives.adoc +608 -0
  508. data/readme-docs/performance-profiler.adoc +389 -0
  509. data/readme-docs/preprocessing-filters.adoc +280 -0
  510. data/xz-file-format-1.2.1.txt +1174 -0
  511. metadata +617 -0
@@ -0,0 +1,180 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark"
4
+ require "tempfile"
5
+ require "fileutils"
6
+ require_relative "models/benchmark_result"
7
+ require_relative "models/comparison_result"
8
+
9
+ module Benchmark
10
+ # Benchmarks filters combined with compression
11
+ class FilterBench
12
+ FILTERS = %w[bcj delta].freeze
13
+ BASE_ALGORITHM = "lzma"
14
+ ITERATIONS = 3
15
+
16
+ attr_reader :verbose
17
+
18
+ def initialize(verbose: false)
19
+ @verbose = verbose
20
+ @seven_zip_available = check_seven_zip_availability
21
+ end
22
+
23
+ def seven_zip_available?
24
+ @seven_zip_available
25
+ end
26
+
27
+ def benchmark_filter(filter, input_file, input_type)
28
+ puts "Benchmarking #{filter} filter..." if verbose
29
+
30
+ omnizip_result = benchmark_omnizip_with_filter(filter, input_file,
31
+ input_type)
32
+ seven_zip_result = if seven_zip_available?
33
+ benchmark_7z_with_filter(filter, input_file,
34
+ input_type)
35
+ else
36
+ create_unavailable_result(filter, input_file,
37
+ input_type)
38
+ end
39
+
40
+ Models::ComparisonResult.new(
41
+ test_name: "#{filter}_filter_#{input_type}",
42
+ omnizip_result: omnizip_result,
43
+ seven_zip_result: seven_zip_result,
44
+ )
45
+ end
46
+
47
+ private
48
+
49
+ def check_seven_zip_availability
50
+ system("which 7z > /dev/null 2>&1") ||
51
+ system("which 7za > /dev/null 2>&1")
52
+ end
53
+
54
+ def get_7z_command
55
+ @get_7z_command ||= if system("which 7z > /dev/null 2>&1")
56
+ "7z"
57
+ elsif system("which 7za > /dev/null 2>&1")
58
+ "7za"
59
+ end
60
+ end
61
+
62
+ def benchmark_omnizip_with_filter(filter, input_file, input_type)
63
+ input_size = File.size(input_file)
64
+ compressed_file = create_temp_file(".7z")
65
+
66
+ begin
67
+ time = measure_time do
68
+ compress_with_filter(filter, input_file, compressed_file)
69
+ end
70
+
71
+ compressed_size = if File.exist?(compressed_file)
72
+ File.size(compressed_file)
73
+ end
74
+
75
+ Models::BenchmarkResult.new(
76
+ algorithm: "#{filter}+#{BASE_ALGORITHM}",
77
+ input_size: input_size,
78
+ input_type: input_type,
79
+ compressed_size: compressed_size,
80
+ compression_time: time,
81
+ )
82
+ rescue StandardError => e
83
+ Models::BenchmarkResult.new(
84
+ algorithm: "#{filter}+#{BASE_ALGORITHM}",
85
+ input_size: input_size,
86
+ input_type: input_type,
87
+ error: e.message,
88
+ )
89
+ ensure
90
+ FileUtils.rm_f(compressed_file)
91
+ end
92
+ end
93
+
94
+ def benchmark_7z_with_filter(filter, input_file, input_type)
95
+ input_size = File.size(input_file)
96
+ compressed_file = create_temp_file(".7z")
97
+
98
+ begin
99
+ time = measure_time do
100
+ compress_with_7z_filter(filter, input_file, compressed_file)
101
+ end
102
+
103
+ compressed_size = if File.exist?(compressed_file)
104
+ File.size(compressed_file)
105
+ end
106
+
107
+ Models::BenchmarkResult.new(
108
+ algorithm: "#{filter}+#{BASE_ALGORITHM}",
109
+ input_size: input_size,
110
+ input_type: input_type,
111
+ compressed_size: compressed_size,
112
+ compression_time: time,
113
+ )
114
+ rescue StandardError => e
115
+ Models::BenchmarkResult.new(
116
+ algorithm: "#{filter}+#{BASE_ALGORITHM}",
117
+ input_size: input_size,
118
+ input_type: input_type,
119
+ error: e.message,
120
+ )
121
+ ensure
122
+ FileUtils.rm_f(compressed_file)
123
+ end
124
+ end
125
+
126
+ def create_unavailable_result(filter, input_file, input_type)
127
+ Models::BenchmarkResult.new(
128
+ algorithm: "#{filter}+#{BASE_ALGORITHM}",
129
+ input_size: File.size(input_file),
130
+ input_type: input_type,
131
+ error: "7-Zip not available",
132
+ )
133
+ end
134
+
135
+ def compress_with_filter(filter, input_file, output_file)
136
+ require_relative "../lib/omnizip"
137
+
138
+ filter_class = case filter
139
+ when "bcj" then Omnizip::Filters::BCJx86
140
+ when "delta" then Omnizip::Filters::Delta
141
+ else raise "Unknown filter: #{filter}"
142
+ end
143
+
144
+ input = File.binread(input_file)
145
+ filtered = filter_class.encode(input)
146
+ compressed = Omnizip::Algorithms::LZMA.compress(filtered)
147
+ File.binwrite(output_file, compressed)
148
+ end
149
+
150
+ def compress_with_7z_filter(filter, input_file, output_file)
151
+ filter_flag = case filter
152
+ when "bcj" then "BCJ"
153
+ when "delta" then "Delta"
154
+ else raise "Unknown filter: #{filter}"
155
+ end
156
+
157
+ cmd = "#{get_7z_command} a -m0=LZMA -mf=#{filter_flag} -mx=5 " \
158
+ "#{output_file} #{input_file} > /dev/null 2>&1"
159
+ success = system(cmd)
160
+ raise "7z compression with filter failed" unless success
161
+ end
162
+
163
+ def measure_time(&block)
164
+ times = []
165
+ ITERATIONS.times do
166
+ time = ::Benchmark.realtime(&block)
167
+ times << time
168
+ end
169
+ times.sum / times.size
170
+ end
171
+
172
+ def create_temp_file(extension)
173
+ temp = Tempfile.new(["benchmark", extension])
174
+ path = temp.path
175
+ temp.close
176
+ temp.unlink
177
+ path
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Benchmark
4
+ module Models
5
+ # Represents the result of a single benchmark test
6
+ class BenchmarkResult
7
+ attr_reader :algorithm, :input_size, :input_type, :compressed_size,
8
+ :compression_time, :decompression_time, :error
9
+
10
+ def initialize(
11
+ algorithm:,
12
+ input_size:,
13
+ input_type:,
14
+ compressed_size: nil,
15
+ compression_time: nil,
16
+ decompression_time: nil,
17
+ error: nil
18
+ )
19
+ @algorithm = algorithm
20
+ @input_size = input_size
21
+ @input_type = input_type
22
+ @compressed_size = compressed_size
23
+ @compression_time = compression_time
24
+ @decompression_time = decompression_time
25
+ @error = error
26
+ end
27
+
28
+ def success?
29
+ error.nil?
30
+ end
31
+
32
+ def compression_ratio
33
+ return nil unless success? && compressed_size && input_size.positive?
34
+
35
+ input_size.to_f / compressed_size
36
+ end
37
+
38
+ def compression_percentage
39
+ return nil unless compression_ratio
40
+
41
+ (1.0 - (1.0 / compression_ratio)) * 100
42
+ end
43
+
44
+ def to_h
45
+ {
46
+ algorithm: algorithm,
47
+ input_size: input_size,
48
+ input_type: input_type,
49
+ compressed_size: compressed_size,
50
+ compression_time: compression_time,
51
+ decompression_time: decompression_time,
52
+ compression_ratio: compression_ratio,
53
+ compression_percentage: compression_percentage,
54
+ error: error,
55
+ }
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "benchmark_result"
4
+
5
+ module Benchmark
6
+ module Models
7
+ # Represents a comparison between omnizip and 7-Zip results
8
+ class ComparisonResult
9
+ attr_reader :test_name, :omnizip_result, :seven_zip_result
10
+
11
+ def initialize(test_name:, omnizip_result:, seven_zip_result:)
12
+ @test_name = test_name
13
+ @omnizip_result = omnizip_result
14
+ @seven_zip_result = seven_zip_result
15
+ end
16
+
17
+ def size_difference_bytes
18
+ return nil unless both_successful?
19
+
20
+ omnizip_result.compressed_size - seven_zip_result.compressed_size
21
+ end
22
+
23
+ def size_difference_percentage
24
+ return nil unless both_successful?
25
+
26
+ ((size_difference_bytes.to_f / seven_zip_result.compressed_size) *
27
+ 100).round(2)
28
+ end
29
+
30
+ def compression_speed_ratio
31
+ return nil unless both_successful?
32
+
33
+ return nil if seven_zip_result.compression_time.nil? ||
34
+ seven_zip_result.compression_time.zero?
35
+
36
+ (omnizip_result.compression_time /
37
+ seven_zip_result.compression_time).round(2)
38
+ end
39
+
40
+ def decompression_speed_ratio
41
+ return nil unless both_successful?
42
+
43
+ return nil if seven_zip_result.decompression_time.nil? ||
44
+ seven_zip_result.decompression_time.zero?
45
+
46
+ (omnizip_result.decompression_time /
47
+ seven_zip_result.decompression_time).round(2)
48
+ end
49
+
50
+ def both_successful?
51
+ omnizip_result.success? && seven_zip_result.success?
52
+ end
53
+
54
+ def to_h
55
+ {
56
+ test_name: test_name,
57
+ omnizip: omnizip_result.to_h,
58
+ seven_zip: seven_zip_result.to_h,
59
+ comparison: {
60
+ size_difference_bytes: size_difference_bytes,
61
+ size_difference_percentage: size_difference_percentage,
62
+ compression_speed_ratio: compression_speed_ratio,
63
+ decompression_speed_ratio: decompression_speed_ratio,
64
+ },
65
+ }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require_relative "../lib/omnizip"
5
+ require_relative "../lib/omnizip/profiler"
6
+ require_relative "../lib/omnizip/profiler/method_profiler"
7
+ require_relative "../lib/omnizip/profiler/memory_profiler"
8
+ require_relative "../lib/omnizip/profiler/report_generator"
9
+ require_relative "test_data"
10
+
11
+ module Benchmark
12
+ # Profiling suite for performance analysis of compression algorithms
13
+ class ProfileSuite
14
+ attr_reader :profiler, :verbose
15
+
16
+ def initialize(verbose: false)
17
+ @verbose = verbose
18
+ @profiler = Omnizip::Profiler.new(profile_name: "compression_profile")
19
+ @test_data = TestData.new
20
+
21
+ # Register profiler strategies
22
+ @profiler.register_profiler(:method,
23
+ Omnizip::Profiler::MethodProfiler.new)
24
+ @profiler.register_profiler(:memory,
25
+ Omnizip::Profiler::MemoryProfiler.new)
26
+ end
27
+
28
+ def run_all
29
+ puts "Starting performance profiling suite..." if verbose
30
+
31
+ generate_test_data
32
+ profile_lzma_encoding
33
+ profile_lzma_decoding
34
+ profile_range_coder
35
+ profile_bwt_transform
36
+ cleanup_test_data
37
+
38
+ analyze_results
39
+ self
40
+ end
41
+
42
+ def profile_lzma_encoding
43
+ puts "\nProfiling LZMA encoding..." if verbose
44
+
45
+ test_file = File.join(@test_data.data_dir, "text_10240.dat")
46
+ data = File.binread(test_file)
47
+
48
+ @profiler.profile("LZMA::encode", profiler_type: :method) do
49
+ output = StringIO.new
50
+ encoder = Omnizip::Algorithms::LZMA::Encoder.new(output)
51
+ encoder.encode_stream(data)
52
+ end
53
+ end
54
+
55
+ def profile_lzma_decoding
56
+ puts "Profiling LZMA decoding..." if verbose
57
+
58
+ test_file = File.join(@test_data.data_dir, "text_10240.dat")
59
+ data = File.binread(test_file)
60
+
61
+ # Encode data first
62
+ encoded_output = StringIO.new
63
+ encoder = Omnizip::Algorithms::LZMA::Encoder.new(encoded_output)
64
+ encoder.encode_stream(data)
65
+ encoded = encoded_output.string
66
+
67
+ @profiler.profile("LZMA::decode", profiler_type: :method) do
68
+ input = StringIO.new(encoded)
69
+ decoder = Omnizip::Algorithms::LZMA::Decoder.new(input)
70
+ decoder.decode_stream
71
+ end
72
+ end
73
+
74
+ def profile_range_coder
75
+ puts "Profiling Range Coder..." if verbose
76
+
77
+ data = Array.new(1000) { rand(256) }
78
+
79
+ @profiler.profile("RangeCoder::encode", profiler_type: :method) do
80
+ output = StringIO.new
81
+ encoder = Omnizip::Algorithms::LZMA::RangeEncoder.new(output)
82
+ data.each { |byte| encoder.encode_direct_bits(byte, 8) }
83
+ encoder.flush
84
+ end
85
+ end
86
+
87
+ def profile_bwt_transform
88
+ puts "Profiling BWT transform..." if verbose
89
+
90
+ test_file = File.join(@test_data.data_dir, "text_10240.dat")
91
+ data = File.binread(test_file)
92
+
93
+ @profiler.profile("BWT::encode", profiler_type: :method) do
94
+ bwt = Omnizip::Algorithms::BZip2::Bwt.new
95
+ bwt.encode(data)
96
+ end
97
+ end
98
+
99
+ def analyze_results
100
+ puts "\nAnalyzing performance results..." if verbose
101
+
102
+ @profiler.analyze_hot_paths(threshold_percentage: 15.0)
103
+ @profiler.identify_bottlenecks
104
+
105
+ generate_report
106
+ generate_suggestions
107
+ end
108
+
109
+ def generate_report
110
+ generator = Omnizip::Profiler::ReportGenerator.new(@profiler.report)
111
+
112
+ if verbose
113
+ puts "\n"
114
+ generator.print_report
115
+ end
116
+
117
+ generator
118
+ end
119
+
120
+ def generate_suggestions
121
+ suggestions = @profiler.generate_suggestions
122
+
123
+ return if suggestions.empty?
124
+
125
+ puts "\n#{'=' * 80}"
126
+ puts "OPTIMIZATION SUGGESTIONS"
127
+ puts "=" * 80
128
+
129
+ suggestions.take(5).each_with_index do |suggestion, index|
130
+ puts "\n#{index + 1}. [#{suggestion.severity.to_s.upcase}] " \
131
+ "#{suggestion.title}"
132
+ puts " #{suggestion.description}"
133
+ puts " Category: #{suggestion.category}"
134
+ puts " Priority Score: #{suggestion.priority_score.round(2)}"
135
+ end
136
+
137
+ suggestions
138
+ end
139
+
140
+ def save_report(filename, format: :text)
141
+ generator = Omnizip::Profiler::ReportGenerator.new(@profiler.report)
142
+ generator.save_to_file(filename, format: format)
143
+ end
144
+
145
+ private
146
+
147
+ def generate_test_data
148
+ puts "\nGenerating test data..." if verbose
149
+
150
+ @test_data.generate_text(10_240, filename: "text_10240.dat")
151
+ @test_data.generate_repetitive(10_240, filename: "repetitive_10240.dat")
152
+ end
153
+
154
+ def cleanup_test_data
155
+ puts "\nCleaning up test data..." if verbose
156
+ @test_data.cleanup
157
+ end
158
+ end
159
+ end
160
+
161
+ # Run profiling if executed directly
162
+ if __FILE__ == $PROGRAM_NAME
163
+ suite = Benchmark::ProfileSuite.new(verbose: true)
164
+ suite.run_all
165
+ suite.save_report("profile_report.txt", format: :text)
166
+ suite.save_report("profile_report.json", format: :json)
167
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Benchmark
6
+ # Formats and reports benchmark results
7
+ class Reporter
8
+ def initialize(results)
9
+ @results = results
10
+ end
11
+
12
+ def print_summary
13
+ puts "\n#{'=' * 80}"
14
+ puts "OMNIZIP vs 7-ZIP BENCHMARK RESULTS"
15
+ puts "=" * 80
16
+
17
+ @results.each do |result|
18
+ print_comparison(result)
19
+ end
20
+
21
+ print_overall_summary
22
+ end
23
+
24
+ def save_to_file(filename)
25
+ File.write(filename, to_json)
26
+ puts "\nResults saved to #{filename}"
27
+ end
28
+
29
+ def to_json(*_args)
30
+ JSON.pretty_generate({
31
+ timestamp: Time.now.iso8601,
32
+ results: @results.map(&:to_h),
33
+ })
34
+ end
35
+
36
+ private
37
+
38
+ def print_comparison(result)
39
+ puts "\n#{'-' * 80}"
40
+ puts "Test: #{result.test_name}"
41
+ puts "-" * 80
42
+
43
+ if result.both_successful?
44
+ print_successful_comparison(result)
45
+ else
46
+ print_failed_comparison(result)
47
+ end
48
+ end
49
+
50
+ def print_successful_comparison(result)
51
+ omni = result.omnizip_result
52
+ seven = result.seven_zip_result
53
+
54
+ puts "Metric Omnizip 7-Zip"
55
+ puts "-" * 80
56
+
57
+ puts format("%-30s %15s %15s",
58
+ "Input Size",
59
+ format_bytes(omni.input_size),
60
+ format_bytes(seven.input_size))
61
+
62
+ puts format("%-30s %15s %15s",
63
+ "Compressed Size",
64
+ format_bytes(omni.compressed_size),
65
+ format_bytes(seven.compressed_size))
66
+
67
+ puts format("%-30s %15.2f %15.2f",
68
+ "Compression Ratio",
69
+ omni.compression_ratio || 0.0,
70
+ seven.compression_ratio || 0.0)
71
+
72
+ puts format("%-30s %15.3fs %15.3fs",
73
+ "Compression Time",
74
+ omni.compression_time || 0.0,
75
+ seven.compression_time || 0.0)
76
+
77
+ puts "\n#{'-' * 80}"
78
+ puts "Comparison:"
79
+ puts "-" * 80
80
+
81
+ if result.size_difference_bytes
82
+ puts format(" Size difference: %+d bytes (%+.1f%%)",
83
+ result.size_difference_bytes,
84
+ result.size_difference_percentage)
85
+ end
86
+
87
+ return unless result.compression_speed_ratio
88
+
89
+ puts format(" Speed ratio: %.1fx slower",
90
+ result.compression_speed_ratio)
91
+ end
92
+
93
+ def print_failed_comparison(result)
94
+ puts "\nOmnizip:"
95
+ print_result_status(result.omnizip_result)
96
+
97
+ puts "\n7-Zip:"
98
+ print_result_status(result.seven_zip_result)
99
+ end
100
+
101
+ def print_result_status(result)
102
+ if result.success?
103
+ puts " Success"
104
+ puts " Compressed: #{format_bytes(result.compressed_size)}"
105
+ puts " Time: #{format_time(result.compression_time)}"
106
+ else
107
+ puts " Failed: #{result.error}"
108
+ end
109
+ end
110
+
111
+ def print_overall_summary
112
+ puts "\n#{'=' * 80}"
113
+ puts "OVERALL SUMMARY"
114
+ puts "=" * 80
115
+
116
+ successful = @results.select(&:both_successful?)
117
+ total = @results.size
118
+
119
+ puts "Successful comparisons: #{successful.size}/#{total}"
120
+
121
+ return if successful.empty?
122
+
123
+ avg_size_diff = successful.filter_map(&:size_difference_percentage)
124
+ .sum / successful.size
125
+ avg_speed_ratio = successful.filter_map(&:compression_speed_ratio)
126
+ .sum / successful.size
127
+
128
+ puts format("\nAverage size difference: %+.1f%%", avg_size_diff)
129
+ puts format("Average speed ratio: %.1fx slower", avg_speed_ratio)
130
+ end
131
+
132
+ def format_bytes(bytes)
133
+ return "N/A" if bytes.nil?
134
+
135
+ if bytes < 1024
136
+ "#{bytes}B"
137
+ elsif bytes < 1024 * 1024
138
+ "#{(bytes / 1024.0).round(1)}KB"
139
+ else
140
+ "#{(bytes / (1024.0 * 1024)).round(1)}MB"
141
+ end
142
+ end
143
+
144
+ def format_time(seconds)
145
+ return "N/A" if seconds.nil?
146
+
147
+ "#{seconds.round(3)}s"
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "benchmark_suite"
5
+
6
+ # Parse command-line options
7
+ options = {
8
+ verbose: false,
9
+ quick: false,
10
+ mode: :all,
11
+ output: nil,
12
+ }
13
+
14
+ ARGV.each do |arg|
15
+ case arg
16
+ when "--verbose", "-v"
17
+ options[:verbose] = true
18
+ when "--quick", "-q"
19
+ options[:quick] = true
20
+ when "--compression-only"
21
+ options[:mode] = :compression
22
+ when "--filters-only"
23
+ options[:mode] = :filters
24
+ when /--output=(.+)/
25
+ options[:output] = Regexp.last_match(1)
26
+ when "--help", "-h"
27
+ puts <<~HELP
28
+ Usage: ruby benchmark/run_benchmarks.rb [OPTIONS]
29
+
30
+ Options:
31
+ -v, --verbose Enable verbose output
32
+ -q, --quick Run quick benchmarks (1 size, 1 type)
33
+ --compression-only Run only compression benchmarks
34
+ --filters-only Run only filter benchmarks
35
+ --output=FILE Save results to JSON file
36
+ -h, --help Show this help message
37
+
38
+ Examples:
39
+ ruby benchmark/run_benchmarks.rb
40
+ ruby benchmark/run_benchmarks.rb --quick --verbose
41
+ ruby benchmark/run_benchmarks.rb --output=results.json
42
+ HELP
43
+ exit 0
44
+ end
45
+ end
46
+
47
+ # Run benchmarks
48
+ suite = Benchmark::BenchmarkSuite.new(
49
+ verbose: options[:verbose],
50
+ quick: options[:quick],
51
+ )
52
+
53
+ case options[:mode]
54
+ when :compression
55
+ suite.run_compression_only
56
+ when :filters
57
+ suite.run_filters_only
58
+ else
59
+ suite.run_all
60
+ end
61
+
62
+ # Display results
63
+ suite.report
64
+
65
+ # Save results if requested
66
+ suite.save_results(options[:output]) if options[:output]