kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }