]> mj.ucw.cz Git - libucw.git/blob - lib/lizard-fb.c
- bugfix: when disabling compression, change bucket_type
[libucw.git] / lib / lizard-fb.c
1 /*
2  *      LiZaRd -- Reading and writing to a fastbuf
3  *
4  *      (c) 2004, Robert Spalek <robert@ucw.cz>
5  */
6
7 #include "lib/lib.h"
8 #include "lib/lizard.h"
9 #include "lib/bbuf.h"
10 #include "lib/fastbuf.h"
11 #include "lib/bucket.h"
12
13 #include <errno.h>
14
15 static uns liz_type;
16 static float liz_min_compr;
17
18 static bb_t bb_in, bb_out;
19
20 void
21 lizard_set_type(uns type, float min_compr)
22 {
23   liz_type = type;
24   liz_min_compr = min_compr;
25 }
26
27 int
28 lizard_bwrite(struct fastbuf *fb_out, byte *ptr_in, uns len_in)
29 {
30   byte *ptr_out;
31   uns len_out;
32   uns type = liz_type;
33   if (type == BUCKET_TYPE_V33_LIZARD && liz_min_compr)
34   {
35     uns est_out = len_in * LIZARD_MAX_MULTIPLY + LIZARD_MAX_ADD + 16;
36     uns aval_out = bdirect_write_prepare(fb_out, &ptr_out);
37     if (aval_out < est_out)
38     {
39       bb_grow(&bb_out, est_out);
40       ptr_out = bb_out.ptr;
41     }
42     else
43       ptr_out += 16;
44     len_out = lizard_compress(ptr_in, len_in, ptr_out);
45     if (len_out + 8 > len_in * liz_min_compr)
46     {
47       type = BUCKET_TYPE_V33;
48       ptr_out = ptr_in;
49       len_out = len_in;
50     }
51   }
52   else
53   {
54     if (type == BUCKET_TYPE_V33_LIZARD)
55       type = BUCKET_TYPE_V33;
56     ptr_out = ptr_in;
57     len_out = len_in;
58   }
59   bputl(fb_out, type);
60   bputl(fb_out, len_out);
61   if (type == BUCKET_TYPE_V33_LIZARD)
62   {
63     bputl(fb_out, len_in);
64     bputl(fb_out, adler32(ptr_in, len_in));
65   }
66   if (ptr_out == bb_out.ptr || ptr_out == ptr_in)
67     bwrite(fb_out, ptr_out, len_out);
68   else
69     bdirect_write_commit(fb_out, ptr_out + len_out);
70   return type;
71 }
72
73 int
74 lizard_bbcopy_compress(struct fastbuf *fb_out, struct fastbuf *fb_in, uns len_in)
75 {
76   byte *ptr_in;
77   uns i = bdirect_read_prepare(fb_in, &ptr_in);
78   if (i < len_in)
79   {
80     bb_grow(&bb_in, len_in);
81     bread(fb_in, bb_in.ptr, len_in);
82     ptr_in = bb_in.ptr;
83   }
84   else
85     bdirect_read_commit(fb_in, ptr_in + len_in);
86   return lizard_bwrite(fb_out, ptr_in, len_in);
87 }
88
89 static int
90 decompress(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out)
91 {
92   uns orig_len = GET_U32(ptr_in);
93   uns orig_adler = GET_U32(ptr_in + 4);
94   ptr_in += 8;
95   *ptr_out = lizard_decompress_safe(ptr_in, liz_buf, orig_len);
96   if (!*ptr_out)
97     return -1;
98   if (adler32(*ptr_out, orig_len) != orig_adler)
99   {
100     errno = EINVAL;
101     return -1;
102   }
103   return orig_len;
104 }
105
106 int
107 lizard_memread(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out, uns *type)
108 {
109   *type = GET_U32(ptr_in);
110   if (*type < BUCKET_TYPE_PLAIN || *type > BUCKET_TYPE_V33_LIZARD)
111   {
112     errno = EINVAL;
113     return -1;
114   }
115   uns stored_len = GET_U32(ptr_in + 4);
116   ptr_in += 8;
117   if (*type == BUCKET_TYPE_V33_LIZARD)
118     return decompress(liz_buf, ptr_in, ptr_out);
119   else
120   {
121     *ptr_out = ptr_in;
122     return stored_len;
123   }
124 }
125
126 int
127 lizard_bread(struct lizard_buffer *liz_buf, struct fastbuf *fb_in, byte **ptr_out, uns *type)
128 {
129   *type = bgetl(fb_in);
130   if (*type < BUCKET_TYPE_PLAIN || *type > BUCKET_TYPE_V33_LIZARD)
131   {
132     if (*type == ~0U)                   // EOF
133       errno = EBADF;
134     else
135       errno = EINVAL;
136     return -1;
137   }
138   uns stored_len = bgetl(fb_in);
139   uns want_len = stored_len + (*type == BUCKET_TYPE_V33_LIZARD ? 8 : 0);
140   byte *ptr_in;
141   uns i = bdirect_read_prepare(fb_in, &ptr_in);
142   if (i < want_len)
143   {
144     bb_grow(&bb_in, want_len);
145     bread(fb_in, bb_in.ptr, want_len);
146     ptr_in = bb_in.ptr;
147   }
148   else
149     bdirect_read_commit(fb_in, ptr_in + want_len);
150   if (*type == BUCKET_TYPE_V33_LIZARD)
151     return decompress(liz_buf, ptr_in, ptr_out);
152   else
153   {
154     *ptr_out = ptr_in;
155     return stored_len;
156   }
157 }