]> mj.ucw.cz Git - libucw.git/blob - lib/lizard-fb.c
2a4c2d2029791b54b61aae45108f7c351480811c
[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     ptr_out = ptr_in;
55     len_out = len_in;
56   }
57   bputl(fb_out, type);
58   bputl(fb_out, len_out);
59   if (type == BUCKET_TYPE_V33_LIZARD)
60   {
61     bputl(fb_out, len_in);
62     bputl(fb_out, adler32(ptr_in, len_in));
63   }
64   if (ptr_out == bb_out.ptr || ptr_out == ptr_in)
65     bwrite(fb_out, ptr_out, len_out);
66   else
67     bdirect_write_commit(fb_out, ptr_out + len_out);
68   return len_out + 8 + (type == BUCKET_TYPE_V33_LIZARD ? 8 : 0);
69 }
70
71 int
72 lizard_bbcopy_compress(struct fastbuf *fb_out, struct fastbuf *fb_in, uns len_in)
73 {
74   byte *ptr_in;
75   uns i = bdirect_read_prepare(fb_in, &ptr_in);
76   if (i < len_in)
77   {
78     bb_grow(&bb_in, len_in);
79     bread(fb_in, bb_in.ptr, len_in);
80     ptr_in = bb_in.ptr;
81   }
82   else
83     bdirect_read_commit(fb_in, ptr_in + len_in);
84   return lizard_bwrite(fb_out, ptr_in, len_in);
85 }
86
87 static int
88 decompress(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out)
89 {
90   uns orig_len = GET_U32(ptr_in);
91   uns orig_adler = GET_U32(ptr_in + 4);
92   ptr_in += 8;
93   *ptr_out = lizard_decompress_safe(ptr_in, liz_buf, orig_len);
94   if (!*ptr_out)
95     return -1;
96   if (adler32(*ptr_out, orig_len) != orig_adler)
97   {
98     errno = EINVAL;
99     return -1;
100   }
101   return orig_len;
102 }
103
104 int
105 lizard_memread(struct lizard_buffer *liz_buf, byte *ptr_in, byte **ptr_out, uns *type)
106 {
107   *type = GET_U32(ptr_in);
108   if (*type < BUCKET_TYPE_PLAIN || *type > BUCKET_TYPE_V33_LIZARD)
109   {
110     errno = EINVAL;
111     return -1;
112   }
113   uns stored_len = GET_U32(ptr_in + 4);
114   ptr_in += 8;
115   if (*type == BUCKET_TYPE_V33_LIZARD)
116     return decompress(liz_buf, ptr_in, ptr_out);
117   else
118   {
119     *ptr_out = ptr_in;
120     return stored_len;
121   }
122 }
123
124 int
125 lizard_bread(struct lizard_buffer *liz_buf, struct fastbuf *fb_in, byte **ptr_out, uns *type)
126 {
127   *type = bgetl(fb_in);
128   if (*type < BUCKET_TYPE_PLAIN || *type > BUCKET_TYPE_V33_LIZARD)
129   {
130     if (*type == ~0U)                   // EOF
131       errno = EBADF;
132     else
133       errno = EINVAL;
134     return -1;
135   }
136   uns stored_len = bgetl(fb_in);
137   uns want_len = stored_len + (*type == BUCKET_TYPE_V33_LIZARD ? 8 : 0);
138   byte *ptr_in;
139   uns i = bdirect_read_prepare(fb_in, &ptr_in);
140   if (i < want_len)
141   {
142     bb_grow(&bb_in, want_len);
143     bread(fb_in, bb_in.ptr, want_len);
144     ptr_in = bb_in.ptr;
145   }
146   else
147     bdirect_read_commit(fb_in, ptr_in + want_len);
148   if (*type == BUCKET_TYPE_V33_LIZARD)
149     return decompress(liz_buf, ptr_in, ptr_out);
150   else
151   {
152     *ptr_out = ptr_in;
153     return stored_len;
154   }
155 }