1 /*
2    Lizard auto-framing library
3    Header File
4    Copyright (C) 2011-2015, Yann Collet
5    Copyright (C) 2016-2017, Przemyslaw Skibinski
6 
7    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8 
9    Redistribution and use in source and binary forms, with or without
10    modification, are permitted provided that the following conditions are
11    met:
12 
13        * Redistributions of source code must retain the above copyright
14    notice, this list of conditions and the following disclaimer.
15        * Redistributions in binary form must reproduce the above
16    copyright notice, this list of conditions and the following disclaimer
17    in the documentation and/or other materials provided with the
18    distribution.
19 
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 
32    You can contact the author at :
33    - Lizard source repository : https://github.com/inikep/lizard
34 */
35 
36 /* LizardF is a stand-alone API to create Lizard-compressed frames
37  * conformant with specification v1.5.1.
38  * All related operations, including memory management, are handled internally by the library.
39  * You don't need lizard_compress.h when using lizard_frame.h.
40  * */
41 
42 #pragma once
43 
44 #if defined (__cplusplus)
45 extern "C" {
46 #endif
47 
48 /*-************************************
49 *  Includes
50 **************************************/
51 #include <stddef.h>   /* size_t */
52 
53 
54 /*-************************************
55 *  Error management
56 **************************************/
57 typedef size_t LizardF_errorCode_t;
58 
59 unsigned    LizardF_isError(LizardF_errorCode_t code);
60 const char* LizardF_getErrorName(LizardF_errorCode_t code);   /* return error code string; useful for debugging */
61 
62 
63 /*-************************************
64 *  Frame compression types
65 **************************************/
66 //#define LIZARDF_DISABLE_OBSOLETE_ENUMS
67 #ifndef LIZARDF_DISABLE_OBSOLETE_ENUMS
68 #  define LIZARDF_OBSOLETE_ENUM(x) ,x
69 #else
70 #  define LIZARDF_OBSOLETE_ENUM(x)
71 #endif
72 
73 typedef enum {
74     LizardF_default=0,
75     LizardF_max128KB=1,
76     LizardF_max256KB=2,
77     LizardF_max1MB=3,
78     LizardF_max4MB=4,
79     LizardF_max16MB=5,
80     LizardF_max64MB=6,
81     LizardF_max256MB=7
82 } LizardF_blockSizeID_t;
83 
84 typedef enum {
85     LizardF_blockLinked=0,
86     LizardF_blockIndependent
87     LIZARDF_OBSOLETE_ENUM(blockLinked = LizardF_blockLinked)
88     LIZARDF_OBSOLETE_ENUM(blockIndependent = LizardF_blockIndependent)
89 } LizardF_blockMode_t;
90 
91 typedef enum {
92     LizardF_noContentChecksum=0,
93     LizardF_contentChecksumEnabled
94     LIZARDF_OBSOLETE_ENUM(noContentChecksum = LizardF_noContentChecksum)
95     LIZARDF_OBSOLETE_ENUM(contentChecksumEnabled = LizardF_contentChecksumEnabled)
96 } LizardF_contentChecksum_t;
97 
98 typedef enum {
99     LizardF_frame=0,
100     LizardF_skippableFrame
101     LIZARDF_OBSOLETE_ENUM(skippableFrame = LizardF_skippableFrame)
102 } LizardF_frameType_t;
103 
104 #ifndef LIZARDF_DISABLE_OBSOLETE_ENUMS
105 typedef LizardF_blockSizeID_t blockSizeID_t;
106 typedef LizardF_blockMode_t blockMode_t;
107 typedef LizardF_frameType_t frameType_t;
108 typedef LizardF_contentChecksum_t contentChecksum_t;
109 #endif
110 
111 typedef struct {
112   LizardF_blockSizeID_t     blockSizeID;           /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
113   LizardF_blockMode_t       blockMode;             /* blockLinked, blockIndependent ; 0 == default */
114   LizardF_contentChecksum_t contentChecksumFlag;   /* noContentChecksum, contentChecksumEnabled ; 0 == default  */
115   LizardF_frameType_t       frameType;             /* LizardF_frame, skippableFrame ; 0 == default */
116   unsigned long long     contentSize;           /* Size of uncompressed (original) content ; 0 == unknown */
117   unsigned               reserved[2];           /* must be zero for forward compatibility */
118 } LizardF_frameInfo_t;
119 
120 typedef struct {
121   LizardF_frameInfo_t frameInfo;
122   int      compressionLevel;       /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */
123   unsigned autoFlush;              /* 1 == always flush (reduce need for tmp buffer) */
124   unsigned reserved[4];            /* must be zero for forward compatibility */
125 } LizardF_preferences_t;
126 
127 
128 /*-*********************************
129 *  Simple compression function
130 ***********************************/
131 size_t LizardF_compressFrameBound(size_t srcSize, const LizardF_preferences_t* preferencesPtr);
132 
133 /*!LizardF_compressFrame() :
134  * Compress an entire srcBuffer into a valid Lizard frame, as defined by specification v1.5.1
135  * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
136  * You can get the minimum value of dstMaxSize by using LizardF_compressFrameBound()
137  * If this condition is not respected, LizardF_compressFrame() will fail (result is an errorCode)
138  * The LizardF_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
139  * The result of the function is the number of bytes written into dstBuffer.
140  * The function outputs an error code if it fails (can be tested using LizardF_isError())
141  */
142 size_t LizardF_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_preferences_t* preferencesPtr);
143 
144 
145 
146 /*-***********************************
147 *  Advanced compression functions
148 *************************************/
149 typedef struct LizardF_cctx_s* LizardF_compressionContext_t;   /* must be aligned on 8-bytes */
150 
151 typedef struct {
152   unsigned stableSrc;    /* 1 == src content will remain available on future calls to LizardF_compress(); avoid saving src content within tmp buffer as future dictionary */
153   unsigned reserved[3];
154 } LizardF_compressOptions_t;
155 
156 /* Resource Management */
157 
158 #define LIZARDF_VERSION 100
159 LizardF_errorCode_t LizardF_createCompressionContext(LizardF_compressionContext_t* cctxPtr, unsigned version);
160 LizardF_errorCode_t LizardF_freeCompressionContext(LizardF_compressionContext_t cctx);
161 /* LizardF_createCompressionContext() :
162  * The first thing to do is to create a compressionContext object, which will be used in all compression operations.
163  * This is achieved using LizardF_createCompressionContext(), which takes as argument a version and an LizardF_preferences_t structure.
164  * The version provided MUST be LIZARDF_VERSION. It is intended to track potential version differences between different binaries.
165  * The function will provide a pointer to a fully allocated LizardF_compressionContext_t object.
166  * If the result LizardF_errorCode_t is not zero, there was an error during context creation.
167  * Object can release its memory using LizardF_freeCompressionContext();
168  */
169 
170 
171 /* Compression */
172 
173 size_t LizardF_compressBegin(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_preferences_t* prefsPtr);
174 /* LizardF_compressBegin() :
175  * will write the frame header into dstBuffer.
176  * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.
177  * The LizardF_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.
178  * The result of the function is the number of bytes written into dstBuffer for the header
179  * or an error code (can be tested using LizardF_isError())
180  */
181 
182 size_t LizardF_compressBound(size_t srcSize, const LizardF_preferences_t* prefsPtr);
183 /* LizardF_compressBound() :
184  * Provides the minimum size of Dst buffer given srcSize to handle worst case situations.
185  * Different preferences can produce different results.
186  * prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to cover worst case.
187  * This function includes frame termination cost (4 bytes, or 8 if frame checksum is enabled)
188  */
189 
190 size_t LizardF_compressUpdate(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_compressOptions_t* cOptPtr);
191 /* LizardF_compressUpdate()
192  * LizardF_compressUpdate() can be called repetitively to compress as much data as necessary.
193  * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
194  * You can get the minimum value of dstMaxSize by using LizardF_compressBound().
195  * If this condition is not respected, LizardF_compress() will fail (result is an errorCode).
196  * LizardF_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.
197  * The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.
198  * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.
199  * The function outputs an error code if it fails (can be tested using LizardF_isError())
200  */
201 
202 size_t LizardF_flush(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* cOptPtr);
203 /* LizardF_flush()
204  * Should you need to generate compressed data immediately, without waiting for the current block to be filled,
205  * you can call Lizard_flush(), which will immediately compress any remaining data buffered within cctx.
206  * Note that dstMaxSize must be large enough to ensure the operation will be successful.
207  * LizardF_compressOptions_t structure is optional : you can provide NULL as argument.
208  * The result of the function is the number of bytes written into dstBuffer
209  * (it can be zero, this means there was no data left within cctx)
210  * The function outputs an error code if it fails (can be tested using LizardF_isError())
211  */
212 
213 size_t LizardF_compressEnd(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* cOptPtr);
214 /* LizardF_compressEnd()
215  * When you want to properly finish the compressed frame, just call LizardF_compressEnd().
216  * It will flush whatever data remained within compressionContext (like Lizard_flush())
217  * but also properly finalize the frame, with an endMark and a checksum.
218  * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)
219  * The function outputs an error code if it fails (can be tested using LizardF_isError())
220  * The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.
221  * A successful call to LizardF_compressEnd() makes cctx available again for next compression task.
222  */
223 
224 
225 /*-*********************************
226 *  Decompression functions
227 ***********************************/
228 
229 typedef struct LizardF_dctx_s* LizardF_decompressionContext_t;   /* must be aligned on 8-bytes */
230 
231 typedef struct {
232   unsigned stableDst;       /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */
233   unsigned reserved[3];
234 } LizardF_decompressOptions_t;
235 
236 
237 /* Resource management */
238 
239 /*!LizardF_createDecompressionContext() :
240  * Create an LizardF_decompressionContext_t object, which will be used to track all decompression operations.
241  * The version provided MUST be LIZARDF_VERSION. It is intended to track potential breaking differences between different versions.
242  * The function will provide a pointer to a fully allocated and initialized LizardF_decompressionContext_t object.
243  * The result is an errorCode, which can be tested using LizardF_isError().
244  * dctx memory can be released using LizardF_freeDecompressionContext();
245  * The result of LizardF_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.
246  * That is, it should be == 0 if decompression has been completed fully and correctly.
247  */
248 LizardF_errorCode_t LizardF_createDecompressionContext(LizardF_decompressionContext_t* dctxPtr, unsigned version);
249 LizardF_errorCode_t LizardF_freeDecompressionContext(LizardF_decompressionContext_t dctx);
250 
251 
252 /*======   Decompression   ======*/
253 
254 /*!LizardF_getFrameInfo() :
255  * This function decodes frame header information (such as max blockSize, frame checksum, etc.).
256  * Its usage is optional. The objective is to extract frame header information, typically for allocation purposes.
257  * A header size is variable and can be from 7 to 15 bytes. It's also possible to input more bytes than that.
258  * The number of bytes read from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
259  * (note that LizardF_getFrameInfo() can also be used anytime *after* starting decompression, in this case 0 input byte is enough)
260  * Frame header info is *copied into* an already allocated LizardF_frameInfo_t structure.
261  * The function result is an hint about how many srcSize bytes LizardF_decompress() expects for next call,
262  *                        or an error code which can be tested using LizardF_isError()
263  *                        (typically, when there is not enough src bytes to fully decode the frame header)
264  * Decompression is expected to resume from where it stopped (srcBuffer + *srcSizePtr)
265  */
266 size_t LizardF_getFrameInfo(LizardF_decompressionContext_t dctx,
267                          LizardF_frameInfo_t* frameInfoPtr,
268                          const void* srcBuffer, size_t* srcSizePtr);
269 
270 /*!LizardF_decompress() :
271  * Call this function repetitively to regenerate data compressed within srcBuffer.
272  * The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
273  *
274  * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
275  *
276  * The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
277  * If number of bytes read is < number of bytes provided, then decompression operation is not completed.
278  * It typically happens when dstBuffer is not large enough to contain all decoded data.
279  * LizardF_decompress() must be called again, starting from where it stopped (srcBuffer + *srcSizePtr)
280  * The function will check this condition, and refuse to continue if it is not respected.
281  *
282  * `dstBuffer` is expected to be flushed between each call to the function, its content will be overwritten.
283  * `dst` arguments can be changed at will at each consecutive call to the function.
284  *
285  * The function result is an hint of how many `srcSize` bytes LizardF_decompress() expects for next call.
286  * Schematically, it's the size of the current (or remaining) compressed block + header of next block.
287  * Respecting the hint provides some boost to performance, since it does skip intermediate buffers.
288  * This is just a hint though, it's always possible to provide any srcSize.
289  * When a frame is fully decoded, the function result will be 0 (no more data expected).
290  * If decompression failed, function result is an error code, which can be tested using LizardF_isError().
291  *
292  * After a frame is fully decoded, dctx can be used again to decompress another frame.
293  */
294 size_t LizardF_decompress(LizardF_decompressionContext_t dctx,
295                        void* dstBuffer, size_t* dstSizePtr,
296                        const void* srcBuffer, size_t* srcSizePtr,
297                        const LizardF_decompressOptions_t* dOptPtr);
298 
299 
300 
301 #if defined (__cplusplus)
302 }
303 #endif
304