mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 22:22:21 -04:00
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:
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)"]
|
||||
]
|
||||
}
|
||||
@@ -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"]]
|
||||
]
|
||||
|
||||
}
|
||||
@@ -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":[]
|
||||
}
|
||||
|
||||
Vendored
+58
@@ -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")
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/lzokayTargets.cmake")
|
||||
check_required_components(lzokay)
|
||||
Vendored
+22
@@ -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.
|
||||
|
||||
Vendored
+62
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Vendored
+646
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+79
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+37
@@ -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;
|
||||
}
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
add_library(minilzo
|
||||
SHARED
|
||||
minilzo.c)
|
||||
Vendored
-453
@@ -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: */
|
||||
Vendored
-3268
File diff suppressed because it is too large
Load Diff
Vendored
-6365
File diff suppressed because it is too large
Load Diff
Vendored
-106
@@ -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: */
|
||||
Reference in New Issue
Block a user