v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
223
source/core/StarCompression.cpp
Normal file
223
source/core/StarCompression.cpp
Normal file
|
@ -0,0 +1,223 @@
|
|||
#include "StarCompression.hpp"
|
||||
#include "StarFormat.hpp"
|
||||
#include "StarLexicalCast.hpp"
|
||||
|
||||
#include <zlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Star {
|
||||
|
||||
void compressData(ByteArray const& in, ByteArray& out, CompressionLevel compression) {
|
||||
out.clear();
|
||||
|
||||
if (in.empty())
|
||||
return;
|
||||
|
||||
const size_t BUFSIZE = 32 * 1024;
|
||||
unsigned char temp_buffer[BUFSIZE];
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
int deflate_res = deflateInit(&strm, compression);
|
||||
if (deflate_res != Z_OK)
|
||||
throw IOException(strf("Failed to initialise deflate (%d)", deflate_res));
|
||||
|
||||
strm.next_in = (unsigned char*)in.ptr();
|
||||
strm.avail_in = in.size();
|
||||
strm.next_out = temp_buffer;
|
||||
strm.avail_out = BUFSIZE;
|
||||
while (deflate_res == Z_OK) {
|
||||
deflate_res = deflate(&strm, Z_FINISH);
|
||||
if (strm.avail_out == 0) {
|
||||
out.append((char const*)temp_buffer, BUFSIZE);
|
||||
strm.next_out = temp_buffer;
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
}
|
||||
deflateEnd(&strm);
|
||||
|
||||
if (deflate_res != Z_STREAM_END)
|
||||
throw IOException(strf("Internal error in uncompressData, deflate_res is %s", deflate_res));
|
||||
|
||||
out.append((char const*)temp_buffer, BUFSIZE - strm.avail_out);
|
||||
}
|
||||
|
||||
ByteArray compressData(ByteArray const& in, CompressionLevel compression) {
|
||||
ByteArray out = ByteArray::withReserve(in.size());
|
||||
compressData(in, out, compression);
|
||||
return out;
|
||||
}
|
||||
|
||||
void uncompressData(ByteArray const& in, ByteArray& out) {
|
||||
out.clear();
|
||||
|
||||
if (in.empty())
|
||||
return;
|
||||
|
||||
const size_t BUFSIZE = 32 * 1024;
|
||||
unsigned char temp_buffer[BUFSIZE];
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
int inflate_res = inflateInit(&strm);
|
||||
if (inflate_res != Z_OK)
|
||||
throw IOException(strf("Failed to initialise inflate (%d)", inflate_res));
|
||||
|
||||
strm.next_in = (unsigned char*)in.ptr();
|
||||
strm.avail_in = in.size();
|
||||
strm.next_out = temp_buffer;
|
||||
strm.avail_out = BUFSIZE;
|
||||
|
||||
while (inflate_res == Z_OK || inflate_res == Z_BUF_ERROR) {
|
||||
inflate_res = inflate(&strm, Z_FINISH);
|
||||
if (strm.avail_out == 0) {
|
||||
out.append((char const*)temp_buffer, BUFSIZE);
|
||||
strm.next_out = temp_buffer;
|
||||
strm.avail_out = BUFSIZE;
|
||||
} else if (inflate_res == Z_BUF_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
inflateEnd(&strm);
|
||||
|
||||
if (inflate_res != Z_STREAM_END)
|
||||
throw IOException(strf("Internal error in uncompressData, inflate_res is %s", inflate_res));
|
||||
|
||||
out.append((char const*)temp_buffer, BUFSIZE - strm.avail_out);
|
||||
}
|
||||
|
||||
ByteArray uncompressData(ByteArray const& in) {
|
||||
ByteArray out = ByteArray::withReserve(in.size());
|
||||
uncompressData(in, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
CompressedFilePtr CompressedFile::open(String const& filename, IOMode mode, CompressionLevel comp) {
|
||||
CompressedFilePtr f = make_shared<CompressedFile>(filename);
|
||||
f->open(mode, comp);
|
||||
return f;
|
||||
}
|
||||
|
||||
CompressedFile::CompressedFile()
|
||||
: IODevice(IOMode::Closed), m_file(0), m_compression(MediumCompression) {}
|
||||
|
||||
CompressedFile::CompressedFile(String filename)
|
||||
: IODevice(IOMode::Closed), m_file(0), m_compression(MediumCompression) {
|
||||
setFilename(move(filename));
|
||||
}
|
||||
|
||||
CompressedFile::~CompressedFile() {
|
||||
close();
|
||||
}
|
||||
|
||||
StreamOffset CompressedFile::pos() {
|
||||
return gztell((gzFile)m_file);
|
||||
}
|
||||
|
||||
void CompressedFile::seek(StreamOffset offset, IOSeek seekMode) {
|
||||
StreamOffset begPos = pos();
|
||||
|
||||
int retCode;
|
||||
if (seekMode == IOSeek::Relative) {
|
||||
retCode = gzseek((gzFile)m_file, (z_off_t)offset, SEEK_CUR);
|
||||
} else if (seekMode == IOSeek::Absolute) {
|
||||
retCode = gzseek((gzFile)m_file, (z_off_t)offset, SEEK_SET);
|
||||
} else {
|
||||
throw IOException("Cannot seek with SeekEnd in compressed file");
|
||||
}
|
||||
|
||||
StreamOffset endPos = pos();
|
||||
|
||||
if (retCode < 0) {
|
||||
throw IOException::format("Seek error: %s", gzerror((gzFile)m_file, 0));
|
||||
} else if ((seekMode == IOSeek::Relative && begPos + offset != endPos)
|
||||
|| (seekMode == IOSeek::Absolute && offset != endPos)) {
|
||||
throw EofException("Error, unexpected end of file found");
|
||||
}
|
||||
}
|
||||
|
||||
bool CompressedFile::atEnd() {
|
||||
return gzeof((gzFile)m_file);
|
||||
}
|
||||
|
||||
size_t CompressedFile::read(char* data, size_t len) {
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
int ret = gzread((gzFile)m_file, data, len);
|
||||
if (ret == 0)
|
||||
throw EofException("Error, unexpected end of file found");
|
||||
else if (ret == -1)
|
||||
throw IOException::format("Read error: %s", gzerror((gzFile)m_file, 0));
|
||||
else
|
||||
return (size_t)ret;
|
||||
}
|
||||
|
||||
size_t CompressedFile::write(const char* data, size_t len) {
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
int ret = gzwrite((gzFile)m_file, data, len);
|
||||
if (ret == 0)
|
||||
throw IOException::format("Write error: %s", gzerror((gzFile)m_file, 0));
|
||||
else
|
||||
return (size_t)ret;
|
||||
}
|
||||
|
||||
void CompressedFile::setFilename(String filename) {
|
||||
if (isOpen())
|
||||
throw IOException("Cannot call setFilename while CompressedFile is open");
|
||||
m_filename = move(filename);
|
||||
}
|
||||
|
||||
void CompressedFile::setCompression(CompressionLevel compression) {
|
||||
if (isOpen())
|
||||
throw IOException("Cannot call setCompression while CompressedFile is open");
|
||||
m_compression = compression;
|
||||
}
|
||||
|
||||
void CompressedFile::open(IOMode mode, CompressionLevel compression) {
|
||||
close();
|
||||
setCompression(compression);
|
||||
open(mode);
|
||||
}
|
||||
|
||||
void CompressedFile::sync() {
|
||||
gzflush((gzFile)m_file, Z_FULL_FLUSH);
|
||||
}
|
||||
|
||||
void CompressedFile::open(IOMode mode) {
|
||||
setMode(mode);
|
||||
String modeString;
|
||||
|
||||
if (mode & IOMode::Append) {
|
||||
throw IOException("CompressedFile not compatible with Append mode");
|
||||
} else if ((mode & IOMode::Read) && (mode & IOMode::Write)) {
|
||||
throw IOException("CompressedFile not compatible with ReadWrite mode");
|
||||
} else if (mode & IOMode::Write) {
|
||||
modeString = "wb";
|
||||
} else if (mode & IOMode::Read) {
|
||||
modeString = "rb";
|
||||
}
|
||||
|
||||
modeString += toString(m_compression);
|
||||
|
||||
m_file = gzopen(m_filename.utf8Ptr(), modeString.utf8Ptr());
|
||||
|
||||
if (!m_file)
|
||||
throw IOException::format("Cannot open filename '%s'", m_filename);
|
||||
}
|
||||
|
||||
void CompressedFile::close() {
|
||||
if (m_file)
|
||||
gzclose((gzFile)m_file);
|
||||
m_file = 0;
|
||||
setMode(IOMode::Closed);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue