third-party/licensing: Switch miniLZO usage to LZOkay (#232)

* add rough jak 2 config so the decompiler can atleast unpack dgos

* third-party: commit lzokay

* Switch to lzokay for DGO decompression

* third-party: Remove minilzo library

* third-party: Add lzokay as a SHARED lib
This commit is contained in:
Tyler Wilding
2021-02-06 06:54:23 -08:00
committed by GitHub
parent ddffda1e8c
commit 5b6a8dcf98
23 changed files with 1140 additions and 10242 deletions
+7
View File
@@ -53,6 +53,13 @@
"projectTarget" : "decompiler.exe (bin\\decompiler.exe)",
"name" : "Run Decompiler - Jak 1",
"args" : [ "${workspaceRoot}/decompiler/config/jak1_ntsc_black_label.jsonc", "${workspaceRoot}/iso_data/jak1", "${workspaceRoot}/decompiler_out/jak1"]
},
{
"type" : "default",
"project" : "CMakeLists.txt",
"projectTarget" : "decompiler.exe (bin\\decompiler.exe)",
"name" : "Run Decompiler - Jak 2",
"args" : [ "${workspaceRoot}/decompiler/config/jak2_ntsc_v1.jsonc", "${workspaceRoot}/iso_data/jak2", "${workspaceRoot}/decompiler_out/jak2"]
}
]
}
+2 -2
View File
@@ -86,8 +86,8 @@ include(GoogleTest)
# build tests
include(test/CMakeLists.txt)
# build minilzo library
add_subdirectory(third-party/minilzo EXCLUDE_FROM_ALL)
# build lzokay library
add_subdirectory(third-party/lzokay EXCLUDE_FROM_ALL)
# build format library
add_subdirectory(third-party/fmt EXCLUDE_FROM_ALL)
+2 -2
View File
@@ -51,7 +51,7 @@ add_library(
)
target_link_libraries(decomp
minilzo
lzokay
common
fmt
)
@@ -63,7 +63,7 @@ add_executable(decompiler
target_link_libraries(decompiler
decomp
common
minilzo
lzokay
fmt)
install(TARGETS decompiler)
+7 -10
View File
@@ -18,7 +18,7 @@
#include "decompiler/data/game_count.h"
#include "LinkedObjectFileCreation.h"
#include "decompiler/config.h"
#include "third-party/minilzo/minilzo.h"
#include "third-party/lzokay/lzokay.hpp"
#include "common/util/BinaryReader.h"
#include "common/util/Timer.h"
#include "common/util/FileUtil.h"
@@ -204,13 +204,10 @@ void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
}
if (is_jak2) {
if (lzo_init() != LZO_E_OK) {
assert(false);
}
BinaryReader compressed_reader(dgo_data);
// seek past oZlB
compressed_reader.ffwd(4);
auto decompressed_size = compressed_reader.read<uint32_t>();
std::size_t decompressed_size = compressed_reader.read<uint32_t>();
std::vector<uint8_t> decompressed_data;
decompressed_data.resize(decompressed_size);
size_t output_offset = 0;
@@ -222,11 +219,11 @@ void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
}
if (chunk_size < MAX_CHUNK_SIZE) {
lzo_uint bytes_written;
auto lzo_rv =
lzo1x_decompress(compressed_reader.here(), chunk_size,
decompressed_data.data() + output_offset, &bytes_written, nullptr);
assert(lzo_rv == LZO_E_OK);
std::size_t bytes_written = 0;
lzokay::EResult ok = lzokay::decompress(
compressed_reader.here(), chunk_size, decompressed_data.data() + output_offset,
decompressed_data.size() - output_offset, bytes_written);
assert(ok == lzokay::EResult::Success);
compressed_reader.ffwd(chunk_size);
output_offset += bytes_written;
} else {
+1 -1
View File
@@ -91,7 +91,7 @@ class ObjectFileDB {
const std::string& obj_name,
TypeSpec* result);
private:
public:
void load_map_file(const std::string& map_data);
void get_objs_from_dgo(const std::string& filename);
void add_obj_from_dgo(const std::string& obj_name,
@@ -0,0 +1,10 @@
{
"gkernel":[
[16, "(function process symbol)"],
[22, "(function process symbol)"],
[25, "(function process symbol)"],
[28, "(function process symbol)"],
[30, "(function process symbol)"],
[32, "(function process symbol)"]
]
}
+112
View File
@@ -0,0 +1,112 @@
{
"(method 2 array)":[
[23, ["gp", "(array int32)"]],
[43, ["gp", "(array uint32)"]],
[63, ["gp", "(array int64)"]],
[83, ["gp", "(array uint64)"]],
[102, ["gp", "(array int8)"]],
[121, ["gp", "(array uint8)"]],
[141, ["gp", "(array int16)"]],
[161, ["gp", "(array uint16)"]],
[185, ["gp", "(array uint128)"]],
[203, ["gp", "(array int32)"]],
[222, ["gp", "(array float)"]],
[231, ["gp", "(array float)"]],
[248, ["gp", "(array basic)"]],
[257, ["gp", "(array basic)"]]
],
"(method 3 array)":[
[44, ["gp", "(array int32)"]],
[62, ["gp", "(array uint32)"]],
[80, ["gp", "(array int64)"]],
[98, ["gp", "(array uint64)"]],
[115, ["gp", "(array int8)"]],
[132, ["gp", "(array int8)"]], // bug in game
[150, ["gp", "(array int16)"]],
[168, ["gp", "(array uint16)"]],
[190, ["gp", "(array uint128)"]],
[203, ["gp", "(array int32)"]],
[225, ["gp", "(array float)"]],
[242, ["gp", "(array basic)"]]
],
"(method 2 handle)":[
[10, ["a3", "process"]],
[11, ["v1", "int"]],
[15, ["gp", "int"]]
],
"(method 3 handle)":[
[10, ["gp", "int"]]
],
"(method 0 cpu-thread)":[
[13, ["v0", "cpu-thread"]]
],
"(method 0 dead-pool-heap)":[
[60, ["v0", "int"]], // a lie, actually the 115 is an align16 constant propagated on addr of heap start.
[61, ["a0", "pointer"], ["v0", "dead-pool-heap"]]
],
"(method 21 dead-pool-heap)":[
[5, ["v1", "pointer"]],
[13, ["a0", "pointer"]],
[25, ["v1", "pointer"]]
],
"(method 5 dead-pool-heap)":[
[3, ["v1", "int"], ["a0", "int"]]
],
"remove-exit":[
[0, ["s6", "process"]]
],
"(method 0 process)":[
[12, ["a0", "int"]],
[13, ["v0", "process"]]
],
"inspect-process-heap":[
[4, ["s5", "basic"]],
[17, ["s5", "int"]]
],
"return-from-thread-dead":[
[0, ["s6", "process"]]
],
"(method 14 dead-pool)":[
[23, ["v1", "process"]], // bad visit order with #f?
[28, ["s4", "(pointer process-tree)"]] // bug in real game, see gkernel.gc
],
"throw":[
[20, ["s4", "protect-frame"]] // type case
],
"(method 0 protect-frame)":[
[0, ["a0", "int"]],
[1, ["v0", "protect-frame"]]
],
"(method 9 process)":[
[43, ["s5", "process"]]
],
"(method 10 process)":[
[24, ["s4", "protect-frame"]]
],
"enter-state":[
[67, ["s0", "protect-frame"]]
],
"name=":[
[24, ["a1", "symbol"]],
[39, ["a0", "symbol"]]
]
}
+39 -32
View File
@@ -1,43 +1,50 @@
{
"game_version":2,
"dgo_names":["ART.CGO", "ATE.DGO", "ATO.DGO", "CAB.DGO", "CAP.DGO", "CAS.DGO", "CASCITY.DGO", "CASEXT.DGO",
"CFA.DGO", "CFB.DGO", "CGA.DGO", "CGB.DGO", "CGC.DGO", "CIA.DGO", "CIB.DGO", "CMA.DGO",
"CMB.DGO", "COA.DGO", "COB.DGO", "COMMON.CGO", "CPA.DGO", "CPO.DGO", "CTA.DGO", "CTB.DGO",
"CTC.DGO", "CTYASHA.DGO", "CTYKORA.DGO", "CWI.DGO", "D3A.DGO", "D3B.DGO", "DEMO.DGO", "DG1.DGO",
"DMI.DGO", "DRB.DGO", "DRI.DGO", "DRILLMTN.DGO", "ENGINE.CGO", "FDA.DGO", "FDB.DGO", "FEA.DGO",
"FEB.DGO", "FOB.DGO", "FOR.DGO", "FORDUMPC.DGO", "FORDUMPD.DGO", "FRA.DGO", "FRB.DGO", "GAME.CGO",
"GARAGE.DGO", "GGA.DGO", "HALFPIPE.DGO", "HIDEOUT.DGO", "HIPHOG.DGO", "INTROCST.DGO", "KERNEL.CGO", "KIOSK.DGO",
"LASHGRD.DGO", "LASHTHRN.DGO", "LBBUSH.DGO", "LBOMBBOT.DGO", "LBRNERMK.DGO", "LCGUARD.DGO", "LCITYLOW.DGO", "LDJAKBRN.DGO",
"LERBRNGD.DGO", "LERLCHAL.DGO", "LERLTESS.DGO", "LERROL.DGO", "LGARCSTA.DGO", "LGUARD.DGO", "LHELLDOG.DGO", "LHIPOUT.DGO",
"LINTCSTB.DGO", "LJAKDAX.DGO", "LJKDXASH.DGO", "LKEIRIFT.DGO", "LKIDDOGE.DGO", "LMEETBRT.DGO", "LOUTCSTB.DGO", "LPACKAGE.DGO",
"LPORTRUN.DGO", "LPOWER.DGO", "LPROTECT.DGO", "LPRSNCST.DGO", "LPRTRACE.DGO", "LRACEBB.DGO", "LRACEBF.DGO", "LRACECB.DGO",
"LRACECF.DGO", "LRACEDB.DGO", "LRACEDF.DGO", "LRACELIT.DGO", "LSACK.DGO", "LSAMERGD.DGO", "LSHUTTLE.DGO", "LSMYSBRT.DGO",
"LTENTOB.DGO", "LTENTOUT.DGO", "LTESS.DGO", "LTHRNOUT.DGO", "LTRNKRKD.DGO", "LTRNTESS.DGO", "LTRNYSAM.DGO", "LWHACK.DGO",
"LWIDEA.DGO", "LWIDEB.DGO", "LWIDEC.DGO", "LWIDESTA.DGO", "LYSAMSAM.DGO", "LYSKDCD.DGO", "MCN.DGO", "MTN.DGO",
"MTX.DGO", "NEB.DGO", "NES.DGO", "NESTT.DGO", "ONINTENT.DGO", "ORACLE.DGO", "OUTROCST.DGO", "PAC.DGO",
"PAE.DGO", "PALBOSS.DGO", "PALOUT.DGO", "PAR.DGO", "PAS.DGO", "PORTWALL.DGO", "PRI.DGO", "RUI.DGO",
"SAG.DGO", "SEB.DGO", "SEW.DGO", "SKA.DGO", "STA.DGO", "STADBLMP.DGO", "STB.DGO", "STC.DGO",
"STD.DGO", "STR.DGO", "SWB.DGO", "SWE.DGO", "TBO.DGO", "THR.DGO", "TITLE.DGO", "TOA.DGO",
"TOB.DGO", "TOC.DGO", "TOD.DGO", "TOE.DGO", "TOMBEXT.DGO", "UNB.DGO", "UND.DGO", "VI1.DGO",
"VIN.DGO"],
"dgo_names":["CGO/COMMON.CGO"],
// to write out disassembled functions in .func files
"write_disassembly":true,
"write_hex_near_instructions":false,
// if false, skips disassembling object files without functions, as these are usually large and not interesting yet.
"disassemble_objects_without_functions":false,
"object_file_names":[],
// to write out data of each object file
"write_hexdump":false,
// to write out hexdump on the v3 only, to avoid the huge level data files
"write_hexdump_on_v3_only":true,
"type_hints_file":"decompiler/config/jak2/type_hints.jsonc",
"anonymous_function_types_file":"decompiler/config/jak2/anonymous_function_types.jsonc",
// to write out "scripts", which are currently just all the linked lists found
"write_scripts":true,
"str_file_names":[],
"str_file_names_":[],
"allowed_objects":[],
"analyze_functions":true,
"analyze_expressions":false,
"function_type_prop":true,
"write_disassembly":true,
"write_hex_near_instructions":false,
"run_ir2":true,
// if false, skips printing disassembly of object with functions, as these are usually large (~1 GB) and not interesting yet.
"disassemble_objects_without_functions":false,
"process_tpages":true,
"process_game_text":true,
"process_game_count":true,
"dump_objs":true,
"write_func_json":false,
// to write out data of each object file
"write_hexdump":false,
// to write out hexdump on the v3 only, to avoid the huge level data files. Only if write_hexdump is true.
"write_hexdump_on_v3_only":true,
// to write out "scripts", which are currently just all the linked lists found. mostly a jak 2/3 thing
"write_scripts":false,
// Experimental Stuff
"find_basic_blocks":true
"find_basic_blocks":true,
"types_with_bad_inspect_methods":[],
"no_type_analysis_functions_by_name":[],
"asm_functions_by_name":[],
"pair_functions_by_name":[]
}
+58
View File
@@ -0,0 +1,58 @@
cmake_minimum_required(VERSION 3.10)
include(CMakePackageConfigHelpers)
project(lzokay VERSION 0.1 LANGUAGES CXX)
add_library(lzokay SHARED lzokay.hpp lzokay.cpp)
add_executable(lzokaytest test.cpp)
target_include_directories(lzokay PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(lzokaytest lzokay)
target_compile_features(lzokay PRIVATE cxx_std_14)
target_compile_features(lzokaytest PRIVATE cxx_std_14)
set_target_properties(lzokay PROPERTIES CXX_STANDARD 14)
set_target_properties(lzokaytest PROPERTIES CXX_STANDARD 14)
# Set installation for headers
install(
FILES "${PROJECT_SOURCE_DIR}/lzokay.hpp"
DESTINATION "include/lzokay"
)
set(version_config_file "${PROJECT_BINARY_DIR}/lzokayConfigVersion.cmake")
set(config_file "${PROJECT_BINARY_DIR}/lzokayConfig.cmake")
set(config_install_dir "lib/cmake/lzokay")
# Associate target with export
install(
TARGETS lzokay
EXPORT lzokayTargets
ARCHIVE DESTINATION "lib"
INCLUDES DESTINATION "include/lzokay" # This sets the INTERFACE_INCLUDE_DIRECTORIES property of the target.
)
# Install the target config files
install(
EXPORT lzokayTargets
NAMESPACE "lzokay::"
DESTINATION "${config_install_dir}"
)
# Generate version config file
write_basic_package_version_file(
"${version_config_file}"
COMPATIBILITY SameMajorVersion
)
# Generate config file
configure_package_config_file(
"Config.cmake.in"
"${config_file}"
INSTALL_DESTINATION "lib/cmake/lzokay"
)
# Install the config files
install(
FILES "${config_file}" "${version_config_file}"
DESTINATION ${config_install_dir}
)
add_subdirectory("lzokay-c")
+4
View File
@@ -0,0 +1,4 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/lzokayTargets.cmake")
check_required_components(lzokay)
+22
View File
@@ -0,0 +1,22 @@
The MIT License
Copyright (c) 2018 Jack Andersen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+62
View File
@@ -0,0 +1,62 @@
LZ👌
===
A minimal, C++14 implementation of the
[LZO compression format](http://www.oberhumer.com/opensource/lzo/).
Objective
---------
The implementation provides compression behavior similar to the
`lzo1x_999_compress` function in `lzo2` (i.e. higher compression, lower speed).
The implementation is fixed to the default parameters of the original and
provides no facilities for various compression "levels" or an initialization
dictionary.
The decompressor is compatible with data compressed by other LZO1X
implementations.
Usage
-----
```cpp
#include <lzokay.hpp>
#include <cstring>
int compress_and_decompress(const uint8_t* data, std::size_t length) {
lzokay::EResult error;
/* This variable and 6th parameter of compress() is optional, but may
* be reused across multiple compression runs; avoiding repeat
* allocation/deallocation of the work memory used by the compressor.
*/
lzokay::Dict<> dict;
std::size_t estimated_size = lzokay::compress_worst_size(length);
std::unique_ptr<uint8_t[]> compressed(new uint8_t[estimated_size]);
std::size_t compressed_size;
error = lzokay::compress(data, length, compressed.get(), estimated_size,
compressed_size, dict);
if (error < lzokay::EResult::Success)
return 1;
std::unique_ptr<uint8_t[]> decompressed(new uint8_t[length]);
std::size_t decompressed_size;
error = lzokay::decompress(compressed.get(), compressed_size,
decompressed.get(), length, decompressed_size);
if (error < lzokay::EResult::Success)
return 1;
if (std::memcmp(data, decompressed.get(), decompressed_size) != 0)
return 1;
return 0;
}
```
License
-------
LZ👌 is available under the
[MIT License](https://github.com/jackoalan/lzokay/blob/master/LICENSE)
and has no external dependencies.
+5
View File
@@ -0,0 +1,5 @@
project(lzokay-c VERSION 0.1 LANGUAGES C CXX)
add_library(lzokay-c lzokay-c.cpp lzokay-c.h)
target_link_libraries(lzokay-c PRIVATE lzokay)
set_target_properties(lzokay-c PROPERTIES CXX_STANDARD 14)
+20
View File
@@ -0,0 +1,20 @@
#include "lzokay-c.h"
#include "../lzokay.hpp"
static_assert(EResult_LookbehindOverrun == lzokay_EResult(lzokay::EResult::LookbehindOverrun), "LookbehindOverrun mismatch");
static_assert(EResult_OutputOverrun == lzokay_EResult(lzokay::EResult::OutputOverrun), "OutputOverrun mismatch");
static_assert(EResult_InputOverrun == lzokay_EResult(lzokay::EResult::InputOverrun), "InputOverrun mismatch");
static_assert(EResult_Error == lzokay_EResult(lzokay::EResult::Error), "Error mismatch");
static_assert(EResult_Success == lzokay_EResult(lzokay::EResult::Success), "Success mismatch");
static_assert(EResult_InputNotConsumed == lzokay_EResult(lzokay::EResult::InputNotConsumed), "InputNotConsumed mismatch");
extern "C"
lzokay_EResult lzokay_decompress(const uint8_t * src, size_t src_size,
uint8_t *output, size_t *output_len)
{
size_t needed_size = 0;
lzokay::EResult error =
lzokay::decompress(src, src_size, output, *output_len, needed_size);
*output_len = needed_size;
return lzokay_EResult(error);
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef LZOKAY_C_INCLUDED
#define LZOKAY_C_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
typedef enum {
EResult_LookbehindOverrun = -4,
EResult_OutputOverrun = -3,
EResult_InputOverrun = -2,
EResult_Error = -1,
EResult_Success = 0,
EResult_InputNotConsumed = 1,
} lzokay_EResult;
lzokay_EResult lzokay_decompress(const uint8_t * src, size_t src_size,
uint8_t *output, size_t *output_len);
#ifdef __cplusplus
}
#endif
#endif // LZOKAY_C_INCLUDED
+646
View File
@@ -0,0 +1,646 @@
#include "lzokay.hpp"
#include <cstring>
#include <algorithm>
/*
* Based on documentation from the Linux sources: Documentation/lzo.txt
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/lzo.txt
*/
namespace lzokay {
#if _WIN32
#define HOST_BIG_ENDIAN 0
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define HOST_BIG_ENDIAN 1
#else
#define HOST_BIG_ENDIAN 0
#endif
#if HOST_BIG_ENDIAN
static uint16_t get_le16(const uint8_t* p) {
uint16_t val = *reinterpret_cast<const uint16_t*>(p);
#if __GNUC__
return __builtin_bswap16(val);
#elif _WIN32
return _byteswap_ushort(val);
#else
return (val = (val << 8) | ((val >> 8) & 0xFF));
#endif
}
#else
static uint16_t get_le16(const uint8_t* p) {
return *reinterpret_cast<const uint16_t*>(p);
}
#endif
constexpr std::size_t Max255Count = std::size_t(~0) / 255 - 2;
#define NEEDS_IN(count) \
if (inp + (count) > inp_end) { \
dst_size = outp - dst; \
return EResult::InputOverrun; \
}
#define NEEDS_OUT(count) \
if (outp + (count) > outp_end) { \
dst_size = outp - dst; \
return EResult::OutputOverrun; \
}
#define CONSUME_ZERO_BYTE_LENGTH \
std::size_t offset; \
{ \
const uint8_t *old_inp = inp; \
while (*inp == 0) ++inp; \
offset = inp - old_inp; \
if (offset > Max255Count) { \
dst_size = outp - dst; \
return EResult::Error; \
} \
}
#define WRITE_ZERO_BYTE_LENGTH(length) \
{ \
std::size_t l; \
for (l = length; l > 255; l -= 255) { *outp++ = 0; } \
*outp++ = l; \
}
constexpr uint32_t M1MaxOffset = 0x0400;
constexpr uint32_t M2MaxOffset = 0x0800;
constexpr uint32_t M3MaxOffset = 0x4000;
constexpr uint32_t M4MaxOffset = 0xbfff;
constexpr uint32_t M1MinLen = 2;
constexpr uint32_t M1MaxLen = 2;
constexpr uint32_t M2MinLen = 3;
constexpr uint32_t M2MaxLen = 8;
constexpr uint32_t M3MinLen = 3;
constexpr uint32_t M3MaxLen = 33;
constexpr uint32_t M4MinLen = 3;
constexpr uint32_t M4MaxLen = 9;
constexpr uint32_t M1Marker = 0x0;
constexpr uint32_t M2Marker = 0x40;
constexpr uint32_t M3Marker = 0x20;
constexpr uint32_t M4Marker = 0x10;
constexpr uint32_t MaxMatchByLengthLen = 34; /* Max M3 len + 1 */
EResult decompress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t init_dst_size,
std::size_t& dst_size) {
dst_size = init_dst_size;
if (src_size < 3) {
dst_size = 0;
return EResult::InputOverrun;
}
const uint8_t* inp = src;
const uint8_t* inp_end = src + src_size;
uint8_t* outp = dst;
uint8_t* outp_end = dst + dst_size;
uint8_t* lbcur;
std::size_t lblen;
std::size_t state = 0;
std::size_t nstate = 0;
/* First byte encoding */
if (*inp >= 22) {
/* 22..255 : copy literal string
* length = (byte - 17) = 4..238
* state = 4 [ don't copy extra literals ]
* skip byte
*/
std::size_t len = *inp++ - uint8_t(17);
NEEDS_IN(len)
NEEDS_OUT(len)
for (std::size_t i = 0; i < len; ++i)
*outp++ = *inp++;
state = 4;
} else if (*inp >= 18) {
/* 18..21 : copy 0..3 literals
* state = (byte - 17) = 0..3 [ copy <state> literals ]
* skip byte
*/
nstate = *inp++ - uint8_t(17);
state = nstate;
NEEDS_IN(nstate)
NEEDS_OUT(nstate)
for (std::size_t i = 0; i < nstate; ++i)
*outp++ = *inp++;
}
/* 0..17 : follow regular instruction encoding, see below. It is worth
* noting that codes 16 and 17 will represent a block copy from
* the dictionary which is empty, and that they will always be
* invalid at this place.
*/
while (true) {
NEEDS_IN(1)
uint8_t inst = *inp++;
if (inst & 0xC0) {
/* [M2]
* 1 L L D D D S S (128..255)
* Copy 5-8 bytes from block within 2kB distance
* state = S (copy S literals after this block)
* length = 5 + L
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 3) + D + 1
*
* 0 1 L D D D S S (64..127)
* Copy 3-4 bytes from block within 2kB distance
* state = S (copy S literals after this block)
* length = 3 + L
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 3) + D + 1
*/
NEEDS_IN(1)
lbcur = outp - ((*inp++ << 3) + ((inst >> 2) & 0x7) + 1);
lblen = std::size_t(inst >> 5) + 1;
nstate = inst & uint8_t(0x3);
} else if (inst & M3Marker) {
/* [M3]
* 0 0 1 L L L L L (32..63)
* Copy of small block within 16kB distance (preferably less than 34B)
* length = 2 + (L ?: 31 + (zero_bytes * 255) + non_zero_byte)
* Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S
* distance = D + 1
* state = S (copy S literals after this block)
*/
lblen = std::size_t(inst & uint8_t(0x1f)) + 2;
if (lblen == 2) {
CONSUME_ZERO_BYTE_LENGTH
NEEDS_IN(1)
lblen += offset * 255 + 31 + *inp++;
}
NEEDS_IN(2)
nstate = get_le16(inp);
inp += 2;
lbcur = outp - ((nstate >> 2) + 1);
nstate &= 0x3;
} else if (inst & M4Marker) {
/* [M4]
* 0 0 0 1 H L L L (16..31)
* Copy of a block within 16..48kB distance (preferably less than 10B)
* length = 2 + (L ?: 7 + (zero_bytes * 255) + non_zero_byte)
* Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S
* distance = 16384 + (H << 14) + D
* state = S (copy S literals after this block)
* End of stream is reached if distance == 16384
*/
lblen = std::size_t(inst & uint8_t(0x7)) + 2;
if (lblen == 2) {
CONSUME_ZERO_BYTE_LENGTH
NEEDS_IN(1)
lblen += offset * 255 + 7 + *inp++;
}
NEEDS_IN(2)
nstate = get_le16(inp);
inp += 2;
lbcur = outp - (((inst & 0x8) << 11) + (nstate >> 2));
nstate &= 0x3;
if (lbcur == outp)
break; /* Stream finished */
lbcur -= 16384;
} else {
/* [M1] Depends on the number of literals copied by the last instruction. */
if (state == 0) {
/* If last instruction did not copy any literal (state == 0), this
* encoding will be a copy of 4 or more literal, and must be interpreted
* like this :
*
* 0 0 0 0 L L L L (0..15) : copy long literal string
* length = 3 + (L ?: 15 + (zero_bytes * 255) + non_zero_byte)
* state = 4 (no extra literals are copied)
*/
std::size_t len = inst + 3;
if (len == 3) {
CONSUME_ZERO_BYTE_LENGTH
NEEDS_IN(1)
len += offset * 255 + 15 + *inp++;
}
/* copy_literal_run */
NEEDS_IN(len)
NEEDS_OUT(len)
for (std::size_t i = 0; i < len; ++i)
*outp++ = *inp++;
state = 4;
continue;
} else if (state != 4) {
/* If last instruction used to copy between 1 to 3 literals (encoded in
* the instruction's opcode or distance), the instruction is a copy of a
* 2-byte block from the dictionary within a 1kB distance. It is worth
* noting that this instruction provides little savings since it uses 2
* bytes to encode a copy of 2 other bytes but it encodes the number of
* following literals for free. It must be interpreted like this :
*
* 0 0 0 0 D D S S (0..15) : copy 2 bytes from <= 1kB distance
* length = 2
* state = S (copy S literals after this block)
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 2) + D + 1
*/
NEEDS_IN(1)
nstate = inst & uint8_t(0x3);
lbcur = outp - ((inst >> 2) + (*inp++ << 2) + 1);
lblen = 2;
} else {
/* If last instruction used to copy 4 or more literals (as detected by
* state == 4), the instruction becomes a copy of a 3-byte block from the
* dictionary from a 2..3kB distance, and must be interpreted like this :
*
* 0 0 0 0 D D S S (0..15) : copy 3 bytes from 2..3 kB distance
* length = 3
* state = S (copy S literals after this block)
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 2) + D + 2049
*/
NEEDS_IN(1)
nstate = inst & uint8_t(0x3);
lbcur = outp - ((inst >> 2) + (*inp++ << 2) + 2049);
lblen = 3;
}
}
if (lbcur < dst) {
dst_size = outp - dst;
return EResult::LookbehindOverrun;
}
NEEDS_IN(nstate)
NEEDS_OUT(lblen + nstate)
/* Copy lookbehind */
for (std::size_t i = 0; i < lblen; ++i)
*outp++ = *lbcur++;
state = nstate;
/* Copy literal */
for (std::size_t i = 0; i < nstate; ++i)
*outp++ = *inp++;
}
dst_size = outp - dst;
if (lblen != 3) /* Ensure terminating M4 was encountered */
return EResult::Error;
if (inp == inp_end)
return EResult::Success;
else if (inp < inp_end)
return EResult::InputNotConsumed;
else
return EResult::InputOverrun;
}
struct State {
const uint8_t* src;
const uint8_t* src_end;
const uint8_t* inp;
uint32_t wind_sz;
uint32_t wind_b;
uint32_t wind_e;
uint32_t cycle1_countdown;
const uint8_t* bufp;
uint32_t buf_sz;
/* Access next input byte and advance both ends of circular buffer */
void get_byte(uint8_t* buf) {
if (inp >= src_end) {
if (wind_sz > 0)
--wind_sz;
buf[wind_e] = 0;
if (wind_e < DictBase::MaxMatchLen)
buf[DictBase::BufSize + wind_e] = 0;
} else {
buf[wind_e] = *inp;
if (wind_e < DictBase::MaxMatchLen)
buf[DictBase::BufSize + wind_e] = *inp;
++inp;
}
if (++wind_e == DictBase::BufSize)
wind_e = 0;
if (++wind_b == DictBase::BufSize)
wind_b = 0;
}
uint32_t pos2off(uint32_t pos) const {
return wind_b > pos ? wind_b - pos : DictBase::BufSize - (pos - wind_b);
}
};
class DictImpl : public DictBase {
public:
struct Match3Impl : DictBase::Match3 {
static uint32_t make_key(const uint8_t* data) {
return ((0x9f5f * (((uint32_t(data[0]) << 5 ^ uint32_t(data[1])) << 5) ^ data[2])) >> 5) & 0x3fff;
}
uint16_t get_head(uint32_t key) const {
return (chain_sz[key] == 0) ? uint16_t(UINT16_MAX) : head[key];
}
void init() {
std::fill(std::begin(chain_sz), std::end(chain_sz), 0);
}
void remove(uint32_t pos, const uint8_t* b) {
--chain_sz[make_key(b + pos)];
}
void advance(State& s, uint32_t& match_pos, uint32_t& match_count, const uint8_t* b) {
uint32_t key = make_key(b + s.wind_b);
match_pos = chain[s.wind_b] = get_head(key);
match_count = chain_sz[key]++;
if (match_count > DictBase::MaxMatchLen)
match_count = DictBase::MaxMatchLen;
head[key] = uint16_t(s.wind_b);
}
void skip_advance(State& s, const uint8_t* b) {
uint32_t key = make_key(b + s.wind_b);
chain[s.wind_b] = get_head(key);
head[key] = uint16_t(s.wind_b);
best_len[s.wind_b] = uint16_t(DictBase::MaxMatchLen + 1);
chain_sz[key]++;
}
};
struct Match2Impl : DictBase::Match2 {
static uint32_t make_key(const uint8_t* data) {
return uint32_t(data[0]) ^ (uint32_t(data[1]) << 8);
}
void init() {
std::fill(std::begin(head), std::end(head), UINT16_MAX);
}
void add(uint16_t pos, const uint8_t* b) {
head[make_key(b + pos)] = pos;
}
void remove(uint32_t pos, const uint8_t* b) {
uint16_t& p = head[make_key(b + pos)];
if (p == pos)
p = UINT16_MAX;
}
bool search(State& s, uint32_t& lb_pos, uint32_t& lb_len,
uint32_t best_pos[MaxMatchByLengthLen], const uint8_t* b) const {
uint16_t pos = head[make_key(b + s.wind_b)];
if (pos == UINT16_MAX)
return false;
if (best_pos[2] == 0)
best_pos[2] = pos + 1;
if (lb_len < 2) {
lb_len = 2;
lb_pos = pos;
}
return true;
}
};
void init(State& s, const uint8_t* src, std::size_t src_size) {
auto& match3 = static_cast<Match3Impl&>(_storage->match3);
auto& match2 = static_cast<Match2Impl&>(_storage->match2);
s.cycle1_countdown = DictBase::MaxDist;
match3.init();
match2.init();
s.src = src;
s.src_end = src + src_size;
s.inp = src;
s.wind_sz = uint32_t(std::min(src_size, std::size_t(MaxMatchLen)));
s.wind_b = 0;
s.wind_e = s.wind_sz;
std::copy_n(s.inp, s.wind_sz, _storage->buffer);
s.inp += s.wind_sz;
if (s.wind_e == DictBase::BufSize)
s.wind_e = 0;
if (s.wind_sz < 3)
std::fill_n(_storage->buffer + s.wind_b + s.wind_sz, 3, 0);
}
void reset_next_input_entry(State& s, Match3Impl& match3, Match2Impl& match2) {
/* Remove match from about-to-be-clobbered buffer entry */
if (s.cycle1_countdown == 0) {
match3.remove(s.wind_e, _storage->buffer);
match2.remove(s.wind_e, _storage->buffer);
} else {
--s.cycle1_countdown;
}
}
void advance(State& s, uint32_t& lb_off, uint32_t& lb_len,
uint32_t best_off[MaxMatchByLengthLen], bool skip) {
auto& match3 = static_cast<Match3Impl&>(_storage->match3);
auto& match2 = static_cast<Match2Impl&>(_storage->match2);
if (skip) {
for (uint32_t i = 0; i < lb_len - 1; ++i) {
reset_next_input_entry(s, match3, match2);
match3.skip_advance(s, _storage->buffer);
match2.add(uint16_t(s.wind_b), _storage->buffer);
s.get_byte(_storage->buffer);
}
}
lb_len = 1;
lb_off = 0;
uint32_t lb_pos;
uint32_t best_pos[MaxMatchByLengthLen] = {};
uint32_t match_pos, match_count;
match3.advance(s, match_pos, match_count, _storage->buffer);
int best_char = _storage->buffer[s.wind_b];
uint32_t best_len = lb_len;
if (lb_len >= s.wind_sz) {
if (s.wind_sz == 0)
best_char = -1;
lb_off = 0;
match3.best_len[s.wind_b] = DictBase::MaxMatchLen + 1;
} else {
if (match2.search(s, lb_pos, lb_len, best_pos, _storage->buffer) && s.wind_sz >= 3) {
for (uint32_t i = 0; i < match_count; ++i, match_pos = match3.chain[match_pos]) {
auto ref_ptr = _storage->buffer + s.wind_b;
auto match_ptr = _storage->buffer + match_pos;
auto mismatch = std::mismatch(ref_ptr, ref_ptr + s.wind_sz, match_ptr);
auto match_len = uint32_t(mismatch.first - ref_ptr);
if (match_len < 2)
continue;
if (match_len < MaxMatchByLengthLen && best_pos[match_len] == 0)
best_pos[match_len] = match_pos + 1;
if (match_len > lb_len) {
lb_len = match_len;
lb_pos = match_pos;
if (match_len == s.wind_sz || match_len > match3.best_len[match_pos])
break;
}
}
}
if (lb_len > best_len)
lb_off = s.pos2off(lb_pos);
match3.best_len[s.wind_b] = uint16_t(lb_len);
for (auto posit = std::begin(best_pos) + 2, offit = best_off + 2;
posit != std::end(best_pos); ++posit, ++offit) {
*offit = (*posit > 0) ? s.pos2off(*posit - 1) : 0;
}
}
reset_next_input_entry(s, match3, match2);
match2.add(uint16_t(s.wind_b), _storage->buffer);
s.get_byte(_storage->buffer);
if (best_char < 0) {
s.buf_sz = 0;
lb_len = 0;
/* Signal exit */
} else {
s.buf_sz = s.wind_sz + 1;
}
s.bufp = s.inp - s.buf_sz;
}
};
static void find_better_match(const uint32_t best_off[MaxMatchByLengthLen], uint32_t& lb_len, uint32_t& lb_off) {
if (lb_len <= M2MinLen || lb_off <= M2MaxOffset)
return;
if (lb_off > M2MaxOffset && lb_len >= M2MinLen + 1 && lb_len <= M2MaxLen + 1 &&
best_off[lb_len - 1] != 0 && best_off[lb_len - 1] <= M2MaxOffset) {
lb_len -= 1;
lb_off = best_off[lb_len];
} else if (lb_off > M3MaxOffset && lb_len >= M4MaxLen + 1 && lb_len <= M2MaxLen + 2 &&
best_off[lb_len - 2] && best_off[lb_len] <= M2MaxOffset) {
lb_len -= 2;
lb_off = best_off[lb_len];
} else if (lb_off > M3MaxOffset && lb_len >= M4MaxLen + 1 && lb_len <= M3MaxLen + 1 &&
best_off[lb_len - 1] != 0 && best_off[lb_len - 2] <= M3MaxOffset) {
lb_len -= 1;
lb_off = best_off[lb_len];
}
}
static EResult encode_literal_run(uint8_t*& outp, const uint8_t* outp_end, const uint8_t* dst, std::size_t& dst_size,
const uint8_t* lit_ptr, uint32_t lit_len) {
if (outp == dst && lit_len <= 238) {
NEEDS_OUT(1);
*outp++ = uint8_t(17 + lit_len);
} else if (lit_len <= 3) {
outp[-2] = uint8_t(outp[-2] | lit_len);
} else if (lit_len <= 18) {
NEEDS_OUT(1);
*outp++ = uint8_t(lit_len - 3);
} else {
NEEDS_OUT((lit_len - 18) / 255 + 2);
*outp++ = 0;
WRITE_ZERO_BYTE_LENGTH(lit_len - 18);
}
NEEDS_OUT(lit_len);
outp = std::copy_n(lit_ptr, lit_len, outp);
return EResult::Success;
}
static EResult encode_lookback_match(uint8_t*& outp, const uint8_t* outp_end, const uint8_t* dst, std::size_t& dst_size,
uint32_t lb_len, uint32_t lb_off, uint32_t last_lit_len) {
if (lb_len == 2) {
lb_off -= 1;
NEEDS_OUT(2);
*outp++ = uint8_t(M1Marker | ((lb_off & 0x3) << 2));
*outp++ = uint8_t(lb_off >> 2);
} else if (lb_len <= M2MaxLen && lb_off <= M2MaxOffset) {
lb_off -= 1;
NEEDS_OUT(2);
*outp++ = uint8_t((lb_len - 1) << 5 | ((lb_off & 0x7) << 2));
*outp++ = uint8_t(lb_off >> 3);
} else if (lb_len == M2MinLen && lb_off <= M1MaxOffset + M2MaxOffset && last_lit_len >= 4) {
lb_off -= 1 + M2MaxOffset;
NEEDS_OUT(2);
*outp++ = uint8_t(M1Marker | ((lb_off & 0x3) << 2));
*outp++ = uint8_t(lb_off >> 2);
} else if (lb_off <= M3MaxOffset) {
lb_off -= 1;
if (lb_len <= M3MaxLen) {
NEEDS_OUT(1);
*outp++ = uint8_t(M3Marker | (lb_len - 2));
} else {
lb_len -= M3MaxLen;
NEEDS_OUT(lb_len / 255 + 2);
*outp++ = uint8_t(M3Marker);
WRITE_ZERO_BYTE_LENGTH(lb_len);
}
NEEDS_OUT(2);
*outp++ = uint8_t(lb_off << 2);
*outp++ = uint8_t(lb_off >> 6);
} else {
lb_off -= 0x4000;
if (lb_len <= M4MaxLen) {
NEEDS_OUT(1);
*outp++ = uint8_t(M4Marker | ((lb_off & 0x4000) >> 11) | (lb_len - 2));
} else {
lb_len -= M4MaxLen;
NEEDS_OUT(lb_len / 255 + 2);
*outp++ = uint8_t(M4Marker | ((lb_off & 0x4000) >> 11));
WRITE_ZERO_BYTE_LENGTH(lb_len);
}
NEEDS_OUT(2);
*outp++ = uint8_t(lb_off << 2);
*outp++ = uint8_t(lb_off >> 6);
}
return EResult::Success;
}
EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t init_dst_size,
std::size_t& dst_size, DictBase& dict) {
EResult err;
State s;
auto& d = static_cast<DictImpl&>(dict);
dst_size = init_dst_size;
uint8_t* outp = dst;
uint8_t* outp_end = dst + dst_size;
uint32_t lit_len = 0;
uint32_t lb_off, lb_len;
uint32_t best_off[MaxMatchByLengthLen];
d.init(s, src, src_size);
const uint8_t* lit_ptr = s.inp;
d.advance(s, lb_off, lb_len, best_off, false);
while (s.buf_sz > 0) {
if (lit_len == 0)
lit_ptr = s.bufp;
if (lb_len < 2 || (lb_len == 2 && (lb_off > M1MaxOffset || lit_len == 0 || lit_len >= 4)) ||
(lb_len == 2 && outp == dst) || (outp == dst && lit_len == 0)) {
lb_len = 0;
} else if (lb_len == M2MinLen && lb_off > M1MaxOffset + M2MaxOffset && lit_len >= 4) {
lb_len = 0;
}
if (lb_len == 0) {
++lit_len;
d.advance(s, lb_off, lb_len, best_off, false);
continue;
}
find_better_match(best_off, lb_len, lb_off);
if ((err = encode_literal_run(outp, outp_end, dst, dst_size, lit_ptr, lit_len)) < EResult::Success)
return err;
if ((err = encode_lookback_match(outp, outp_end, dst, dst_size, lb_len, lb_off, lit_len)) < EResult::Success)
return err;
lit_len = 0;
d.advance(s, lb_off, lb_len, best_off, true);
}
if ((err = encode_literal_run(outp, outp_end, dst, dst_size, lit_ptr, lit_len)) < EResult::Success)
return err;
/* Terminating M4 */
NEEDS_OUT(3);
*outp++ = M4Marker | 1;
*outp++ = 0;
*outp++ = 0;
dst_size = outp - dst;
return EResult::Success;
}
}
+79
View File
@@ -0,0 +1,79 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <memory>
namespace lzokay {
enum class EResult {
LookbehindOverrun = -4,
OutputOverrun = -3,
InputOverrun = -2,
Error = -1,
Success = 0,
InputNotConsumed = 1,
};
class DictBase {
protected:
static constexpr uint32_t HashSize = 0x4000;
static constexpr uint32_t MaxDist = 0xbfff;
static constexpr uint32_t MaxMatchLen = 0x800;
static constexpr uint32_t BufSize = MaxDist + MaxMatchLen;
/* List encoding of previous 3-byte data matches */
struct Match3 {
uint16_t head[HashSize]; /* key -> chain-head-pos */
uint16_t chain_sz[HashSize]; /* key -> chain-size */
uint16_t chain[BufSize]; /* chain-pos -> next-chain-pos */
uint16_t best_len[BufSize]; /* chain-pos -> best-match-length */
};
/* Encoding of 2-byte data matches */
struct Match2 {
uint16_t head[1 << 16]; /* 2-byte-data -> head-pos */
};
struct Data {
Match3 match3;
Match2 match2;
/* Circular buffer caching enough data to access the maximum lookback
* distance of 48K + maximum match length of 2K. An additional 2K is
* allocated so the start of the buffer may be replicated at the end,
* therefore providing efficient circular access.
*/
uint8_t buffer[BufSize + MaxMatchLen];
};
using storage_type = Data;
storage_type* _storage;
DictBase() = default;
friend struct State;
friend EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t& dst_size, DictBase& dict);
};
template <template<typename> class _Alloc = std::allocator>
class Dict : public DictBase {
_Alloc<DictBase::storage_type> _allocator;
public:
Dict() { _storage = _allocator.allocate(1); }
~Dict() { _allocator.deallocate(_storage, 1); }
};
EResult decompress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t dst_size,
std::size_t& out_size);
EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t dst_size,
std::size_t& out_size, DictBase& dict);
inline EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t dst_size,
std::size_t& out_size) {
Dict<> dict;
return compress(src, src_size, dst, dst_size, out_size, dict);
}
constexpr std::size_t compress_worst_size(std::size_t s) {
return s + s / 16 + 64 + 3;
}
}
+37
View File
@@ -0,0 +1,37 @@
#include "lzokay.hpp"
#include <cstring>
int compress_and_decompress(const uint8_t* data, std::size_t length) {
lzokay::EResult error;
/* This variable and 5th parameter of compress() is optional, but may
* be reused across multiple compression runs; avoiding repeat
* allocation/deallocation of the work memory used by the compressor.
*/
lzokay::Dict<> dict;
std::size_t compressed_size = lzokay::compress_worst_size(length);
std::unique_ptr<uint8_t[]> compressed(new uint8_t[compressed_size]);
error = lzokay::compress(data, length, compressed.get(), compressed_size,
compressed_size, dict);
if (error < lzokay::EResult::Success)
return 1;
std::unique_ptr<uint8_t[]> decompressed(new uint8_t[length]);
std::size_t decompressed_size;
error = lzokay::decompress(compressed.get(), compressed_size,
decompressed.get(), length, decompressed_size);
if (error < lzokay::EResult::Success)
return 1;
if (std::memcmp(data, decompressed.get(), decompressed_size) != 0)
return 1;
return 0;
}
int main(int argc, char** argv) {
const char* testdata = "Hello World!";
int ret = compress_and_decompress(reinterpret_cast<const uint8_t*>(testdata), 12);
return ret;
}
-3
View File
@@ -1,3 +0,0 @@
add_library(minilzo
SHARED
minilzo.c)
-453
View File
@@ -1,453 +0,0 @@
/* lzoconf.h -- configuration of the LZO data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library 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 the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __LZOCONF_H_INCLUDED
#define __LZOCONF_H_INCLUDED 1
#define LZO_VERSION 0x20a0 /* 2.10 */
#define LZO_VERSION_STRING "2.10"
#define LZO_VERSION_DATE "Mar 01 2017"
/* internal Autoconf configuration file - only used when building LZO */
#if defined(LZO_HAVE_CONFIG_H)
# include <config.h>
#endif
#include <limits.h>
#include <stddef.h>
/***********************************************************************
// LZO requires a conforming <limits.h>
************************************************************************/
#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
# error "invalid CHAR_BIT"
#endif
#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
# error "check your compiler installation"
#endif
#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
# error "your limits.h macros are broken"
#endif
/* get OS and architecture defines */
#ifndef __LZODEFS_H_INCLUDED
#include <lzo/lzodefs.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************
// some core defines
************************************************************************/
/* memory checkers */
#if !defined(__LZO_CHECKER)
# if defined(__BOUNDS_CHECKING_ON)
# define __LZO_CHECKER 1
# elif defined(__CHECKER__)
# define __LZO_CHECKER 1
# elif defined(__INSURE__)
# define __LZO_CHECKER 1
# elif defined(__PURIFY__)
# define __LZO_CHECKER 1
# endif
#endif
/***********************************************************************
// integral and pointer types
************************************************************************/
/* lzo_uint must match size_t */
#if !defined(LZO_UINT_MAX)
# if (LZO_ABI_LLP64)
# if (LZO_OS_WIN64)
typedef unsigned __int64 lzo_uint;
typedef __int64 lzo_int;
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64
# else
typedef lzo_ullong_t lzo_uint;
typedef lzo_llong_t lzo_int;
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG
# endif
# define LZO_SIZEOF_LZO_INT 8
# define LZO_UINT_MAX 0xffffffffffffffffull
# define LZO_INT_MAX 9223372036854775807LL
# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
# elif (LZO_ABI_IP32L64) /* MIPS R5900 */
typedef unsigned int lzo_uint;
typedef int lzo_int;
# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT
# define LZO_UINT_MAX UINT_MAX
# define LZO_INT_MAX INT_MAX
# define LZO_INT_MIN INT_MIN
# elif (ULONG_MAX >= LZO_0xffffffffL)
typedef unsigned long lzo_uint;
typedef long lzo_int;
# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG
# define LZO_UINT_MAX ULONG_MAX
# define LZO_INT_MAX LONG_MAX
# define LZO_INT_MIN LONG_MIN
# else
# error "lzo_uint"
# endif
#endif
/* The larger type of lzo_uint and lzo_uint32_t. */
#if (LZO_SIZEOF_LZO_INT >= 4)
# define lzo_xint lzo_uint
#else
# define lzo_xint lzo_uint32_t
#endif
typedef int lzo_bool;
/* sanity checks */
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t))
#ifndef __LZO_MMODEL
#define __LZO_MMODEL /*empty*/
#endif
/* no typedef here because of const-pointer issues */
#define lzo_bytep unsigned char __LZO_MMODEL *
#define lzo_charp char __LZO_MMODEL *
#define lzo_voidp void __LZO_MMODEL *
#define lzo_shortp short __LZO_MMODEL *
#define lzo_ushortp unsigned short __LZO_MMODEL *
#define lzo_intp lzo_int __LZO_MMODEL *
#define lzo_uintp lzo_uint __LZO_MMODEL *
#define lzo_xintp lzo_xint __LZO_MMODEL *
#define lzo_voidpp lzo_voidp __LZO_MMODEL *
#define lzo_bytepp lzo_bytep __LZO_MMODEL *
#define lzo_int8_tp lzo_int8_t __LZO_MMODEL *
#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL *
#define lzo_int16_tp lzo_int16_t __LZO_MMODEL *
#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL *
#define lzo_int32_tp lzo_int32_t __LZO_MMODEL *
#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL *
#if defined(lzo_int64_t)
#define lzo_int64_tp lzo_int64_t __LZO_MMODEL *
#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL *
#endif
/* Older LZO versions used to support ancient systems and memory models
* such as 16-bit MSDOS with __huge pointers or Cray PVP, but these
* obsolete configurations are not supported any longer.
*/
#if defined(__LZO_MMODEL_HUGE)
#error "__LZO_MMODEL_HUGE memory model is unsupported"
#endif
#if (LZO_MM_PVP)
#error "LZO_MM_PVP memory model is unsupported"
#endif
#if (LZO_SIZEOF_INT < 4)
#error "LZO_SIZEOF_INT < 4 is unsupported"
#endif
#if (__LZO_UINTPTR_T_IS_POINTER)
#error "__LZO_UINTPTR_T_IS_POINTER is unsupported"
#endif
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4)
/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should
* work but have not received much testing lately, so be strict here.
*/
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep))
/***********************************************************************
// function types
************************************************************************/
/* name mangling */
#if !defined(__LZO_EXTERN_C)
# ifdef __cplusplus
# define __LZO_EXTERN_C extern "C"
# else
# define __LZO_EXTERN_C extern
# endif
#endif
/* calling convention */
#if !defined(__LZO_CDECL)
# define __LZO_CDECL __lzo_cdecl
#endif
/* DLL export information */
#if !defined(__LZO_EXPORT1)
# define __LZO_EXPORT1 /*empty*/
#endif
#if !defined(__LZO_EXPORT2)
# define __LZO_EXPORT2 /*empty*/
#endif
/* __cdecl calling convention for public C and assembly functions */
#if !defined(LZO_PUBLIC)
# define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL
#endif
#if !defined(LZO_EXTERN)
# define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r)
#endif
#if !defined(LZO_PRIVATE)
# define LZO_PRIVATE(r) static r __LZO_CDECL
#endif
/* function types */
typedef int
(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
typedef int
(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
typedef int
(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
typedef int
(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem,
const lzo_bytep dict, lzo_uint dict_len );
typedef int
(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem,
const lzo_bytep dict, lzo_uint dict_len );
/* Callback interface. Currently only the progress indicator ("nprogress")
* is used, but this may change in a future release. */
struct lzo_callback_t;
typedef struct lzo_callback_t lzo_callback_t;
#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
/* malloc & free function types */
typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
(lzo_callback_p self, lzo_uint items, lzo_uint size);
typedef void (__LZO_CDECL *lzo_free_func_t)
(lzo_callback_p self, lzo_voidp ptr);
/* a progress indicator callback function */
typedef void (__LZO_CDECL *lzo_progress_func_t)
(lzo_callback_p, lzo_uint, lzo_uint, int);
struct lzo_callback_t
{
/* custom allocators (set to 0 to disable) */
lzo_alloc_func_t nalloc; /* [not used right now] */
lzo_free_func_t nfree; /* [not used right now] */
/* a progress indicator callback function (set to 0 to disable) */
lzo_progress_func_t nprogress;
/* INFO: the first parameter "self" of the nalloc/nfree/nprogress
* callbacks points back to this struct, so you are free to store
* some extra info in the following variables. */
lzo_voidp user1;
lzo_xint user2;
lzo_xint user3;
};
/***********************************************************************
// error codes and prototypes
************************************************************************/
/* Error codes for the compression/decompression functions. Negative
* values are errors, positive values will be used for special but
* normal events.
*/
#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
#define LZO_E_INVALID_ARGUMENT (-10)
#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */
#define LZO_E_OUTPUT_NOT_CONSUMED (-12)
#define LZO_E_INTERNAL_ERROR (-99)
#ifndef lzo_sizeof_dict_t
# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
#endif
/* lzo_init() should be the first function you call.
* Check the return code !
*
* lzo_init() is a macro to allow checking that the library and the
* compiler's view of various types are consistent.
*/
#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
(int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\
(int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
(int)sizeof(lzo_callback_t))
LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
/* version functions (useful for shared libraries) */
LZO_EXTERN(unsigned) lzo_version(void);
LZO_EXTERN(const char *) lzo_version_string(void);
LZO_EXTERN(const char *) lzo_version_date(void);
LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
/* string functions */
LZO_EXTERN(int)
lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
LZO_EXTERN(lzo_voidp)
lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
LZO_EXTERN(lzo_voidp)
lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
LZO_EXTERN(lzo_voidp)
lzo_memset(lzo_voidp buf, int c, lzo_uint len);
/* checksum functions */
LZO_EXTERN(lzo_uint32_t)
lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len);
LZO_EXTERN(lzo_uint32_t)
lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len);
LZO_EXTERN(const lzo_uint32_tp)
lzo_get_crc32_table(void);
/* misc. */
LZO_EXTERN(int) _lzo_config_check(void);
typedef union {
lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04;
void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09;
#if defined(lzo_int64_t)
lzo_uint64_t a10;
#endif
} lzo_align_t;
/* align a char pointer on a boundary that is a multiple of 'size' */
LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
#define LZO_PTR_ALIGN_UP(p,size) \
((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
/***********************************************************************
// deprecated macros - only for backward compatibility
************************************************************************/
/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
#define lzo_byte unsigned char
/* deprecated type names */
#define lzo_int32 lzo_int32_t
#define lzo_uint32 lzo_uint32_t
#define lzo_int32p lzo_int32_t __LZO_MMODEL *
#define lzo_uint32p lzo_uint32_t __LZO_MMODEL *
#define LZO_INT32_MAX LZO_INT32_C(2147483647)
#define LZO_UINT32_MAX LZO_UINT32_C(4294967295)
#if defined(lzo_int64_t)
#define lzo_int64 lzo_int64_t
#define lzo_uint64 lzo_uint64_t
#define lzo_int64p lzo_int64_t __LZO_MMODEL *
#define lzo_uint64p lzo_uint64_t __LZO_MMODEL *
#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807)
#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615)
#endif
/* deprecated types */
typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u;
typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u;
/* deprecated defines */
#if !defined(LZO_SIZEOF_LZO_UINT)
# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT
#endif
#if defined(LZO_CFG_COMPAT)
#define __LZOCONF_H 1
#if defined(LZO_ARCH_I086)
# define __LZO_i386 1
#elif defined(LZO_ARCH_I386)
# define __LZO_i386 1
#endif
#if defined(LZO_OS_DOS16)
# define __LZO_DOS 1
# define __LZO_DOS16 1
#elif defined(LZO_OS_DOS32)
# define __LZO_DOS 1
#elif defined(LZO_OS_WIN16)
# define __LZO_WIN 1
# define __LZO_WIN16 1
#elif defined(LZO_OS_WIN32)
# define __LZO_WIN 1
#endif
#define __LZO_CMODEL /*empty*/
#define __LZO_DMODEL /*empty*/
#define __LZO_ENTRY __LZO_CDECL
#define LZO_EXTERN_CDECL LZO_EXTERN
#define LZO_ALIGN LZO_PTR_ALIGN_UP
#define lzo_compress_asm_t lzo_compress_t
#define lzo_decompress_asm_t lzo_decompress_t
#endif /* LZO_CFG_COMPAT */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
-3268
View File
File diff suppressed because it is too large Load Diff
-6365
View File
File diff suppressed because it is too large Load Diff
-106
View File
@@ -1,106 +0,0 @@
/* minilzo.h -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library 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 the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
/*
* NOTE:
* the full LZO package can be found at
* http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __MINILZO_H_INCLUDED
#define __MINILZO_H_INCLUDED 1
#define MINILZO_VERSION 0x20a0 /* 2.10 */
#if defined(__LZOCONF_H_INCLUDED)
# error "you cannot use both LZO and miniLZO"
#endif
/* internal Autoconf configuration file - only used when building miniLZO */
#ifdef MINILZO_HAVE_CONFIG_H
# include <config.h>
#endif
#include <limits.h>
#include <stddef.h>
#ifndef __LZODEFS_H_INCLUDED
#include "lzodefs.h"
#endif
#undef LZO_HAVE_CONFIG_H
#include "lzoconf.h"
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
# error "version mismatch in header files"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************
//
************************************************************************/
/* Memory required for the wrkmem parameter.
* When the required size is 0, you can also pass a NULL pointer.
*/
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t))
#define LZO1X_MEM_DECOMPRESS (0)
/* compression */
LZO_EXTERN(int)
lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
/* decompression */
LZO_EXTERN(int)
lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
/* safe decompression with overrun testing */
LZO_EXTERN(int)
lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */