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 CPP11_auto_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);
    }
}
