laag-xz 5.2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (393) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +57 -0
  3. data/LICENSE.txt +65 -0
  4. data/README.org +34 -0
  5. data/ext/laag/xz/extconf.rb +21 -0
  6. data/laag-xz.gemspec +20 -0
  7. data/lib/laag/xz.rb +29 -0
  8. data/vendor/git.tukaani.org/xz/.gitignore +66 -0
  9. data/vendor/git.tukaani.org/xz/AUTHORS +27 -0
  10. data/vendor/git.tukaani.org/xz/COPYING +65 -0
  11. data/vendor/git.tukaani.org/xz/COPYING.GPLv2 +339 -0
  12. data/vendor/git.tukaani.org/xz/COPYING.GPLv3 +674 -0
  13. data/vendor/git.tukaani.org/xz/COPYING.LGPLv2.1 +502 -0
  14. data/vendor/git.tukaani.org/xz/ChangeLog +7 -0
  15. data/vendor/git.tukaani.org/xz/Doxyfile.in +1234 -0
  16. data/vendor/git.tukaani.org/xz/INSTALL +618 -0
  17. data/vendor/git.tukaani.org/xz/INSTALL.generic +365 -0
  18. data/vendor/git.tukaani.org/xz/Makefile.am +110 -0
  19. data/vendor/git.tukaani.org/xz/NEWS +571 -0
  20. data/vendor/git.tukaani.org/xz/PACKAGERS +231 -0
  21. data/vendor/git.tukaani.org/xz/README +308 -0
  22. data/vendor/git.tukaani.org/xz/THANKS +124 -0
  23. data/vendor/git.tukaani.org/xz/TODO +111 -0
  24. data/vendor/git.tukaani.org/xz/autogen.sh +22 -0
  25. data/vendor/git.tukaani.org/xz/build-aux/manconv.sh +58 -0
  26. data/vendor/git.tukaani.org/xz/build-aux/version.sh +24 -0
  27. data/vendor/git.tukaani.org/xz/configure.ac +900 -0
  28. data/vendor/git.tukaani.org/xz/debug/Makefile.am +30 -0
  29. data/vendor/git.tukaani.org/xz/debug/README +17 -0
  30. data/vendor/git.tukaani.org/xz/debug/crc32.c +39 -0
  31. data/vendor/git.tukaani.org/xz/debug/full_flush.c +103 -0
  32. data/vendor/git.tukaani.org/xz/debug/hex2bin.c +53 -0
  33. data/vendor/git.tukaani.org/xz/debug/known_sizes.c +129 -0
  34. data/vendor/git.tukaani.org/xz/debug/memusage.c +51 -0
  35. data/vendor/git.tukaani.org/xz/debug/repeat.c +36 -0
  36. data/vendor/git.tukaani.org/xz/debug/sync_flush.c +125 -0
  37. data/vendor/git.tukaani.org/xz/debug/translation.bash +100 -0
  38. data/vendor/git.tukaani.org/xz/doc/examples/00_README.txt +31 -0
  39. data/vendor/git.tukaani.org/xz/doc/examples/01_compress_easy.c +297 -0
  40. data/vendor/git.tukaani.org/xz/doc/examples/02_decompress.c +287 -0
  41. data/vendor/git.tukaani.org/xz/doc/examples/03_compress_custom.c +193 -0
  42. data/vendor/git.tukaani.org/xz/doc/examples/04_compress_easy_mt.c +206 -0
  43. data/vendor/git.tukaani.org/xz/doc/examples/Makefile +24 -0
  44. data/vendor/git.tukaani.org/xz/doc/examples_old/xz_pipe_comp.c +127 -0
  45. data/vendor/git.tukaani.org/xz/doc/examples_old/xz_pipe_decomp.c +123 -0
  46. data/vendor/git.tukaani.org/xz/doc/faq.txt +224 -0
  47. data/vendor/git.tukaani.org/xz/doc/history.txt +150 -0
  48. data/vendor/git.tukaani.org/xz/doc/lzma-file-format.txt +166 -0
  49. data/vendor/git.tukaani.org/xz/doc/xz-file-format.txt +1150 -0
  50. data/vendor/git.tukaani.org/xz/dos/INSTALL.txt +79 -0
  51. data/vendor/git.tukaani.org/xz/dos/Makefile +147 -0
  52. data/vendor/git.tukaani.org/xz/dos/README.txt +123 -0
  53. data/vendor/git.tukaani.org/xz/dos/config.h +136 -0
  54. data/vendor/git.tukaani.org/xz/extra/7z2lzma/7z2lzma.bash +115 -0
  55. data/vendor/git.tukaani.org/xz/extra/scanlzma/scanlzma.c +88 -0
  56. data/vendor/git.tukaani.org/xz/lib/Makefile.am +32 -0
  57. data/vendor/git.tukaani.org/xz/lib/getopt.c +1197 -0
  58. data/vendor/git.tukaani.org/xz/lib/getopt.in.h +226 -0
  59. data/vendor/git.tukaani.org/xz/lib/getopt1.c +171 -0
  60. data/vendor/git.tukaani.org/xz/lib/getopt_int.h +131 -0
  61. data/vendor/git.tukaani.org/xz/m4/.gitignore +38 -0
  62. data/vendor/git.tukaani.org/xz/m4/ax_check_capsicum.m4 +85 -0
  63. data/vendor/git.tukaani.org/xz/m4/ax_pthread.m4 +332 -0
  64. data/vendor/git.tukaani.org/xz/m4/getopt.m4 +71 -0
  65. data/vendor/git.tukaani.org/xz/m4/posix-shell.m4 +63 -0
  66. data/vendor/git.tukaani.org/xz/m4/tuklib_common.m4 +22 -0
  67. data/vendor/git.tukaani.org/xz/m4/tuklib_cpucores.m4 +176 -0
  68. data/vendor/git.tukaani.org/xz/m4/tuklib_integer.m4 +74 -0
  69. data/vendor/git.tukaani.org/xz/m4/tuklib_mbstr.m4 +30 -0
  70. data/vendor/git.tukaani.org/xz/m4/tuklib_physmem.m4 +212 -0
  71. data/vendor/git.tukaani.org/xz/m4/tuklib_progname.m4 +25 -0
  72. data/vendor/git.tukaani.org/xz/macosx/build.sh +113 -0
  73. data/vendor/git.tukaani.org/xz/po/.gitignore +31 -0
  74. data/vendor/git.tukaani.org/xz/po/LINGUAS +6 -0
  75. data/vendor/git.tukaani.org/xz/po/Makevars +46 -0
  76. data/vendor/git.tukaani.org/xz/po/POTFILES.in +13 -0
  77. data/vendor/git.tukaani.org/xz/po/cs.po +949 -0
  78. data/vendor/git.tukaani.org/xz/po/de.po +993 -0
  79. data/vendor/git.tukaani.org/xz/po/fr.po +978 -0
  80. data/vendor/git.tukaani.org/xz/po/it.po +1067 -0
  81. data/vendor/git.tukaani.org/xz/po/pl.po +968 -0
  82. data/vendor/git.tukaani.org/xz/po/vi.po +1039 -0
  83. data/vendor/git.tukaani.org/xz/src/Makefile.am +42 -0
  84. data/vendor/git.tukaani.org/xz/src/common/common_w32res.rc +50 -0
  85. data/vendor/git.tukaani.org/xz/src/common/mythread.h +521 -0
  86. data/vendor/git.tukaani.org/xz/src/common/sysdefs.h +202 -0
  87. data/vendor/git.tukaani.org/xz/src/common/tuklib_common.h +71 -0
  88. data/vendor/git.tukaani.org/xz/src/common/tuklib_config.h +7 -0
  89. data/vendor/git.tukaani.org/xz/src/common/tuklib_cpucores.c +100 -0
  90. data/vendor/git.tukaani.org/xz/src/common/tuklib_cpucores.h +23 -0
  91. data/vendor/git.tukaani.org/xz/src/common/tuklib_exit.c +57 -0
  92. data/vendor/git.tukaani.org/xz/src/common/tuklib_exit.h +25 -0
  93. data/vendor/git.tukaani.org/xz/src/common/tuklib_gettext.h +44 -0
  94. data/vendor/git.tukaani.org/xz/src/common/tuklib_integer.h +534 -0
  95. data/vendor/git.tukaani.org/xz/src/common/tuklib_mbstr.h +66 -0
  96. data/vendor/git.tukaani.org/xz/src/common/tuklib_mbstr_fw.c +31 -0
  97. data/vendor/git.tukaani.org/xz/src/common/tuklib_mbstr_width.c +64 -0
  98. data/vendor/git.tukaani.org/xz/src/common/tuklib_open_stdxxx.c +57 -0
  99. data/vendor/git.tukaani.org/xz/src/common/tuklib_open_stdxxx.h +23 -0
  100. data/vendor/git.tukaani.org/xz/src/common/tuklib_physmem.c +216 -0
  101. data/vendor/git.tukaani.org/xz/src/common/tuklib_physmem.h +28 -0
  102. data/vendor/git.tukaani.org/xz/src/common/tuklib_progname.c +50 -0
  103. data/vendor/git.tukaani.org/xz/src/common/tuklib_progname.h +32 -0
  104. data/vendor/git.tukaani.org/xz/src/liblzma/Makefile.am +122 -0
  105. data/vendor/git.tukaani.org/xz/src/liblzma/api/Makefile.am +23 -0
  106. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma.h +325 -0
  107. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/base.h +659 -0
  108. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/bcj.h +90 -0
  109. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/block.h +581 -0
  110. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/check.h +150 -0
  111. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/container.h +632 -0
  112. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/delta.h +77 -0
  113. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/filter.h +425 -0
  114. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/hardware.h +64 -0
  115. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/index.h +686 -0
  116. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/index_hash.h +107 -0
  117. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/lzma12.h +420 -0
  118. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/stream_flags.h +223 -0
  119. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/version.h +121 -0
  120. data/vendor/git.tukaani.org/xz/src/liblzma/api/lzma/vli.h +166 -0
  121. data/vendor/git.tukaani.org/xz/src/liblzma/check/Makefile.inc +53 -0
  122. data/vendor/git.tukaani.org/xz/src/liblzma/check/check.c +174 -0
  123. data/vendor/git.tukaani.org/xz/src/liblzma/check/check.h +172 -0
  124. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_fast.c +82 -0
  125. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_small.c +61 -0
  126. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_table.c +19 -0
  127. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_table_be.h +525 -0
  128. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_table_le.h +525 -0
  129. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_tablegen.c +117 -0
  130. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc32_x86.S +304 -0
  131. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_fast.c +72 -0
  132. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_small.c +53 -0
  133. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_table.c +19 -0
  134. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_table_be.h +521 -0
  135. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_table_le.h +521 -0
  136. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_tablegen.c +88 -0
  137. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc64_x86.S +287 -0
  138. data/vendor/git.tukaani.org/xz/src/liblzma/check/crc_macros.h +30 -0
  139. data/vendor/git.tukaani.org/xz/src/liblzma/check/sha256.c +196 -0
  140. data/vendor/git.tukaani.org/xz/src/liblzma/common/Makefile.inc +79 -0
  141. data/vendor/git.tukaani.org/xz/src/liblzma/common/alone_decoder.c +243 -0
  142. data/vendor/git.tukaani.org/xz/src/liblzma/common/alone_decoder.h +23 -0
  143. data/vendor/git.tukaani.org/xz/src/liblzma/common/alone_encoder.c +163 -0
  144. data/vendor/git.tukaani.org/xz/src/liblzma/common/auto_decoder.c +195 -0
  145. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_buffer_decoder.c +80 -0
  146. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_buffer_encoder.c +337 -0
  147. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_buffer_encoder.h +24 -0
  148. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_decoder.c +257 -0
  149. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_decoder.h +22 -0
  150. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_encoder.c +223 -0
  151. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_encoder.h +47 -0
  152. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_header_decoder.c +124 -0
  153. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_header_encoder.c +132 -0
  154. data/vendor/git.tukaani.org/xz/src/liblzma/common/block_util.c +90 -0
  155. data/vendor/git.tukaani.org/xz/src/liblzma/common/common.c +445 -0
  156. data/vendor/git.tukaani.org/xz/src/liblzma/common/common.h +314 -0
  157. data/vendor/git.tukaani.org/xz/src/liblzma/common/easy_buffer_encoder.c +27 -0
  158. data/vendor/git.tukaani.org/xz/src/liblzma/common/easy_decoder_memusage.c +24 -0
  159. data/vendor/git.tukaani.org/xz/src/liblzma/common/easy_encoder.c +24 -0
  160. data/vendor/git.tukaani.org/xz/src/liblzma/common/easy_encoder_memusage.c +24 -0
  161. data/vendor/git.tukaani.org/xz/src/liblzma/common/easy_preset.c +27 -0
  162. data/vendor/git.tukaani.org/xz/src/liblzma/common/easy_preset.h +32 -0
  163. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_buffer_decoder.c +88 -0
  164. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_buffer_encoder.c +55 -0
  165. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_common.c +337 -0
  166. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_common.h +48 -0
  167. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_decoder.c +184 -0
  168. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_decoder.h +23 -0
  169. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_encoder.c +286 -0
  170. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_encoder.h +27 -0
  171. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_flags_decoder.c +46 -0
  172. data/vendor/git.tukaani.org/xz/src/liblzma/common/filter_flags_encoder.c +56 -0
  173. data/vendor/git.tukaani.org/xz/src/liblzma/common/hardware_cputhreads.c +22 -0
  174. data/vendor/git.tukaani.org/xz/src/liblzma/common/hardware_physmem.c +25 -0
  175. data/vendor/git.tukaani.org/xz/src/liblzma/common/index.c +1250 -0
  176. data/vendor/git.tukaani.org/xz/src/liblzma/common/index.h +73 -0
  177. data/vendor/git.tukaani.org/xz/src/liblzma/common/index_decoder.c +352 -0
  178. data/vendor/git.tukaani.org/xz/src/liblzma/common/index_encoder.c +256 -0
  179. data/vendor/git.tukaani.org/xz/src/liblzma/common/index_encoder.h +23 -0
  180. data/vendor/git.tukaani.org/xz/src/liblzma/common/index_hash.c +334 -0
  181. data/vendor/git.tukaani.org/xz/src/liblzma/common/memcmplen.h +175 -0
  182. data/vendor/git.tukaani.org/xz/src/liblzma/common/outqueue.c +184 -0
  183. data/vendor/git.tukaani.org/xz/src/liblzma/common/outqueue.h +156 -0
  184. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_buffer_decoder.c +91 -0
  185. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_buffer_encoder.c +141 -0
  186. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_decoder.c +467 -0
  187. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_decoder.h +22 -0
  188. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_encoder.c +340 -0
  189. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_encoder_mt.c +1143 -0
  190. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_flags_common.c +47 -0
  191. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_flags_common.h +33 -0
  192. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_flags_decoder.c +82 -0
  193. data/vendor/git.tukaani.org/xz/src/liblzma/common/stream_flags_encoder.c +86 -0
  194. data/vendor/git.tukaani.org/xz/src/liblzma/common/vli_decoder.c +86 -0
  195. data/vendor/git.tukaani.org/xz/src/liblzma/common/vli_encoder.c +69 -0
  196. data/vendor/git.tukaani.org/xz/src/liblzma/common/vli_size.c +30 -0
  197. data/vendor/git.tukaani.org/xz/src/liblzma/delta/Makefile.inc +23 -0
  198. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_common.c +73 -0
  199. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_common.h +20 -0
  200. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_decoder.c +78 -0
  201. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_decoder.h +26 -0
  202. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_encoder.c +125 -0
  203. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_encoder.h +24 -0
  204. data/vendor/git.tukaani.org/xz/src/liblzma/delta/delta_private.h +37 -0
  205. data/vendor/git.tukaani.org/xz/src/liblzma/liblzma.map +108 -0
  206. data/vendor/git.tukaani.org/xz/src/liblzma/liblzma.pc.in +19 -0
  207. data/vendor/git.tukaani.org/xz/src/liblzma/liblzma_w32res.rc +12 -0
  208. data/vendor/git.tukaani.org/xz/src/liblzma/lz/Makefile.inc +22 -0
  209. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_decoder.c +306 -0
  210. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_decoder.h +234 -0
  211. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_encoder.c +616 -0
  212. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_encoder.h +327 -0
  213. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_encoder_hash.h +108 -0
  214. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_encoder_hash_table.h +68 -0
  215. data/vendor/git.tukaani.org/xz/src/liblzma/lz/lz_encoder_mf.c +744 -0
  216. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/Makefile.inc +47 -0
  217. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/fastpos.h +141 -0
  218. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/fastpos_table.c +519 -0
  219. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/fastpos_tablegen.c +56 -0
  220. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma2_decoder.c +310 -0
  221. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma2_decoder.h +29 -0
  222. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma2_encoder.c +410 -0
  223. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma2_encoder.h +43 -0
  224. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_common.h +224 -0
  225. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_decoder.c +1064 -0
  226. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_decoder.h +53 -0
  227. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_encoder.c +677 -0
  228. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_encoder.h +58 -0
  229. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_encoder_optimum_fast.c +170 -0
  230. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_encoder_optimum_normal.c +855 -0
  231. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_encoder_presets.c +64 -0
  232. data/vendor/git.tukaani.org/xz/src/liblzma/lzma/lzma_encoder_private.h +148 -0
  233. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/Makefile.inc +21 -0
  234. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/price.h +92 -0
  235. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/price_table.c +22 -0
  236. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/price_tablegen.c +87 -0
  237. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/range_common.h +71 -0
  238. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/range_decoder.h +185 -0
  239. data/vendor/git.tukaani.org/xz/src/liblzma/rangecoder/range_encoder.h +231 -0
  240. data/vendor/git.tukaani.org/xz/src/liblzma/simple/Makefile.inc +47 -0
  241. data/vendor/git.tukaani.org/xz/src/liblzma/simple/arm.c +71 -0
  242. data/vendor/git.tukaani.org/xz/src/liblzma/simple/armthumb.c +76 -0
  243. data/vendor/git.tukaani.org/xz/src/liblzma/simple/ia64.c +112 -0
  244. data/vendor/git.tukaani.org/xz/src/liblzma/simple/powerpc.c +75 -0
  245. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_coder.c +282 -0
  246. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_coder.h +72 -0
  247. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_decoder.c +40 -0
  248. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_decoder.h +22 -0
  249. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_encoder.c +38 -0
  250. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_encoder.h +23 -0
  251. data/vendor/git.tukaani.org/xz/src/liblzma/simple/simple_private.h +74 -0
  252. data/vendor/git.tukaani.org/xz/src/liblzma/simple/sparc.c +83 -0
  253. data/vendor/git.tukaani.org/xz/src/liblzma/simple/x86.c +159 -0
  254. data/vendor/git.tukaani.org/xz/src/liblzma/validate_map.sh +68 -0
  255. data/vendor/git.tukaani.org/xz/src/lzmainfo/Makefile.am +39 -0
  256. data/vendor/git.tukaani.org/xz/src/lzmainfo/lzmainfo.1 +60 -0
  257. data/vendor/git.tukaani.org/xz/src/lzmainfo/lzmainfo.c +219 -0
  258. data/vendor/git.tukaani.org/xz/src/lzmainfo/lzmainfo_w32res.rc +12 -0
  259. data/vendor/git.tukaani.org/xz/src/scripts/Makefile.am +55 -0
  260. data/vendor/git.tukaani.org/xz/src/scripts/xzdiff.1 +77 -0
  261. data/vendor/git.tukaani.org/xz/src/scripts/xzdiff.in +200 -0
  262. data/vendor/git.tukaani.org/xz/src/scripts/xzgrep.1 +98 -0
  263. data/vendor/git.tukaani.org/xz/src/scripts/xzgrep.in +215 -0
  264. data/vendor/git.tukaani.org/xz/src/scripts/xzless.1 +69 -0
  265. data/vendor/git.tukaani.org/xz/src/scripts/xzless.in +58 -0
  266. data/vendor/git.tukaani.org/xz/src/scripts/xzmore.1 +55 -0
  267. data/vendor/git.tukaani.org/xz/src/scripts/xzmore.in +78 -0
  268. data/vendor/git.tukaani.org/xz/src/xz/Makefile.am +111 -0
  269. data/vendor/git.tukaani.org/xz/src/xz/args.c +700 -0
  270. data/vendor/git.tukaani.org/xz/src/xz/args.h +44 -0
  271. data/vendor/git.tukaani.org/xz/src/xz/coder.c +936 -0
  272. data/vendor/git.tukaani.org/xz/src/xz/coder.h +76 -0
  273. data/vendor/git.tukaani.org/xz/src/xz/file_io.c +1300 -0
  274. data/vendor/git.tukaani.org/xz/src/xz/file_io.h +156 -0
  275. data/vendor/git.tukaani.org/xz/src/xz/hardware.c +150 -0
  276. data/vendor/git.tukaani.org/xz/src/xz/hardware.h +37 -0
  277. data/vendor/git.tukaani.org/xz/src/xz/list.c +1192 -0
  278. data/vendor/git.tukaani.org/xz/src/xz/list.h +18 -0
  279. data/vendor/git.tukaani.org/xz/src/xz/main.c +330 -0
  280. data/vendor/git.tukaani.org/xz/src/xz/main.h +30 -0
  281. data/vendor/git.tukaani.org/xz/src/xz/message.c +1258 -0
  282. data/vendor/git.tukaani.org/xz/src/xz/message.h +167 -0
  283. data/vendor/git.tukaani.org/xz/src/xz/mytime.c +89 -0
  284. data/vendor/git.tukaani.org/xz/src/xz/mytime.h +47 -0
  285. data/vendor/git.tukaani.org/xz/src/xz/options.c +363 -0
  286. data/vendor/git.tukaani.org/xz/src/xz/options.h +31 -0
  287. data/vendor/git.tukaani.org/xz/src/xz/private.h +66 -0
  288. data/vendor/git.tukaani.org/xz/src/xz/signals.c +209 -0
  289. data/vendor/git.tukaani.org/xz/src/xz/signals.h +43 -0
  290. data/vendor/git.tukaani.org/xz/src/xz/suffix.c +399 -0
  291. data/vendor/git.tukaani.org/xz/src/xz/suffix.h +28 -0
  292. data/vendor/git.tukaani.org/xz/src/xz/util.c +288 -0
  293. data/vendor/git.tukaani.org/xz/src/xz/util.h +123 -0
  294. data/vendor/git.tukaani.org/xz/src/xz/xz.1 +2786 -0
  295. data/vendor/git.tukaani.org/xz/src/xz/xz_w32res.rc +12 -0
  296. data/vendor/git.tukaani.org/xz/src/xzdec/Makefile.am +82 -0
  297. data/vendor/git.tukaani.org/xz/src/xzdec/lzmadec_w32res.rc +12 -0
  298. data/vendor/git.tukaani.org/xz/src/xzdec/xzdec.1 +146 -0
  299. data/vendor/git.tukaani.org/xz/src/xzdec/xzdec.c +323 -0
  300. data/vendor/git.tukaani.org/xz/src/xzdec/xzdec_w32res.rc +12 -0
  301. data/vendor/git.tukaani.org/xz/tests/Makefile.am +57 -0
  302. data/vendor/git.tukaani.org/xz/tests/bcj_test.c +65 -0
  303. data/vendor/git.tukaani.org/xz/tests/compress_prepared_bcj_sparc +0 -0
  304. data/vendor/git.tukaani.org/xz/tests/compress_prepared_bcj_x86 +0 -0
  305. data/vendor/git.tukaani.org/xz/tests/create_compress_files.c +158 -0
  306. data/vendor/git.tukaani.org/xz/tests/files/README +240 -0
  307. data/vendor/git.tukaani.org/xz/tests/files/bad-0-backward_size.xz +0 -0
  308. data/vendor/git.tukaani.org/xz/tests/files/bad-0-empty-truncated.xz +0 -0
  309. data/vendor/git.tukaani.org/xz/tests/files/bad-0-footer_magic.xz +0 -0
  310. data/vendor/git.tukaani.org/xz/tests/files/bad-0-header_magic.xz +0 -0
  311. data/vendor/git.tukaani.org/xz/tests/files/bad-0-nonempty_index.xz +0 -0
  312. data/vendor/git.tukaani.org/xz/tests/files/bad-0cat-alone.xz +0 -0
  313. data/vendor/git.tukaani.org/xz/tests/files/bad-0cat-header_magic.xz +0 -0
  314. data/vendor/git.tukaani.org/xz/tests/files/bad-0catpad-empty.xz +0 -0
  315. data/vendor/git.tukaani.org/xz/tests/files/bad-0pad-empty.xz +0 -0
  316. data/vendor/git.tukaani.org/xz/tests/files/bad-1-block_header-1.xz +0 -0
  317. data/vendor/git.tukaani.org/xz/tests/files/bad-1-block_header-2.xz +0 -0
  318. data/vendor/git.tukaani.org/xz/tests/files/bad-1-block_header-3.xz +0 -0
  319. data/vendor/git.tukaani.org/xz/tests/files/bad-1-block_header-4.xz +0 -0
  320. data/vendor/git.tukaani.org/xz/tests/files/bad-1-block_header-5.xz +0 -0
  321. data/vendor/git.tukaani.org/xz/tests/files/bad-1-block_header-6.xz +0 -0
  322. data/vendor/git.tukaani.org/xz/tests/files/bad-1-check-crc32.xz +0 -0
  323. data/vendor/git.tukaani.org/xz/tests/files/bad-1-check-crc64.xz +0 -0
  324. data/vendor/git.tukaani.org/xz/tests/files/bad-1-check-sha256.xz +0 -0
  325. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-1.xz +0 -0
  326. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-2.xz +0 -0
  327. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-3.xz +0 -0
  328. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-4.xz +0 -0
  329. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-5.xz +0 -0
  330. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-6.xz +0 -0
  331. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-7.xz +0 -0
  332. data/vendor/git.tukaani.org/xz/tests/files/bad-1-lzma2-8.xz +0 -0
  333. data/vendor/git.tukaani.org/xz/tests/files/bad-1-stream_flags-1.xz +0 -0
  334. data/vendor/git.tukaani.org/xz/tests/files/bad-1-stream_flags-2.xz +0 -0
  335. data/vendor/git.tukaani.org/xz/tests/files/bad-1-stream_flags-3.xz +0 -0
  336. data/vendor/git.tukaani.org/xz/tests/files/bad-1-vli-1.xz +0 -0
  337. data/vendor/git.tukaani.org/xz/tests/files/bad-1-vli-2.xz +0 -0
  338. data/vendor/git.tukaani.org/xz/tests/files/bad-2-compressed_data_padding.xz +0 -0
  339. data/vendor/git.tukaani.org/xz/tests/files/bad-2-index-1.xz +0 -0
  340. data/vendor/git.tukaani.org/xz/tests/files/bad-2-index-2.xz +0 -0
  341. data/vendor/git.tukaani.org/xz/tests/files/bad-2-index-3.xz +0 -0
  342. data/vendor/git.tukaani.org/xz/tests/files/bad-2-index-4.xz +0 -0
  343. data/vendor/git.tukaani.org/xz/tests/files/bad-2-index-5.xz +0 -0
  344. data/vendor/git.tukaani.org/xz/tests/files/good-0-empty.xz +0 -0
  345. data/vendor/git.tukaani.org/xz/tests/files/good-0cat-empty.xz +0 -0
  346. data/vendor/git.tukaani.org/xz/tests/files/good-0catpad-empty.xz +0 -0
  347. data/vendor/git.tukaani.org/xz/tests/files/good-0pad-empty.xz +0 -0
  348. data/vendor/git.tukaani.org/xz/tests/files/good-1-3delta-lzma2.xz +0 -0
  349. data/vendor/git.tukaani.org/xz/tests/files/good-1-block_header-1.xz +0 -0
  350. data/vendor/git.tukaani.org/xz/tests/files/good-1-block_header-2.xz +0 -0
  351. data/vendor/git.tukaani.org/xz/tests/files/good-1-block_header-3.xz +0 -0
  352. data/vendor/git.tukaani.org/xz/tests/files/good-1-check-crc32.xz +0 -0
  353. data/vendor/git.tukaani.org/xz/tests/files/good-1-check-crc64.xz +0 -0
  354. data/vendor/git.tukaani.org/xz/tests/files/good-1-check-none.xz +0 -0
  355. data/vendor/git.tukaani.org/xz/tests/files/good-1-check-sha256.xz +0 -0
  356. data/vendor/git.tukaani.org/xz/tests/files/good-1-delta-lzma2.tiff.xz +0 -0
  357. data/vendor/git.tukaani.org/xz/tests/files/good-1-lzma2-1.xz +0 -0
  358. data/vendor/git.tukaani.org/xz/tests/files/good-1-lzma2-2.xz +0 -0
  359. data/vendor/git.tukaani.org/xz/tests/files/good-1-lzma2-3.xz +0 -0
  360. data/vendor/git.tukaani.org/xz/tests/files/good-1-lzma2-4.xz +0 -0
  361. data/vendor/git.tukaani.org/xz/tests/files/good-1-lzma2-5.xz +0 -0
  362. data/vendor/git.tukaani.org/xz/tests/files/good-1-sparc-lzma2.xz +0 -0
  363. data/vendor/git.tukaani.org/xz/tests/files/good-1-x86-lzma2.xz +0 -0
  364. data/vendor/git.tukaani.org/xz/tests/files/good-2-lzma2.xz +0 -0
  365. data/vendor/git.tukaani.org/xz/tests/files/unsupported-block_header.xz +0 -0
  366. data/vendor/git.tukaani.org/xz/tests/files/unsupported-check.xz +0 -0
  367. data/vendor/git.tukaani.org/xz/tests/files/unsupported-filter_flags-1.xz +0 -0
  368. data/vendor/git.tukaani.org/xz/tests/files/unsupported-filter_flags-2.xz +0 -0
  369. data/vendor/git.tukaani.org/xz/tests/files/unsupported-filter_flags-3.xz +0 -0
  370. data/vendor/git.tukaani.org/xz/tests/test_bcj_exact_size.c +113 -0
  371. data/vendor/git.tukaani.org/xz/tests/test_block_header.c +240 -0
  372. data/vendor/git.tukaani.org/xz/tests/test_check.c +83 -0
  373. data/vendor/git.tukaani.org/xz/tests/test_compress.sh +142 -0
  374. data/vendor/git.tukaani.org/xz/tests/test_files.sh +57 -0
  375. data/vendor/git.tukaani.org/xz/tests/test_filter_flags.c +258 -0
  376. data/vendor/git.tukaani.org/xz/tests/test_index.c +689 -0
  377. data/vendor/git.tukaani.org/xz/tests/test_scripts.sh +76 -0
  378. data/vendor/git.tukaani.org/xz/tests/test_stream_flags.c +180 -0
  379. data/vendor/git.tukaani.org/xz/tests/tests.h +124 -0
  380. data/vendor/git.tukaani.org/xz/tests/xzgrep_expected_output +39 -0
  381. data/vendor/git.tukaani.org/xz/windows/INSTALL-MSVC.txt +47 -0
  382. data/vendor/git.tukaani.org/xz/windows/INSTALL-MinGW.txt +138 -0
  383. data/vendor/git.tukaani.org/xz/windows/README-Windows.txt +122 -0
  384. data/vendor/git.tukaani.org/xz/windows/build.bash +203 -0
  385. data/vendor/git.tukaani.org/xz/windows/vs2013/config.h +148 -0
  386. data/vendor/git.tukaani.org/xz/windows/vs2013/liblzma.vcxproj +354 -0
  387. data/vendor/git.tukaani.org/xz/windows/vs2013/liblzma_dll.vcxproj +383 -0
  388. data/vendor/git.tukaani.org/xz/windows/vs2013/xz_win.sln +48 -0
  389. data/vendor/git.tukaani.org/xz/windows/vs2017/config.h +148 -0
  390. data/vendor/git.tukaani.org/xz/windows/vs2017/liblzma.vcxproj +355 -0
  391. data/vendor/git.tukaani.org/xz/windows/vs2017/liblzma_dll.vcxproj +384 -0
  392. data/vendor/git.tukaani.org/xz/windows/vs2017/xz_win.sln +48 -0
  393. metadata +457 -0
@@ -0,0 +1,22 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ /// \file stream_decoder.h
4
+ /// \brief Decodes .xz Streams
5
+ //
6
+ // Author: Lasse Collin
7
+ //
8
+ // This file has been put into the public domain.
9
+ // You can do whatever you want with this file.
10
+ //
11
+ ///////////////////////////////////////////////////////////////////////////////
12
+
13
+ #ifndef LZMA_STREAM_DECODER_H
14
+ #define LZMA_STREAM_DECODER_H
15
+
16
+ #include "common.h"
17
+
18
+ extern lzma_ret lzma_stream_decoder_init(
19
+ lzma_next_coder *next, const lzma_allocator *allocator,
20
+ uint64_t memlimit, uint32_t flags);
21
+
22
+ #endif
@@ -0,0 +1,340 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ /// \file stream_encoder.c
4
+ /// \brief Encodes .xz Streams
5
+ //
6
+ // Author: Lasse Collin
7
+ //
8
+ // This file has been put into the public domain.
9
+ // You can do whatever you want with this file.
10
+ //
11
+ ///////////////////////////////////////////////////////////////////////////////
12
+
13
+ #include "block_encoder.h"
14
+ #include "index_encoder.h"
15
+
16
+
17
+ typedef struct {
18
+ enum {
19
+ SEQ_STREAM_HEADER,
20
+ SEQ_BLOCK_INIT,
21
+ SEQ_BLOCK_HEADER,
22
+ SEQ_BLOCK_ENCODE,
23
+ SEQ_INDEX_ENCODE,
24
+ SEQ_STREAM_FOOTER,
25
+ } sequence;
26
+
27
+ /// True if Block encoder has been initialized by
28
+ /// stream_encoder_init() or stream_encoder_update()
29
+ /// and thus doesn't need to be initialized in stream_encode().
30
+ bool block_encoder_is_initialized;
31
+
32
+ /// Block
33
+ lzma_next_coder block_encoder;
34
+
35
+ /// Options for the Block encoder
36
+ lzma_block block_options;
37
+
38
+ /// The filter chain currently in use
39
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
40
+
41
+ /// Index encoder. This is separate from Block encoder, because this
42
+ /// doesn't take much memory, and when encoding multiple Streams
43
+ /// with the same encoding options we avoid reallocating memory.
44
+ lzma_next_coder index_encoder;
45
+
46
+ /// Index to hold sizes of the Blocks
47
+ lzma_index *index;
48
+
49
+ /// Read position in buffer[]
50
+ size_t buffer_pos;
51
+
52
+ /// Total number of bytes in buffer[]
53
+ size_t buffer_size;
54
+
55
+ /// Buffer to hold Stream Header, Block Header, and Stream Footer.
56
+ /// Block Header has biggest maximum size.
57
+ uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
58
+ } lzma_stream_coder;
59
+
60
+
61
+ static lzma_ret
62
+ block_encoder_init(lzma_stream_coder *coder, const lzma_allocator *allocator)
63
+ {
64
+ // Prepare the Block options. Even though Block encoder doesn't need
65
+ // compressed_size, uncompressed_size, and header_size to be
66
+ // initialized, it is a good idea to do it here, because this way
67
+ // we catch if someone gave us Filter ID that cannot be used in
68
+ // Blocks/Streams.
69
+ coder->block_options.compressed_size = LZMA_VLI_UNKNOWN;
70
+ coder->block_options.uncompressed_size = LZMA_VLI_UNKNOWN;
71
+
72
+ return_if_error(lzma_block_header_size(&coder->block_options));
73
+
74
+ // Initialize the actual Block encoder.
75
+ return lzma_block_encoder_init(&coder->block_encoder, allocator,
76
+ &coder->block_options);
77
+ }
78
+
79
+
80
+ static lzma_ret
81
+ stream_encode(void *coder_ptr, const lzma_allocator *allocator,
82
+ const uint8_t *restrict in, size_t *restrict in_pos,
83
+ size_t in_size, uint8_t *restrict out,
84
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
85
+ {
86
+ lzma_stream_coder *coder = coder_ptr;
87
+
88
+ // Main loop
89
+ while (*out_pos < out_size)
90
+ switch (coder->sequence) {
91
+ case SEQ_STREAM_HEADER:
92
+ case SEQ_BLOCK_HEADER:
93
+ case SEQ_STREAM_FOOTER:
94
+ lzma_bufcpy(coder->buffer, &coder->buffer_pos,
95
+ coder->buffer_size, out, out_pos, out_size);
96
+ if (coder->buffer_pos < coder->buffer_size)
97
+ return LZMA_OK;
98
+
99
+ if (coder->sequence == SEQ_STREAM_FOOTER)
100
+ return LZMA_STREAM_END;
101
+
102
+ coder->buffer_pos = 0;
103
+ ++coder->sequence;
104
+ break;
105
+
106
+ case SEQ_BLOCK_INIT: {
107
+ if (*in_pos == in_size) {
108
+ // If we are requested to flush or finish the current
109
+ // Block, return LZMA_STREAM_END immediately since
110
+ // there's nothing to do.
111
+ if (action != LZMA_FINISH)
112
+ return action == LZMA_RUN
113
+ ? LZMA_OK : LZMA_STREAM_END;
114
+
115
+ // The application had used LZMA_FULL_FLUSH to finish
116
+ // the previous Block, but now wants to finish without
117
+ // encoding new data, or it is simply creating an
118
+ // empty Stream with no Blocks.
119
+ //
120
+ // Initialize the Index encoder, and continue to
121
+ // actually encoding the Index.
122
+ return_if_error(lzma_index_encoder_init(
123
+ &coder->index_encoder, allocator,
124
+ coder->index));
125
+ coder->sequence = SEQ_INDEX_ENCODE;
126
+ break;
127
+ }
128
+
129
+ // Initialize the Block encoder unless it was already
130
+ // initialized by stream_encoder_init() or
131
+ // stream_encoder_update().
132
+ if (!coder->block_encoder_is_initialized)
133
+ return_if_error(block_encoder_init(coder, allocator));
134
+
135
+ // Make it false so that we don't skip the initialization
136
+ // with the next Block.
137
+ coder->block_encoder_is_initialized = false;
138
+
139
+ // Encode the Block Header. This shouldn't fail since we have
140
+ // already initialized the Block encoder.
141
+ if (lzma_block_header_encode(&coder->block_options,
142
+ coder->buffer) != LZMA_OK)
143
+ return LZMA_PROG_ERROR;
144
+
145
+ coder->buffer_size = coder->block_options.header_size;
146
+ coder->sequence = SEQ_BLOCK_HEADER;
147
+ break;
148
+ }
149
+
150
+ case SEQ_BLOCK_ENCODE: {
151
+ static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
152
+ LZMA_RUN,
153
+ LZMA_SYNC_FLUSH,
154
+ LZMA_FINISH,
155
+ LZMA_FINISH,
156
+ LZMA_FINISH,
157
+ };
158
+
159
+ const lzma_ret ret = coder->block_encoder.code(
160
+ coder->block_encoder.coder, allocator,
161
+ in, in_pos, in_size,
162
+ out, out_pos, out_size, convert[action]);
163
+ if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
164
+ return ret;
165
+
166
+ // Add a new Index Record.
167
+ const lzma_vli unpadded_size = lzma_block_unpadded_size(
168
+ &coder->block_options);
169
+ assert(unpadded_size != 0);
170
+ return_if_error(lzma_index_append(coder->index, allocator,
171
+ unpadded_size,
172
+ coder->block_options.uncompressed_size));
173
+
174
+ coder->sequence = SEQ_BLOCK_INIT;
175
+ break;
176
+ }
177
+
178
+ case SEQ_INDEX_ENCODE: {
179
+ // Call the Index encoder. It doesn't take any input, so
180
+ // those pointers can be NULL.
181
+ const lzma_ret ret = coder->index_encoder.code(
182
+ coder->index_encoder.coder, allocator,
183
+ NULL, NULL, 0,
184
+ out, out_pos, out_size, LZMA_RUN);
185
+ if (ret != LZMA_STREAM_END)
186
+ return ret;
187
+
188
+ // Encode the Stream Footer into coder->buffer.
189
+ const lzma_stream_flags stream_flags = {
190
+ .version = 0,
191
+ .backward_size = lzma_index_size(coder->index),
192
+ .check = coder->block_options.check,
193
+ };
194
+
195
+ if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
196
+ != LZMA_OK)
197
+ return LZMA_PROG_ERROR;
198
+
199
+ coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
200
+ coder->sequence = SEQ_STREAM_FOOTER;
201
+ break;
202
+ }
203
+
204
+ default:
205
+ assert(0);
206
+ return LZMA_PROG_ERROR;
207
+ }
208
+
209
+ return LZMA_OK;
210
+ }
211
+
212
+
213
+ static void
214
+ stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
215
+ {
216
+ lzma_stream_coder *coder = coder_ptr;
217
+
218
+ lzma_next_end(&coder->block_encoder, allocator);
219
+ lzma_next_end(&coder->index_encoder, allocator);
220
+ lzma_index_end(coder->index, allocator);
221
+
222
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
223
+ lzma_free(coder->filters[i].options, allocator);
224
+
225
+ lzma_free(coder, allocator);
226
+ return;
227
+ }
228
+
229
+
230
+ static lzma_ret
231
+ stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
232
+ const lzma_filter *filters,
233
+ const lzma_filter *reversed_filters)
234
+ {
235
+ lzma_stream_coder *coder = coder_ptr;
236
+
237
+ if (coder->sequence <= SEQ_BLOCK_INIT) {
238
+ // There is no incomplete Block waiting to be finished,
239
+ // thus we can change the whole filter chain. Start by
240
+ // trying to initialize the Block encoder with the new
241
+ // chain. This way we detect if the chain is valid.
242
+ coder->block_encoder_is_initialized = false;
243
+ coder->block_options.filters = (lzma_filter *)(filters);
244
+ const lzma_ret ret = block_encoder_init(coder, allocator);
245
+ coder->block_options.filters = coder->filters;
246
+ if (ret != LZMA_OK)
247
+ return ret;
248
+
249
+ coder->block_encoder_is_initialized = true;
250
+
251
+ } else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
252
+ // We are in the middle of a Block. Try to update only
253
+ // the filter-specific options.
254
+ return_if_error(coder->block_encoder.update(
255
+ coder->block_encoder.coder, allocator,
256
+ filters, reversed_filters));
257
+ } else {
258
+ // Trying to update the filter chain when we are already
259
+ // encoding Index or Stream Footer.
260
+ return LZMA_PROG_ERROR;
261
+ }
262
+
263
+ // Free the copy of the old chain and make a copy of the new chain.
264
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
265
+ lzma_free(coder->filters[i].options, allocator);
266
+
267
+ return lzma_filters_copy(filters, coder->filters, allocator);
268
+ }
269
+
270
+
271
+ static lzma_ret
272
+ stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
273
+ const lzma_filter *filters, lzma_check check)
274
+ {
275
+ lzma_next_coder_init(&stream_encoder_init, next, allocator);
276
+
277
+ if (filters == NULL)
278
+ return LZMA_PROG_ERROR;
279
+
280
+ lzma_stream_coder *coder = next->coder;
281
+
282
+ if (coder == NULL) {
283
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
284
+ if (coder == NULL)
285
+ return LZMA_MEM_ERROR;
286
+
287
+ next->coder = coder;
288
+ next->code = &stream_encode;
289
+ next->end = &stream_encoder_end;
290
+ next->update = &stream_encoder_update;
291
+
292
+ coder->filters[0].id = LZMA_VLI_UNKNOWN;
293
+ coder->block_encoder = LZMA_NEXT_CODER_INIT;
294
+ coder->index_encoder = LZMA_NEXT_CODER_INIT;
295
+ coder->index = NULL;
296
+ }
297
+
298
+ // Basic initializations
299
+ coder->sequence = SEQ_STREAM_HEADER;
300
+ coder->block_options.version = 0;
301
+ coder->block_options.check = check;
302
+
303
+ // Initialize the Index
304
+ lzma_index_end(coder->index, allocator);
305
+ coder->index = lzma_index_init(allocator);
306
+ if (coder->index == NULL)
307
+ return LZMA_MEM_ERROR;
308
+
309
+ // Encode the Stream Header
310
+ lzma_stream_flags stream_flags = {
311
+ .version = 0,
312
+ .check = check,
313
+ };
314
+ return_if_error(lzma_stream_header_encode(
315
+ &stream_flags, coder->buffer));
316
+
317
+ coder->buffer_pos = 0;
318
+ coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
319
+
320
+ // Initialize the Block encoder. This way we detect unsupported
321
+ // filter chains when initializing the Stream encoder instead of
322
+ // giving an error after Stream Header has already written out.
323
+ return stream_encoder_update(coder, allocator, filters, NULL);
324
+ }
325
+
326
+
327
+ extern LZMA_API(lzma_ret)
328
+ lzma_stream_encoder(lzma_stream *strm,
329
+ const lzma_filter *filters, lzma_check check)
330
+ {
331
+ lzma_next_strm_init(stream_encoder_init, strm, filters, check);
332
+
333
+ strm->internal->supported_actions[LZMA_RUN] = true;
334
+ strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
335
+ strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
336
+ strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
337
+ strm->internal->supported_actions[LZMA_FINISH] = true;
338
+
339
+ return LZMA_OK;
340
+ }
@@ -0,0 +1,1143 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ /// \file stream_encoder_mt.c
4
+ /// \brief Multithreaded .xz Stream encoder
5
+ //
6
+ // Author: Lasse Collin
7
+ //
8
+ // This file has been put into the public domain.
9
+ // You can do whatever you want with this file.
10
+ //
11
+ ///////////////////////////////////////////////////////////////////////////////
12
+
13
+ #include "filter_encoder.h"
14
+ #include "easy_preset.h"
15
+ #include "block_encoder.h"
16
+ #include "block_buffer_encoder.h"
17
+ #include "index_encoder.h"
18
+ #include "outqueue.h"
19
+
20
+
21
+ /// Maximum supported block size. This makes it simpler to prevent integer
22
+ /// overflows if we are given unusually large block size.
23
+ #define BLOCK_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX)
24
+
25
+
26
+ typedef enum {
27
+ /// Waiting for work.
28
+ THR_IDLE,
29
+
30
+ /// Encoding is in progress.
31
+ THR_RUN,
32
+
33
+ /// Encoding is in progress but no more input data will
34
+ /// be read.
35
+ THR_FINISH,
36
+
37
+ /// The main thread wants the thread to stop whatever it was doing
38
+ /// but not exit.
39
+ THR_STOP,
40
+
41
+ /// The main thread wants the thread to exit. We could use
42
+ /// cancellation but since there's stopped anyway, this is lazier.
43
+ THR_EXIT,
44
+
45
+ } worker_state;
46
+
47
+ typedef struct lzma_stream_coder_s lzma_stream_coder;
48
+
49
+ typedef struct worker_thread_s worker_thread;
50
+ struct worker_thread_s {
51
+ worker_state state;
52
+
53
+ /// Input buffer of coder->block_size bytes. The main thread will
54
+ /// put new input into this and update in_size accordingly. Once
55
+ /// no more input is coming, state will be set to THR_FINISH.
56
+ uint8_t *in;
57
+
58
+ /// Amount of data available in the input buffer. This is modified
59
+ /// only by the main thread.
60
+ size_t in_size;
61
+
62
+ /// Output buffer for this thread. This is set by the main
63
+ /// thread every time a new Block is started with this thread
64
+ /// structure.
65
+ lzma_outbuf *outbuf;
66
+
67
+ /// Pointer to the main structure is needed when putting this
68
+ /// thread back to the stack of free threads.
69
+ lzma_stream_coder *coder;
70
+
71
+ /// The allocator is set by the main thread. Since a copy of the
72
+ /// pointer is kept here, the application must not change the
73
+ /// allocator before calling lzma_end().
74
+ const lzma_allocator *allocator;
75
+
76
+ /// Amount of uncompressed data that has already been compressed.
77
+ uint64_t progress_in;
78
+
79
+ /// Amount of compressed data that is ready.
80
+ uint64_t progress_out;
81
+
82
+ /// Block encoder
83
+ lzma_next_coder block_encoder;
84
+
85
+ /// Compression options for this Block
86
+ lzma_block block_options;
87
+
88
+ /// Next structure in the stack of free worker threads.
89
+ worker_thread *next;
90
+
91
+ mythread_mutex mutex;
92
+ mythread_cond cond;
93
+
94
+ /// The ID of this thread is used to join the thread
95
+ /// when it's not needed anymore.
96
+ mythread thread_id;
97
+ };
98
+
99
+
100
+ struct lzma_stream_coder_s {
101
+ enum {
102
+ SEQ_STREAM_HEADER,
103
+ SEQ_BLOCK,
104
+ SEQ_INDEX,
105
+ SEQ_STREAM_FOOTER,
106
+ } sequence;
107
+
108
+ /// Start a new Block every block_size bytes of input unless
109
+ /// LZMA_FULL_FLUSH or LZMA_FULL_BARRIER is used earlier.
110
+ size_t block_size;
111
+
112
+ /// The filter chain currently in use
113
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
114
+
115
+
116
+ /// Index to hold sizes of the Blocks
117
+ lzma_index *index;
118
+
119
+ /// Index encoder
120
+ lzma_next_coder index_encoder;
121
+
122
+
123
+ /// Stream Flags for encoding the Stream Header and Stream Footer.
124
+ lzma_stream_flags stream_flags;
125
+
126
+ /// Buffer to hold Stream Header and Stream Footer.
127
+ uint8_t header[LZMA_STREAM_HEADER_SIZE];
128
+
129
+ /// Read position in header[]
130
+ size_t header_pos;
131
+
132
+
133
+ /// Output buffer queue for compressed data
134
+ lzma_outq outq;
135
+
136
+
137
+ /// Maximum wait time if cannot use all the input and cannot
138
+ /// fill the output buffer. This is in milliseconds.
139
+ uint32_t timeout;
140
+
141
+
142
+ /// Error code from a worker thread
143
+ lzma_ret thread_error;
144
+
145
+ /// Array of allocated thread-specific structures
146
+ worker_thread *threads;
147
+
148
+ /// Number of structures in "threads" above. This is also the
149
+ /// number of threads that will be created at maximum.
150
+ uint32_t threads_max;
151
+
152
+ /// Number of thread structures that have been initialized, and
153
+ /// thus the number of worker threads actually created so far.
154
+ uint32_t threads_initialized;
155
+
156
+ /// Stack of free threads. When a thread finishes, it puts itself
157
+ /// back into this stack. This starts as empty because threads
158
+ /// are created only when actually needed.
159
+ worker_thread *threads_free;
160
+
161
+ /// The most recent worker thread to which the main thread writes
162
+ /// the new input from the application.
163
+ worker_thread *thr;
164
+
165
+
166
+ /// Amount of uncompressed data in Blocks that have already
167
+ /// been finished.
168
+ uint64_t progress_in;
169
+
170
+ /// Amount of compressed data in Stream Header + Blocks that
171
+ /// have already been finished.
172
+ uint64_t progress_out;
173
+
174
+
175
+ mythread_mutex mutex;
176
+ mythread_cond cond;
177
+ };
178
+
179
+
180
+ /// Tell the main thread that something has gone wrong.
181
+ static void
182
+ worker_error(worker_thread *thr, lzma_ret ret)
183
+ {
184
+ assert(ret != LZMA_OK);
185
+ assert(ret != LZMA_STREAM_END);
186
+
187
+ mythread_sync(thr->coder->mutex) {
188
+ if (thr->coder->thread_error == LZMA_OK)
189
+ thr->coder->thread_error = ret;
190
+
191
+ mythread_cond_signal(&thr->coder->cond);
192
+ }
193
+
194
+ return;
195
+ }
196
+
197
+
198
+ static worker_state
199
+ worker_encode(worker_thread *thr, worker_state state)
200
+ {
201
+ assert(thr->progress_in == 0);
202
+ assert(thr->progress_out == 0);
203
+
204
+ // Set the Block options.
205
+ thr->block_options = (lzma_block){
206
+ .version = 0,
207
+ .check = thr->coder->stream_flags.check,
208
+ .compressed_size = thr->coder->outq.buf_size_max,
209
+ .uncompressed_size = thr->coder->block_size,
210
+
211
+ // TODO: To allow changing the filter chain, the filters
212
+ // array must be copied to each worker_thread.
213
+ .filters = thr->coder->filters,
214
+ };
215
+
216
+ // Calculate maximum size of the Block Header. This amount is
217
+ // reserved in the beginning of the buffer so that Block Header
218
+ // along with Compressed Size and Uncompressed Size can be
219
+ // written there.
220
+ lzma_ret ret = lzma_block_header_size(&thr->block_options);
221
+ if (ret != LZMA_OK) {
222
+ worker_error(thr, ret);
223
+ return THR_STOP;
224
+ }
225
+
226
+ // Initialize the Block encoder.
227
+ ret = lzma_block_encoder_init(&thr->block_encoder,
228
+ thr->allocator, &thr->block_options);
229
+ if (ret != LZMA_OK) {
230
+ worker_error(thr, ret);
231
+ return THR_STOP;
232
+ }
233
+
234
+ size_t in_pos = 0;
235
+ size_t in_size = 0;
236
+
237
+ thr->outbuf->size = thr->block_options.header_size;
238
+ const size_t out_size = thr->coder->outq.buf_size_max;
239
+
240
+ do {
241
+ mythread_sync(thr->mutex) {
242
+ // Store in_pos and out_pos into *thr so that
243
+ // an application may read them via
244
+ // lzma_get_progress() to get progress information.
245
+ //
246
+ // NOTE: These aren't updated when the encoding
247
+ // finishes. Instead, the final values are taken
248
+ // later from thr->outbuf.
249
+ thr->progress_in = in_pos;
250
+ thr->progress_out = thr->outbuf->size;
251
+
252
+ while (in_size == thr->in_size
253
+ && thr->state == THR_RUN)
254
+ mythread_cond_wait(&thr->cond, &thr->mutex);
255
+
256
+ state = thr->state;
257
+ in_size = thr->in_size;
258
+ }
259
+
260
+ // Return if we were asked to stop or exit.
261
+ if (state >= THR_STOP)
262
+ return state;
263
+
264
+ lzma_action action = state == THR_FINISH
265
+ ? LZMA_FINISH : LZMA_RUN;
266
+
267
+ // Limit the amount of input given to the Block encoder
268
+ // at once. This way this thread can react fairly quickly
269
+ // if the main thread wants us to stop or exit.
270
+ static const size_t in_chunk_max = 16384;
271
+ size_t in_limit = in_size;
272
+ if (in_size - in_pos > in_chunk_max) {
273
+ in_limit = in_pos + in_chunk_max;
274
+ action = LZMA_RUN;
275
+ }
276
+
277
+ ret = thr->block_encoder.code(
278
+ thr->block_encoder.coder, thr->allocator,
279
+ thr->in, &in_pos, in_limit, thr->outbuf->buf,
280
+ &thr->outbuf->size, out_size, action);
281
+ } while (ret == LZMA_OK && thr->outbuf->size < out_size);
282
+
283
+ switch (ret) {
284
+ case LZMA_STREAM_END:
285
+ assert(state == THR_FINISH);
286
+
287
+ // Encode the Block Header. By doing it after
288
+ // the compression, we can store the Compressed Size
289
+ // and Uncompressed Size fields.
290
+ ret = lzma_block_header_encode(&thr->block_options,
291
+ thr->outbuf->buf);
292
+ if (ret != LZMA_OK) {
293
+ worker_error(thr, ret);
294
+ return THR_STOP;
295
+ }
296
+
297
+ break;
298
+
299
+ case LZMA_OK:
300
+ // The data was incompressible. Encode it using uncompressed
301
+ // LZMA2 chunks.
302
+ //
303
+ // First wait that we have gotten all the input.
304
+ mythread_sync(thr->mutex) {
305
+ while (thr->state == THR_RUN)
306
+ mythread_cond_wait(&thr->cond, &thr->mutex);
307
+
308
+ state = thr->state;
309
+ in_size = thr->in_size;
310
+ }
311
+
312
+ if (state >= THR_STOP)
313
+ return state;
314
+
315
+ // Do the encoding. This takes care of the Block Header too.
316
+ thr->outbuf->size = 0;
317
+ ret = lzma_block_uncomp_encode(&thr->block_options,
318
+ thr->in, in_size, thr->outbuf->buf,
319
+ &thr->outbuf->size, out_size);
320
+
321
+ // It shouldn't fail.
322
+ if (ret != LZMA_OK) {
323
+ worker_error(thr, LZMA_PROG_ERROR);
324
+ return THR_STOP;
325
+ }
326
+
327
+ break;
328
+
329
+ default:
330
+ worker_error(thr, ret);
331
+ return THR_STOP;
332
+ }
333
+
334
+ // Set the size information that will be read by the main thread
335
+ // to write the Index field.
336
+ thr->outbuf->unpadded_size
337
+ = lzma_block_unpadded_size(&thr->block_options);
338
+ assert(thr->outbuf->unpadded_size != 0);
339
+ thr->outbuf->uncompressed_size = thr->block_options.uncompressed_size;
340
+
341
+ return THR_FINISH;
342
+ }
343
+
344
+
345
+ static MYTHREAD_RET_TYPE
346
+ worker_start(void *thr_ptr)
347
+ {
348
+ worker_thread *thr = thr_ptr;
349
+ worker_state state = THR_IDLE; // Init to silence a warning
350
+
351
+ while (true) {
352
+ // Wait for work.
353
+ mythread_sync(thr->mutex) {
354
+ while (true) {
355
+ // The thread is already idle so if we are
356
+ // requested to stop, just set the state.
357
+ if (thr->state == THR_STOP) {
358
+ thr->state = THR_IDLE;
359
+ mythread_cond_signal(&thr->cond);
360
+ }
361
+
362
+ state = thr->state;
363
+ if (state != THR_IDLE)
364
+ break;
365
+
366
+ mythread_cond_wait(&thr->cond, &thr->mutex);
367
+ }
368
+ }
369
+
370
+ assert(state != THR_IDLE);
371
+ assert(state != THR_STOP);
372
+
373
+ if (state <= THR_FINISH)
374
+ state = worker_encode(thr, state);
375
+
376
+ if (state == THR_EXIT)
377
+ break;
378
+
379
+ // Mark the thread as idle unless the main thread has
380
+ // told us to exit. Signal is needed for the case
381
+ // where the main thread is waiting for the threads to stop.
382
+ mythread_sync(thr->mutex) {
383
+ if (thr->state != THR_EXIT) {
384
+ thr->state = THR_IDLE;
385
+ mythread_cond_signal(&thr->cond);
386
+ }
387
+ }
388
+
389
+ mythread_sync(thr->coder->mutex) {
390
+ // Mark the output buffer as finished if
391
+ // no errors occurred.
392
+ thr->outbuf->finished = state == THR_FINISH;
393
+
394
+ // Update the main progress info.
395
+ thr->coder->progress_in
396
+ += thr->outbuf->uncompressed_size;
397
+ thr->coder->progress_out += thr->outbuf->size;
398
+ thr->progress_in = 0;
399
+ thr->progress_out = 0;
400
+
401
+ // Return this thread to the stack of free threads.
402
+ thr->next = thr->coder->threads_free;
403
+ thr->coder->threads_free = thr;
404
+
405
+ mythread_cond_signal(&thr->coder->cond);
406
+ }
407
+ }
408
+
409
+ // Exiting, free the resources.
410
+ mythread_mutex_destroy(&thr->mutex);
411
+ mythread_cond_destroy(&thr->cond);
412
+
413
+ lzma_next_end(&thr->block_encoder, thr->allocator);
414
+ lzma_free(thr->in, thr->allocator);
415
+ return MYTHREAD_RET_VALUE;
416
+ }
417
+
418
+
419
+ /// Make the threads stop but not exit. Optionally wait for them to stop.
420
+ static void
421
+ threads_stop(lzma_stream_coder *coder, bool wait_for_threads)
422
+ {
423
+ // Tell the threads to stop.
424
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
425
+ mythread_sync(coder->threads[i].mutex) {
426
+ coder->threads[i].state = THR_STOP;
427
+ mythread_cond_signal(&coder->threads[i].cond);
428
+ }
429
+ }
430
+
431
+ if (!wait_for_threads)
432
+ return;
433
+
434
+ // Wait for the threads to settle in the idle state.
435
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
436
+ mythread_sync(coder->threads[i].mutex) {
437
+ while (coder->threads[i].state != THR_IDLE)
438
+ mythread_cond_wait(&coder->threads[i].cond,
439
+ &coder->threads[i].mutex);
440
+ }
441
+ }
442
+
443
+ return;
444
+ }
445
+
446
+
447
+ /// Stop the threads and free the resources associated with them.
448
+ /// Wait until the threads have exited.
449
+ static void
450
+ threads_end(lzma_stream_coder *coder, const lzma_allocator *allocator)
451
+ {
452
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
453
+ mythread_sync(coder->threads[i].mutex) {
454
+ coder->threads[i].state = THR_EXIT;
455
+ mythread_cond_signal(&coder->threads[i].cond);
456
+ }
457
+ }
458
+
459
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
460
+ int ret = mythread_join(coder->threads[i].thread_id);
461
+ assert(ret == 0);
462
+ (void)ret;
463
+ }
464
+
465
+ lzma_free(coder->threads, allocator);
466
+ return;
467
+ }
468
+
469
+
470
+ /// Initialize a new worker_thread structure and create a new thread.
471
+ static lzma_ret
472
+ initialize_new_thread(lzma_stream_coder *coder,
473
+ const lzma_allocator *allocator)
474
+ {
475
+ worker_thread *thr = &coder->threads[coder->threads_initialized];
476
+
477
+ thr->in = lzma_alloc(coder->block_size, allocator);
478
+ if (thr->in == NULL)
479
+ return LZMA_MEM_ERROR;
480
+
481
+ if (mythread_mutex_init(&thr->mutex))
482
+ goto error_mutex;
483
+
484
+ if (mythread_cond_init(&thr->cond))
485
+ goto error_cond;
486
+
487
+ thr->state = THR_IDLE;
488
+ thr->allocator = allocator;
489
+ thr->coder = coder;
490
+ thr->progress_in = 0;
491
+ thr->progress_out = 0;
492
+ thr->block_encoder = LZMA_NEXT_CODER_INIT;
493
+
494
+ if (mythread_create(&thr->thread_id, &worker_start, thr))
495
+ goto error_thread;
496
+
497
+ ++coder->threads_initialized;
498
+ coder->thr = thr;
499
+
500
+ return LZMA_OK;
501
+
502
+ error_thread:
503
+ mythread_cond_destroy(&thr->cond);
504
+
505
+ error_cond:
506
+ mythread_mutex_destroy(&thr->mutex);
507
+
508
+ error_mutex:
509
+ lzma_free(thr->in, allocator);
510
+ return LZMA_MEM_ERROR;
511
+ }
512
+
513
+
514
+ static lzma_ret
515
+ get_thread(lzma_stream_coder *coder, const lzma_allocator *allocator)
516
+ {
517
+ // If there are no free output subqueues, there is no
518
+ // point to try getting a thread.
519
+ if (!lzma_outq_has_buf(&coder->outq))
520
+ return LZMA_OK;
521
+
522
+ // If there is a free structure on the stack, use it.
523
+ mythread_sync(coder->mutex) {
524
+ if (coder->threads_free != NULL) {
525
+ coder->thr = coder->threads_free;
526
+ coder->threads_free = coder->threads_free->next;
527
+ }
528
+ }
529
+
530
+ if (coder->thr == NULL) {
531
+ // If there are no uninitialized structures left, return.
532
+ if (coder->threads_initialized == coder->threads_max)
533
+ return LZMA_OK;
534
+
535
+ // Initialize a new thread.
536
+ return_if_error(initialize_new_thread(coder, allocator));
537
+ }
538
+
539
+ // Reset the parts of the thread state that have to be done
540
+ // in the main thread.
541
+ mythread_sync(coder->thr->mutex) {
542
+ coder->thr->state = THR_RUN;
543
+ coder->thr->in_size = 0;
544
+ coder->thr->outbuf = lzma_outq_get_buf(&coder->outq);
545
+ mythread_cond_signal(&coder->thr->cond);
546
+ }
547
+
548
+ return LZMA_OK;
549
+ }
550
+
551
+
552
+ static lzma_ret
553
+ stream_encode_in(lzma_stream_coder *coder, const lzma_allocator *allocator,
554
+ const uint8_t *restrict in, size_t *restrict in_pos,
555
+ size_t in_size, lzma_action action)
556
+ {
557
+ while (*in_pos < in_size
558
+ || (coder->thr != NULL && action != LZMA_RUN)) {
559
+ if (coder->thr == NULL) {
560
+ // Get a new thread.
561
+ const lzma_ret ret = get_thread(coder, allocator);
562
+ if (coder->thr == NULL)
563
+ return ret;
564
+ }
565
+
566
+ // Copy the input data to thread's buffer.
567
+ size_t thr_in_size = coder->thr->in_size;
568
+ lzma_bufcpy(in, in_pos, in_size, coder->thr->in,
569
+ &thr_in_size, coder->block_size);
570
+
571
+ // Tell the Block encoder to finish if
572
+ // - it has got block_size bytes of input; or
573
+ // - all input was used and LZMA_FINISH, LZMA_FULL_FLUSH,
574
+ // or LZMA_FULL_BARRIER was used.
575
+ //
576
+ // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER.
577
+ const bool finish = thr_in_size == coder->block_size
578
+ || (*in_pos == in_size && action != LZMA_RUN);
579
+
580
+ bool block_error = false;
581
+
582
+ mythread_sync(coder->thr->mutex) {
583
+ if (coder->thr->state == THR_IDLE) {
584
+ // Something has gone wrong with the Block
585
+ // encoder. It has set coder->thread_error
586
+ // which we will read a few lines later.
587
+ block_error = true;
588
+ } else {
589
+ // Tell the Block encoder its new amount
590
+ // of input and update the state if needed.
591
+ coder->thr->in_size = thr_in_size;
592
+
593
+ if (finish)
594
+ coder->thr->state = THR_FINISH;
595
+
596
+ mythread_cond_signal(&coder->thr->cond);
597
+ }
598
+ }
599
+
600
+ if (block_error) {
601
+ lzma_ret ret;
602
+
603
+ mythread_sync(coder->mutex) {
604
+ ret = coder->thread_error;
605
+ }
606
+
607
+ return ret;
608
+ }
609
+
610
+ if (finish)
611
+ coder->thr = NULL;
612
+ }
613
+
614
+ return LZMA_OK;
615
+ }
616
+
617
+
618
+ /// Wait until more input can be consumed, more output can be read, or
619
+ /// an optional timeout is reached.
620
+ static bool
621
+ wait_for_work(lzma_stream_coder *coder, mythread_condtime *wait_abs,
622
+ bool *has_blocked, bool has_input)
623
+ {
624
+ if (coder->timeout != 0 && !*has_blocked) {
625
+ // Every time when stream_encode_mt() is called via
626
+ // lzma_code(), *has_blocked starts as false. We set it
627
+ // to true here and calculate the absolute time when
628
+ // we must return if there's nothing to do.
629
+ //
630
+ // The idea of *has_blocked is to avoid unneeded calls
631
+ // to mythread_condtime_set(), which may do a syscall
632
+ // depending on the operating system.
633
+ *has_blocked = true;
634
+ mythread_condtime_set(wait_abs, &coder->cond, coder->timeout);
635
+ }
636
+
637
+ bool timed_out = false;
638
+
639
+ mythread_sync(coder->mutex) {
640
+ // There are four things that we wait. If one of them
641
+ // becomes possible, we return.
642
+ // - If there is input left, we need to get a free
643
+ // worker thread and an output buffer for it.
644
+ // - Data ready to be read from the output queue.
645
+ // - A worker thread indicates an error.
646
+ // - Time out occurs.
647
+ while ((!has_input || coder->threads_free == NULL
648
+ || !lzma_outq_has_buf(&coder->outq))
649
+ && !lzma_outq_is_readable(&coder->outq)
650
+ && coder->thread_error == LZMA_OK
651
+ && !timed_out) {
652
+ if (coder->timeout != 0)
653
+ timed_out = mythread_cond_timedwait(
654
+ &coder->cond, &coder->mutex,
655
+ wait_abs) != 0;
656
+ else
657
+ mythread_cond_wait(&coder->cond,
658
+ &coder->mutex);
659
+ }
660
+ }
661
+
662
+ return timed_out;
663
+ }
664
+
665
+
666
+ static lzma_ret
667
+ stream_encode_mt(void *coder_ptr, const lzma_allocator *allocator,
668
+ const uint8_t *restrict in, size_t *restrict in_pos,
669
+ size_t in_size, uint8_t *restrict out,
670
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
671
+ {
672
+ lzma_stream_coder *coder = coder_ptr;
673
+
674
+ switch (coder->sequence) {
675
+ case SEQ_STREAM_HEADER:
676
+ lzma_bufcpy(coder->header, &coder->header_pos,
677
+ sizeof(coder->header),
678
+ out, out_pos, out_size);
679
+ if (coder->header_pos < sizeof(coder->header))
680
+ return LZMA_OK;
681
+
682
+ coder->header_pos = 0;
683
+ coder->sequence = SEQ_BLOCK;
684
+
685
+ // Fall through
686
+
687
+ case SEQ_BLOCK: {
688
+ // Initialized to silence warnings.
689
+ lzma_vli unpadded_size = 0;
690
+ lzma_vli uncompressed_size = 0;
691
+ lzma_ret ret = LZMA_OK;
692
+
693
+ // These are for wait_for_work().
694
+ bool has_blocked = false;
695
+ mythread_condtime wait_abs;
696
+
697
+ while (true) {
698
+ mythread_sync(coder->mutex) {
699
+ // Check for Block encoder errors.
700
+ ret = coder->thread_error;
701
+ if (ret != LZMA_OK) {
702
+ assert(ret != LZMA_STREAM_END);
703
+ break;
704
+ }
705
+
706
+ // Try to read compressed data to out[].
707
+ ret = lzma_outq_read(&coder->outq,
708
+ out, out_pos, out_size,
709
+ &unpadded_size,
710
+ &uncompressed_size);
711
+ }
712
+
713
+ if (ret == LZMA_STREAM_END) {
714
+ // End of Block. Add it to the Index.
715
+ ret = lzma_index_append(coder->index,
716
+ allocator, unpadded_size,
717
+ uncompressed_size);
718
+
719
+ // If we didn't fill the output buffer yet,
720
+ // try to read more data. Maybe the next
721
+ // outbuf has been finished already too.
722
+ if (*out_pos < out_size)
723
+ continue;
724
+ }
725
+
726
+ if (ret != LZMA_OK) {
727
+ // coder->thread_error was set or
728
+ // lzma_index_append() failed.
729
+ threads_stop(coder, false);
730
+ return ret;
731
+ }
732
+
733
+ // Try to give uncompressed data to a worker thread.
734
+ ret = stream_encode_in(coder, allocator,
735
+ in, in_pos, in_size, action);
736
+ if (ret != LZMA_OK) {
737
+ threads_stop(coder, false);
738
+ return ret;
739
+ }
740
+
741
+ // See if we should wait or return.
742
+ //
743
+ // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER.
744
+ if (*in_pos == in_size) {
745
+ // LZMA_RUN: More data is probably coming
746
+ // so return to let the caller fill the
747
+ // input buffer.
748
+ if (action == LZMA_RUN)
749
+ return LZMA_OK;
750
+
751
+ // LZMA_FULL_BARRIER: The same as with
752
+ // LZMA_RUN but tell the caller that the
753
+ // barrier was completed.
754
+ if (action == LZMA_FULL_BARRIER)
755
+ return LZMA_STREAM_END;
756
+
757
+ // Finishing or flushing isn't completed until
758
+ // all input data has been encoded and copied
759
+ // to the output buffer.
760
+ if (lzma_outq_is_empty(&coder->outq)) {
761
+ // LZMA_FINISH: Continue to encode
762
+ // the Index field.
763
+ if (action == LZMA_FINISH)
764
+ break;
765
+
766
+ // LZMA_FULL_FLUSH: Return to tell
767
+ // the caller that flushing was
768
+ // completed.
769
+ if (action == LZMA_FULL_FLUSH)
770
+ return LZMA_STREAM_END;
771
+ }
772
+ }
773
+
774
+ // Return if there is no output space left.
775
+ // This check must be done after testing the input
776
+ // buffer, because we might want to use a different
777
+ // return code.
778
+ if (*out_pos == out_size)
779
+ return LZMA_OK;
780
+
781
+ // Neither in nor out has been used completely.
782
+ // Wait until there's something we can do.
783
+ if (wait_for_work(coder, &wait_abs, &has_blocked,
784
+ *in_pos < in_size))
785
+ return LZMA_TIMED_OUT;
786
+ }
787
+
788
+ // All Blocks have been encoded and the threads have stopped.
789
+ // Prepare to encode the Index field.
790
+ return_if_error(lzma_index_encoder_init(
791
+ &coder->index_encoder, allocator,
792
+ coder->index));
793
+ coder->sequence = SEQ_INDEX;
794
+
795
+ // Update the progress info to take the Index and
796
+ // Stream Footer into account. Those are very fast to encode
797
+ // so in terms of progress information they can be thought
798
+ // to be ready to be copied out.
799
+ coder->progress_out += lzma_index_size(coder->index)
800
+ + LZMA_STREAM_HEADER_SIZE;
801
+ }
802
+
803
+ // Fall through
804
+
805
+ case SEQ_INDEX: {
806
+ // Call the Index encoder. It doesn't take any input, so
807
+ // those pointers can be NULL.
808
+ const lzma_ret ret = coder->index_encoder.code(
809
+ coder->index_encoder.coder, allocator,
810
+ NULL, NULL, 0,
811
+ out, out_pos, out_size, LZMA_RUN);
812
+ if (ret != LZMA_STREAM_END)
813
+ return ret;
814
+
815
+ // Encode the Stream Footer into coder->buffer.
816
+ coder->stream_flags.backward_size
817
+ = lzma_index_size(coder->index);
818
+ if (lzma_stream_footer_encode(&coder->stream_flags,
819
+ coder->header) != LZMA_OK)
820
+ return LZMA_PROG_ERROR;
821
+
822
+ coder->sequence = SEQ_STREAM_FOOTER;
823
+ }
824
+
825
+ // Fall through
826
+
827
+ case SEQ_STREAM_FOOTER:
828
+ lzma_bufcpy(coder->header, &coder->header_pos,
829
+ sizeof(coder->header),
830
+ out, out_pos, out_size);
831
+ return coder->header_pos < sizeof(coder->header)
832
+ ? LZMA_OK : LZMA_STREAM_END;
833
+ }
834
+
835
+ assert(0);
836
+ return LZMA_PROG_ERROR;
837
+ }
838
+
839
+
840
+ static void
841
+ stream_encoder_mt_end(void *coder_ptr, const lzma_allocator *allocator)
842
+ {
843
+ lzma_stream_coder *coder = coder_ptr;
844
+
845
+ // Threads must be killed before the output queue can be freed.
846
+ threads_end(coder, allocator);
847
+ lzma_outq_end(&coder->outq, allocator);
848
+
849
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
850
+ lzma_free(coder->filters[i].options, allocator);
851
+
852
+ lzma_next_end(&coder->index_encoder, allocator);
853
+ lzma_index_end(coder->index, allocator);
854
+
855
+ mythread_cond_destroy(&coder->cond);
856
+ mythread_mutex_destroy(&coder->mutex);
857
+
858
+ lzma_free(coder, allocator);
859
+ return;
860
+ }
861
+
862
+
863
+ /// Options handling for lzma_stream_encoder_mt_init() and
864
+ /// lzma_stream_encoder_mt_memusage()
865
+ static lzma_ret
866
+ get_options(const lzma_mt *options, lzma_options_easy *opt_easy,
867
+ const lzma_filter **filters, uint64_t *block_size,
868
+ uint64_t *outbuf_size_max)
869
+ {
870
+ // Validate some of the options.
871
+ if (options == NULL)
872
+ return LZMA_PROG_ERROR;
873
+
874
+ if (options->flags != 0 || options->threads == 0
875
+ || options->threads > LZMA_THREADS_MAX)
876
+ return LZMA_OPTIONS_ERROR;
877
+
878
+ if (options->filters != NULL) {
879
+ // Filter chain was given, use it as is.
880
+ *filters = options->filters;
881
+ } else {
882
+ // Use a preset.
883
+ if (lzma_easy_preset(opt_easy, options->preset))
884
+ return LZMA_OPTIONS_ERROR;
885
+
886
+ *filters = opt_easy->filters;
887
+ }
888
+
889
+ // Block size
890
+ if (options->block_size > 0) {
891
+ if (options->block_size > BLOCK_SIZE_MAX)
892
+ return LZMA_OPTIONS_ERROR;
893
+
894
+ *block_size = options->block_size;
895
+ } else {
896
+ // Determine the Block size from the filter chain.
897
+ *block_size = lzma_mt_block_size(*filters);
898
+ if (*block_size == 0)
899
+ return LZMA_OPTIONS_ERROR;
900
+
901
+ assert(*block_size <= BLOCK_SIZE_MAX);
902
+ }
903
+
904
+ // Calculate the maximum amount output that a single output buffer
905
+ // may need to hold. This is the same as the maximum total size of
906
+ // a Block.
907
+ *outbuf_size_max = lzma_block_buffer_bound64(*block_size);
908
+ if (*outbuf_size_max == 0)
909
+ return LZMA_MEM_ERROR;
910
+
911
+ return LZMA_OK;
912
+ }
913
+
914
+
915
+ static void
916
+ get_progress(void *coder_ptr, uint64_t *progress_in, uint64_t *progress_out)
917
+ {
918
+ lzma_stream_coder *coder = coder_ptr;
919
+
920
+ // Lock coder->mutex to prevent finishing threads from moving their
921
+ // progress info from the worker_thread structure to lzma_stream_coder.
922
+ mythread_sync(coder->mutex) {
923
+ *progress_in = coder->progress_in;
924
+ *progress_out = coder->progress_out;
925
+
926
+ for (size_t i = 0; i < coder->threads_initialized; ++i) {
927
+ mythread_sync(coder->threads[i].mutex) {
928
+ *progress_in += coder->threads[i].progress_in;
929
+ *progress_out += coder->threads[i]
930
+ .progress_out;
931
+ }
932
+ }
933
+ }
934
+
935
+ return;
936
+ }
937
+
938
+
939
+ static lzma_ret
940
+ stream_encoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator,
941
+ const lzma_mt *options)
942
+ {
943
+ lzma_next_coder_init(&stream_encoder_mt_init, next, allocator);
944
+
945
+ // Get the filter chain.
946
+ lzma_options_easy easy;
947
+ const lzma_filter *filters;
948
+ uint64_t block_size;
949
+ uint64_t outbuf_size_max;
950
+ return_if_error(get_options(options, &easy, &filters,
951
+ &block_size, &outbuf_size_max));
952
+
953
+ #if SIZE_MAX < UINT64_MAX
954
+ if (block_size > SIZE_MAX)
955
+ return LZMA_MEM_ERROR;
956
+ #endif
957
+
958
+ // Validate the filter chain so that we can give an error in this
959
+ // function instead of delaying it to the first call to lzma_code().
960
+ // The memory usage calculation verifies the filter chain as
961
+ // a side effect so we take advatange of that.
962
+ if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
963
+ return LZMA_OPTIONS_ERROR;
964
+
965
+ // Validate the Check ID.
966
+ if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
967
+ return LZMA_PROG_ERROR;
968
+
969
+ if (!lzma_check_is_supported(options->check))
970
+ return LZMA_UNSUPPORTED_CHECK;
971
+
972
+ // Allocate and initialize the base structure if needed.
973
+ lzma_stream_coder *coder = next->coder;
974
+ if (coder == NULL) {
975
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
976
+ if (coder == NULL)
977
+ return LZMA_MEM_ERROR;
978
+
979
+ next->coder = coder;
980
+
981
+ // For the mutex and condition variable initializations
982
+ // the error handling has to be done here because
983
+ // stream_encoder_mt_end() doesn't know if they have
984
+ // already been initialized or not.
985
+ if (mythread_mutex_init(&coder->mutex)) {
986
+ lzma_free(coder, allocator);
987
+ next->coder = NULL;
988
+ return LZMA_MEM_ERROR;
989
+ }
990
+
991
+ if (mythread_cond_init(&coder->cond)) {
992
+ mythread_mutex_destroy(&coder->mutex);
993
+ lzma_free(coder, allocator);
994
+ next->coder = NULL;
995
+ return LZMA_MEM_ERROR;
996
+ }
997
+
998
+ next->code = &stream_encode_mt;
999
+ next->end = &stream_encoder_mt_end;
1000
+ next->get_progress = &get_progress;
1001
+ // next->update = &stream_encoder_mt_update;
1002
+
1003
+ coder->filters[0].id = LZMA_VLI_UNKNOWN;
1004
+ coder->index_encoder = LZMA_NEXT_CODER_INIT;
1005
+ coder->index = NULL;
1006
+ memzero(&coder->outq, sizeof(coder->outq));
1007
+ coder->threads = NULL;
1008
+ coder->threads_max = 0;
1009
+ coder->threads_initialized = 0;
1010
+ }
1011
+
1012
+ // Basic initializations
1013
+ coder->sequence = SEQ_STREAM_HEADER;
1014
+ coder->block_size = (size_t)(block_size);
1015
+ coder->thread_error = LZMA_OK;
1016
+ coder->thr = NULL;
1017
+
1018
+ // Allocate the thread-specific base structures.
1019
+ assert(options->threads > 0);
1020
+ if (coder->threads_max != options->threads) {
1021
+ threads_end(coder, allocator);
1022
+
1023
+ coder->threads = NULL;
1024
+ coder->threads_max = 0;
1025
+
1026
+ coder->threads_initialized = 0;
1027
+ coder->threads_free = NULL;
1028
+
1029
+ coder->threads = lzma_alloc(
1030
+ options->threads * sizeof(worker_thread),
1031
+ allocator);
1032
+ if (coder->threads == NULL)
1033
+ return LZMA_MEM_ERROR;
1034
+
1035
+ coder->threads_max = options->threads;
1036
+ } else {
1037
+ // Reuse the old structures and threads. Tell the running
1038
+ // threads to stop and wait until they have stopped.
1039
+ threads_stop(coder, true);
1040
+ }
1041
+
1042
+ // Output queue
1043
+ return_if_error(lzma_outq_init(&coder->outq, allocator,
1044
+ outbuf_size_max, options->threads));
1045
+
1046
+ // Timeout
1047
+ coder->timeout = options->timeout;
1048
+
1049
+ // Free the old filter chain and copy the new one.
1050
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
1051
+ lzma_free(coder->filters[i].options, allocator);
1052
+
1053
+ return_if_error(lzma_filters_copy(
1054
+ filters, coder->filters, allocator));
1055
+
1056
+ // Index
1057
+ lzma_index_end(coder->index, allocator);
1058
+ coder->index = lzma_index_init(allocator);
1059
+ if (coder->index == NULL)
1060
+ return LZMA_MEM_ERROR;
1061
+
1062
+ // Stream Header
1063
+ coder->stream_flags.version = 0;
1064
+ coder->stream_flags.check = options->check;
1065
+ return_if_error(lzma_stream_header_encode(
1066
+ &coder->stream_flags, coder->header));
1067
+
1068
+ coder->header_pos = 0;
1069
+
1070
+ // Progress info
1071
+ coder->progress_in = 0;
1072
+ coder->progress_out = LZMA_STREAM_HEADER_SIZE;
1073
+
1074
+ return LZMA_OK;
1075
+ }
1076
+
1077
+
1078
+ extern LZMA_API(lzma_ret)
1079
+ lzma_stream_encoder_mt(lzma_stream *strm, const lzma_mt *options)
1080
+ {
1081
+ lzma_next_strm_init(stream_encoder_mt_init, strm, options);
1082
+
1083
+ strm->internal->supported_actions[LZMA_RUN] = true;
1084
+ // strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
1085
+ strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
1086
+ strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
1087
+ strm->internal->supported_actions[LZMA_FINISH] = true;
1088
+
1089
+ return LZMA_OK;
1090
+ }
1091
+
1092
+
1093
+ // This function name is a monster but it's consistent with the older
1094
+ // monster names. :-( 31 chars is the max that C99 requires so in that
1095
+ // sense it's not too long. ;-)
1096
+ extern LZMA_API(uint64_t)
1097
+ lzma_stream_encoder_mt_memusage(const lzma_mt *options)
1098
+ {
1099
+ lzma_options_easy easy;
1100
+ const lzma_filter *filters;
1101
+ uint64_t block_size;
1102
+ uint64_t outbuf_size_max;
1103
+
1104
+ if (get_options(options, &easy, &filters, &block_size,
1105
+ &outbuf_size_max) != LZMA_OK)
1106
+ return UINT64_MAX;
1107
+
1108
+ // Memory usage of the input buffers
1109
+ const uint64_t inbuf_memusage = options->threads * block_size;
1110
+
1111
+ // Memory usage of the filter encoders
1112
+ uint64_t filters_memusage = lzma_raw_encoder_memusage(filters);
1113
+ if (filters_memusage == UINT64_MAX)
1114
+ return UINT64_MAX;
1115
+
1116
+ filters_memusage *= options->threads;
1117
+
1118
+ // Memory usage of the output queue
1119
+ const uint64_t outq_memusage = lzma_outq_memusage(
1120
+ outbuf_size_max, options->threads);
1121
+ if (outq_memusage == UINT64_MAX)
1122
+ return UINT64_MAX;
1123
+
1124
+ // Sum them with overflow checking.
1125
+ uint64_t total_memusage = LZMA_MEMUSAGE_BASE
1126
+ + sizeof(lzma_stream_coder)
1127
+ + options->threads * sizeof(worker_thread);
1128
+
1129
+ if (UINT64_MAX - total_memusage < inbuf_memusage)
1130
+ return UINT64_MAX;
1131
+
1132
+ total_memusage += inbuf_memusage;
1133
+
1134
+ if (UINT64_MAX - total_memusage < filters_memusage)
1135
+ return UINT64_MAX;
1136
+
1137
+ total_memusage += filters_memusage;
1138
+
1139
+ if (UINT64_MAX - total_memusage < outq_memusage)
1140
+ return UINT64_MAX;
1141
+
1142
+ return total_memusage + outq_memusage;
1143
+ }