igzip: Implement zlib compression format

Change-Id: I3d3cca425a494ac629cea230de74e3d32fcaea79
Signed-off-by: Roy Oursler <roy.j.oursler@intel.com>
This commit is contained in:
Roy Oursler 2017-05-01 12:44:30 -07:00 committed by Xiaodong Liu
parent c68e15dc53
commit 4259169107
9 changed files with 213 additions and 42 deletions

View File

@ -94,7 +94,8 @@ other_src += igzip/bitbuf2.asm \
igzip/flatten_ll.h \
igzip/encode_df.h \
igzip/encode_df_asm.asm \
igzip/heap_macros.asm
igzip/heap_macros.asm \
igzip/igzip_checksums.h
examples += igzip/igzip_example igzip/igzip_sync_flush_example

View File

@ -28,6 +28,7 @@
**********************************************************************/
#include <stdint.h>
#include "igzip_checksums.h"
uint32_t crc32_table_gzip_base[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
@ -104,3 +105,41 @@ uint32_t crc32_gzip_base(uint32_t crc, uint8_t * start, uint32_t length)
crc = (crc >> 8) ^ crc32_table_gzip_base[(crc & 0xff) ^ *start++];
return ~crc;
}
uint32_t adler32_base(uint32_t adler32, uint8_t * start, uint32_t length)
{
uint8_t *end, *next = start;
uint64_t A, B;
A = adler32 & 0xffff;
B = adler32 >> 16;
/* Internally the checksum is being stored as B | (A-1) so crc and
* addler have same init value */
A += 1;
while (length > MAX_ADLER_BUF) {
end = next + MAX_ADLER_BUF;
for (; next < end; next++) {
A += *next;
B += A;
}
A = A % ADLER_MOD;
B = B % ADLER_MOD;
length -= MAX_ADLER_BUF;
}
end = next + length;
for (; next < end; next++) {
A += *next;
B += A;
}
A -= 1;
A = A % ADLER_MOD;
B = B % ADLER_MOD;
return B << 16 | A;
}

View File

@ -71,6 +71,8 @@
#define GZIP_HEADER_SIZE 10
#define GZIP_TRAILER_SIZE 8
#define ZLIB_HEADER_SIZE 2
#define ZLIB_TRAILER_SIZE 4
/**
* @brief Prints a table of uint8_t elements to a file.
@ -224,7 +226,11 @@ void fprint_header(FILE * output_file)
"\t0x1f, 0x8b, 0x08, 0x00, 0x00,\n" "\t0x00, 0x00, 0x00, 0x00, 0xff\t};\n\n");
fprintf(output_file, "const uint32_t gzip_hdr_bytes = %d;\n", GZIP_HEADER_SIZE);
fprintf(output_file, "const uint32_t gzip_trl_bytes = %d;\n", GZIP_TRAILER_SIZE);
fprintf(output_file, "const uint32_t gzip_trl_bytes = %d;\n\n", GZIP_TRAILER_SIZE);
fprintf(output_file, "const uint8_t zlib_hdr[] = { 0x78, 0x01 };\n\n");
fprintf(output_file, "const uint32_t zlib_hdr_bytes = %d;\n", ZLIB_HEADER_SIZE);
fprintf(output_file, "const uint32_t zlib_trl_bytes = %d;\n", ZLIB_TRAILER_SIZE);
}
int main(int argc, char *argv[])

View File

@ -39,6 +39,11 @@ const uint8_t gzip_hdr[] = {
const uint32_t gzip_hdr_bytes = 10;
const uint32_t gzip_trl_bytes = 8;
const uint8_t zlib_hdr[] = { 0x78, 0x01 };
const uint32_t zlib_hdr_bytes = 2;
const uint32_t zlib_trl_bytes = 4;
struct isal_hufftables hufftables_default = {
.deflate_hdr = {
@ -2281,6 +2286,11 @@ const uint8_t gzip_hdr[] = {
const uint32_t gzip_hdr_bytes = 10;
const uint32_t gzip_trl_bytes = 8;
const uint8_t zlib_hdr[] = { 0x78, 0x01 };
const uint32_t zlib_hdr_bytes = 2;
const uint32_t zlib_trl_bytes = 4;
struct isal_hufftables hufftables_default = {
.deflate_hdr = {

View File

@ -50,20 +50,36 @@
#include "huff_codes.h"
#include "encode_df.h"
#include "igzip_level_buf_structs.h"
#include "igzip_checksums.h"
#ifdef __FreeBSD__
#include <sys/types.h>
#include <sys/endian.h>
# define to_be32(x) bswap32(x)
#elif defined (__APPLE__)
#include <libkern/OSByteOrder.h>
# define to_be32(x) OSSwapInt32(x)
#elif defined (__GNUC__) && !defined (__MINGW32__)
# include <byteswap.h>
# define to_be32(x) bswap_32(x)
#elif defined _WIN64
# define to_be32(x) _byteswap_ulong(x)
#endif
extern const uint8_t gzip_hdr[];
extern const uint32_t gzip_hdr_bytes;
extern const uint32_t gzip_trl_bytes;
extern const uint8_t zlib_hdr[];
extern const uint32_t zlib_hdr_bytes;
extern const uint32_t zlib_trl_bytes;
extern const struct isal_hufftables hufftables_default;
extern const struct isal_hufftables hufftables_static;
extern uint32_t crc32_gzip(uint32_t init_crc, const unsigned char *buf, uint64_t len);
static int write_stored_block_stateless(struct isal_zstream *stream, uint32_t stored_len,
uint32_t crc32);
static int write_gzip_header_stateless(struct isal_zstream *stream);
static void write_gzip_header(struct isal_zstream *stream);
static int write_stream_header_stateless(struct isal_zstream *stream);
static void write_stream_header(struct isal_zstream *stream);
static int write_deflate_header_stateless(struct isal_zstream *stream);
static int write_deflate_header_unaligned_stateless(struct isal_zstream *stream);
@ -110,6 +126,22 @@ struct slver isal_deflate_set_hufftables_slver_00_01_008b;
struct slver isal_deflate_set_hufftables_slver = { 0x008b, 0x01, 0x00 };
/*****************************************************************/
void update_checksum(struct isal_zstream *stream, uint8_t * start_in, uint64_t length)
{
struct isal_zstate *state = &stream->internal_state;
switch (stream->gzip_flag) {
case IGZIP_GZIP:
case IGZIP_GZIP_NO_HDR:
state->crc = crc32_gzip(state->crc, start_in, length);
break;
case IGZIP_ZLIB:
case IGZIP_ZLIB_NO_HDR:
state->crc = isal_adler32(state->crc, start_in, length);
break;
}
}
static
void sync_flush(struct isal_zstream *stream)
{
@ -235,8 +267,8 @@ static void create_icf_block_hdr(struct isal_zstream *stream)
if (end_out - stream->next_out >= ISAL_DEF_MAX_HDR_SIZE) {
/* Determine whether this is the final block */
if (stream->gzip_flag == IGZIP_GZIP)
write_gzip_header_stateless(stream);
if (stream->gzip_flag == IGZIP_GZIP || stream->gzip_flag == IGZIP_ZLIB)
write_stream_header_stateless(stream);
set_buf(write_buf, stream->next_out, stream->avail_out);
@ -288,7 +320,6 @@ static void isal_deflate_pass(struct isal_zstream *stream)
if (state->state == ZSTATE_FLUSH_READ_BUFFER)
isal_deflate_finish(stream);
if (state->state == ZSTATE_SYNC_FLUSH)
sync_flush(stream);
@ -296,7 +327,7 @@ static void isal_deflate_pass(struct isal_zstream *stream)
flush_write_buffer(stream);
if (stream->gzip_flag)
state->crc = crc32_gzip(state->crc, start_in, stream->next_in - start_in);
update_checksum(stream, start_in, stream->next_in - start_in);
if (state->state == ZSTATE_TRL)
write_trailer(stream);
@ -342,7 +373,7 @@ static void isal_deflate_icf_pass(struct isal_zstream *stream)
flush_write_buffer(stream);
if (stream->gzip_flag)
state->crc = crc32_gzip(state->crc, start_in, stream->next_in - start_in);
update_checksum(stream, start_in, stream->next_in - start_in);
if (state->state == ZSTATE_TRL)
write_trailer(stream);
@ -507,7 +538,7 @@ static void write_constant_compressed_stateless(struct isal_zstream *stream,
stream->total_out += bytes;
if (stream->gzip_flag)
state->crc = crc32_gzip(state->crc, start_in, stream->next_in - start_in);
update_checksum(stream, start_in, stream->next_in - start_in);
return;
}
@ -535,8 +566,8 @@ static int isal_deflate_int_stateless(struct isal_zstream *stream)
uint32_t repeat_length;
struct isal_zstate *state = &stream->internal_state;
if (stream->gzip_flag == IGZIP_GZIP)
if (write_gzip_header_stateless(stream))
if (stream->gzip_flag == IGZIP_GZIP || stream->gzip_flag == IGZIP_ZLIB)
if (write_stream_header_stateless(stream))
return STATELESS_OVERFLOW;
if (stream->avail_in >= 8
@ -590,7 +621,6 @@ static int write_stored_block_stateless(struct isal_zstream *stream,
uint64_t stored_blk_hdr;
uint32_t copy_size;
uint32_t avail_in;
uint64_t gzip_trl;
if (stream->avail_out < stored_len)
return STATELESS_OVERFLOW;
@ -603,6 +633,10 @@ static int write_stored_block_stateless(struct isal_zstream *stream,
memcpy(stream->next_out, gzip_hdr, gzip_hdr_bytes);
stream->next_out += gzip_hdr_bytes;
stream->gzip_flag = IGZIP_GZIP_NO_HDR;
} else if (stream->gzip_flag == IGZIP_ZLIB) {
memcpy(stream->next_out, zlib_hdr, zlib_hdr_bytes);
stream->next_out += zlib_hdr_bytes;
stream->gzip_flag = IGZIP_ZLIB_NO_HDR;
}
do {
@ -635,11 +669,19 @@ static int write_stored_block_stateless(struct isal_zstream *stream,
} while (avail_in != 0);
if (stream->gzip_flag && stream->internal_state.has_eob_hdr) {
gzip_trl = stream->avail_in;
gzip_trl <<= 32;
gzip_trl |= crc32 & 0xFFFFFFFF;
memcpy(stream->next_out, &gzip_trl, gzip_trl_bytes);
stream->next_out += gzip_trl_bytes;
switch (stream->gzip_flag) {
case IGZIP_GZIP:
case IGZIP_GZIP_NO_HDR:
*(uint64_t *) stream->next_out =
((uint64_t) stream->total_in << 32) | crc32;
stream->next_out += gzip_trl_bytes;
break;
case IGZIP_ZLIB:
case IGZIP_ZLIB_NO_HDR:
*(uint32_t *) stream->next_out =
to_be32((crc32 & 0xFFFF0000) | ((crc32 & 0xFFFF) + 1) % ADLER_MOD);
stream->next_out += zlib_trl_bytes;
}
}
stream->avail_in = 0;
@ -750,7 +792,6 @@ int isal_deflate_stateless(struct isal_zstream *stream)
const uint32_t total_out = stream->total_out;
const uint32_t gzip_flag = stream->gzip_flag;
uint32_t crc32 = 0;
uint32_t stored_len;
/* Final block has already been written */
@ -786,6 +827,12 @@ int isal_deflate_stateless(struct isal_zstream *stream)
else if (stream->gzip_flag == IGZIP_GZIP_NO_HDR)
stored_len += gzip_trl_bytes;
else if (stream->gzip_flag == IGZIP_ZLIB)
stored_len += zlib_hdr_bytes + zlib_trl_bytes;
else if (stream->gzip_flag == IGZIP_ZLIB_NO_HDR)
stored_len += zlib_trl_bytes;
/*
the output buffer should be no less than 8 bytes
while empty stored deflate block is 5 bytes only
@ -817,10 +864,12 @@ int isal_deflate_stateless(struct isal_zstream *stream)
stream->gzip_flag = gzip_flag;
if (stream->gzip_flag)
crc32 = crc32_gzip(0x0, next_in, avail_in);
if (stream->gzip_flag) {
stream->internal_state.crc = 0;
update_checksum(stream, next_in, avail_in);
}
return write_stored_block_stateless(stream, stored_len, crc32);
return write_stored_block_stateless(stream, stored_len, stream->internal_state.crc);
}
int isal_deflate(struct isal_zstream *stream)
@ -920,38 +969,66 @@ int isal_deflate(struct isal_zstream *stream)
return ret;
}
static int write_gzip_header_stateless(struct isal_zstream *stream)
static int write_stream_header_stateless(struct isal_zstream *stream)
{
if (gzip_hdr_bytes >= stream->avail_out)
uint32_t hdr_bytes;
const uint8_t *hdr;
uint32_t next_flag;
if (stream->gzip_flag == IGZIP_ZLIB) {
hdr_bytes = zlib_hdr_bytes;
hdr = zlib_hdr;
next_flag = IGZIP_ZLIB_NO_HDR;
} else {
hdr_bytes = gzip_hdr_bytes;
hdr = gzip_hdr;
next_flag = IGZIP_GZIP_NO_HDR;
}
if (hdr_bytes >= stream->avail_out)
return STATELESS_OVERFLOW;
stream->avail_out -= gzip_hdr_bytes;
stream->total_out += gzip_hdr_bytes;
stream->avail_out -= hdr_bytes;
stream->total_out += hdr_bytes;
memcpy(stream->next_out, gzip_hdr, gzip_hdr_bytes);
memcpy(stream->next_out, hdr, hdr_bytes);
stream->next_out += gzip_hdr_bytes;
stream->gzip_flag = IGZIP_GZIP_NO_HDR;
stream->next_out += hdr_bytes;
stream->gzip_flag = next_flag;
return COMP_OK;
}
static void write_gzip_header(struct isal_zstream *stream)
static void write_stream_header(struct isal_zstream *stream)
{
struct isal_zstate *state = &stream->internal_state;
int bytes_to_write = gzip_hdr_bytes;
int bytes_to_write;
uint32_t hdr_bytes;
const uint8_t *hdr;
uint32_t next_flag;
if (stream->gzip_flag == IGZIP_ZLIB) {
hdr_bytes = zlib_hdr_bytes;
hdr = zlib_hdr;
next_flag = IGZIP_ZLIB_NO_HDR;
} else {
hdr_bytes = gzip_hdr_bytes;
hdr = gzip_hdr;
next_flag = IGZIP_GZIP_NO_HDR;
}
bytes_to_write = hdr_bytes;
bytes_to_write -= state->count;
if (bytes_to_write > stream->avail_out)
bytes_to_write = stream->avail_out;
memcpy(stream->next_out, gzip_hdr + state->count, bytes_to_write);
memcpy(stream->next_out, hdr + state->count, bytes_to_write);
state->count += bytes_to_write;
if (state->count == gzip_hdr_bytes) {
if (state->count == hdr_bytes) {
state->count = 0;
stream->gzip_flag = IGZIP_GZIP_NO_HDR;
stream->gzip_flag = next_flag;
}
stream->avail_out -= bytes_to_write;
@ -1084,8 +1161,8 @@ void write_header(struct isal_zstream *stream, uint8_t * deflate_hdr,
stream->total_out += count;
}
if (stream->gzip_flag == IGZIP_GZIP)
write_gzip_header(stream);
if (stream->gzip_flag == IGZIP_GZIP || stream->gzip_flag == IGZIP_ZLIB)
write_stream_header(stream);
count = deflate_hdr_count - state->count;
@ -1165,10 +1242,23 @@ void write_trailer(struct isal_zstream *stream)
if (stream->gzip_flag) {
if (!is_full(&state->bitbuf)) {
*(uint64_t *) stream->next_out =
((uint64_t) stream->total_in << 32) | crc;
stream->next_out += 8;
bytes += 8;
switch (stream->gzip_flag) {
case IGZIP_GZIP:
case IGZIP_GZIP_NO_HDR:
*(uint64_t *) stream->next_out =
((uint64_t) stream->total_in << 32) | crc;
stream->next_out += gzip_trl_bytes;
bytes += gzip_trl_bytes;
break;
case IGZIP_ZLIB:
case IGZIP_ZLIB_NO_HDR:
*(uint32_t *) stream->next_out =
to_be32((crc & 0xFFFF0000)
| ((crc & 0xFFFF) + 1) % ADLER_MOD);
stream->next_out += zlib_trl_bytes;
bytes += zlib_trl_bytes;
break;
}
state->state = ZSTATE_END;
}
} else

View File

@ -41,6 +41,7 @@ struct deflate_icf *encode_deflate_icf_base(struct deflate_icf *next_in,
struct deflate_icf *end_in, struct BitBuf2 *bb,
struct hufftables_icf *hufftables);
uint32_t crc32_gzip_base(uint32_t init_crc, const unsigned char *buf, uint64_t len);
uint32_t adler32_base(uint32_t init, const unsigned char *buf, uint64_t len);
int decode_huffman_code_block_stateless_base(struct inflate_state *s);
void isal_deflate_body(struct isal_zstream *stream)
@ -81,6 +82,11 @@ uint32_t crc32_gzip(uint32_t init_crc, const unsigned char *buf, uint64_t len)
return crc32_gzip_base(init_crc, buf, len);
}
uint32_t isal_adler32(uint32_t init, const unsigned char *buf, uint64_t len)
{
return adler32_base(init, buf, len);
}
int decode_huffman_code_block_stateless(struct inflate_state *s)
{
return decode_huffman_code_block_stateless_base(s);

12
igzip/igzip_checksums.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef IGZIP_CHECKSUMS_H
#define IGZIP_CHECKSUMS_H
#include <stdint.h>
#define MAX_ADLER_BUF (1 << 28)
#define ADLER_MOD 65521
uint32_t crc32_gzip(uint32_t init_crc, const unsigned char *buf, uint64_t len);
uint32_t isal_adler32(uint32_t init_crc, const unsigned char *buf, uint64_t len);
#endif

View File

@ -63,6 +63,8 @@ extern encode_deflate_icf_04
extern crc32_gzip_base
extern crc32_gzip_01
extern adler32_base
section .text
%include "multibinary.asm"
@ -85,3 +87,6 @@ mbin_dispatch_init5 encode_deflate_icf, encode_deflate_icf_base, encode_deflate_
mbin_interface crc32_gzip
mbin_dispatch_init5 crc32_gzip, crc32_gzip_base, crc32_gzip_base, crc32_gzip_01, crc32_gzip_01
mbin_interface isal_adler32
mbin_dispatch_init5 isal_adler32, adler32_base, adler32_base, adler32_base, adler32_base

View File

@ -146,6 +146,8 @@ enum {IGZIP_LIT_TABLE_SIZE = ISAL_DEF_LIT_SYMBOLS};
#define IGZIP_DEFLATE 0 /* Default */
#define IGZIP_GZIP 1
#define IGZIP_GZIP_NO_HDR 2
#define IGZIP_ZLIB 3
#define IGZIP_ZLIB_NO_HDR 4
/* Compression Return values */
#define COMP_OK 0