mirror of
https://github.com/aaru-dps/Aaru.Compression.Native.git
synced 2025-12-16 19:24:31 +00:00
Compare commits
24 Commits
v6.0.0-alp
...
v6.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
d188ebe02e
|
|||
|
e97dd11da5
|
|||
|
27e2baf54a
|
|||
|
1323bba72f
|
|||
|
a39e6abb97
|
|||
|
afc6f3e2bc
|
|||
|
bfb9a6b524
|
|||
|
750df1cca9
|
|||
|
a336ce953e
|
|||
|
057d0c0242
|
|||
|
0068268c65
|
|||
|
beb8b405db
|
|||
|
b3474d88f6
|
|||
|
9ed17b84c3
|
|||
|
8ba4d258bf
|
|||
|
9db2e3212d
|
|||
|
6637fb486f
|
|||
|
17d4446fb1
|
|||
|
b285754ad4
|
|||
|
36102254a5
|
|||
|
c215979aaf
|
|||
|
e948c31fba
|
|||
|
123879fc7c
|
|||
|
47e6c8e50f
|
102
.clang-format
102
.clang-format
@@ -1,48 +1,55 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
AccessModifierOffset: -2
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: true
|
AlignArrayOfStructures: Right
|
||||||
AlignConsecutiveDeclarations: true
|
AlignConsecutiveAssignments: AcrossComments
|
||||||
AlignEscapedNewlines: Right
|
AlignConsecutiveBitFields: true
|
||||||
|
AlignConsecutiveDeclarations: AcrossComments
|
||||||
|
AlignConsecutiveMacros: AcrossComments
|
||||||
|
AlignConsecutiveShortCaseStatements:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: true
|
||||||
|
AlignCaseColons: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
AlignOperands: true
|
AlignOperands: true
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
AllowShortBlocksOnASingleLine: true
|
AllowShortBlocksOnASingleLine: Always
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AllowShortIfStatementsOnASingleLine: Always
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLoopsOnASingleLine: true
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
BinPackArguments: false
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
BinPackParameters: false
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterClass: true
|
AfterCaseLabel: true
|
||||||
|
AfterClass: false
|
||||||
AfterControlStatement: true
|
AfterControlStatement: true
|
||||||
AfterEnum: true
|
AfterEnum: true
|
||||||
AfterFunction: true
|
AfterFunction: true
|
||||||
AfterNamespace: true
|
AfterNamespace: true
|
||||||
AfterObjCDeclaration: true
|
AfterObjCDeclaration: false
|
||||||
AfterStruct: true
|
AfterStruct: true
|
||||||
AfterUnion: true
|
AfterUnion: true
|
||||||
AfterExternBlock: true
|
AfterExternBlock: true
|
||||||
BeforeCatch: true
|
BeforeCatch: true
|
||||||
BeforeElse: true
|
BeforeElse: true
|
||||||
IndentBraces: false
|
IndentBraces: false
|
||||||
SplitEmptyFunction: false
|
|
||||||
SplitEmptyRecord: false
|
|
||||||
SplitEmptyNamespace: false
|
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Allman
|
BreakBeforeBraces: Allman
|
||||||
BreakBeforeInheritanceComma: false
|
BreakBeforeInheritanceComma: false
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializersBeforeComma: false
|
BreakConstructorInitializersBeforeComma: false
|
||||||
BreakConstructorInitializers: BeforeColon
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakStringLiterals: true
|
|
||||||
ColumnLimit: 120
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
ConstructorInitializerIndentWidth: 4
|
ConstructorInitializerIndentWidth: 4
|
||||||
@@ -56,39 +63,30 @@ ForEachMacros:
|
|||||||
- foreach
|
- foreach
|
||||||
- Q_FOREACH
|
- Q_FOREACH
|
||||||
- BOOST_FOREACH
|
- BOOST_FOREACH
|
||||||
IncludeBlocks: Regroup
|
IncludeBlocks: Preserve
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '^(<winsock2.h>)'
|
- Regex: '^<ext/.*\.h>'
|
||||||
Priority: -3
|
Priority: 2
|
||||||
SortPriority: -4
|
- Regex: '^<.*\.h>'
|
||||||
- Regex: '^(<windows.h>)'
|
|
||||||
Priority: -3
|
|
||||||
SortPriority: -3
|
|
||||||
- Regex: '^(<.*)'
|
|
||||||
Priority: -2
|
|
||||||
SortPriority: -2
|
|
||||||
- Regex: '^("(win32|windows))'
|
|
||||||
Priority: 1
|
Priority: 1
|
||||||
SortPriority: -1
|
- Regex: '^<.*'
|
||||||
- Regex: '^("library.h")'
|
Priority: 2
|
||||||
Priority: 0
|
- Regex: 'library\.h'
|
||||||
SortPriority: -1
|
Priority: 2
|
||||||
- Regex: '.*'
|
- Regex: '.*'
|
||||||
Priority: 0
|
Priority: 3
|
||||||
SortPriority: 0
|
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentPPDirectives: None
|
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
IndentWrappedFunctionNames: true
|
IndentWrappedFunctionNames: false
|
||||||
JavaScriptQuotes: Double
|
JavaScriptQuotes: Leave
|
||||||
JavaScriptWrapImports: true
|
JavaScriptWrapImports: true
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
LineEnding: LF
|
||||||
MacroBlockBegin: ''
|
MacroBlockBegin: ''
|
||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: All
|
NamespaceIndentation: None
|
||||||
ObjCBlockIndentWidth: 4
|
ObjCBlockIndentWidth: 2
|
||||||
ObjCSpaceAfterProperty: false
|
ObjCSpaceAfterProperty: false
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
PenaltyBreakAssignment: 2
|
PenaltyBreakAssignment: 2
|
||||||
@@ -98,23 +96,21 @@ PenaltyBreakFirstLessLess: 120
|
|||||||
PenaltyBreakString: 1000
|
PenaltyBreakString: 1000
|
||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
PointerAlignment: Left
|
PointerAlignment: Right
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
SortIncludes: true
|
SeparateDefinitionBlocks: Always
|
||||||
SortUsingDeclarations: true
|
SortIncludes: CaseInsensitive
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterTemplateKeyword: false
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeParens: Never
|
SpaceBeforeParens: Never
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 2
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
SpacesInContainerLiterals: false
|
SpacesInContainerLiterals: true
|
||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
Standard: Cpp11
|
Standard: Latest
|
||||||
TabWidth: 8
|
TabWidth: 4
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
...
|
|
||||||
|
|
||||||
|
|||||||
2042
.editorconfig
2042
.editorconfig
File diff suppressed because it is too large
Load Diff
115
.idea/codeStyles/Project.xml
generated
115
.idea/codeStyles/Project.xml
generated
@@ -24,6 +24,105 @@
|
|||||||
<option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE_PARS" value="true" />
|
<option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE_PARS" value="true" />
|
||||||
<option name="ALIGN_DICTIONARY_PAIR_VALUES" value="true" />
|
<option name="ALIGN_DICTIONARY_PAIR_VALUES" value="true" />
|
||||||
</Objective-C>
|
</Objective-C>
|
||||||
|
<RiderCodeStyleSettings>
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||||
|
</RiderCodeStyleSettings>
|
||||||
<Shell_Script>
|
<Shell_Script>
|
||||||
<option name="SWITCH_CASES_INDENTED" value="true" />
|
<option name="SWITCH_CASES_INDENTED" value="true" />
|
||||||
<option name="REDIRECT_FOLLOWED_BY_SPACE" value="true" />
|
<option name="REDIRECT_FOLLOWED_BY_SPACE" value="true" />
|
||||||
@@ -36,22 +135,6 @@
|
|||||||
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="ObjectiveC">
|
<codeStyleSettings language="ObjectiveC">
|
||||||
<option name="BRACE_STYLE" value="2" />
|
|
||||||
<option name="CLASS_BRACE_STYLE" value="2" />
|
|
||||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
|
||||||
<option name="WHILE_ON_NEW_LINE" value="true" />
|
|
||||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
|
||||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
|
||||||
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
|
||||||
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
|
|
||||||
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
|
|
||||||
<option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
|
|
||||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
|
||||||
<indentOptions>
|
<indentOptions>
|
||||||
<option name="LABEL_INDENT_ABSOLUTE" value="true" />
|
<option name="LABEL_INDENT_ABSOLUTE" value="true" />
|
||||||
</indentOptions>
|
</indentOptions>
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Aaru.Compression.Native</id>
|
<id>Aaru.Compression.Native</id>
|
||||||
<version>6.0.0-alpha10</version>
|
<version>6.0.0-alpha.11.3</version>
|
||||||
<description>C implementation of compression algorithms used by Aaru.</description>
|
<description>C implementation of compression algorithms used by Aaru.</description>
|
||||||
<authors>claunia</authors>
|
<authors>claunia</authors>
|
||||||
<projectUrl>https://github.com/aaru-dps/Aaru.Compression.Native</projectUrl>
|
<projectUrl>https://github.com/aaru-dps/Aaru.Compression.Native</projectUrl>
|
||||||
<licenseUrl>https://spdx.org/licenses/LGPL-2.1-only.html</licenseUrl>
|
<licenseUrl>https://spdx.org/licenses/LGPL-2.1-only.html</licenseUrl>
|
||||||
<copyright>Copyright © 2011-2023 Natalia Portillo</copyright>
|
<copyright>Copyright © 2011-2025 Natalia Portillo</copyright>
|
||||||
<repository type="git" url="https://github.com/aaru-dps/Aaru.Compression.Native.git" />
|
<repository type="git" url="https://github.com/aaru-dps/Aaru.Compression.Native.git" />
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
# This file is part of the Aaru Data Preservation Suite.
|
# This file is part of the Aaru Data Preservation Suite.
|
||||||
# Copyright (c) 2019-2023 Natalia Portillo.
|
# Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or modify
|
# This library is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Lesser General Public License as
|
# it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -128,7 +128,22 @@ endif()
|
|||||||
|
|
||||||
add_subdirectory(3rdparty)
|
add_subdirectory(3rdparty)
|
||||||
|
|
||||||
add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h adc.c adc.h lzip.c flac.c flac.h)
|
add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h adc.c adc.h lzip.c flac.c flac.h
|
||||||
|
zoo/lzd.c
|
||||||
|
zoo/lzd.h
|
||||||
|
zoo/lzh.c
|
||||||
|
zoo/decode.c
|
||||||
|
zoo/huf.c
|
||||||
|
zoo/io.c
|
||||||
|
zoo/lh5.h
|
||||||
|
zoo/lh5.c
|
||||||
|
zoo/lzh.h
|
||||||
|
zoo/ar.h
|
||||||
|
zoo/maketbl.c
|
||||||
|
arc/pack.c
|
||||||
|
arc/squeeze.c
|
||||||
|
arc/crunch.c
|
||||||
|
arc/lzw.c)
|
||||||
|
|
||||||
include(3rdparty/bzip2.cmake)
|
include(3rdparty/bzip2.cmake)
|
||||||
include(3rdparty/flac.cmake)
|
include(3rdparty/flac.cmake)
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ This repository contains the Aaru.Compression.Native library for [Aaru](https://
|
|||||||
|
|
||||||
The purpose of this library is to provide compression and de-compression algorithms for Aaru.
|
The purpose of this library is to provide compression and de-compression algorithms for Aaru.
|
||||||
|
|
||||||
No archiver processing code should fall here, those go in [Aaru.Compression](https://github.com/aaru-dps/Aaru/tree/devel/Aaru.Compression).
|
No archiver processing code should fall here, those go
|
||||||
|
in [Aaru.Compression](https://github.com/aaru-dps/Aaru/tree/devel/Aaru.Compression).
|
||||||
|
|
||||||
To build you just need Docker on Linux and run `build.sh`, that will generate a NuGet package for use with Aaru.Compression.
|
To build you just need Docker on Linux and run `build.sh`, that will generate a NuGet package for use with
|
||||||
|
Aaru.Compression.
|
||||||
|
|
||||||
Currently implemented algorithms are:
|
Currently implemented algorithms are:
|
||||||
|
|
||||||
- Apple Data Compression (RLE with sliding dictionary created for Apple Disk Copy's NDIF)
|
- Apple Data Compression (RLE with sliding dictionary created for Apple Disk Copy's NDIF)
|
||||||
- Apple RLE (Run Length Encoding created for Apple DART)
|
- Apple RLE (Run Length Encoding created for Apple DART)
|
||||||
- [BZIP2](https://gitlab.com/bzip2/bzip2.git)
|
- [BZIP2](https://gitlab.com/bzip2/bzip2.git)
|
||||||
@@ -24,4 +27,4 @@ The resulting output of `build.sh` falls under the LGPL 2.1 license as stated in
|
|||||||
|
|
||||||
Any new algorithm added should be under a license compatible with the LGPL 2.1 license to be accepted.
|
Any new algorithm added should be under a license compatible with the LGPL 2.1 license to be accepted.
|
||||||
|
|
||||||
© 2021-2023 Natalia Portillo
|
© 2021-2025 Natalia Portillo
|
||||||
28
adc.c
28
adc.c
@@ -19,10 +19,14 @@ FORCE_INLINE int GetChunkSize(uint8_t byt)
|
|||||||
{
|
{
|
||||||
switch(GetChunkType(byt))
|
switch(GetChunkType(byt))
|
||||||
{
|
{
|
||||||
case ADC_PLAIN: return (byt & 0x7F) + 1;
|
case ADC_PLAIN:
|
||||||
case ADC_TWO_BYTE: return ((byt & 0x3F) >> 2) + 3;
|
return (byt & 0x7F) + 1;
|
||||||
case ADC_THREE_BYTE: return (byt & 0x3F) + 4;
|
case ADC_TWO_BYTE:
|
||||||
default: return -1;
|
return ((byt & 0x3F) >> 2) + 3;
|
||||||
|
case ADC_THREE_BYTE:
|
||||||
|
return (byt & 0x3F) + 4;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,16 +34,18 @@ FORCE_INLINE int GetOffset(uint8_t chunk[])
|
|||||||
{
|
{
|
||||||
switch(GetChunkType(chunk[0]))
|
switch(GetChunkType(chunk[0]))
|
||||||
{
|
{
|
||||||
case ADC_PLAIN: return 0;
|
case ADC_PLAIN:
|
||||||
case ADC_TWO_BYTE: return ((chunk[0] & 0x03) << 8) + chunk[1];
|
return 0;
|
||||||
case ADC_THREE_BYTE: return (chunk[1] << 8) + chunk[2];
|
case ADC_TWO_BYTE:
|
||||||
default: return -1;
|
return ((chunk[0] & 0x03) << 8) + chunk[1];
|
||||||
|
case ADC_THREE_BYTE:
|
||||||
|
return (chunk[1] << 8) + chunk[2];
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_adc_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_adc_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||||
int32_t dst_size,
|
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size)
|
int32_t src_size)
|
||||||
{
|
{
|
||||||
int inputPosition = 0;
|
int inputPosition = 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
* Copyright © 2018-2019 David Ryskalczyk
|
* Copyright © 2018-2019 David Ryskalczyk
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
@@ -24,10 +24,8 @@
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "apple_rle.h"
|
#include "apple_rle.h"
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_apple_rle_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_apple_rle_decode_buffer(uint8_t *dst_buffer, int32_t dst_size,
|
||||||
int32_t dst_size,
|
const uint8_t *src_buffer, int32_t src_size)
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size)
|
|
||||||
{
|
{
|
||||||
static int32_t count = 0;
|
static int32_t count = 0;
|
||||||
static bool nextA = true; // true if A, false if B
|
static bool nextA = true; // true if A, false if B
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
|||||||
295
arc/crunch.c
Normal file
295
arc/crunch.c
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
* Copyright © 2018-2019 David Ryskalczyk
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../library.h"
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE !FALSE
|
||||||
|
#define TABSIZE 4096 // Size of the string table.
|
||||||
|
#define NO_PRED 0xFFFF // Indicates no predecessor in the string table.
|
||||||
|
#define EMPTY 0xFFFF // Indicates an empty stack.
|
||||||
|
|
||||||
|
typedef unsigned char u_char;
|
||||||
|
typedef unsigned short u_short;
|
||||||
|
|
||||||
|
// Entry in the string table.
|
||||||
|
struct entry
|
||||||
|
{
|
||||||
|
char used; // Is this entry in use?
|
||||||
|
u_char follower; // The character that follows the string.
|
||||||
|
u_short next; // Next entry in a collision chain.
|
||||||
|
u_short predecessor; // Code for the preceding string.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static variables for decompression state.
|
||||||
|
static struct entry *string_tab;
|
||||||
|
static u_char *stack;
|
||||||
|
static int sp;
|
||||||
|
|
||||||
|
// Buffer management variables.
|
||||||
|
static const u_char *in_buf_ptr;
|
||||||
|
static size_t in_len_rem;
|
||||||
|
static int inflag;
|
||||||
|
|
||||||
|
// Pointer to the hash function to use.
|
||||||
|
static u_short (*h)(u_short, u_char);
|
||||||
|
|
||||||
|
// Original hash function from ARC.
|
||||||
|
static u_short oldh(u_short pred, u_char foll)
|
||||||
|
{
|
||||||
|
long local;
|
||||||
|
local = ((pred + foll) | 0x0800) & 0xFFFF;
|
||||||
|
local *= local;
|
||||||
|
return (local >> 6) & 0x0FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Newer, faster hash function.
|
||||||
|
static u_short newh(u_short pred, u_char foll) { return (((pred + foll) & 0xFFFF) * 15073) & 0xFFF; }
|
||||||
|
|
||||||
|
// Finds the end of a collision list.
|
||||||
|
static u_short eolist(u_short index)
|
||||||
|
{
|
||||||
|
int temp;
|
||||||
|
while((temp = string_tab[index].next)) index = temp;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hashes a string to find its position in the table.
|
||||||
|
static u_short hash_it(u_short pred, u_char foll)
|
||||||
|
{
|
||||||
|
u_short local, tempnext;
|
||||||
|
struct entry *ep;
|
||||||
|
|
||||||
|
local = (*h)(pred, foll);
|
||||||
|
|
||||||
|
if(!string_tab[local].used)
|
||||||
|
return local;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
local = eolist(local);
|
||||||
|
tempnext = (local + 101) & 0x0FFF;
|
||||||
|
ep = &string_tab[tempnext];
|
||||||
|
|
||||||
|
while(ep->used)
|
||||||
|
{
|
||||||
|
if(++tempnext == TABSIZE)
|
||||||
|
{
|
||||||
|
tempnext = 0;
|
||||||
|
ep = string_tab;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++ep;
|
||||||
|
}
|
||||||
|
string_tab[local].next = tempnext;
|
||||||
|
return tempnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a new string to the table.
|
||||||
|
static void upd_tab(u_short pred, u_short foll)
|
||||||
|
{
|
||||||
|
struct entry *ep;
|
||||||
|
ep = &string_tab[hash_it(pred, foll)];
|
||||||
|
ep->used = TRUE;
|
||||||
|
ep->next = 0;
|
||||||
|
ep->predecessor = pred;
|
||||||
|
ep->follower = foll;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializes the string table.
|
||||||
|
static void init_tab()
|
||||||
|
{
|
||||||
|
memset((char *)string_tab, 0, TABSIZE * sizeof(struct entry));
|
||||||
|
for(unsigned int i = 0; i < 256; i++) upd_tab(NO_PRED, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a 12-bit code from the input buffer.
|
||||||
|
static int get_code()
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
if(in_len_rem < 2) return -1;
|
||||||
|
|
||||||
|
if((inflag ^= 1))
|
||||||
|
{
|
||||||
|
code = (*in_buf_ptr++ << 4);
|
||||||
|
code |= (*in_buf_ptr >> 4);
|
||||||
|
in_len_rem--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
code = (*in_buf_ptr++ & 0x0f) << 8;
|
||||||
|
code |= (*in_buf_ptr++);
|
||||||
|
in_len_rem -= 2;
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushes a character onto the stack.
|
||||||
|
#define PUSH(c) \
|
||||||
|
do { \
|
||||||
|
stack[sp] = ((char)(c)); \
|
||||||
|
if(++sp >= TABSIZE) return -1; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// Pops a character from the stack.
|
||||||
|
#define POP() ((sp > 0) ? (int)stack[--sp] : EMPTY)
|
||||||
|
|
||||||
|
// Internal crunch decompression logic.
|
||||||
|
static int arc_decompress_crunch_internal(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len, int new_hash)
|
||||||
|
{
|
||||||
|
// Basic validation of pointers.
|
||||||
|
if(!in_buf || !out_buf || !out_len) { return -1; }
|
||||||
|
|
||||||
|
// Allocate memory for tables.
|
||||||
|
string_tab = (struct entry *)malloc(TABSIZE * sizeof(struct entry));
|
||||||
|
stack = (u_char *)malloc(TABSIZE * sizeof(u_char));
|
||||||
|
if(!string_tab || !stack)
|
||||||
|
{
|
||||||
|
if(string_tab) free(string_tab);
|
||||||
|
if(stack) free(stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select the hash function.
|
||||||
|
if(new_hash)
|
||||||
|
h = newh;
|
||||||
|
else
|
||||||
|
h = oldh;
|
||||||
|
|
||||||
|
// Initialize state.
|
||||||
|
sp = 0;
|
||||||
|
init_tab();
|
||||||
|
int code_count = TABSIZE - 256;
|
||||||
|
in_buf_ptr = in_buf;
|
||||||
|
in_len_rem = in_len;
|
||||||
|
inflag = 0;
|
||||||
|
|
||||||
|
// Main decompression loop.
|
||||||
|
int oldcode = get_code();
|
||||||
|
if(oldcode == -1)
|
||||||
|
{
|
||||||
|
*out_len = 0;
|
||||||
|
free(string_tab);
|
||||||
|
free(stack);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int finchar = string_tab[oldcode].follower;
|
||||||
|
|
||||||
|
size_t out_pos = 0;
|
||||||
|
if(out_pos < *out_len) { out_buf[out_pos++] = finchar; }
|
||||||
|
|
||||||
|
int newcode;
|
||||||
|
while((newcode = get_code()) != -1)
|
||||||
|
{
|
||||||
|
int code = newcode;
|
||||||
|
struct entry *ep = &string_tab[code];
|
||||||
|
|
||||||
|
// Handle unknown codes and KwKwK case.
|
||||||
|
if(!ep->used)
|
||||||
|
{
|
||||||
|
code = oldcode;
|
||||||
|
ep = &string_tab[code];
|
||||||
|
PUSH(finchar);
|
||||||
|
}
|
||||||
|
// Decode the string by traversing the table.
|
||||||
|
while(ep->predecessor != NO_PRED)
|
||||||
|
{
|
||||||
|
PUSH(ep->follower);
|
||||||
|
code = ep->predecessor;
|
||||||
|
ep = &string_tab[code];
|
||||||
|
}
|
||||||
|
PUSH(finchar = ep->follower);
|
||||||
|
|
||||||
|
// Add the new string to the table if there's room.
|
||||||
|
if(code_count)
|
||||||
|
{
|
||||||
|
upd_tab(oldcode, finchar);
|
||||||
|
--code_count;
|
||||||
|
}
|
||||||
|
oldcode = newcode;
|
||||||
|
|
||||||
|
// Write the decoded string to the output buffer.
|
||||||
|
while(sp > 0)
|
||||||
|
{
|
||||||
|
int c = POP();
|
||||||
|
if(c == EMPTY) break;
|
||||||
|
if(out_pos < *out_len) { out_buf[out_pos++] = (unsigned char)c; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up and return.
|
||||||
|
*out_len = out_pos;
|
||||||
|
free(string_tab);
|
||||||
|
free(stack);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompresses crunched data.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len)
|
||||||
|
{
|
||||||
|
return arc_decompress_crunch_internal(in_buf, in_len, out_buf, out_len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompresses crunched data with non-repeat packing.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch_nrpack(const unsigned char *in_buf, size_t in_len,
|
||||||
|
unsigned char *out_buf, size_t *out_len)
|
||||||
|
{
|
||||||
|
// Allocate a temporary buffer for the intermediate decompressed data.
|
||||||
|
size_t temp_len = *out_len * 2; // Heuristic for temp buffer size.
|
||||||
|
unsigned char *temp_buf = malloc(temp_len);
|
||||||
|
if(!temp_buf) return -1;
|
||||||
|
|
||||||
|
// First, decompress the crunched data.
|
||||||
|
int result = arc_decompress_crunch_internal(in_buf, in_len, temp_buf, &temp_len, 0);
|
||||||
|
if(result == 0)
|
||||||
|
{
|
||||||
|
// Then, decompress the non-repeat packing.
|
||||||
|
result = arc_decompress_pack(temp_buf, temp_len, out_buf, out_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(temp_buf);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompresses crunched data with non-repeat packing and the new hash function.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch_nrpack_new(const unsigned char *in_buf, size_t in_len,
|
||||||
|
unsigned char *out_buf, size_t *out_len)
|
||||||
|
{
|
||||||
|
// Allocate a temporary buffer.
|
||||||
|
size_t temp_len = *out_len * 2; // Heuristic.
|
||||||
|
unsigned char *temp_buf = malloc(temp_len);
|
||||||
|
if(!temp_buf) return -1;
|
||||||
|
|
||||||
|
// Decompress crunched data with the new hash.
|
||||||
|
int result = arc_decompress_crunch_internal(in_buf, in_len, temp_buf, &temp_len, 1);
|
||||||
|
if(result == 0)
|
||||||
|
{
|
||||||
|
// Decompress non-repeat packing.
|
||||||
|
result = arc_decompress_pack(temp_buf, temp_len, out_buf, out_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(temp_buf);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
271
arc/lzw.c
Normal file
271
arc/lzw.c
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
* Copyright © 2018-2019 David Ryskalczyk
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../library.h"
|
||||||
|
|
||||||
|
#define CRBITS 12 // Max bits for crunching.
|
||||||
|
#define SQBITS 13 // Max bits for squashing.
|
||||||
|
#define INIT_BITS 9 // Initial number of bits per code.
|
||||||
|
#define MAXCODE(n) ((1 << (n)) - 1) // Macro to calculate max code for n bits.
|
||||||
|
#define FIRST 257 // First available code.
|
||||||
|
#define CLEAR 256 // Code to clear the dictionary.
|
||||||
|
|
||||||
|
// LZW decompression state variables.
|
||||||
|
static int Bits;
|
||||||
|
static int max_maxcode;
|
||||||
|
static int n_bits;
|
||||||
|
static int maxcode;
|
||||||
|
static int clear_flg;
|
||||||
|
static int free_ent;
|
||||||
|
static unsigned short *prefix;
|
||||||
|
static unsigned char *suffix;
|
||||||
|
static unsigned char *stack;
|
||||||
|
|
||||||
|
// Buffer management variables.
|
||||||
|
static const unsigned char *in_buf_ptr;
|
||||||
|
static size_t in_len_rem;
|
||||||
|
static int offset;
|
||||||
|
static char buf[SQBITS];
|
||||||
|
|
||||||
|
// Reads a variable-length code from the input buffer.
|
||||||
|
static int getcode()
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
static int size = 0;
|
||||||
|
int r_off, bits;
|
||||||
|
unsigned char *bp = (unsigned char *)buf;
|
||||||
|
|
||||||
|
// Check if we need to increase code size or handle a clear flag.
|
||||||
|
if(clear_flg > 0 || offset >= size || free_ent > maxcode)
|
||||||
|
{
|
||||||
|
if(free_ent > maxcode)
|
||||||
|
{
|
||||||
|
n_bits++;
|
||||||
|
if(n_bits == Bits)
|
||||||
|
maxcode = max_maxcode;
|
||||||
|
else
|
||||||
|
maxcode = MAXCODE(n_bits);
|
||||||
|
}
|
||||||
|
if(clear_flg > 0)
|
||||||
|
{
|
||||||
|
maxcode = MAXCODE(n_bits = INIT_BITS);
|
||||||
|
clear_flg = 0;
|
||||||
|
}
|
||||||
|
// Read n_bits bytes into the buffer.
|
||||||
|
for(size = 0; size < n_bits; size++)
|
||||||
|
{
|
||||||
|
if(in_len_rem == 0)
|
||||||
|
{
|
||||||
|
code = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = *in_buf_ptr++;
|
||||||
|
in_len_rem--;
|
||||||
|
buf[size] = (char)code;
|
||||||
|
}
|
||||||
|
if(size <= 0) return -1; // End of file.
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
size = (size << 3) - (n_bits - 1);
|
||||||
|
}
|
||||||
|
r_off = offset;
|
||||||
|
bits = n_bits;
|
||||||
|
|
||||||
|
// Extract the code from the buffer.
|
||||||
|
bp += (r_off >> 3);
|
||||||
|
r_off &= 7;
|
||||||
|
|
||||||
|
code = (*bp++ >> r_off);
|
||||||
|
bits -= 8 - r_off;
|
||||||
|
r_off = 8 - r_off;
|
||||||
|
|
||||||
|
if(bits >= 8)
|
||||||
|
{
|
||||||
|
code |= *bp++ << r_off;
|
||||||
|
r_off += 8;
|
||||||
|
bits -= 8;
|
||||||
|
}
|
||||||
|
code |= (*bp & ((1 << bits) - 1)) << r_off;
|
||||||
|
offset += n_bits;
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main LZW decompression logic.
|
||||||
|
static int arc_decompress_lzw(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len,
|
||||||
|
int squash)
|
||||||
|
{
|
||||||
|
// Basic validation of pointers.
|
||||||
|
if(!in_buf || !out_buf || !out_len) { return -1; }
|
||||||
|
|
||||||
|
// Initialize buffer pointers and lengths.
|
||||||
|
in_buf_ptr = in_buf;
|
||||||
|
in_len_rem = in_len;
|
||||||
|
|
||||||
|
// Set parameters based on whether we're unsquashing or uncrushing.
|
||||||
|
if(squash) { Bits = SQBITS; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Bits = CRBITS;
|
||||||
|
if(in_len_rem > 0)
|
||||||
|
{
|
||||||
|
// Crunch format has a header byte indicating max bits.
|
||||||
|
if(*in_buf_ptr != CRBITS) return -1;
|
||||||
|
in_buf_ptr++;
|
||||||
|
in_len_rem--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_len_rem <= 0)
|
||||||
|
{
|
||||||
|
*out_len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize LZW parameters.
|
||||||
|
max_maxcode = 1 << Bits;
|
||||||
|
clear_flg = 0;
|
||||||
|
n_bits = INIT_BITS;
|
||||||
|
maxcode = MAXCODE(n_bits);
|
||||||
|
|
||||||
|
// Allocate memory for LZW tables.
|
||||||
|
prefix = (unsigned short *)malloc(max_maxcode * sizeof(unsigned short));
|
||||||
|
suffix = (unsigned char *)malloc(max_maxcode * sizeof(unsigned char));
|
||||||
|
stack = (unsigned char *)malloc(max_maxcode * sizeof(unsigned char));
|
||||||
|
|
||||||
|
if(!prefix || !suffix || !stack)
|
||||||
|
{
|
||||||
|
if(prefix) free(prefix);
|
||||||
|
if(suffix) free(suffix);
|
||||||
|
if(stack) free(stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the first 256 entries of the dictionary.
|
||||||
|
memset(prefix, 0, 256 * sizeof(unsigned short));
|
||||||
|
for(int code = 255; code >= 0; code--) { suffix[code] = (unsigned char)code; }
|
||||||
|
|
||||||
|
free_ent = FIRST;
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
// Main decompression loop.
|
||||||
|
int finchar, oldcode, incode;
|
||||||
|
finchar = oldcode = getcode();
|
||||||
|
if(oldcode == -1)
|
||||||
|
{
|
||||||
|
*out_len = 0;
|
||||||
|
free(prefix);
|
||||||
|
free(suffix);
|
||||||
|
free(stack);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t out_pos = 0;
|
||||||
|
if(out_pos < *out_len) { out_buf[out_pos++] = finchar; }
|
||||||
|
|
||||||
|
unsigned char *stackp = stack;
|
||||||
|
int code;
|
||||||
|
while((code = getcode()) > -1)
|
||||||
|
{
|
||||||
|
if(code == CLEAR)
|
||||||
|
{
|
||||||
|
// Clear the dictionary.
|
||||||
|
memset(prefix, 0, 256 * sizeof(unsigned short));
|
||||||
|
clear_flg = 1;
|
||||||
|
free_ent = FIRST - 1;
|
||||||
|
if((code = getcode()) == -1) break;
|
||||||
|
}
|
||||||
|
incode = code;
|
||||||
|
// Handle KwKwK case.
|
||||||
|
if(code >= free_ent)
|
||||||
|
{
|
||||||
|
if(code > free_ent)
|
||||||
|
{
|
||||||
|
// Error: invalid code.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*stackp++ = finchar;
|
||||||
|
code = oldcode;
|
||||||
|
}
|
||||||
|
// Decode the string by traversing the dictionary.
|
||||||
|
while(code >= 256)
|
||||||
|
{
|
||||||
|
*stackp++ = suffix[code];
|
||||||
|
code = prefix[code];
|
||||||
|
}
|
||||||
|
*stackp++ = finchar = suffix[code];
|
||||||
|
|
||||||
|
// Write the decoded string to the output buffer.
|
||||||
|
do {
|
||||||
|
if(out_pos < *out_len) { out_buf[out_pos++] = *--stackp; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stackp--; // Discard if output buffer is full.
|
||||||
|
}
|
||||||
|
} while(stackp > stack);
|
||||||
|
|
||||||
|
// Add the new string to the dictionary.
|
||||||
|
if((code = free_ent) < max_maxcode)
|
||||||
|
{
|
||||||
|
prefix[code] = (unsigned short)oldcode;
|
||||||
|
suffix[code] = finchar;
|
||||||
|
free_ent = code + 1;
|
||||||
|
}
|
||||||
|
oldcode = incode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up and return.
|
||||||
|
*out_len = out_pos;
|
||||||
|
free(prefix);
|
||||||
|
free(suffix);
|
||||||
|
free(stack);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompresses squashed data.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_squash(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len)
|
||||||
|
{
|
||||||
|
return arc_decompress_lzw(in_buf, in_len, out_buf, out_len, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompresses crunched data.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch_dynamic(const unsigned char *in_buf, size_t in_len,
|
||||||
|
unsigned char *out_buf, size_t *out_len)
|
||||||
|
{
|
||||||
|
// Allocate a temporary buffer.
|
||||||
|
size_t temp_len = *out_len * 2; // Heuristic.
|
||||||
|
unsigned char *temp_buf = malloc(temp_len);
|
||||||
|
if(!temp_buf) return -1;
|
||||||
|
|
||||||
|
// Decompress crunched data.
|
||||||
|
int result = arc_decompress_lzw(in_buf, in_len, temp_buf, &temp_len, 0);
|
||||||
|
if(result == 0)
|
||||||
|
{
|
||||||
|
// Decompress non-repeat packing.
|
||||||
|
result = arc_decompress_pack(temp_buf, temp_len, out_buf, out_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(temp_buf);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
78
arc/pack.c
Normal file
78
arc/pack.c
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
* Copyright © 2018-2019 David Ryskalczyk
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../library.h"
|
||||||
|
|
||||||
|
#define DLE 0x90 // Data Link Escape character, used as a repeat marker.
|
||||||
|
|
||||||
|
// Decompresses data using non-repeat packing.
|
||||||
|
// This algorithm encodes runs of identical bytes.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_pack(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len)
|
||||||
|
{
|
||||||
|
// Basic validation of pointers.
|
||||||
|
if(!in_buf || !out_buf || !out_len) { return -1; }
|
||||||
|
|
||||||
|
size_t in_pos = 0;
|
||||||
|
size_t out_pos = 0;
|
||||||
|
unsigned char state = 0; // 0 for normal (NOHIST), 1 for in-repeat (INREP).
|
||||||
|
unsigned char lastc = 0; // Last character seen.
|
||||||
|
|
||||||
|
// Loop through the input buffer until it's exhausted or the output buffer is full.
|
||||||
|
while(in_pos < in_len && out_pos < *out_len)
|
||||||
|
{
|
||||||
|
if(state == 1)
|
||||||
|
{ // We are in a repeat sequence.
|
||||||
|
if(in_buf[in_pos])
|
||||||
|
{ // The byte after DLE is the repeat count.
|
||||||
|
unsigned char count = in_buf[in_pos];
|
||||||
|
// Write the last character 'count' times.
|
||||||
|
while(--count && out_pos < *out_len) { out_buf[out_pos++] = lastc; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // A count of 0 means the DLE character itself should be written.
|
||||||
|
if(out_pos < *out_len) { out_buf[out_pos++] = DLE; }
|
||||||
|
}
|
||||||
|
state = 0; // Return to normal state.
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Normal state.
|
||||||
|
if(in_buf[in_pos] != DLE)
|
||||||
|
{ // Not a repeat sequence.
|
||||||
|
if(out_pos < *out_len)
|
||||||
|
{
|
||||||
|
// Copy the character and save it as the last character.
|
||||||
|
out_buf[out_pos++] = lastc = in_buf[in_pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // DLE marks the start of a repeat sequence.
|
||||||
|
state = 1; // Enter repeat state.
|
||||||
|
}
|
||||||
|
in_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the output length to the number of bytes written.
|
||||||
|
*out_len = out_pos;
|
||||||
|
// Return success.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
148
arc/squeeze.c
Normal file
148
arc/squeeze.c
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
* Copyright © 2018-2019 David Ryskalczyk
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "../library.h"
|
||||||
|
|
||||||
|
#define SPEOF 256 // Special end-of-file token.
|
||||||
|
#define NUMVALS 257 // Number of values in the Huffman tree (256 chars + SPEOF).
|
||||||
|
|
||||||
|
// Node structure for the Huffman decoding tree.
|
||||||
|
struct nd
|
||||||
|
{
|
||||||
|
int child[2]; // Children of the node.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static variables for the decompression state.
|
||||||
|
static struct nd nodes[NUMVALS]; // The Huffman tree.
|
||||||
|
static int numnodes; // Number of nodes in the tree.
|
||||||
|
|
||||||
|
static int bpos; // Bit position in the current byte.
|
||||||
|
static unsigned char curin; // Current byte being read.
|
||||||
|
|
||||||
|
// Pointers for buffer management.
|
||||||
|
static const unsigned char *in_buf_ptr;
|
||||||
|
static size_t in_len_rem;
|
||||||
|
static unsigned char *out_buf_ptr;
|
||||||
|
static size_t out_len_rem;
|
||||||
|
|
||||||
|
// Reads a byte from the input buffer.
|
||||||
|
static int get_byte()
|
||||||
|
{
|
||||||
|
if(in_len_rem == 0) { return EOF; }
|
||||||
|
in_len_rem--;
|
||||||
|
return *in_buf_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arc_decompress_huffman(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len)
|
||||||
|
{
|
||||||
|
// Basic validation of pointers.
|
||||||
|
if(!in_buf || !out_buf || !out_len) { return -1; }
|
||||||
|
|
||||||
|
// Initialize buffer pointers and lengths.
|
||||||
|
in_buf_ptr = in_buf;
|
||||||
|
in_len_rem = in_len;
|
||||||
|
out_buf_ptr = out_buf;
|
||||||
|
out_len_rem = *out_len;
|
||||||
|
|
||||||
|
bpos = 99; // Force initial read.
|
||||||
|
|
||||||
|
// Read the number of nodes in the Huffman tree.
|
||||||
|
if(in_len_rem < 2) return -1;
|
||||||
|
numnodes = get_byte();
|
||||||
|
numnodes |= get_byte() << 8;
|
||||||
|
|
||||||
|
if(numnodes < 0 || numnodes >= NUMVALS)
|
||||||
|
{
|
||||||
|
return -1; // Invalid tree.
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARC: initialize for possible empty tree (SPEOF only)
|
||||||
|
nodes[0].child[0] = -(SPEOF + 1);
|
||||||
|
nodes[0].child[1] = -(SPEOF + 1);
|
||||||
|
|
||||||
|
// Read the Huffman tree from the input buffer, sign-extend 16-bit values
|
||||||
|
for(int i = 0; i < numnodes; ++i)
|
||||||
|
{
|
||||||
|
if(in_len_rem < 4) return -1;
|
||||||
|
uint8_t b0 = get_byte();
|
||||||
|
uint8_t b1 = get_byte();
|
||||||
|
uint8_t b2 = get_byte();
|
||||||
|
uint8_t b3 = get_byte();
|
||||||
|
nodes[i].child[0] = (int16_t)((b0) | (b1 << 8));
|
||||||
|
nodes[i].child[1] = (int16_t)((b2) | (b3 << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t written = 0;
|
||||||
|
// bpos is already 99 from init
|
||||||
|
|
||||||
|
while(written < *out_len)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
// follow bit stream in tree to a leaf
|
||||||
|
while(i >= 0)
|
||||||
|
{
|
||||||
|
if(++bpos > 7)
|
||||||
|
{
|
||||||
|
int c = get_byte();
|
||||||
|
if(c == EOF)
|
||||||
|
{
|
||||||
|
*out_len = written;
|
||||||
|
return 0; // End of input
|
||||||
|
}
|
||||||
|
curin = c;
|
||||||
|
bpos = 0;
|
||||||
|
// move a level deeper in tree
|
||||||
|
i = nodes[i].child[curin & 1];
|
||||||
|
}
|
||||||
|
else { i = nodes[i].child[1 & (curin >>= 1)]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode fake node index to original data value
|
||||||
|
int value = -(i + 1);
|
||||||
|
|
||||||
|
if(value == SPEOF)
|
||||||
|
{
|
||||||
|
break; // End of data
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_buf_ptr++ = value;
|
||||||
|
written++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = written;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompresses data using Huffman squeezing.
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_squeeze(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len)
|
||||||
|
{
|
||||||
|
size_t temp_len = *out_len * 2;
|
||||||
|
unsigned char *temp_buf = malloc(temp_len);
|
||||||
|
if(!temp_buf) return -1;
|
||||||
|
|
||||||
|
int result = arc_decompress_huffman(in_buf, in_len, temp_buf, &temp_len);
|
||||||
|
if(result == 0) { result = arc_decompress_pack(temp_buf, temp_len, out_buf, out_len); }
|
||||||
|
|
||||||
|
free(temp_buf);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
11
build.sh
11
build.sh
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# This file is part of the Aaru Data Preservation Suite.
|
# This file is part of the Aaru Data Preservation Suite.
|
||||||
# Copyright (c) 2019-2023 Natalia Portillo.
|
# Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or modify
|
# This library is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Lesser General Public License as
|
# it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -179,7 +179,7 @@ docker/dockcross-win-arm cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1
|
|||||||
sed -e 's/\-soname,libAaru\.Compression\.Native\.so//g' ./CMakeFiles/Aaru.Compression.Native.dir/link.txt > link.txt
|
sed -e 's/\-soname,libAaru\.Compression\.Native\.so//g' ./CMakeFiles/Aaru.Compression.Native.dir/link.txt > link.txt
|
||||||
mv link.txt ./CMakeFiles/Aaru.Compression.Native.dir/link.txt
|
mv link.txt ./CMakeFiles/Aaru.Compression.Native.dir/link.txt
|
||||||
docker/dockcross-win-arm make Aaru.Compression.Native
|
docker/dockcross-win-arm make Aaru.Compression.Native
|
||||||
mv libAaru.Compression.Native.so runtimes/win-arm/native/libAaru.Compression.Native.dll
|
mv libAaru.Compression.Native.dll runtimes/win-arm/native/
|
||||||
|
|
||||||
## Windows (ARM64)
|
## Windows (ARM64)
|
||||||
# Detected system processor: aarch64
|
# Detected system processor: aarch64
|
||||||
@@ -191,14 +191,14 @@ docker/dockcross-win-arm64 cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE
|
|||||||
sed -e 's/\-soname,libAaru\.Compression\.Native\.so//g' ./CMakeFiles/Aaru.Compression.Native.dir/link.txt > link.txt
|
sed -e 's/\-soname,libAaru\.Compression\.Native\.so//g' ./CMakeFiles/Aaru.Compression.Native.dir/link.txt > link.txt
|
||||||
mv link.txt ./CMakeFiles/Aaru.Compression.Native.dir/link.txt
|
mv link.txt ./CMakeFiles/Aaru.Compression.Native.dir/link.txt
|
||||||
docker/dockcross-win-arm64 make Aaru.Compression.Native
|
docker/dockcross-win-arm64 make Aaru.Compression.Native
|
||||||
mv libAaru.Compression.Native.so runtimes/win-arm64/native/libAaru.Compression.Native.dll
|
mv libAaru.Compression.Native.dll runtimes/win-arm64/native/
|
||||||
|
|
||||||
## Windows (AMD64)
|
## Windows (AMD64)
|
||||||
# Detected system processor: x86_64
|
# Detected system processor: x86_64
|
||||||
# TODO: Requires MSVCRT.DLL
|
# TODO: Requires MSVCRT.DLL
|
||||||
rm -f CMakeCache.txt
|
rm -f CMakeCache.txt
|
||||||
mkdir -p runtimes/win-x64/native
|
mkdir -p runtimes/win-x64/native
|
||||||
docker run --rm dockcross/windows-shared-x64 > docker/dockcross-win-x64
|
docker run --rm dockcross/windows-static-x64 > docker/dockcross-win-x64
|
||||||
chmod +x docker/dockcross-win-x64
|
chmod +x docker/dockcross-win-x64
|
||||||
docker/dockcross-win-x64 cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1 .
|
docker/dockcross-win-x64 cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1 .
|
||||||
docker/dockcross-win-x64 make Aaru.Compression.Native
|
docker/dockcross-win-x64 make Aaru.Compression.Native
|
||||||
@@ -209,7 +209,7 @@ mv libAaru.Compression.Native.dll runtimes/win-x64/native/
|
|||||||
# TODO: Requires MSVCRT.DLL
|
# TODO: Requires MSVCRT.DLL
|
||||||
rm -f CMakeCache.txt
|
rm -f CMakeCache.txt
|
||||||
mkdir -p runtimes/win-x86/native
|
mkdir -p runtimes/win-x86/native
|
||||||
docker run --rm dockcross/windows-shared-x86 > docker/dockcross-win-x86
|
docker run --rm dockcross/windows-static-x86 > docker/dockcross-win-x86
|
||||||
chmod +x docker/dockcross-win-x86
|
chmod +x docker/dockcross-win-x86
|
||||||
docker/dockcross-win-x86 cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1 .
|
docker/dockcross-win-x86 cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1 .
|
||||||
docker/dockcross-win-x86 make Aaru.Compression.Native
|
docker/dockcross-win-x86 make Aaru.Compression.Native
|
||||||
@@ -222,6 +222,7 @@ if [[ ${OS_NAME} == Darwin ]]; then
|
|||||||
make Aaru.Compression.Native
|
make Aaru.Compression.Native
|
||||||
mkdir -p runtimes/osx-x64/native
|
mkdir -p runtimes/osx-x64/native
|
||||||
mv libAaru.Compression.Native.dylib runtimes/osx-x64/native
|
mv libAaru.Compression.Native.dylib runtimes/osx-x64/native
|
||||||
|
make clean
|
||||||
|
|
||||||
rm -f CMakeCache.txt
|
rm -f CMakeCache.txt
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1 -DAARU_MACOS_TARGET_ARCH=arm64 .
|
cmake -DCMAKE_BUILD_TYPE=Release -DAARU_BUILD_PACKAGE=1 -DAARU_MACOS_TARGET_ARCH=arm64 .
|
||||||
|
|||||||
1
codealike.json
Normal file
1
codealike.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"projectId":"748d69bc-5b46-4b80-9066-57e2fbcd92d0","projectName":"Aaru.Compression.Native"}
|
||||||
37
flac.c
37
flac.c
@@ -6,20 +6,25 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "library.h"
|
|
||||||
#include "3rdparty/flac/include/FLAC/metadata.h"
|
#include "3rdparty/flac/include/FLAC/metadata.h"
|
||||||
#include "3rdparty/flac/include/FLAC/stream_decoder.h"
|
#include "3rdparty/flac/include/FLAC/stream_decoder.h"
|
||||||
#include "3rdparty/flac/include/FLAC/stream_encoder.h"
|
#include "3rdparty/flac/include/FLAC/stream_encoder.h"
|
||||||
|
#include "library.h"
|
||||||
#include "flac.h"
|
#include "flac.h"
|
||||||
|
|
||||||
static FLAC__StreamDecoderReadStatus
|
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder,
|
||||||
read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
|
FLAC__byte buffer[],
|
||||||
|
size_t * bytes,
|
||||||
|
void * client_data);
|
||||||
|
|
||||||
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder,
|
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder,
|
||||||
const FLAC__Frame * frame,
|
const FLAC__Frame * frame,
|
||||||
const FLAC__int32 *const buffer[],
|
const FLAC__int32 *const buffer[],
|
||||||
void * client_data);
|
void * client_data);
|
||||||
static void
|
|
||||||
error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data);
|
static void error_callback(const FLAC__StreamDecoder * decoder,
|
||||||
|
FLAC__StreamDecoderErrorStatus status,
|
||||||
|
void * client_data);
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_flac_decode_redbook_buffer(uint8_t * dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_flac_decode_redbook_buffer(uint8_t * dst_buffer,
|
||||||
size_t dst_size,
|
size_t dst_size,
|
||||||
@@ -51,8 +56,16 @@ AARU_EXPORT size_t AARU_CALL AARU_flac_decode_redbook_buffer(uint8_t* dst_
|
|||||||
|
|
||||||
FLAC__stream_decoder_set_md5_checking(decoder, false);
|
FLAC__stream_decoder_set_md5_checking(decoder, false);
|
||||||
|
|
||||||
init_status = FLAC__stream_decoder_init_stream(
|
init_status = FLAC__stream_decoder_init_stream(decoder, read_callback, // 1
|
||||||
decoder, read_callback, NULL, NULL, NULL, NULL, write_callback, NULL, error_callback, ctx);
|
NULL, // 2 seek
|
||||||
|
NULL, // 3 tell
|
||||||
|
NULL, // 4 length
|
||||||
|
NULL, // 5 eof
|
||||||
|
write_callback, // 6 write
|
||||||
|
NULL, // 7 metadata
|
||||||
|
error_callback, // 8 error
|
||||||
|
ctx // 9 client_data
|
||||||
|
);
|
||||||
|
|
||||||
if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
|
if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
|
||||||
{
|
{
|
||||||
@@ -72,8 +85,10 @@ AARU_EXPORT size_t AARU_CALL AARU_flac_decode_redbook_buffer(uint8_t* dst_
|
|||||||
return ret_size;
|
return ret_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FLAC__StreamDecoderReadStatus
|
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder,
|
||||||
read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data)
|
FLAC__byte buffer[],
|
||||||
|
size_t * bytes,
|
||||||
|
void * client_data)
|
||||||
{
|
{
|
||||||
aaru_flac_ctx *ctx = (aaru_flac_ctx *)client_data;
|
aaru_flac_ctx *ctx = (aaru_flac_ctx *)client_data;
|
||||||
|
|
||||||
@@ -213,8 +228,8 @@ AARU_EXPORT size_t AARU_CALL AARU_flac_encode_redbook_buffer(uint8_t* dst_
|
|||||||
|
|
||||||
if(application_id_len > 0 && application_id != NULL)
|
if(application_id_len > 0 && application_id != NULL)
|
||||||
if((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) != NULL)
|
if((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) != NULL)
|
||||||
FLAC__metadata_object_application_set_data(
|
FLAC__metadata_object_application_set_data(metadata[0], (unsigned char *)application_id, application_id_len,
|
||||||
metadata[0], (unsigned char*)application_id, application_id_len, true);
|
true);
|
||||||
|
|
||||||
FLAC__stream_encoder_set_metadata(encoder, metadata, 1);
|
FLAC__stream_encoder_set_metadata(encoder, metadata, 1);
|
||||||
|
|
||||||
|
|||||||
69
library.c
69
library.c
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -25,81 +25,54 @@
|
|||||||
#include "3rdparty/lzma/C/LzmaLib.h"
|
#include "3rdparty/lzma/C/LzmaLib.h"
|
||||||
#include "3rdparty/zstd/lib/zstd.h"
|
#include "3rdparty/zstd/lib/zstd.h"
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_decode_buffer(uint8_t *dst_buffer, uint32_t *dst_size,
|
||||||
uint32_t* dst_size,
|
const uint8_t *src_buffer, uint32_t src_size)
|
||||||
const uint8_t* src_buffer,
|
|
||||||
uint32_t src_size)
|
|
||||||
{
|
{
|
||||||
return BZ2_bzBuffToBuffDecompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, 0, 0);
|
return BZ2_bzBuffToBuffDecompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t *dst_buffer, uint32_t *dst_size,
|
||||||
uint32_t* dst_size,
|
const uint8_t *src_buffer, uint32_t src_size,
|
||||||
const uint8_t* src_buffer,
|
|
||||||
uint32_t src_size,
|
|
||||||
int32_t blockSize100k)
|
int32_t blockSize100k)
|
||||||
{
|
{
|
||||||
return BZ2_bzBuffToBuffCompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, blockSize100k, 0, 0);
|
return BZ2_bzBuffToBuffCompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, blockSize100k, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||||
size_t dst_size,
|
size_t src_size, void *scratch_buffer)
|
||||||
const uint8_t* src_buffer,
|
|
||||||
size_t src_size,
|
|
||||||
void* scratch_buffer)
|
|
||||||
{
|
{
|
||||||
return lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer);
|
return lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer);
|
||||||
}
|
}
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_encode_buffer(uint8_t* dst_buffer,
|
|
||||||
size_t dst_size,
|
AARU_EXPORT size_t AARU_CALL AARU_lzfse_encode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||||
const uint8_t* src_buffer,
|
size_t src_size, void *scratch_buffer)
|
||||||
size_t src_size,
|
|
||||||
void* scratch_buffer)
|
|
||||||
{
|
{
|
||||||
return lzfse_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer);
|
return lzfse_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzma_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||||
size_t* dst_size,
|
size_t *srcLen, const uint8_t *props, size_t propsSize)
|
||||||
const uint8_t* src_buffer,
|
|
||||||
size_t* srcLen,
|
|
||||||
const uint8_t* props,
|
|
||||||
size_t propsSize)
|
|
||||||
{
|
{
|
||||||
return LzmaUncompress(dst_buffer, dst_size, src_buffer, srcLen, props, propsSize);
|
return LzmaUncompress(dst_buffer, dst_size, src_buffer, srcLen, props, propsSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||||
size_t* dst_size,
|
size_t srcLen, uint8_t *outProps, size_t *outPropsSize,
|
||||||
const uint8_t* src_buffer,
|
int32_t level, uint32_t dictSize, int32_t lc, int32_t lp,
|
||||||
size_t srcLen,
|
int32_t pb, int32_t fb, int32_t numThreads)
|
||||||
uint8_t* outProps,
|
|
||||||
size_t* outPropsSize,
|
|
||||||
int32_t level,
|
|
||||||
uint32_t dictSize,
|
|
||||||
int32_t lc,
|
|
||||||
int32_t lp,
|
|
||||||
int32_t pb,
|
|
||||||
int32_t fb,
|
|
||||||
int32_t numThreads)
|
|
||||||
{
|
{
|
||||||
return LzmaCompress(
|
return LzmaCompress(dst_buffer, dst_size, src_buffer, srcLen, outProps, outPropsSize, level, dictSize, lc, lp, pb,
|
||||||
dst_buffer, dst_size, src_buffer, srcLen, outProps, outPropsSize, level, dictSize, lc, lp, pb, fb, numThreads);
|
fb, numThreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_decode_buffer(void* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_zstd_decode_buffer(void *dst_buffer, size_t dst_size, const void *src_buffer,
|
||||||
size_t dst_size,
|
|
||||||
const void* src_buffer,
|
|
||||||
size_t src_size)
|
size_t src_size)
|
||||||
{
|
{
|
||||||
return ZSTD_decompress(dst_buffer, dst_size, src_buffer, src_size);
|
return ZSTD_decompress(dst_buffer, dst_size, src_buffer, src_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_encode_buffer(void* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_zstd_encode_buffer(void *dst_buffer, size_t dst_size, const void *src_buffer,
|
||||||
size_t dst_size,
|
size_t src_size, int32_t compressionLevel)
|
||||||
const void* src_buffer,
|
|
||||||
size_t src_size,
|
|
||||||
int32_t compressionLevel)
|
|
||||||
{
|
{
|
||||||
return ZSTD_compress(dst_buffer, dst_size, src_buffer, src_size, compressionLevel);
|
return ZSTD_compress(dst_buffer, dst_size, src_buffer, src_size, compressionLevel);
|
||||||
}
|
}
|
||||||
|
|||||||
145
library.h
145
library.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -54,107 +54,92 @@
|
|||||||
#define FORCE_INLINE static inline __attribute__((always_inline))
|
#define FORCE_INLINE static inline __attribute__((always_inline))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_adc_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_adc_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||||
int32_t dst_size,
|
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size);
|
int32_t src_size);
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_apple_rle_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_apple_rle_decode_buffer(uint8_t *dst_buffer, int32_t dst_size,
|
||||||
int32_t dst_size,
|
const uint8_t *src_buffer, int32_t src_size);
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size);
|
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_flac_decode_redbook_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_flac_decode_redbook_buffer(uint8_t *dst_buffer, size_t dst_size,
|
||||||
size_t dst_size,
|
const uint8_t *src_buffer, size_t src_size);
|
||||||
const uint8_t* src_buffer,
|
|
||||||
size_t src_size);
|
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_flac_encode_redbook_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_flac_encode_redbook_buffer(
|
||||||
size_t dst_size,
|
uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size, uint32_t blocksize,
|
||||||
const uint8_t* src_buffer,
|
int32_t do_mid_side_stereo, int32_t loose_mid_side_stereo, const char *apodization, uint32_t max_lpc_order,
|
||||||
size_t src_size,
|
uint32_t qlp_coeff_precision, int32_t do_qlp_coeff_prec_search, int32_t do_exhaustive_model_search,
|
||||||
uint32_t blocksize,
|
uint32_t min_residual_partition_order, uint32_t max_residual_partition_order, const char *application_id,
|
||||||
int32_t do_mid_side_stereo,
|
|
||||||
int32_t loose_mid_side_stereo,
|
|
||||||
const char* apodization,
|
|
||||||
uint32_t max_lpc_order,
|
|
||||||
uint32_t qlp_coeff_precision,
|
|
||||||
int32_t do_qlp_coeff_prec_search,
|
|
||||||
int32_t do_exhaustive_model_search,
|
|
||||||
uint32_t min_residual_partition_order,
|
|
||||||
uint32_t max_residual_partition_order,
|
|
||||||
const char* application_id,
|
|
||||||
uint32_t application_id_len);
|
uint32_t application_id_len);
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzip_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzip_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||||
int32_t dst_size,
|
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size);
|
int32_t src_size);
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzip_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzip_encode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||||
int32_t dst_size,
|
int32_t src_size, int32_t dictionary_size,
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size,
|
|
||||||
int32_t dictionary_size,
|
|
||||||
int32_t match_len_limit);
|
int32_t match_len_limit);
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_decode_buffer(uint8_t *dst_buffer, uint32_t *dst_size,
|
||||||
uint32_t* dst_size,
|
const uint8_t *src_buffer, uint32_t src_size);
|
||||||
const uint8_t* src_buffer,
|
|
||||||
uint32_t src_size);
|
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t *dst_buffer, uint32_t *dst_size,
|
||||||
uint32_t* dst_size,
|
const uint8_t *src_buffer, uint32_t src_size,
|
||||||
const uint8_t* src_buffer,
|
|
||||||
uint32_t src_size,
|
|
||||||
int32_t blockSize100k);
|
int32_t blockSize100k);
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||||
size_t dst_size,
|
size_t src_size, void *scratch_buffer);
|
||||||
const uint8_t* src_buffer,
|
|
||||||
size_t src_size,
|
|
||||||
void* scratch_buffer);
|
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_lzfse_encode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||||
size_t dst_size,
|
size_t src_size, void *scratch_buffer);
|
||||||
const uint8_t* src_buffer,
|
|
||||||
size_t src_size,
|
|
||||||
void* scratch_buffer);
|
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzma_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||||
size_t* dst_size,
|
size_t *src_size, const uint8_t *props, size_t propsSize);
|
||||||
const uint8_t* src_buffer,
|
|
||||||
size_t* src_size,
|
|
||||||
const uint8_t* props,
|
|
||||||
size_t propsSize);
|
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||||
size_t* dst_size,
|
size_t src_size, uint8_t *outProps, size_t *outPropsSize,
|
||||||
const uint8_t* src_buffer,
|
int32_t level, uint32_t dictSize, int32_t lc, int32_t lp,
|
||||||
size_t src_size,
|
int32_t pb, int32_t fb, int32_t numThreads);
|
||||||
uint8_t* outProps,
|
|
||||||
size_t* outPropsSize,
|
|
||||||
int32_t level,
|
|
||||||
uint32_t dictSize,
|
|
||||||
int32_t lc,
|
|
||||||
int32_t lp,
|
|
||||||
int32_t pb,
|
|
||||||
int32_t fb,
|
|
||||||
int32_t numThreads);
|
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_decode_buffer(void* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_zstd_decode_buffer(void *dst_buffer, size_t dst_size, const void *src_buffer,
|
||||||
size_t dst_size,
|
|
||||||
const void* src_buffer,
|
|
||||||
size_t src_size);
|
size_t src_size);
|
||||||
|
|
||||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_encode_buffer(void* dst_buffer,
|
AARU_EXPORT size_t AARU_CALL AARU_zstd_encode_buffer(void *dst_buffer, size_t dst_size, const void *src_buffer,
|
||||||
size_t dst_size,
|
size_t src_size, int32_t compressionLevel);
|
||||||
const void* src_buffer,
|
|
||||||
size_t src_size,
|
AARU_EXPORT void AARU_CALL *CreateLZDContext(void);
|
||||||
int32_t compressionLevel);
|
|
||||||
|
AARU_EXPORT void AARU_CALL DestroyLZDContext(void *ctx);
|
||||||
|
|
||||||
|
AARU_EXPORT int AARU_CALL LZD_FeedNative(void *ctx, const unsigned char *data, size_t length);
|
||||||
|
|
||||||
|
AARU_EXPORT int AARU_CALL LZD_DrainNative(void *ctx, unsigned char *outBuf, size_t outBufLen, size_t *produced);
|
||||||
|
|
||||||
|
AARU_EXPORT int AARU_CALL lh5_decompress(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len);
|
||||||
|
|
||||||
#define AARU_CHECKUMS_NATIVE_VERSION 0x06000089
|
#define AARU_CHECKUMS_NATIVE_VERSION 0x06000089
|
||||||
|
|
||||||
AARU_EXPORT uint64_t AARU_CALL AARU_get_acn_version();
|
AARU_EXPORT uint64_t AARU_CALL AARU_get_acn_version();
|
||||||
|
|
||||||
|
// ARC method 3: Stored with non-repeat packing
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_pack(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len);
|
||||||
|
// ARC method 4: Huffman squeezing
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_squeeze(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len);
|
||||||
|
// Method 5: LZW (crunching)
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len);
|
||||||
|
// Method 6: LZW with non-repeat packing (crunching)
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch_nrpack(const unsigned char *in_buf, size_t in_len,
|
||||||
|
unsigned char *out_buf, size_t *out_len);
|
||||||
|
// Method 7: LZW with non-repeat packing and new hash (Crunching)
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch_nrpack_new(const unsigned char *in_buf, size_t in_len,
|
||||||
|
unsigned char *out_buf, size_t *out_len);
|
||||||
|
|
||||||
|
// Method 8: Dynamic LZW (crunching)
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_crunch_dynamic(const unsigned char *in_buf, size_t in_len,
|
||||||
|
unsigned char *out_buf, size_t *out_len);
|
||||||
|
|
||||||
|
// Method 9: Dynamic LZW with 13 bits (squashing)
|
||||||
|
AARU_EXPORT int AARU_CALL arc_decompress_squash(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf,
|
||||||
|
size_t *out_len);
|
||||||
|
|
||||||
#endif // AARU_COMPRESSION_NATIVE_LIBRARY_H
|
#endif // AARU_COMPRESSION_NATIVE_LIBRARY_H
|
||||||
|
|||||||
13
lzip.c
13
lzip.c
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
* Copyright © 2018-2019 David Ryskalczyk
|
* Copyright © 2018-2019 David Ryskalczyk
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
@@ -23,9 +23,7 @@
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "3rdparty/lzlib/lzlib.h"
|
#include "3rdparty/lzlib/lzlib.h"
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzip_decode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzip_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||||
int32_t dst_size,
|
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size)
|
int32_t src_size)
|
||||||
{
|
{
|
||||||
int max_in_size;
|
int max_in_size;
|
||||||
@@ -83,11 +81,8 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzip_decode_buffer(uint8_t* dst_buffer,
|
|||||||
return out_pos;
|
return out_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
AARU_EXPORT int32_t AARU_CALL AARU_lzip_encode_buffer(uint8_t* dst_buffer,
|
AARU_EXPORT int32_t AARU_CALL AARU_lzip_encode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||||
int32_t dst_size,
|
int32_t src_size, int32_t dictionary_size,
|
||||||
const uint8_t* src_buffer,
|
|
||||||
int32_t src_size,
|
|
||||||
int32_t dictionary_size,
|
|
||||||
int32_t match_len_limit)
|
int32_t match_len_limit)
|
||||||
{
|
{
|
||||||
int max_in_size;
|
int max_in_size;
|
||||||
|
|||||||
@@ -39,7 +39,30 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/audio.bin
|
|||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/data.bin
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/data.bin
|
||||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/alice29.lzd
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/alice29.lh5
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arcpack.bin
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arcsqueeze.bin
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arccrunchnr.bin
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arccrunch_dynamic.bin
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arcsquash.bin
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||||
|
|
||||||
# 'Google_Tests_run' is the target name
|
# 'Google_Tests_run' is the target name
|
||||||
# 'test1.cpp tests2.cpp' are source files with tests
|
# 'test1.cpp tests2.cpp' are source files with tests
|
||||||
add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp)
|
add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp
|
||||||
|
zoo/lzd.cpp arc/pack.cpp lh5.cpp arc/squeeze.cpp arc/crunch.cpp
|
||||||
|
arc/squash.cpp)
|
||||||
target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native")
|
target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "../adc.h"
|
|
||||||
#include "../library.h"
|
#include "../library.h"
|
||||||
|
#include "../adc.h"
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "../apple_rle.h"
|
|
||||||
#include "../library.h"
|
#include "../library.h"
|
||||||
|
#include "../apple_rle.h"
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
|||||||
133
tests/arc/crunch.cpp
Normal file
133
tests/arc/crunch.cpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../../library.h"
|
||||||
|
#include "../crc32.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#define EXPECTED_CRC32 0x66007dba
|
||||||
|
|
||||||
|
static const uint8_t *buffer;
|
||||||
|
|
||||||
|
class crunchFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
crunchFixture()
|
||||||
|
{
|
||||||
|
// initialization;
|
||||||
|
// can also be done in SetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/arccrunchnr.bin", path);
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
buffer = (const uint8_t *)malloc(72537);
|
||||||
|
fread((void *)buffer, 1, 72537, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() { free((void *)buffer); }
|
||||||
|
|
||||||
|
~crunchFixture()
|
||||||
|
{
|
||||||
|
// resources cleanup, no exceptions allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared user data
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(crunchFixture, crunch)
|
||||||
|
{
|
||||||
|
size_t destLen = 152089;
|
||||||
|
size_t srcLen = 72537;
|
||||||
|
auto *outBuf = (uint8_t *)malloc(152089);
|
||||||
|
|
||||||
|
auto err = arc_decompress_crunch_nrpack(buffer, srcLen, outBuf, &destLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
EXPECT_EQ(destLen, 152089);
|
||||||
|
|
||||||
|
auto crc = crc32_data(outBuf, 152089);
|
||||||
|
|
||||||
|
free(outBuf);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||||
|
}
|
||||||
|
|
||||||
|
class crunchDynamicFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
crunchDynamicFixture()
|
||||||
|
{
|
||||||
|
// initialization;
|
||||||
|
// can also be done in SetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/arccrunch_dynamic.bin", path);
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
buffer = (const uint8_t *)malloc(73189);
|
||||||
|
fread((void *)buffer, 1, 73189, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() { free((void *)buffer); }
|
||||||
|
|
||||||
|
~crunchDynamicFixture()
|
||||||
|
{
|
||||||
|
// resources cleanup, no exceptions allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared user data
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(crunchDynamicFixture, crunchDynamic)
|
||||||
|
{
|
||||||
|
size_t destLen = 152089;
|
||||||
|
size_t srcLen = 73189;
|
||||||
|
auto *outBuf = (uint8_t *)malloc(152089);
|
||||||
|
|
||||||
|
auto err = arc_decompress_crunch_dynamic(buffer, srcLen, outBuf, &destLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
EXPECT_EQ(destLen, 152089);
|
||||||
|
|
||||||
|
auto crc = crc32_data(outBuf, 152089);
|
||||||
|
|
||||||
|
free(outBuf);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||||
|
}
|
||||||
82
tests/arc/pack.cpp
Normal file
82
tests/arc/pack.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../../library.h"
|
||||||
|
#include "../crc32.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#define EXPECTED_CRC32 0x66007dba
|
||||||
|
|
||||||
|
static const uint8_t *buffer;
|
||||||
|
|
||||||
|
class packFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
packFixture()
|
||||||
|
{
|
||||||
|
// initialization;
|
||||||
|
// can also be done in SetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/arcpack.bin", path);
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
buffer = (const uint8_t *)malloc(149855);
|
||||||
|
fread((void *)buffer, 1, 149855, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() { free((void *)buffer); }
|
||||||
|
|
||||||
|
~packFixture()
|
||||||
|
{
|
||||||
|
// resources cleanup, no exceptions allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared user data
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(packFixture, pack)
|
||||||
|
{
|
||||||
|
uint8_t params[] = {0x5D, 0x00, 0x00, 0x00, 0x02};
|
||||||
|
size_t destLen = 152089;
|
||||||
|
size_t srcLen = 149855;
|
||||||
|
auto *outBuf = (uint8_t *)malloc(152089);
|
||||||
|
|
||||||
|
auto err = arc_decompress_pack(buffer, srcLen, outBuf, &destLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
EXPECT_EQ(destLen, 152089);
|
||||||
|
|
||||||
|
auto crc = crc32_data(outBuf, 152089);
|
||||||
|
|
||||||
|
free(outBuf);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||||
|
}
|
||||||
81
tests/arc/squash.cpp
Normal file
81
tests/arc/squash.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../../library.h"
|
||||||
|
#include "../crc32.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#define EXPECTED_CRC32 0x66007dba
|
||||||
|
|
||||||
|
static const uint8_t *buffer;
|
||||||
|
|
||||||
|
class squashFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
squashFixture()
|
||||||
|
{
|
||||||
|
// initialization;
|
||||||
|
// can also be done in SetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/arcsquash.bin", path);
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
buffer = (const uint8_t *)malloc(67308);
|
||||||
|
fread((void *)buffer, 1, 67308, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() { free((void *)buffer); }
|
||||||
|
|
||||||
|
~squashFixture()
|
||||||
|
{
|
||||||
|
// resources cleanup, no exceptions allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared user data
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(squashFixture, squash)
|
||||||
|
{
|
||||||
|
size_t destLen = 152089;
|
||||||
|
size_t srcLen = 67308;
|
||||||
|
auto *outBuf = (uint8_t *)malloc(152089);
|
||||||
|
|
||||||
|
auto err = arc_decompress_squash(buffer, srcLen, outBuf, &destLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
EXPECT_EQ(destLen, 152089);
|
||||||
|
|
||||||
|
auto crc = crc32_data(outBuf, 152089);
|
||||||
|
|
||||||
|
free(outBuf);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||||
|
}
|
||||||
81
tests/arc/squeeze.cpp
Normal file
81
tests/arc/squeeze.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../../library.h"
|
||||||
|
#include "../crc32.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#define EXPECTED_CRC32 0x66007dba
|
||||||
|
|
||||||
|
static const uint8_t *buffer;
|
||||||
|
|
||||||
|
class squeezeFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
squeezeFixture()
|
||||||
|
{
|
||||||
|
// initialization;
|
||||||
|
// can also be done in SetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/arcsqueeze.bin", path);
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
buffer = (const uint8_t *)malloc(88044);
|
||||||
|
fread((void *)buffer, 1, 88044, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() { free((void *)buffer); }
|
||||||
|
|
||||||
|
~squeezeFixture()
|
||||||
|
{
|
||||||
|
// resources cleanup, no exceptions allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared user data
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(squeezeFixture, squeeze)
|
||||||
|
{
|
||||||
|
size_t destLen = 152089;
|
||||||
|
size_t srcLen = 88044;
|
||||||
|
auto *outBuf = (uint8_t *)malloc(152089);
|
||||||
|
|
||||||
|
auto err = arc_decompress_squeeze(buffer, srcLen, outBuf, &destLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
EXPECT_EQ(destLen, 152089);
|
||||||
|
|
||||||
|
auto crc = crc32_data(outBuf, 152089);
|
||||||
|
|
||||||
|
free(outBuf);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define CRC32_ISO_POLY 0xEDB88320
|
#define CRC32_ISO_POLY 0xEDB88320
|
||||||
@@ -43,13 +44,13 @@ uint32_t crc32_data(const uint8_t *data, uint32_t len)
|
|||||||
localTable[i] = entry;
|
localTable[i] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < len; i++)
|
for(i = 0; i < len; i++) localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)];
|
||||||
localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)];
|
|
||||||
|
|
||||||
localHashInt ^= CRC32_ISO_SEED;
|
localHashInt ^= CRC32_ISO_SEED;
|
||||||
|
|
||||||
return localHashInt;
|
return localHashInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -24,6 +24,7 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t crc32_data(const uint8_t *data, uint32_t len);
|
uint32_t crc32_data(const uint8_t *data, uint32_t len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
BIN
tests/data/alice29.lh5
Normal file
BIN
tests/data/alice29.lh5
Normal file
Binary file not shown.
BIN
tests/data/alice29.lzd
Normal file
BIN
tests/data/alice29.lzd
Normal file
Binary file not shown.
BIN
tests/data/arccrunch_dynamic.bin
Executable file
BIN
tests/data/arccrunch_dynamic.bin
Executable file
Binary file not shown.
BIN
tests/data/arccrunchnr.bin
Executable file
BIN
tests/data/arccrunchnr.bin
Executable file
Binary file not shown.
3628
tests/data/arcpack.bin
Executable file
3628
tests/data/arcpack.bin
Executable file
File diff suppressed because it is too large
Load Diff
BIN
tests/data/arcsquash.bin
Executable file
BIN
tests/data/arcsquash.bin
Executable file
Binary file not shown.
BIN
tests/data/arcsqueeze.bin
Executable file
BIN
tests/data/arcsqueeze.bin
Executable file
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../flac.h"
|
|
||||||
#include "../library.h"
|
#include "../library.h"
|
||||||
|
#include "../flac.h"
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
@@ -109,22 +109,9 @@ TEST_F(flacFixture, flacCompress)
|
|||||||
original_crc = crc32_data(original, original_len);
|
original_crc = crc32_data(original, original_len);
|
||||||
|
|
||||||
// Compress
|
// Compress
|
||||||
newSize = AARU_flac_encode_redbook_buffer(cmp_buffer,
|
newSize = AARU_flac_encode_redbook_buffer(cmp_buffer, cmp_len, original, original_len, 4608, 1, 0,
|
||||||
cmp_len,
|
"partial_tukey(0/1.0/1.0)", 12, 0, 1, false, 0, 8,
|
||||||
original,
|
"Aaru.Compression.Native.Tests", strlen("Aaru.Compression.Native.Tests"));
|
||||||
original_len,
|
|
||||||
4608,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
"partial_tukey(0/1.0/1.0)",
|
|
||||||
12,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
8,
|
|
||||||
"Aaru.Compression.Native.Tests",
|
|
||||||
strlen("Aaru.Compression.Native.Tests"));
|
|
||||||
cmp_len = newSize;
|
cmp_len = newSize;
|
||||||
|
|
||||||
// Decompress
|
// Decompress
|
||||||
|
|||||||
84
tests/lh5.cpp
Normal file
84
tests/lh5.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../zoo/lh5.h"
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../library.h"
|
||||||
|
#include "crc32.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#define EXPECTED_CRC32 0x66007dba
|
||||||
|
|
||||||
|
static const uint8_t *buffer;
|
||||||
|
|
||||||
|
class lh5Fixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
lh5Fixture()
|
||||||
|
{
|
||||||
|
// initialization;
|
||||||
|
// can also be done in SetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp()
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(path, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/alice29.lh5", path);
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
buffer = (const uint8_t *)malloc(59104);
|
||||||
|
fread((void *)buffer, 1, 59104, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() { free((void *)buffer); }
|
||||||
|
|
||||||
|
~lh5Fixture()
|
||||||
|
{
|
||||||
|
// resources cleanup, no exceptions allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared user data
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(lh5Fixture, lh5)
|
||||||
|
{
|
||||||
|
uint8_t params[] = {0x5D, 0x00, 0x00, 0x00, 0x02};
|
||||||
|
size_t destLen = 152089;
|
||||||
|
size_t srcLen = 59104;
|
||||||
|
auto *outBuf = (uint8_t *)malloc(152089);
|
||||||
|
|
||||||
|
auto err = lh5_decompress(buffer, srcLen, outBuf, &destLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
EXPECT_EQ(destLen, 152089);
|
||||||
|
|
||||||
|
auto crc = crc32_data(outBuf, 152089);
|
||||||
|
|
||||||
|
free(outBuf);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
@@ -114,8 +114,8 @@ TEST_F(lzmaFixture, lzmaCompress)
|
|||||||
original_crc = crc32_data(original, original_len);
|
original_crc = crc32_data(original, original_len);
|
||||||
|
|
||||||
// Compress
|
// Compress
|
||||||
err = AARU_lzma_encode_buffer(
|
err = AARU_lzma_encode_buffer(cmp_buffer, &cmp_len, original, original_len, props, &props_len, 9, 1048576, 3, 0, 2,
|
||||||
cmp_buffer, &cmp_len, original, original_len, props, &props_len, 9, 1048576, 3, 0, 2, 273, 2);
|
273, 2);
|
||||||
EXPECT_EQ(err, 0);
|
EXPECT_EQ(err, 0);
|
||||||
|
|
||||||
// Decompress
|
// Decompress
|
||||||
|
|||||||
182
tests/zoo/lzd.cpp
Normal file
182
tests/zoo/lzd.cpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../../library.h"
|
||||||
|
#include "../crc32.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#define OUTPUT_CHUNK 8192
|
||||||
|
#define EXPECTED_SIZE 152089
|
||||||
|
#define EXPECTED_CRC32_VAL 0x66007dba
|
||||||
|
|
||||||
|
static long long filesize_of(const char* path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if(stat(path, &st) == 0) return (long long)st.st_size;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class lzdFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
getcwd(cwd, PATH_MAX);
|
||||||
|
snprintf(filename, PATH_MAX, "%s/data/alice29.lzd", cwd);
|
||||||
|
|
||||||
|
inFile = fopen(filename, "rb");
|
||||||
|
ASSERT_NE(inFile, nullptr) << "Failed to open input file";
|
||||||
|
|
||||||
|
fileSize = filesize_of(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override
|
||||||
|
{
|
||||||
|
if(inFile) fclose(inFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* inFile = nullptr;
|
||||||
|
long long fileSize = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LZD_OK = 0,
|
||||||
|
LZD_NEED_INPUT = 1,
|
||||||
|
LZD_NEED_OUTPUT = 2,
|
||||||
|
LZD_DONE = 3
|
||||||
|
} LZDStatus;
|
||||||
|
|
||||||
|
TEST_F(lzdFixture, ZooMethod1)
|
||||||
|
{
|
||||||
|
unsigned char inbuf[OUTPUT_CHUNK];
|
||||||
|
unsigned char outbuf[OUTPUT_CHUNK];
|
||||||
|
|
||||||
|
bool flushed = false;
|
||||||
|
bool eof = false;
|
||||||
|
size_t total_out = 0;
|
||||||
|
size_t total_in = 0;
|
||||||
|
size_t iter = 0;
|
||||||
|
|
||||||
|
fprintf(stderr, "INPUT FILE SIZE=%lld bytes\n", fileSize);
|
||||||
|
|
||||||
|
void* ctx = CreateLZDContext();
|
||||||
|
ASSERT_NE(ctx, nullptr) << "Failed to create LZD context";
|
||||||
|
|
||||||
|
// allocate buffer for full output to CRC at the end
|
||||||
|
uint8_t* full_out = (uint8_t*)malloc(EXPECTED_SIZE);
|
||||||
|
ASSERT_NE(full_out, nullptr);
|
||||||
|
size_t full_offset = 0;
|
||||||
|
|
||||||
|
while(!eof)
|
||||||
|
{
|
||||||
|
size_t nread = fread(inbuf, 1, sizeof inbuf, inFile);
|
||||||
|
if(nread == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "[FEED] size=0 flushed=0 (final empty feed)\n");
|
||||||
|
LZD_FeedNative(ctx, nullptr, 0);
|
||||||
|
flushed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
total_in += nread;
|
||||||
|
fprintf(stderr, "[FEED] size=%zu flushed=0 (real data) total_in=%zu\n",
|
||||||
|
nread, total_in);
|
||||||
|
LZD_FeedNative(ctx, inbuf, nread);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t produced = 0;
|
||||||
|
int st = LZD_OK;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
produced = 0;
|
||||||
|
st = LZD_DrainNative(ctx, outbuf, sizeof outbuf, &produced);
|
||||||
|
fprintf(stderr, "-- LOOP iter=%zu total_out=%zu --\n", iter++, total_out);
|
||||||
|
fprintf(stderr, "[DRAIN] produced=%zu status=%d flushed=%d eof=%d\n",
|
||||||
|
produced, st, flushed ? 1 : 0, eof ? 1 : 0);
|
||||||
|
|
||||||
|
if(produced > 0)
|
||||||
|
{
|
||||||
|
memcpy(full_out + full_offset, outbuf, produced);
|
||||||
|
full_offset += produced;
|
||||||
|
total_out += produced;
|
||||||
|
}
|
||||||
|
if(st == LZD_DONE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, ">>> SET eof=1 (DONE from decoder)\n");
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
} while(produced > 0);
|
||||||
|
|
||||||
|
if(flushed)
|
||||||
|
{
|
||||||
|
for(int spins = 0; spins < 8 && !eof; spins++)
|
||||||
|
{
|
||||||
|
size_t more = 0;
|
||||||
|
int st2 = LZD_DrainNative(ctx, outbuf, sizeof outbuf, &more);
|
||||||
|
fprintf(stderr, "-- LOOP iter=%zu total_out=%zu --\n", iter++, total_out);
|
||||||
|
fprintf(stderr, "[DRAIN] produced=%zu status=%d flushed=1 eof=%d\n",
|
||||||
|
more, st2, eof ? 1 : 0);
|
||||||
|
if(more > 0)
|
||||||
|
{
|
||||||
|
memcpy(full_out + full_offset, outbuf, more);
|
||||||
|
full_offset += more;
|
||||||
|
total_out += more;
|
||||||
|
}
|
||||||
|
else if(st2 == LZD_DONE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, ">>> SET eof=1 (DONE after flush)\n");
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!eof)
|
||||||
|
{
|
||||||
|
fprintf(stderr, ">>> SET eof=1 (no more data and already flushed)\n");
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "\nTOTAL IN=%zu bytes\n", total_in);
|
||||||
|
fprintf(stderr, "TOTAL OUT=%zu bytes\n", total_out);
|
||||||
|
|
||||||
|
DestroyLZDContext(ctx);
|
||||||
|
|
||||||
|
// Now verify the decompressed size and CRC
|
||||||
|
EXPECT_EQ(total_out, static_cast<size_t>(EXPECTED_SIZE));
|
||||||
|
uint32_t crc = crc32_data(full_out, total_out);
|
||||||
|
free(full_out);
|
||||||
|
|
||||||
|
EXPECT_EQ(crc, static_cast<uint32_t>(EXPECTED_CRC32_VAL));
|
||||||
|
EXPECT_EQ(total_in, static_cast<size_t>(fileSize));
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Aaru Data Preservation Suite.
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
* Copyright (c) 2019-2023 Natalia Portillo.
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
|||||||
40
zoo/ar.h
Normal file
40
zoo/ar.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*$Source: /usr/home/dhesi/zoo/RCS/ar.h,v $*/
|
||||||
|
/*$Id: ar.h,v 1.17 91/07/09 01:39:50 dhesi Exp $*/
|
||||||
|
/***********************************************************
|
||||||
|
ar.h
|
||||||
|
|
||||||
|
Adapted from "ar" archiver written by Haruhiko Okumura.
|
||||||
|
***********************************************************/
|
||||||
|
// Modified for in-memory decompression by Natalia Portillo, 2025
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* all the prototypes follow here for all files */
|
||||||
|
|
||||||
|
/* DECODE.C */
|
||||||
|
void decode_start();
|
||||||
|
int decode(uint32_t count, uint8_t *buffer);
|
||||||
|
|
||||||
|
/* HUF.C */
|
||||||
|
void output(uint32_t c, uint32_t p);
|
||||||
|
uint32_t decode_c(void);
|
||||||
|
uint32_t decode_p(void);
|
||||||
|
void huf_decode_start(void);
|
||||||
|
|
||||||
|
/* IO.C */
|
||||||
|
void fillbuf(int n);
|
||||||
|
uint32_t getbits(int n);
|
||||||
|
void putbits(int n, uint32_t x);
|
||||||
|
void init_getbits(void);
|
||||||
|
void init_putbits(void);
|
||||||
|
|
||||||
|
/* MAKETBL.C */
|
||||||
|
void make_table(int nchar, uint8_t bitlen[], int tablebits, uint16_t table[]);
|
||||||
|
|
||||||
|
/* MAKETREE.C */
|
||||||
|
int make_tree(int nparm, uint16_t freqparm[], uint8_t lenparm[], uint16_t codeparm[]);
|
||||||
|
|
||||||
|
/* for lzh modules and also for ar.c to use in defining buffer size */
|
||||||
|
#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
|
||||||
|
#define DICSIZ ((unsigned)1 << DICBIT)
|
||||||
104
zoo/decode.c
Normal file
104
zoo/decode.c
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/*$Source: /usr/home/dhesi/zoo/RCS/decode.c,v $*/
|
||||||
|
/*$Id: decode.c,v 1.6 91/07/09 01:39:49 dhesi Exp $*/
|
||||||
|
/***********************************************************
|
||||||
|
decode.c
|
||||||
|
|
||||||
|
Adapted from Haruhiko Okumura’s “ar” archiver. This
|
||||||
|
version has been modified in 2025 by Natalia Portillo
|
||||||
|
for in-memory decompression.
|
||||||
|
***********************************************************/
|
||||||
|
|
||||||
|
#include <limits.h> // for UCHAR_MAX
|
||||||
|
#include <stdint.h> // for fixed-width integer types
|
||||||
|
|
||||||
|
#include "ar.h" // archive format constants
|
||||||
|
#include "lzh.h" // LZH-specific constants (DICSIZ, THRESHOLD, etc.)
|
||||||
|
|
||||||
|
extern int decoded; // flag set by decode_c() when end-of-stream is reached
|
||||||
|
|
||||||
|
static int j; // number of literal/copy runs remaining from a match
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decode_start()
|
||||||
|
*
|
||||||
|
* Prepare the decoder for a new file:
|
||||||
|
* - Initialize the Huffman bitstream (via huf_decode_start())
|
||||||
|
* - Reset the sliding-window copy counter `j`
|
||||||
|
* - Clear the end-of-data flag `decoded`
|
||||||
|
*/
|
||||||
|
void decode_start()
|
||||||
|
{
|
||||||
|
huf_decode_start(); // reset bit-reader state
|
||||||
|
j = 0; // no pending copy runs yet
|
||||||
|
decoded = 0; // not yet at end-of-stream
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decode(count, buffer)
|
||||||
|
*
|
||||||
|
* Decode up to `count` bytes (usually DICSIZ) into `buffer[]`.
|
||||||
|
* Returns the actual number of bytes written, or 0 if `decoded` is set.
|
||||||
|
*
|
||||||
|
* Sliding‐window logic:
|
||||||
|
* 1. If `j` > 0, we are in the middle of copying a previous match:
|
||||||
|
* - Copy one byte from `buffer[i]` into `buffer[r]`
|
||||||
|
* - Advance `i` (circular within DICSIZ) and `r`
|
||||||
|
* - Decrement `j` and repeat until `j` = 0 or `r` = count
|
||||||
|
* 2. Otherwise, fetch the next symbol `c = decode_c()`:
|
||||||
|
* - If `c <= UCHAR_MAX`, it’s a literal byte: emit it directly
|
||||||
|
* - Else it’s a match:
|
||||||
|
* • compute `j = match_length = c - (UCHAR_MAX + 1 - THRESHOLD)`
|
||||||
|
* • compute `i = (r - match_offset - 1) mod DICSIZ`,
|
||||||
|
* where match_offset = decode_p()
|
||||||
|
* • enter copy loop from step 1
|
||||||
|
*/
|
||||||
|
int decode(uint32_t count, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
static uint32_t i; // sliding-window read index (circular)
|
||||||
|
uint32_t r; // write position in buffer
|
||||||
|
uint32_t c; // symbol or match code
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
// Step 1: finish any pending copy from a previous match
|
||||||
|
while(--j >= 0)
|
||||||
|
{
|
||||||
|
buffer[r] = buffer[i]; // copy one byte from history
|
||||||
|
i = (i + 1) & (DICSIZ - 1); // wrap index within [0, DICSIZ)
|
||||||
|
if(++r == count) // if output buffer is full
|
||||||
|
return r; // return bytes written so far
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: decode new symbols until end-of-stream or buffer full
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
c = decode_c(); // get next Huffman symbol
|
||||||
|
if(decoded) // end-of-stream marker reached
|
||||||
|
return r; // no more bytes to decode
|
||||||
|
|
||||||
|
if(c <= UCHAR_MAX)
|
||||||
|
{
|
||||||
|
// Literal byte: emit it directly
|
||||||
|
buffer[r] = (uint8_t)c;
|
||||||
|
if(++r == count) return r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Match sequence: compute how many bytes to copy
|
||||||
|
// j = match length
|
||||||
|
j = c - (UCHAR_MAX + 1 - THRESHOLD);
|
||||||
|
|
||||||
|
// i = start position in sliding window:
|
||||||
|
// current output position minus offset minus 1, wrapped
|
||||||
|
i = (r - decode_p() - 1) & (DICSIZ - 1);
|
||||||
|
|
||||||
|
// Copy `j` bytes from history
|
||||||
|
while(--j >= 0)
|
||||||
|
{
|
||||||
|
buffer[r] = buffer[i];
|
||||||
|
i = (i + 1) & (DICSIZ - 1);
|
||||||
|
if(++r == count) return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
244
zoo/huf.c
Normal file
244
zoo/huf.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/*$Source: /usr/home/dhesi/zoo/RCS/huf.c,v $*/
|
||||||
|
/*$Id: huf.c,v 1.9 91/07/09 01:39:55 dhesi Exp $*/
|
||||||
|
/***********************************************************
|
||||||
|
huf.c -- static Huffman decoding
|
||||||
|
|
||||||
|
Adapted from Haruhiko Okumura’s “ar” archiver.
|
||||||
|
Modified in 2025 by Natalia Portillo for in-memory I/O.
|
||||||
|
***********************************************************/
|
||||||
|
|
||||||
|
#include <limits.h> // UCHAR_MAX
|
||||||
|
#include "ar.h" // archive format constants
|
||||||
|
#include "lzh.h" // LZH algorithm constants (NC, DICBIT, CODE_BIT, etc.)
|
||||||
|
|
||||||
|
// NP = number of position codes = DICBIT+1
|
||||||
|
// NT = number of tree codes = CODE_BIT+3
|
||||||
|
// PBIT, TBIT = bit‐width to transmit NP/NT in header
|
||||||
|
#define NP (DICBIT + 1)
|
||||||
|
#define NT (CODE_BIT + 3)
|
||||||
|
#define PBIT 4 /* smallest bits so (1<<PBIT)>NP */
|
||||||
|
#define TBIT 5 /* smallest bits so (1<<TBIT)>NT */
|
||||||
|
|
||||||
|
// NPT = max(NP,NT) for prefix‐tree lengths
|
||||||
|
#if NT > NP
|
||||||
|
#define NPT NT
|
||||||
|
#else
|
||||||
|
#define NPT NP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// forward declarations of helper routines
|
||||||
|
static void read_pt_len(int nn, int nbit, int i_special);
|
||||||
|
static void read_c_len(void);
|
||||||
|
|
||||||
|
int decoded; // flag set when end-of-stream block is seen
|
||||||
|
|
||||||
|
// Huffman tree storage arrays
|
||||||
|
// left[]/right[] store the binary tree structure for fast decoding
|
||||||
|
uint16_t left[2 * NC - 1], right[2 * NC - 1];
|
||||||
|
|
||||||
|
// c_len[] = code lengths for literal/length tree (NC symbols)
|
||||||
|
// pt_len[] = code lengths for position‐tree / prefix table (NPT symbols)
|
||||||
|
// buf = temporary buffer pointer used during encoding; unused in decode
|
||||||
|
static uint8_t *buf, c_len[NC], pt_len[NPT];
|
||||||
|
|
||||||
|
// size of buf if used, and remaining symbols in current block
|
||||||
|
static uint32_t bufsiz = 0, blocksize;
|
||||||
|
|
||||||
|
// Frequency, code and decode‐table structures
|
||||||
|
static uint16_t c_freq[2 * NC - 1], // literal/length frequency counts
|
||||||
|
c_table[4096], // fast‐lookup table for literal/length decoding
|
||||||
|
c_code[NC], // canonical Huffman codes for literals
|
||||||
|
p_freq[2 * NP - 1], // position frequency counts
|
||||||
|
pt_table[256], // prefix‐tree fast lookup (for reading code lengths)
|
||||||
|
pt_code[NPT], // canonical codes for prefix‐tree
|
||||||
|
t_freq[2 * NT - 1]; // temporary freq for tree of code‐length codes
|
||||||
|
|
||||||
|
/***** decoding helper: read prefix‐tree code-lengths *****/
|
||||||
|
static void read_pt_len(int nn, int nbit, int i_special)
|
||||||
|
{
|
||||||
|
int i, c, n;
|
||||||
|
uint32_t mask;
|
||||||
|
|
||||||
|
// 1) read how many code‐lengths to consume
|
||||||
|
n = getbits(nbit);
|
||||||
|
if(n == 0)
|
||||||
|
{
|
||||||
|
// special case: all code‐lengths are identical
|
||||||
|
c = getbits(nbit);
|
||||||
|
for(i = 0; i < nn; i++) // zero out lengths
|
||||||
|
pt_len[i] = 0;
|
||||||
|
for(i = 0; i < 256; i++) // prefix‐table always returns 'c'
|
||||||
|
pt_table[i] = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 2) read code lengths one by one
|
||||||
|
i = 0;
|
||||||
|
while(i < n)
|
||||||
|
{
|
||||||
|
// peek top 3 bits of bitbuf to guess small lengths
|
||||||
|
c = bitbuf >> (BITBUFSIZ - 3);
|
||||||
|
if(c == 7)
|
||||||
|
{
|
||||||
|
// if all three bits are 1, count additional ones
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 3);
|
||||||
|
while(mask & bitbuf)
|
||||||
|
{
|
||||||
|
c++;
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// consume the actual length bits
|
||||||
|
fillbuf((c < 7) ? 3 : (c - 3));
|
||||||
|
pt_len[i++] = c;
|
||||||
|
|
||||||
|
// at special index, read a small run of zeros
|
||||||
|
if(i == i_special)
|
||||||
|
{
|
||||||
|
c = getbits(2);
|
||||||
|
while(--c >= 0 && i < nn) pt_len[i++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// any remaining symbols get code‐length zero
|
||||||
|
while(i < nn) pt_len[i++] = 0;
|
||||||
|
|
||||||
|
// build fast lookup table from lengths
|
||||||
|
make_table(nn, pt_len, 8, pt_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** decoding helper: read literal/length code‐lengths *****/
|
||||||
|
static void read_c_len(void)
|
||||||
|
{
|
||||||
|
int i, c, n;
|
||||||
|
uint32_t mask;
|
||||||
|
|
||||||
|
// 1) how many literal codes?
|
||||||
|
n = getbits(CBIT);
|
||||||
|
if(n == 0)
|
||||||
|
{
|
||||||
|
// all code‐lengths identical
|
||||||
|
c = getbits(CBIT);
|
||||||
|
for(i = 0; i < NC; i++) c_len[i] = 0;
|
||||||
|
for(i = 0; i < 4096; i++) c_table[i] = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 2) read each code length via prefix‐tree
|
||||||
|
i = 0;
|
||||||
|
while(i < n)
|
||||||
|
{
|
||||||
|
// lookup next symbol in prefix‐table
|
||||||
|
c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
|
||||||
|
if(c >= NT)
|
||||||
|
{
|
||||||
|
// if prefix code is non-leaf, walk tree
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 8);
|
||||||
|
do {
|
||||||
|
c = (bitbuf & mask) ? right[c] : left[c];
|
||||||
|
mask >>= 1;
|
||||||
|
} while(c >= NT);
|
||||||
|
}
|
||||||
|
// consume code‐length bits
|
||||||
|
fillbuf(pt_len[c]);
|
||||||
|
|
||||||
|
// c ≤ 2: run-length encoding of zeros
|
||||||
|
if(c <= 2)
|
||||||
|
{
|
||||||
|
if(c == 0)
|
||||||
|
c = 1;
|
||||||
|
else if(c == 1)
|
||||||
|
c = getbits(4) + 3;
|
||||||
|
else
|
||||||
|
c = getbits(CBIT) + 20;
|
||||||
|
while(--c >= 0 && i < NC) c_len[i++] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// real code-length = c−2
|
||||||
|
c_len[i++] = (uint8_t)(c - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill rest with zero lengths
|
||||||
|
while(i < NC) c_len[i++] = 0;
|
||||||
|
|
||||||
|
// build fast lookup for literal/length codes
|
||||||
|
make_table(NC, c_len, 12, c_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** decode next literal/length symbol or end-of-block *****/
|
||||||
|
uint32_t decode_c(void)
|
||||||
|
{
|
||||||
|
uint32_t j, mask;
|
||||||
|
|
||||||
|
// if starting a new block, read its header
|
||||||
|
if(blocksize == 0)
|
||||||
|
{
|
||||||
|
blocksize = getbits(16); // block size = number of symbols
|
||||||
|
if(blocksize == 0)
|
||||||
|
{ // zero block → end of data
|
||||||
|
decoded = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// read three Huffman trees for this block:
|
||||||
|
// 1) code-length codes for literal tree (NT,TBIT,3)
|
||||||
|
read_pt_len(NT, TBIT, 3);
|
||||||
|
// 2) literal/length tree lengths (CBIT)
|
||||||
|
read_c_len();
|
||||||
|
// 3) prefix-tree lengths for positions (NP,PBIT,-1)
|
||||||
|
read_pt_len(NP, PBIT, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume one symbol from this block
|
||||||
|
blocksize--;
|
||||||
|
|
||||||
|
// fast table lookup: top 12 bits
|
||||||
|
j = c_table[bitbuf >> (BITBUFSIZ - 12)];
|
||||||
|
if(j >= NC)
|
||||||
|
{
|
||||||
|
// need to walk tree if overflow
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 12);
|
||||||
|
do {
|
||||||
|
j = (bitbuf & mask) ? right[j] : left[j];
|
||||||
|
mask >>= 1;
|
||||||
|
} while(j >= NC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove j’s code length bits from bitbuf
|
||||||
|
fillbuf(c_len[j]);
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** decode match-position extra bits *****/
|
||||||
|
uint32_t decode_p(void)
|
||||||
|
{
|
||||||
|
uint32_t j, mask;
|
||||||
|
|
||||||
|
// fast table lookup: top 8 bits
|
||||||
|
j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
|
||||||
|
if(j >= NP)
|
||||||
|
{
|
||||||
|
// tree walk for long codes
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 8);
|
||||||
|
do {
|
||||||
|
j = (bitbuf & mask) ? right[j] : left[j];
|
||||||
|
mask >>= 1;
|
||||||
|
} while(j >= NP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume prefix bits
|
||||||
|
fillbuf(pt_len[j]);
|
||||||
|
|
||||||
|
// if non-zero, read extra bits to form full position
|
||||||
|
if(j != 0) j = (1U << (j - 1)) + getbits((int)(j - 1));
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** start a new Huffman decode session *****/
|
||||||
|
void huf_decode_start(void)
|
||||||
|
{
|
||||||
|
init_getbits(); // reset bit buffer & subbitbuf state
|
||||||
|
blocksize = 0; // force reading a fresh block header
|
||||||
|
}
|
||||||
129
zoo/io.c
Normal file
129
zoo/io.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*$Source: /usr/home/dhesi/zoo/RCS/io.c,v $*/
|
||||||
|
/*$Id: io.c,v 1.14 91/07/09 01:39:54 dhesi Exp $*/
|
||||||
|
/***********************************************************
|
||||||
|
io.c -- input/output (modified for in-memory I/O)
|
||||||
|
|
||||||
|
Adapted from Haruhiko Okumura’s “ar” archiver.
|
||||||
|
This version feeds compressed bytes from a memory buffer
|
||||||
|
(via mem_getc()) and writes decompressed output to a buffer
|
||||||
|
(via mem_putc()), eliminating FILE* dependencies.
|
||||||
|
Modified for in-memory decompression by Natalia Portillo, 2025
|
||||||
|
***********************************************************/
|
||||||
|
|
||||||
|
#include <limits.h> // Provides CHAR_BIT for bit-width operations
|
||||||
|
|
||||||
|
#include "ar.h" // Archive format constants (e.g., CODE_BIT, NC)
|
||||||
|
#include "lh5.h" // Declarations for mem_getc(), mem_putc(), buffer state
|
||||||
|
#include "lzh.h" // LZH algorithm constants (e.g., BITBUFSIZ, DICSIZ)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Global bit-I/O state
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
uint16_t bitbuf; // Accumulates bits shifted in from the input stream
|
||||||
|
int unpackable; // Unused in decompression here (was for encode error)
|
||||||
|
// Byte counters (optional diagnostics; not used to gate decompression)
|
||||||
|
size_t compsize; // Count of output bytes produced (for compression mode)
|
||||||
|
size_t origsize; // Count of input bytes consumed (for CRC in file I/O)
|
||||||
|
uint32_t subbitbuf; // Holds the last byte fetched; bits are consumed from here
|
||||||
|
int bitcount; // How many valid bits remain in subbitbuf
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fillbuf(n)
|
||||||
|
// Shift the global bitbuf left by n bits, then read in n new bits
|
||||||
|
// from the input buffer (in-memory) to replenish bitbuf.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void fillbuf(int n) /* Shift bitbuf n bits left, read n bits */
|
||||||
|
{
|
||||||
|
// Make room for n bits
|
||||||
|
bitbuf <<= n;
|
||||||
|
|
||||||
|
// While we still need more bits than we have in subbitbuf...
|
||||||
|
while(n > bitcount)
|
||||||
|
{
|
||||||
|
// Pull any remaining bits from subbitbuf into bitbuf
|
||||||
|
bitbuf |= subbitbuf << (n -= bitcount);
|
||||||
|
|
||||||
|
// Fetch the next compressed byte from input memory
|
||||||
|
{
|
||||||
|
int c = mem_getc(); // read one byte or 0 at EOF
|
||||||
|
subbitbuf = (c == EOF ? 0 : (uint8_t)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset bitcount: a full new byte is available
|
||||||
|
bitcount = CHAR_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, consume the last n bits from subbitbuf into bitbuf
|
||||||
|
bitbuf |= subbitbuf >> (bitcount -= n);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// getbits(n)
|
||||||
|
// Return the next n bits from bitbuf (highest-order bits), then
|
||||||
|
// call fillbuf(n) to replace them. Useful for reading variable-length codes.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
uint32_t getbits(int n)
|
||||||
|
{
|
||||||
|
uint32_t x = bitbuf >> (BITBUFSIZ - n); // extract top n bits
|
||||||
|
fillbuf(n); // replenish bitbuf for future reads
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// putbits(n, x)
|
||||||
|
// Write the lowest n bits of x into the output buffer, packing them
|
||||||
|
// into bytes via subbitbuf/bitcount and sending full bytes out
|
||||||
|
// with mem_putc(). Used by the encoder; kept here for completeness.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void putbits(int n, uint32_t x) /* Write rightmost n bits of x */
|
||||||
|
{
|
||||||
|
// If we have enough room in subbitbuf, just pack the bits
|
||||||
|
if(n < bitcount) { subbitbuf |= x << (bitcount -= n); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Output the first full byte when subbitbuf fills
|
||||||
|
{
|
||||||
|
int w = (int)(subbitbuf | (x >> (n -= bitcount)));
|
||||||
|
mem_putc(w);
|
||||||
|
compsize++; // increment output counter (for compression)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If remaining bits don't fill a full byte, stash them
|
||||||
|
if(n < CHAR_BIT) { subbitbuf = x << (bitcount = CHAR_BIT - n); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise, flush a second full byte
|
||||||
|
{
|
||||||
|
int w2 = (int)(x >> (n - CHAR_BIT));
|
||||||
|
mem_putc(w2);
|
||||||
|
compsize++;
|
||||||
|
}
|
||||||
|
// And stash any leftover bits beyond two bytes
|
||||||
|
subbitbuf = x << (bitcount = 2 * CHAR_BIT - n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// init_getbits()
|
||||||
|
// Reset the bit-reader state so that fillbuf() will load fresh bits
|
||||||
|
// from the start of the input buffer.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void init_getbits()
|
||||||
|
{
|
||||||
|
bitbuf = 0; // clear accumulated bits
|
||||||
|
subbitbuf = 0; // no pending byte
|
||||||
|
bitcount = 0; // no bits available
|
||||||
|
fillbuf(BITBUFSIZ); // pre-load the bit buffer fully
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// init_putbits()
|
||||||
|
// Reset the bit-writer state so subsequent putbits() calls start fresh.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void init_putbits()
|
||||||
|
{
|
||||||
|
bitcount = CHAR_BIT; // subbitbuf is empty but ready for CHAR_BIT bits
|
||||||
|
subbitbuf = 0; // clear any leftover byte data
|
||||||
|
}
|
||||||
94
zoo/lh5.c
Normal file
94
zoo/lh5.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* lh5_mem.c
|
||||||
|
*
|
||||||
|
* In-memory I/O glue for LH5 decompression.
|
||||||
|
* Implements mem_getc(), mem_putc(), and the top-level
|
||||||
|
* lh5_decompress() entry point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lh5.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../library.h"
|
||||||
|
|
||||||
|
/* Forward-declaration of the decompression driver in lzh.c */
|
||||||
|
extern int lzh_decode(void);
|
||||||
|
|
||||||
|
/* Buffer I/O state (see lh5_mem.h for externs) */
|
||||||
|
const uint8_t *in_ptr;
|
||||||
|
size_t in_left;
|
||||||
|
uint8_t *out_ptr;
|
||||||
|
size_t out_left;
|
||||||
|
int mem_error;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mem_getc(): return next compressed byte, or 0 when in_left==0.
|
||||||
|
* Never sets mem_error on input underflow.
|
||||||
|
*/
|
||||||
|
int mem_getc(void)
|
||||||
|
{
|
||||||
|
if(in_left == 0) { return 0; /* mimic feof → subbitbuf = 0 */ }
|
||||||
|
int c = *in_ptr++;
|
||||||
|
in_left--;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mem_putc(): write one output byte, set mem_error on overflow.
|
||||||
|
*/
|
||||||
|
int mem_putc(int c)
|
||||||
|
{
|
||||||
|
if(out_left == 0)
|
||||||
|
{
|
||||||
|
mem_error = 1;
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
*out_ptr++ = (uint8_t)c;
|
||||||
|
out_left--;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Top-level in-memory decompressor.
|
||||||
|
*
|
||||||
|
* in_buf points to 'in_len' bytes of compressed data.
|
||||||
|
* out_buf must have at least *out_len bytes available.
|
||||||
|
* On return *out_len is set to the number of bytes written.
|
||||||
|
*
|
||||||
|
* Returns 0 on success
|
||||||
|
* -1 on error (bad stream or output too small)
|
||||||
|
*/
|
||||||
|
AARU_EXPORT int AARU_CALL lh5_decompress(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len)
|
||||||
|
{
|
||||||
|
/* Initialize buffer pointers and error flag */
|
||||||
|
in_ptr = in_buf;
|
||||||
|
in_left = in_len;
|
||||||
|
out_ptr = out_buf;
|
||||||
|
out_left = *out_len;
|
||||||
|
mem_error = 0;
|
||||||
|
|
||||||
|
/* Invoke the core LH5 decode routine (now buffer-based) */
|
||||||
|
if(lzh_decode() != 0 || mem_error) { return -1; }
|
||||||
|
|
||||||
|
/* Compute actual output size */
|
||||||
|
*out_len = (size_t)(out_ptr - out_buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
54
zoo/lh5.h
Normal file
54
zoo/lh5.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* lh5_mem.h
|
||||||
|
*
|
||||||
|
* In-memory I/O glue for LH5 decompression.
|
||||||
|
* Defines the mem_getc()/mem_putc() buffer readers/writers
|
||||||
|
* and declares the lh5_decompress() entry point.
|
||||||
|
*/
|
||||||
|
#ifndef AARU_COMPRESSION_NATIVE_LH5_H
|
||||||
|
#define AARU_COMPRESSION_NATIVE_LH5_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
* State for in-memory I/O
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* in_ptr/in_left: where to read next compressed byte
|
||||||
|
* out_ptr/out_left: where to write next decompressed byte
|
||||||
|
* mem_error: set to 1 on underflow/overflow
|
||||||
|
*/
|
||||||
|
extern const uint8_t *in_ptr;
|
||||||
|
extern size_t in_left;
|
||||||
|
extern uint8_t *out_ptr;
|
||||||
|
extern size_t out_left;
|
||||||
|
extern int mem_error;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
* Fetch one byte from in_buf; returns EOF on underflow
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
int mem_getc(void);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
* Write one byte into out_buf; returns c or EOF on overflow
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
int mem_putc(int c);
|
||||||
|
|
||||||
|
#endif // AARU_COMPRESSION_NATIVE_LH5_H
|
||||||
230
zoo/lzd.c
Normal file
230
zoo/lzd.c
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Lempel-Ziv-Davis compression implementation based on the public domain code from
|
||||||
|
// Rahul Dhesi from zoo
|
||||||
|
|
||||||
|
#include "lzd.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../library.h"
|
||||||
|
|
||||||
|
// Reset the dictionary to its initial state
|
||||||
|
static void init_dict(LZDContext *ctx)
|
||||||
|
{
|
||||||
|
ctx->nbits = 9; // start with 9‑bit codes
|
||||||
|
ctx->max_code = 1u << 9; // maximum code value for current nbits
|
||||||
|
ctx->free_code = FIRST_FREE; // next free dictionary slot
|
||||||
|
ctx->have_old = 0; // no "previous code" yet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Follow the head[] chain until you get the first literal byte of a code
|
||||||
|
static int firstch(LZDContext *ctx, int code)
|
||||||
|
{
|
||||||
|
int steps = 0;
|
||||||
|
while(code > 255)
|
||||||
|
{ // follow links until you hit a literal (0‑255)
|
||||||
|
if((unsigned)code > MAXMAX) return -1; // invalid code range
|
||||||
|
if(++steps > (int)MAXMAX) return -1; // prevent infinite loop
|
||||||
|
code = ctx->head[code];
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure there are at least nbits available in the bit buffer
|
||||||
|
static int fill_bits(LZDContext *ctx)
|
||||||
|
{
|
||||||
|
while(ctx->bitcount < (int)ctx->nbits)
|
||||||
|
{
|
||||||
|
if(ctx->in_pos >= ctx->in_len) return -1; // no more input available
|
||||||
|
// pull a byte from the input stream into bitbuf at current position
|
||||||
|
ctx->bitbuf |= (uint64_t)ctx->in_ptr[ctx->in_pos++] << ctx->bitcount;
|
||||||
|
ctx->bitcount += 8;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next code of nbits from the bit buffer
|
||||||
|
static int read_code(LZDContext *ctx)
|
||||||
|
{
|
||||||
|
if(fill_bits(ctx) < 0) return -1; // top up bits if needed
|
||||||
|
int code = (int)(ctx->bitbuf & masks[ctx->nbits]); // mask off the low nbits
|
||||||
|
ctx->bitbuf >>= ctx->nbits; // consume bits
|
||||||
|
ctx->bitcount -= ctx->nbits;
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise a decompression context: allocate tables, set up initial dictionary
|
||||||
|
LZDStatus LZD_Init(LZDContext *ctx)
|
||||||
|
{
|
||||||
|
memset(ctx, 0, sizeof *ctx);
|
||||||
|
// allocate head, tail and stack arrays to hold dictionary links and output stack
|
||||||
|
ctx->head = malloc((MAXMAX + 1) * sizeof *ctx->head);
|
||||||
|
ctx->tail = malloc((MAXMAX + 1) * sizeof *ctx->tail);
|
||||||
|
ctx->stack = malloc((MAXMAX + 1) * sizeof *ctx->stack);
|
||||||
|
if(!ctx->head || !ctx->tail || !ctx->stack) return LZD_NEED_INPUT;
|
||||||
|
|
||||||
|
// initialise first 256 dictionary entries to literal bytes
|
||||||
|
for(int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
ctx->head[i] = -1;
|
||||||
|
ctx->tail[i] = (uint8_t)i;
|
||||||
|
}
|
||||||
|
// set stack pointers to empty
|
||||||
|
ctx->stack_lim = ctx->stack + (MAXMAX + 1);
|
||||||
|
ctx->stack_ptr = ctx->stack_lim;
|
||||||
|
init_dict(ctx); // reset code size/free_code
|
||||||
|
ctx->bitbuf = 0;
|
||||||
|
ctx->bitcount = 0;
|
||||||
|
return LZD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point the context at a new input buffer
|
||||||
|
LZDStatus LZD_Feed(LZDContext *ctx, const unsigned char *in, size_t in_len)
|
||||||
|
{
|
||||||
|
ctx->in_ptr = in;
|
||||||
|
ctx->in_len = in_len;
|
||||||
|
ctx->in_pos = 0;
|
||||||
|
return LZD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull decompressed bytes into `out` up to out_len or until input is exhausted
|
||||||
|
LZDStatus LZD_Drain(LZDContext *ctx, unsigned char *out, size_t out_len, size_t *out_produced)
|
||||||
|
{
|
||||||
|
size_t outpos = 0;
|
||||||
|
|
||||||
|
while(outpos < out_len)
|
||||||
|
{
|
||||||
|
// If there are bytes on the stack (from expanding a code), emit them first
|
||||||
|
if(ctx->stack_ptr < ctx->stack_lim)
|
||||||
|
{
|
||||||
|
out[outpos++] = (uint8_t)*ctx->stack_ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, read the next code from the bitstream
|
||||||
|
int raw = read_code(ctx);
|
||||||
|
if(raw < 0)
|
||||||
|
{
|
||||||
|
*out_produced = outpos;
|
||||||
|
// If we emitted something, signal OK; otherwise tell caller we need more input
|
||||||
|
return outpos > 0 ? LZD_OK : LZD_NEED_INPUT;
|
||||||
|
}
|
||||||
|
unsigned code = (unsigned)raw;
|
||||||
|
|
||||||
|
// Special code: CLEAR – reset the dictionary and read a fresh literal
|
||||||
|
if(code == CLEAR)
|
||||||
|
{
|
||||||
|
init_dict(ctx);
|
||||||
|
int lit = read_code(ctx);
|
||||||
|
if(lit < 0)
|
||||||
|
{
|
||||||
|
*out_produced = outpos;
|
||||||
|
return outpos > 0 ? LZD_OK : LZD_NEED_INPUT;
|
||||||
|
}
|
||||||
|
ctx->old_code = (unsigned)lit;
|
||||||
|
ctx->have_old = 1;
|
||||||
|
out[outpos++] = (uint8_t)lit;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Special code: Z_EOF – end of compressed stream
|
||||||
|
if(code == Z_EOF)
|
||||||
|
{
|
||||||
|
*out_produced = outpos;
|
||||||
|
return LZD_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned in_code = code;
|
||||||
|
// Handle KwKwK case: code not yet in the dictionary
|
||||||
|
if(code >= ctx->free_code)
|
||||||
|
{
|
||||||
|
if(!ctx->have_old) return LZD_DONE;
|
||||||
|
int fc = firstch(ctx, ctx->old_code); // get first character of previous code
|
||||||
|
if(fc < 0) return LZD_DONE;
|
||||||
|
*--ctx->stack_ptr = (char)fc;
|
||||||
|
code = ctx->old_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk backwards through dictionary, pushing bytes onto the stack
|
||||||
|
while(code > 255)
|
||||||
|
{
|
||||||
|
*--ctx->stack_ptr = (char)ctx->tail[code];
|
||||||
|
code = ctx->head[code];
|
||||||
|
}
|
||||||
|
uint8_t first_byte = (uint8_t)code;
|
||||||
|
*--ctx->stack_ptr = (char)first_byte;
|
||||||
|
|
||||||
|
// Add new sequence to dictionary if we have a valid previous code
|
||||||
|
if(ctx->have_old && ctx->free_code <= MAXMAX)
|
||||||
|
{
|
||||||
|
ctx->tail[ctx->free_code] = first_byte;
|
||||||
|
ctx->head[ctx->free_code] = (int)ctx->old_code;
|
||||||
|
ctx->free_code++;
|
||||||
|
// Increase code width when table fills up to current max_code
|
||||||
|
if(ctx->free_code >= ctx->max_code && ctx->nbits < MAXBITS)
|
||||||
|
{
|
||||||
|
ctx->nbits++;
|
||||||
|
ctx->max_code <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->old_code = in_code;
|
||||||
|
ctx->have_old = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_produced = outpos;
|
||||||
|
return LZD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free dynamic allocations inside an LZDContext
|
||||||
|
void LZD_Destroy(LZDContext *ctx)
|
||||||
|
{
|
||||||
|
if(!ctx) return;
|
||||||
|
free(ctx->head);
|
||||||
|
free(ctx->tail);
|
||||||
|
free(ctx->stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API: allocate+initialise a new context
|
||||||
|
AARU_EXPORT void AARU_CALL *CreateLZDContext(void)
|
||||||
|
{
|
||||||
|
LZDContext *c = malloc(sizeof *c);
|
||||||
|
return c && LZD_Init(c) == LZD_OK ? c : (free(c), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API: destroy and free a context
|
||||||
|
AARU_EXPORT void AARU_CALL DestroyLZDContext(void *ctx)
|
||||||
|
{
|
||||||
|
if(ctx)
|
||||||
|
{
|
||||||
|
LZD_Destroy(ctx);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API wrapper to feed new compressed data
|
||||||
|
AARU_EXPORT int AARU_CALL LZD_FeedNative(void *ctx, const unsigned char *data, size_t length)
|
||||||
|
{
|
||||||
|
return LZD_Feed(ctx, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API wrapper to drain decompressed data
|
||||||
|
AARU_EXPORT int AARU_CALL LZD_DrainNative(void *ctx, unsigned char *outBuf, size_t outBufLen, size_t *produced)
|
||||||
|
{
|
||||||
|
return LZD_Drain(ctx, outBuf, outBufLen, produced);
|
||||||
|
}
|
||||||
86
zoo/lzd.h
Normal file
86
zoo/lzd.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Aaru Data Preservation Suite.
|
||||||
|
* Copyright (c) 2019-2025 Natalia Portillo.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LZD_H
|
||||||
|
#define LZD_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAXBITS 13
|
||||||
|
#define MAXMAX ((1U << MAXBITS) - 1) // 8191
|
||||||
|
#define FIRST_FREE 258 // first free code after CLEAR+EOF
|
||||||
|
#define CLEAR 256
|
||||||
|
#define Z_EOF 257
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LZD_OK = 0,
|
||||||
|
LZD_NEED_INPUT = 1,
|
||||||
|
LZD_NEED_OUTPUT = 2,
|
||||||
|
LZD_DONE = 3
|
||||||
|
} LZDStatus;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int * head;
|
||||||
|
uint8_t *tail;
|
||||||
|
unsigned nbits;
|
||||||
|
unsigned max_code;
|
||||||
|
unsigned free_code;
|
||||||
|
unsigned old_code;
|
||||||
|
int have_old;
|
||||||
|
|
||||||
|
char *stack;
|
||||||
|
char *stack_lim;
|
||||||
|
char *stack_ptr;
|
||||||
|
|
||||||
|
uint64_t bitbuf;
|
||||||
|
int bitcount;
|
||||||
|
|
||||||
|
const unsigned char *in_ptr;
|
||||||
|
size_t in_len;
|
||||||
|
size_t in_pos;
|
||||||
|
} LZDContext;
|
||||||
|
|
||||||
|
static const unsigned masks[MAXBITS + 1] = {
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(1u << 9) - 1,
|
||||||
|
(1u << 10) - 1,
|
||||||
|
(1u << 11) - 1,
|
||||||
|
(1u << 12) - 1,
|
||||||
|
(1u << 13) - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
LZDStatus LZD_Init(LZDContext *ctx);
|
||||||
|
|
||||||
|
LZDStatus LZD_Feed(LZDContext *ctx, const unsigned char *in, size_t in_len);
|
||||||
|
|
||||||
|
LZDStatus LZD_Drain(LZDContext *ctx, unsigned char *out, size_t out_len, size_t *out_produced);
|
||||||
|
|
||||||
|
void LZD_Destroy(LZDContext *ctx);
|
||||||
|
|
||||||
|
#endif // LZD_H
|
||||||
31
zoo/lzh.c
Normal file
31
zoo/lzh.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* $Id: lzh.c,v 1.15 91/07/06 19:18:51 dhesi Exp $ */
|
||||||
|
// Modified for in-memory decompression by Natalia Portillo, 2025
|
||||||
|
|
||||||
|
#include "lzh.h" /* prototypes for encode(), lzh_decode() */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ar.h"
|
||||||
|
#include "lh5.h" /* mem_getc(), mem_putc(), in_ptr/in_left, out_ptr/out_left */
|
||||||
|
|
||||||
|
extern int decoded; /* from huf.c */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lzh_decode now reads from in_buf/in_len and writes into out_buf/out_len
|
||||||
|
* entirely in memory, via mem_getc()/mem_putc().
|
||||||
|
*/
|
||||||
|
int lzh_decode(void)
|
||||||
|
{
|
||||||
|
int n, i;
|
||||||
|
uint8_t buffer[DICSIZ];
|
||||||
|
|
||||||
|
/* Initialize the Huffman bit reader and sliding-window state */
|
||||||
|
decode_start();
|
||||||
|
|
||||||
|
/* Decode blocks of up to DICSIZ bytes until end‐of‐stream */
|
||||||
|
while(!decoded)
|
||||||
|
{
|
||||||
|
n = decode(DICSIZ, buffer);
|
||||||
|
for(i = 0; i < n; i++) { mem_putc(buffer[i]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem_error ? -1 : 0;
|
||||||
|
}
|
||||||
31
zoo/lzh.h
Normal file
31
zoo/lzh.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*$Source: /usr/home/dhesi/zoo/RCS/lzh.h,v $*/
|
||||||
|
/*$Id: lzh.h,v 1.3 91/07/09 01:39:23 dhesi Exp $*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Adapted from "ar" archiver written by Haruhiko Okumura.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Modified for in-memory decompression by Natalia Portillo, 2025
|
||||||
|
|
||||||
|
/* io.c */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern uint16_t bitbuf;
|
||||||
|
#define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
|
||||||
|
|
||||||
|
/* encode.c and decode.c */
|
||||||
|
|
||||||
|
#define MATCHBIT 8 /* bits for MAXMATCH - THRESHOLD */
|
||||||
|
#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */
|
||||||
|
#define THRESHOLD 3 /* choose optimal value */
|
||||||
|
#define PERC_FLAG ((unsigned)0x8000)
|
||||||
|
|
||||||
|
/* huf.c */
|
||||||
|
|
||||||
|
#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
|
||||||
|
/* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||||
|
#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
|
||||||
|
#define CODE_BIT 16 /* codeword length */
|
||||||
|
|
||||||
|
extern uint16_t left[], right[];
|
||||||
130
zoo/maketbl.c
Normal file
130
zoo/maketbl.c
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/*$Source: /usr/home/dhesi/zoo/RCS/maketbl.c,v $*/
|
||||||
|
/*$Id: maketbl.c,v 1.8 91/07/09 01:39:52 dhesi Exp $*/
|
||||||
|
/***********************************************************
|
||||||
|
maketbl.c -- make table for decoding
|
||||||
|
|
||||||
|
Builds a fast lookup table + fallback tree for Huffman
|
||||||
|
codes given code lengths. Used by decode_c() to map
|
||||||
|
input bit patterns to symbols efficiently.
|
||||||
|
|
||||||
|
Adapted from Haruhiko Okumura’s “ar” archiver.
|
||||||
|
Modified for in-memory decompression by Natalia Portillo, 2025
|
||||||
|
***********************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ar.h" // provides NC, CODE_BIT, etc.
|
||||||
|
#include "lzh.h" // provides BITBUFSIZ
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_table(nchar, bitlen, tablebits, table):
|
||||||
|
*
|
||||||
|
* nchar = number of symbols
|
||||||
|
* bitlen[] = array of code lengths for each symbol [0..nchar-1]
|
||||||
|
* tablebits = number of bits for fast direct lookup
|
||||||
|
* table[] = output table of size (1<<tablebits), entries are:
|
||||||
|
* - symbol index if code length ≤ tablebits
|
||||||
|
* - zero or tree node index to follow for longer codes
|
||||||
|
*
|
||||||
|
* Algorithm steps:
|
||||||
|
* 1) Count how many codes of each length (count[1..16]).
|
||||||
|
* 2) Compute 'start' offsets for each length in a 16-bit code space.
|
||||||
|
* 3) Normalize starts to 'tablebits' prefix domain, build 'weight'.
|
||||||
|
* 4) Fill direct-mapped entries for short codes.
|
||||||
|
* 5) Build binary tree (using left[]/right[]) for codes longer than tablebits.
|
||||||
|
*/
|
||||||
|
void make_table(int nchar, uint8_t *bitlen, int tablebits, uint16_t *table)
|
||||||
|
{
|
||||||
|
uint16_t count[17]; // count[L] = number of symbols with length L
|
||||||
|
uint16_t weight[17]; // weight[L] = step size in prefix domain for length L
|
||||||
|
uint16_t start[18]; // start[L] = base code for length L in 16-bit space
|
||||||
|
uint16_t *p; // pointer into 'table' or tree
|
||||||
|
uint32_t i, k, len, ch;
|
||||||
|
uint32_t jutbits; // bits to drop when mapping into tablebits
|
||||||
|
uint32_t avail; // next free node index for left[]/right[] tree
|
||||||
|
uint32_t nextcode; // end-of-range code for current length
|
||||||
|
uint32_t mask; // bitmask for tree insertion
|
||||||
|
|
||||||
|
// 1) Zero counts, then tally code-lengths
|
||||||
|
for(i = 1; i <= 16; i++) count[i] = 0;
|
||||||
|
for(i = 0; i < (uint32_t)nchar; i++) count[bitlen[i]]++;
|
||||||
|
|
||||||
|
// 2) Compute cumulative start positions in the 16-bit code space
|
||||||
|
start[1] = 0;
|
||||||
|
for(i = 1; i <= 16; i++) start[i + 1] = start[i] + (count[i] << (16 - i));
|
||||||
|
|
||||||
|
// Validate: sum of all codes must fill 16-bit range
|
||||||
|
if(start[17] != (uint16_t)(1U << 16)) fprintf(stderr, "make_table: Bad decode table\n");
|
||||||
|
|
||||||
|
// Prepare for mapping into tablebits-bit table
|
||||||
|
jutbits = 16 - tablebits;
|
||||||
|
for(i = 1; i <= (uint32_t)tablebits; i++)
|
||||||
|
{
|
||||||
|
// Shrink start[i] into prefix domain
|
||||||
|
start[i] >>= jutbits;
|
||||||
|
// Weight = 2^(tablebits - i)
|
||||||
|
weight[i] = (uint16_t)(1U << (tablebits - i));
|
||||||
|
}
|
||||||
|
// For lengths > tablebits, weight = 2^(16 - length)
|
||||||
|
for(; i <= 16; i++) weight[i] = (uint16_t)(1U << (16 - i));
|
||||||
|
|
||||||
|
// 3) Clear any unused table slots between last short code and end
|
||||||
|
i = start[tablebits + 1] >> jutbits;
|
||||||
|
if(i != (uint16_t)(1U << tablebits))
|
||||||
|
{
|
||||||
|
k = 1U << tablebits;
|
||||||
|
while(i < k) table[i++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize tree node index after the direct table entries
|
||||||
|
avail = nchar;
|
||||||
|
// Mask for inspecting bits when building tree
|
||||||
|
mask = 1U << (15 - tablebits);
|
||||||
|
|
||||||
|
// 4) For each symbol, place its codes in table or tree
|
||||||
|
for(ch = 0; ch < (uint32_t)nchar; ch++)
|
||||||
|
{
|
||||||
|
len = bitlen[ch];
|
||||||
|
if(len == 0) continue; // skip symbols with no code
|
||||||
|
|
||||||
|
// Next code range = [start[len], start[len]+weight[len])
|
||||||
|
nextcode = start[len] + weight[len];
|
||||||
|
|
||||||
|
if(len <= tablebits)
|
||||||
|
{
|
||||||
|
// Direct mapping: fill all table slots in this range
|
||||||
|
for(k = start[len]; k < nextcode; k++) table[k] = (uint16_t)ch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Build or extend tree for longer codes
|
||||||
|
// Start at table index for this prefix
|
||||||
|
k = start[len];
|
||||||
|
p = &table[k >> jutbits];
|
||||||
|
// Number of extra bits beyond tablebits
|
||||||
|
uint32_t extra = len - tablebits;
|
||||||
|
|
||||||
|
// Walk/construct tree nodes bit by bit
|
||||||
|
while(extra-- > 0)
|
||||||
|
{
|
||||||
|
if(*p == 0)
|
||||||
|
{
|
||||||
|
// allocate a new node for left[]/right[]
|
||||||
|
left[avail] = right[avail] = 0;
|
||||||
|
*p = (uint16_t)avail++;
|
||||||
|
}
|
||||||
|
// branch left or right based on current code bit
|
||||||
|
if(k & mask)
|
||||||
|
p = &right[*p];
|
||||||
|
else
|
||||||
|
p = &left[*p];
|
||||||
|
|
||||||
|
// shift to next bit in code
|
||||||
|
k <<= 1;
|
||||||
|
}
|
||||||
|
// At leaf: assign symbol
|
||||||
|
*p = (uint16_t)ch;
|
||||||
|
}
|
||||||
|
// Advance start[len] for next code of same length
|
||||||
|
start[len] = nextcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user