summaryrefslogtreecommitdiffstats
path: root/depends/lzma/wrapper/simple.c
blob: 98d3c285b44e259bcb591704d57c6b238d018182 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * 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.
 *
 * simple.c - a wrapper around easylzma to compress/decompress to memory
 */

#include "simple.h"

#include <string.h>
#include <assert.h>

struct dataStream
{
	const unsigned char *inData;
	size_t inLen;

	unsigned char *outData;
	size_t outLen;
};

static int inputCallback(void *ctx, void *buf, size_t *size)
{
	size_t rd = 0;
	struct dataStream *ds = (struct dataStream *)ctx;
	assert(ds != NULL);

	rd = (ds->inLen < *size) ? ds->inLen : *size;

	if (rd > 0)
	{
		memcpy(buf, (void *)ds->inData, rd);
		ds->inData += rd;
		ds->inLen -= rd;
	}

	*size = rd;

	return 0;
}

static size_t outputCallback(void *ctx, const void *buf, size_t size)
{
	struct dataStream *ds = (struct dataStream *)ctx;
	assert(ds != NULL);

	if (size > 0)
	{
		ds->outData = realloc(ds->outData, ds->outLen + size);
		memcpy((void *)(ds->outData + ds->outLen), buf, size);
		ds->outLen += size;
	}

	return size;
}

int simpleCompress(elzma_file_format format, const unsigned char *inData, size_t inLen,
				   unsigned char **outData, size_t *outLen)
{
	int rc;
	elzma_compress_handle hand;

	/* allocate compression handle */
	hand = elzma_compress_alloc();
	assert(hand != NULL);

	rc = elzma_compress_config(hand, ELZMA_LC_DEFAULT, ELZMA_LP_DEFAULT, ELZMA_PB_DEFAULT, 5,
							   (1 << 20) /* 1mb */, format, inLen);

	if (rc != ELZMA_E_OK)
	{
		elzma_compress_free(&hand);
		return rc;
	}

	/* now run the compression */
	{
		struct dataStream ds;
		ds.inData = inData;
		ds.inLen = inLen;
		ds.outData = NULL;
		ds.outLen = 0;

		rc = elzma_compress_run(hand, inputCallback, (void *)&ds, outputCallback, (void *)&ds,
								NULL, NULL);

		if (rc != ELZMA_E_OK)
		{
			if (ds.outData != NULL)
				free(ds.outData);
			elzma_compress_free(&hand);
			return rc;
		}

		*outData = ds.outData;
		*outLen = ds.outLen;
	}

	return rc;
}

int simpleDecompress(elzma_file_format format, const unsigned char *inData, size_t inLen,
					 unsigned char **outData, size_t *outLen)
{
	int rc;
	elzma_decompress_handle hand;

	hand = elzma_decompress_alloc();

	/* now run the compression */
	{
		struct dataStream ds;
		ds.inData = inData;
		ds.inLen = inLen;
		ds.outData = NULL;
		ds.outLen = 0;

		rc = elzma_decompress_run(hand, inputCallback, (void *)&ds, outputCallback, (void *)&ds,
								  format);

		if (rc != ELZMA_E_OK)
		{
			if (ds.outData != NULL)
				free(ds.outData);
			elzma_decompress_free(&hand);
			return rc;
		}

		*outData = ds.outData;
		*outLen = ds.outLen;
	}

	return rc;
}