125 lines
3.8 KiB
C
125 lines
3.8 KiB
C
/*
|
|
* Copyright (c) 2007-2013 Apple Inc. All rights reserved.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* The contents of this file constitute Original Code as defined in and
|
|
* are subject to the Apple Public Source License Version 1.1 (the
|
|
* "License"). You may not use this file except in compliance with the
|
|
* License. Please obtain a copy of the License at
|
|
* http://www.apple.com/publicsource and read it before using this file.
|
|
*
|
|
* This Original Code and all software distributed under the License are
|
|
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
|
|
* License for the specific language governing rights and limitations
|
|
* under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*/
|
|
|
|
#include <sys.h>
|
|
#include <arch.h>
|
|
#include <lib/lzss.h>
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
uint32_t decompress_lzss_vec(uint8_t *dst, uint32_t dstlen, const uint8_t *src, uint32_t srclen);
|
|
|
|
#define N 4096 /* size of ring buffer - must be power of 2 */
|
|
#define F 18 /* upper limit for match_length */
|
|
#define THRESHOLD 2 /* encode string into position and length
|
|
if match_length is greater than this */
|
|
#define NIL N /* index for root of binary search trees */
|
|
#define TEXT_BUF (N + F - 1) /* size of ring buffer with F-1 extra bytes
|
|
to aid string comparison */
|
|
|
|
uint32_t decompress_lzss(uint8_t * __restrict dst, uint32_t dstlen, const uint8_t * __restrict src, uint32_t srclen)
|
|
{
|
|
#if (ARCH_ARMv7 && WITH_VFP) || defined(__arm64__)
|
|
#if WITH_VFP_ALWAYS_ON
|
|
return decompress_lzss_vec(dst, dstlen, src, srclen);
|
|
#else
|
|
bool fp_enabled;
|
|
uint32_t result;
|
|
|
|
fp_enabled = arch_task_fp_enable(true);
|
|
result = decompress_lzss_vec(dst, dstlen, src, srclen);
|
|
arch_task_fp_enable(fp_enabled);
|
|
return result;
|
|
#endif // WITH_VFP_ALWAYS_ON
|
|
#else
|
|
uint8_t *text_buf = NULL;
|
|
uint8_t *dststart = dst;
|
|
uint8_t *dstend = dst + dstlen;
|
|
const uint8_t *srcend = src + srclen;
|
|
uint32_t i, j, k, r, c;
|
|
uint32_t flags;
|
|
uint32_t result = 0;
|
|
|
|
text_buf = (uint8_t *)malloc(TEXT_BUF);
|
|
if (text_buf == NULL)
|
|
goto error;
|
|
memset(text_buf, ' ', N - F);
|
|
|
|
r = N - F;
|
|
flags = 0;
|
|
for ( ; ; ) {
|
|
if (((flags >>= 1) & 0x100) == 0) {
|
|
if (src < srcend) {
|
|
c = *src++;
|
|
} else {
|
|
break;
|
|
}
|
|
flags = c | 0xFF00; /* uses higher byte cleverly */
|
|
} /* to count eight */
|
|
if (flags & 1) {
|
|
if (src < srcend) {
|
|
c = *src++;
|
|
} else {
|
|
break;
|
|
}
|
|
if (dst == dstend) {
|
|
goto error;
|
|
}
|
|
*dst++ = c;
|
|
text_buf[r++] = c;
|
|
r &= (N - 1);
|
|
} else {
|
|
if (src < srcend) {
|
|
i = *src++;
|
|
} else {
|
|
break;
|
|
}
|
|
if (src < srcend) {
|
|
j = *src++;
|
|
} else {
|
|
break;
|
|
}
|
|
i |= ((j & 0xF0) << 4);
|
|
j = (j & 0x0F) + THRESHOLD;
|
|
for (k = 0; k <= j; k++) {
|
|
c = text_buf[(i + k) & (N - 1)];
|
|
if (dst == dstend) {
|
|
goto error;
|
|
}
|
|
*dst++ = c;
|
|
text_buf[r++] = c;
|
|
r &= (N - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
result = dst - dststart;
|
|
|
|
error:
|
|
if (text_buf != NULL)
|
|
free(text_buf);
|
|
|
|
return result;
|
|
#endif
|
|
}
|