aboutsummaryrefslogtreecommitdiff
path: root/core/packer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'core/packer.cc')
-rw-r--r--core/packer.cc145
1 files changed, 145 insertions, 0 deletions
diff --git a/core/packer.cc b/core/packer.cc
new file mode 100644
index 0000000..f7da0c6
--- /dev/null
+++ b/core/packer.cc
@@ -0,0 +1,145 @@
+#include "../third-party/lzma/Alloc.h"
+#include "objects.h"
+#include "files.h"
+#include "packer.h"
+
+/**
+ * PackerInStream
+ */
+
+static SRes ReadFromStream(void *object, void *data, size_t *size)
+{
+ PackerInputStream *p = reinterpret_cast<PackerInputStream *>(object);
+ size_t read_size = (*size < p->size - p->pos) ? *size : p->size - p->pos;
+ if (read_size) {
+ read_size = p->file->Read(data, read_size);
+ p->pos += read_size;
+ }
+ *size = read_size;
+ return SZ_OK;
+}
+
+PackerInputStream::PackerInputStream(IArchitecture *file_, size_t size_)
+ : file(file_), data(NULL), size(size_), pos(0)
+{
+ p.Read = ReadFromStream;
+}
+
+static SRes ReadFromData(void *object, void *data, size_t *size)
+{
+ PackerInputStream *p = reinterpret_cast<PackerInputStream *>(object);
+ size_t read_size = (*size < p->size - p->pos) ? *size : p->size - p->pos;
+ if (read_size) {
+ memcpy(data, p->data->data() + p->pos, read_size);
+ p->pos += read_size;
+ }
+ *size = read_size;
+ return SZ_OK;
+}
+
+PackerInputStream::PackerInputStream(Data *data_)
+ : file(NULL), data(data_), size(data_->size()), pos(0)
+{
+ p.Read = ReadFromData;
+}
+
+/**
+ * PackerOutStream
+ */
+
+static size_t WriteToStream(void *object, const void *data, size_t size)
+{
+ PackerOutputStream *p = reinterpret_cast<PackerOutputStream *>(object);
+ p->data->PushBuff(data, size);
+ return size;
+}
+
+PackerOutputStream::PackerOutputStream(Data *data_)
+ : data(data_)
+{
+ p.Write = WriteToStream;
+}
+
+/**
+ * PackerProgress
+ */
+
+SRes PackProgress(void *object, UInt64 inSize, UInt64 /*outSize*/)
+{
+ PackerProgress *p = reinterpret_cast<PackerProgress *>(object);
+ if (p->file)
+ p->file->StepProgress(inSize - p->last_pos);
+ p->last_pos = inSize;
+ return SZ_OK;
+}
+
+PackerProgress::PackerProgress(IArchitecture *file_)
+ : file(file_), last_pos(0)
+{
+ p.Progress = PackProgress;
+}
+
+/**
+ * Packer
+ */
+
+Packer::Packer()
+{
+ encoder_ = LzmaEnc_Create(&g_Alloc);
+ if (encoder_ == 0)
+ throw 1;
+
+ LzmaEncProps_Init(&props_);
+ props_.level = 9;
+ props_.writeEndMark = true;
+ props_.dictSize = 1 << 24;
+ if (LzmaEnc_SetProps(encoder_, &props_) != SZ_OK)
+ throw 1;
+}
+
+Packer::~Packer()
+{
+ if (encoder_ != 0)
+ LzmaEnc_Destroy(encoder_, &g_Alloc, &g_BigAlloc);
+}
+
+bool Packer::WriteProps(Data *data)
+{
+ data->clear();
+
+ Byte props_buff[LZMA_PROPS_SIZE];
+ size_t props_size = sizeof(props_buff);
+ if (LzmaEnc_WriteProperties(encoder_, props_buff, &props_size) != SZ_OK)
+ return false;
+ data->PushBuff(props_buff, props_size);
+ return true;
+}
+
+bool Packer::Code(IArchitecture *file, PackerInputStream &in, PackerOutputStream &out)
+{
+ out.data->clear();
+
+ PackerProgress progress(file);
+ if (LzmaEnc_Encode(encoder_, &out.p, &in.p, &progress.p, &g_Alloc, &g_BigAlloc) != SZ_OK)
+ return false;
+
+ // LzmaEnc_Encode never calls last progress
+ file->StepProgress(in.size - progress.last_pos);
+ return true;
+}
+
+bool Packer::Code(IArchitecture *file, Data *in_data, Data *out_data)
+{
+ PackerInputStream in(in_data);
+ PackerOutputStream out(out_data);
+
+ return Code(file, in, out);
+}
+
+bool Packer::Code(IArchitecture *file, size_t size, Data *data)
+{
+ PackerInputStream in(file, size);
+ PackerOutputStream out(data);
+
+ return Code(file, in, out);
+} \ No newline at end of file