diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2021-09-08 16:02:41 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2021-09-08 16:02:41 +0200 |
commit | 43b92007c6c2a360b9924e1bbe58e81c4dc6e38f (patch) | |
tree | 84930cd9f153a4199857edfa7192eca27e1873f4 /libbutl/lz4.cxx | |
parent | 98c4038df36fb73601c58ccd885d1c2d3703cf6e (diff) |
Implement lz4::{istream,ostream}lz4-fdstream
Diffstat (limited to 'libbutl/lz4.cxx')
-rw-r--r-- | libbutl/lz4.cxx | 98 |
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; } |