blockStreaming_doubleBuffer.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // LZ4 streaming API example : double buffer
  2. // Copyright : Takayuki Matsuoka
  3. #if defined(_MSC_VER) && (_MSC_VER <= 1800) /* Visual Studio <= 2013 */
  4. # define _CRT_SECURE_NO_WARNINGS
  5. # define snprintf sprintf_s
  6. #endif
  7. #include "lz4.h"
  8. #include <stdio.h>
  9. #include <stdint.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. enum {
  13. BLOCK_BYTES = 1024 * 8,
  14. // BLOCK_BYTES = 1024 * 64,
  15. };
  16. size_t write_int(FILE* fp, int i) {
  17. return fwrite(&i, sizeof(i), 1, fp);
  18. }
  19. size_t write_bin(FILE* fp, const void* array, size_t arrayBytes) {
  20. return fwrite(array, 1, arrayBytes, fp);
  21. }
  22. size_t read_int(FILE* fp, int* i) {
  23. return fread(i, sizeof(*i), 1, fp);
  24. }
  25. size_t read_bin(FILE* fp, void* array, size_t arrayBytes) {
  26. return fread(array, 1, arrayBytes, fp);
  27. }
  28. void test_compress(FILE* outFp, FILE* inpFp)
  29. {
  30. LZ4_stream_t lz4Stream_body;
  31. LZ4_stream_t* lz4Stream = &lz4Stream_body;
  32. char inpBuf[2][BLOCK_BYTES];
  33. int inpBufIndex = 0;
  34. LZ4_initStream(lz4Stream, sizeof (*lz4Stream));
  35. for(;;) {
  36. char* const inpPtr = inpBuf[inpBufIndex];
  37. const int inpBytes = (int) read_bin(inpFp, inpPtr, BLOCK_BYTES);
  38. if(0 == inpBytes) {
  39. break;
  40. }
  41. {
  42. char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)];
  43. const int cmpBytes = LZ4_compress_fast_continue(
  44. lz4Stream, inpPtr, cmpBuf, inpBytes, sizeof(cmpBuf), 1);
  45. if(cmpBytes <= 0) {
  46. break;
  47. }
  48. write_int(outFp, cmpBytes);
  49. write_bin(outFp, cmpBuf, (size_t) cmpBytes);
  50. }
  51. inpBufIndex = (inpBufIndex + 1) % 2;
  52. }
  53. write_int(outFp, 0);
  54. }
  55. void test_decompress(FILE* outFp, FILE* inpFp)
  56. {
  57. LZ4_streamDecode_t lz4StreamDecode_body;
  58. LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body;
  59. char decBuf[2][BLOCK_BYTES];
  60. int decBufIndex = 0;
  61. LZ4_setStreamDecode(lz4StreamDecode, NULL, 0);
  62. for(;;) {
  63. char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)];
  64. int cmpBytes = 0;
  65. {
  66. const size_t readCount0 = read_int(inpFp, &cmpBytes);
  67. if(readCount0 != 1 || cmpBytes <= 0) {
  68. break;
  69. }
  70. const size_t readCount1 = read_bin(inpFp, cmpBuf, (size_t) cmpBytes);
  71. if(readCount1 != (size_t) cmpBytes) {
  72. break;
  73. }
  74. }
  75. {
  76. char* const decPtr = decBuf[decBufIndex];
  77. const int decBytes = LZ4_decompress_safe_continue(
  78. lz4StreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES);
  79. if(decBytes <= 0) {
  80. break;
  81. }
  82. write_bin(outFp, decPtr, (size_t) decBytes);
  83. }
  84. decBufIndex = (decBufIndex + 1) % 2;
  85. }
  86. }
  87. int compare(FILE* fp0, FILE* fp1)
  88. {
  89. int result = 0;
  90. while(0 == result) {
  91. char b0[65536];
  92. char b1[65536];
  93. const size_t r0 = read_bin(fp0, b0, sizeof(b0));
  94. const size_t r1 = read_bin(fp1, b1, sizeof(b1));
  95. result = (int) r0 - (int) r1;
  96. if(0 == r0 || 0 == r1) {
  97. break;
  98. }
  99. if(0 == result) {
  100. result = memcmp(b0, b1, r0);
  101. }
  102. }
  103. return result;
  104. }
  105. int main(int argc, char* argv[])
  106. {
  107. char inpFilename[256] = { 0 };
  108. char lz4Filename[256] = { 0 };
  109. char decFilename[256] = { 0 };
  110. if(argc < 2) {
  111. printf("Please specify input filename\n");
  112. return 0;
  113. }
  114. snprintf(inpFilename, 256, "%s", argv[1]);
  115. snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], BLOCK_BYTES);
  116. snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], BLOCK_BYTES);
  117. printf("inp = [%s]\n", inpFilename);
  118. printf("lz4 = [%s]\n", lz4Filename);
  119. printf("dec = [%s]\n", decFilename);
  120. // compress
  121. {
  122. FILE* inpFp = fopen(inpFilename, "rb");
  123. FILE* outFp = fopen(lz4Filename, "wb");
  124. printf("compress : %s -> %s\n", inpFilename, lz4Filename);
  125. test_compress(outFp, inpFp);
  126. printf("compress : done\n");
  127. fclose(outFp);
  128. fclose(inpFp);
  129. }
  130. // decompress
  131. {
  132. FILE* inpFp = fopen(lz4Filename, "rb");
  133. FILE* outFp = fopen(decFilename, "wb");
  134. printf("decompress : %s -> %s\n", lz4Filename, decFilename);
  135. test_decompress(outFp, inpFp);
  136. printf("decompress : done\n");
  137. fclose(outFp);
  138. fclose(inpFp);
  139. }
  140. // verify
  141. {
  142. FILE* inpFp = fopen(inpFilename, "rb");
  143. FILE* decFp = fopen(decFilename, "rb");
  144. printf("verify : %s <-> %s\n", inpFilename, decFilename);
  145. const int cmp = compare(inpFp, decFp);
  146. if(0 == cmp) {
  147. printf("verify : OK\n");
  148. } else {
  149. printf("verify : NG\n");
  150. }
  151. fclose(decFp);
  152. fclose(inpFp);
  153. }
  154. return 0;
  155. }