aboutsummaryrefslogtreecommitdiff
path: root/libbutl/lz4.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbutl/lz4.cxx')
-rw-r--r--libbutl/lz4.cxx98
1 files changed, 73 insertions, 25 deletions
diff --git a/libbutl/lz4.cxx b/libbutl/lz4.cxx
index a28ed78..386971a 100644
--- a/libbutl/lz4.cxx
+++ b/libbutl/lz4.cxx
@@ -28,6 +28,10 @@
#include <libbutl/utility.mxx> // eos()
+#if 1
+#include <libbutl/lz4-stream.hxx>
+#endif
+
using namespace std;
namespace butl
@@ -212,6 +216,7 @@ namespace butl
if (LZ4F_isError (on))
throw_exception (on);
+ in = 0; // All consumed.
return;
}
else
@@ -239,11 +244,15 @@ namespace butl
size_t n;
- n = LZ4F_compressUpdate (ctx, ob + on, oc - on, ib, in, nullptr);
- if (LZ4F_isError (n))
- throw_exception (n);
+ if (in != 0)
+ {
+ n = LZ4F_compressUpdate (ctx, ob + on, oc - on, ib, in, nullptr);
+ if (LZ4F_isError (n))
+ throw_exception (n);
- on += n;
+ in = 0; // All consumed.
+ on += n;
+ }
// Write the end marker.
//
@@ -266,6 +275,21 @@ namespace butl
int block_id,
optional<uint64_t> content_size)
{
+#if 1
+ char buf[1024 * 3 + 7];
+ ostream cos (os, level, block_id, content_size);
+
+ for (bool e (false); !e; )
+ {
+ e = eof (is.read (buf, sizeof (buf)));
+ cos.write (buf, is.gcount ());
+ //for (streamsize i (0), n (is.gcount ()); i != n; ++i)
+ // cos.put (buf[i]);
+ }
+
+ cos.close ();
+ return 0;
+#else
compressor c;
// Input/output buffer guards.
@@ -314,6 +338,7 @@ namespace butl
}
return ot;
+#endif
}
// decompression
@@ -391,6 +416,7 @@ namespace butl
// We expect LZ4F_decompress() to consume what it asked for.
//
assert (e == in && h <= ic);
+ in = 0; // All consumed.
return h;
}
@@ -398,13 +424,26 @@ namespace butl
uint64_t
decompress (ofdstream& os, ifdstream& is)
{
- decompressor d;
-
- // Input/output buffer guards.
+ // Write the specified number of bytes from the output buffer updating
+ // the total written.
//
- unique_ptr<char[]> ibg;
- unique_ptr<char[]> obg;
+ uint64_t ot (0);
+ auto write = [&os, &ot] (char* b, size_t n)
+ {
+ os.write (b, static_cast<streamsize> (n));
+ ot += n;
+ };
+
+#if 1
+ char buf[1024 * 3 + 7];
+ istream dis (is, true, istream::badbit);
+ for (bool e (false); !e; )
+ {
+ e = eof (dis.read (buf, sizeof (buf)));
+ write (buf, static_cast<size_t> (dis.gcount ()));
+ }
+#else
// Read into the specified buffer returning the number of bytes read and
// updating the eof flag.
//
@@ -422,20 +461,27 @@ namespace butl
return n;
};
- // Write the specified number of bytes from the output buffer updating
- // the total written.
+ decompressor d;
+
+ // Input/output buffer guards.
//
- uint64_t ot (0);
- auto write = [&os, &ot] (char* b, size_t n)
- {
- os.write (b, static_cast<streamsize> (n));
- ot += n;
- };
+ unique_ptr<char[]> ibg;
+ unique_ptr<char[]> obg;
size_t h; // Input hint.
// First read in the header and allocate the buffers.
//
+ // What if we hit EOF here? And could begin() return 0? Turns out the
+ // answer to both questions is yes: 0-byte content compresses to 15
+ // bytes (with or without content size; 1-byte -- to 20/28 bytes). We
+ // can ignore EOF here since an attempt to read more will result in
+ // another EOF. And code below is prepared to handle 0 initial hint.
+ //
+ // @@ We could end up leaving some of the input content from the
+ // header in the input buffer which the caller will have to way
+ // of using/detecting.
+ //
d.hn = read (d.hb, sizeof (d.hb));
h = d.begin ();
@@ -453,20 +499,22 @@ namespace butl
// Keep decompressing, writing, and reading chunks of compressed
// content.
//
- for (;;)
+ while (h != 0)
{
h = d.next ();
- write (d.ob, d.on);
-
- if (h == 0)
- break;
+ if (d.on != 0) // next() may just buffer the data.
+ write (d.ob, d.on);
- if (eof)
- throw invalid_argument ("incomplete compressed content");
+ if (h != 0)
+ {
+ if (eof)
+ throw invalid_argument ("incomplete compressed content");
- d.in = read (d.ib, h);
+ d.in = read (d.ib, h);
+ }
}
+#endif
return ot;
}