]> mj.ucw.cz Git - libucw.git/commitdiff
added a module that supports transparent compression of data streamed into
authorRobert Spalek <robert@ucw.cz>
Tue, 17 Aug 2004 20:12:05 +0000 (20:12 +0000)
committerRobert Spalek <robert@ucw.cz>
Tue, 17 Aug 2004 20:12:05 +0000 (20:12 +0000)
an output fastbuf.  on the other side, reading from the stream is also
transparent

* will be used for cards
* untested

lib/Makefile
lib/lizard-fb.c [new file with mode: 0644]
lib/lizard.h

index df0d046aeb610e85c99b99e274d9db887ba3716b..6114d4960001257061b240674ec05f097ecfaabc 100644 (file)
@@ -20,7 +20,7 @@ LIBSH_MODS= \
        db \
        url urlkey finger \
        mainloop exitstatus runcmd sighandler \
-       lizard lizard-safe adler32 \
+       lizard lizard-safe lizard-fb lizard-fb adler32 \
        md5 md5hex \
        base64 base224 \
        sync
diff --git a/lib/lizard-fb.c b/lib/lizard-fb.c
new file mode 100644 (file)
index 0000000..2a6d174
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ *     LiZaRd -- Reading and writing to a fastbuf
+ *
+ *     (c) 2004, Robert Spalek <robert@ucw.cz>
+ */
+
+#include "lib/lib.h"
+#include "lib/lizard.h"
+#include "lib/bbuf.h"
+#include "lib/fastbuf.h"
+#include "lib/bucket.h"
+
+#include <errno.h>
+
+static uns liz_type;
+static float liz_min_compr;
+
+static bb_t bb_in, bb_out;
+
+void
+lizard_set_type(uns type, float min_compr)
+{
+  liz_type = type;
+  liz_min_compr = min_compr;
+}
+
+int
+lizard_bwrite(struct fastbuf *fb_out, byte *ptr_in, uns len_in)
+{
+  byte *ptr_out;
+  uns len_out;
+  uns type = liz_type;
+  if (type == BUCKET_TYPE_V33_LIZARD)
+  {
+    uns est_out = len_in * LIZARD_MAX_MULTIPLY + LIZARD_MAX_ADD + 16;
+    uns aval_out = bdirect_write_prepare(fb_out, &ptr_out);
+    if (aval_out < est_out)
+    {
+      bb_grow(&bb_out, est_out);
+      ptr_out = bb_out.ptr;
+    }
+    else
+      ptr_out += 16;
+    len_out = lizard_compress(ptr_in, len_in, ptr_out);
+    if (len_out + 8 > len_in * liz_min_compr)
+    {
+      type = BUCKET_TYPE_V33;
+      ptr_out = ptr_in;
+      len_out = len_in;
+    }
+  }
+  else
+  {
+    ptr_out = ptr_in;
+    len_out = len_in;
+  }
+  bputl(fb_out, type);
+  bputl(fb_out, len_out);
+  if (type == BUCKET_TYPE_V33_LIZARD)
+  {
+    bputl(fb_out, len_in);
+    bputl(fb_out, adler32(ptr_in, len_in));
+  }
+  if (ptr_out == bb_out.ptr || ptr_out == ptr_in)
+    bwrite(fb_out, ptr_out, len_out);
+  else
+    bdirect_write_commit(fb_out, ptr_out + len_out);
+  return len_out + 8 + (type == BUCKET_TYPE_V33_LIZARD ? 8 : 0);
+}
+
+int
+lizard_bbcopy(struct fastbuf *fb_out, struct fastbuf *fb_in, uns len_in)
+{
+  byte *ptr_in;
+  uns i = bdirect_read_prepare(fb_in, &ptr_in);
+  if (i < len_in)
+  {
+    bb_grow(&bb_in, len_in);
+    bread(fb_in, bb_in.ptr, len_in);
+    ptr_in = bb_in.ptr;
+  }
+  else
+    bdirect_read_commit(fb_in, ptr_in + len_in);
+  return lizard_bwrite(fb_out, ptr_in, len_in);
+}
+
+static int
+decompress(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out)
+{
+  uns orig_len = GET_U32(ptr_in);
+  uns orig_adler = GET_U32(ptr_in + 4);
+  ptr_in += 8;
+  *ptr_out = lizard_decompress_safe(ptr_in, liz_buf, orig_len);
+  if (!*ptr_out)
+    return -1;
+  if (adler32(*ptr_out, orig_len) != orig_adler)
+  {
+    errno = EINVAL;
+    return -1;
+  }
+  return orig_len;
+}
+
+int
+lizard_memread(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out, uns *type)
+{
+  *type = GET_U32(ptr_in);
+  uns stored_len = GET_U32(ptr_in + 4);
+  ptr_in += 8;
+  if (*type == BUCKET_TYPE_V33_LIZARD)
+    return decompress(liz_buf, ptr_in, ptr_out);
+  else
+  {
+    *ptr_out = ptr_in;
+    return stored_len;
+  }
+}
+
+int
+lizard_bread(struct lizard_buffer *liz_buf, struct fastbuf *fb_in, byte **ptr_out, uns *type)
+{
+  *type = bgetl(fb_in);
+  uns stored_len = bgetl(fb_in);
+  uns want_len = stored_len + (*type == BUCKET_TYPE_V33_LIZARD ? 8 : 0);
+  byte *ptr_in;
+  uns i = bdirect_read_prepare(fb_in, &ptr_in);
+  if (i < want_len)
+  {
+    bb_grow(&bb_in, want_len);
+    bread(fb_in, bb_in.ptr, want_len);
+    ptr_in = bb_in.ptr;
+  }
+  else
+    bdirect_read_commit(fb_in, ptr_in + want_len);
+  if (*type == BUCKET_TYPE_V33_LIZARD)
+    return decompress(liz_buf, ptr_in, ptr_out);
+  else
+  {
+    *ptr_out = ptr_in;
+    return stored_len;
+  }
+}
index bc7f317ea15f86aac9672b1bfa6714f1dd470404..bf4705a8bf33618b70a910add5cc36d870cdde1a 100644 (file)
@@ -46,4 +46,14 @@ adler32(byte *buf, uns len)
   return update_adler32(1, buf, len);
 }
 
+/* lizard-fb.c */
+struct fastbuf;
+
+void lizard_set_type(uns type, float min_compr);
+int lizard_bwrite(struct fastbuf *fb_out, byte *ptr_in, uns len_in);
+int lizard_bbcopy(struct fastbuf *fb_out, struct fastbuf *fb_in, uns len_in);
+int lizard_memread(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out, uns *type);
+int lizard_bread(struct lizard_buffer *liz_buf, struct fastbuf *fb_in, byte **ptr_out, uns *type);
+  /* These functions use static variables, hence they are not re-entrant.  */
+
 #endif