peerplays-fc/vendor/easylzma/src/lzma_header.c
2013-08-13 13:28:53 -04:00

141 lines
3.6 KiB
C

/*
* 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;
}