diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mailnews/base/src/nsMsgCompressOStream.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mailnews/base/src/nsMsgCompressOStream.cpp')
-rw-r--r-- | comm/mailnews/base/src/nsMsgCompressOStream.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/comm/mailnews/base/src/nsMsgCompressOStream.cpp b/comm/mailnews/base/src/nsMsgCompressOStream.cpp new file mode 100644 index 0000000000..fd490274ca --- /dev/null +++ b/comm/mailnews/base/src/nsMsgCompressOStream.cpp @@ -0,0 +1,128 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsMsgCompressOStream.h" +#include "prio.h" +#include "prmem.h" + +#define BUFFER_SIZE 16384 + +nsMsgCompressOStream::nsMsgCompressOStream() : m_zbuf(nullptr) {} + +nsMsgCompressOStream::~nsMsgCompressOStream() { Close(); } + +NS_IMPL_ISUPPORTS(nsMsgCompressOStream, nsIOutputStream) + +nsresult nsMsgCompressOStream::InitOutputStream(nsIOutputStream* rawStream) { + // protect against repeat calls + if (m_oStream) return NS_ERROR_UNEXPECTED; + + // allocate some memory for a buffer + m_zbuf = mozilla::MakeUnique<char[]>(BUFFER_SIZE); + if (!m_zbuf) return NS_ERROR_OUT_OF_MEMORY; + + // set up the zlib object + m_zstream.zalloc = Z_NULL; + m_zstream.zfree = Z_NULL; + m_zstream.opaque = Z_NULL; + + // http://zlib.net/manual.html is rather silent on the topic, but + // perl's Compress::Raw::Zlib manual says: + // -WindowBits [...] + // To compress an RFC 1951 data stream, set WindowBits to -MAX_WBITS. + if (deflateInit2(&m_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, + MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) + return NS_ERROR_FAILURE; + + m_oStream = rawStream; + + return NS_OK; +} + +/* void close (); */ +NS_IMETHODIMP nsMsgCompressOStream::Close() { + if (m_oStream) { + m_oStream = nullptr; + deflateEnd(&m_zstream); + } + m_zbuf = nullptr; + + return NS_OK; +} + +NS_IMETHODIMP +nsMsgCompressOStream::Write(const char* buf, uint32_t count, uint32_t* result) { + if (!m_oStream) return NS_BASE_STREAM_CLOSED; + + m_zstream.next_in = (Bytef*)buf; + m_zstream.avail_in = count; + + // keep looping until the buffer doesn't get filled + do { + m_zstream.next_out = (Bytef*)m_zbuf.get(); + m_zstream.avail_out = BUFFER_SIZE; + // Using "Z_SYNC_FLUSH" may cause excess flushes if the calling + // code does a lot of small writes. An option with the IMAP + // protocol is to check the buffer for "\n" at the end, but + // in the interests of keeping this generic, don't optimise + // yet. An alternative is to require ->Flush always, but that + // is likely to break callers. + int zr = deflate(&m_zstream, Z_SYNC_FLUSH); + if (zr == Z_STREAM_END || zr == Z_BUF_ERROR) + zr = Z_OK; // not an error for our purposes + if (zr != Z_OK) return NS_ERROR_FAILURE; + + uint32_t out_size = BUFFER_SIZE - m_zstream.avail_out; + const char* out_buf = m_zbuf.get(); + + // push everything in the buffer before repeating + while (out_size) { + uint32_t out_result; + nsresult rv = m_oStream->Write(out_buf, out_size, &out_result); + NS_ENSURE_SUCCESS(rv, rv); + if (!out_result) return NS_BASE_STREAM_CLOSED; + out_size -= out_result; + out_buf += out_result; + } + + // http://www.zlib.net/manual.html says: + // If deflate returns with avail_out == 0, this function must be + // called again with the same value of the flush parameter and + // more output space (updated avail_out), until the flush is + // complete (deflate returns with non-zero avail_out). + } while (!m_zstream.avail_out); + + *result = count; + + return NS_OK; +} + +NS_IMETHODIMP +nsMsgCompressOStream::Flush(void) { + if (!m_oStream) return NS_BASE_STREAM_CLOSED; + + return m_oStream->Flush(); +} + +NS_IMETHODIMP +nsMsgCompressOStream::WriteFrom(nsIInputStream* inStr, uint32_t count, + uint32_t* _retval) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsMsgCompressOStream::WriteSegments(nsReadSegmentFun reader, void* closure, + uint32_t count, uint32_t* _retval) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* boolean isNonBlocking (); */ +NS_IMETHODIMP nsMsgCompressOStream::IsNonBlocking(bool* aNonBlocking) { + *aNonBlocking = false; + return NS_OK; +} + +NS_IMETHODIMP nsMsgCompressOStream::StreamStatus() { + return m_oStream->StreamStatus(); +} |