yaz0 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,434 @@
1
+ #include <string.h>
2
+ #include <stdio.h>
3
+ #include "libyaz0.h"
4
+
5
+ static const uint32_t kProbesPerLevel[] = {
6
+ 0x0,
7
+ 0x1,
8
+ 0x2,
9
+ 0x4,
10
+ 0x8,
11
+ 0x10,
12
+ 0x40,
13
+ 0x100,
14
+ 0x200,
15
+ 0x1000
16
+ };
17
+
18
+ static uint32_t hash(uint8_t a, uint8_t b, uint8_t c)
19
+ {
20
+ uint32_t x = (uint32_t)a | ((uint32_t)b << 8) | ((uint32_t)c << 16);
21
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
22
+ x = (x >> 16) ^ x;
23
+ return x;
24
+ }
25
+
26
+ static void hashWrite(Yaz0Stream* s, uint32_t h, uint32_t offset)
27
+ {
28
+ uint32_t maxProbes;
29
+ uint32_t bucket;
30
+ uint32_t tmpBucket;
31
+ uint32_t oldest;
32
+ uint32_t entry;
33
+ int32_t pos;
34
+
35
+ oldest = 0xffffffff;
36
+ maxProbes = kProbesPerLevel[s->level];
37
+ for (uint32_t i = 0; i < maxProbes; ++i)
38
+ {
39
+ tmpBucket = (h + i) % HASH_MAX_ENTRIES;
40
+ entry = s->htEntries[tmpBucket];
41
+ if (entry == 0xffffffff)
42
+ {
43
+ s->htSize++;
44
+ bucket = tmpBucket;
45
+ break;
46
+ }
47
+ pos = (int32_t)(s->totalOut - entry);
48
+ if (pos > 0x1000)
49
+ {
50
+ bucket = tmpBucket;
51
+ break;
52
+ }
53
+ if (entry < oldest)
54
+ {
55
+ oldest = entry;
56
+ bucket = tmpBucket;
57
+ }
58
+ }
59
+ s->htEntries[bucket] = s->totalOut + offset;
60
+ s->htHashes[bucket] = h;
61
+ }
62
+
63
+ static void rebuildHashTable(Yaz0Stream* s)
64
+ {
65
+ uint32_t newEntries[HASH_MAX_ENTRIES];
66
+ uint32_t newHashes[HASH_MAX_ENTRIES];
67
+ uint32_t entry;
68
+ uint32_t pos;
69
+ uint32_t h;
70
+ uint32_t bucket;
71
+ uint32_t size;
72
+
73
+ memset(newEntries, 0xff, sizeof(newEntries));
74
+ memset(newHashes, 0xff, sizeof(newHashes));
75
+ size = 0;
76
+
77
+ for (uint32_t i = 0; i < HASH_MAX_ENTRIES; ++i)
78
+ {
79
+ entry = s->htEntries[i];
80
+ if (entry == 0xffffffff)
81
+ continue;
82
+ pos = s->totalOut - entry;
83
+ if (pos > 0x1000)
84
+ continue;
85
+
86
+ /* Entry still good - move to the table */
87
+ h = s->htHashes[i];
88
+ bucket = h % HASH_MAX_ENTRIES;
89
+ for (;;)
90
+ {
91
+ if (newEntries[bucket] == 0xffffffff)
92
+ {
93
+ newEntries[bucket] = entry;
94
+ newHashes[bucket] = h;
95
+ size++;
96
+ break;
97
+ }
98
+ bucket = (bucket + 1) % HASH_MAX_ENTRIES;
99
+ }
100
+ }
101
+
102
+ s->htSize = size;
103
+ memcpy(s->htEntries, newEntries, sizeof(newEntries));
104
+ memcpy(s->htHashes, newHashes, sizeof(newHashes));
105
+ }
106
+
107
+ static uint32_t maxSize(Yaz0Stream* stream)
108
+ {
109
+ /* the extra byte is for look-aheads */
110
+ static const uint32_t maxNecessary = 0x888 + 1;
111
+ uint32_t max;
112
+
113
+ max = stream->decompSize - stream->totalOut;
114
+ if (max > maxNecessary)
115
+ max = maxNecessary;
116
+ return max;
117
+ }
118
+
119
+ /* start: start of avail data */
120
+ /* end: end of avail data */
121
+ /* We need to write more data at the end of the window */
122
+
123
+ static int feed(Yaz0Stream* s)
124
+ {
125
+ uint32_t avail;
126
+ uint32_t min;
127
+ uint32_t max;
128
+ uint32_t size;
129
+ int ret;
130
+
131
+ /* Check how much data we have */
132
+ if (s->window_start > s->window_end)
133
+ avail = WINDOW_SIZE - s->window_start + s->window_end;
134
+ else
135
+ avail = s->window_end - s->window_start;
136
+ if (avail >= maxSize(s))
137
+ return YAZ0_OK;
138
+
139
+ /* We need more data */
140
+ min = maxSize(s) - avail;
141
+ max = WINDOW_SIZE - 0x1000 - avail;
142
+ if (max > s->sizeIn - s->cursorIn)
143
+ max = s->sizeIn - s->cursorIn;
144
+ if (max < min)
145
+ ret = YAZ0_NEED_AVAIL_IN;
146
+ else
147
+ ret = YAZ0_OK;
148
+ if (s->window_end + max >= WINDOW_SIZE)
149
+ {
150
+ /* We might need two copies */
151
+ size = WINDOW_SIZE - s->window_end;
152
+ memcpy(s->window + s->window_end, s->in + s->cursorIn, size);
153
+ s->cursorIn += size;
154
+ s->window_end = 0;
155
+ max -= size;
156
+ }
157
+ memcpy(s->window + s->window_end, s->in + s->cursorIn, max);
158
+ s->cursorIn += max;
159
+ s->window_end += max;
160
+ return ret;
161
+ }
162
+
163
+ static uint32_t matchSize(Yaz0Stream* s, uint32_t offset, uint32_t pos, uint32_t hintSize)
164
+ {
165
+ uint32_t size = 0;
166
+ uint32_t start = s->window_start + offset;
167
+ uint32_t cursorA = (start + WINDOW_SIZE - pos) % WINDOW_SIZE;
168
+ uint32_t cursorB = start % WINDOW_SIZE;
169
+ uint32_t maxSize;
170
+
171
+ maxSize = s->decompSize - s->totalOut;
172
+ if (maxSize > 0x111)
173
+ maxSize = 0x111;
174
+ if (hintSize)
175
+ {
176
+ if (s->window[(cursorA + hintSize) % WINDOW_SIZE] != s->window[(cursorB + hintSize) % WINDOW_SIZE])
177
+ return 0;
178
+ }
179
+ for (;;)
180
+ {
181
+ if (s->window[(cursorA + size) % WINDOW_SIZE] != s->window[(cursorB + size) % WINDOW_SIZE])
182
+ break;
183
+ size++;
184
+ if (size == maxSize)
185
+ break;
186
+ }
187
+ return size;
188
+ }
189
+
190
+ static void findHashMatch(Yaz0Stream* s, uint32_t h, uint32_t offset, uint32_t* outSize, uint32_t* outPos)
191
+ {
192
+ uint32_t bucket;
193
+ uint32_t entry;
194
+ uint32_t bestSize;
195
+ uint32_t bestPos;
196
+ uint32_t size;
197
+ uint32_t pos;
198
+ uint32_t maxProbes;
199
+
200
+ bestSize = 0;
201
+ bestPos = 0;
202
+ maxProbes = kProbesPerLevel[s->level];
203
+ for (uint32_t i = 0; i < maxProbes; ++i)
204
+ {
205
+ bucket = (h + i) % HASH_MAX_ENTRIES;
206
+ entry = s->htEntries[bucket];
207
+ if (entry == 0xffffffff)
208
+ break;
209
+ if (s->htHashes[bucket] == h)
210
+ {
211
+ pos = s->totalOut + offset - entry;
212
+ if (pos > 0x1000)
213
+ continue;
214
+ size = matchSize(s, offset, pos, bestSize);
215
+ if (size > bestSize)
216
+ {
217
+ bestSize = size;
218
+ bestPos = pos;
219
+ }
220
+ }
221
+ }
222
+
223
+ if (bestSize < 3)
224
+ {
225
+ *outSize = 0;
226
+ }
227
+ else
228
+ {
229
+ *outSize = bestSize;
230
+ *outPos = bestPos;
231
+ }
232
+ }
233
+
234
+ static void findEarlyZeroes(Yaz0Stream* s, uint32_t* outSize, uint32_t* outPos)
235
+ {
236
+ uint32_t size;
237
+ uint32_t bestSize;
238
+ uint32_t bestPos;
239
+
240
+ bestSize = 0;
241
+ bestPos = 0;
242
+ for (uint32_t pos = 0x1000; pos > 0x990; --pos)
243
+ {
244
+ size = matchSize(s, 0, pos, 0);
245
+ if (size > bestSize)
246
+ {
247
+ bestSize = size;
248
+ bestPos = pos;
249
+ }
250
+ }
251
+
252
+ if (bestSize < 3)
253
+ {
254
+ *outSize = 0;
255
+ }
256
+ else
257
+ {
258
+ *outSize = bestSize;
259
+ *outPos = bestPos;
260
+ }
261
+ }
262
+
263
+ static void emitGroup(Yaz0Stream* s, int count, const uint32_t* arrSize, const uint32_t* arrPos)
264
+ {
265
+ uint8_t header;
266
+ uint32_t size;
267
+ uint32_t pos;
268
+
269
+ header = 0;
270
+ for (int i = 0; i < count; ++i)
271
+ {
272
+ if (!arrSize[i])
273
+ header |= (1 << (7 - i));
274
+ }
275
+ s->out[s->cursorOut++] = header;
276
+ for (int i = 0; i < count; ++i)
277
+ {
278
+ size = arrSize[i];
279
+ pos = arrPos[i];
280
+ if (!size)
281
+ s->out[s->cursorOut++] = (uint8_t)pos;
282
+ else
283
+ {
284
+ pos--;
285
+ if (size >= 0x12)
286
+ {
287
+ /* 3 bytes */
288
+ s->out[s->cursorOut++] = (uint8_t)(pos >> 8);
289
+ s->out[s->cursorOut++] = (uint8_t)pos;
290
+ s->out[s->cursorOut++] = (uint8_t)(size - 0x12);
291
+ }
292
+ else
293
+ {
294
+ /* 2 bytes */
295
+ s->out[s->cursorOut++] = (uint8_t)(pos >> 8) | (uint8_t)((size - 2) << 4);
296
+ s->out[s->cursorOut++] = (uint8_t)pos;
297
+ }
298
+ }
299
+ }
300
+ }
301
+
302
+ static void compressGroup(Yaz0Stream* s)
303
+ {
304
+ int groupCount;
305
+ uint32_t h;
306
+ uint32_t size;
307
+ uint32_t pos;
308
+ uint32_t nextSize;
309
+ uint32_t nextPos;
310
+ uint32_t arrSize[8];
311
+ uint32_t arrPos[8];
312
+ uint8_t a;
313
+ uint8_t b;
314
+ uint8_t c;
315
+ uint8_t d;
316
+
317
+ for (groupCount = 0; groupCount < 8; ++groupCount)
318
+ {
319
+ a = s->window[s->window_start];
320
+ b = s->window[(s->window_start + 1) % WINDOW_SIZE];
321
+ c = s->window[(s->window_start + 2) % WINDOW_SIZE];
322
+ d = s->window[(s->window_start + 3) % WINDOW_SIZE];
323
+ h = hash(a, b, c);
324
+ findHashMatch(s, h, 0, &size, &pos);
325
+ hashWrite(s, h, 0);
326
+
327
+ /* Check for early zero */
328
+ if (s->window[s->window_start] == 0 && s->totalOut < 0x1000)
329
+ {
330
+ findEarlyZeroes(s, &nextSize, &nextPos);
331
+ if (nextSize > size)
332
+ {
333
+ size = nextSize;
334
+ pos = nextPos;
335
+ }
336
+ }
337
+
338
+ nextSize = 0;
339
+ nextPos = 0;
340
+ h = hash(b, c, d);
341
+ findHashMatch(s, h, 1, &nextSize, &nextPos);
342
+
343
+ if (!size || nextSize > size)
344
+ {
345
+ arrSize[groupCount] = 0;
346
+ arrPos[groupCount] = s->window[s->window_start];
347
+ s->window_start += 1;
348
+ s->totalOut += 1;
349
+ }
350
+ else
351
+ {
352
+ arrSize[groupCount] = size;
353
+ arrPos[groupCount] = pos;
354
+ for (uint32_t i = 1; i < size; ++i)
355
+ {
356
+ a = b;
357
+ b = c;
358
+ c = s->window[(s->window_start + 2 + i) % WINDOW_SIZE];
359
+ h = hash(a, b, c);
360
+ hashWrite(s, h, i);
361
+ }
362
+ s->window_start += size;
363
+ s->totalOut += size;
364
+ }
365
+ s->window_start %= WINDOW_SIZE;
366
+ if (s->totalOut >= s->decompSize)
367
+ {
368
+ groupCount++;
369
+ break;
370
+ }
371
+ }
372
+ if (s->htSize > HASH_REBUILD)
373
+ rebuildHashTable(s);
374
+ emitGroup(s, groupCount, arrSize, arrPos);
375
+ }
376
+
377
+ int yaz0ModeCompress(Yaz0Stream* s, uint32_t size, int level)
378
+ {
379
+ memset(s, 0, sizeof(*s));
380
+ s->mode = MODE_COMPRESS;
381
+ s->decompSize = size;
382
+ if (level < 1)
383
+ level = 1;
384
+ else if (level > 9)
385
+ level = 9;
386
+ s->level = level;
387
+ for (int i = 0; i < HASH_MAX_ENTRIES; ++i)
388
+ {
389
+ s->htHashes[i] = 0xffffffff;
390
+ s->htEntries[i] = 0xffffffff;
391
+ }
392
+ return YAZ0_OK;
393
+ }
394
+
395
+ int yaz0_RunCompress(Yaz0Stream* stream)
396
+ {
397
+ uint32_t tmp;
398
+ int ret;
399
+
400
+ /* Write headers */
401
+ if (!stream->headersDone)
402
+ {
403
+ if (stream->sizeOut < 16)
404
+ return YAZ0_NEED_AVAIL_OUT;
405
+ memcpy(stream->out, "Yaz0", 4);
406
+ tmp = swap32(stream->decompSize);
407
+ memcpy(stream->out + 4, &tmp, 4);
408
+ tmp = 0;
409
+ memcpy(stream->out + 8, &tmp, 4);
410
+ memcpy(stream->out + 12, &tmp, 4);
411
+ stream->cursorOut += 16;
412
+ stream->headersDone = 1;
413
+ }
414
+
415
+ /* Compress */
416
+ for (;;)
417
+ {
418
+ /* Check EOF */
419
+ if (stream->totalOut >= stream->decompSize)
420
+ return YAZ0_OK;
421
+
422
+ /* Check output space */
423
+ if (stream->sizeOut - stream->cursorOut < 1 + 8 * 3)
424
+ return YAZ0_NEED_AVAIL_OUT;
425
+
426
+ /* Check that we have consumed enough input */
427
+ ret = feed(stream);
428
+ if (ret)
429
+ return ret;
430
+
431
+ /* Compress one chunk */
432
+ compressGroup(stream);
433
+ }
434
+ }
@@ -0,0 +1,197 @@
1
+ #include <string.h>
2
+ #include <stdio.h>
3
+ #include "libyaz0.h"
4
+
5
+ int yaz0ModeDecompress(Yaz0Stream* s)
6
+ {
7
+ memset(s, 0, sizeof(*s));
8
+ s->mode = MODE_DECOMPRESS;
9
+ return YAZ0_OK;
10
+ }
11
+
12
+ void loadAux(Yaz0Stream* stream, uint32_t size)
13
+ {
14
+ if (stream->sizeIn - stream->cursorIn < size)
15
+ size = stream->sizeIn - stream->cursorIn;
16
+ for (uint32_t i = 0; i < size; i++)
17
+ stream->auxBuf[stream->auxSize++] = stream->in[stream->cursorIn++];
18
+ }
19
+
20
+ int flush(Yaz0Stream* stream)
21
+ {
22
+ size_t chunkSize;
23
+ size_t outSize;
24
+
25
+ if (stream->window_start == stream->window_end)
26
+ return YAZ0_OK;
27
+ if (stream->cursorOut >= stream->sizeOut)
28
+ return YAZ0_NEED_AVAIL_OUT;
29
+ outSize = stream->sizeOut - stream->cursorOut;
30
+ if (stream->window_start > stream->window_end)
31
+ {
32
+ /* Wrap around - we will need 2 copies */
33
+ chunkSize = WINDOW_SIZE - stream->window_start;
34
+ if (chunkSize > outSize)
35
+ chunkSize = outSize;
36
+ memcpy(stream->out + stream->cursorOut, stream->window + stream->window_start, chunkSize);
37
+ stream->cursorOut += chunkSize;
38
+ stream->window_start += chunkSize;
39
+ stream->window_start %= WINDOW_SIZE;
40
+ outSize -= chunkSize;
41
+ }
42
+ /* Copy the rest */
43
+ chunkSize = stream->window_end - stream->window_start;
44
+ if (chunkSize > outSize)
45
+ chunkSize = outSize;
46
+ memcpy(stream->out + stream->cursorOut, stream->window + stream->window_start, chunkSize);
47
+ stream->cursorOut += chunkSize;
48
+ stream->window_start += chunkSize;
49
+ return YAZ0_OK;
50
+ }
51
+
52
+ static int yaz0_ReadHeaders(Yaz0Stream* stream)
53
+ {
54
+ loadAux(stream, 16 - stream->auxSize);
55
+ if (stream->auxSize < 16)
56
+ return YAZ0_NEED_AVAIL_IN;
57
+ if (memcmp(stream->auxBuf, "Yaz0", 4))
58
+ return YAZ0_BAD_MAGIC;
59
+ stream->decompSize = swap32(*(uint32_t*)&stream->auxBuf[4]);
60
+ stream->auxSize = 0;
61
+ return YAZ0_OK;
62
+ }
63
+
64
+ static uint32_t windowFreeSize(Yaz0Stream* stream)
65
+ {
66
+ uint32_t size;
67
+ if (stream->window_start > stream->window_end)
68
+ size = WINDOW_SIZE - stream->window_start + stream->window_end;
69
+ else
70
+ size = stream->window_end - stream->window_start;
71
+ return WINDOW_SIZE - size;
72
+ }
73
+
74
+ static int ensureWindowFree(Yaz0Stream* stream)
75
+ {
76
+ static const uint32_t maxSize = 0x111 * 8;
77
+
78
+ if (windowFreeSize(stream) < maxSize)
79
+ {
80
+ flush(stream);
81
+ if (windowFreeSize(stream) < maxSize)
82
+ return YAZ0_NEED_AVAIL_OUT;
83
+ }
84
+ return YAZ0_OK;
85
+ }
86
+
87
+ int yaz0_DoDecompress(Yaz0Stream* stream)
88
+ {
89
+ uint8_t groupBit;
90
+ uint8_t byte;
91
+ int ret;
92
+ uint16_t n;
93
+ uint16_t r;
94
+ for (;;)
95
+ {
96
+ /* No group and no EOF - We need to read */
97
+ if (stream->groupCount == 0)
98
+ {
99
+ /* Before we read, we eant to ensure the window is large enough */
100
+ /* This will avoid a lot of checks and let us write the whole group */
101
+ ret = ensureWindowFree(stream);
102
+ if (ret)
103
+ return ret;
104
+ if (stream->cursorIn >= stream->sizeIn)
105
+ return YAZ0_NEED_AVAIL_IN;
106
+ stream->groupHeader = stream->in[stream->cursorIn++];
107
+ stream->groupCount = 8;
108
+ }
109
+
110
+ /* We have a group! */
111
+ while (stream->groupCount)
112
+ {
113
+ /* Get the group bit */
114
+ groupBit = stream->groupHeader & (1 << (stream->groupCount - 1));
115
+ if (groupBit)
116
+ {
117
+ /* Group bit is 1 - direct write */
118
+ if (stream->cursorIn >= stream->sizeIn)
119
+ return YAZ0_NEED_AVAIL_IN;
120
+
121
+ /* Everything ok, copy the byte */
122
+ byte = stream->in[stream->cursorIn++];
123
+ stream->window[stream->window_end++] = byte;
124
+ stream->window_end %= WINDOW_SIZE;
125
+ stream->totalOut++;
126
+ }
127
+ else
128
+ {
129
+ if (stream->auxSize < 2)
130
+ {
131
+ loadAux(stream, 2 - stream->auxSize);
132
+ if (stream->auxSize < 2)
133
+ return YAZ0_NEED_AVAIL_IN;
134
+ }
135
+ /* Do we need 2 or 3 bytes? */
136
+ n = ((uint8_t)stream->auxBuf[0]) >> 4;
137
+ if (!n)
138
+ {
139
+ /* We have a large chunk */
140
+ loadAux(stream, 1);
141
+ if (stream->auxSize < 3)
142
+ return YAZ0_NEED_AVAIL_IN;
143
+ n = (uint8_t)stream->auxBuf[2] + 0x12;
144
+ }
145
+ else
146
+ {
147
+ /* We have a small chunk */
148
+ n = ((uint8_t)stream->auxBuf[0] >> 4) + 2;
149
+ }
150
+ r = ((uint16_t)(((uint8_t)stream->auxBuf[0] & 0x0f) << 8) | ((uint8_t)stream->auxBuf[1]));
151
+ r++;
152
+ /* Reset the aux buffer */
153
+ uint32_t cursor = (stream->window_end + WINDOW_SIZE - r) % WINDOW_SIZE;
154
+ for (int i = 0; i < n; ++i)
155
+ {
156
+ stream->window[stream->window_end++] = stream->window[cursor++];
157
+ stream->window_end %= WINDOW_SIZE;
158
+ cursor %= WINDOW_SIZE;
159
+ }
160
+ stream->auxSize = 0;
161
+ stream->totalOut += n;
162
+ }
163
+ stream->groupCount--;
164
+ /* Check for EOF */
165
+ if (stream->totalOut >= stream->decompSize)
166
+ return YAZ0_OK;
167
+ }
168
+ }
169
+ }
170
+
171
+ int yaz0_RunDecompress(Yaz0Stream* stream)
172
+ {
173
+ int ret;
174
+
175
+ /* Check the headers */
176
+ if (!stream->headersDone)
177
+ {
178
+ ret = yaz0_ReadHeaders(stream);
179
+ if (ret)
180
+ return ret;
181
+ stream->headersDone = 1;
182
+ }
183
+
184
+ if (stream->totalOut < stream->decompSize)
185
+ {
186
+ /* We did not decompress everything */
187
+ ret = yaz0_DoDecompress(stream);
188
+ if (ret)
189
+ return ret;
190
+ }
191
+
192
+ /* We did decompress everything */
193
+ flush(stream);
194
+ if (stream->window_start != stream->window_end)
195
+ return YAZ0_NEED_AVAIL_OUT;
196
+ return YAZ0_OK;
197
+ }
@@ -0,0 +1,64 @@
1
+ #include <stdlib.h>
2
+ #include "libyaz0.h"
3
+
4
+ int yaz0Init(Yaz0Stream** ptr)
5
+ {
6
+ Yaz0Stream* s;
7
+
8
+ s = malloc(sizeof(*s));
9
+ if (!s)
10
+ return YAZ0_OUT_OF_MEMORY;
11
+ s->mode = MODE_NONE;
12
+ s->cursorOut = 0;
13
+ s->decompSize = 0;
14
+ *ptr = s;
15
+ return YAZ0_OK;
16
+ }
17
+
18
+ int yaz0Destroy(Yaz0Stream* stream)
19
+ {
20
+ free(stream);
21
+ return YAZ0_OK;
22
+ }
23
+
24
+ int yaz0Run(Yaz0Stream* s)
25
+ {
26
+ switch (s->mode)
27
+ {
28
+ case MODE_NONE:
29
+ return YAZ0_OK;
30
+ case MODE_DECOMPRESS:
31
+ return yaz0_RunDecompress(s);
32
+ case MODE_COMPRESS:
33
+ return yaz0_RunCompress(s);
34
+ default:
35
+ unreachable();
36
+ }
37
+ }
38
+
39
+ int yaz0Input(Yaz0Stream* stream, const void* data, uint32_t size)
40
+ {
41
+ stream->in = data;
42
+ stream->sizeIn = size;
43
+ stream->cursorIn = 0;
44
+
45
+ return YAZ0_OK;
46
+ }
47
+
48
+ int yaz0Output(Yaz0Stream* stream, void* data, uint32_t size)
49
+ {
50
+ stream->out = data;
51
+ stream->sizeOut = size;
52
+ stream->cursorOut = 0;
53
+ return YAZ0_OK;
54
+ }
55
+
56
+ uint32_t yaz0OutputChunkSize(const Yaz0Stream* stream)
57
+ {
58
+ return stream->cursorOut;
59
+ }
60
+
61
+ uint32_t yaz0DecompressedSize(const Yaz0Stream* stream)
62
+ {
63
+ return stream->decompSize;
64
+ }