/*
 * Copyright (C) 2008 Nokia Corporation.
 * Copyright (C) 2008 University of Szeged, Hungary
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 * Authors: Artem Bityutskiy
 *          Adrian Hunter
 *          Zoltan Sogor
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <zlib.h>
#include <lzo/lzo1x.h>
#include <linux/types.h>

#include "compr.h"
#include "ubifs-media.h"
#include "mkfs.ubifs.h"

static void *lzo_mem;
static unsigned long long errcnt = 0;
static struct ubifs_info *c = &info_;

#define DEFLATE_DEF_LEVEL     Z_DEFAULT_COMPRESSION
#define DEFLATE_DEF_WINBITS   11
#define DEFLATE_DEF_MEMLEVEL  8

static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
			size_t *out_len)
{
	z_stream strm;

	strm.zalloc = NULL;
	strm.zfree = NULL;

	/*
	 * Match exactly the zlib parameters used by the Linux kernel crypto
	 * API.
	 */
        if (deflateInit2(&strm, DEFLATE_DEF_LEVEL, Z_DEFLATED,
			 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
			 Z_DEFAULT_STRATEGY)) {
		errcnt += 1;
		return -1;
	}

	strm.next_in = in_buf;
	strm.avail_in = in_len;
	strm.total_in = 0;

	strm.next_out = out_buf;
	strm.avail_out = *out_len;
	strm.total_out = 0;

	if (deflate(&strm, Z_FINISH) != Z_STREAM_END) {
		deflateEnd(&strm);
		errcnt += 1;
		return -1;
	}

	if (deflateEnd(&strm) != Z_OK) {
		errcnt += 1;
		return -1;
	}

	*out_len = strm.total_out;

	return 0;
}

static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
			size_t *out_len)
{
	lzo_uint len;
	int ret;

	len = *out_len;
	ret = lzo1x_999_compress(in_buf, in_len, out_buf, &len, lzo_mem);
	*out_len = len;

	if (ret != LZO_E_OK) {
		errcnt += 1;
		return -1;
	}

	return 0;
}

static int no_compress(void *in_buf, size_t in_len, void *out_buf,
		       size_t *out_len)
{
	memcpy(out_buf, in_buf, in_len);
	*out_len = in_len;
	return 0;
}

static char *zlib_buf;

static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
			       size_t *out_len, int *type)
{
	int lzo_ret, zlib_ret;
	size_t lzo_len, zlib_len;

	lzo_len = zlib_len = *out_len;
	lzo_ret = lzo_compress(in_buf, in_len, out_buf, &lzo_len);
	zlib_ret = zlib_deflate(in_buf, in_len, zlib_buf, &zlib_len);

	if (lzo_ret && zlib_ret)
		/* Both compressors failed */
		return -1;

	if (!lzo_ret && !zlib_ret) {
		double percent;

		/* Both compressors succeeded */
		if (lzo_len <= zlib_len )
			goto select_lzo;

		percent = (double)zlib_len / (double)lzo_len;
		percent *= 100;
		if (percent > 100 - c->favor_percent)
			goto select_lzo;
		goto select_zlib;
	}

	if (lzo_ret)
		/* Only zlib compressor succeeded */
		goto select_zlib;

	/* Only LZO compressor succeeded */

select_lzo:
	*out_len = lzo_len;
	*type = MKFS_UBIFS_COMPR_LZO;
	return 0;

select_zlib:
	*out_len = zlib_len;
	*type = MKFS_UBIFS_COMPR_ZLIB;
	memcpy(out_buf, zlib_buf, zlib_len);
	return 0;
}

int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
		  int type)
{
	int ret;

	if (in_len < UBIFS_MIN_COMPR_LEN) {
		no_compress(in_buf, in_len, out_buf, out_len);
		return MKFS_UBIFS_COMPR_NONE;
	}

	if (c->favor_lzo)
		ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type);
	else {
		switch (type) {
		case MKFS_UBIFS_COMPR_LZO:
			ret = lzo_compress(in_buf, in_len, out_buf, out_len);
			break;
		case MKFS_UBIFS_COMPR_ZLIB:
			ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
			break;
		case MKFS_UBIFS_COMPR_NONE:
			ret = 1;
			break;
		default:
			errcnt += 1;
			ret = 1;
			break;
		}
	}
	if (ret || *out_len >= in_len) {
		no_compress(in_buf, in_len, out_buf, out_len);
		return MKFS_UBIFS_COMPR_NONE;
	}
	return type;
}

int init_compression(void)
{
	lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
	if (!lzo_mem)
		return -1;

	zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
	if (!zlib_buf) {
		free(lzo_mem);
		return -1;
	}

	return 0;
}

void destroy_compression(void)
{
	free(zlib_buf);
	free(lzo_mem);
	if (errcnt)
		fprintf(stderr, "%llu compression errors occurred\n", errcnt);
}
