summaryrefslogtreecommitdiffstats
path: root/depends/lzma/wrapper/lzma_header.c
diff options
context:
space:
mode:
Diffstat (limited to 'depends/lzma/wrapper/lzma_header.c')
-rw-r--r--depends/lzma/wrapper/lzma_header.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/depends/lzma/wrapper/lzma_header.c b/depends/lzma/wrapper/lzma_header.c
new file mode 100644
index 00000000..ab32549f
--- /dev/null
+++ b/depends/lzma/wrapper/lzma_header.c
@@ -0,0 +1,134 @@
+/*
+ * Written in 2009 by Lloyd Hilaiel
+ *
+ * License
+ *
+ * All the cruft you find here is public domain. You don't have to credit
+ * anyone to use this code, but my personal request is that you mention
+ * Igor Pavlov for his hard, high quality work.
+ */
+
+/* XXX: clean this up, it's mostly lifted from pavel */
+
+#include "lzma_header.h"
+
+#include <string.h>
+#include <assert.h>
+
+#define ELZMA_LZMA_HEADER_SIZE 13
+#define ELZMA_LZMA_PROPSBUF_SIZE 5
+
+/****************
+ Header parsing
+ ****************/
+
+#ifndef UINT64_MAX
+#define UINT64_MAX ((unsigned long long)-1)
+#endif
+
+/* Parse the properties byte */
+static char lzmadec_header_properties(unsigned char *pb, unsigned char *lp, unsigned char *lc,
+ const unsigned char c)
+{
+ /* pb, lp and lc are encoded into a single byte. */
+ if (c > (9 * 5 * 5))
+ return -1;
+ *pb = c / (9 * 5); /* 0 <= pb <= 4 */
+ *lp = (c % (9 * 5)) / 9; /* 0 <= lp <= 4 */
+ *lc = c % 9; /* 0 <= lc <= 8 */
+
+ assert(*pb < 5 && *lp < 5 && *lc < 9);
+ return 0;
+}
+
+/* Parse the dictionary size (4 bytes, little endian) */
+static char lzmadec_header_dictionary(unsigned int *size, const unsigned char *buffer)
+{
+ unsigned int i;
+ *size = 0;
+ for (i = 0; i < 4; i++)
+ *size += (unsigned int)(*buffer++) << (i * 8);
+ /* The dictionary size is limited to 256 MiB (checked from
+ * LZMA SDK 4.30) */
+ if (*size > (1 << 28))
+ return -1;
+ return 0;
+}
+
+/* Parse the uncompressed size field (8 bytes, little endian) */
+static void lzmadec_header_uncompressed(unsigned long long *size, unsigned char *is_streamed,
+ const unsigned char *buffer)
+{
+ unsigned int i;
+
+ /* Streamed files have all 64 bits set in the size field.
+ * We don't know the uncompressed size beforehand. */
+ *is_streamed = 1; /* Assume streamed. */
+ *size = 0;
+ for (i = 0; i < 8; i++)
+ {
+ *size += (unsigned long long)buffer[i] << (i * 8);
+ if (buffer[i] != 255)
+ *is_streamed = 0;
+ }
+ assert((*is_streamed == 1 && *size == UINT64_MAX) ||
+ (*is_streamed == 0 && *size < UINT64_MAX));
+}
+
+static void initLzmaHeader(struct elzma_file_header *hdr)
+{
+ memset((void *)hdr, 0, sizeof(struct elzma_file_header));
+}
+
+static int parseLzmaHeader(const unsigned char *hdrBuf, struct elzma_file_header *hdr)
+{
+ if (lzmadec_header_properties(&(hdr->pb), &(hdr->lp), &(hdr->lc), *hdrBuf) ||
+ lzmadec_header_dictionary(&(hdr->dictSize), hdrBuf + 1))
+ {
+ return 1;
+ }
+ lzmadec_header_uncompressed(&(hdr->uncompressedSize), &(hdr->isStreamed), hdrBuf + 5);
+
+ return 0;
+}
+
+static int serializeLzmaHeader(unsigned char *hdrBuf, const struct elzma_file_header *hdr)
+{
+ unsigned int i;
+
+ memset((void *)hdrBuf, 0, ELZMA_LZMA_HEADER_SIZE);
+
+ /* encode lc, pb, and lp */
+ *hdrBuf++ = hdr->lc + (hdr->pb * 45) + (hdr->lp * 45 * 9);
+
+ /* encode dictionary size */
+ for (i = 0; i < 4; i++)
+ {
+ *(hdrBuf++) = (unsigned char)(hdr->dictSize >> (i * 8));
+ }
+
+ /* encode uncompressed size */
+ for (i = 0; i < 8; i++)
+ {
+ if (hdr->isStreamed)
+ {
+ *(hdrBuf++) = 0xff;
+ }
+ else
+ {
+ *(hdrBuf++) = (unsigned char)(hdr->uncompressedSize >> (i * 8));
+ }
+ }
+
+ return 0;
+}
+
+void initializeLZMAFormatHandler(struct elzma_format_handler *hand)
+{
+ hand->header_size = ELZMA_LZMA_HEADER_SIZE;
+ hand->init_header = initLzmaHeader;
+ hand->parse_header = parseLzmaHeader;
+ hand->serialize_header = serializeLzmaHeader;
+ hand->footer_size = 0;
+ hand->serialize_footer = NULL;
+}