2012-05-28 14:49:29 +00:00
|
|
|
/*
|
|
|
|
* This file is a part of Pcompress, a chunked parallel multi-
|
|
|
|
* algorithm lossless compression and decompression program.
|
|
|
|
*
|
2013-03-07 14:56:48 +00:00
|
|
|
* Copyright (C) 2012-2013 Moinak Ghosh. All rights reserved.
|
2012-05-28 14:49:29 +00:00
|
|
|
* Use is subject to license terms.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
2012-07-07 16:48:29 +00:00
|
|
|
* version 3 of the License, or (at your option) any later version.
|
2012-05-28 14:49:29 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
2013-03-07 14:56:48 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this program.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
2012-05-28 14:49:29 +00:00
|
|
|
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
2014-07-26 09:58:40 +00:00
|
|
|
*
|
2012-05-28 14:49:29 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <utils.h>
|
|
|
|
#include <pcompress.h>
|
|
|
|
#include <allocator.h>
|
|
|
|
#include <Ppmd8.h>
|
2013-12-21 15:12:38 +00:00
|
|
|
#include <pthread.h>
|
2012-05-28 14:49:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* PPMd model order to working set memory size mappings.
|
|
|
|
*/
|
2013-06-03 15:21:00 +00:00
|
|
|
static unsigned int ppmd8_mem_sz[] = {
|
2012-05-28 14:49:29 +00:00
|
|
|
(16 << 20),
|
|
|
|
(16 << 20),
|
|
|
|
(32 << 20),
|
|
|
|
(32 << 20),
|
|
|
|
(64 << 20),
|
|
|
|
(64 << 20),
|
|
|
|
(100 << 20),
|
|
|
|
(100 << 20),
|
|
|
|
(400 << 20),
|
|
|
|
(400 << 20),
|
|
|
|
(700 << 20),
|
|
|
|
(700 << 20),
|
|
|
|
(700 << 20),
|
|
|
|
(1200 << 20),
|
|
|
|
(1200 << 20)
|
|
|
|
};
|
|
|
|
|
2013-12-21 15:12:38 +00:00
|
|
|
static pthread_mutex_t mem_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static int mem_inited = 0;
|
|
|
|
|
2012-05-28 14:49:29 +00:00
|
|
|
static ISzAlloc g_Alloc = {
|
|
|
|
slab_alloc,
|
2013-12-21 18:02:27 +00:00
|
|
|
slab_release,
|
2012-05-28 14:49:29 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2013-12-21 18:02:27 +00:00
|
|
|
int
|
|
|
|
ppmd_alloc(void *data)
|
2012-05-31 16:06:33 +00:00
|
|
|
{
|
2013-12-21 18:02:27 +00:00
|
|
|
CPpmd8 *_ppmd = (CPpmd8 *)data;
|
|
|
|
|
|
|
|
if (!Ppmd8_Alloc(_ppmd, ppmd8_mem_sz[_ppmd->Order], &g_Alloc)) {
|
|
|
|
log_msg(LOG_ERR, 0, "PPMD: Out of memory.\n");
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
Ppmd8_Construct(_ppmd);
|
|
|
|
return (0);
|
2012-05-31 16:06:33 +00:00
|
|
|
}
|
|
|
|
|
2012-12-04 18:39:47 +00:00
|
|
|
void
|
2013-12-21 18:02:27 +00:00
|
|
|
ppmd_free(void *data)
|
|
|
|
{
|
|
|
|
CPpmd8 *_ppmd = (CPpmd8 *)data;
|
|
|
|
Ppmd8_Free(_ppmd, &g_Alloc);
|
2012-12-04 18:39:47 +00:00
|
|
|
}
|
|
|
|
|
2012-05-28 14:49:29 +00:00
|
|
|
int
|
2013-12-21 18:02:27 +00:00
|
|
|
ppmd_state_init(void **data, int *level, int alloc)
|
2012-05-28 14:49:29 +00:00
|
|
|
{
|
|
|
|
CPpmd8 *_ppmd;
|
|
|
|
|
2013-12-21 15:12:38 +00:00
|
|
|
pthread_mutex_lock(&mem_init_lock);
|
|
|
|
if (!mem_inited) {
|
|
|
|
slab_cache_add(sizeof (CPpmd8));
|
|
|
|
slab_cache_add(ppmd8_mem_sz[*level]);
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&mem_init_lock);
|
2012-05-28 14:49:29 +00:00
|
|
|
_ppmd = (CPpmd8 *)slab_alloc(NULL, sizeof (CPpmd8));
|
|
|
|
if (!_ppmd)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
/* Levels 0 - 14 correspond to PPMd model orders 0 - 14. */
|
|
|
|
if (*level > 14) *level = 14;
|
|
|
|
_ppmd->Order = *level;
|
|
|
|
|
|
|
|
_ppmd->Base = 0;
|
|
|
|
_ppmd->Size = 0;
|
|
|
|
*data = _ppmd;
|
|
|
|
if (*level > 9) *level = 9;
|
2013-12-21 18:02:27 +00:00
|
|
|
|
|
|
|
if (alloc)
|
|
|
|
return (ppmd_alloc(*data));
|
2012-05-28 14:49:29 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2013-12-21 18:02:27 +00:00
|
|
|
void
|
|
|
|
ppmd_stats(int show)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ppmd_props(algo_props_t *data, int level, uint64_t chunksize) {
|
|
|
|
data->delta2_span = 100;
|
|
|
|
data->deltac_min_distance = FOURM;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ppmd_init(void **data, int *level, int nthreads, uint64_t chunksize,
|
|
|
|
int file_version, compress_op_t op)
|
|
|
|
{
|
|
|
|
return (ppmd_state_init(data, level, 1));
|
|
|
|
}
|
|
|
|
|
2012-05-28 14:49:29 +00:00
|
|
|
int
|
|
|
|
ppmd_deinit(void **data)
|
|
|
|
{
|
|
|
|
CPpmd8 *_ppmd = (CPpmd8 *)(*data);
|
|
|
|
if (_ppmd) {
|
2013-12-21 18:02:27 +00:00
|
|
|
ppmd_free(*data);
|
|
|
|
slab_release(NULL, _ppmd);
|
2012-05-28 14:49:29 +00:00
|
|
|
}
|
|
|
|
*data = NULL;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-09 04:45:06 +00:00
|
|
|
ppmd_compress(void *src, uint64_t srclen, void *dst,
|
2013-11-08 18:20:28 +00:00
|
|
|
uint64_t *dstlen, int level, uchar_t chdr, int btype, void *data)
|
2012-05-28 14:49:29 +00:00
|
|
|
{
|
|
|
|
CPpmd8 *_ppmd = (CPpmd8 *)data;
|
|
|
|
uchar_t *_src = (uchar_t *)src;
|
|
|
|
|
2013-11-09 11:16:19 +00:00
|
|
|
if (PC_TYPE(btype) == TYPE_COMPRESSED)
|
2013-11-08 18:20:28 +00:00
|
|
|
return (-1);
|
2013-11-09 11:16:19 +00:00
|
|
|
|
2012-05-28 14:49:29 +00:00
|
|
|
Ppmd8_RangeEnc_Init(_ppmd);
|
|
|
|
Ppmd8_Init(_ppmd, _ppmd->Order, PPMD8_RESTORE_METHOD_RESTART);
|
|
|
|
_ppmd->buf = (Byte *)dst;
|
|
|
|
_ppmd->bufLen = *dstlen;
|
|
|
|
_ppmd->bufUsed = 0;
|
2012-11-09 14:35:13 +00:00
|
|
|
_ppmd->overflow = 0;
|
2012-05-28 14:49:29 +00:00
|
|
|
|
|
|
|
Ppmd8_EncodeBuffer(_ppmd, _src, srclen);
|
|
|
|
Ppmd8_EncodeSymbol(_ppmd, -1);
|
|
|
|
Ppmd8_RangeEnc_FlushData(_ppmd);
|
|
|
|
|
2012-11-09 14:35:13 +00:00
|
|
|
if (_ppmd->overflow) return (-1);
|
2012-05-28 14:49:29 +00:00
|
|
|
*dstlen = _ppmd->bufUsed;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-09 04:45:06 +00:00
|
|
|
ppmd_decompress(void *src, uint64_t srclen, void *dst,
|
2013-11-08 18:20:28 +00:00
|
|
|
uint64_t *dstlen, int level, uchar_t chdr, int btype, void *data)
|
2012-05-28 14:49:29 +00:00
|
|
|
{
|
|
|
|
CPpmd8 *_ppmd = (CPpmd8 *)data;
|
2012-07-01 16:14:02 +00:00
|
|
|
Byte *_src = (Byte *)src;
|
2012-05-28 14:49:29 +00:00
|
|
|
Byte *_dst = (Byte *)dst;
|
2014-04-27 18:42:51 +00:00
|
|
|
SizeT i;
|
2012-05-28 14:49:29 +00:00
|
|
|
int res;
|
|
|
|
|
|
|
|
_ppmd->buf = (Byte *)_src;
|
|
|
|
_ppmd->bufLen = srclen;
|
|
|
|
_ppmd->bufUsed = 0;
|
2012-11-09 14:35:13 +00:00
|
|
|
_ppmd->overflow = 0;
|
2012-05-28 14:49:29 +00:00
|
|
|
Ppmd8_RangeDec_Init(_ppmd);
|
|
|
|
Ppmd8_Init(_ppmd, _ppmd->Order, PPMD8_RESTORE_METHOD_RESTART);
|
|
|
|
|
|
|
|
res = Ppmd8_DecodeToBuffer(_ppmd, _dst, *dstlen, &i);
|
|
|
|
if (res < 0 && res != -1) {
|
|
|
|
if (Ppmd8_DecodeSymbol(_ppmd) != -1)
|
|
|
|
return (-1);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2012-11-09 14:35:13 +00:00
|
|
|
if (i < *dstlen || _ppmd->overflow)
|
2012-05-28 14:49:29 +00:00
|
|
|
return (-1);
|
|
|
|
return (0);
|
|
|
|
}
|