Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
// This is a simple high-level driver to write items into streams
// in a compressed form. Useful if, due to some reason, we do not
// want to write directly into a compressed archive.
//
// Note that this code is rather slow, and is not recommended for
// saving a lot of small objects (use a compressed archive instead).

#ifndef GENERS_COMPRESSEDIO_HH_
#define GENERS_COMPRESSEDIO_HH_

#include "Alignment/Geners/interface/CStringStream.hh"
#include "Alignment/Geners/interface/GenericIO.hh"

namespace gs {
  // The following function returns "true" on success, "false" on failure
  template <class Item>
  bool write_compressed_item(std::ostream &os,
                             const Item &item,
                             CStringStream::CompressionMode m = CStringStream::ZLIB,
                             int compressionLevel = -1,
                             unsigned minSizeToCompress = 1024U,
                             unsigned bufSize = 1048576U);

  template <class Item>
  void restore_compressed_item(std::istream &in, Item *item);

  template <class Item>
  std::unique_ptr<Item> read_compressed_item(std::istream &in);
}  // namespace gs

namespace gs {
  template <class Item>
  inline bool write_compressed_item(std::ostream &os,
                                    const Item &item,
                                    const CStringStream::CompressionMode m,
                                    const int compressionLevel,
                                    const unsigned minSizeToCompress,
                                    const unsigned bufSize) {
    CStringStream cs(m, compressionLevel, minSizeToCompress, bufSize);
    unsigned compressionCode = 0;
    long long len = 0;
    const std::streampos base = os.tellp();
    write_pod(os, len);
    write_pod(os, compressionCode);
    if (os.fail() || os.bad())
      return false;
    const std::streampos start = os.tellp();
    cs.setSink(os);
    if (!write_item(cs, item))
      return false;
    cs.flush();
    compressionCode = static_cast<unsigned>(cs.writeCompressed());
    const std::streampos now = os.tellp();
    const std::streamoff off = now - start;
    len = off;
    os.seekp(base);
    write_pod(os, len);
    write_pod(os, compressionCode);
    os.seekp(now);
    return !(cs.fail() || cs.bad() || os.fail() || os.bad());
  }

  template <class Item>
  inline void restore_compressed_item(std::istream &is, Item *item) {
    long long len;
    read_pod(is, &len);
    unsigned compressionCode;
    read_pod(is, &compressionCode);
    CStringStream::CompressionMode m = static_cast<CStringStream::CompressionMode>(compressionCode);
    CStringStream cs(m, -1, 1024U, 1048576U);
    cs.readCompressed(is, compressionCode, len);
    if (!is.good())
      throw IOReadFailure(
          "In restore_compressed_item: "
          "input stream failure");
    restore_item(cs, item);
  }

  template <class Item>
  inline std::unique_ptr<Item> read_compressed_item(std::istream &is) {
    long long len;
    read_pod(is, &len);
    unsigned compressionCode;
    read_pod(is, &compressionCode);
    CStringStream::CompressionMode m = static_cast<CStringStream::CompressionMode>(compressionCode);
    CStringStream cs(m, -1, 1024U, 1048576U);
    cs.readCompressed(is, compressionCode, len);
    if (!is.good())
      throw IOReadFailure(
          "In read_compressed_item: "
          "input stream failure");
    return read_item<Item, std::istream>(cs);
  }
}  // namespace gs

#endif  // GENERS_COMPRESSEDIO_HH_