Rizin
unix-like reverse engineering framework and cli tools
dictionaryRandomAccess.c File Reference
#include "lz4.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

Go to the source code of this file.

Macros

#define MIN(x, y)   ((x) < (y) ? (x) : (y))
 

Enumerations

enum  { BLOCK_BYTES = 1024 , DICTIONARY_BYTES = 1024 , MAX_BLOCKS = 1024 }
 

Functions

void write_int (FILE *fp, int i)
 
void write_bin (FILE *fp, const void *array, size_t arrayBytes)
 
void read_int (FILE *fp, int *i)
 
size_t read_bin (FILE *fp, void *array, size_t arrayBytes)
 
void seek_bin (FILE *fp, long offset, int origin)
 
void test_compress (FILE *outFp, FILE *inpFp, void *dict, int dictSize)
 
void test_decompress (FILE *outFp, FILE *inpFp, void *dict, int dictSize, int offset, int length)
 
int compare (FILE *fp0, FILE *fp1, int length)
 
int main (int argc, char *argv[])
 

Variables

const char kTestMagic [] = { 'T', 'E', 'S', 'T' }
 

Macro Definition Documentation

◆ MIN

#define MIN (   x,
 
)    ((x) < (y) ? (x) : (y))

Definition at line 14 of file dictionaryRandomAccess.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
BLOCK_BYTES 
DICTIONARY_BYTES 
MAX_BLOCKS 

Definition at line 16 of file dictionaryRandomAccess.c.

16  {
17  BLOCK_BYTES = 1024, /* 1 KiB of uncompressed data in a block */
18  DICTIONARY_BYTES = 1024, /* Load a 1 KiB dictionary */
19  MAX_BLOCKS = 1024 /* For simplicity of implementation */
20 };
@ DICTIONARY_BYTES

Function Documentation

◆ compare()

int compare ( FILE *  fp0,
FILE *  fp1,
int  length 
)

Definition at line 173 of file dictionaryRandomAccess.c.

174 {
175  int result = 0;
176 
177  while(0 == result) {
178  char b0[4096];
179  char b1[4096];
180  const size_t r0 = read_bin(fp0, b0, MIN(length, (int)sizeof(b0)));
181  const size_t r1 = read_bin(fp1, b1, MIN(length, (int)sizeof(b1)));
182 
183  result = (int) r0 - (int) r1;
184 
185  if(0 == r0 || 0 == r1) {
186  break;
187  }
188  if(0 == result) {
189  result = memcmp(b0, b1, r0);
190  }
191  length -= r0;
192  }
193 
194  return result;
195 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
size_t read_bin(FILE *fp, void *array, size_t arrayBytes)
#define MIN(x, y)
static int
Definition: sfsocketcall.h:114

References b1, int, length, MIN, r0, r1, and read_bin().

Referenced by main().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 198 of file dictionaryRandomAccess.c.

199 {
200  char inpFilename[256] = { 0 };
201  char lz4Filename[256] = { 0 };
202  char decFilename[256] = { 0 };
203  char dictFilename[256] = { 0 };
204  int offset;
205  int length;
206  char dict[DICTIONARY_BYTES];
207  int dictSize;
208 
209  if(argc < 5) {
210  printf("Usage: %s input dictionary offset length", argv[0]);
211  return 0;
212  }
213 
214  snprintf(inpFilename, 256, "%s", argv[1]);
215  snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], BLOCK_BYTES);
216  snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], BLOCK_BYTES);
217  snprintf(dictFilename, 256, "%s", argv[2]);
218  offset = atoi(argv[3]);
219  length = atoi(argv[4]);
220 
221  printf("inp = [%s]\n", inpFilename);
222  printf("lz4 = [%s]\n", lz4Filename);
223  printf("dec = [%s]\n", decFilename);
224  printf("dict = [%s]\n", dictFilename);
225  printf("offset = [%d]\n", offset);
226  printf("length = [%d]\n", length);
227 
228  /* Load dictionary */
229  {
230  FILE* dictFp = fopen(dictFilename, "rb");
231  dictSize = (int)read_bin(dictFp, dict, DICTIONARY_BYTES);
232  fclose(dictFp);
233  }
234 
235  /* compress */
236  {
237  FILE* inpFp = fopen(inpFilename, "rb");
238  FILE* outFp = fopen(lz4Filename, "wb");
239 
240  printf("compress : %s -> %s\n", inpFilename, lz4Filename);
241  test_compress(outFp, inpFp, dict, dictSize);
242  printf("compress : done\n");
243 
244  fclose(outFp);
245  fclose(inpFp);
246  }
247 
248  /* decompress */
249  {
250  FILE* inpFp = fopen(lz4Filename, "rb");
251  FILE* outFp = fopen(decFilename, "wb");
252 
253  printf("decompress : %s -> %s\n", lz4Filename, decFilename);
254  test_decompress(outFp, inpFp, dict, DICTIONARY_BYTES, offset, length);
255  printf("decompress : done\n");
256 
257  fclose(outFp);
258  fclose(inpFp);
259  }
260 
261  /* verify */
262  {
263  FILE* inpFp = fopen(inpFilename, "rb");
264  FILE* decFp = fopen(decFilename, "rb");
265  seek_bin(inpFp, offset, SEEK_SET);
266 
267  printf("verify : %s <-> %s\n", inpFilename, decFilename);
268  const int cmp = compare(inpFp, decFp, length);
269  if(0 == cmp) {
270  printf("verify : OK\n");
271  } else {
272  printf("verify : NG\n");
273  }
274 
275  fclose(decFp);
276  fclose(inpFp);
277  }
278 
279  return 0;
280 }
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
void seek_bin(FILE *fp, long offset, int origin)
void test_compress(FILE *outFp, FILE *inpFp, void *dict, int dictSize)
int compare(FILE *fp0, FILE *fp1, int length)
void test_decompress(FILE *outFp, FILE *inpFp, void *dict, int dictSize, int offset, int length)
voidpf uLong offset
Definition: ioapi.h:144
snprintf
Definition: kernel.h:364
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
string FILE
Definition: benchmark.py:21
#define SEEK_SET
Definition: zip.c:88

References argv, BLOCK_BYTES, cmp(), compare(), DICTIONARY_BYTES, benchmark::FILE, int, length, printf(), read_bin(), seek_bin(), SEEK_SET, snprintf, test_compress(), and test_decompress().

◆ read_bin()

size_t read_bin ( FILE *  fp,
void *  array,
size_t  arrayBytes 
)

Definition at line 45 of file dictionaryRandomAccess.c.

45  {
46  size_t read = fread(array, 1, arrayBytes, fp);
47  if (ferror(fp)) { exit(12); }
48  return read;
49 }
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References test-lz4-list::exit, and read().

Referenced by compare(), main(), test_compress(), and test_decompress().

◆ read_int()

void read_int ( FILE *  fp,
int i 
)

Definition at line 40 of file dictionaryRandomAccess.c.

40  {
41  size_t read = fread(i, sizeof(*i), 1, fp);
42  if (read != 1) { exit(12); }
43 }
lzma_index ** i
Definition: index.h:629

References test-lz4-list::exit, i, and read().

Referenced by test_decompress().

◆ seek_bin()

void seek_bin ( FILE *  fp,
long  offset,
int  origin 
)

Definition at line 51 of file dictionaryRandomAccess.c.

51  {
52  if (fseek(fp, offset, origin)) { exit(14); }
53 }
voidpf uLong int origin
Definition: ioapi.h:144

References test-lz4-list::exit.

Referenced by main(), and test_decompress().

◆ test_compress()

void test_compress ( FILE *  outFp,
FILE *  inpFp,
void *  dict,
int  dictSize 
)

Definition at line 56 of file dictionaryRandomAccess.c.

57 {
58  LZ4_stream_t lz4Stream_body;
59  LZ4_stream_t* lz4Stream = &lz4Stream_body;
60 
61  char inpBuf[BLOCK_BYTES];
62  int offsets[MAX_BLOCKS];
63  int *offsetsEnd = offsets;
64 
65 
66  LZ4_initStream(lz4Stream, sizeof(*lz4Stream));
67 
68  /* Write header magic */
69  write_bin(outFp, kTestMagic, sizeof(kTestMagic));
70 
71  *offsetsEnd++ = sizeof(kTestMagic);
72  /* Write compressed data blocks. Each block contains BLOCK_BYTES of plain
73  data except possibly the last. */
74  for(;;) {
75  const int inpBytes = (int) read_bin(inpFp, inpBuf, BLOCK_BYTES);
76  if(0 == inpBytes) {
77  break;
78  }
79 
80  /* Forget previously compressed data and load the dictionary */
81  LZ4_loadDict(lz4Stream, dict, dictSize);
82  {
83  char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)];
84  const int cmpBytes = LZ4_compress_fast_continue(
85  lz4Stream, inpBuf, cmpBuf, inpBytes, sizeof(cmpBuf), 1);
86  if(cmpBytes <= 0) { exit(1); }
87  write_bin(outFp, cmpBuf, (size_t)cmpBytes);
88  /* Keep track of the offsets */
89  *offsetsEnd = *(offsetsEnd - 1) + cmpBytes;
90  ++offsetsEnd;
91  }
92  if (offsetsEnd - offsets > MAX_BLOCKS) { exit(2); }
93  }
94  /* Write the tailing jump table */
95  {
96  int *ptr = offsets;
97  while (ptr != offsetsEnd) {
98  write_int(outFp, *ptr++);
99  }
100  write_int(outFp, offsetsEnd - offsets);
101  }
102 }
void write_int(FILE *fp, int i)
void write_bin(FILE *fp, const void *array, size_t arrayBytes)
const char kTestMagic[]
int LZ4_loadDict(LZ4_stream_t *LZ4_dict, const char *dictionary, int dictSize)
Definition: lz4.c:1475
LZ4_stream_t * LZ4_initStream(void *buffer, size_t size)
Definition: lz4.c:1443
int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
Definition: lz4.c:1565
#define LZ4_COMPRESSBOUND(isize)
Definition: lz4.h:171

References BLOCK_BYTES, test-lz4-list::exit, int, kTestMagic, LZ4_compress_fast_continue(), LZ4_COMPRESSBOUND, LZ4_initStream(), LZ4_loadDict(), MAX_BLOCKS, read_bin(), write_bin(), and write_int().

Referenced by main().

◆ test_decompress()

void test_decompress ( FILE *  outFp,
FILE *  inpFp,
void *  dict,
int  dictSize,
int  offset,
int  length 
)

Definition at line 105 of file dictionaryRandomAccess.c.

106 {
107  LZ4_streamDecode_t lz4StreamDecode_body;
108  LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body;
109 
110  /* The blocks [currentBlock, endBlock) contain the data we want */
111  int currentBlock = offset / BLOCK_BYTES;
112  int endBlock = ((offset + length - 1) / BLOCK_BYTES) + 1;
113 
114  char decBuf[BLOCK_BYTES];
115  int offsets[MAX_BLOCKS];
116 
117  /* Special cases */
118  if (length == 0) { return; }
119 
120  /* Read the magic bytes */
121  {
122  char magic[sizeof(kTestMagic)];
123  size_t read = read_bin(inpFp, magic, sizeof(magic));
124  if (read != sizeof(magic)) { exit(1); }
125  if (memcmp(kTestMagic, magic, sizeof(magic))) { exit(2); }
126  }
127 
128  /* Read the offsets tail */
129  {
130  int numOffsets;
131  int block;
132  int *offsetsPtr = offsets;
133  seek_bin(inpFp, -4, SEEK_END);
134  read_int(inpFp, &numOffsets);
135  if (numOffsets <= endBlock) { exit(3); }
136  seek_bin(inpFp, -4 * (numOffsets + 1), SEEK_END);
137  for (block = 0; block <= endBlock; ++block) {
138  read_int(inpFp, offsetsPtr++);
139  }
140  }
141  /* Seek to the first block to read */
142  seek_bin(inpFp, offsets[currentBlock], SEEK_SET);
144 
145  /* Start decoding */
146  for(; currentBlock < endBlock; ++currentBlock) {
147  char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)];
148  /* The difference in offsets is the size of the block */
149  int cmpBytes = offsets[currentBlock + 1] - offsets[currentBlock];
150  {
151  const size_t read = read_bin(inpFp, cmpBuf, (size_t)cmpBytes);
152  if(read != (size_t)cmpBytes) { exit(4); }
153  }
154 
155  /* Load the dictionary */
156  LZ4_setStreamDecode(lz4StreamDecode, dict, dictSize);
157  {
158  const int decBytes = LZ4_decompress_safe_continue(
159  lz4StreamDecode, cmpBuf, decBuf, cmpBytes, BLOCK_BYTES);
160  if(decBytes <= 0) { exit(5); }
161  {
162  /* Write out the part of the data we care about */
163  int blockLength = MIN(length, (decBytes - offset));
164  write_bin(outFp, decBuf + offset, (size_t)blockLength);
165  offset = 0;
166  length -= blockLength;
167  }
168  }
169  }
170 }
void read_int(FILE *fp, int *i)
int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize)
Definition: lz4.c:2285
LZ4_FORCE_O2 int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest, int compressedSize, int maxOutputSize)
Definition: lz4.c:2322
#define SEEK_END
Definition: zip.c:84

References BLOCK_BYTES, test-lz4-list::exit, kTestMagic, length, LZ4_COMPRESSBOUND, LZ4_decompress_safe_continue(), LZ4_setStreamDecode(), MAX_BLOCKS, MIN, read(), read_bin(), read_int(), seek_bin(), SEEK_END, SEEK_SET, and write_bin().

Referenced by main().

◆ write_bin()

void write_bin ( FILE *  fp,
const void *  array,
size_t  arrayBytes 
)

Definition at line 35 of file dictionaryRandomAccess.c.

35  {
36  size_t written = fwrite(array, 1, arrayBytes, fp);
37  if (written != arrayBytes) { exit(11); }
38 }

References test-lz4-list::exit.

Referenced by test_compress(), and test_decompress().

◆ write_int()

void write_int ( FILE *  fp,
int  i 
)

Definition at line 30 of file dictionaryRandomAccess.c.

30  {
31  size_t written = fwrite(&i, sizeof(i), 1, fp);
32  if (written != 1) { exit(10); }
33 }

References test-lz4-list::exit, and i.

Referenced by test_compress().

Variable Documentation

◆ kTestMagic

const char kTestMagic[] = { 'T', 'E', 'S', 'T' }

Magic bytes for this test case. This is not a great magic number because it is a common word in ASCII. However, it is important to have some versioning system in your format.

Definition at line 27 of file dictionaryRandomAccess.c.

Referenced by test_compress(), and test_decompress().