├── .clang-format ├── .clang-tidy ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── documentation.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ ├── clang-format.yml │ ├── closed-issue-message.yml │ ├── handle-stale-discussions.yml │ ├── issue-regression-labeler.yml │ └── stale_issue.yml ├── .gitignore ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── builder.json ├── cmake └── aws-c-compression-config.cmake ├── codebuild ├── common-posix.sh ├── common-windows.bat ├── linux-clang3-x64.yml ├── linux-clang6-x64.yml ├── linux-gcc-4x-x64.yml ├── linux-gcc-4x-x86.yml ├── linux-gcc-5x-x64.yml ├── linux-gcc-6x-x64.yml ├── linux-gcc-7x-x64.yml ├── windows-msvc-2015-x86.yml ├── windows-msvc-2015.yml └── windows-msvc-2017.yml ├── format-check.py ├── include └── aws │ └── compression │ ├── compression.h │ ├── exports.h │ ├── huffman.h │ └── private │ └── huffman_testing.h ├── source ├── compression.c ├── huffman.c ├── huffman_generator │ ├── CMakeLists.txt │ └── generator.c └── huffman_testing.c └── tests ├── CMakeLists.txt ├── fuzz ├── decode.c ├── transitive.c └── transitive_chunked.c ├── huffman_test.c ├── library_test.c ├── test_huffman_static.c └── test_huffman_static_table.def /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Mozilla 4 | AlignAfterOpenBracket: AlwaysBreak 5 | AlignConsecutiveAssignments: false 6 | AlignConsecutiveDeclarations: false 7 | AlignEscapedNewlines: Right 8 | AlignOperands: true 9 | AlignTrailingComments: true 10 | AllowAllParametersOfDeclarationOnNextLine: false 11 | AllowShortBlocksOnASingleLine: false 12 | AllowShortCaseLabelsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: Inline 14 | AllowShortIfStatementsOnASingleLine: false 15 | AllowShortLoopsOnASingleLine: false 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakBeforeMultilineStrings: false 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BreakBeforeBinaryOperators: None 21 | BreakBeforeBraces: Attach 22 | BreakBeforeTernaryOperators: true 23 | BreakStringLiterals: true 24 | ColumnLimit: 120 25 | ContinuationIndentWidth: 4 26 | DerivePointerAlignment: false 27 | IncludeBlocks: Preserve 28 | IndentCaseLabels: true 29 | IndentPPDirectives: AfterHash 30 | IndentWidth: 4 31 | IndentWrappedFunctionNames: true 32 | KeepEmptyLinesAtTheStartOfBlocks: true 33 | MacroBlockBegin: '' 34 | MacroBlockEnd: '' 35 | MaxEmptyLinesToKeep: 1 36 | PenaltyBreakAssignment: 2 37 | PenaltyBreakBeforeFirstCallParameter: 19 38 | PenaltyBreakComment: 300 39 | PenaltyBreakFirstLessLess: 120 40 | PenaltyBreakString: 1000 41 | PenaltyExcessCharacter: 1000000 42 | PenaltyReturnTypeOnItsOwnLine: 100000 43 | PointerAlignment: Right 44 | ReflowComments: true 45 | SortIncludes: true 46 | SpaceAfterCStyleCast: false 47 | SpaceBeforeAssignmentOperators: true 48 | SpaceBeforeParens: ControlStatements 49 | SpaceInEmptyParentheses: false 50 | SpacesInContainerLiterals: true 51 | SpacesInCStyleCastParentheses: false 52 | SpacesInParentheses: false 53 | SpacesInSquareBrackets: false 54 | Standard: Cpp11 55 | TabWidth: 4 56 | UseTab: Never 57 | ... 58 | 59 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: 'clang-diagnostic-*,clang-analyzer-*,readability-*,modernize-*,bugprone-*,misc-*,google-runtime-int,llvm-header-guard,fuchsia-restrict-system-includes,-clang-analyzer-valist.Uninitialized,-clang-analyzer-security.insecureAPI.rand,-clang-analyzer-alpha.*,-readability-magic-numbers' 3 | WarningsAsErrors: '*' 4 | HeaderFilterRegex: '\./*' 5 | FormatStyle: 'file' 6 | # Use empty line filter to skip linting code we don't own 7 | CheckOptions: 8 | - key: readability-braces-around-statements.ShortStatementLines 9 | value: '1' 10 | - key: google-runtime-int.TypeSufix 11 | value: '_t' 12 | - key: fuchsia-restrict-system-includes.Includes 13 | value: '*,-stdint.h,-stdbool.h,-assert.h' 14 | 15 | ... 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🐛 Bug Report" 3 | description: Report a bug 4 | title: "(short issue description)" 5 | labels: [bug, needs-triage] 6 | assignees: [] 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the bug 12 | description: What is the problem? A clear and concise description of the bug. 13 | validations: 14 | required: true 15 | - type: checkboxes 16 | id: regression 17 | attributes: 18 | label: Regression Issue 19 | description: What is a regression? If it worked in a previous version but doesn't in the latest version, it's considered a regression. In this case, please provide specific version number in the report. 20 | options: 21 | - label: Select this option if this issue appears to be a regression. 22 | required: false 23 | - type: textarea 24 | id: expected 25 | attributes: 26 | label: Expected Behavior 27 | description: | 28 | What did you expect to happen? 29 | validations: 30 | required: true 31 | - type: textarea 32 | id: current 33 | attributes: 34 | label: Current Behavior 35 | description: | 36 | What actually happened? 37 | 38 | Please include full errors, uncaught exceptions, stack traces, and relevant logs. 39 | If service responses are relevant, please include wire logs. 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: reproduction 44 | attributes: 45 | label: Reproduction Steps 46 | description: | 47 | Provide a self-contained, concise snippet of code that can be used to reproduce the issue. 48 | For more complex issues provide a repo with the smallest sample that reproduces the bug. 49 | 50 | Avoid including business logic or unrelated code, it makes diagnosis more difficult. 51 | The code sample should be an SSCCE. See http://sscce.org/ for details. In short, please provide a code sample that we can copy/paste, run and reproduce. 52 | validations: 53 | required: true 54 | - type: textarea 55 | id: solution 56 | attributes: 57 | label: Possible Solution 58 | description: | 59 | Suggest a fix/reason for the bug 60 | validations: 61 | required: false 62 | - type: textarea 63 | id: context 64 | attributes: 65 | label: Additional Information/Context 66 | description: | 67 | Anything else that might be relevant for troubleshooting this bug. Providing context helps us come up with a solution that is most useful in the real world. 68 | validations: 69 | required: false 70 | 71 | - type: input 72 | id: aws-c-compression-version 73 | attributes: 74 | label: aws-c-compression version used 75 | validations: 76 | required: true 77 | 78 | - type: input 79 | id: compiler-version 80 | attributes: 81 | label: Compiler and version used 82 | validations: 83 | required: true 84 | 85 | - type: input 86 | id: operating-system 87 | attributes: 88 | label: Operating System and version 89 | validations: 90 | required: true 91 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 💬 General Question 4 | url: https://github.com/awslabs/aws-c-compression/discussions/categories/q-a 5 | about: Please ask and answer questions as a discussion thread 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "📕 Documentation Issue" 3 | description: Report an issue in the API Reference documentation or Developer Guide 4 | title: "(short issue description)" 5 | labels: [documentation, needs-triage] 6 | assignees: [] 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the issue 12 | description: A clear and concise description of the issue. 13 | validations: 14 | required: true 15 | 16 | - type: textarea 17 | id: links 18 | attributes: 19 | label: Links 20 | description: | 21 | Include links to affected documentation page(s). 22 | validations: 23 | required: true 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | description: Suggest an idea for this project 4 | title: "(short issue description)" 5 | labels: [feature-request, needs-triage] 6 | assignees: [] 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the feature 12 | description: A clear and concise description of the feature you are proposing. 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: use-case 17 | attributes: 18 | label: Use Case 19 | description: | 20 | Why do you need this feature? For example: "I'm always frustrated when..." 21 | validations: 22 | required: true 23 | - type: textarea 24 | id: solution 25 | attributes: 26 | label: Proposed Solution 27 | description: | 28 | Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation. 29 | validations: 30 | required: false 31 | - type: textarea 32 | id: other 33 | attributes: 34 | label: Other Information 35 | description: | 36 | Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc. 37 | validations: 38 | required: false 39 | - type: checkboxes 40 | id: ack 41 | attributes: 42 | label: Acknowledgements 43 | options: 44 | - label: I may be able to implement this feature request 45 | required: false 46 | - label: This feature might incur a breaking change 47 | required: false 48 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - 'main' 7 | 8 | env: 9 | BUILDER_VERSION: v0.9.72 10 | BUILDER_SOURCE: releases 11 | BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net 12 | PACKAGE_NAME: aws-c-compression 13 | LINUX_BASE_IMAGE: ubuntu-18-x64 14 | RUN: ${{ github.run_id }}-${{ github.run_number }} 15 | CRT_CI_ROLE: ${{ secrets.CRT_CI_ROLE_ARN }} 16 | AWS_DEFAULT_REGION: us-east-1 17 | 18 | permissions: 19 | id-token: write # This is required for requesting the JWT 20 | 21 | jobs: 22 | linux-compat: 23 | runs-on: ubuntu-24.04 # latest 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | image: 28 | - manylinux1-x64 29 | - manylinux1-x86 30 | - manylinux2014-x64 31 | - manylinux2014-x86 32 | - fedora-34-x64 33 | - opensuse-leap 34 | - rhel8-x64 35 | - al2-x64 36 | steps: 37 | - uses: aws-actions/configure-aws-credentials@v4 38 | with: 39 | role-to-assume: ${{ env.CRT_CI_ROLE }} 40 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 41 | # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages 42 | - name: Build ${{ env.PACKAGE_NAME }} 43 | run: | 44 | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh 45 | ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ matrix.image }} build -p ${{ env.PACKAGE_NAME }} 46 | 47 | linux-compiler-compat: 48 | runs-on: ubuntu-24.04 # latest 49 | strategy: 50 | matrix: 51 | compiler: 52 | - clang-3 53 | - clang-6 54 | - clang-8 55 | - clang-9 56 | - clang-10 57 | - clang-11 58 | - clang-15 59 | - clang-17 60 | - gcc-4.8 61 | - gcc-5 62 | - gcc-6 63 | - gcc-7 64 | - gcc-8 65 | - gcc-11 66 | - gcc-13 67 | steps: 68 | - uses: aws-actions/configure-aws-credentials@v4 69 | with: 70 | role-to-assume: ${{ env.CRT_CI_ROLE }} 71 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 72 | # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages 73 | - name: Build ${{ env.PACKAGE_NAME }} 74 | run: | 75 | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh 76 | ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=${{ matrix.compiler }} 77 | 78 | clang-sanitizers: 79 | runs-on: ubuntu-24.04 # latest 80 | strategy: 81 | matrix: 82 | sanitizers: [",thread", ",address,undefined"] 83 | steps: 84 | - uses: aws-actions/configure-aws-credentials@v4 85 | with: 86 | role-to-assume: ${{ env.CRT_CI_ROLE }} 87 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 88 | # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages 89 | - name: Build ${{ env.PACKAGE_NAME }} 90 | run: | 91 | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh 92 | ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=clang-11 --cmake-extra=-DENABLE_SANITIZERS=ON --cmake-extra=-DSANITIZERS="${{ matrix.sanitizers }}" 93 | 94 | linux-shared-libs: 95 | runs-on: ubuntu-24.04 # latest 96 | steps: 97 | - uses: aws-actions/configure-aws-credentials@v4 98 | with: 99 | role-to-assume: ${{ env.CRT_CI_ROLE }} 100 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 101 | # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages 102 | - name: Build ${{ env.PACKAGE_NAME }} 103 | run: | 104 | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh 105 | ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DBUILD_SHARED_LIBS=ON 106 | 107 | windows: 108 | runs-on: windows-2022 # latest 109 | steps: 110 | - uses: aws-actions/configure-aws-credentials@v4 111 | with: 112 | role-to-assume: ${{ env.CRT_CI_ROLE }} 113 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 114 | - name: Build ${{ env.PACKAGE_NAME }} + consumers 115 | run: | 116 | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" 117 | python builder.pyz build -p ${{ env.PACKAGE_NAME }} 118 | 119 | windows-vc14: 120 | runs-on: windows-2019 # windows-2019 is last env with Visual Studio 2015 (v14.0) 121 | strategy: 122 | matrix: 123 | arch: [x86, x64] 124 | steps: 125 | - uses: aws-actions/configure-aws-credentials@v4 126 | with: 127 | role-to-assume: ${{ env.CRT_CI_ROLE }} 128 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 129 | - name: Build ${{ env.PACKAGE_NAME }} + consumers 130 | run: | 131 | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" 132 | python builder.pyz build -p ${{ env.PACKAGE_NAME }} --target windows-${{ matrix.arch }} --compiler msvc-14 133 | 134 | windows-shared-libs: 135 | runs-on: windows-2022 # latest 136 | steps: 137 | - uses: aws-actions/configure-aws-credentials@v4 138 | with: 139 | role-to-assume: ${{ env.CRT_CI_ROLE }} 140 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 141 | - name: Build ${{ env.PACKAGE_NAME }} + consumers 142 | run: | 143 | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" 144 | python builder.pyz build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DBUILD_SHARED_LIBS=ON 145 | 146 | windows-app-verifier: 147 | runs-on: windows-2022 # latest 148 | steps: 149 | - uses: aws-actions/configure-aws-credentials@v4 150 | with: 151 | role-to-assume: ${{ env.CRT_CI_ROLE }} 152 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 153 | - name: Build ${{ env.PACKAGE_NAME }} + consumers 154 | run: | 155 | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" 156 | python builder.pyz build -p ${{ env.PACKAGE_NAME }} run_tests=false --cmake-extra=-DBUILD_TESTING=ON 157 | - name: Run and check AppVerifier 158 | run: | 159 | python .\aws-c-compression\build\deps\aws-c-common\scripts\appverifier_ctest.py --build_directory .\aws-c-compression\build\aws-c-compression 160 | 161 | macos: 162 | runs-on: macos-14 # latest 163 | steps: 164 | - uses: aws-actions/configure-aws-credentials@v4 165 | with: 166 | role-to-assume: ${{ env.CRT_CI_ROLE }} 167 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 168 | - name: Build ${{ env.PACKAGE_NAME }} + consumers 169 | run: | 170 | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" 171 | chmod a+x builder 172 | ./builder build -p ${{ env.PACKAGE_NAME }} 173 | 174 | macos-x64: 175 | runs-on: macos-14-large # latest 176 | steps: 177 | - uses: aws-actions/configure-aws-credentials@v4 178 | with: 179 | role-to-assume: ${{ env.CRT_CI_ROLE }} 180 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 181 | - name: Build ${{ env.PACKAGE_NAME }} + consumers 182 | run: | 183 | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" 184 | chmod a+x builder 185 | ./builder build -p ${{ env.PACKAGE_NAME }} 186 | 187 | # Test downstream repos. 188 | # This should not be required because we can run into a chicken and egg problem if there is a change that needs some fix in a downstream repo. 189 | downstream: 190 | runs-on: ubuntu-24.04 # latest 191 | steps: 192 | - uses: aws-actions/configure-aws-credentials@v4 193 | with: 194 | role-to-assume: ${{ env.CRT_CI_ROLE }} 195 | aws-region: ${{ env.AWS_DEFAULT_REGION }} 196 | # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages 197 | - name: Build ${{ env.PACKAGE_NAME }} 198 | run: | 199 | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh 200 | ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build downstream -p ${{ env.PACKAGE_NAME }} 201 | -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push] 4 | 5 | jobs: 6 | clang-format: 7 | 8 | runs-on: ubuntu-24.04 # latest 9 | 10 | steps: 11 | - name: Checkout Sources 12 | uses: actions/checkout@v4 13 | 14 | - name: clang-format lint 15 | run: | 16 | ./format-check.py 17 | -------------------------------------------------------------------------------- /.github/workflows/closed-issue-message.yml: -------------------------------------------------------------------------------- 1 | name: Closed Issue Message 2 | on: 3 | issues: 4 | types: [closed] 5 | jobs: 6 | auto_comment: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: aws-actions/closed-issue-message@v1 10 | with: 11 | # These inputs are both required 12 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 13 | message: | 14 | ### ⚠️COMMENT VISIBILITY WARNING⚠️ 15 | Comments on closed issues are hard for our team to see. 16 | If you need more assistance, please either tag a team member or open a new issue that references this one. 17 | If you wish to keep having a conversation with other community members under this issue feel free to do so. 18 | -------------------------------------------------------------------------------- /.github/workflows/handle-stale-discussions.yml: -------------------------------------------------------------------------------- 1 | name: HandleStaleDiscussions 2 | on: 3 | schedule: 4 | - cron: '0 */4 * * *' 5 | discussion_comment: 6 | types: [created] 7 | 8 | jobs: 9 | handle-stale-discussions: 10 | name: Handle stale discussions 11 | runs-on: ubuntu-latest 12 | permissions: 13 | discussions: write 14 | steps: 15 | - name: Stale discussions action 16 | uses: aws-github-ops/handle-stale-discussions@v1 17 | env: 18 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} -------------------------------------------------------------------------------- /.github/workflows/issue-regression-labeler.yml: -------------------------------------------------------------------------------- 1 | # Apply potential regression label on issues 2 | name: issue-regression-label 3 | on: 4 | issues: 5 | types: [opened, edited] 6 | jobs: 7 | add-regression-label: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | steps: 12 | - name: Fetch template body 13 | id: check_regression 14 | uses: actions/github-script@v7 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | TEMPLATE_BODY: ${{ github.event.issue.body }} 18 | with: 19 | script: | 20 | const regressionPattern = /\[x\] Select this option if this issue appears to be a regression\./i; 21 | const template = `${process.env.TEMPLATE_BODY}` 22 | const match = regressionPattern.test(template); 23 | core.setOutput('is_regression', match); 24 | - name: Manage regression label 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | run: | 28 | if [ "${{ steps.check_regression.outputs.is_regression }}" == "true" ]; then 29 | gh issue edit ${{ github.event.issue.number }} --add-label "potential-regression" -R ${{ github.repository }} 30 | else 31 | gh issue edit ${{ github.event.issue.number }} --remove-label "potential-regression" -R ${{ github.repository }} 32 | fi 33 | -------------------------------------------------------------------------------- /.github/workflows/stale_issue.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues" 2 | 3 | # Controls when the action will run. 4 | on: 5 | schedule: 6 | - cron: "*/60 * * * *" 7 | 8 | jobs: 9 | cleanup: 10 | runs-on: ubuntu-latest 11 | name: Stale issue job 12 | steps: 13 | - uses: aws-actions/stale-issue-cleanup@v3 14 | with: 15 | # Setting messages to an empty string will cause the automation to skip 16 | # that category 17 | ancient-issue-message: Greetings! Sorry to say but this is a very old issue that is probably not getting as much attention as it deserves. We encourage you to check if this is still an issue in the latest release and if you find that this is still a problem, please feel free to open a new one. 18 | stale-issue-message: Greetings! It looks like this issue hasn’t been active in a few days. We encourage you to check if this is still an issue in the latest release. Because it has been a few days since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one. 19 | stale-pr-message: Greetings! It looks like this PR hasn’t been active in a few days, add a comment or an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one. 20 | 21 | # These labels are required 22 | stale-issue-label: closing-soon 23 | exempt-issue-label: automation-exempt 24 | stale-pr-label: closing-soon 25 | exempt-pr-label: pr/needs-review 26 | response-requested-label: response-requested 27 | 28 | # Don't set closed-for-staleness label to skip closing very old issues 29 | # regardless of label 30 | closed-for-staleness-label: closed-for-staleness 31 | 32 | # Issue timing 33 | days-before-stale: 2 34 | days-before-close: 5 35 | days-before-ancient: 36500 36 | 37 | # If you don't want to mark a issue as being ancient based on a 38 | # threshold of "upvotes", you can set this here. An "upvote" is 39 | # the total number of +1, heart, hooray, and rocket reactions 40 | # on an issue. 41 | minimum-upvotes-to-exempt: 1 42 | 43 | repo-token: ${{ secrets.GITHUB_TOKEN }} 44 | loglevel: DEBUG 45 | # Set dry-run to true to not perform label or close actions. 46 | dry-run: false 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE Artifacts 2 | .metadata 3 | .build 4 | .idea 5 | *.d 6 | Debug 7 | Release 8 | *~ 9 | *# 10 | *.iml 11 | tags 12 | 13 | #vim swap file 14 | *.swp 15 | 16 | #compiled python files 17 | *.pyc 18 | 19 | #Vagrant stuff 20 | Vagrantfile 21 | .vagrant 22 | 23 | #Mac stuff 24 | .DS_Store 25 | 26 | #doxygen 27 | doxygen/html/ 28 | doxygen/latex/ 29 | 30 | 31 | #cmake artifacts 32 | dependencies 33 | _build 34 | build 35 | _build_* 36 | cmake-build* 37 | 38 | # Compiled Object files 39 | *.slo 40 | *.lo 41 | *.o 42 | *.obj 43 | 44 | # Precompiled Headers 45 | *.gch 46 | *.pch 47 | 48 | # Compiled Dynamic libraries 49 | *.so 50 | *.dylib 51 | *.dll 52 | 53 | # Fortran module files 54 | *.mod 55 | 56 | # Compiled Static libraries 57 | *.lai 58 | *.la 59 | *.a 60 | *.lib 61 | 62 | # Executables 63 | *.exe 64 | *.out 65 | *.app 66 | 67 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9...3.31) 2 | project(aws-c-compression C) 3 | 4 | if (NOT IN_SOURCE_BUILD) 5 | # this is required so we can use aws-c-common's CMake modules 6 | find_package(aws-c-common REQUIRED) 7 | endif() 8 | 9 | include(AwsCFlags) 10 | include(AwsCheckHeaders) 11 | include(AwsSharedLibSetup) 12 | include(AwsSanitizers) 13 | include(CheckCCompilerFlag) 14 | include(AwsFindPackage) 15 | include(GNUInstallDirs) 16 | 17 | file(GLOB AWS_COMPRESSION_HEADERS 18 | "include/aws/compression/*.h" 19 | ) 20 | 21 | file(GLOB AWS_COMPRESSION_PRIV_HEADERS 22 | "include/aws/compression/private/*.h" 23 | ) 24 | 25 | file(GLOB AWS_COMPRESSION_TESTING_HEADERS 26 | "include/aws/testing/compression/*.h" 27 | "include/aws/testing/compression/*.inl" 28 | ) 29 | 30 | file(GLOB AWS_COMPRESSION_SRC 31 | "source/*.c" 32 | ) 33 | 34 | file(GLOB COMPRESSION_HEADERS 35 | ${AWS_COMPRESSION_HEADERS} 36 | ${AWS_COMPRESSION_PRIV_HEADERS} 37 | ${AWS_COMPRESSION_TESTING_HEADERS} 38 | ) 39 | 40 | file(GLOB COMPRESSION_SRC 41 | ${AWS_COMPRESSION_SRC} 42 | ) 43 | 44 | add_library(${PROJECT_NAME} ${LIBTYPE} ${COMPRESSION_HEADERS} ${COMPRESSION_SRC}) 45 | aws_set_common_properties(${PROJECT_NAME}) 46 | aws_prepare_symbol_visibility_args(${PROJECT_NAME} "AWS_COMPRESSION") 47 | 48 | aws_add_sanitizers(${PROJECT_NAME}) 49 | 50 | # We are not ABI stable yet 51 | set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0) 52 | 53 | target_include_directories(${PROJECT_NAME} PUBLIC 54 | $ 55 | $) 56 | 57 | aws_use_package(aws-c-common) 58 | target_link_libraries(${PROJECT_NAME} PUBLIC ${DEP_AWS_LIBS}) 59 | 60 | aws_prepare_shared_lib_exports(${PROJECT_NAME}) 61 | 62 | aws_check_headers(${PROJECT_NAME} ${AWS_COMPRESSION_HEADERS}) 63 | install(FILES ${AWS_COMPRESSION_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/aws/compression") 64 | install(FILES ${AWS_COMPRESSION_TESTING_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/aws/testing/compression") 65 | 66 | if (BUILD_SHARED_LIBS) 67 | set (TARGET_DIR "shared") 68 | else() 69 | set (TARGET_DIR "static") 70 | endif() 71 | 72 | install(EXPORT "${PROJECT_NAME}-targets" 73 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${TARGET_DIR}" 74 | NAMESPACE AWS:: 75 | COMPONENT Development) 76 | 77 | configure_file("cmake/${PROJECT_NAME}-config.cmake" 78 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 79 | @ONLY) 80 | 81 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 82 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/" 83 | COMPONENT Development) 84 | 85 | option(BUILD_HUFFMAN_GENERATOR "Whether or not to build the aws-c-common-huffman-generator tool" OFF) 86 | if (BUILD_HUFFMAN_GENERATOR) 87 | add_subdirectory(source/huffman_generator) 88 | endif() 89 | 90 | include(CTest) 91 | if (BUILD_TESTING) 92 | add_subdirectory(tests) 93 | endif() 94 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/awslabs/aws-c-compression/issues), or [recently closed](https://github.com/awslabs/aws-c-compression/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/aws-c-compression/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/awslabs/aws-c-compression/blob/main/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | AWS C Compression 2 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | SPDX-License-Identifier: Apache-2.0. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AWS C Compression 2 | 3 | This is a cross-platform C99 implementation of compression algorithms such as 4 | gzip, and huffman encoding/decoding. Currently only huffman is implemented. 5 | 6 | ## License 7 | 8 | This library is licensed under the Apache 2.0 License. 9 | 10 | ## Usage 11 | 12 | ### Building 13 | 14 | Note that aws-c-compression has a dependency on aws-c-common: 15 | 16 | ``` 17 | git clone git@github.com:awslabs/aws-c-common.git 18 | cmake -DCMAKE_PREFIX_PATH= -DCMAKE_INSTALL_PREFIX= -S aws-c-common -B aws-c-common/build 19 | cmake --build aws-c-common/build --target install 20 | 21 | git clone git@github.com:awslabs/aws-c-compression.git 22 | cmake -DCMAKE_PREFIX_PATH= -DCMAKE_INSTALL_PREFIX= -S aws-c-compression -B aws-c-compression/build 23 | cmake --build aws-c-compression/build --target install 24 | ``` 25 | 26 | ### Huffman 27 | 28 | The Huffman implemention in this library is designed around the concept of a 29 | generic "symbol coder" object, which defines how each symbol (value between 0 30 | and 255) is encoded and decoded. This object looks like this: 31 | ```c 32 | typedef struct aws_huffman_code (*aws_huffman_symbol_encoder)(uint8_t symbol, void *userdata); 33 | typedef uint8_t (*aws_huffman_symbol_decoder)(uint32_t bits, uint8_t *symbol, void *userdata); 34 | 35 | struct aws_huffman_symbol_coder { 36 | aws_huffman_symbol_encoder encode; 37 | aws_huffman_symbol_decoder decode; 38 | void *userdata; 39 | }; 40 | ``` 41 | These callbacks may be implemented manually, or you may use the included 42 | Huffman coder generator to generate one from a table definition file. The 43 | generator expects to be called with the following arguments: 44 | ```shell 45 | $ aws-c-compression-huffman-generator path/to/table.def path/to/generated.c coder_name 46 | ``` 47 | 48 | The table definition file should be in the following format: 49 | ```c 50 | /* sym bits code len */ 51 | HUFFMAN_CODE( 0, "1100101110", 0x32e, 10) 52 | HUFFMAN_CODE( 1, "1100101111", 0x32f, 10) 53 | /* ... */ 54 | ``` 55 | The HUFFMAN_CODE macro expects 4 arguments: 56 | * sym: the symbol value [0-255] 57 | * bits: the bits representing the symbol in string form 58 | * code: the bits representing the symbol in numeric form 59 | * len: the number of bits used to represent the symbol 60 | 61 | > #### Note 62 | > This file may also be `#include`d in the following way to generate a static 63 | > list of codes: 64 | > ```c 65 | > /* Provides the HUFFMAN_CODE macro */ 66 | > #include 67 | > 68 | > static struct huffman_test_code_point code_points[] = { 69 | > #include "test_huffman_static_table.def" 70 | > }; 71 | > ``` 72 | 73 | This will emit a c file which exports a function with the following signiture: 74 | ```c 75 | struct aws_huffman_symbol_coder *{coder_name}_get_coder(); 76 | ``` 77 | Note that this function does not allocate, but maintains a static instance of 78 | the coder. 79 | 80 | 81 | An example implementation of this file is provided in 82 | `tests/test_huffman_static_table.def`. 83 | 84 | 85 | To use the coder, forward declare that function, and pass the result as the 86 | second argument to `aws_huffman_encoder_init` and `aws_huffman_decoder_init`. 87 | ```c 88 | struct aws_huffman_encoder encoder; 89 | aws_huffman_encoder_init(&encoder, {coder_name}_get_coder()); 90 | 91 | struct aws_huffman_decoder decoder; 92 | aws_huffman_decoder_init(&decoder, {coder_name}_get_coder()) 93 | ``` 94 | 95 | #### Encoding 96 | ```c 97 | /** 98 | * Encode a symbol buffer into the output buffer. 99 | * 100 | * \param[in] encoder The encoder object to use 101 | * \param[in] to_encode The symbol buffer to encode 102 | * \param[in,out] length In: The length of to_decode. Out: The number of bytes read from to_encode 103 | * \param[in] output The buffer to write encoded bytes to 104 | * \param[in,out] output_size In: The size of output. Out: The number of bytes written to output 105 | * 106 | * \return AWS_OP_SUCCESS if encoding is successful, AWS_OP_ERR the code for the error that occured 107 | */ 108 | int aws_huffman_encode(struct aws_huffman_encoder *encoder, const char *to_encode, size_t *length, uint8_t *output, size_t *output_size); 109 | ``` 110 | The encoder is built to support partial encoding. This means that if there 111 | isn't enough space in `output`, the encoder will encode as much as possible, 112 | update `length` to indicate how much was consumed, `output_size` won't change, 113 | and `AWS_ERROR_SHORT_BUFFER` will be raised. `aws_huffman_encode` may then be 114 | called again like the following pseudo-code: 115 | ```c 116 | void encode_and_send(const char *to_encode, size_t size) { 117 | while (size > 0) { 118 | uint8_t output[some_chunk_size]; 119 | size_t output_size = sizeof(output); 120 | size_t bytes_read = size; 121 | aws_huffman_encode(encoder, to_encode, &bytes_read, output, &output_size); 122 | /* AWS_ERROR_SHORT_BUFFER was raised... */ 123 | send_output_to_someone_else(output, output_size); 124 | 125 | to_encode += bytes_read; 126 | size -= bytes_read; 127 | } 128 | /* Be sure to reset the encoder after use */ 129 | aws_huffman_encoder_reset(encoder); 130 | } 131 | ``` 132 | 133 | `aws_huffman_encoder` also has a `uint8_t` field called `eos_padding` that 134 | defines how any unwritten bits in the last byte of output are filled. The most 135 | significant bits will used. For example, if the last byte contains only 3 bits 136 | and `eos_padding` is `0b01010101`, `01010` will be appended to the byte. 137 | 138 | #### Decoding 139 | ```c 140 | /** 141 | * Decodes a byte buffer into the provided symbol array. 142 | * 143 | * \param[in] decoder The decoder object to use 144 | * \param[in] to_decode The encoded byte buffer to read from 145 | * \param[in,out] length In: The length of to_decode. Out: The number of bytes read from to_decode 146 | * \param[in] output The buffer to write decoded symbols to 147 | * \param[in,out] output_size In: The size of output. Out: The number of bytes written to output 148 | * 149 | * \return AWS_OP_SUCCESS if encoding is successful, AWS_OP_ERR the code for the error that occured 150 | */ 151 | int aws_huffman_decode(struct aws_huffman_decoder *decoder, const uint8_t *to_decode, size_t *length, char *output, size_t *output_size); 152 | ``` 153 | The decoder is built to support partial encoding. This means that if there 154 | isn't enough space in `output`, the decoder will decode as much as possible, 155 | update `length` to indicate how much was consumed, `output_size` won't change, 156 | and `AWS_ERROR_SHORT_BUFFER` will be raised. `aws_huffman_decode` may then be 157 | called again like the following pseudo-code: 158 | ```c 159 | void decode_and_send(const char *to_decode, size_t size) { 160 | while (size > 0) { 161 | uint8_t output[some_chunk_size]; 162 | size_t output_size = sizeof(output); 163 | size_t bytes_read = size; 164 | aws_huffman_decode(decoder, to_decode, &bytes_read, output, &output_size); 165 | /* AWS_ERROR_SHORT_BUFFER was raised... */ 166 | send_output_to_someone_else(output, output_size); 167 | 168 | to_decode += bytes_read; 169 | size -= bytes_read; 170 | } 171 | /* Be sure to reset the decoder after use */ 172 | aws_huffman_decoder_reset(decoder); 173 | } 174 | ``` 175 | 176 | Upon completion of a decode, the most significant bits of 177 | `decoder->working_bits` will contain the final bits of `to_decode` that could 178 | not match a symbol. This is useful for verifying the padding bits of a stream. 179 | For example, to validate that a stream ends in all 1's (like HPACK requires), 180 | you could do the following: 181 | ```c 182 | AWS_ASSERT(decoder->working_bits == UINT64_MAX << (64 - decoder->num_bits)); 183 | ``` 184 | -------------------------------------------------------------------------------- /builder.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-c-compression", 3 | "upstream": [ 4 | { "name": "aws-c-common" } 5 | ], 6 | "downstream": [ 7 | { "name": "aws-c-http" } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /cmake/aws-c-compression-config.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | find_dependency(aws-c-common) 4 | 5 | macro(aws_load_targets type) 6 | include(${CMAKE_CURRENT_LIST_DIR}/${type}/@PROJECT_NAME@-targets.cmake) 7 | endmacro() 8 | 9 | # try to load the lib follow BUILD_SHARED_LIBS. Fall back if not exist. 10 | if (BUILD_SHARED_LIBS) 11 | if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/shared") 12 | aws_load_targets(shared) 13 | else() 14 | aws_load_targets(static) 15 | endif() 16 | else() 17 | if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/static") 18 | aws_load_targets(static) 19 | else() 20 | aws_load_targets(shared) 21 | endif() 22 | endif() 23 | -------------------------------------------------------------------------------- /codebuild/common-posix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | CMAKE_ARGS="$@" 6 | BUILD_PATH="/tmp/builds" 7 | mkdir -p $BUILD_PATH 8 | INSTALL_PATH="$BUILD_PATH/install" 9 | mkdir -p $INSTALL_PATH 10 | 11 | function install_library { 12 | pushd $BUILD_PATH 13 | git clone https://github.com/awslabs/$1.git 14 | cd $1 15 | 16 | if [ -n "$2" ]; then 17 | git checkout $2 18 | fi 19 | 20 | cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH -DCMAKE_PREFIX_PATH=$INSTALL_PATH -DENABLE_SANITIZERS=ON $CMAKE_ARGS ./ 21 | make install 22 | 23 | popd 24 | } 25 | 26 | install_library aws-c-common 27 | 28 | if [ "$CODEBUILD_SRC_DIR" ]; then 29 | cd $CODEBUILD_SRC_DIR 30 | fi 31 | 32 | mkdir build 33 | cd build 34 | cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH -DCMAKE_PREFIX_PATH=$INSTALL_PATH -DENABLE_SANITIZERS=ON $CMAKE_ARGS ../ 35 | make 36 | 37 | LSAN_OPTIONS=verbosity=1:log_threads=1 ctest --output-on-failure 38 | -------------------------------------------------------------------------------- /codebuild/common-windows.bat: -------------------------------------------------------------------------------- 1 | 2 | set CMAKE_ARGS=%* 3 | 4 | set BUILDS_DIR=%TEMP%\builds 5 | set INSTALL_DIR=%BUILDS_DIR%\install 6 | mkdir %BUILDS_DIR% 7 | mkdir %INSTALL_DIR% 8 | 9 | CALL :install_library aws-c-common 10 | 11 | mkdir %BUILDS_DIR%\aws-c-compression-build 12 | cd %BUILDS_DIR%\aws-c-compression-build 13 | cmake %CMAKE_ARGS% -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%" -DCMAKE_PREFIX_PATH="%INSTALL_DIR%" %CODEBUILD_SRC_DIR% || goto error 14 | cmake --build . --config RelWithDebInfo || goto error 15 | ctest -V || goto error 16 | 17 | goto :EOF 18 | 19 | :install_library 20 | mkdir %BUILDS_DIR%\%~1-build 21 | cd %BUILDS_DIR%\%~1-build 22 | git clone https://github.com/awslabs/%~1.git 23 | cmake %CMAKE_ARGS% -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%" -DCMAKE_PREFIX_PATH="%INSTALL_DIR%" %~1 || goto error 24 | cmake --build . --target install --config RelWithDebInfo || goto error 25 | exit /b %errorlevel% 26 | 27 | :error 28 | echo Failed with error #%errorlevel%. 29 | exit /b %errorlevel% -------------------------------------------------------------------------------- /codebuild/linux-clang3-x64.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this buildspec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - sudo apt-get update -y 7 | - sudo apt-get update 8 | - sudo apt-get install clang-3.9 cmake3 clang-tidy-3.9 -y 9 | 10 | pre_build: 11 | commands: 12 | - export CC=clang-3.9 13 | build: 14 | commands: 15 | - echo Build started on `date` 16 | - ./codebuild/common-posix.sh -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 17 | - clang-tidy-3.9 -p=build **/*.c 18 | post_build: 19 | commands: 20 | - echo Build completed on `date` 21 | 22 | -------------------------------------------------------------------------------- /codebuild/linux-clang6-x64.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this buildspec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 7 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test 8 | - sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main" 9 | - sudo apt-get update -y 10 | - sudo apt-get install clang-6.0 cmake3 clang-tidy-6.0 clang-format-6.0 -y -f 11 | 12 | pre_build: 13 | commands: 14 | - export CC=clang-6.0 15 | - export CLANG_FORMAT=clang-format-6.0 16 | build: 17 | commands: 18 | - echo Build started on `date` 19 | - ./codebuild/common-posix.sh -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DENABLE_FUZZ_TESTS=ON 20 | - clang-tidy-6.0 -p=build **/*.c 21 | - ./format-check.sh 22 | post_build: 23 | commands: 24 | - echo Build completed on `date` 25 | 26 | -------------------------------------------------------------------------------- /codebuild/linux-gcc-4x-x64.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this build spec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - sudo apt-get update -y 7 | - sudo apt-get install gcc cmake3 -y 8 | pre_build: 9 | commands: 10 | - export CC=gcc 11 | build: 12 | commands: 13 | - echo Build started on `date` 14 | - ./codebuild/common-posix.sh 15 | post_build: 16 | commands: 17 | - echo Build completed on `date` 18 | 19 | -------------------------------------------------------------------------------- /codebuild/linux-gcc-4x-x86.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this build spec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - sudo apt-get update -y 7 | - sudo apt-get install gcc gcc-multilib cmake3 -y 8 | pre_build: 9 | commands: 10 | - export CC=gcc 11 | build: 12 | commands: 13 | - echo Build started on `date` 14 | - ./codebuild/common-posix.sh -DCMAKE_C_FLAGS="-m32" -DCMAKE_LINK_FLAGS="-m32" 15 | post_build: 16 | commands: 17 | - echo Build completed on `date` 18 | 19 | -------------------------------------------------------------------------------- /codebuild/linux-gcc-5x-x64.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this build spec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test 7 | - sudo apt-get update -y 8 | - sudo apt-get install gcc-5 cmake3 -y 9 | pre_build: 10 | commands: 11 | - export CC=gcc-5 12 | build: 13 | commands: 14 | - echo Build started on `date` 15 | - ./codebuild/common-posix.sh 16 | post_build: 17 | commands: 18 | - echo Build completed on `date` 19 | 20 | -------------------------------------------------------------------------------- /codebuild/linux-gcc-6x-x64.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this build spec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test 7 | - sudo apt-get update -y 8 | - sudo apt-get install gcc-6 cmake3 -y 9 | pre_build: 10 | commands: 11 | - export CC=gcc-6 12 | build: 13 | commands: 14 | - echo Build started on `date` 15 | - ./codebuild/common-posix.sh 16 | post_build: 17 | commands: 18 | - echo Build completed on `date` 19 | 20 | -------------------------------------------------------------------------------- /codebuild/linux-gcc-7x-x64.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | #this build spec assumes the ubuntu 14.04 trusty image 3 | phases: 4 | install: 5 | commands: 6 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test 7 | - sudo apt-get update -y 8 | - sudo apt-get install gcc-7 cmake3 -y 9 | pre_build: 10 | commands: 11 | - export CC=gcc-7 12 | build: 13 | commands: 14 | - echo Build started on `date` 15 | - ./codebuild/common-posix.sh 16 | post_build: 17 | commands: 18 | - echo Build completed on `date` 19 | 20 | -------------------------------------------------------------------------------- /codebuild/windows-msvc-2015-x86.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | 3 | phases: 4 | build: 5 | commands: 6 | - .\codebuild\common-windows.bat -G "Visual Studio 14 2015" 7 | 8 | -------------------------------------------------------------------------------- /codebuild/windows-msvc-2015.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | 3 | phases: 4 | build: 5 | commands: 6 | - .\codebuild\common-windows.bat -G "Visual Studio 14 2015 Win64" 7 | 8 | -------------------------------------------------------------------------------- /codebuild/windows-msvc-2017.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | 3 | phases: 4 | build: 5 | commands: 6 | - .\codebuild\common-windows.bat -G "Visual Studio 15 2017 Win64" 7 | 8 | -------------------------------------------------------------------------------- /format-check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import os 4 | from pathlib import Path 5 | import re 6 | from subprocess import list2cmdline, run 7 | from tempfile import NamedTemporaryFile 8 | 9 | CLANG_FORMAT_VERSION = '18.1.6' 10 | 11 | INCLUDE_REGEX = re.compile( 12 | r'^(include|source|tests|verification)/.*\.(c|h|inl)$') 13 | EXCLUDE_REGEX = re.compile(r'^$') 14 | 15 | arg_parser = argparse.ArgumentParser(description="Check with clang-format") 16 | arg_parser.add_argument('-i', '--inplace-edit', action='store_true', 17 | help="Edit files inplace") 18 | args = arg_parser.parse_args() 19 | 20 | os.chdir(Path(__file__).parent) 21 | 22 | # create file containing list of all files to format 23 | filepaths_file = NamedTemporaryFile(delete=False) 24 | for dirpath, dirnames, filenames in os.walk('.'): 25 | for filename in filenames: 26 | # our regexes expect filepath to use forward slash 27 | filepath = Path(dirpath, filename).as_posix() 28 | if not INCLUDE_REGEX.match(filepath): 29 | continue 30 | if EXCLUDE_REGEX.match(filepath): 31 | continue 32 | 33 | filepaths_file.write(f"{filepath}\n".encode()) 34 | filepaths_file.close() 35 | 36 | # use pipx to run clang-format from PyPI 37 | # this is a simple way to run the same clang-format version regardless of OS 38 | cmd = ['pipx', 'run', f'clang-format=={CLANG_FORMAT_VERSION}', 39 | f'--files={filepaths_file.name}'] 40 | if args.inplace_edit: 41 | cmd += ['-i'] 42 | else: 43 | cmd += ['--Werror', '--dry-run'] 44 | 45 | print(f"{Path.cwd()}$ {list2cmdline(cmd)}") 46 | if run(cmd).returncode: 47 | exit(1) 48 | -------------------------------------------------------------------------------- /include/aws/compression/compression.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_COMPRESSION_COMPRESSION_H 2 | #define AWS_COMPRESSION_COMPRESSION_H 3 | 4 | /** 5 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 6 | * SPDX-License-Identifier: Apache-2.0. 7 | */ 8 | 9 | #include 10 | 11 | #include 12 | 13 | AWS_PUSH_SANE_WARNING_LEVEL 14 | 15 | #define AWS_C_COMPRESSION_PACKAGE_ID 3 16 | 17 | enum aws_compression_error { 18 | AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL = AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_COMPRESSION_PACKAGE_ID), 19 | 20 | AWS_ERROR_END_COMPRESSION_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_COMPRESSION_PACKAGE_ID) 21 | }; 22 | 23 | AWS_EXTERN_C_BEGIN 24 | 25 | /** 26 | * Initializes internal datastructures used by aws-c-compression. 27 | * Must be called before using any functionality in aws-c-compression. 28 | */ 29 | AWS_COMPRESSION_API 30 | void aws_compression_library_init(struct aws_allocator *alloc); 31 | 32 | /** 33 | * Clean up internal datastructures used by aws-c-compression. 34 | * Must not be called until application is done using functionality in aws-c-compression. 35 | */ 36 | AWS_COMPRESSION_API 37 | void aws_compression_library_clean_up(void); 38 | 39 | AWS_EXTERN_C_END 40 | AWS_POP_SANE_WARNING_LEVEL 41 | 42 | #endif /* AWS_COMPRESSION_COMPRESSION_H */ 43 | -------------------------------------------------------------------------------- /include/aws/compression/exports.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_COMPRESSION_EXPORTS_H 2 | #define AWS_COMPRESSION_EXPORTS_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #if defined(AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined(_WIN32) 8 | # ifdef AWS_COMPRESSION_USE_IMPORT_EXPORT 9 | # ifdef AWS_COMPRESSION_EXPORTS 10 | # define AWS_COMPRESSION_API __declspec(dllexport) 11 | # else 12 | # define AWS_COMPRESSION_API __declspec(dllimport) 13 | # endif /* AWS_COMPRESSION_EXPORTS */ 14 | # else 15 | # define AWS_COMPRESSION_API 16 | # endif /* AWS_COMPRESSION_USE_IMPORT_EXPORT */ 17 | 18 | #else /* defined (AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) */ 19 | # if defined(AWS_COMPRESSION_USE_IMPORT_EXPORT) && defined(AWS_COMPRESSION_EXPORTS) 20 | # define AWS_COMPRESSION_API __attribute__((visibility("default"))) 21 | # else 22 | # define AWS_COMPRESSION_API 23 | # endif 24 | 25 | #endif /* defined (AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) */ 26 | 27 | #endif /* AWS_COMPRESSION_EXPORTS_H */ 28 | -------------------------------------------------------------------------------- /include/aws/compression/huffman.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_COMPRESSION_HUFFMAN_H 2 | #define AWS_COMPRESSION_HUFFMAN_H 3 | 4 | /** 5 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 6 | * SPDX-License-Identifier: Apache-2.0. 7 | */ 8 | 9 | #include 10 | 11 | #include 12 | 13 | AWS_PUSH_SANE_WARNING_LEVEL 14 | 15 | /** 16 | * Represents an encoded code 17 | */ 18 | struct aws_huffman_code { 19 | /** 20 | * The value of the code 21 | * \note The pattern is stored in the least significant bits 22 | */ 23 | uint32_t pattern; 24 | /** The number of bits in pattern to use */ 25 | uint8_t num_bits; 26 | }; 27 | 28 | /** 29 | * Function used to encode a single symbol to an aws_huffman_code 30 | * 31 | * \param[in] symbol The symbol to encode 32 | * \param[in] userdata Optional userdata (aws_huffman_symbol_coder.userdata) 33 | * 34 | * \returns The code representing the symbol. If this symbol is not recognized, 35 | * return a code with num_bits set to 0. 36 | */ 37 | typedef struct aws_huffman_code(aws_huffman_symbol_encoder_fn)(uint8_t symbol, void *userdata); 38 | /** 39 | * Function used to decode a code into a symbol 40 | * 41 | * \param[in] bits The bits to attept to decode a symbol from 42 | * \param[out] symbol The symbol found. Do not write to if no valid symbol 43 | * found \param[in] userdata Optional userdata 44 | * (aws_huffman_symbol_coder.userdata) 45 | * 46 | * \returns The number of bits read from bits 47 | */ 48 | typedef uint8_t(aws_huffman_symbol_decoder_fn)(uint32_t bits, uint8_t *symbol, void *userdata); 49 | 50 | /** 51 | * Structure used to define how symbols are encoded and decoded 52 | */ 53 | struct aws_huffman_symbol_coder { 54 | aws_huffman_symbol_encoder_fn *encode; 55 | aws_huffman_symbol_decoder_fn *decode; 56 | void *userdata; 57 | }; 58 | 59 | /** 60 | * Structure used for persistent encoding. 61 | * Allows for reading from or writing to incomplete buffers. 62 | */ 63 | struct aws_huffman_encoder { 64 | /* Params */ 65 | struct aws_huffman_symbol_coder *coder; 66 | uint8_t eos_padding; 67 | 68 | /* State */ 69 | struct aws_huffman_code overflow_bits; 70 | }; 71 | 72 | /** 73 | * Structure used for persistent decoding. 74 | * Allows for reading from or writing to incomplete buffers. 75 | */ 76 | struct aws_huffman_decoder { 77 | /* Param */ 78 | struct aws_huffman_symbol_coder *coder; 79 | bool allow_growth; 80 | 81 | /* State */ 82 | uint64_t working_bits; 83 | uint8_t num_bits; 84 | }; 85 | 86 | AWS_EXTERN_C_BEGIN 87 | 88 | /** 89 | * Initialize a encoder object with a symbol coder. 90 | */ 91 | AWS_COMPRESSION_API 92 | void aws_huffman_encoder_init(struct aws_huffman_encoder *encoder, struct aws_huffman_symbol_coder *coder); 93 | 94 | /** 95 | * Resets a decoder for use with a new binary stream 96 | */ 97 | AWS_COMPRESSION_API 98 | void aws_huffman_encoder_reset(struct aws_huffman_encoder *encoder); 99 | 100 | /** 101 | * Initialize a decoder object with a symbol coder. 102 | */ 103 | AWS_COMPRESSION_API 104 | void aws_huffman_decoder_init(struct aws_huffman_decoder *decoder, struct aws_huffman_symbol_coder *coder); 105 | 106 | /** 107 | * Resets a decoder for use with a new binary stream 108 | */ 109 | AWS_COMPRESSION_API 110 | void aws_huffman_decoder_reset(struct aws_huffman_decoder *decoder); 111 | 112 | /** 113 | * Get the byte length of to_encode post-encoding. 114 | * 115 | * \param[in] encoder The encoder object to use 116 | * \param[in] to_encode The symbol buffer to encode 117 | * 118 | * \return The length of the encoded string. 119 | */ 120 | AWS_COMPRESSION_API 121 | size_t aws_huffman_get_encoded_length(struct aws_huffman_encoder *encoder, struct aws_byte_cursor to_encode); 122 | 123 | /** 124 | * Encode a symbol buffer into the output buffer. 125 | * 126 | * \param[in] encoder The encoder object to use 127 | * \param[in] to_encode The symbol buffer to encode 128 | * \param[in] output The buffer to write encoded bytes to 129 | * 130 | * \return AWS_OP_SUCCESS if encoding is successful, AWS_OP_ERR otherwise 131 | */ 132 | AWS_COMPRESSION_API 133 | int aws_huffman_encode( 134 | struct aws_huffman_encoder *encoder, 135 | struct aws_byte_cursor *to_encode, 136 | struct aws_byte_buf *output); 137 | 138 | /** 139 | * Decodes a byte buffer into the provided symbol array. 140 | * 141 | * \param[in] decoder The decoder object to use 142 | * \param[in] to_decode The encoded byte buffer to read from 143 | * \param[in] output The buffer to write decoded symbols to. 144 | * If decoder is set to allow growth, capacity will be increased when necessary. 145 | * 146 | * \return AWS_OP_SUCCESS if encoding is successful, AWS_OP_ERR otherwise 147 | */ 148 | AWS_COMPRESSION_API 149 | int aws_huffman_decode( 150 | struct aws_huffman_decoder *decoder, 151 | struct aws_byte_cursor *to_decode, 152 | struct aws_byte_buf *output); 153 | 154 | /** 155 | * Set whether or not to increase capacity when the output buffer fills up while decoding. 156 | * This is false by default. 157 | */ 158 | AWS_COMPRESSION_API 159 | void aws_huffman_decoder_allow_growth(struct aws_huffman_decoder *decoder, bool allow_growth); 160 | 161 | AWS_EXTERN_C_END 162 | AWS_POP_SANE_WARNING_LEVEL 163 | 164 | #endif /* AWS_COMPRESSION_HUFFMAN_H */ 165 | -------------------------------------------------------------------------------- /include/aws/compression/private/huffman_testing.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_COMPRESSION_HUFFMAN_TESTING_H 2 | #define AWS_COMPRESSION_HUFFMAN_TESTING_H 3 | 4 | /** 5 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 6 | * SPDX-License-Identifier: Apache-2.0. 7 | */ 8 | 9 | #include 10 | 11 | /** 12 | * The intended use of file is to allow testing of huffman character coders. 13 | * By doing the following, you can ensure the output of encoders decoders are 14 | * correct: 15 | * 16 | * \code{c} 17 | * static struct huffman_test_code_point code_points[] = { 18 | * #include "test_huffman_static_table.def" 19 | * }; 20 | * \endcode 21 | * 22 | * You may then iterate over each code point in the array, and test the 23 | * following (pseudo-code): 24 | * 25 | * \code{c} for (cp in code_points) { 26 | * AWS_ASSERT(my_coder->encode(cp.symbol) == cp.pattern); 27 | * AWS_ASSERT(my_coder->decode(cp.pattern) == cp.symbol); 28 | * } 29 | * \endcode 30 | */ 31 | 32 | /** 33 | * Structure containing all relevant information about a code point 34 | */ 35 | struct huffman_test_code_point { 36 | uint8_t symbol; 37 | struct aws_huffman_code code; 38 | }; 39 | 40 | /** 41 | * Macro to be used when including a table def file, populates an array of 42 | * huffman_test_code_points 43 | */ 44 | #define HUFFMAN_CODE(psymbol, pbit_string, pbit_pattern, pnum_bits) \ 45 | { \ 46 | .symbol = (psymbol), \ 47 | .code = \ 48 | { \ 49 | .pattern = (pbit_pattern), \ 50 | .num_bits = (pnum_bits), \ 51 | }, \ 52 | }, 53 | 54 | /** 55 | * Function to test a huffman coder to ensure the transitive property applies 56 | * (input == decode(incode(input))) 57 | * 58 | * \param[in] coder The symbol coder to test 59 | * \param[in] input The buffer to test 60 | * \param[in] size The size of input 61 | * \param[in] encoded_size The length of the encoded buffer. Pass 0 to skip check. 62 | * \param[out] error_string In case of failure, the error string to report 63 | * 64 | * \return AWS_OP_SUCCESS on success, AWS_OP_FAILURE on failure (error_string 65 | * will be set) 66 | */ 67 | AWS_COMPRESSION_API 68 | int huffman_test_transitive( 69 | struct aws_huffman_symbol_coder *coder, 70 | const char *input, 71 | size_t size, 72 | size_t encoded_size, 73 | const char **error_string); 74 | 75 | /** 76 | * Function to test a huffman coder to ensure the transitive property applies 77 | * when doing partial encodes/decodes (input == decode(incode(input))) 78 | * 79 | * \param[in] coder The symbol coder to test 80 | * \param[in] input The buffer to test 81 | * \param[in] size The size of input 82 | * \param[in] encoded_size The length of the encoded buffer. Pass 0 to skip check. 83 | * \param[in] output_chunk_size The amount of output to write at once 84 | * \param[out] error_string In case of failure, the error string to 85 | * report 86 | * 87 | * \return AWS_OP_SUCCESS on success, AWS_OP_FAILURE on failure (error_string 88 | * will be set) 89 | */ 90 | AWS_COMPRESSION_API 91 | int huffman_test_transitive_chunked( 92 | struct aws_huffman_symbol_coder *coder, 93 | const char *input, 94 | size_t size, 95 | size_t encoded_size, 96 | size_t output_chunk_size, 97 | const char **error_string); 98 | 99 | #endif /* AWS_COMPRESSION_HUFFMAN_TESTING_H */ 100 | -------------------------------------------------------------------------------- /source/compression.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | #define DEFINE_ERROR_INFO(CODE, STR) \ 9 | [(CODE) - AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_COMPRESSION_PACKAGE_ID)] = \ 10 | AWS_DEFINE_ERROR_INFO(CODE, STR, "aws-c-compression") 11 | 12 | /* clang-format off */ 13 | static struct aws_error_info s_errors[] = { 14 | DEFINE_ERROR_INFO( 15 | AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL, 16 | "Compression encountered an unknown symbol."), 17 | }; 18 | /* clang-format on */ 19 | 20 | static struct aws_error_info_list s_error_list = { 21 | .error_list = s_errors, 22 | .count = AWS_ARRAY_SIZE(s_errors), 23 | }; 24 | 25 | static bool s_library_initialized = false; 26 | void aws_compression_library_init(struct aws_allocator *alloc) { 27 | if (s_library_initialized) { 28 | return; 29 | } 30 | s_library_initialized = true; 31 | 32 | aws_common_library_init(alloc); 33 | aws_register_error_info(&s_error_list); 34 | } 35 | 36 | void aws_compression_library_clean_up(void) { 37 | if (!s_library_initialized) { 38 | return; 39 | } 40 | s_library_initialized = false; 41 | 42 | aws_unregister_error_info(&s_error_list); 43 | aws_common_library_clean_up(); 44 | } 45 | -------------------------------------------------------------------------------- /source/huffman.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | #define BITSIZEOF(val) (sizeof(val) * 8) 9 | 10 | static uint8_t MAX_PATTERN_BITS = BITSIZEOF(((struct aws_huffman_code *)0)->pattern); 11 | 12 | void aws_huffman_encoder_init(struct aws_huffman_encoder *encoder, struct aws_huffman_symbol_coder *coder) { 13 | 14 | AWS_ASSERT(encoder); 15 | AWS_ASSERT(coder); 16 | 17 | AWS_ZERO_STRUCT(*encoder); 18 | encoder->coder = coder; 19 | encoder->eos_padding = UINT8_MAX; 20 | } 21 | 22 | void aws_huffman_encoder_reset(struct aws_huffman_encoder *encoder) { 23 | 24 | AWS_ASSERT(encoder); 25 | 26 | AWS_ZERO_STRUCT(encoder->overflow_bits); 27 | } 28 | 29 | void aws_huffman_decoder_init(struct aws_huffman_decoder *decoder, struct aws_huffman_symbol_coder *coder) { 30 | 31 | AWS_ASSERT(decoder); 32 | AWS_ASSERT(coder); 33 | 34 | AWS_ZERO_STRUCT(*decoder); 35 | decoder->coder = coder; 36 | } 37 | 38 | void aws_huffman_decoder_reset(struct aws_huffman_decoder *decoder) { 39 | 40 | decoder->working_bits = 0; 41 | decoder->num_bits = 0; 42 | } 43 | 44 | void aws_huffman_decoder_allow_growth(struct aws_huffman_decoder *decoder, bool allow_growth) { 45 | decoder->allow_growth = allow_growth; 46 | } 47 | 48 | /* Much of encode is written in a helper function, 49 | so this struct helps avoid passing all the parameters through by hand */ 50 | struct encoder_state { 51 | struct aws_huffman_encoder *encoder; 52 | struct aws_byte_buf *output_buf; 53 | uint8_t working; 54 | uint8_t bit_pos; 55 | }; 56 | 57 | /* Helper function to write a single bit_pattern to memory (or working_bits if 58 | * out of buffer space) */ 59 | static int encode_write_bit_pattern(struct encoder_state *state, struct aws_huffman_code bit_pattern) { 60 | AWS_PRECONDITION(state->output_buf->len < state->output_buf->capacity); 61 | 62 | if (bit_pattern.num_bits == 0) { 63 | return aws_raise_error(AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL); 64 | } 65 | 66 | uint8_t bits_to_write = bit_pattern.num_bits; 67 | while (bits_to_write > 0) { 68 | uint8_t bits_for_current = bits_to_write > state->bit_pos ? state->bit_pos : bits_to_write; 69 | /* Chop off the top 0s and bits that have already been read */ 70 | uint8_t bits_to_cut = 71 | (BITSIZEOF(bit_pattern.pattern) - bit_pattern.num_bits) + (bit_pattern.num_bits - bits_to_write); 72 | 73 | /* Write the appropiate number of bits to this byte 74 | Shift to the left to cut any unneeded bits 75 | Shift to the right to position the bits correctly */ 76 | state->working |= (bit_pattern.pattern << bits_to_cut) >> (MAX_PATTERN_BITS - state->bit_pos); 77 | 78 | bits_to_write -= bits_for_current; 79 | state->bit_pos -= bits_for_current; 80 | 81 | if (state->bit_pos == 0) { 82 | /* Save the whole byte */ 83 | aws_byte_buf_write_u8(state->output_buf, state->working); 84 | 85 | state->bit_pos = 8; 86 | state->working = 0; 87 | 88 | if (state->output_buf->len == state->output_buf->capacity) { 89 | state->encoder->overflow_bits.num_bits = bits_to_write; 90 | 91 | if (bits_to_write) { 92 | /* If buffer is full and there are remaining bits, save them to overflow and return */ 93 | bits_to_cut += bits_for_current; 94 | 95 | state->encoder->overflow_bits.pattern = 96 | (bit_pattern.pattern << bits_to_cut) >> (MAX_PATTERN_BITS - bits_to_write); 97 | 98 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 99 | } 100 | } 101 | } 102 | } 103 | 104 | return AWS_OP_SUCCESS; 105 | } 106 | 107 | size_t aws_huffman_get_encoded_length(struct aws_huffman_encoder *encoder, struct aws_byte_cursor to_encode) { 108 | 109 | AWS_PRECONDITION(encoder); 110 | AWS_PRECONDITION(aws_byte_cursor_is_valid(&to_encode)); 111 | 112 | size_t num_bits = 0; 113 | 114 | while (to_encode.len) { 115 | uint8_t new_byte = 0; 116 | aws_byte_cursor_read_u8(&to_encode, &new_byte); 117 | struct aws_huffman_code code_point = encoder->coder->encode(new_byte, encoder->coder->userdata); 118 | num_bits += code_point.num_bits; 119 | } 120 | 121 | size_t length = num_bits / 8; 122 | 123 | /* Round up */ 124 | if (num_bits % 8) { 125 | ++length; 126 | } 127 | 128 | return length; 129 | } 130 | 131 | int aws_huffman_encode( 132 | struct aws_huffman_encoder *encoder, 133 | struct aws_byte_cursor *to_encode, 134 | struct aws_byte_buf *output) { 135 | 136 | AWS_ASSERT(encoder); 137 | AWS_ASSERT(encoder->coder); 138 | AWS_ASSERT(to_encode); 139 | AWS_ASSERT(output); 140 | 141 | struct encoder_state state = { 142 | .working = 0, 143 | .bit_pos = 8, 144 | }; 145 | state.encoder = encoder; 146 | state.output_buf = output; 147 | 148 | /* Write any bits leftover from previous invocation */ 149 | if (encoder->overflow_bits.num_bits) { 150 | if (output->len == output->capacity) { 151 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 152 | } 153 | 154 | if (encode_write_bit_pattern(&state, encoder->overflow_bits)) { 155 | return AWS_OP_ERR; 156 | } 157 | 158 | encoder->overflow_bits.num_bits = 0; 159 | } 160 | 161 | while (to_encode->len) { 162 | if (output->len == output->capacity) { 163 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 164 | } 165 | 166 | uint8_t new_byte = 0; 167 | aws_byte_cursor_read_u8(to_encode, &new_byte); 168 | struct aws_huffman_code code_point = encoder->coder->encode(new_byte, encoder->coder->userdata); 169 | 170 | if (encode_write_bit_pattern(&state, code_point)) { 171 | return AWS_OP_ERR; 172 | } 173 | } 174 | 175 | /* The following code only runs when the buffer has written successfully */ 176 | 177 | /* If whole buffer processed, write EOS */ 178 | if (state.bit_pos != 8) { 179 | struct aws_huffman_code eos_cp; 180 | eos_cp.pattern = encoder->eos_padding; 181 | eos_cp.num_bits = state.bit_pos; 182 | encode_write_bit_pattern(&state, eos_cp); 183 | AWS_ASSERT(state.bit_pos == 8); 184 | } 185 | 186 | return AWS_OP_SUCCESS; 187 | } 188 | 189 | /* Decode's reading is written in a helper function, 190 | so this struct helps avoid passing all the parameters through by hand */ 191 | struct huffman_decoder_state { 192 | struct aws_huffman_decoder *decoder; 193 | struct aws_byte_cursor *input_cursor; 194 | }; 195 | 196 | static void decode_fill_working_bits(struct huffman_decoder_state *state) { 197 | 198 | /* Read from bytes in the buffer until there are enough bytes to process */ 199 | while (state->decoder->num_bits < MAX_PATTERN_BITS && state->input_cursor->len) { 200 | 201 | /* Read the appropiate number of bits from this byte */ 202 | uint8_t new_byte = 0; 203 | aws_byte_cursor_read_u8(state->input_cursor, &new_byte); 204 | 205 | uint64_t positioned = ((uint64_t)new_byte) 206 | << (BITSIZEOF(state->decoder->working_bits) - 8 - state->decoder->num_bits); 207 | state->decoder->working_bits |= positioned; 208 | 209 | state->decoder->num_bits += 8; 210 | } 211 | } 212 | 213 | int aws_huffman_decode( 214 | struct aws_huffman_decoder *decoder, 215 | struct aws_byte_cursor *to_decode, 216 | struct aws_byte_buf *output) { 217 | 218 | AWS_ASSERT(decoder); 219 | AWS_ASSERT(decoder->coder); 220 | AWS_ASSERT(to_decode); 221 | AWS_ASSERT(output); 222 | 223 | struct huffman_decoder_state state; 224 | state.decoder = decoder; 225 | state.input_cursor = to_decode; 226 | 227 | /* Measures how much of the input was read */ 228 | size_t bits_left = decoder->num_bits + to_decode->len * 8; 229 | 230 | while (1) { 231 | 232 | decode_fill_working_bits(&state); 233 | 234 | uint8_t symbol; 235 | uint8_t bits_read = decoder->coder->decode( 236 | (uint32_t)(decoder->working_bits >> (BITSIZEOF(decoder->working_bits) - MAX_PATTERN_BITS)), 237 | &symbol, 238 | decoder->coder->userdata); 239 | 240 | if (bits_read == 0) { 241 | if (bits_left < MAX_PATTERN_BITS) { 242 | /* More input is needed to continue */ 243 | return AWS_OP_SUCCESS; 244 | } 245 | /* Unknown symbol found */ 246 | return aws_raise_error(AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL); 247 | } 248 | if (bits_read > bits_left) { 249 | /* Check if the buffer has been overrun. 250 | Note: because of the check in decode_fill_working_bits, 251 | the buffer won't actually overrun, instead there will 252 | be 0's in the bottom of working_bits. */ 253 | 254 | return AWS_OP_SUCCESS; 255 | } 256 | 257 | if (output->len == output->capacity) { 258 | /* Check if we've hit the end of the output buffer. 259 | * Grow buffer, or raise error, depending on settings */ 260 | if (decoder->allow_growth) { 261 | /* Double the capacity */ 262 | if (aws_byte_buf_reserve_relative(output, output->capacity)) { 263 | return AWS_OP_ERR; 264 | } 265 | } else { 266 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 267 | } 268 | } 269 | 270 | bits_left -= bits_read; 271 | decoder->working_bits <<= bits_read; 272 | decoder->num_bits -= bits_read; 273 | 274 | /* Store the found symbol */ 275 | aws_byte_buf_write_u8(output, symbol); 276 | 277 | /* Successfully decoded whole buffer */ 278 | if (bits_left == 0) { 279 | return AWS_OP_SUCCESS; 280 | } 281 | } 282 | 283 | /* This case is unreachable */ 284 | AWS_ASSERT(0); 285 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 286 | } 287 | -------------------------------------------------------------------------------- /source/huffman_generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB GENERATIR_SRC "generator.c") 2 | 3 | set(GENERATOR_BINARY_NAME ${CMAKE_PROJECT_NAME}-huffman-generator) 4 | 5 | add_executable(${GENERATOR_BINARY_NAME} ${GENERATIR_SRC}) 6 | aws_set_common_properties(${GENERATOR_BINARY_NAME}) 7 | aws_add_sanitizers(${GENERATOR_BINARY_NAME}) 8 | target_include_directories(${GENERATOR_BINARY_NAME} PRIVATE 9 | ${PROJECT_SOURCE_DIR}/include 10 | ) 11 | 12 | if (MSVC) 13 | target_compile_definitions(${GENERATOR_BINARY_NAME} PRIVATE "-D_CRT_SECURE_NO_WARNINGS") 14 | endif () 15 | 16 | 17 | install( 18 | TARGETS ${GENERATOR_BINARY_NAME} 19 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 20 | ) 21 | -------------------------------------------------------------------------------- /source/huffman_generator/generator.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include /* NOLINT(fuchsia-restrict-system-includes) */ 7 | #include 8 | #include /* NOLINT(fuchsia-restrict-system-includes) */ 9 | #include 10 | #include 11 | #include 12 | 13 | struct huffman_code { 14 | uint8_t num_bits; 15 | uint32_t bits; 16 | }; 17 | 18 | struct huffman_code_point { 19 | uint8_t symbol; 20 | struct huffman_code code; 21 | }; 22 | 23 | enum { num_code_points = 256 }; 24 | static struct huffman_code_point code_points[num_code_points]; 25 | 26 | static size_t skip_whitespace(const char *str) { 27 | size_t offset = 0; 28 | while (str[offset] == ' ' || str[offset] == '\t') { 29 | ++offset; 30 | } 31 | return offset; 32 | } 33 | 34 | static size_t read_past_comma(const char *str) { 35 | size_t offset = 0; 36 | while (str[offset] != ',') { 37 | ++offset; 38 | } 39 | return offset + 1; 40 | } 41 | 42 | int read_code_points(const char *input_path) { 43 | 44 | memset(code_points, 0, sizeof(code_points)); 45 | FILE *file = fopen(input_path, "r"); 46 | if (!file) { 47 | printf("Failed to open file '%s' for read.", input_path); 48 | return 1; 49 | } 50 | 51 | static const char HC_KEYWORD[] = "HUFFMAN_CODE"; 52 | static const size_t HC_KW_LEN = sizeof(HC_KEYWORD) - 1; 53 | 54 | int is_comment = 0; 55 | char line[120]; 56 | while (fgets(line, sizeof(line), file) != NULL) { 57 | const size_t line_length = strlen(line); 58 | 59 | if (line[0] == '#') { 60 | /* Ignore preprocessor directives */ 61 | continue; 62 | } 63 | for (size_t i = 0; i < line_length - 1; ++i) { 64 | if (!is_comment) { 65 | if (line[i] == '/' && line[i + 1] == '*') { 66 | is_comment = 1; 67 | } else if (strncmp(&line[i], HC_KEYWORD, HC_KW_LEN) == 0) { 68 | /* Found code, parse it */ 69 | 70 | /* Skip macro */ 71 | const char *current_char = &line[i + HC_KW_LEN]; 72 | current_char += skip_whitespace(current_char); 73 | /* Skip ( */ 74 | assert(*current_char == '('); 75 | ++current_char; 76 | 77 | /* Parse symbol */ 78 | uint8_t symbol = (uint8_t)atoi(current_char); 79 | struct huffman_code_point *code_point = &code_points[symbol]; 80 | 81 | assert(!code_point->symbol && "Symbol already found!"); 82 | 83 | code_point->symbol = symbol; 84 | 85 | current_char += read_past_comma(current_char); 86 | /* Skip the binary string form */ 87 | current_char += read_past_comma(current_char); 88 | 89 | /* Parse bits */ 90 | code_point->code.bits = (uint32_t)strtol(current_char, NULL, 16); 91 | 92 | current_char += read_past_comma(current_char); 93 | 94 | code_point->code.num_bits = (uint8_t)atoi(current_char); 95 | } 96 | } else if (line[i] == '*' && line[i + 1] == '/') { 97 | is_comment = 0; 98 | } 99 | } 100 | } 101 | 102 | fclose(file); 103 | 104 | return 0; 105 | } 106 | 107 | void code_write(struct huffman_code *code, FILE *file) { 108 | 109 | for (int bit_idx = code->num_bits - 1; bit_idx >= 0; --bit_idx) { 110 | char bit = ((code->bits >> bit_idx) & 0x1) ? '1' : '0'; 111 | fprintf(file, "%c", bit); 112 | } 113 | } 114 | 115 | struct huffman_node { 116 | struct huffman_code_point *value; 117 | 118 | struct huffman_code code; 119 | struct huffman_node *children[2]; 120 | }; 121 | 122 | struct huffman_node *huffman_node_new(struct huffman_code code) { 123 | 124 | struct huffman_node *node = malloc(sizeof(struct huffman_node)); 125 | memset(node, 0, sizeof(struct huffman_node)); 126 | node->code = code; 127 | return node; 128 | } 129 | 130 | struct huffman_node *huffman_node_new_value(struct huffman_code_point *value) { 131 | 132 | struct huffman_node *node = malloc(sizeof(struct huffman_node)); 133 | memset(node, 0, sizeof(struct huffman_node)); 134 | node->value = value; 135 | node->code = value->code; 136 | return node; 137 | } 138 | 139 | /* note: Does not actually free the memory. 140 | This is useful so this function may be called on the tree root. */ 141 | void huffman_node_clean_up(struct huffman_node *node) { 142 | 143 | for (int i = 0; i < 2; ++i) { 144 | if (node->children[i]) { 145 | huffman_node_clean_up(node->children[i]); 146 | free(node->children[i]); 147 | } 148 | } 149 | 150 | memset(node, 0, sizeof(struct huffman_node)); 151 | } 152 | 153 | /* This function writes what to do if the pattern for node is a match */ 154 | void huffman_node_write_decode_handle_value(struct huffman_node *node, FILE *file) { 155 | 156 | if (!node) { 157 | /* Invalid node, return 0 */ 158 | fprintf(file, " return 0; /* invalid node */\n"); 159 | } else if (node->value) { 160 | /* Attempt to inline value return */ 161 | fprintf( 162 | file, 163 | " *symbol = %u;\n" 164 | " return %u;\n", 165 | node->value->symbol, 166 | node->value->code.num_bits); 167 | } else { 168 | /* Otherwise go to branch check */ 169 | fprintf(file, " goto node_"); 170 | code_write(&node->code, file); 171 | fprintf(file, ";\n"); 172 | } 173 | } 174 | 175 | void huffman_node_write_decode(struct huffman_node *node, FILE *file, uint8_t current_bit) { 176 | 177 | /* Value nodes should have been inlined into parent branch checks */ 178 | assert(!node->value); 179 | assert(node->children[0] || node->children[1]); 180 | 181 | static int write_label = 0; 182 | 183 | if (write_label) { 184 | /* Write this node's label after the first run */ 185 | fprintf(file, "node_"); 186 | code_write(&node->code, file); 187 | fprintf(file, ":\n"); 188 | } 189 | 190 | write_label = 1; 191 | 192 | /* Check 1 bit pattern */ 193 | uint32_t single_bit_mask = (uint32_t)(1ull << (31 - current_bit)); 194 | uint32_t left_aligned_pattern = ((node->code.bits << 1) + 1) << (31 - node->code.num_bits); 195 | uint32_t check_pattern = left_aligned_pattern & single_bit_mask; 196 | fprintf(file, " if (bits & 0x%x) {\n", check_pattern); 197 | 198 | huffman_node_write_decode_handle_value(node->children[1], file); 199 | 200 | fprintf(file, " } else {\n"); 201 | 202 | /* Child 0 is valid, go there */ 203 | huffman_node_write_decode_handle_value(node->children[0], file); 204 | 205 | fprintf(file, " }\n\n"); 206 | 207 | /* Recursively write child nodes */ 208 | for (uint8_t i = 0; i < 2; ++i) { 209 | struct huffman_node *child = node->children[i]; 210 | if (child && !child->value) { 211 | huffman_node_write_decode(child, file, current_bit + 1); 212 | } 213 | } 214 | } 215 | 216 | int main(int argc, char *argv[]) { 217 | 218 | if (argc != 4) { 219 | fprintf( 220 | stderr, 221 | "generator expects 3 arguments: [input file] [output file] " 222 | "[encoding name]\n" 223 | "A function of the following signature will be exported:\n" 224 | "struct aws_huffman_symbol_coder *[encoding name]_get_coder()\n"); 225 | return 1; 226 | } 227 | 228 | const char *input_file = argv[1]; 229 | const char *output_file = argv[2]; 230 | const char *decoder_name = argv[3]; 231 | 232 | if (read_code_points(input_file)) { 233 | return 1; 234 | } 235 | 236 | struct huffman_node tree_root; 237 | memset(&tree_root, 0, sizeof(struct huffman_node)); 238 | 239 | /* Populate the tree */ 240 | for (size_t i = 0; i < num_code_points; ++i) { 241 | 242 | struct huffman_code_point *value = &code_points[i]; 243 | if (value->code.num_bits == 0) { 244 | continue; 245 | } 246 | 247 | struct huffman_node *current = &tree_root; 248 | 249 | uint8_t bit_idx = value->code.num_bits - 1; 250 | while (1) { 251 | struct huffman_code code = value->code; 252 | code.bits >>= bit_idx; 253 | code.num_bits = value->code.num_bits - bit_idx; 254 | 255 | uint8_t encoded_bit = code.bits & 0x01; 256 | assert(encoded_bit == 0 || encoded_bit == 1); 257 | 258 | if (bit_idx == 0) { 259 | /* Done traversing, add value as leaf */ 260 | assert(!current->children[encoded_bit]); 261 | current->children[encoded_bit] = huffman_node_new_value(value); 262 | break; 263 | } 264 | 265 | if (current->children[encoded_bit]) { 266 | /* Not at the end yet, keep traversing */ 267 | current = current->children[encoded_bit]; 268 | } else { 269 | /* Not at the end yet, but this is the first time down this 270 | * path. */ 271 | struct huffman_node *new_node = huffman_node_new(code); 272 | current->children[encoded_bit] = new_node; 273 | current = new_node; 274 | } 275 | 276 | --bit_idx; 277 | } 278 | } 279 | 280 | /* Open the file */ 281 | FILE *file = fopen(output_file, "w"); 282 | if (!file) { 283 | printf("Failed to open file '%s' for write.", output_file); 284 | return 1; 285 | } 286 | 287 | /* Write the file/function header */ 288 | fprintf( 289 | file, 290 | "/**\n" 291 | " * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n" 292 | " * SPDX-License-Identifier: Apache-2.0.\n" 293 | " */\n" 294 | "\n" 295 | "/* WARNING: THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. */\n" 296 | "/* clang-format off */\n" 297 | "\n" 298 | "#include \n" 299 | "\n" 300 | "static struct aws_huffman_code code_points[] = {\n"); 301 | 302 | for (size_t i = 0; i < num_code_points; ++i) { 303 | struct huffman_code_point *cp = &code_points[i]; 304 | fprintf( 305 | file, 306 | " { .pattern = 0x%x, .num_bits = %u }, /* '%c' %u */\n", 307 | cp->code.bits, 308 | cp->code.num_bits, 309 | isprint(cp->symbol) ? cp->symbol : ' ', 310 | cp->symbol); 311 | } 312 | 313 | fprintf( 314 | file, 315 | "};\n" 316 | "\n" 317 | "static struct aws_huffman_code encode_symbol(uint8_t symbol, void " 318 | "*userdata) {\n" 319 | " (void)userdata;\n\n" 320 | " return code_points[symbol];\n" 321 | "}\n" 322 | "\n" 323 | "/* NOLINTNEXTLINE(readability-function-size) */\n" 324 | "static uint8_t decode_symbol(uint32_t bits, uint8_t *symbol, void " 325 | "*userdata) {\n" 326 | " (void)userdata;\n\n"); 327 | 328 | /* Traverse the tree */ 329 | huffman_node_write_decode(&tree_root, file, 0); 330 | 331 | /* Write the function footer & encode header */ 332 | fprintf( 333 | file, 334 | "}\n" 335 | "\n" 336 | "struct aws_huffman_symbol_coder *%s_get_coder(void) {\n" 337 | "\n" 338 | " static struct aws_huffman_symbol_coder coder = {\n" 339 | " .encode = encode_symbol,\n" 340 | " .decode = decode_symbol,\n" 341 | " .userdata = NULL,\n" 342 | " };\n" 343 | " return &coder;\n" 344 | "}\n", 345 | decoder_name); 346 | 347 | fclose(file); 348 | 349 | huffman_node_clean_up(&tree_root); 350 | 351 | return 0; 352 | } 353 | -------------------------------------------------------------------------------- /source/huffman_testing.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | /** 7 | * See aws/testing/compression/huffman.h for docs. 8 | */ 9 | #define AWS_UNSTABLE_TESTING_API 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | int huffman_test_transitive( 16 | struct aws_huffman_symbol_coder *coder, 17 | const char *input, 18 | size_t size, 19 | size_t encoded_size, 20 | const char **error_string) { 21 | 22 | struct aws_huffman_encoder encoder; 23 | aws_huffman_encoder_init(&encoder, coder); 24 | struct aws_huffman_decoder decoder; 25 | aws_huffman_decoder_init(&decoder, coder); 26 | 27 | const size_t intermediate_buffer_size = size * 2; 28 | AWS_VARIABLE_LENGTH_ARRAY(uint8_t, intermediate_buffer, intermediate_buffer_size); 29 | memset(intermediate_buffer, 0, intermediate_buffer_size); 30 | AWS_VARIABLE_LENGTH_ARRAY(char, output_buffer, size); 31 | memset(output_buffer, 0, size); 32 | 33 | struct aws_byte_cursor to_encode = aws_byte_cursor_from_array((uint8_t *)input, size); 34 | struct aws_byte_buf intermediate_buf = aws_byte_buf_from_empty_array(intermediate_buffer, intermediate_buffer_size); 35 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, size); 36 | 37 | int result = aws_huffman_encode(&encoder, &to_encode, &intermediate_buf); 38 | 39 | if (result != AWS_OP_SUCCESS) { 40 | *error_string = "aws_huffman_encode failed"; 41 | return AWS_OP_ERR; 42 | } 43 | if (to_encode.len != 0) { 44 | *error_string = "not all data encoded"; 45 | return AWS_OP_ERR; 46 | } 47 | if (encoded_size && intermediate_buf.len != encoded_size) { 48 | *error_string = "encoded length is incorrect"; 49 | return AWS_OP_ERR; 50 | } 51 | 52 | struct aws_byte_cursor intermediate_cur = aws_byte_cursor_from_buf(&intermediate_buf); 53 | result = aws_huffman_decode(&decoder, &intermediate_cur, &output_buf); 54 | 55 | if (result != AWS_OP_SUCCESS) { 56 | *error_string = "aws_huffman_decode failed"; 57 | return AWS_OP_ERR; 58 | } 59 | if (intermediate_cur.len != 0) { 60 | *error_string = "not all encoded data was decoded"; 61 | return AWS_OP_ERR; 62 | } 63 | if (output_buf.len != size) { 64 | *error_string = "decode output size incorrect"; 65 | return AWS_OP_ERR; 66 | } 67 | if (memcmp(input, output_buffer, size) != 0) { 68 | *error_string = "decoded data does not match input data"; 69 | return AWS_OP_ERR; 70 | } 71 | 72 | return AWS_OP_SUCCESS; 73 | } 74 | 75 | int huffman_test_transitive_chunked( 76 | struct aws_huffman_symbol_coder *coder, 77 | const char *input, 78 | size_t size, 79 | size_t encoded_size, 80 | size_t output_chunk_size, 81 | const char **error_string) { 82 | 83 | struct aws_huffman_encoder encoder; 84 | aws_huffman_encoder_init(&encoder, coder); 85 | struct aws_huffman_decoder decoder; 86 | aws_huffman_decoder_init(&decoder, coder); 87 | 88 | const size_t intermediate_buffer_size = size * 2; 89 | AWS_VARIABLE_LENGTH_ARRAY(uint8_t, intermediate_buffer, intermediate_buffer_size); 90 | memset(intermediate_buffer, 0, intermediate_buffer_size); 91 | AWS_VARIABLE_LENGTH_ARRAY(char, output_buffer, size); 92 | memset(output_buffer, 0, size); 93 | 94 | struct aws_byte_cursor to_encode = aws_byte_cursor_from_array(input, size); 95 | struct aws_byte_buf intermediate_buf = aws_byte_buf_from_empty_array(intermediate_buffer, (size_t)-1); 96 | intermediate_buf.capacity = 0; 97 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, (size_t)-1); 98 | output_buf.capacity = 0; 99 | 100 | int result = AWS_OP_SUCCESS; 101 | 102 | { 103 | do { 104 | const size_t previous_intermediate_len = intermediate_buf.len; 105 | 106 | intermediate_buf.capacity += output_chunk_size; 107 | result = aws_huffman_encode(&encoder, &to_encode, &intermediate_buf); 108 | 109 | if (intermediate_buf.len == previous_intermediate_len) { 110 | *error_string = "encode didn't write any data"; 111 | return AWS_OP_ERR; 112 | } 113 | 114 | if (result != AWS_OP_SUCCESS && aws_last_error() != AWS_ERROR_SHORT_BUFFER) { 115 | *error_string = "encode returned wrong error code"; 116 | return AWS_OP_ERR; 117 | } 118 | } while (result != AWS_OP_SUCCESS); 119 | } 120 | 121 | if (result != AWS_OP_SUCCESS) { 122 | *error_string = "aws_huffman_encode failed"; 123 | return AWS_OP_ERR; 124 | } 125 | if (intermediate_buf.len > intermediate_buffer_size) { 126 | *error_string = "too much data encoded"; 127 | return AWS_OP_ERR; 128 | } 129 | if (encoded_size && intermediate_buf.len != encoded_size) { 130 | *error_string = "encoded length is incorrect"; 131 | return AWS_OP_ERR; 132 | } 133 | 134 | struct aws_byte_cursor intermediate_cur = aws_byte_cursor_from_buf(&intermediate_buf); 135 | 136 | { 137 | do { 138 | const size_t previous_output_len = output_buf.len; 139 | 140 | output_buf.capacity += output_chunk_size; 141 | if (output_buf.capacity > size) { 142 | output_buf.capacity = size; 143 | } 144 | 145 | result = aws_huffman_decode(&decoder, &intermediate_cur, &output_buf); 146 | 147 | if (output_buf.len == previous_output_len) { 148 | *error_string = "decode didn't write any data"; 149 | return AWS_OP_ERR; 150 | } 151 | 152 | if (result != AWS_OP_SUCCESS && aws_last_error() != AWS_ERROR_SHORT_BUFFER) { 153 | *error_string = "decode returned wrong error code"; 154 | return AWS_OP_ERR; 155 | } 156 | } while (result != AWS_OP_SUCCESS); 157 | } 158 | 159 | if (result != AWS_OP_SUCCESS) { 160 | *error_string = "aws_huffman_decode failed"; 161 | return AWS_OP_ERR; 162 | } 163 | if (output_buf.len != size) { 164 | *error_string = "decode output size incorrect"; 165 | return AWS_OP_ERR; 166 | } 167 | if (memcmp(input, output_buffer, size) != 0) { 168 | *error_string = "decoded data does not match input data"; 169 | return AWS_OP_ERR; 170 | } 171 | 172 | return AWS_OP_SUCCESS; 173 | } 174 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(CTest) 2 | include(AwsTestHarness) 3 | include(AwsLibFuzzer) 4 | 5 | enable_testing() 6 | 7 | file(GLOB TEST_SRC "*.c") 8 | file(GLOB TEST_HDRS "*.h") 9 | file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) 10 | 11 | add_test_case(library_init) 12 | 13 | add_test_case(huffman_symbol_encoder) 14 | add_test_case(huffman_encoder) 15 | add_test_case(huffman_encoder_all_code_points) 16 | add_test_case(huffman_encoder_partial_output) 17 | add_test_case(huffman_encoder_exact_output) 18 | 19 | add_test_case(huffman_symbol_decoder) 20 | add_test_case(huffman_decoder) 21 | add_test_case(huffman_decoder_all_code_points) 22 | add_test_case(huffman_decoder_partial_input) 23 | add_test_case(huffman_decoder_partial_output) 24 | add_test_case(huffman_decoder_allow_growth) 25 | 26 | add_test_case(huffman_transitive) 27 | add_test_case(huffman_transitive_even_bytes) 28 | add_test_case(huffman_transitive_all_code_points) 29 | add_test_case(huffman_transitive_chunked) 30 | 31 | generate_test_driver(${PROJECT_NAME}-tests) 32 | if(MSVC) 33 | target_compile_definitions(${PROJECT_NAME}-tests PRIVATE "-D_CRT_SECURE_NO_WARNINGS") 34 | endif() 35 | 36 | file(GLOB FUZZ_TESTS "fuzz/*.c") 37 | aws_add_fuzz_tests("${FUZZ_TESTS}" "test_huffman_static.c" "") 38 | -------------------------------------------------------------------------------- /tests/fuzz/decode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | struct aws_huffman_symbol_coder *test_get_coder(void); 12 | 13 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 14 | 15 | if (!size) { 16 | return 0; 17 | } 18 | 19 | struct aws_huffman_decoder decoder; 20 | aws_huffman_decoder_init(&decoder, test_get_coder()); 21 | 22 | size_t output_buffer_size = size * 2; 23 | char output_buffer[output_buffer_size]; 24 | 25 | struct aws_byte_cursor to_decode = aws_byte_cursor_from_array(data, size); 26 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, AWS_ARRAY_SIZE(output_buffer)); 27 | 28 | /* Don't really care about result, just make sure there's no crash */ 29 | aws_huffman_decode(&decoder, &to_decode, &output_buf); 30 | 31 | return 0; // Non-zero return values are reserved for future use. 32 | } 33 | -------------------------------------------------------------------------------- /tests/fuzz/transitive.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | struct aws_huffman_symbol_coder *test_get_coder(void); 12 | 13 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 14 | 15 | if (!size) { 16 | return 0; 17 | } 18 | 19 | const char *error_message = NULL; 20 | int result = huffman_test_transitive(test_get_coder(), (const char *)data, size, 0, &error_message); 21 | ASSERT_SUCCESS(result, error_message); 22 | 23 | return 0; // Non-zero return values are reserved for future use. 24 | } 25 | -------------------------------------------------------------------------------- /tests/fuzz/transitive_chunked.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | struct aws_huffman_symbol_coder *test_get_coder(void); 12 | 13 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 14 | 15 | if (!size) { 16 | return 0; 17 | } 18 | 19 | static const size_t step_sizes[] = {1, 2, 4, 8, 16, 32, 64, 128}; 20 | for (size_t i = 0; i < sizeof(step_sizes) / sizeof(size_t); ++i) { 21 | size_t step_size = step_sizes[i]; 22 | 23 | const char *error_message = NULL; 24 | int result = 25 | huffman_test_transitive_chunked(test_get_coder(), (const char *)data, size, 0, step_size, &error_message); 26 | ASSERT_SUCCESS(result, error_message); 27 | } 28 | 29 | return 0; // Non-zero return values are reserved for future use. 30 | } 31 | -------------------------------------------------------------------------------- /tests/huffman_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | /* Exported by generated file */ 12 | struct aws_huffman_symbol_coder *test_get_coder(void); 13 | 14 | static struct huffman_test_code_point s_code_points[] = { 15 | #include "test_huffman_static_table.def" 16 | }; 17 | enum { NUM_CODE_POINTS = sizeof(s_code_points) / sizeof(s_code_points[0]) }; 18 | 19 | /* Useful data for testing */ 20 | static const char s_url_string[] = "www.example.com"; 21 | enum { URL_STRING_LEN = sizeof(s_url_string) - 1 }; 22 | 23 | static uint8_t s_encoded_url[] = {0x9e, 0x79, 0xeb, 0x9b, 0x04, 0xb3, 0x5a, 0x94, 0xd5, 0xe0, 0x4c, 0xdf}; 24 | enum { ENCODED_URL_LEN = sizeof(s_encoded_url) }; 25 | 26 | static const char s_all_codes[] = " !\"#$%&'()*+,-./" 27 | "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[" 28 | "\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; 29 | enum { ALL_CODES_LEN = sizeof(s_all_codes) - 1 }; 30 | static uint8_t s_encoded_codes[] = { 31 | 0x26, 0x9b, 0xa7, 0x69, 0xfa, 0x86, 0xa3, 0xa9, 0x56, 0xd4, 0xf5, 0x4d, 0x57, 0x56, 0xb9, 0xc4, 0x57, 0xd5, 32 | 0xf5, 0x8d, 0x67, 0x5a, 0xd6, 0xf5, 0xcd, 0x77, 0x5e, 0xd7, 0xf6, 0x0d, 0x87, 0x62, 0xd8, 0xf6, 0x4d, 0x97, 33 | 0x66, 0xba, 0xd9, 0xf6, 0x8b, 0xbc, 0x4e, 0x2b, 0x17, 0x8c, 0xc6, 0xe3, 0xaf, 0x36, 0x9d, 0xab, 0x1f, 0x90, 34 | 0xda, 0xf6, 0xcc, 0x8e, 0xdb, 0xb7, 0x6d, 0xf7, 0xbb, 0x86, 0x4a, 0xfb, 0x71, 0xc9, 0xee, 0x5b, 0x9e, 0xe9, 35 | 0xba, 0xee, 0xdb, 0xbe, 0xf0, 0x5b, 0x10, 0x42, 0x68, 0xac, 0xc6, 0x7b, 0xf9, 0x25, 0x99, 0x09, 0xb5, 0x94, 36 | 0x52, 0xd8, 0xdc, 0x09, 0xf0, 0x68, 0xde, 0x77, 0xad, 0xef, 0x7c, 0xdf, 0x7f}; 37 | enum { ENCODED_CODES_LEN = sizeof(s_encoded_codes) }; 38 | 39 | static const size_t s_step_sizes[] = {1, 2, 4, 8, 16, 32, 64, 128}; 40 | enum { NUM_STEP_SIZES = sizeof(s_step_sizes) / sizeof(s_step_sizes[0]) }; 41 | 42 | AWS_TEST_CASE(huffman_symbol_encoder, test_huffman_symbol_encoder) 43 | static int test_huffman_symbol_encoder(struct aws_allocator *allocator, void *ctx) { 44 | (void)allocator; 45 | (void)ctx; 46 | /* Test encoding each character */ 47 | 48 | struct aws_huffman_symbol_coder *coder = test_get_coder(); 49 | 50 | for (size_t i = 0; i < NUM_CODE_POINTS; ++i) { 51 | struct huffman_test_code_point *value = &s_code_points[i]; 52 | 53 | struct aws_huffman_code code = coder->encode(value->symbol, NULL); 54 | 55 | ASSERT_UINT_EQUALS(value->code.pattern, code.pattern); 56 | ASSERT_UINT_EQUALS(value->code.num_bits, code.num_bits); 57 | } 58 | 59 | return AWS_OP_SUCCESS; 60 | } 61 | 62 | AWS_TEST_CASE(huffman_encoder, test_huffman_encoder) 63 | static int test_huffman_encoder(struct aws_allocator *allocator, void *ctx) { 64 | (void)allocator; 65 | (void)ctx; 66 | /* Test encoding a short url */ 67 | 68 | uint8_t output_buffer[ENCODED_URL_LEN + 1]; 69 | AWS_ZERO_ARRAY(output_buffer); 70 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, ENCODED_URL_LEN); 71 | 72 | struct aws_huffman_symbol_coder *coder = test_get_coder(); 73 | struct aws_huffman_encoder encoder; 74 | aws_huffman_encoder_init(&encoder, coder); 75 | 76 | struct aws_byte_cursor to_encode = aws_byte_cursor_from_array(s_url_string, URL_STRING_LEN); 77 | const size_t encoded_length = aws_huffman_get_encoded_length(&encoder, to_encode); 78 | ASSERT_UINT_EQUALS(ENCODED_URL_LEN, encoded_length); 79 | int result = aws_huffman_encode(&encoder, &to_encode, &output_buf); 80 | ASSERT_SUCCESS(result); 81 | 82 | ASSERT_UINT_EQUALS(ENCODED_URL_LEN, output_buf.len); 83 | ASSERT_UINT_EQUALS(0, output_buffer[ENCODED_URL_LEN]); 84 | ASSERT_BIN_ARRAYS_EQUALS(s_encoded_url, ENCODED_URL_LEN, output_buf.buffer, output_buf.len); 85 | 86 | return AWS_OP_SUCCESS; 87 | } 88 | 89 | AWS_TEST_CASE(huffman_encoder_all_code_points, test_huffman_encoder_all_code_points) 90 | static int test_huffman_encoder_all_code_points(struct aws_allocator *allocator, void *ctx) { 91 | (void)allocator; 92 | (void)ctx; 93 | /* Test encoding a sequence of all character values expressable as 94 | * characters */ 95 | 96 | uint8_t output_buffer[ENCODED_CODES_LEN + 1]; 97 | AWS_ZERO_ARRAY(output_buffer); 98 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, ENCODED_CODES_LEN); 99 | 100 | struct aws_huffman_symbol_coder *coder = test_get_coder(); 101 | struct aws_huffman_encoder encoder; 102 | aws_huffman_encoder_init(&encoder, coder); 103 | 104 | struct aws_byte_cursor to_encode = aws_byte_cursor_from_array(s_all_codes, ALL_CODES_LEN); 105 | const size_t encoded_length = aws_huffman_get_encoded_length(&encoder, to_encode); 106 | ASSERT_UINT_EQUALS(ENCODED_CODES_LEN, encoded_length); 107 | int result = aws_huffman_encode(&encoder, &to_encode, &output_buf); 108 | ASSERT_SUCCESS(result); 109 | 110 | ASSERT_UINT_EQUALS(ENCODED_CODES_LEN, output_buf.len); 111 | ASSERT_UINT_EQUALS(0, output_buffer[ENCODED_CODES_LEN]); 112 | ASSERT_BIN_ARRAYS_EQUALS(s_encoded_codes, ENCODED_CODES_LEN, output_buf.buffer, output_buf.len); 113 | 114 | return AWS_OP_SUCCESS; 115 | } 116 | 117 | AWS_TEST_CASE(huffman_encoder_partial_output, test_huffman_encoder_partial_output) 118 | static int test_huffman_encoder_partial_output(struct aws_allocator *allocator, void *ctx) { 119 | (void)allocator; 120 | (void)ctx; 121 | /* Test encoding when the output buffer size is limited */ 122 | 123 | struct aws_huffman_encoder encoder; 124 | aws_huffman_encoder_init(&encoder, test_get_coder()); 125 | 126 | uint8_t output_buffer[ENCODED_CODES_LEN]; 127 | 128 | for (size_t i = 0; i < NUM_STEP_SIZES; ++i) { 129 | const size_t step_size = s_step_sizes[i]; 130 | 131 | aws_huffman_encoder_reset(&encoder); 132 | 133 | struct aws_byte_cursor to_encode = aws_byte_cursor_from_array(s_all_codes, ALL_CODES_LEN); 134 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, (size_t)-1); 135 | output_buf.capacity = 0; 136 | AWS_ZERO_ARRAY(output_buffer); 137 | 138 | do { 139 | output_buf.capacity += step_size; 140 | if (output_buf.capacity > ENCODED_CODES_LEN) { 141 | output_buf.capacity = ENCODED_CODES_LEN; 142 | } 143 | 144 | const size_t previous_output_len = output_buf.len; 145 | 146 | int result = aws_huffman_encode(&encoder, &to_encode, &output_buf); 147 | 148 | ASSERT_TRUE(output_buf.len > previous_output_len); 149 | ASSERT_BIN_ARRAYS_EQUALS(s_encoded_codes, output_buf.len, output_buf.buffer, output_buf.len); 150 | 151 | if (output_buf.len == ENCODED_CODES_LEN) { 152 | ASSERT_SUCCESS(result); 153 | } else { 154 | ASSERT_UINT_EQUALS(AWS_ERROR_SHORT_BUFFER, aws_last_error()); 155 | aws_reset_error(); 156 | } 157 | } while (output_buf.len < ENCODED_CODES_LEN); 158 | 159 | ASSERT_UINT_EQUALS(ENCODED_CODES_LEN, output_buf.len); 160 | 161 | ASSERT_BIN_ARRAYS_EQUALS(s_encoded_codes, ENCODED_CODES_LEN, output_buf.buffer, output_buf.len); 162 | } 163 | 164 | return AWS_OP_SUCCESS; 165 | } 166 | 167 | AWS_TEST_CASE(huffman_encoder_exact_output, test_huffman_encoder_exact_output) 168 | static int test_huffman_encoder_exact_output(struct aws_allocator *allocator, void *ctx) { 169 | (void)allocator; 170 | (void)ctx; 171 | /* Test encoding when the output buffer size is exactly the necessary size */ 172 | struct aws_huffman_encoder encoder; 173 | aws_huffman_encoder_init(&encoder, test_get_coder()); 174 | 175 | uint8_t output_buffer[2]; 176 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, 2); 177 | 178 | /* Encode a character that uses 8 bits into a 1 byte buffer */ 179 | struct aws_byte_cursor to_encode = aws_byte_cursor_from_array("?", 1); 180 | uint8_t expected_1byte[] = {0xba}; 181 | output_buf.capacity = 1; 182 | ASSERT_SUCCESS(aws_huffman_encode(&encoder, &to_encode, &output_buf)); 183 | ASSERT_BIN_ARRAYS_EQUALS(expected_1byte, 1, output_buf.buffer, output_buf.len); 184 | 185 | /* Encode 2 characters that sum to 16 bits, into a 2 byte buffer 186 | * y: 101000 187 | * z: 1101111001 188 | * combined: 1010001101111001 == 0xa379 */ 189 | to_encode = aws_byte_cursor_from_array("yz", 2); 190 | uint8_t expected_2byte[] = {0xa3, 0x79}; 191 | output_buf.capacity = 2; 192 | aws_byte_buf_reset(&output_buf, true /*zero*/); 193 | ASSERT_SUCCESS(aws_huffman_encode(&encoder, &to_encode, &output_buf)); 194 | ASSERT_BIN_ARRAYS_EQUALS(expected_2byte, 2, output_buf.buffer, output_buf.len); 195 | 196 | return AWS_OP_SUCCESS; 197 | } 198 | 199 | AWS_TEST_CASE(huffman_symbol_decoder, test_huffman_symbol_decoder) 200 | static int test_huffman_symbol_decoder(struct aws_allocator *allocator, void *ctx) { 201 | (void)allocator; 202 | (void)ctx; 203 | /* Test decoding each character */ 204 | 205 | struct aws_huffman_symbol_coder *coder = test_get_coder(); 206 | 207 | for (size_t i = 0; i < NUM_CODE_POINTS; ++i) { 208 | struct huffman_test_code_point *value = &s_code_points[i]; 209 | 210 | uint32_t bit_pattern = value->code.pattern << (32 - value->code.num_bits); 211 | 212 | uint8_t out; 213 | size_t bits_read = coder->decode(bit_pattern, &out, NULL); 214 | 215 | ASSERT_UINT_EQUALS(value->symbol, out); 216 | ASSERT_UINT_EQUALS(value->code.num_bits, bits_read); 217 | } 218 | 219 | return AWS_OP_SUCCESS; 220 | } 221 | 222 | AWS_TEST_CASE(huffman_decoder, test_huffman_decoder) 223 | static int test_huffman_decoder(struct aws_allocator *allocator, void *ctx) { 224 | (void)allocator; 225 | (void)ctx; 226 | /* Test decoding a short url */ 227 | 228 | char output_buffer[URL_STRING_LEN + 1]; 229 | AWS_ZERO_ARRAY(output_buffer); 230 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, URL_STRING_LEN); 231 | 232 | struct aws_huffman_symbol_coder *coder = test_get_coder(); 233 | struct aws_huffman_decoder decoder; 234 | aws_huffman_decoder_init(&decoder, coder); 235 | 236 | struct aws_byte_cursor to_decode = aws_byte_cursor_from_array(s_encoded_url, ENCODED_URL_LEN); 237 | int result = aws_huffman_decode(&decoder, &to_decode, &output_buf); 238 | 239 | ASSERT_SUCCESS(result); 240 | ASSERT_UINT_EQUALS(URL_STRING_LEN, output_buf.len); 241 | ASSERT_UINT_EQUALS(0, to_decode.len); 242 | ASSERT_UINT_EQUALS(output_buffer[URL_STRING_LEN], 0); 243 | ASSERT_BIN_ARRAYS_EQUALS(s_url_string, URL_STRING_LEN, output_buf.buffer, output_buf.len); 244 | 245 | return AWS_OP_SUCCESS; 246 | } 247 | 248 | AWS_TEST_CASE(huffman_decoder_all_code_points, test_huffman_decoder_all_code_points) 249 | static int test_huffman_decoder_all_code_points(struct aws_allocator *allocator, void *ctx) { 250 | (void)allocator; 251 | (void)ctx; 252 | /* Test decoding a sequence of all character values expressable as 253 | * characters */ 254 | 255 | char output_buffer[ALL_CODES_LEN + 1]; 256 | AWS_ZERO_ARRAY(output_buffer); 257 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, ALL_CODES_LEN); 258 | 259 | struct aws_huffman_symbol_coder *coder = test_get_coder(); 260 | struct aws_huffman_decoder decoder; 261 | aws_huffman_decoder_init(&decoder, coder); 262 | 263 | struct aws_byte_cursor to_decode = aws_byte_cursor_from_array(s_encoded_codes, ENCODED_CODES_LEN); 264 | int result = aws_huffman_decode(&decoder, &to_decode, &output_buf); 265 | 266 | ASSERT_SUCCESS(result); 267 | ASSERT_UINT_EQUALS(ALL_CODES_LEN, output_buf.len); 268 | ASSERT_UINT_EQUALS(0, to_decode.len); 269 | ASSERT_UINT_EQUALS(output_buffer[ALL_CODES_LEN], 0); 270 | ASSERT_BIN_ARRAYS_EQUALS(s_all_codes, ALL_CODES_LEN, output_buf.buffer, output_buf.len); 271 | 272 | return AWS_OP_SUCCESS; 273 | } 274 | 275 | AWS_TEST_CASE(huffman_decoder_partial_input, test_huffman_decoder_partial_input) 276 | static int test_huffman_decoder_partial_input(struct aws_allocator *allocator, void *ctx) { 277 | (void)allocator; 278 | (void)ctx; 279 | /* Test decoding a buffer in chunks */ 280 | 281 | struct aws_huffman_decoder decoder; 282 | aws_huffman_decoder_init(&decoder, test_get_coder()); 283 | 284 | char output_buffer[150]; 285 | 286 | for (size_t i = 0; i < NUM_STEP_SIZES; ++i) { 287 | const size_t step_size = s_step_sizes[i]; 288 | 289 | aws_huffman_decoder_reset(&decoder); 290 | 291 | struct aws_byte_cursor to_decode = aws_byte_cursor_from_array(s_encoded_codes, ENCODED_CODES_LEN); 292 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, ALL_CODES_LEN); 293 | AWS_ZERO_ARRAY(output_buffer); 294 | 295 | do { 296 | const size_t chunk_size = step_size < to_decode.len ? step_size : to_decode.len; 297 | struct aws_byte_cursor to_decode_chunk = aws_byte_cursor_advance(&to_decode, chunk_size); 298 | 299 | int result = aws_huffman_decode(&decoder, &to_decode_chunk, &output_buf); 300 | 301 | ASSERT_UINT_EQUALS(0, to_decode_chunk.len); 302 | ASSERT_BIN_ARRAYS_EQUALS(s_all_codes, output_buf.len, output_buf.buffer, output_buf.len); 303 | 304 | if (output_buf.len == ALL_CODES_LEN) { 305 | ASSERT_SUCCESS(result); 306 | } 307 | } while (output_buf.len < ALL_CODES_LEN); 308 | 309 | ASSERT_UINT_EQUALS(ALL_CODES_LEN, output_buf.len); 310 | ASSERT_BIN_ARRAYS_EQUALS(s_all_codes, ALL_CODES_LEN, output_buf.buffer, output_buf.len); 311 | } 312 | 313 | return AWS_OP_SUCCESS; 314 | } 315 | 316 | AWS_TEST_CASE(huffman_decoder_partial_output, test_huffman_decoder_partial_output) 317 | static int test_huffman_decoder_partial_output(struct aws_allocator *allocator, void *ctx) { 318 | (void)allocator; 319 | (void)ctx; 320 | /* Test decoding when the output buffer size is limited */ 321 | 322 | struct aws_huffman_decoder decoder; 323 | aws_huffman_decoder_init(&decoder, test_get_coder()); 324 | 325 | char output_buffer[150]; 326 | 327 | for (size_t i = 0; i < NUM_STEP_SIZES; ++i) { 328 | const size_t step_size = s_step_sizes[i]; 329 | 330 | aws_huffman_decoder_reset(&decoder); 331 | 332 | struct aws_byte_cursor to_decode = aws_byte_cursor_from_array(s_encoded_codes, ENCODED_CODES_LEN); 333 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, (size_t)-1); 334 | output_buf.capacity = 0; /* Can't set above because it sets buffer to 0 */ 335 | AWS_ZERO_ARRAY(output_buffer); 336 | 337 | do { 338 | output_buf.capacity += step_size; 339 | if (output_buf.capacity > ALL_CODES_LEN) { 340 | output_buf.capacity = ALL_CODES_LEN; 341 | } 342 | 343 | const size_t previous_output_size = output_buf.len; 344 | 345 | int result = aws_huffman_decode(&decoder, &to_decode, &output_buf); 346 | 347 | ASSERT_TRUE(output_buf.len > previous_output_size); 348 | ASSERT_BIN_ARRAYS_EQUALS(s_all_codes, output_buf.len, output_buf.buffer, output_buf.len); 349 | 350 | if (output_buf.len == ALL_CODES_LEN) { 351 | ASSERT_SUCCESS(result); 352 | } else { 353 | ASSERT_UINT_EQUALS(AWS_ERROR_SHORT_BUFFER, aws_last_error()); 354 | aws_reset_error(); 355 | } 356 | } while (output_buf.len < ALL_CODES_LEN); 357 | 358 | ASSERT_UINT_EQUALS(ALL_CODES_LEN, output_buf.len); 359 | ASSERT_BIN_ARRAYS_EQUALS(s_all_codes, ALL_CODES_LEN, output_buf.buffer, output_buf.len); 360 | } 361 | 362 | return AWS_OP_SUCCESS; 363 | } 364 | 365 | AWS_TEST_CASE(huffman_decoder_allow_growth, test_huffman_decoder_allow_growth) 366 | static int test_huffman_decoder_allow_growth(struct aws_allocator *allocator, void *ctx) { 367 | (void)ctx; 368 | /* Test that decoder will grow output buffer if allow-growth is set */ 369 | 370 | struct aws_huffman_decoder decoder; 371 | aws_huffman_decoder_init(&decoder, test_get_coder()); 372 | aws_huffman_decoder_allow_growth(&decoder, true); 373 | 374 | struct aws_byte_buf output_buf; 375 | ASSERT_SUCCESS(aws_byte_buf_init(&output_buf, allocator, 1 /* way too small */)); 376 | 377 | struct aws_byte_cursor to_decode = aws_byte_cursor_from_array(s_encoded_url, ENCODED_URL_LEN); 378 | ASSERT_SUCCESS(aws_huffman_decode(&decoder, &to_decode, &output_buf)); 379 | 380 | ASSERT_UINT_EQUALS(0, to_decode.len); 381 | ASSERT_BIN_ARRAYS_EQUALS(s_url_string, URL_STRING_LEN, output_buf.buffer, output_buf.len); 382 | 383 | aws_byte_buf_clean_up(&output_buf); 384 | return AWS_OP_SUCCESS; 385 | } 386 | 387 | AWS_TEST_CASE(huffman_transitive, test_huffman_transitive) 388 | static int test_huffman_transitive(struct aws_allocator *allocator, void *ctx) { 389 | (void)allocator; 390 | (void)ctx; 391 | /* Test encoding a short url and immediately decoding it */ 392 | 393 | const char *error_message = NULL; 394 | int result = 395 | huffman_test_transitive(test_get_coder(), s_url_string, URL_STRING_LEN, ENCODED_URL_LEN, &error_message); 396 | ASSERT_SUCCESS(result, error_message); 397 | 398 | return AWS_OP_SUCCESS; 399 | } 400 | 401 | AWS_TEST_CASE(huffman_transitive_even_bytes, test_huffman_transitive_even_bytes) 402 | static int test_huffman_transitive_even_bytes(struct aws_allocator *allocator, void *ctx) { 403 | (void)allocator; 404 | (void)ctx; 405 | /* Test encoding a string that encodes to a multiple of 8 bits */ 406 | 407 | const char *error_message = NULL; 408 | int result = huffman_test_transitive(test_get_coder(), "cdfh", 4, 3, &error_message); 409 | ASSERT_SUCCESS(result, error_message); 410 | 411 | return AWS_OP_SUCCESS; 412 | } 413 | 414 | AWS_TEST_CASE(huffman_transitive_all_code_points, test_huffman_transitive_all_code_points) 415 | static int test_huffman_transitive_all_code_points(struct aws_allocator *allocator, void *ctx) { 416 | (void)allocator; 417 | (void)ctx; 418 | /* Test encoding a sequence of all character values expressable as 419 | * characters and immediately decoding it */ 420 | 421 | const char *error_message = NULL; 422 | int result = 423 | huffman_test_transitive(test_get_coder(), s_all_codes, ALL_CODES_LEN, ENCODED_CODES_LEN, &error_message); 424 | ASSERT_SUCCESS(result, error_message); 425 | 426 | return AWS_OP_SUCCESS; 427 | } 428 | 429 | AWS_TEST_CASE(huffman_transitive_chunked, test_huffman_transitive_chunked) 430 | static int test_huffman_transitive_chunked(struct aws_allocator *allocator, void *ctx) { 431 | (void)allocator; 432 | (void)ctx; 433 | /* Test encoding a sequence of all character values expressable as 434 | * characters and immediately decoding it */ 435 | 436 | for (size_t i = 0; i < NUM_STEP_SIZES; ++i) { 437 | const size_t step_size = s_step_sizes[i]; 438 | 439 | const char *error_message = NULL; 440 | int result = huffman_test_transitive_chunked( 441 | test_get_coder(), s_all_codes, ALL_CODES_LEN, ENCODED_CODES_LEN, step_size, &error_message); 442 | ASSERT_SUCCESS(result, error_message); 443 | } 444 | 445 | return AWS_OP_SUCCESS; 446 | } 447 | -------------------------------------------------------------------------------- /tests/library_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | AWS_TEST_CASE(library_init, s_test_library_init) 10 | static int s_test_library_init(struct aws_allocator *allocator, void *ctx) { 11 | (void)ctx; 12 | 13 | aws_compression_library_init(allocator); 14 | 15 | /* Ensure that errors were registered */ 16 | const char *err_name = aws_error_name(AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL); 17 | const char *expected = "AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL"; 18 | ASSERT_BIN_ARRAYS_EQUALS(expected, strlen(expected), err_name, strlen(err_name)); 19 | 20 | aws_compression_library_clean_up(); 21 | return AWS_OP_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /tests/test_huffman_static.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | /* WARNING: THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. */ 7 | 8 | #include 9 | 10 | static struct aws_huffman_code code_points[] = { 11 | {.pattern = 0x32e, .num_bits = 10}, /* ' ' 0 */ 12 | {.pattern = 0x32f, .num_bits = 10}, /* ' ' 1 */ 13 | {.pattern = 0x330, .num_bits = 10}, /* ' ' 2 */ 14 | {.pattern = 0x331, .num_bits = 10}, /* ' ' 3 */ 15 | {.pattern = 0x332, .num_bits = 10}, /* ' ' 4 */ 16 | {.pattern = 0x333, .num_bits = 10}, /* ' ' 5 */ 17 | {.pattern = 0x334, .num_bits = 10}, /* ' ' 6 */ 18 | {.pattern = 0x335, .num_bits = 10}, /* ' ' 7 */ 19 | {.pattern = 0x336, .num_bits = 10}, /* ' ' 8 */ 20 | {.pattern = 0x337, .num_bits = 10}, /* ' ' 9 */ 21 | {.pattern = 0xb8, .num_bits = 8}, /* ' ' 10 */ 22 | {.pattern = 0x338, .num_bits = 10}, /* ' ' 11 */ 23 | {.pattern = 0x339, .num_bits = 10}, /* ' ' 12 */ 24 | {.pattern = 0x33a, .num_bits = 10}, /* ' ' 13 */ 25 | {.pattern = 0x33b, .num_bits = 10}, /* ' ' 14 */ 26 | {.pattern = 0x33c, .num_bits = 10}, /* ' ' 15 */ 27 | {.pattern = 0x33d, .num_bits = 10}, /* ' ' 16 */ 28 | {.pattern = 0x33e, .num_bits = 10}, /* ' ' 17 */ 29 | {.pattern = 0x33f, .num_bits = 10}, /* ' ' 18 */ 30 | {.pattern = 0x340, .num_bits = 10}, /* ' ' 19 */ 31 | {.pattern = 0x341, .num_bits = 10}, /* ' ' 20 */ 32 | {.pattern = 0x342, .num_bits = 10}, /* ' ' 21 */ 33 | {.pattern = 0x343, .num_bits = 10}, /* ' ' 22 */ 34 | {.pattern = 0x344, .num_bits = 10}, /* ' ' 23 */ 35 | {.pattern = 0x345, .num_bits = 10}, /* ' ' 24 */ 36 | {.pattern = 0x346, .num_bits = 10}, /* ' ' 25 */ 37 | {.pattern = 0x347, .num_bits = 10}, /* ' ' 26 */ 38 | {.pattern = 0x348, .num_bits = 10}, /* ' ' 27 */ 39 | {.pattern = 0x349, .num_bits = 10}, /* ' ' 28 */ 40 | {.pattern = 0x34a, .num_bits = 10}, /* ' ' 29 */ 41 | {.pattern = 0x34b, .num_bits = 10}, /* ' ' 30 */ 42 | {.pattern = 0x34c, .num_bits = 10}, /* ' ' 31 */ 43 | {.pattern = 0x4, .num_bits = 5}, /* ' ' 32 */ 44 | {.pattern = 0x34d, .num_bits = 10}, /* '!' 33 */ 45 | {.pattern = 0x34e, .num_bits = 10}, /* '"' 34 */ 46 | {.pattern = 0x34f, .num_bits = 10}, /* '#' 35 */ 47 | {.pattern = 0x350, .num_bits = 10}, /* '$' 36 */ 48 | {.pattern = 0x351, .num_bits = 10}, /* '%' 37 */ 49 | {.pattern = 0x352, .num_bits = 10}, /* '&' 38 */ 50 | {.pattern = 0x56, .num_bits = 7}, /* ''' 39 */ 51 | {.pattern = 0x353, .num_bits = 10}, /* '(' 40 */ 52 | {.pattern = 0x354, .num_bits = 10}, /* ')' 41 */ 53 | {.pattern = 0x355, .num_bits = 10}, /* '*' 42 */ 54 | {.pattern = 0x356, .num_bits = 10}, /* '+' 43 */ 55 | {.pattern = 0xb9, .num_bits = 8}, /* ',' 44 */ 56 | {.pattern = 0x188, .num_bits = 9}, /* '-' 45 */ 57 | {.pattern = 0x57, .num_bits = 7}, /* '.' 46 */ 58 | {.pattern = 0x357, .num_bits = 10}, /* '/' 47 */ 59 | {.pattern = 0x358, .num_bits = 10}, /* '0' 48 */ 60 | {.pattern = 0x359, .num_bits = 10}, /* '1' 49 */ 61 | {.pattern = 0x35a, .num_bits = 10}, /* '2' 50 */ 62 | {.pattern = 0x35b, .num_bits = 10}, /* '3' 51 */ 63 | {.pattern = 0x35c, .num_bits = 10}, /* '4' 52 */ 64 | {.pattern = 0x35d, .num_bits = 10}, /* '5' 53 */ 65 | {.pattern = 0x35e, .num_bits = 10}, /* '6' 54 */ 66 | {.pattern = 0x35f, .num_bits = 10}, /* '7' 55 */ 67 | {.pattern = 0x360, .num_bits = 10}, /* '8' 56 */ 68 | {.pattern = 0x361, .num_bits = 10}, /* '9' 57 */ 69 | {.pattern = 0x362, .num_bits = 10}, /* ':' 58 */ 70 | {.pattern = 0x363, .num_bits = 10}, /* ';' 59 */ 71 | {.pattern = 0x364, .num_bits = 10}, /* '<' 60 */ 72 | {.pattern = 0x365, .num_bits = 10}, /* '=' 61 */ 73 | {.pattern = 0x366, .num_bits = 10}, /* '>' 62 */ 74 | {.pattern = 0xba, .num_bits = 8}, /* '?' 63 */ 75 | {.pattern = 0x367, .num_bits = 10}, /* '@' 64 */ 76 | {.pattern = 0x368, .num_bits = 10}, /* 'A' 65 */ 77 | {.pattern = 0xbb, .num_bits = 8}, /* 'B' 66 */ 78 | {.pattern = 0x189, .num_bits = 9}, /* 'C' 67 */ 79 | {.pattern = 0x18a, .num_bits = 9}, /* 'D' 68 */ 80 | {.pattern = 0x18b, .num_bits = 9}, /* 'E' 69 */ 81 | {.pattern = 0x18c, .num_bits = 9}, /* 'F' 70 */ 82 | {.pattern = 0x18d, .num_bits = 9}, /* 'G' 71 */ 83 | {.pattern = 0x18e, .num_bits = 9}, /* 'H' 72 */ 84 | {.pattern = 0xbc, .num_bits = 8}, /* 'I' 73 */ 85 | {.pattern = 0x369, .num_bits = 10}, /* 'J' 74 */ 86 | {.pattern = 0x36a, .num_bits = 10}, /* 'K' 75 */ 87 | {.pattern = 0x18f, .num_bits = 9}, /* 'L' 76 */ 88 | {.pattern = 0x190, .num_bits = 9}, /* 'M' 77 */ 89 | {.pattern = 0x36b, .num_bits = 10}, /* 'N' 78 */ 90 | {.pattern = 0x36c, .num_bits = 10}, /* 'O' 79 */ 91 | {.pattern = 0x191, .num_bits = 9}, /* 'P' 80 */ 92 | {.pattern = 0x36d, .num_bits = 10}, /* 'Q' 81 */ 93 | {.pattern = 0x36e, .num_bits = 10}, /* 'R' 82 */ 94 | {.pattern = 0x36f, .num_bits = 10}, /* 'S' 83 */ 95 | {.pattern = 0xbd, .num_bits = 8}, /* 'T' 84 */ 96 | {.pattern = 0x370, .num_bits = 10}, /* 'U' 85 */ 97 | {.pattern = 0x192, .num_bits = 9}, /* 'V' 86 */ 98 | {.pattern = 0xbe, .num_bits = 8}, /* 'W' 87 */ 99 | {.pattern = 0x371, .num_bits = 10}, /* 'X' 88 */ 100 | {.pattern = 0x193, .num_bits = 9}, /* 'Y' 89 */ 101 | {.pattern = 0x372, .num_bits = 10}, /* 'Z' 90 */ 102 | {.pattern = 0x373, .num_bits = 10}, /* '[' 91 */ 103 | {.pattern = 0x374, .num_bits = 10}, /* '\' 92 */ 104 | {.pattern = 0x375, .num_bits = 10}, /* ']' 93 */ 105 | {.pattern = 0x376, .num_bits = 10}, /* '^' 94 */ 106 | {.pattern = 0x377, .num_bits = 10}, /* '_' 95 */ 107 | {.pattern = 0x378, .num_bits = 10}, /* '`' 96 */ 108 | {.pattern = 0x5, .num_bits = 5}, /* 'a' 97 */ 109 | {.pattern = 0x58, .num_bits = 7}, /* 'b' 98 */ 110 | {.pattern = 0x20, .num_bits = 6}, /* 'c' 99 */ 111 | {.pattern = 0x21, .num_bits = 6}, /* 'd' 100 */ 112 | {.pattern = 0x6, .num_bits = 5}, /* 'e' 101 */ 113 | {.pattern = 0x22, .num_bits = 6}, /* 'f' 102 */ 114 | {.pattern = 0x59, .num_bits = 7}, /* 'g' 103 */ 115 | {.pattern = 0x23, .num_bits = 6}, /* 'h' 104 */ 116 | {.pattern = 0x7, .num_bits = 5}, /* 'i' 105 */ 117 | {.pattern = 0xbf, .num_bits = 8}, /* 'j' 106 */ 118 | {.pattern = 0x24, .num_bits = 6}, /* 'k' 107 */ 119 | {.pattern = 0x25, .num_bits = 6}, /* 'l' 108 */ 120 | {.pattern = 0x26, .num_bits = 6}, /* 'm' 109 */ 121 | {.pattern = 0x8, .num_bits = 5}, /* 'n' 110 */ 122 | {.pattern = 0x9, .num_bits = 5}, /* 'o' 111 */ 123 | {.pattern = 0x5a, .num_bits = 7}, /* 'p' 112 */ 124 | {.pattern = 0x194, .num_bits = 9}, /* 'q' 113 */ 125 | {.pattern = 0xa, .num_bits = 5}, /* 'r' 114 */ 126 | {.pattern = 0xb, .num_bits = 5}, /* 's' 115 */ 127 | {.pattern = 0xc, .num_bits = 5}, /* 't' 116 */ 128 | {.pattern = 0xd, .num_bits = 5}, /* 'u' 117 */ 129 | {.pattern = 0xc0, .num_bits = 8}, /* 'v' 118 */ 130 | {.pattern = 0x27, .num_bits = 6}, /* 'w' 119 */ 131 | {.pattern = 0xc1, .num_bits = 8}, /* 'x' 120 */ 132 | {.pattern = 0x28, .num_bits = 6}, /* 'y' 121 */ 133 | {.pattern = 0x379, .num_bits = 10}, /* 'z' 122 */ 134 | {.pattern = 0x37a, .num_bits = 10}, /* '{' 123 */ 135 | {.pattern = 0x37b, .num_bits = 10}, /* '|' 124 */ 136 | {.pattern = 0x37c, .num_bits = 10}, /* '}' 125 */ 137 | {.pattern = 0x37d, .num_bits = 10}, /* '~' 126 */ 138 | {.pattern = 0x37e, .num_bits = 10}, /* ' ' 127 */ 139 | {.pattern = 0x37f, .num_bits = 10}, /* ' ' 128 */ 140 | {.pattern = 0x380, .num_bits = 10}, /* ' ' 129 */ 141 | {.pattern = 0x381, .num_bits = 10}, /* ' ' 130 */ 142 | {.pattern = 0x382, .num_bits = 10}, /* ' ' 131 */ 143 | {.pattern = 0x383, .num_bits = 10}, /* ' ' 132 */ 144 | {.pattern = 0x384, .num_bits = 10}, /* ' ' 133 */ 145 | {.pattern = 0x385, .num_bits = 10}, /* ' ' 134 */ 146 | {.pattern = 0x386, .num_bits = 10}, /* ' ' 135 */ 147 | {.pattern = 0x387, .num_bits = 10}, /* ' ' 136 */ 148 | {.pattern = 0x388, .num_bits = 10}, /* ' ' 137 */ 149 | {.pattern = 0x389, .num_bits = 10}, /* ' ' 138 */ 150 | {.pattern = 0x38a, .num_bits = 10}, /* ' ' 139 */ 151 | {.pattern = 0x38b, .num_bits = 10}, /* ' ' 140 */ 152 | {.pattern = 0x38c, .num_bits = 10}, /* ' ' 141 */ 153 | {.pattern = 0x38d, .num_bits = 10}, /* ' ' 142 */ 154 | {.pattern = 0x38e, .num_bits = 10}, /* ' ' 143 */ 155 | {.pattern = 0x38f, .num_bits = 10}, /* ' ' 144 */ 156 | {.pattern = 0x390, .num_bits = 10}, /* ' ' 145 */ 157 | {.pattern = 0x391, .num_bits = 10}, /* ' ' 146 */ 158 | {.pattern = 0x392, .num_bits = 10}, /* ' ' 147 */ 159 | {.pattern = 0x393, .num_bits = 10}, /* ' ' 148 */ 160 | {.pattern = 0x394, .num_bits = 10}, /* ' ' 149 */ 161 | {.pattern = 0x395, .num_bits = 10}, /* ' ' 150 */ 162 | {.pattern = 0x396, .num_bits = 10}, /* ' ' 151 */ 163 | {.pattern = 0x397, .num_bits = 10}, /* ' ' 152 */ 164 | {.pattern = 0x398, .num_bits = 10}, /* ' ' 153 */ 165 | {.pattern = 0x399, .num_bits = 10}, /* ' ' 154 */ 166 | {.pattern = 0x39a, .num_bits = 10}, /* ' ' 155 */ 167 | {.pattern = 0x39b, .num_bits = 10}, /* ' ' 156 */ 168 | {.pattern = 0x39c, .num_bits = 10}, /* ' ' 157 */ 169 | {.pattern = 0x39d, .num_bits = 10}, /* ' ' 158 */ 170 | {.pattern = 0x39e, .num_bits = 10}, /* ' ' 159 */ 171 | {.pattern = 0x39f, .num_bits = 10}, /* ' ' 160 */ 172 | {.pattern = 0x3a0, .num_bits = 10}, /* ' ' 161 */ 173 | {.pattern = 0x3a1, .num_bits = 10}, /* ' ' 162 */ 174 | {.pattern = 0x3a2, .num_bits = 10}, /* ' ' 163 */ 175 | {.pattern = 0x3a3, .num_bits = 10}, /* ' ' 164 */ 176 | {.pattern = 0x3a4, .num_bits = 10}, /* ' ' 165 */ 177 | {.pattern = 0x3a5, .num_bits = 10}, /* ' ' 166 */ 178 | {.pattern = 0x3a6, .num_bits = 10}, /* ' ' 167 */ 179 | {.pattern = 0x3a7, .num_bits = 10}, /* ' ' 168 */ 180 | {.pattern = 0x3a8, .num_bits = 10}, /* ' ' 169 */ 181 | {.pattern = 0x3a9, .num_bits = 10}, /* ' ' 170 */ 182 | {.pattern = 0x3aa, .num_bits = 10}, /* ' ' 171 */ 183 | {.pattern = 0x3ab, .num_bits = 10}, /* ' ' 172 */ 184 | {.pattern = 0x3ac, .num_bits = 10}, /* ' ' 173 */ 185 | {.pattern = 0x3ad, .num_bits = 10}, /* ' ' 174 */ 186 | {.pattern = 0x3ae, .num_bits = 10}, /* ' ' 175 */ 187 | {.pattern = 0x3af, .num_bits = 10}, /* ' ' 176 */ 188 | {.pattern = 0x3b0, .num_bits = 10}, /* ' ' 177 */ 189 | {.pattern = 0x3b1, .num_bits = 10}, /* ' ' 178 */ 190 | {.pattern = 0x3b2, .num_bits = 10}, /* ' ' 179 */ 191 | {.pattern = 0x3b3, .num_bits = 10}, /* ' ' 180 */ 192 | {.pattern = 0x3b4, .num_bits = 10}, /* ' ' 181 */ 193 | {.pattern = 0x3b5, .num_bits = 10}, /* ' ' 182 */ 194 | {.pattern = 0x3b6, .num_bits = 10}, /* ' ' 183 */ 195 | {.pattern = 0x3b7, .num_bits = 10}, /* ' ' 184 */ 196 | {.pattern = 0x3b8, .num_bits = 10}, /* ' ' 185 */ 197 | {.pattern = 0x3b9, .num_bits = 10}, /* ' ' 186 */ 198 | {.pattern = 0x3ba, .num_bits = 10}, /* ' ' 187 */ 199 | {.pattern = 0x3bb, .num_bits = 10}, /* ' ' 188 */ 200 | {.pattern = 0x3bc, .num_bits = 10}, /* ' ' 189 */ 201 | {.pattern = 0x3bd, .num_bits = 10}, /* ' ' 190 */ 202 | {.pattern = 0x3be, .num_bits = 10}, /* ' ' 191 */ 203 | {.pattern = 0x3bf, .num_bits = 10}, /* ' ' 192 */ 204 | {.pattern = 0x3c0, .num_bits = 10}, /* ' ' 193 */ 205 | {.pattern = 0x3c1, .num_bits = 10}, /* ' ' 194 */ 206 | {.pattern = 0x3c2, .num_bits = 10}, /* ' ' 195 */ 207 | {.pattern = 0x3c3, .num_bits = 10}, /* ' ' 196 */ 208 | {.pattern = 0x3c4, .num_bits = 10}, /* ' ' 197 */ 209 | {.pattern = 0x3c5, .num_bits = 10}, /* ' ' 198 */ 210 | {.pattern = 0x3c6, .num_bits = 10}, /* ' ' 199 */ 211 | {.pattern = 0x3c7, .num_bits = 10}, /* ' ' 200 */ 212 | {.pattern = 0x3c8, .num_bits = 10}, /* ' ' 201 */ 213 | {.pattern = 0x3c9, .num_bits = 10}, /* ' ' 202 */ 214 | {.pattern = 0x3ca, .num_bits = 10}, /* ' ' 203 */ 215 | {.pattern = 0x3cb, .num_bits = 10}, /* ' ' 204 */ 216 | {.pattern = 0x3cc, .num_bits = 10}, /* ' ' 205 */ 217 | {.pattern = 0x3cd, .num_bits = 10}, /* ' ' 206 */ 218 | {.pattern = 0x3ce, .num_bits = 10}, /* ' ' 207 */ 219 | {.pattern = 0x3cf, .num_bits = 10}, /* ' ' 208 */ 220 | {.pattern = 0x3d0, .num_bits = 10}, /* ' ' 209 */ 221 | {.pattern = 0x3d1, .num_bits = 10}, /* ' ' 210 */ 222 | {.pattern = 0x3d2, .num_bits = 10}, /* ' ' 211 */ 223 | {.pattern = 0x3d3, .num_bits = 10}, /* ' ' 212 */ 224 | {.pattern = 0x3d4, .num_bits = 10}, /* ' ' 213 */ 225 | {.pattern = 0x3d5, .num_bits = 10}, /* ' ' 214 */ 226 | {.pattern = 0x3d6, .num_bits = 10}, /* ' ' 215 */ 227 | {.pattern = 0x3d7, .num_bits = 10}, /* ' ' 216 */ 228 | {.pattern = 0x3d8, .num_bits = 10}, /* ' ' 217 */ 229 | {.pattern = 0x3d9, .num_bits = 10}, /* ' ' 218 */ 230 | {.pattern = 0x3da, .num_bits = 10}, /* ' ' 219 */ 231 | {.pattern = 0x3db, .num_bits = 10}, /* ' ' 220 */ 232 | {.pattern = 0x3dc, .num_bits = 10}, /* ' ' 221 */ 233 | {.pattern = 0x3dd, .num_bits = 10}, /* ' ' 222 */ 234 | {.pattern = 0x3de, .num_bits = 10}, /* ' ' 223 */ 235 | {.pattern = 0x3df, .num_bits = 10}, /* ' ' 224 */ 236 | {.pattern = 0x3e0, .num_bits = 10}, /* ' ' 225 */ 237 | {.pattern = 0x3e1, .num_bits = 10}, /* ' ' 226 */ 238 | {.pattern = 0x3e2, .num_bits = 10}, /* ' ' 227 */ 239 | {.pattern = 0x3e3, .num_bits = 10}, /* ' ' 228 */ 240 | {.pattern = 0x3e4, .num_bits = 10}, /* ' ' 229 */ 241 | {.pattern = 0x3e5, .num_bits = 10}, /* ' ' 230 */ 242 | {.pattern = 0x3e6, .num_bits = 10}, /* ' ' 231 */ 243 | {.pattern = 0x3e7, .num_bits = 10}, /* ' ' 232 */ 244 | {.pattern = 0x3e8, .num_bits = 10}, /* ' ' 233 */ 245 | {.pattern = 0x3e9, .num_bits = 10}, /* ' ' 234 */ 246 | {.pattern = 0x3ea, .num_bits = 10}, /* ' ' 235 */ 247 | {.pattern = 0x3eb, .num_bits = 10}, /* ' ' 236 */ 248 | {.pattern = 0x3ec, .num_bits = 10}, /* ' ' 237 */ 249 | {.pattern = 0x3ed, .num_bits = 10}, /* ' ' 238 */ 250 | {.pattern = 0x3ee, .num_bits = 10}, /* ' ' 239 */ 251 | {.pattern = 0x3ef, .num_bits = 10}, /* ' ' 240 */ 252 | {.pattern = 0x3f0, .num_bits = 10}, /* ' ' 241 */ 253 | {.pattern = 0x3f1, .num_bits = 10}, /* ' ' 242 */ 254 | {.pattern = 0x3f2, .num_bits = 10}, /* ' ' 243 */ 255 | {.pattern = 0x3f3, .num_bits = 10}, /* ' ' 244 */ 256 | {.pattern = 0x3f4, .num_bits = 10}, /* ' ' 245 */ 257 | {.pattern = 0x3f5, .num_bits = 10}, /* ' ' 246 */ 258 | {.pattern = 0x3f6, .num_bits = 10}, /* ' ' 247 */ 259 | {.pattern = 0x3f7, .num_bits = 10}, /* ' ' 248 */ 260 | {.pattern = 0x3f8, .num_bits = 10}, /* ' ' 249 */ 261 | {.pattern = 0x3f9, .num_bits = 10}, /* ' ' 250 */ 262 | {.pattern = 0x3fa, .num_bits = 10}, /* ' ' 251 */ 263 | {.pattern = 0x3fb, .num_bits = 10}, /* ' ' 252 */ 264 | {.pattern = 0x3fc, .num_bits = 10}, /* ' ' 253 */ 265 | {.pattern = 0x3fd, .num_bits = 10}, /* ' ' 254 */ 266 | {.pattern = 0x3fe, .num_bits = 10}, /* ' ' 255 */ 267 | }; 268 | 269 | static struct aws_huffman_code encode_symbol(uint8_t symbol, void *userdata) { 270 | (void)userdata; 271 | 272 | return code_points[symbol]; 273 | } 274 | 275 | /* NOLINTNEXTLINE(readability-function-size) */ 276 | static uint8_t decode_symbol(uint32_t bits, uint8_t *symbol, void *userdata) { 277 | (void)userdata; 278 | 279 | if (bits & 0x80000000) { 280 | goto node_1; 281 | } else { 282 | goto node_0; 283 | } 284 | 285 | node_0: 286 | if (bits & 0x40000000) { 287 | goto node_01; 288 | } else { 289 | goto node_00; 290 | } 291 | 292 | node_00: 293 | if (bits & 0x20000000) { 294 | goto node_001; 295 | } else { 296 | return 0; /* invalid node */ 297 | } 298 | 299 | node_001: 300 | if (bits & 0x10000000) { 301 | goto node_0011; 302 | } else { 303 | goto node_0010; 304 | } 305 | 306 | node_0010: 307 | if (bits & 0x8000000) { 308 | *symbol = 97; 309 | return 5; 310 | } else { 311 | *symbol = 32; 312 | return 5; 313 | } 314 | 315 | node_0011: 316 | if (bits & 0x8000000) { 317 | *symbol = 105; 318 | return 5; 319 | } else { 320 | *symbol = 101; 321 | return 5; 322 | } 323 | 324 | node_01: 325 | if (bits & 0x20000000) { 326 | goto node_011; 327 | } else { 328 | goto node_010; 329 | } 330 | 331 | node_010: 332 | if (bits & 0x10000000) { 333 | goto node_0101; 334 | } else { 335 | goto node_0100; 336 | } 337 | 338 | node_0100: 339 | if (bits & 0x8000000) { 340 | *symbol = 111; 341 | return 5; 342 | } else { 343 | *symbol = 110; 344 | return 5; 345 | } 346 | 347 | node_0101: 348 | if (bits & 0x8000000) { 349 | *symbol = 115; 350 | return 5; 351 | } else { 352 | *symbol = 114; 353 | return 5; 354 | } 355 | 356 | node_011: 357 | if (bits & 0x10000000) { 358 | return 0; /* invalid node */ 359 | } else { 360 | goto node_0110; 361 | } 362 | 363 | node_0110: 364 | if (bits & 0x8000000) { 365 | *symbol = 117; 366 | return 5; 367 | } else { 368 | *symbol = 116; 369 | return 5; 370 | } 371 | 372 | node_1: 373 | if (bits & 0x40000000) { 374 | goto node_11; 375 | } else { 376 | goto node_10; 377 | } 378 | 379 | node_10: 380 | if (bits & 0x20000000) { 381 | goto node_101; 382 | } else { 383 | goto node_100; 384 | } 385 | 386 | node_100: 387 | if (bits & 0x10000000) { 388 | goto node_1001; 389 | } else { 390 | goto node_1000; 391 | } 392 | 393 | node_1000: 394 | if (bits & 0x8000000) { 395 | goto node_10001; 396 | } else { 397 | goto node_10000; 398 | } 399 | 400 | node_10000: 401 | if (bits & 0x4000000) { 402 | *symbol = 100; 403 | return 6; 404 | } else { 405 | *symbol = 99; 406 | return 6; 407 | } 408 | 409 | node_10001: 410 | if (bits & 0x4000000) { 411 | *symbol = 104; 412 | return 6; 413 | } else { 414 | *symbol = 102; 415 | return 6; 416 | } 417 | 418 | node_1001: 419 | if (bits & 0x8000000) { 420 | goto node_10011; 421 | } else { 422 | goto node_10010; 423 | } 424 | 425 | node_10010: 426 | if (bits & 0x4000000) { 427 | *symbol = 108; 428 | return 6; 429 | } else { 430 | *symbol = 107; 431 | return 6; 432 | } 433 | 434 | node_10011: 435 | if (bits & 0x4000000) { 436 | *symbol = 119; 437 | return 6; 438 | } else { 439 | *symbol = 109; 440 | return 6; 441 | } 442 | 443 | node_101: 444 | if (bits & 0x10000000) { 445 | goto node_1011; 446 | } else { 447 | goto node_1010; 448 | } 449 | 450 | node_1010: 451 | if (bits & 0x8000000) { 452 | goto node_10101; 453 | } else { 454 | goto node_10100; 455 | } 456 | 457 | node_10100: 458 | if (bits & 0x4000000) { 459 | return 0; /* invalid node */ 460 | } else { 461 | *symbol = 121; 462 | return 6; 463 | } 464 | 465 | node_10101: 466 | if (bits & 0x4000000) { 467 | goto node_101011; 468 | } else { 469 | return 0; /* invalid node */ 470 | } 471 | 472 | node_101011: 473 | if (bits & 0x2000000) { 474 | *symbol = 46; 475 | return 7; 476 | } else { 477 | *symbol = 39; 478 | return 7; 479 | } 480 | 481 | node_1011: 482 | if (bits & 0x8000000) { 483 | goto node_10111; 484 | } else { 485 | goto node_10110; 486 | } 487 | 488 | node_10110: 489 | if (bits & 0x4000000) { 490 | goto node_101101; 491 | } else { 492 | goto node_101100; 493 | } 494 | 495 | node_101100: 496 | if (bits & 0x2000000) { 497 | *symbol = 103; 498 | return 7; 499 | } else { 500 | *symbol = 98; 501 | return 7; 502 | } 503 | 504 | node_101101: 505 | if (bits & 0x2000000) { 506 | return 0; /* invalid node */ 507 | } else { 508 | *symbol = 112; 509 | return 7; 510 | } 511 | 512 | node_10111: 513 | if (bits & 0x4000000) { 514 | goto node_101111; 515 | } else { 516 | goto node_101110; 517 | } 518 | 519 | node_101110: 520 | if (bits & 0x2000000) { 521 | goto node_1011101; 522 | } else { 523 | goto node_1011100; 524 | } 525 | 526 | node_1011100: 527 | if (bits & 0x1000000) { 528 | *symbol = 44; 529 | return 8; 530 | } else { 531 | *symbol = 10; 532 | return 8; 533 | } 534 | 535 | node_1011101: 536 | if (bits & 0x1000000) { 537 | *symbol = 66; 538 | return 8; 539 | } else { 540 | *symbol = 63; 541 | return 8; 542 | } 543 | 544 | node_101111: 545 | if (bits & 0x2000000) { 546 | goto node_1011111; 547 | } else { 548 | goto node_1011110; 549 | } 550 | 551 | node_1011110: 552 | if (bits & 0x1000000) { 553 | *symbol = 84; 554 | return 8; 555 | } else { 556 | *symbol = 73; 557 | return 8; 558 | } 559 | 560 | node_1011111: 561 | if (bits & 0x1000000) { 562 | *symbol = 106; 563 | return 8; 564 | } else { 565 | *symbol = 87; 566 | return 8; 567 | } 568 | 569 | node_11: 570 | if (bits & 0x20000000) { 571 | goto node_111; 572 | } else { 573 | goto node_110; 574 | } 575 | 576 | node_110: 577 | if (bits & 0x10000000) { 578 | goto node_1101; 579 | } else { 580 | goto node_1100; 581 | } 582 | 583 | node_1100: 584 | if (bits & 0x8000000) { 585 | goto node_11001; 586 | } else { 587 | goto node_11000; 588 | } 589 | 590 | node_11000: 591 | if (bits & 0x4000000) { 592 | goto node_110001; 593 | } else { 594 | goto node_110000; 595 | } 596 | 597 | node_110000: 598 | if (bits & 0x2000000) { 599 | return 0; /* invalid node */ 600 | } else { 601 | goto node_1100000; 602 | } 603 | 604 | node_1100000: 605 | if (bits & 0x1000000) { 606 | *symbol = 120; 607 | return 8; 608 | } else { 609 | *symbol = 118; 610 | return 8; 611 | } 612 | 613 | node_110001: 614 | if (bits & 0x2000000) { 615 | goto node_1100011; 616 | } else { 617 | goto node_1100010; 618 | } 619 | 620 | node_1100010: 621 | if (bits & 0x1000000) { 622 | goto node_11000101; 623 | } else { 624 | goto node_11000100; 625 | } 626 | 627 | node_11000100: 628 | if (bits & 0x800000) { 629 | *symbol = 67; 630 | return 9; 631 | } else { 632 | *symbol = 45; 633 | return 9; 634 | } 635 | 636 | node_11000101: 637 | if (bits & 0x800000) { 638 | *symbol = 69; 639 | return 9; 640 | } else { 641 | *symbol = 68; 642 | return 9; 643 | } 644 | 645 | node_1100011: 646 | if (bits & 0x1000000) { 647 | goto node_11000111; 648 | } else { 649 | goto node_11000110; 650 | } 651 | 652 | node_11000110: 653 | if (bits & 0x800000) { 654 | *symbol = 71; 655 | return 9; 656 | } else { 657 | *symbol = 70; 658 | return 9; 659 | } 660 | 661 | node_11000111: 662 | if (bits & 0x800000) { 663 | *symbol = 76; 664 | return 9; 665 | } else { 666 | *symbol = 72; 667 | return 9; 668 | } 669 | 670 | node_11001: 671 | if (bits & 0x4000000) { 672 | goto node_110011; 673 | } else { 674 | goto node_110010; 675 | } 676 | 677 | node_110010: 678 | if (bits & 0x2000000) { 679 | goto node_1100101; 680 | } else { 681 | goto node_1100100; 682 | } 683 | 684 | node_1100100: 685 | if (bits & 0x1000000) { 686 | goto node_11001001; 687 | } else { 688 | goto node_11001000; 689 | } 690 | 691 | node_11001000: 692 | if (bits & 0x800000) { 693 | *symbol = 80; 694 | return 9; 695 | } else { 696 | *symbol = 77; 697 | return 9; 698 | } 699 | 700 | node_11001001: 701 | if (bits & 0x800000) { 702 | *symbol = 89; 703 | return 9; 704 | } else { 705 | *symbol = 86; 706 | return 9; 707 | } 708 | 709 | node_1100101: 710 | if (bits & 0x1000000) { 711 | goto node_11001011; 712 | } else { 713 | goto node_11001010; 714 | } 715 | 716 | node_11001010: 717 | if (bits & 0x800000) { 718 | return 0; /* invalid node */ 719 | } else { 720 | *symbol = 113; 721 | return 9; 722 | } 723 | 724 | node_11001011: 725 | if (bits & 0x800000) { 726 | goto node_110010111; 727 | } else { 728 | return 0; /* invalid node */ 729 | } 730 | 731 | node_110010111: 732 | if (bits & 0x400000) { 733 | *symbol = 1; 734 | return 10; 735 | } else { 736 | *symbol = 0; 737 | return 10; 738 | } 739 | 740 | node_110011: 741 | if (bits & 0x2000000) { 742 | goto node_1100111; 743 | } else { 744 | goto node_1100110; 745 | } 746 | 747 | node_1100110: 748 | if (bits & 0x1000000) { 749 | goto node_11001101; 750 | } else { 751 | goto node_11001100; 752 | } 753 | 754 | node_11001100: 755 | if (bits & 0x800000) { 756 | goto node_110011001; 757 | } else { 758 | goto node_110011000; 759 | } 760 | 761 | node_110011000: 762 | if (bits & 0x400000) { 763 | *symbol = 3; 764 | return 10; 765 | } else { 766 | *symbol = 2; 767 | return 10; 768 | } 769 | 770 | node_110011001: 771 | if (bits & 0x400000) { 772 | *symbol = 5; 773 | return 10; 774 | } else { 775 | *symbol = 4; 776 | return 10; 777 | } 778 | 779 | node_11001101: 780 | if (bits & 0x800000) { 781 | goto node_110011011; 782 | } else { 783 | goto node_110011010; 784 | } 785 | 786 | node_110011010: 787 | if (bits & 0x400000) { 788 | *symbol = 7; 789 | return 10; 790 | } else { 791 | *symbol = 6; 792 | return 10; 793 | } 794 | 795 | node_110011011: 796 | if (bits & 0x400000) { 797 | *symbol = 9; 798 | return 10; 799 | } else { 800 | *symbol = 8; 801 | return 10; 802 | } 803 | 804 | node_1100111: 805 | if (bits & 0x1000000) { 806 | goto node_11001111; 807 | } else { 808 | goto node_11001110; 809 | } 810 | 811 | node_11001110: 812 | if (bits & 0x800000) { 813 | goto node_110011101; 814 | } else { 815 | goto node_110011100; 816 | } 817 | 818 | node_110011100: 819 | if (bits & 0x400000) { 820 | *symbol = 12; 821 | return 10; 822 | } else { 823 | *symbol = 11; 824 | return 10; 825 | } 826 | 827 | node_110011101: 828 | if (bits & 0x400000) { 829 | *symbol = 14; 830 | return 10; 831 | } else { 832 | *symbol = 13; 833 | return 10; 834 | } 835 | 836 | node_11001111: 837 | if (bits & 0x800000) { 838 | goto node_110011111; 839 | } else { 840 | goto node_110011110; 841 | } 842 | 843 | node_110011110: 844 | if (bits & 0x400000) { 845 | *symbol = 16; 846 | return 10; 847 | } else { 848 | *symbol = 15; 849 | return 10; 850 | } 851 | 852 | node_110011111: 853 | if (bits & 0x400000) { 854 | *symbol = 18; 855 | return 10; 856 | } else { 857 | *symbol = 17; 858 | return 10; 859 | } 860 | 861 | node_1101: 862 | if (bits & 0x8000000) { 863 | goto node_11011; 864 | } else { 865 | goto node_11010; 866 | } 867 | 868 | node_11010: 869 | if (bits & 0x4000000) { 870 | goto node_110101; 871 | } else { 872 | goto node_110100; 873 | } 874 | 875 | node_110100: 876 | if (bits & 0x2000000) { 877 | goto node_1101001; 878 | } else { 879 | goto node_1101000; 880 | } 881 | 882 | node_1101000: 883 | if (bits & 0x1000000) { 884 | goto node_11010001; 885 | } else { 886 | goto node_11010000; 887 | } 888 | 889 | node_11010000: 890 | if (bits & 0x800000) { 891 | goto node_110100001; 892 | } else { 893 | goto node_110100000; 894 | } 895 | 896 | node_110100000: 897 | if (bits & 0x400000) { 898 | *symbol = 20; 899 | return 10; 900 | } else { 901 | *symbol = 19; 902 | return 10; 903 | } 904 | 905 | node_110100001: 906 | if (bits & 0x400000) { 907 | *symbol = 22; 908 | return 10; 909 | } else { 910 | *symbol = 21; 911 | return 10; 912 | } 913 | 914 | node_11010001: 915 | if (bits & 0x800000) { 916 | goto node_110100011; 917 | } else { 918 | goto node_110100010; 919 | } 920 | 921 | node_110100010: 922 | if (bits & 0x400000) { 923 | *symbol = 24; 924 | return 10; 925 | } else { 926 | *symbol = 23; 927 | return 10; 928 | } 929 | 930 | node_110100011: 931 | if (bits & 0x400000) { 932 | *symbol = 26; 933 | return 10; 934 | } else { 935 | *symbol = 25; 936 | return 10; 937 | } 938 | 939 | node_1101001: 940 | if (bits & 0x1000000) { 941 | goto node_11010011; 942 | } else { 943 | goto node_11010010; 944 | } 945 | 946 | node_11010010: 947 | if (bits & 0x800000) { 948 | goto node_110100101; 949 | } else { 950 | goto node_110100100; 951 | } 952 | 953 | node_110100100: 954 | if (bits & 0x400000) { 955 | *symbol = 28; 956 | return 10; 957 | } else { 958 | *symbol = 27; 959 | return 10; 960 | } 961 | 962 | node_110100101: 963 | if (bits & 0x400000) { 964 | *symbol = 30; 965 | return 10; 966 | } else { 967 | *symbol = 29; 968 | return 10; 969 | } 970 | 971 | node_11010011: 972 | if (bits & 0x800000) { 973 | goto node_110100111; 974 | } else { 975 | goto node_110100110; 976 | } 977 | 978 | node_110100110: 979 | if (bits & 0x400000) { 980 | *symbol = 33; 981 | return 10; 982 | } else { 983 | *symbol = 31; 984 | return 10; 985 | } 986 | 987 | node_110100111: 988 | if (bits & 0x400000) { 989 | *symbol = 35; 990 | return 10; 991 | } else { 992 | *symbol = 34; 993 | return 10; 994 | } 995 | 996 | node_110101: 997 | if (bits & 0x2000000) { 998 | goto node_1101011; 999 | } else { 1000 | goto node_1101010; 1001 | } 1002 | 1003 | node_1101010: 1004 | if (bits & 0x1000000) { 1005 | goto node_11010101; 1006 | } else { 1007 | goto node_11010100; 1008 | } 1009 | 1010 | node_11010100: 1011 | if (bits & 0x800000) { 1012 | goto node_110101001; 1013 | } else { 1014 | goto node_110101000; 1015 | } 1016 | 1017 | node_110101000: 1018 | if (bits & 0x400000) { 1019 | *symbol = 37; 1020 | return 10; 1021 | } else { 1022 | *symbol = 36; 1023 | return 10; 1024 | } 1025 | 1026 | node_110101001: 1027 | if (bits & 0x400000) { 1028 | *symbol = 40; 1029 | return 10; 1030 | } else { 1031 | *symbol = 38; 1032 | return 10; 1033 | } 1034 | 1035 | node_11010101: 1036 | if (bits & 0x800000) { 1037 | goto node_110101011; 1038 | } else { 1039 | goto node_110101010; 1040 | } 1041 | 1042 | node_110101010: 1043 | if (bits & 0x400000) { 1044 | *symbol = 42; 1045 | return 10; 1046 | } else { 1047 | *symbol = 41; 1048 | return 10; 1049 | } 1050 | 1051 | node_110101011: 1052 | if (bits & 0x400000) { 1053 | *symbol = 47; 1054 | return 10; 1055 | } else { 1056 | *symbol = 43; 1057 | return 10; 1058 | } 1059 | 1060 | node_1101011: 1061 | if (bits & 0x1000000) { 1062 | goto node_11010111; 1063 | } else { 1064 | goto node_11010110; 1065 | } 1066 | 1067 | node_11010110: 1068 | if (bits & 0x800000) { 1069 | goto node_110101101; 1070 | } else { 1071 | goto node_110101100; 1072 | } 1073 | 1074 | node_110101100: 1075 | if (bits & 0x400000) { 1076 | *symbol = 49; 1077 | return 10; 1078 | } else { 1079 | *symbol = 48; 1080 | return 10; 1081 | } 1082 | 1083 | node_110101101: 1084 | if (bits & 0x400000) { 1085 | *symbol = 51; 1086 | return 10; 1087 | } else { 1088 | *symbol = 50; 1089 | return 10; 1090 | } 1091 | 1092 | node_11010111: 1093 | if (bits & 0x800000) { 1094 | goto node_110101111; 1095 | } else { 1096 | goto node_110101110; 1097 | } 1098 | 1099 | node_110101110: 1100 | if (bits & 0x400000) { 1101 | *symbol = 53; 1102 | return 10; 1103 | } else { 1104 | *symbol = 52; 1105 | return 10; 1106 | } 1107 | 1108 | node_110101111: 1109 | if (bits & 0x400000) { 1110 | *symbol = 55; 1111 | return 10; 1112 | } else { 1113 | *symbol = 54; 1114 | return 10; 1115 | } 1116 | 1117 | node_11011: 1118 | if (bits & 0x4000000) { 1119 | goto node_110111; 1120 | } else { 1121 | goto node_110110; 1122 | } 1123 | 1124 | node_110110: 1125 | if (bits & 0x2000000) { 1126 | goto node_1101101; 1127 | } else { 1128 | goto node_1101100; 1129 | } 1130 | 1131 | node_1101100: 1132 | if (bits & 0x1000000) { 1133 | goto node_11011001; 1134 | } else { 1135 | goto node_11011000; 1136 | } 1137 | 1138 | node_11011000: 1139 | if (bits & 0x800000) { 1140 | goto node_110110001; 1141 | } else { 1142 | goto node_110110000; 1143 | } 1144 | 1145 | node_110110000: 1146 | if (bits & 0x400000) { 1147 | *symbol = 57; 1148 | return 10; 1149 | } else { 1150 | *symbol = 56; 1151 | return 10; 1152 | } 1153 | 1154 | node_110110001: 1155 | if (bits & 0x400000) { 1156 | *symbol = 59; 1157 | return 10; 1158 | } else { 1159 | *symbol = 58; 1160 | return 10; 1161 | } 1162 | 1163 | node_11011001: 1164 | if (bits & 0x800000) { 1165 | goto node_110110011; 1166 | } else { 1167 | goto node_110110010; 1168 | } 1169 | 1170 | node_110110010: 1171 | if (bits & 0x400000) { 1172 | *symbol = 61; 1173 | return 10; 1174 | } else { 1175 | *symbol = 60; 1176 | return 10; 1177 | } 1178 | 1179 | node_110110011: 1180 | if (bits & 0x400000) { 1181 | *symbol = 64; 1182 | return 10; 1183 | } else { 1184 | *symbol = 62; 1185 | return 10; 1186 | } 1187 | 1188 | node_1101101: 1189 | if (bits & 0x1000000) { 1190 | goto node_11011011; 1191 | } else { 1192 | goto node_11011010; 1193 | } 1194 | 1195 | node_11011010: 1196 | if (bits & 0x800000) { 1197 | goto node_110110101; 1198 | } else { 1199 | goto node_110110100; 1200 | } 1201 | 1202 | node_110110100: 1203 | if (bits & 0x400000) { 1204 | *symbol = 74; 1205 | return 10; 1206 | } else { 1207 | *symbol = 65; 1208 | return 10; 1209 | } 1210 | 1211 | node_110110101: 1212 | if (bits & 0x400000) { 1213 | *symbol = 78; 1214 | return 10; 1215 | } else { 1216 | *symbol = 75; 1217 | return 10; 1218 | } 1219 | 1220 | node_11011011: 1221 | if (bits & 0x800000) { 1222 | goto node_110110111; 1223 | } else { 1224 | goto node_110110110; 1225 | } 1226 | 1227 | node_110110110: 1228 | if (bits & 0x400000) { 1229 | *symbol = 81; 1230 | return 10; 1231 | } else { 1232 | *symbol = 79; 1233 | return 10; 1234 | } 1235 | 1236 | node_110110111: 1237 | if (bits & 0x400000) { 1238 | *symbol = 83; 1239 | return 10; 1240 | } else { 1241 | *symbol = 82; 1242 | return 10; 1243 | } 1244 | 1245 | node_110111: 1246 | if (bits & 0x2000000) { 1247 | goto node_1101111; 1248 | } else { 1249 | goto node_1101110; 1250 | } 1251 | 1252 | node_1101110: 1253 | if (bits & 0x1000000) { 1254 | goto node_11011101; 1255 | } else { 1256 | goto node_11011100; 1257 | } 1258 | 1259 | node_11011100: 1260 | if (bits & 0x800000) { 1261 | goto node_110111001; 1262 | } else { 1263 | goto node_110111000; 1264 | } 1265 | 1266 | node_110111000: 1267 | if (bits & 0x400000) { 1268 | *symbol = 88; 1269 | return 10; 1270 | } else { 1271 | *symbol = 85; 1272 | return 10; 1273 | } 1274 | 1275 | node_110111001: 1276 | if (bits & 0x400000) { 1277 | *symbol = 91; 1278 | return 10; 1279 | } else { 1280 | *symbol = 90; 1281 | return 10; 1282 | } 1283 | 1284 | node_11011101: 1285 | if (bits & 0x800000) { 1286 | goto node_110111011; 1287 | } else { 1288 | goto node_110111010; 1289 | } 1290 | 1291 | node_110111010: 1292 | if (bits & 0x400000) { 1293 | *symbol = 93; 1294 | return 10; 1295 | } else { 1296 | *symbol = 92; 1297 | return 10; 1298 | } 1299 | 1300 | node_110111011: 1301 | if (bits & 0x400000) { 1302 | *symbol = 95; 1303 | return 10; 1304 | } else { 1305 | *symbol = 94; 1306 | return 10; 1307 | } 1308 | 1309 | node_1101111: 1310 | if (bits & 0x1000000) { 1311 | goto node_11011111; 1312 | } else { 1313 | goto node_11011110; 1314 | } 1315 | 1316 | node_11011110: 1317 | if (bits & 0x800000) { 1318 | goto node_110111101; 1319 | } else { 1320 | goto node_110111100; 1321 | } 1322 | 1323 | node_110111100: 1324 | if (bits & 0x400000) { 1325 | *symbol = 122; 1326 | return 10; 1327 | } else { 1328 | *symbol = 96; 1329 | return 10; 1330 | } 1331 | 1332 | node_110111101: 1333 | if (bits & 0x400000) { 1334 | *symbol = 124; 1335 | return 10; 1336 | } else { 1337 | *symbol = 123; 1338 | return 10; 1339 | } 1340 | 1341 | node_11011111: 1342 | if (bits & 0x800000) { 1343 | goto node_110111111; 1344 | } else { 1345 | goto node_110111110; 1346 | } 1347 | 1348 | node_110111110: 1349 | if (bits & 0x400000) { 1350 | *symbol = 126; 1351 | return 10; 1352 | } else { 1353 | *symbol = 125; 1354 | return 10; 1355 | } 1356 | 1357 | node_110111111: 1358 | if (bits & 0x400000) { 1359 | *symbol = 128; 1360 | return 10; 1361 | } else { 1362 | *symbol = 127; 1363 | return 10; 1364 | } 1365 | 1366 | node_111: 1367 | if (bits & 0x10000000) { 1368 | goto node_1111; 1369 | } else { 1370 | goto node_1110; 1371 | } 1372 | 1373 | node_1110: 1374 | if (bits & 0x8000000) { 1375 | goto node_11101; 1376 | } else { 1377 | goto node_11100; 1378 | } 1379 | 1380 | node_11100: 1381 | if (bits & 0x4000000) { 1382 | goto node_111001; 1383 | } else { 1384 | goto node_111000; 1385 | } 1386 | 1387 | node_111000: 1388 | if (bits & 0x2000000) { 1389 | goto node_1110001; 1390 | } else { 1391 | goto node_1110000; 1392 | } 1393 | 1394 | node_1110000: 1395 | if (bits & 0x1000000) { 1396 | goto node_11100001; 1397 | } else { 1398 | goto node_11100000; 1399 | } 1400 | 1401 | node_11100000: 1402 | if (bits & 0x800000) { 1403 | goto node_111000001; 1404 | } else { 1405 | goto node_111000000; 1406 | } 1407 | 1408 | node_111000000: 1409 | if (bits & 0x400000) { 1410 | *symbol = 130; 1411 | return 10; 1412 | } else { 1413 | *symbol = 129; 1414 | return 10; 1415 | } 1416 | 1417 | node_111000001: 1418 | if (bits & 0x400000) { 1419 | *symbol = 132; 1420 | return 10; 1421 | } else { 1422 | *symbol = 131; 1423 | return 10; 1424 | } 1425 | 1426 | node_11100001: 1427 | if (bits & 0x800000) { 1428 | goto node_111000011; 1429 | } else { 1430 | goto node_111000010; 1431 | } 1432 | 1433 | node_111000010: 1434 | if (bits & 0x400000) { 1435 | *symbol = 134; 1436 | return 10; 1437 | } else { 1438 | *symbol = 133; 1439 | return 10; 1440 | } 1441 | 1442 | node_111000011: 1443 | if (bits & 0x400000) { 1444 | *symbol = 136; 1445 | return 10; 1446 | } else { 1447 | *symbol = 135; 1448 | return 10; 1449 | } 1450 | 1451 | node_1110001: 1452 | if (bits & 0x1000000) { 1453 | goto node_11100011; 1454 | } else { 1455 | goto node_11100010; 1456 | } 1457 | 1458 | node_11100010: 1459 | if (bits & 0x800000) { 1460 | goto node_111000101; 1461 | } else { 1462 | goto node_111000100; 1463 | } 1464 | 1465 | node_111000100: 1466 | if (bits & 0x400000) { 1467 | *symbol = 138; 1468 | return 10; 1469 | } else { 1470 | *symbol = 137; 1471 | return 10; 1472 | } 1473 | 1474 | node_111000101: 1475 | if (bits & 0x400000) { 1476 | *symbol = 140; 1477 | return 10; 1478 | } else { 1479 | *symbol = 139; 1480 | return 10; 1481 | } 1482 | 1483 | node_11100011: 1484 | if (bits & 0x800000) { 1485 | goto node_111000111; 1486 | } else { 1487 | goto node_111000110; 1488 | } 1489 | 1490 | node_111000110: 1491 | if (bits & 0x400000) { 1492 | *symbol = 142; 1493 | return 10; 1494 | } else { 1495 | *symbol = 141; 1496 | return 10; 1497 | } 1498 | 1499 | node_111000111: 1500 | if (bits & 0x400000) { 1501 | *symbol = 144; 1502 | return 10; 1503 | } else { 1504 | *symbol = 143; 1505 | return 10; 1506 | } 1507 | 1508 | node_111001: 1509 | if (bits & 0x2000000) { 1510 | goto node_1110011; 1511 | } else { 1512 | goto node_1110010; 1513 | } 1514 | 1515 | node_1110010: 1516 | if (bits & 0x1000000) { 1517 | goto node_11100101; 1518 | } else { 1519 | goto node_11100100; 1520 | } 1521 | 1522 | node_11100100: 1523 | if (bits & 0x800000) { 1524 | goto node_111001001; 1525 | } else { 1526 | goto node_111001000; 1527 | } 1528 | 1529 | node_111001000: 1530 | if (bits & 0x400000) { 1531 | *symbol = 146; 1532 | return 10; 1533 | } else { 1534 | *symbol = 145; 1535 | return 10; 1536 | } 1537 | 1538 | node_111001001: 1539 | if (bits & 0x400000) { 1540 | *symbol = 148; 1541 | return 10; 1542 | } else { 1543 | *symbol = 147; 1544 | return 10; 1545 | } 1546 | 1547 | node_11100101: 1548 | if (bits & 0x800000) { 1549 | goto node_111001011; 1550 | } else { 1551 | goto node_111001010; 1552 | } 1553 | 1554 | node_111001010: 1555 | if (bits & 0x400000) { 1556 | *symbol = 150; 1557 | return 10; 1558 | } else { 1559 | *symbol = 149; 1560 | return 10; 1561 | } 1562 | 1563 | node_111001011: 1564 | if (bits & 0x400000) { 1565 | *symbol = 152; 1566 | return 10; 1567 | } else { 1568 | *symbol = 151; 1569 | return 10; 1570 | } 1571 | 1572 | node_1110011: 1573 | if (bits & 0x1000000) { 1574 | goto node_11100111; 1575 | } else { 1576 | goto node_11100110; 1577 | } 1578 | 1579 | node_11100110: 1580 | if (bits & 0x800000) { 1581 | goto node_111001101; 1582 | } else { 1583 | goto node_111001100; 1584 | } 1585 | 1586 | node_111001100: 1587 | if (bits & 0x400000) { 1588 | *symbol = 154; 1589 | return 10; 1590 | } else { 1591 | *symbol = 153; 1592 | return 10; 1593 | } 1594 | 1595 | node_111001101: 1596 | if (bits & 0x400000) { 1597 | *symbol = 156; 1598 | return 10; 1599 | } else { 1600 | *symbol = 155; 1601 | return 10; 1602 | } 1603 | 1604 | node_11100111: 1605 | if (bits & 0x800000) { 1606 | goto node_111001111; 1607 | } else { 1608 | goto node_111001110; 1609 | } 1610 | 1611 | node_111001110: 1612 | if (bits & 0x400000) { 1613 | *symbol = 158; 1614 | return 10; 1615 | } else { 1616 | *symbol = 157; 1617 | return 10; 1618 | } 1619 | 1620 | node_111001111: 1621 | if (bits & 0x400000) { 1622 | *symbol = 160; 1623 | return 10; 1624 | } else { 1625 | *symbol = 159; 1626 | return 10; 1627 | } 1628 | 1629 | node_11101: 1630 | if (bits & 0x4000000) { 1631 | goto node_111011; 1632 | } else { 1633 | goto node_111010; 1634 | } 1635 | 1636 | node_111010: 1637 | if (bits & 0x2000000) { 1638 | goto node_1110101; 1639 | } else { 1640 | goto node_1110100; 1641 | } 1642 | 1643 | node_1110100: 1644 | if (bits & 0x1000000) { 1645 | goto node_11101001; 1646 | } else { 1647 | goto node_11101000; 1648 | } 1649 | 1650 | node_11101000: 1651 | if (bits & 0x800000) { 1652 | goto node_111010001; 1653 | } else { 1654 | goto node_111010000; 1655 | } 1656 | 1657 | node_111010000: 1658 | if (bits & 0x400000) { 1659 | *symbol = 162; 1660 | return 10; 1661 | } else { 1662 | *symbol = 161; 1663 | return 10; 1664 | } 1665 | 1666 | node_111010001: 1667 | if (bits & 0x400000) { 1668 | *symbol = 164; 1669 | return 10; 1670 | } else { 1671 | *symbol = 163; 1672 | return 10; 1673 | } 1674 | 1675 | node_11101001: 1676 | if (bits & 0x800000) { 1677 | goto node_111010011; 1678 | } else { 1679 | goto node_111010010; 1680 | } 1681 | 1682 | node_111010010: 1683 | if (bits & 0x400000) { 1684 | *symbol = 166; 1685 | return 10; 1686 | } else { 1687 | *symbol = 165; 1688 | return 10; 1689 | } 1690 | 1691 | node_111010011: 1692 | if (bits & 0x400000) { 1693 | *symbol = 168; 1694 | return 10; 1695 | } else { 1696 | *symbol = 167; 1697 | return 10; 1698 | } 1699 | 1700 | node_1110101: 1701 | if (bits & 0x1000000) { 1702 | goto node_11101011; 1703 | } else { 1704 | goto node_11101010; 1705 | } 1706 | 1707 | node_11101010: 1708 | if (bits & 0x800000) { 1709 | goto node_111010101; 1710 | } else { 1711 | goto node_111010100; 1712 | } 1713 | 1714 | node_111010100: 1715 | if (bits & 0x400000) { 1716 | *symbol = 170; 1717 | return 10; 1718 | } else { 1719 | *symbol = 169; 1720 | return 10; 1721 | } 1722 | 1723 | node_111010101: 1724 | if (bits & 0x400000) { 1725 | *symbol = 172; 1726 | return 10; 1727 | } else { 1728 | *symbol = 171; 1729 | return 10; 1730 | } 1731 | 1732 | node_11101011: 1733 | if (bits & 0x800000) { 1734 | goto node_111010111; 1735 | } else { 1736 | goto node_111010110; 1737 | } 1738 | 1739 | node_111010110: 1740 | if (bits & 0x400000) { 1741 | *symbol = 174; 1742 | return 10; 1743 | } else { 1744 | *symbol = 173; 1745 | return 10; 1746 | } 1747 | 1748 | node_111010111: 1749 | if (bits & 0x400000) { 1750 | *symbol = 176; 1751 | return 10; 1752 | } else { 1753 | *symbol = 175; 1754 | return 10; 1755 | } 1756 | 1757 | node_111011: 1758 | if (bits & 0x2000000) { 1759 | goto node_1110111; 1760 | } else { 1761 | goto node_1110110; 1762 | } 1763 | 1764 | node_1110110: 1765 | if (bits & 0x1000000) { 1766 | goto node_11101101; 1767 | } else { 1768 | goto node_11101100; 1769 | } 1770 | 1771 | node_11101100: 1772 | if (bits & 0x800000) { 1773 | goto node_111011001; 1774 | } else { 1775 | goto node_111011000; 1776 | } 1777 | 1778 | node_111011000: 1779 | if (bits & 0x400000) { 1780 | *symbol = 178; 1781 | return 10; 1782 | } else { 1783 | *symbol = 177; 1784 | return 10; 1785 | } 1786 | 1787 | node_111011001: 1788 | if (bits & 0x400000) { 1789 | *symbol = 180; 1790 | return 10; 1791 | } else { 1792 | *symbol = 179; 1793 | return 10; 1794 | } 1795 | 1796 | node_11101101: 1797 | if (bits & 0x800000) { 1798 | goto node_111011011; 1799 | } else { 1800 | goto node_111011010; 1801 | } 1802 | 1803 | node_111011010: 1804 | if (bits & 0x400000) { 1805 | *symbol = 182; 1806 | return 10; 1807 | } else { 1808 | *symbol = 181; 1809 | return 10; 1810 | } 1811 | 1812 | node_111011011: 1813 | if (bits & 0x400000) { 1814 | *symbol = 184; 1815 | return 10; 1816 | } else { 1817 | *symbol = 183; 1818 | return 10; 1819 | } 1820 | 1821 | node_1110111: 1822 | if (bits & 0x1000000) { 1823 | goto node_11101111; 1824 | } else { 1825 | goto node_11101110; 1826 | } 1827 | 1828 | node_11101110: 1829 | if (bits & 0x800000) { 1830 | goto node_111011101; 1831 | } else { 1832 | goto node_111011100; 1833 | } 1834 | 1835 | node_111011100: 1836 | if (bits & 0x400000) { 1837 | *symbol = 186; 1838 | return 10; 1839 | } else { 1840 | *symbol = 185; 1841 | return 10; 1842 | } 1843 | 1844 | node_111011101: 1845 | if (bits & 0x400000) { 1846 | *symbol = 188; 1847 | return 10; 1848 | } else { 1849 | *symbol = 187; 1850 | return 10; 1851 | } 1852 | 1853 | node_11101111: 1854 | if (bits & 0x800000) { 1855 | goto node_111011111; 1856 | } else { 1857 | goto node_111011110; 1858 | } 1859 | 1860 | node_111011110: 1861 | if (bits & 0x400000) { 1862 | *symbol = 190; 1863 | return 10; 1864 | } else { 1865 | *symbol = 189; 1866 | return 10; 1867 | } 1868 | 1869 | node_111011111: 1870 | if (bits & 0x400000) { 1871 | *symbol = 192; 1872 | return 10; 1873 | } else { 1874 | *symbol = 191; 1875 | return 10; 1876 | } 1877 | 1878 | node_1111: 1879 | if (bits & 0x8000000) { 1880 | goto node_11111; 1881 | } else { 1882 | goto node_11110; 1883 | } 1884 | 1885 | node_11110: 1886 | if (bits & 0x4000000) { 1887 | goto node_111101; 1888 | } else { 1889 | goto node_111100; 1890 | } 1891 | 1892 | node_111100: 1893 | if (bits & 0x2000000) { 1894 | goto node_1111001; 1895 | } else { 1896 | goto node_1111000; 1897 | } 1898 | 1899 | node_1111000: 1900 | if (bits & 0x1000000) { 1901 | goto node_11110001; 1902 | } else { 1903 | goto node_11110000; 1904 | } 1905 | 1906 | node_11110000: 1907 | if (bits & 0x800000) { 1908 | goto node_111100001; 1909 | } else { 1910 | goto node_111100000; 1911 | } 1912 | 1913 | node_111100000: 1914 | if (bits & 0x400000) { 1915 | *symbol = 194; 1916 | return 10; 1917 | } else { 1918 | *symbol = 193; 1919 | return 10; 1920 | } 1921 | 1922 | node_111100001: 1923 | if (bits & 0x400000) { 1924 | *symbol = 196; 1925 | return 10; 1926 | } else { 1927 | *symbol = 195; 1928 | return 10; 1929 | } 1930 | 1931 | node_11110001: 1932 | if (bits & 0x800000) { 1933 | goto node_111100011; 1934 | } else { 1935 | goto node_111100010; 1936 | } 1937 | 1938 | node_111100010: 1939 | if (bits & 0x400000) { 1940 | *symbol = 198; 1941 | return 10; 1942 | } else { 1943 | *symbol = 197; 1944 | return 10; 1945 | } 1946 | 1947 | node_111100011: 1948 | if (bits & 0x400000) { 1949 | *symbol = 200; 1950 | return 10; 1951 | } else { 1952 | *symbol = 199; 1953 | return 10; 1954 | } 1955 | 1956 | node_1111001: 1957 | if (bits & 0x1000000) { 1958 | goto node_11110011; 1959 | } else { 1960 | goto node_11110010; 1961 | } 1962 | 1963 | node_11110010: 1964 | if (bits & 0x800000) { 1965 | goto node_111100101; 1966 | } else { 1967 | goto node_111100100; 1968 | } 1969 | 1970 | node_111100100: 1971 | if (bits & 0x400000) { 1972 | *symbol = 202; 1973 | return 10; 1974 | } else { 1975 | *symbol = 201; 1976 | return 10; 1977 | } 1978 | 1979 | node_111100101: 1980 | if (bits & 0x400000) { 1981 | *symbol = 204; 1982 | return 10; 1983 | } else { 1984 | *symbol = 203; 1985 | return 10; 1986 | } 1987 | 1988 | node_11110011: 1989 | if (bits & 0x800000) { 1990 | goto node_111100111; 1991 | } else { 1992 | goto node_111100110; 1993 | } 1994 | 1995 | node_111100110: 1996 | if (bits & 0x400000) { 1997 | *symbol = 206; 1998 | return 10; 1999 | } else { 2000 | *symbol = 205; 2001 | return 10; 2002 | } 2003 | 2004 | node_111100111: 2005 | if (bits & 0x400000) { 2006 | *symbol = 208; 2007 | return 10; 2008 | } else { 2009 | *symbol = 207; 2010 | return 10; 2011 | } 2012 | 2013 | node_111101: 2014 | if (bits & 0x2000000) { 2015 | goto node_1111011; 2016 | } else { 2017 | goto node_1111010; 2018 | } 2019 | 2020 | node_1111010: 2021 | if (bits & 0x1000000) { 2022 | goto node_11110101; 2023 | } else { 2024 | goto node_11110100; 2025 | } 2026 | 2027 | node_11110100: 2028 | if (bits & 0x800000) { 2029 | goto node_111101001; 2030 | } else { 2031 | goto node_111101000; 2032 | } 2033 | 2034 | node_111101000: 2035 | if (bits & 0x400000) { 2036 | *symbol = 210; 2037 | return 10; 2038 | } else { 2039 | *symbol = 209; 2040 | return 10; 2041 | } 2042 | 2043 | node_111101001: 2044 | if (bits & 0x400000) { 2045 | *symbol = 212; 2046 | return 10; 2047 | } else { 2048 | *symbol = 211; 2049 | return 10; 2050 | } 2051 | 2052 | node_11110101: 2053 | if (bits & 0x800000) { 2054 | goto node_111101011; 2055 | } else { 2056 | goto node_111101010; 2057 | } 2058 | 2059 | node_111101010: 2060 | if (bits & 0x400000) { 2061 | *symbol = 214; 2062 | return 10; 2063 | } else { 2064 | *symbol = 213; 2065 | return 10; 2066 | } 2067 | 2068 | node_111101011: 2069 | if (bits & 0x400000) { 2070 | *symbol = 216; 2071 | return 10; 2072 | } else { 2073 | *symbol = 215; 2074 | return 10; 2075 | } 2076 | 2077 | node_1111011: 2078 | if (bits & 0x1000000) { 2079 | goto node_11110111; 2080 | } else { 2081 | goto node_11110110; 2082 | } 2083 | 2084 | node_11110110: 2085 | if (bits & 0x800000) { 2086 | goto node_111101101; 2087 | } else { 2088 | goto node_111101100; 2089 | } 2090 | 2091 | node_111101100: 2092 | if (bits & 0x400000) { 2093 | *symbol = 218; 2094 | return 10; 2095 | } else { 2096 | *symbol = 217; 2097 | return 10; 2098 | } 2099 | 2100 | node_111101101: 2101 | if (bits & 0x400000) { 2102 | *symbol = 220; 2103 | return 10; 2104 | } else { 2105 | *symbol = 219; 2106 | return 10; 2107 | } 2108 | 2109 | node_11110111: 2110 | if (bits & 0x800000) { 2111 | goto node_111101111; 2112 | } else { 2113 | goto node_111101110; 2114 | } 2115 | 2116 | node_111101110: 2117 | if (bits & 0x400000) { 2118 | *symbol = 222; 2119 | return 10; 2120 | } else { 2121 | *symbol = 221; 2122 | return 10; 2123 | } 2124 | 2125 | node_111101111: 2126 | if (bits & 0x400000) { 2127 | *symbol = 224; 2128 | return 10; 2129 | } else { 2130 | *symbol = 223; 2131 | return 10; 2132 | } 2133 | 2134 | node_11111: 2135 | if (bits & 0x4000000) { 2136 | goto node_111111; 2137 | } else { 2138 | goto node_111110; 2139 | } 2140 | 2141 | node_111110: 2142 | if (bits & 0x2000000) { 2143 | goto node_1111101; 2144 | } else { 2145 | goto node_1111100; 2146 | } 2147 | 2148 | node_1111100: 2149 | if (bits & 0x1000000) { 2150 | goto node_11111001; 2151 | } else { 2152 | goto node_11111000; 2153 | } 2154 | 2155 | node_11111000: 2156 | if (bits & 0x800000) { 2157 | goto node_111110001; 2158 | } else { 2159 | goto node_111110000; 2160 | } 2161 | 2162 | node_111110000: 2163 | if (bits & 0x400000) { 2164 | *symbol = 226; 2165 | return 10; 2166 | } else { 2167 | *symbol = 225; 2168 | return 10; 2169 | } 2170 | 2171 | node_111110001: 2172 | if (bits & 0x400000) { 2173 | *symbol = 228; 2174 | return 10; 2175 | } else { 2176 | *symbol = 227; 2177 | return 10; 2178 | } 2179 | 2180 | node_11111001: 2181 | if (bits & 0x800000) { 2182 | goto node_111110011; 2183 | } else { 2184 | goto node_111110010; 2185 | } 2186 | 2187 | node_111110010: 2188 | if (bits & 0x400000) { 2189 | *symbol = 230; 2190 | return 10; 2191 | } else { 2192 | *symbol = 229; 2193 | return 10; 2194 | } 2195 | 2196 | node_111110011: 2197 | if (bits & 0x400000) { 2198 | *symbol = 232; 2199 | return 10; 2200 | } else { 2201 | *symbol = 231; 2202 | return 10; 2203 | } 2204 | 2205 | node_1111101: 2206 | if (bits & 0x1000000) { 2207 | goto node_11111011; 2208 | } else { 2209 | goto node_11111010; 2210 | } 2211 | 2212 | node_11111010: 2213 | if (bits & 0x800000) { 2214 | goto node_111110101; 2215 | } else { 2216 | goto node_111110100; 2217 | } 2218 | 2219 | node_111110100: 2220 | if (bits & 0x400000) { 2221 | *symbol = 234; 2222 | return 10; 2223 | } else { 2224 | *symbol = 233; 2225 | return 10; 2226 | } 2227 | 2228 | node_111110101: 2229 | if (bits & 0x400000) { 2230 | *symbol = 236; 2231 | return 10; 2232 | } else { 2233 | *symbol = 235; 2234 | return 10; 2235 | } 2236 | 2237 | node_11111011: 2238 | if (bits & 0x800000) { 2239 | goto node_111110111; 2240 | } else { 2241 | goto node_111110110; 2242 | } 2243 | 2244 | node_111110110: 2245 | if (bits & 0x400000) { 2246 | *symbol = 238; 2247 | return 10; 2248 | } else { 2249 | *symbol = 237; 2250 | return 10; 2251 | } 2252 | 2253 | node_111110111: 2254 | if (bits & 0x400000) { 2255 | *symbol = 240; 2256 | return 10; 2257 | } else { 2258 | *symbol = 239; 2259 | return 10; 2260 | } 2261 | 2262 | node_111111: 2263 | if (bits & 0x2000000) { 2264 | goto node_1111111; 2265 | } else { 2266 | goto node_1111110; 2267 | } 2268 | 2269 | node_1111110: 2270 | if (bits & 0x1000000) { 2271 | goto node_11111101; 2272 | } else { 2273 | goto node_11111100; 2274 | } 2275 | 2276 | node_11111100: 2277 | if (bits & 0x800000) { 2278 | goto node_111111001; 2279 | } else { 2280 | goto node_111111000; 2281 | } 2282 | 2283 | node_111111000: 2284 | if (bits & 0x400000) { 2285 | *symbol = 242; 2286 | return 10; 2287 | } else { 2288 | *symbol = 241; 2289 | return 10; 2290 | } 2291 | 2292 | node_111111001: 2293 | if (bits & 0x400000) { 2294 | *symbol = 244; 2295 | return 10; 2296 | } else { 2297 | *symbol = 243; 2298 | return 10; 2299 | } 2300 | 2301 | node_11111101: 2302 | if (bits & 0x800000) { 2303 | goto node_111111011; 2304 | } else { 2305 | goto node_111111010; 2306 | } 2307 | 2308 | node_111111010: 2309 | if (bits & 0x400000) { 2310 | *symbol = 246; 2311 | return 10; 2312 | } else { 2313 | *symbol = 245; 2314 | return 10; 2315 | } 2316 | 2317 | node_111111011: 2318 | if (bits & 0x400000) { 2319 | *symbol = 248; 2320 | return 10; 2321 | } else { 2322 | *symbol = 247; 2323 | return 10; 2324 | } 2325 | 2326 | node_1111111: 2327 | if (bits & 0x1000000) { 2328 | goto node_11111111; 2329 | } else { 2330 | goto node_11111110; 2331 | } 2332 | 2333 | node_11111110: 2334 | if (bits & 0x800000) { 2335 | goto node_111111101; 2336 | } else { 2337 | goto node_111111100; 2338 | } 2339 | 2340 | node_111111100: 2341 | if (bits & 0x400000) { 2342 | *symbol = 250; 2343 | return 10; 2344 | } else { 2345 | *symbol = 249; 2346 | return 10; 2347 | } 2348 | 2349 | node_111111101: 2350 | if (bits & 0x400000) { 2351 | *symbol = 252; 2352 | return 10; 2353 | } else { 2354 | *symbol = 251; 2355 | return 10; 2356 | } 2357 | 2358 | node_11111111: 2359 | if (bits & 0x800000) { 2360 | goto node_111111111; 2361 | } else { 2362 | goto node_111111110; 2363 | } 2364 | 2365 | node_111111110: 2366 | if (bits & 0x400000) { 2367 | *symbol = 254; 2368 | return 10; 2369 | } else { 2370 | *symbol = 253; 2371 | return 10; 2372 | } 2373 | 2374 | node_111111111: 2375 | if (bits & 0x400000) { 2376 | return 0; /* invalid node */ 2377 | } else { 2378 | *symbol = 255; 2379 | return 10; 2380 | } 2381 | } 2382 | 2383 | struct aws_huffman_symbol_coder *test_get_coder(void) { 2384 | 2385 | static struct aws_huffman_symbol_coder coder = { 2386 | .encode = encode_symbol, 2387 | .decode = decode_symbol, 2388 | .userdata = NULL, 2389 | }; 2390 | return &coder; 2391 | } 2392 | -------------------------------------------------------------------------------- /tests/test_huffman_static_table.def: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #ifndef HUFFMAN_CODE 7 | #error "Macro HUFFMAN_CODE must be defined before including this header file!" 8 | #endif 9 | 10 | /* sym bits code len */ 11 | HUFFMAN_CODE( 0, "1100101110", 0x32e, 10) 12 | HUFFMAN_CODE( 1, "1100101111", 0x32f, 10) 13 | HUFFMAN_CODE( 2, "1100110000", 0x330, 10) 14 | HUFFMAN_CODE( 3, "1100110001", 0x331, 10) 15 | HUFFMAN_CODE( 4, "1100110010", 0x332, 10) 16 | HUFFMAN_CODE( 5, "1100110011", 0x333, 10) 17 | HUFFMAN_CODE( 6, "1100110100", 0x334, 10) 18 | HUFFMAN_CODE( 7, "1100110101", 0x335, 10) 19 | HUFFMAN_CODE( 8, "1100110110", 0x336, 10) 20 | HUFFMAN_CODE( 9, "1100110111", 0x337, 10) 21 | HUFFMAN_CODE( 10, "10111000", 0xb8, 8) 22 | HUFFMAN_CODE( 11, "1100111000", 0x338, 10) 23 | HUFFMAN_CODE( 12, "1100111001", 0x339, 10) 24 | HUFFMAN_CODE( 13, "1100111010", 0x33a, 10) 25 | HUFFMAN_CODE( 14, "1100111011", 0x33b, 10) 26 | HUFFMAN_CODE( 15, "1100111100", 0x33c, 10) 27 | HUFFMAN_CODE( 16, "1100111101", 0x33d, 10) 28 | HUFFMAN_CODE( 17, "1100111110", 0x33e, 10) 29 | HUFFMAN_CODE( 18, "1100111111", 0x33f, 10) 30 | HUFFMAN_CODE( 19, "1101000000", 0x340, 10) 31 | HUFFMAN_CODE( 20, "1101000001", 0x341, 10) 32 | HUFFMAN_CODE( 21, "1101000010", 0x342, 10) 33 | HUFFMAN_CODE( 22, "1101000011", 0x343, 10) 34 | HUFFMAN_CODE( 23, "1101000100", 0x344, 10) 35 | HUFFMAN_CODE( 24, "1101000101", 0x345, 10) 36 | HUFFMAN_CODE( 25, "1101000110", 0x346, 10) 37 | HUFFMAN_CODE( 26, "1101000111", 0x347, 10) 38 | HUFFMAN_CODE( 27, "1101001000", 0x348, 10) 39 | HUFFMAN_CODE( 28, "1101001001", 0x349, 10) 40 | HUFFMAN_CODE( 29, "1101001010", 0x34a, 10) 41 | HUFFMAN_CODE( 30, "1101001011", 0x34b, 10) 42 | HUFFMAN_CODE( 31, "1101001100", 0x34c, 10) 43 | HUFFMAN_CODE( 32, "00100", 0x4, 5) 44 | HUFFMAN_CODE( 33, "1101001101", 0x34d, 10) 45 | HUFFMAN_CODE( 34, "1101001110", 0x34e, 10) 46 | HUFFMAN_CODE( 35, "1101001111", 0x34f, 10) 47 | HUFFMAN_CODE( 36, "1101010000", 0x350, 10) 48 | HUFFMAN_CODE( 37, "1101010001", 0x351, 10) 49 | HUFFMAN_CODE( 38, "1101010010", 0x352, 10) 50 | HUFFMAN_CODE( 39, "1010110", 0x56, 7) 51 | HUFFMAN_CODE( 40, "1101010011", 0x353, 10) 52 | HUFFMAN_CODE( 41, "1101010100", 0x354, 10) 53 | HUFFMAN_CODE( 42, "1101010101", 0x355, 10) 54 | HUFFMAN_CODE( 43, "1101010110", 0x356, 10) 55 | HUFFMAN_CODE( 44, "10111001", 0xb9, 8) 56 | HUFFMAN_CODE( 45, "110001000", 0x188, 9) 57 | HUFFMAN_CODE( 46, "1010111", 0x57, 7) 58 | HUFFMAN_CODE( 47, "1101010111", 0x357, 10) 59 | HUFFMAN_CODE( 48, "1101011000", 0x358, 10) 60 | HUFFMAN_CODE( 49, "1101011001", 0x359, 10) 61 | HUFFMAN_CODE( 50, "1101011010", 0x35a, 10) 62 | HUFFMAN_CODE( 51, "1101011011", 0x35b, 10) 63 | HUFFMAN_CODE( 52, "1101011100", 0x35c, 10) 64 | HUFFMAN_CODE( 53, "1101011101", 0x35d, 10) 65 | HUFFMAN_CODE( 54, "1101011110", 0x35e, 10) 66 | HUFFMAN_CODE( 55, "1101011111", 0x35f, 10) 67 | HUFFMAN_CODE( 56, "1101100000", 0x360, 10) 68 | HUFFMAN_CODE( 57, "1101100001", 0x361, 10) 69 | HUFFMAN_CODE( 58, "1101100010", 0x362, 10) 70 | HUFFMAN_CODE( 59, "1101100011", 0x363, 10) 71 | HUFFMAN_CODE( 60, "1101100100", 0x364, 10) 72 | HUFFMAN_CODE( 61, "1101100101", 0x365, 10) 73 | HUFFMAN_CODE( 62, "1101100110", 0x366, 10) 74 | HUFFMAN_CODE( 63, "10111010", 0xba, 8) 75 | HUFFMAN_CODE( 64, "1101100111", 0x367, 10) 76 | HUFFMAN_CODE( 65, "1101101000", 0x368, 10) 77 | HUFFMAN_CODE( 66, "10111011", 0xbb, 8) 78 | HUFFMAN_CODE( 67, "110001001", 0x189, 9) 79 | HUFFMAN_CODE( 68, "110001010", 0x18a, 9) 80 | HUFFMAN_CODE( 69, "110001011", 0x18b, 9) 81 | HUFFMAN_CODE( 70, "110001100", 0x18c, 9) 82 | HUFFMAN_CODE( 71, "110001101", 0x18d, 9) 83 | HUFFMAN_CODE( 72, "110001110", 0x18e, 9) 84 | HUFFMAN_CODE( 73, "10111100", 0xbc, 8) 85 | HUFFMAN_CODE( 74, "1101101001", 0x369, 10) 86 | HUFFMAN_CODE( 75, "1101101010", 0x36a, 10) 87 | HUFFMAN_CODE( 76, "110001111", 0x18f, 9) 88 | HUFFMAN_CODE( 77, "110010000", 0x190, 9) 89 | HUFFMAN_CODE( 78, "1101101011", 0x36b, 10) 90 | HUFFMAN_CODE( 79, "1101101100", 0x36c, 10) 91 | HUFFMAN_CODE( 80, "110010001", 0x191, 9) 92 | HUFFMAN_CODE( 81, "1101101101", 0x36d, 10) 93 | HUFFMAN_CODE( 82, "1101101110", 0x36e, 10) 94 | HUFFMAN_CODE( 83, "1101101111", 0x36f, 10) 95 | HUFFMAN_CODE( 84, "10111101", 0xbd, 8) 96 | HUFFMAN_CODE( 85, "1101110000", 0x370, 10) 97 | HUFFMAN_CODE( 86, "110010010", 0x192, 9) 98 | HUFFMAN_CODE( 87, "10111110", 0xbe, 8) 99 | HUFFMAN_CODE( 88, "1101110001", 0x371, 10) 100 | HUFFMAN_CODE( 89, "110010011", 0x193, 9) 101 | HUFFMAN_CODE( 90, "1101110010", 0x372, 10) 102 | HUFFMAN_CODE( 91, "1101110011", 0x373, 10) 103 | HUFFMAN_CODE( 92, "1101110100", 0x374, 10) 104 | HUFFMAN_CODE( 93, "1101110101", 0x375, 10) 105 | HUFFMAN_CODE( 94, "1101110110", 0x376, 10) 106 | HUFFMAN_CODE( 95, "1101110111", 0x377, 10) 107 | HUFFMAN_CODE( 96, "1101111000", 0x378, 10) 108 | HUFFMAN_CODE( 97, "00101", 0x5, 5) 109 | HUFFMAN_CODE( 98, "1011000", 0x58, 7) 110 | HUFFMAN_CODE( 99, "100000", 0x20, 6) 111 | HUFFMAN_CODE(100, "100001", 0x21, 6) 112 | HUFFMAN_CODE(101, "00110", 0x6, 5) 113 | HUFFMAN_CODE(102, "100010", 0x22, 6) 114 | HUFFMAN_CODE(103, "1011001", 0x59, 7) 115 | HUFFMAN_CODE(104, "100011", 0x23, 6) 116 | HUFFMAN_CODE(105, "00111", 0x7, 5) 117 | HUFFMAN_CODE(106, "10111111", 0xbf, 8) 118 | HUFFMAN_CODE(107, "100100", 0x24, 6) 119 | HUFFMAN_CODE(108, "100101", 0x25, 6) 120 | HUFFMAN_CODE(109, "100110", 0x26, 6) 121 | HUFFMAN_CODE(110, "01000", 0x8, 5) 122 | HUFFMAN_CODE(111, "01001", 0x9, 5) 123 | HUFFMAN_CODE(112, "1011010", 0x5a, 7) 124 | HUFFMAN_CODE(113, "110010100", 0x194, 9) 125 | HUFFMAN_CODE(114, "01010", 0xa, 5) 126 | HUFFMAN_CODE(115, "01011", 0xb, 5) 127 | HUFFMAN_CODE(116, "01100", 0xc, 5) 128 | HUFFMAN_CODE(117, "01101", 0xd, 5) 129 | HUFFMAN_CODE(118, "11000000", 0xc0, 8) 130 | HUFFMAN_CODE(119, "100111", 0x27, 6) 131 | HUFFMAN_CODE(120, "11000001", 0xc1, 8) 132 | HUFFMAN_CODE(121, "101000", 0x28, 6) 133 | HUFFMAN_CODE(122, "1101111001", 0x379, 10) 134 | HUFFMAN_CODE(123, "1101111010", 0x37a, 10) 135 | HUFFMAN_CODE(124, "1101111011", 0x37b, 10) 136 | HUFFMAN_CODE(125, "1101111100", 0x37c, 10) 137 | HUFFMAN_CODE(126, "1101111101", 0x37d, 10) 138 | HUFFMAN_CODE(127, "1101111110", 0x37e, 10) 139 | HUFFMAN_CODE(128, "1101111111", 0x37f, 10) 140 | HUFFMAN_CODE(129, "1110000000", 0x380, 10) 141 | HUFFMAN_CODE(130, "1110000001", 0x381, 10) 142 | HUFFMAN_CODE(131, "1110000010", 0x382, 10) 143 | HUFFMAN_CODE(132, "1110000011", 0x383, 10) 144 | HUFFMAN_CODE(133, "1110000100", 0x384, 10) 145 | HUFFMAN_CODE(134, "1110000101", 0x385, 10) 146 | HUFFMAN_CODE(135, "1110000110", 0x386, 10) 147 | HUFFMAN_CODE(136, "1110000111", 0x387, 10) 148 | HUFFMAN_CODE(137, "1110001000", 0x388, 10) 149 | HUFFMAN_CODE(138, "1110001001", 0x389, 10) 150 | HUFFMAN_CODE(139, "1110001010", 0x38a, 10) 151 | HUFFMAN_CODE(140, "1110001011", 0x38b, 10) 152 | HUFFMAN_CODE(141, "1110001100", 0x38c, 10) 153 | HUFFMAN_CODE(142, "1110001101", 0x38d, 10) 154 | HUFFMAN_CODE(143, "1110001110", 0x38e, 10) 155 | HUFFMAN_CODE(144, "1110001111", 0x38f, 10) 156 | HUFFMAN_CODE(145, "1110010000", 0x390, 10) 157 | HUFFMAN_CODE(146, "1110010001", 0x391, 10) 158 | HUFFMAN_CODE(147, "1110010010", 0x392, 10) 159 | HUFFMAN_CODE(148, "1110010011", 0x393, 10) 160 | HUFFMAN_CODE(149, "1110010100", 0x394, 10) 161 | HUFFMAN_CODE(150, "1110010101", 0x395, 10) 162 | HUFFMAN_CODE(151, "1110010110", 0x396, 10) 163 | HUFFMAN_CODE(152, "1110010111", 0x397, 10) 164 | HUFFMAN_CODE(153, "1110011000", 0x398, 10) 165 | HUFFMAN_CODE(154, "1110011001", 0x399, 10) 166 | HUFFMAN_CODE(155, "1110011010", 0x39a, 10) 167 | HUFFMAN_CODE(156, "1110011011", 0x39b, 10) 168 | HUFFMAN_CODE(157, "1110011100", 0x39c, 10) 169 | HUFFMAN_CODE(158, "1110011101", 0x39d, 10) 170 | HUFFMAN_CODE(159, "1110011110", 0x39e, 10) 171 | HUFFMAN_CODE(160, "1110011111", 0x39f, 10) 172 | HUFFMAN_CODE(161, "1110100000", 0x3a0, 10) 173 | HUFFMAN_CODE(162, "1110100001", 0x3a1, 10) 174 | HUFFMAN_CODE(163, "1110100010", 0x3a2, 10) 175 | HUFFMAN_CODE(164, "1110100011", 0x3a3, 10) 176 | HUFFMAN_CODE(165, "1110100100", 0x3a4, 10) 177 | HUFFMAN_CODE(166, "1110100101", 0x3a5, 10) 178 | HUFFMAN_CODE(167, "1110100110", 0x3a6, 10) 179 | HUFFMAN_CODE(168, "1110100111", 0x3a7, 10) 180 | HUFFMAN_CODE(169, "1110101000", 0x3a8, 10) 181 | HUFFMAN_CODE(170, "1110101001", 0x3a9, 10) 182 | HUFFMAN_CODE(171, "1110101010", 0x3aa, 10) 183 | HUFFMAN_CODE(172, "1110101011", 0x3ab, 10) 184 | HUFFMAN_CODE(173, "1110101100", 0x3ac, 10) 185 | HUFFMAN_CODE(174, "1110101101", 0x3ad, 10) 186 | HUFFMAN_CODE(175, "1110101110", 0x3ae, 10) 187 | HUFFMAN_CODE(176, "1110101111", 0x3af, 10) 188 | HUFFMAN_CODE(177, "1110110000", 0x3b0, 10) 189 | HUFFMAN_CODE(178, "1110110001", 0x3b1, 10) 190 | HUFFMAN_CODE(179, "1110110010", 0x3b2, 10) 191 | HUFFMAN_CODE(180, "1110110011", 0x3b3, 10) 192 | HUFFMAN_CODE(181, "1110110100", 0x3b4, 10) 193 | HUFFMAN_CODE(182, "1110110101", 0x3b5, 10) 194 | HUFFMAN_CODE(183, "1110110110", 0x3b6, 10) 195 | HUFFMAN_CODE(184, "1110110111", 0x3b7, 10) 196 | HUFFMAN_CODE(185, "1110111000", 0x3b8, 10) 197 | HUFFMAN_CODE(186, "1110111001", 0x3b9, 10) 198 | HUFFMAN_CODE(187, "1110111010", 0x3ba, 10) 199 | HUFFMAN_CODE(188, "1110111011", 0x3bb, 10) 200 | HUFFMAN_CODE(189, "1110111100", 0x3bc, 10) 201 | HUFFMAN_CODE(190, "1110111101", 0x3bd, 10) 202 | HUFFMAN_CODE(191, "1110111110", 0x3be, 10) 203 | HUFFMAN_CODE(192, "1110111111", 0x3bf, 10) 204 | HUFFMAN_CODE(193, "1111000000", 0x3c0, 10) 205 | HUFFMAN_CODE(194, "1111000001", 0x3c1, 10) 206 | HUFFMAN_CODE(195, "1111000010", 0x3c2, 10) 207 | HUFFMAN_CODE(196, "1111000011", 0x3c3, 10) 208 | HUFFMAN_CODE(197, "1111000100", 0x3c4, 10) 209 | HUFFMAN_CODE(198, "1111000101", 0x3c5, 10) 210 | HUFFMAN_CODE(199, "1111000110", 0x3c6, 10) 211 | HUFFMAN_CODE(200, "1111000111", 0x3c7, 10) 212 | HUFFMAN_CODE(201, "1111001000", 0x3c8, 10) 213 | HUFFMAN_CODE(202, "1111001001", 0x3c9, 10) 214 | HUFFMAN_CODE(203, "1111001010", 0x3ca, 10) 215 | HUFFMAN_CODE(204, "1111001011", 0x3cb, 10) 216 | HUFFMAN_CODE(205, "1111001100", 0x3cc, 10) 217 | HUFFMAN_CODE(206, "1111001101", 0x3cd, 10) 218 | HUFFMAN_CODE(207, "1111001110", 0x3ce, 10) 219 | HUFFMAN_CODE(208, "1111001111", 0x3cf, 10) 220 | HUFFMAN_CODE(209, "1111010000", 0x3d0, 10) 221 | HUFFMAN_CODE(210, "1111010001", 0x3d1, 10) 222 | HUFFMAN_CODE(211, "1111010010", 0x3d2, 10) 223 | HUFFMAN_CODE(212, "1111010011", 0x3d3, 10) 224 | HUFFMAN_CODE(213, "1111010100", 0x3d4, 10) 225 | HUFFMAN_CODE(214, "1111010101", 0x3d5, 10) 226 | HUFFMAN_CODE(215, "1111010110", 0x3d6, 10) 227 | HUFFMAN_CODE(216, "1111010111", 0x3d7, 10) 228 | HUFFMAN_CODE(217, "1111011000", 0x3d8, 10) 229 | HUFFMAN_CODE(218, "1111011001", 0x3d9, 10) 230 | HUFFMAN_CODE(219, "1111011010", 0x3da, 10) 231 | HUFFMAN_CODE(220, "1111011011", 0x3db, 10) 232 | HUFFMAN_CODE(221, "1111011100", 0x3dc, 10) 233 | HUFFMAN_CODE(222, "1111011101", 0x3dd, 10) 234 | HUFFMAN_CODE(223, "1111011110", 0x3de, 10) 235 | HUFFMAN_CODE(224, "1111011111", 0x3df, 10) 236 | HUFFMAN_CODE(225, "1111100000", 0x3e0, 10) 237 | HUFFMAN_CODE(226, "1111100001", 0x3e1, 10) 238 | HUFFMAN_CODE(227, "1111100010", 0x3e2, 10) 239 | HUFFMAN_CODE(228, "1111100011", 0x3e3, 10) 240 | HUFFMAN_CODE(229, "1111100100", 0x3e4, 10) 241 | HUFFMAN_CODE(230, "1111100101", 0x3e5, 10) 242 | HUFFMAN_CODE(231, "1111100110", 0x3e6, 10) 243 | HUFFMAN_CODE(232, "1111100111", 0x3e7, 10) 244 | HUFFMAN_CODE(233, "1111101000", 0x3e8, 10) 245 | HUFFMAN_CODE(234, "1111101001", 0x3e9, 10) 246 | HUFFMAN_CODE(235, "1111101010", 0x3ea, 10) 247 | HUFFMAN_CODE(236, "1111101011", 0x3eb, 10) 248 | HUFFMAN_CODE(237, "1111101100", 0x3ec, 10) 249 | HUFFMAN_CODE(238, "1111101101", 0x3ed, 10) 250 | HUFFMAN_CODE(239, "1111101110", 0x3ee, 10) 251 | HUFFMAN_CODE(240, "1111101111", 0x3ef, 10) 252 | HUFFMAN_CODE(241, "1111110000", 0x3f0, 10) 253 | HUFFMAN_CODE(242, "1111110001", 0x3f1, 10) 254 | HUFFMAN_CODE(243, "1111110010", 0x3f2, 10) 255 | HUFFMAN_CODE(244, "1111110011", 0x3f3, 10) 256 | HUFFMAN_CODE(245, "1111110100", 0x3f4, 10) 257 | HUFFMAN_CODE(246, "1111110101", 0x3f5, 10) 258 | HUFFMAN_CODE(247, "1111110110", 0x3f6, 10) 259 | HUFFMAN_CODE(248, "1111110111", 0x3f7, 10) 260 | HUFFMAN_CODE(249, "1111111000", 0x3f8, 10) 261 | HUFFMAN_CODE(250, "1111111001", 0x3f9, 10) 262 | HUFFMAN_CODE(251, "1111111010", 0x3fa, 10) 263 | HUFFMAN_CODE(252, "1111111011", 0x3fb, 10) 264 | HUFFMAN_CODE(253, "1111111100", 0x3fc, 10) 265 | HUFFMAN_CODE(254, "1111111101", 0x3fd, 10) 266 | HUFFMAN_CODE(255, "1111111110", 0x3fe, 10) 267 | --------------------------------------------------------------------------------