overlap.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /* overlap.c -- example program: overlapping (de)compression
  2. This file is part of the LZO real-time data compression library.
  3. Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer
  4. All Rights Reserved.
  5. The LZO library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of
  8. the License, or (at your option) any later version.
  9. The LZO library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with the LZO library; see the file COPYING.
  15. If not, write to the Free Software Foundation, Inc.,
  16. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. Markus F.X.J. Oberhumer
  18. <markus@oberhumer.com>
  19. http://www.oberhumer.com/opensource/lzo/
  20. */
  21. /*************************************************************************
  22. // This program shows how to do overlapping compression and
  23. // in-place decompression.
  24. //
  25. // Please study LZO.FAQ and simple.c first.
  26. **************************************************************************/
  27. #include <lzo/lzoconf.h>
  28. #include <lzo/lzo1x.h>
  29. /* portability layer */
  30. static const char *progname = NULL;
  31. #define WANT_LZO_MALLOC 1
  32. #define WANT_LZO_FREAD 1
  33. #define WANT_LZO_WILDARGV 1
  34. #define WANT_XMALLOC 1
  35. #include "examples/portab.h"
  36. /* Overhead (in bytes) for the in-place decompression buffer.
  37. * Most files need only 16 !
  38. * (try 'overlap -16 file' or even 'overlap -8 file')
  39. *
  40. * Worst case (for files that are compressible by only a few bytes)
  41. * is 'in_len / 16 + 64 + 3'. See step 5a) below.
  42. *
  43. * For overlapping compression '0xbfff + in_len / 16 + 64 + 3' bytes
  44. * will be needed. See step 4a) below.
  45. */
  46. static long opt_overhead = 0; /* assume worst case */
  47. static unsigned long total_files = 0;
  48. static unsigned long total_in = 0;
  49. /*************************************************************************
  50. //
  51. **************************************************************************/
  52. static int do_file(const char *in_name)
  53. {
  54. int r;
  55. FILE *fp = NULL;
  56. long l;
  57. lzo_voidp wrkmem = NULL;
  58. lzo_bytep in = NULL;
  59. lzo_uint in_len; /* uncompressed length */
  60. lzo_bytep out = NULL;
  61. lzo_uint out_len; /* compressed length */
  62. lzo_bytep overlap = NULL;
  63. lzo_uint overhead;
  64. lzo_uint offset;
  65. lzo_uint new_len = 0;
  66. /*
  67. * Step 1: open the input file
  68. */
  69. fp = fopen(in_name, "rb");
  70. if (fp == NULL)
  71. {
  72. printf("%s: %s: cannot open file\n", progname, in_name);
  73. goto next_file;
  74. }
  75. fseek(fp, 0, SEEK_END);
  76. l = ftell(fp);
  77. fseek(fp, 0, SEEK_SET);
  78. if (l <= 0)
  79. {
  80. printf("%s: %s: empty file -- skipping\n", progname, in_name);
  81. goto next_file;
  82. }
  83. in_len = (lzo_uint) l;
  84. if ((long) in_len != l || l > 256L * 1024L * 1024L)
  85. {
  86. printf("%s: %s: file is too big -- skipping\n", progname, in_name);
  87. goto next_file;
  88. }
  89. /*
  90. * Step 2: allocate compression buffers and read the file
  91. */
  92. in = (lzo_bytep) xmalloc(in_len);
  93. out = (lzo_bytep) xmalloc(in_len + in_len / 16 + 64 + 3);
  94. wrkmem = (lzo_voidp) xmalloc(LZO1X_1_MEM_COMPRESS);
  95. in_len = (lzo_uint) lzo_fread(fp, in, in_len);
  96. fclose(fp); fp = NULL;
  97. printf("%s: %s: read %lu bytes\n", progname, in_name, (unsigned long) in_len);
  98. total_files++;
  99. total_in += (unsigned long) in_len;
  100. /*
  101. * Step 3: compress from 'in' to 'out' with LZO1X-1
  102. */
  103. r = lzo1x_1_compress(in, in_len, out, &out_len, wrkmem);
  104. if (r != LZO_E_OK || out_len > in_len + in_len / 16 + 64 + 3)
  105. {
  106. /* this should NEVER happen */
  107. printf("internal error - compression failed: %d\n", r);
  108. exit(1);
  109. }
  110. printf("%-25s %8lu -> %8lu\n", "LZO1X-1:", (unsigned long) in_len, (unsigned long) out_len);
  111. /***** Step 4: overlapping compression *****/
  112. /*
  113. * Step 4a: allocate the 'overlap' buffer for overlapping compression
  114. */
  115. overhead = in_len > 0xbfff ? 0xbfff : in_len;
  116. overhead += in_len / 16 + 64 + 3;
  117. overlap = (lzo_bytep) xmalloc(in_len + overhead);
  118. /*
  119. * Step 4b: prepare data in 'overlap' buffer.
  120. * copy uncompressed data at the top of the overlap buffer
  121. */
  122. /*** offset = in_len + overhead - in_len; ***/
  123. offset = overhead;
  124. lzo_memcpy(overlap + offset, in, in_len);
  125. /*
  126. * Step 4c: do an in-place compression within the 'overlap' buffer
  127. */
  128. r = lzo1x_1_compress(overlap + offset, in_len, overlap, &new_len, wrkmem);
  129. if (r != LZO_E_OK)
  130. {
  131. /* this should NEVER happen */
  132. printf("in-place compression failed: %d\n", r);
  133. exit(1);
  134. }
  135. /*
  136. * Step 4d: verify overlapping compression
  137. */
  138. if (new_len != out_len || lzo_memcmp(out, overlap, out_len) != 0)
  139. {
  140. /* As compression is non-deterministic there can be a difference
  141. * in the representation of the compressed data (but this usually
  142. * happens very seldom). So we have to verify the overlapping
  143. * compression by doing a temporary decompression.
  144. */
  145. lzo_uint ll = in_len;
  146. lzo_bytep tmp = (lzo_bytep) xmalloc(ll);
  147. r = lzo1x_decompress_safe(overlap, new_len, tmp, &ll, NULL);
  148. if (r != LZO_E_OK || ll != in_len || lzo_memcmp(in, tmp, ll) != 0)
  149. {
  150. /* this should NEVER happen */
  151. printf("in-place compression data error\n");
  152. exit(1);
  153. }
  154. lzo_free(tmp);
  155. }
  156. printf(" in-place compression: %8lu -> %8lu overhead: %7lu\n",
  157. (unsigned long) in_len, (unsigned long) new_len, (unsigned long) overhead);
  158. lzo_free(overlap); overlap = NULL;
  159. /***** Step 5: in-place decompression *****/
  160. /*
  161. * Step 5a: allocate the 'overlap' buffer for in-place decompression
  162. */
  163. if (opt_overhead == 0 || out_len >= in_len)
  164. overhead = in_len / 16 + 64 + 3;
  165. else
  166. overhead = (lzo_uint) opt_overhead;
  167. overlap = (lzo_bytep) xmalloc(in_len + overhead);
  168. /*
  169. * Step 5b: prepare data in 'overlap' buffer.
  170. * copy compressed data at the top of the overlap buffer
  171. */
  172. offset = in_len + overhead - out_len;
  173. lzo_memcpy(overlap + offset, out, out_len);
  174. /*
  175. * Step 5c: do an in-place decompression within the 'overlap' buffer
  176. */
  177. new_len = in_len;
  178. r = lzo1x_decompress_safe(overlap + offset, out_len, overlap, &new_len, NULL);
  179. if (r != LZO_E_OK)
  180. {
  181. /* this may happen if overhead is too small */
  182. printf("in-place decompression failed: %d - increase 'opt_overhead'\n", r);
  183. exit(1);
  184. }
  185. /*
  186. * Step 5d: verify decompression
  187. */
  188. if (new_len != in_len || lzo_memcmp(in, overlap, in_len) != 0)
  189. {
  190. /* this may happen if overhead is too small */
  191. printf("in-place decompression data error - increase 'opt_overhead'\n");
  192. exit(1);
  193. }
  194. printf(" in-place decompression: %8lu -> %8lu overhead: %7lu\n",
  195. (unsigned long) out_len, (unsigned long) new_len, (unsigned long) overhead);
  196. lzo_free(overlap); overlap = NULL;
  197. next_file:
  198. lzo_free(overlap);
  199. lzo_free(wrkmem);
  200. lzo_free(out);
  201. lzo_free(in);
  202. if (fp) fclose(fp);
  203. return 0;
  204. }
  205. /*************************************************************************
  206. //
  207. **************************************************************************/
  208. int __lzo_cdecl_main main(int argc, char *argv[])
  209. {
  210. int r;
  211. int i = 1;
  212. lzo_wildargv(&argc, &argv);
  213. printf("\nLZO real-time data compression library (v%s, %s).\n",
  214. lzo_version_string(), lzo_version_date());
  215. printf("Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
  216. progname = argv[0];
  217. if (i < argc && argv[i][0] == '-')
  218. opt_overhead = atol(&argv[i++][1]);
  219. #if 1
  220. if (opt_overhead != 0 && opt_overhead < 4)
  221. {
  222. printf("%s: invalid overhead value %ld\n", progname, opt_overhead);
  223. exit(1);
  224. }
  225. #endif
  226. if (i >= argc)
  227. {
  228. printf("usage: %s [-overhead_in_bytes] file..\n", progname);
  229. exit(1);
  230. }
  231. /*
  232. * Step 1: initialize the LZO library
  233. */
  234. if (lzo_init() != LZO_E_OK)
  235. {
  236. printf("internal error - lzo_init() failed !!!\n");
  237. printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
  238. exit(1);
  239. }
  240. /*
  241. * Step 2: process files
  242. */
  243. for (r = 0; r == 0 && i < argc; i++)
  244. r = do_file(argv[i]);
  245. printf("\nDone. Successfully processed %lu bytes in %lu files.\n",
  246. total_in, total_files);
  247. return r;
  248. }
  249. /* vim:set ts=4 sw=4 et: */