mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 10:07:02 -06:00
202 lines
5.9 KiB
C
202 lines
5.9 KiB
C
/*
|
|
* Copyright (c) 2018, Conor McCarthy
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under both the BSD-style license (found in the
|
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
* in the COPYING file in the root directory of this source tree).
|
|
* You may select, at your option, one of the above-listed licenses.
|
|
*/
|
|
|
|
#ifndef FL2_RADIX_GET_H_
|
|
#define FL2_RADIX_GET_H_
|
|
|
|
#if defined (__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
U32 length;
|
|
U32 dist;
|
|
} RMF_match;
|
|
|
|
static size_t RMF_bitpackExtendMatch(const BYTE* const data,
|
|
const U32* const table,
|
|
ptrdiff_t const start_index,
|
|
ptrdiff_t limit,
|
|
U32 const link,
|
|
size_t const length)
|
|
{
|
|
ptrdiff_t end_index = start_index + length;
|
|
ptrdiff_t const dist = start_index - link;
|
|
|
|
if (limit > start_index + (ptrdiff_t)kMatchLenMax)
|
|
limit = start_index + kMatchLenMax;
|
|
|
|
while (end_index < limit && end_index - (ptrdiff_t)(table[end_index] & RADIX_LINK_MASK) == dist)
|
|
end_index += table[end_index] >> RADIX_LINK_BITS;
|
|
|
|
if (end_index >= limit) {
|
|
DEBUGLOG(7, "RMF_bitpackExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(limit - start_index));
|
|
return limit - start_index;
|
|
}
|
|
|
|
while (end_index < limit && data[end_index - dist] == data[end_index])
|
|
++end_index;
|
|
|
|
DEBUGLOG(7, "RMF_bitpackExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(end_index - start_index));
|
|
return end_index - start_index;
|
|
}
|
|
|
|
#define GetMatchLink(table, pos) ((const RMF_unit*)(table))[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]
|
|
|
|
#define GetMatchLength(table, pos) ((const RMF_unit*)(table))[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK]
|
|
|
|
static size_t RMF_structuredExtendMatch(const BYTE* const data,
|
|
const U32* const table,
|
|
ptrdiff_t const start_index,
|
|
ptrdiff_t limit,
|
|
U32 const link,
|
|
size_t const length)
|
|
{
|
|
ptrdiff_t end_index = start_index + length;
|
|
ptrdiff_t const dist = start_index - link;
|
|
|
|
if (limit > start_index + (ptrdiff_t)kMatchLenMax)
|
|
limit = start_index + kMatchLenMax;
|
|
|
|
while (end_index < limit && end_index - (ptrdiff_t)GetMatchLink(table, end_index) == dist)
|
|
end_index += GetMatchLength(table, end_index);
|
|
|
|
if (end_index >= limit) {
|
|
DEBUGLOG(7, "RMF_structuredExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(limit - start_index));
|
|
return limit - start_index;
|
|
}
|
|
|
|
while (end_index < limit && data[end_index - dist] == data[end_index])
|
|
++end_index;
|
|
|
|
DEBUGLOG(7, "RMF_structuredExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(end_index - start_index));
|
|
return end_index - start_index;
|
|
}
|
|
|
|
FORCE_INLINE_TEMPLATE
|
|
RMF_match RMF_getMatch(FL2_dataBlock block,
|
|
FL2_matchTable* tbl,
|
|
unsigned max_depth,
|
|
int structTbl,
|
|
size_t pos)
|
|
{
|
|
if (structTbl)
|
|
{
|
|
U32 const link = GetMatchLink(tbl->table, pos);
|
|
|
|
RMF_match match;
|
|
match.length = 0;
|
|
|
|
if (link == RADIX_NULL_LINK)
|
|
return match;
|
|
|
|
size_t const length = GetMatchLength(tbl->table, pos);
|
|
size_t const dist = pos - link - 1;
|
|
|
|
if (length == max_depth || length == STRUCTURED_MAX_LENGTH /* from HandleRepeat */)
|
|
match.length = (U32)RMF_structuredExtendMatch(block.data, tbl->table, pos, block.end, link, length);
|
|
else
|
|
match.length = (U32)length;
|
|
|
|
match.dist = (U32)dist;
|
|
|
|
return match;
|
|
}
|
|
else {
|
|
U32 link = tbl->table[pos];
|
|
|
|
RMF_match match;
|
|
match.length = 0;
|
|
|
|
if (link == RADIX_NULL_LINK)
|
|
return match;
|
|
|
|
size_t const length = link >> RADIX_LINK_BITS;
|
|
link &= RADIX_LINK_MASK;
|
|
size_t const dist = pos - link - 1;
|
|
|
|
if (length == max_depth || length == BITPACK_MAX_LENGTH /* from HandleRepeat */)
|
|
match.length = (U32)RMF_bitpackExtendMatch(block.data, tbl->table, pos, block.end, link, length);
|
|
else
|
|
match.length = (U32)length;
|
|
|
|
match.dist = (U32)dist;
|
|
|
|
return match;
|
|
}
|
|
}
|
|
|
|
FORCE_INLINE_TEMPLATE
|
|
RMF_match RMF_getNextMatch(FL2_dataBlock block,
|
|
FL2_matchTable* tbl,
|
|
unsigned max_depth,
|
|
int structTbl,
|
|
size_t pos)
|
|
{
|
|
if (structTbl)
|
|
{
|
|
U32 const link = GetMatchLink(tbl->table, pos);
|
|
|
|
RMF_match match;
|
|
match.length = 0;
|
|
|
|
if (link == RADIX_NULL_LINK)
|
|
return match;
|
|
|
|
size_t const length = GetMatchLength(tbl->table, pos);
|
|
size_t const dist = pos - link - 1;
|
|
|
|
/* same distance, one byte shorter */
|
|
if (link - 1 == GetMatchLink(tbl->table, pos - 1))
|
|
return match;
|
|
|
|
if (length == max_depth || length == STRUCTURED_MAX_LENGTH /* from HandleRepeat */)
|
|
match.length = (U32)RMF_structuredExtendMatch(block.data, tbl->table, pos, block.end, link, length);
|
|
else
|
|
match.length = (U32)length;
|
|
|
|
match.dist = (U32)dist;
|
|
|
|
return match;
|
|
}
|
|
else {
|
|
U32 link = tbl->table[pos];
|
|
|
|
RMF_match match;
|
|
match.length = 0;
|
|
|
|
if (link == RADIX_NULL_LINK)
|
|
return match;
|
|
|
|
size_t const length = link >> RADIX_LINK_BITS;
|
|
link &= RADIX_LINK_MASK;
|
|
size_t const dist = pos - link - 1;
|
|
|
|
/* same distance, one byte shorter */
|
|
if (link - 1 == (tbl->table[pos - 1] & RADIX_LINK_MASK))
|
|
return match;
|
|
|
|
if (length == max_depth || length == BITPACK_MAX_LENGTH /* from HandleRepeat */)
|
|
match.length = (U32)RMF_bitpackExtendMatch(block.data, tbl->table, pos, block.end, link, length);
|
|
else
|
|
match.length = (U32)length;
|
|
|
|
match.dist = (U32)dist;
|
|
|
|
return match;
|
|
}
|
|
}
|
|
|
|
#if defined (__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif /* FL2_RADIX_GET_H_ */ |