~mmach/netext73/lz4

« back to all changes in this revision

Viewing changes to lib/lz4file.c

  • Committer: mmach
  • Date: 2022-11-09 18:52:10 UTC
  • Revision ID: netbit73@gmail.com-20221109185210-w358idlhh0phq688
1.9.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * LZ4 file library
 
3
 * Copyright (C) 2022, Xiaomi Inc.
 
4
 *
 
5
 * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions are
 
9
 * met:
 
10
 *
 
11
 * - Redistributions of source code must retain the above copyright
 
12
 *   notice, this list of conditions and the following disclaimer.
 
13
 * - Redistributions in binary form must reproduce the above
 
14
 *   copyright notice, this list of conditions and the following disclaimer
 
15
 *   in the documentation and/or other materials provided with the
 
16
 *   distribution.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 *
 
30
 * You can contact the author at :
 
31
 * - LZ4 homepage : http://www.lz4.org
 
32
 * - LZ4 source repository : https://github.com/lz4/lz4
 
33
 */
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
#include "lz4.h"
 
37
#include "lz4file.h"
 
38
 
 
39
struct LZ4_readFile_s {
 
40
  LZ4F_dctx* dctxPtr;
 
41
  FILE* fp;
 
42
  LZ4_byte* srcBuf;
 
43
  size_t srcBufNext;
 
44
  size_t srcBufSize;
 
45
  size_t srcBufMaxSize;
 
46
};
 
47
 
 
48
struct LZ4_writeFile_s {
 
49
  LZ4F_cctx* cctxPtr;
 
50
  FILE* fp;
 
51
  LZ4_byte* dstBuf;
 
52
  size_t maxWriteSize;
 
53
  size_t dstBufMaxSize;
 
54
  LZ4F_errorCode_t errCode;
 
55
};
 
56
 
 
57
LZ4F_errorCode_t LZ4F_readOpen(LZ4_readFile_t** lz4fRead, FILE* fp)
 
58
{
 
59
  char buf[LZ4F_HEADER_SIZE_MAX];
 
60
  size_t consumedSize;
 
61
  LZ4F_errorCode_t ret;
 
62
  LZ4F_frameInfo_t info;
 
63
 
 
64
  if (fp == NULL || lz4fRead == NULL) {
 
65
    return -LZ4F_ERROR_GENERIC;
 
66
  }
 
67
 
 
68
  *lz4fRead = (LZ4_readFile_t*)calloc(1, sizeof(LZ4_readFile_t));
 
69
  if (*lz4fRead == NULL) {
 
70
    return -LZ4F_ERROR_allocation_failed;
 
71
  }
 
72
 
 
73
  ret = LZ4F_createDecompressionContext(&(*lz4fRead)->dctxPtr, LZ4F_getVersion());
 
74
  if (LZ4F_isError(ret)) {
 
75
    free(*lz4fRead);
 
76
    return ret;
 
77
  }
 
78
 
 
79
  (*lz4fRead)->fp = fp;
 
80
  consumedSize = fread(buf, 1, sizeof(buf), (*lz4fRead)->fp);
 
81
  if (consumedSize != sizeof(buf)) {
 
82
    free(*lz4fRead);
 
83
    return -LZ4F_ERROR_GENERIC;
 
84
  }
 
85
 
 
86
  ret = LZ4F_getFrameInfo((*lz4fRead)->dctxPtr, &info, buf, &consumedSize);
 
87
  if (LZ4F_isError(ret)) {
 
88
      LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
 
89
      free(*lz4fRead);
 
90
      return ret;
 
91
    }
 
92
 
 
93
  switch (info.blockSizeID) {
 
94
    case LZ4F_default :
 
95
    case LZ4F_max64KB :
 
96
      (*lz4fRead)->srcBufMaxSize = 64 * 1024;
 
97
      break;
 
98
    case LZ4F_max256KB:
 
99
      (*lz4fRead)->srcBufMaxSize = 256 * 1024;
 
100
      break;
 
101
    case LZ4F_max1MB:
 
102
      (*lz4fRead)->srcBufMaxSize = 1 * 1024 * 1024;
 
103
      break;
 
104
    case LZ4F_max4MB:
 
105
      (*lz4fRead)->srcBufMaxSize = 4 * 1024 * 1024;
 
106
      break;
 
107
    default:
 
108
      LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
 
109
      free(*lz4fRead);
 
110
      return -LZ4F_ERROR_maxBlockSize_invalid;
 
111
  }
 
112
 
 
113
  (*lz4fRead)->srcBuf = (LZ4_byte*)malloc((*lz4fRead)->srcBufMaxSize);
 
114
  if ((*lz4fRead)->srcBuf == NULL) {
 
115
    LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
 
116
    free(lz4fRead);
 
117
    return -LZ4F_ERROR_allocation_failed;
 
118
  }
 
119
 
 
120
  (*lz4fRead)->srcBufSize = sizeof(buf) - consumedSize;
 
121
  memcpy((*lz4fRead)->srcBuf, buf + consumedSize, (*lz4fRead)->srcBufSize);
 
122
 
 
123
  return ret;
 
124
}
 
125
 
 
126
size_t LZ4F_read(LZ4_readFile_t* lz4fRead, void* buf, size_t size)
 
127
{
 
128
  LZ4_byte* p = (LZ4_byte*)buf;
 
129
  size_t next = 0;
 
130
 
 
131
  if (lz4fRead == NULL || buf == NULL)
 
132
    return -LZ4F_ERROR_GENERIC;
 
133
 
 
134
  while (next < size) {
 
135
    size_t srcsize = lz4fRead->srcBufSize - lz4fRead->srcBufNext;
 
136
    size_t dstsize = size - next;
 
137
    size_t ret;
 
138
 
 
139
    if (srcsize == 0) {
 
140
      ret = fread(lz4fRead->srcBuf, 1, lz4fRead->srcBufMaxSize, lz4fRead->fp);
 
141
      if (ret > 0) {
 
142
        lz4fRead->srcBufSize = ret;
 
143
        srcsize = lz4fRead->srcBufSize;
 
144
        lz4fRead->srcBufNext = 0;
 
145
      }
 
146
      else if (ret == 0) {
 
147
        break;
 
148
      }
 
149
      else {
 
150
        return -LZ4F_ERROR_GENERIC;
 
151
      }
 
152
    }
 
153
 
 
154
    ret = LZ4F_decompress(lz4fRead->dctxPtr,
 
155
                          p, &dstsize,
 
156
                          lz4fRead->srcBuf + lz4fRead->srcBufNext,
 
157
                          &srcsize,
 
158
                          NULL);
 
159
    if (LZ4F_isError(ret)) {
 
160
        return ret;
 
161
    }
 
162
 
 
163
    lz4fRead->srcBufNext += srcsize;
 
164
    next += dstsize;
 
165
    p += dstsize;
 
166
  }
 
167
 
 
168
  return next;
 
169
}
 
170
 
 
171
LZ4F_errorCode_t LZ4F_readClose(LZ4_readFile_t* lz4fRead)
 
172
{
 
173
  if (lz4fRead == NULL)
 
174
    return -LZ4F_ERROR_GENERIC;
 
175
  LZ4F_freeDecompressionContext(lz4fRead->dctxPtr);
 
176
  free(lz4fRead->srcBuf);
 
177
  free(lz4fRead);
 
178
  return LZ4F_OK_NoError;
 
179
}
 
180
 
 
181
LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4F_preferences_t* prefsPtr)
 
182
{
 
183
  LZ4_byte buf[LZ4F_HEADER_SIZE_MAX];
 
184
  size_t ret;
 
185
 
 
186
  if (fp == NULL || lz4fWrite == NULL)
 
187
    return -LZ4F_ERROR_GENERIC;
 
188
 
 
189
  *lz4fWrite = (LZ4_writeFile_t*)malloc(sizeof(LZ4_writeFile_t));
 
190
  if (*lz4fWrite == NULL) {
 
191
    return -LZ4F_ERROR_allocation_failed;
 
192
  }
 
193
  if (prefsPtr != NULL) {
 
194
    switch (prefsPtr->frameInfo.blockSizeID) {
 
195
      case LZ4F_default :
 
196
      case LZ4F_max64KB :
 
197
        (*lz4fWrite)->maxWriteSize = 64 * 1024;
 
198
        break;
 
199
      case LZ4F_max256KB:
 
200
        (*lz4fWrite)->maxWriteSize = 256 * 1024;
 
201
        break;
 
202
      case LZ4F_max1MB:
 
203
        (*lz4fWrite)->maxWriteSize = 1 * 1024 * 1024;
 
204
        break;
 
205
      case LZ4F_max4MB:
 
206
        (*lz4fWrite)->maxWriteSize = 4 * 1024 * 1024;
 
207
        break;
 
208
      default:
 
209
        free(lz4fWrite);
 
210
        return -LZ4F_ERROR_maxBlockSize_invalid;
 
211
      }
 
212
    } else {
 
213
      (*lz4fWrite)->maxWriteSize = 64 * 1024;
 
214
    }
 
215
 
 
216
  (*lz4fWrite)->dstBufMaxSize = LZ4F_compressBound((*lz4fWrite)->maxWriteSize, prefsPtr);
 
217
  (*lz4fWrite)->dstBuf = (LZ4_byte*)malloc((*lz4fWrite)->dstBufMaxSize);
 
218
  if ((*lz4fWrite)->dstBuf == NULL) {
 
219
    free(*lz4fWrite);
 
220
    return -LZ4F_ERROR_allocation_failed;
 
221
  }
 
222
 
 
223
  ret = LZ4F_createCompressionContext(&(*lz4fWrite)->cctxPtr, LZ4F_getVersion());
 
224
  if (LZ4F_isError(ret)) {
 
225
      free((*lz4fWrite)->dstBuf);
 
226
      free(*lz4fWrite);
 
227
      return ret;
 
228
  }
 
229
 
 
230
  ret = LZ4F_compressBegin((*lz4fWrite)->cctxPtr, buf, LZ4F_HEADER_SIZE_MAX, prefsPtr);
 
231
  if (LZ4F_isError(ret)) {
 
232
      LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr);
 
233
      free((*lz4fWrite)->dstBuf);
 
234
      free(*lz4fWrite);
 
235
      return ret;
 
236
  }
 
237
 
 
238
  if (ret != fwrite(buf, 1, ret, fp)) {
 
239
    LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr);
 
240
    free((*lz4fWrite)->dstBuf);
 
241
    free(*lz4fWrite);
 
242
    return -LZ4F_ERROR_GENERIC;
 
243
  }
 
244
 
 
245
  (*lz4fWrite)->fp = fp;
 
246
  (*lz4fWrite)->errCode = LZ4F_OK_NoError;
 
247
  return LZ4F_OK_NoError;
 
248
}
 
249
 
 
250
size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, void* buf, size_t size)
 
251
{
 
252
  LZ4_byte* p = (LZ4_byte*)buf;
 
253
  size_t remain = size;
 
254
  size_t chunk;
 
255
  size_t ret;
 
256
 
 
257
  if (lz4fWrite == NULL || buf == NULL)
 
258
    return -LZ4F_ERROR_GENERIC;
 
259
  while (remain) {
 
260
    if (remain > lz4fWrite->maxWriteSize)
 
261
      chunk = lz4fWrite->maxWriteSize;
 
262
    else
 
263
      chunk = remain;
 
264
 
 
265
    ret = LZ4F_compressUpdate(lz4fWrite->cctxPtr,
 
266
                              lz4fWrite->dstBuf, lz4fWrite->dstBufMaxSize,
 
267
                              p, chunk,
 
268
                              NULL);
 
269
    if (LZ4F_isError(ret)) {
 
270
      lz4fWrite->errCode = ret;
 
271
      return ret;
 
272
    }
 
273
 
 
274
    if(ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) {
 
275
      lz4fWrite->errCode = -LZ4F_ERROR_GENERIC;
 
276
      return -LZ4F_ERROR_GENERIC;
 
277
    }
 
278
 
 
279
    p += chunk;
 
280
    remain -= chunk;
 
281
  }
 
282
 
 
283
  return size;
 
284
}
 
285
 
 
286
LZ4F_errorCode_t LZ4F_writeClose(LZ4_writeFile_t* lz4fWrite)
 
287
{
 
288
  LZ4F_errorCode_t ret = LZ4F_OK_NoError;
 
289
 
 
290
  if (lz4fWrite == NULL)
 
291
    return -LZ4F_ERROR_GENERIC;
 
292
 
 
293
  if (lz4fWrite->errCode == LZ4F_OK_NoError) {
 
294
    ret =  LZ4F_compressEnd(lz4fWrite->cctxPtr,
 
295
                            lz4fWrite->dstBuf, lz4fWrite->dstBufMaxSize,
 
296
                            NULL);
 
297
    if (LZ4F_isError(ret)) {
 
298
      goto out;
 
299
    }
 
300
 
 
301
    if (ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) {
 
302
      ret = -LZ4F_ERROR_GENERIC;
 
303
    }
 
304
  }
 
305
 
 
306
out:
 
307
  LZ4F_freeCompressionContext(lz4fWrite->cctxPtr);
 
308
  free(lz4fWrite->dstBuf);
 
309
  free(lz4fWrite);
 
310
  return ret;
 
311
}