Skip to content

Commit

Permalink
Initial Commit of minlzlib
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Ionescu committed Apr 16, 2020
1 parent 8b1bdaf commit 2ee81c1
Show file tree
Hide file tree
Showing 15 changed files with 2,451 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
.vs
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required (VERSION 3.8)
project (minlzma)

add_subdirectory(minlzlib)
add_subdirectory(minlzdec)
58 changes: 58 additions & 0 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"configurations": [
{
"name": "win-amd64",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": []
},
{
"name": "wsl-amd64",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeExecutable": "/usr/bin/cmake",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "linux_clang_x64" ],
"wslPath": "${defaultWSLPath}",
"addressSanitizerRuntimeFlags": "detect_leaks=0",
"variables": []
},
{
"name": "win-release-amd64",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ],
"variables": []
},
{
"name": "wsl-release-amd64",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeExecutable": "/usr/bin/cmake",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "linux_clang_x64" ],
"wslPath": "${defaultWSLPath}",
"addressSanitizerRuntimeFlags": "detect_leaks=0",
"variables": []
}
]
}
13 changes: 13 additions & 0 deletions minlzlib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required (VERSION 3.8)

if(!MSVC)
add_compile_options(-Wno-undefined-inline)
endif()

add_library (minlzlib STATIC "inputbuf.c" "dictbuf.c" "lzma2dec.c" "lzmadec.c" "rangedec.c" "xzstream.c" "lzmadec.h" "xzstream.h" "minlzlib.h")
set_target_properties(minlzlib PROPERTIES C_STANDARD 11 C_STANDARD_REQUIRED YES C_EXTENSIONS NO)
target_include_directories (minlzlib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

if(MSVC)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/Ox /Ob2 /Oi /Ot /Oy /GF /GL /Gy /MD /Zi /DNDEBUG")
endif()
31 changes: 31 additions & 0 deletions minlzlib/CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": []
},
{
"name": "WSL-Clang-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeExecutable": "/usr/bin/cmake",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "linux_clang_x64" ],
"wslPath": "${defaultWSLPath}",
"addressSanitizerRuntimeFlags": "detect_leaks=0",
"variables": []
}
]
}
151 changes: 151 additions & 0 deletions minlzlib/dictbuf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*++
Copyright (c) Alex Ionescu. All rights reserved.
Module Name:
dictbuf.c
Abstract:
This module implements the management of the LZMA "history buffer" which is
often called the "dictionary". Routines for writing into the history buffer
as well as for reading back from it are implemented, as well as mechanisms
for repeating previous symbols forward into the dictionary. This forms the
basis for LZMA match distance-length pairs that are found and decompressed.
Note that for simplicity's sake, the dictionary is stored directly in the
output buffer, such that no "flushing" or copying is needed back and forth.
Author:
Alex Ionescu (@aionescu) 15-Apr-2020 - Initial version
Environment:
Windows & Linux, user mode and kernel mode.
--*/

#include "minlzlib.h"

//
// State used for the history buffer (dictionary)
//
typedef struct _DICTIONARY_STATE
{
//
// Buffer, start position, current position, and offset limit in the buffer
//
uint8_t* Buffer;
uint32_t Start;
uint32_t Offset;
uint32_t Limit;
uint32_t Size;
} DICTIONARY_STATE, *PDICTIONARY_STATE;
DICTIONARY_STATE g_Dictionary;
PDICTIONARY_STATE Dictionary = &g_Dictionary;

void
DtInitialize (
uint8_t* HistoryBuffer,
uint32_t Size
)
{
//
// Initialize the buffer and reset the position
//
Dictionary->Buffer = HistoryBuffer;
Dictionary->Offset = 0;
Dictionary->Size = Size;
}

bool
DtSetLimit (
uint32_t Limit
)
{
//
// Make sure that the passed in dictionary limit fits within the size, and
// then set this as the new limit. Save the starting point (current offset)
//
if ((Dictionary->Offset + Limit) > Dictionary->Size)
{
return false;
}
Dictionary->Limit = Dictionary->Offset + Limit;
Dictionary->Start = Dictionary->Offset;
return true;
}

bool
DtIsComplete (
uint32_t* BytesProcessed
)
{
//
// Return bytes processed and if the dictionary has been fully written to
//
*BytesProcessed = Dictionary->Offset - Dictionary->Start;
return (Dictionary->Offset == Dictionary->Limit);
}

bool
DtCanWrite (
uint32_t* Position
)
{
//
// Return our position and make sure it's not beyond the uncompressed size
//
*Position = Dictionary->Offset;
return (Dictionary->Offset < Dictionary->Limit);
}

uint8_t
DtGetSymbol (
uint32_t Distance
)
{
//
// If the dictionary is still empty, just return 0, otherwise, return the
// symbol that is Distance bytes backward
//
if (Distance > Dictionary->Offset)
{
return 0;
}
return Dictionary->Buffer[Dictionary->Offset - Distance];
}

void
DtPutSymbol (
uint8_t Symbol
)
{
//
// Write the symbol and advance our position
//
Dictionary->Buffer[Dictionary->Offset++] = Symbol;
}

bool
DtRepeatSymbol (
uint32_t Length,
uint32_t Distance
)
{
//
// Make sure we never get asked to write past the end of the dictionary,
// then rewrite the stream of symbols forward into the dictionary
//
if ((Length + Dictionary->Offset) > Dictionary->Limit)
{
return false;
}

do
{
DtPutSymbol(DtGetSymbol(Distance));
} while (--Length > 0);
return true;
}
114 changes: 114 additions & 0 deletions minlzlib/inputbuf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*++
Copyright (c) Alex Ionescu. All rights reserved.
Module Name:
inputbuf.c
Abstract:
This module implements helper functions for managing the input buffer that
contains arithmetic-coded LZ77 match distance-length pairs and raw literals
Both seeking (such that an external reader can refer to multiple bytes) and
reading (capturing) an individual byte are supported. Support for aligning
input data to 4 bytes (which is a requirement for XZ-encoded files) is also
implemented.
Author:
Alex Ionescu (@aionescu) 15-Apr-2020 - Initial version
Environment:
Windows & Linux, user mode and kernel mode.
--*/

#include "minlzlib.h"

//
// Input Buffer State
//
typedef struct _BUFFER_STATE
{
//
// Start of the buffer, current offset, and total input size
//
uint8_t* Buffer;
uint32_t Offset;
uint32_t Size;
} BUFFER_STATE, * PBUFFER_STATE;
BUFFER_STATE g_In;
PBUFFER_STATE In = &g_In;

bool
BfAlign (
void
)
{
uint8_t padByte;
//
// Keep reading until we reach 32-bit alignment. All bytes must be zero.
//
while (In->Offset & 3)
{
if (!BfRead(&padByte) || (padByte != 0))
{
return false;
}
}
return true;
}

bool
BfSeek (
uint32_t Length,
uint8_t** Bytes
)
{
//
// Make sure the input buffer has enough space to seek the desired size, if
// it does, return the current position and then seek past the desired size
//
if ((In->Offset + Length) > In->Size)
{
*Bytes = 0;
return false;
}
*Bytes = &In->Buffer[In->Offset];
In->Offset += Length;
return true;
}

bool
BfRead (
uint8_t* Byte
)
{
uint8_t* pByte;
//
// Seek past the byte and read it
//
if (!BfSeek(sizeof(*Byte), &pByte))
{
*Byte = 0;
return false;
}
*Byte = *pByte;
return true;
}

void
BfInitialize (
uint8_t* InputBuffer,
uint32_t InputSize
)
{
//
// Save all the data in the context buffer state
//
In->Buffer = InputBuffer;
In->Size = InputSize;
In->Offset = 0;
}
Loading

0 comments on commit 2ee81c1

Please sign in to comment.