compress.c (2705B)
1 /* Public standalone compression API: a thin composition over the internal codec 2 * shims (src/dist/{deflate,lz4frame}.c) that also back <kit/package.h>. See 3 * <kit/compress.h>. */ 4 5 #include <kit/compress.h> 6 7 #include "core/diag.h" 8 #include "dist/deflate.h" 9 #include "dist/dist.h" 10 #include "dist/lz4frame.h" 11 12 /* Container magic: gzip (RFC 1952) and the LZ4 frame magic, little-endian 13 * 0x184D2204. Used only to auto-detect the format on decompress. */ 14 static const uint8_t COMPRESS_GZIP_MAGIC[2] = {0x1f, 0x8b}; 15 static const uint8_t COMPRESS_LZ4F_MAGIC[4] = {0x04, 0x22, 0x4d, 0x18}; 16 17 static const char* compress_fmt_name(KitCompressFormat fmt) { 18 return fmt == KIT_COMPRESS_GZIP ? "gzip" : "lz4"; 19 } 20 21 KitStatus kit_compress(const KitContext* ctx, KitCompressFormat fmt, 22 const uint8_t* data, size_t len, KitWriter* out) { 23 int r; 24 if (!ctx || !ctx->heap || !out || (!data && len != 0)) return KIT_ERR; 25 switch (fmt) { 26 case KIT_COMPRESS_GZIP: 27 r = dist_gz_compress(out, data, len); 28 break; 29 case KIT_COMPRESS_LZ4_FRAME: 30 r = dist_lz4f_compress(ctx->heap, out, data, len); 31 break; 32 default: 33 kit_ctx_diagf(ctx, "compress: unknown format %d", (int)fmt); 34 return KIT_ERR; 35 } 36 if (r != DIST_OK) { 37 kit_ctx_diagf(ctx, "compress: %s encode failed", compress_fmt_name(fmt)); 38 return KIT_ERR; 39 } 40 return KIT_OK; 41 } 42 43 KitStatus kit_decompress(const KitContext* ctx, KitCompressFormat fmt, 44 const uint8_t* data, size_t len, KitWriter* out) { 45 int r; 46 if (!ctx || !ctx->heap || !out || (!data && len != 0)) return KIT_ERR; 47 switch (fmt) { 48 case KIT_COMPRESS_GZIP: 49 r = dist_gz_decompress(out, data, len); 50 break; 51 case KIT_COMPRESS_LZ4_FRAME: 52 r = dist_lz4f_decompress(ctx->heap, out, data, len); 53 break; 54 default: 55 kit_ctx_diagf(ctx, "decompress: unknown format %d", (int)fmt); 56 return KIT_ERR; 57 } 58 if (r != DIST_OK) { 59 kit_ctx_diagf(ctx, "decompress: %s decode failed", compress_fmt_name(fmt)); 60 return KIT_ERR; 61 } 62 return KIT_OK; 63 } 64 65 KitStatus kit_compress_detect(const uint8_t* data, size_t len, 66 KitCompressFormat* out_fmt) { 67 if (!data || !out_fmt) return KIT_ERR; 68 if (len >= sizeof COMPRESS_GZIP_MAGIC && data[0] == COMPRESS_GZIP_MAGIC[0] && 69 data[1] == COMPRESS_GZIP_MAGIC[1]) { 70 *out_fmt = KIT_COMPRESS_GZIP; 71 return KIT_OK; 72 } 73 if (len >= sizeof COMPRESS_LZ4F_MAGIC && data[0] == COMPRESS_LZ4F_MAGIC[0] && 74 data[1] == COMPRESS_LZ4F_MAGIC[1] && data[2] == COMPRESS_LZ4F_MAGIC[2] && 75 data[3] == COMPRESS_LZ4F_MAGIC[3]) { 76 *out_fmt = KIT_COMPRESS_LZ4_FRAME; 77 return KIT_OK; 78 } 79 return KIT_ERR; 80 }